[maglev][arm64] Add Checked/Truncate/Int32/Float64 IRs

Bug: v8:7700
Change-Id: I3a94cc3d4902b7296a9be93b9998d4cfa9b3153b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4111162
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: Patrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84929}
This commit is contained in:
Victor Gomes 2022-12-16 15:56:24 +01:00 committed by V8 LUCI CQ
parent de5df9aebc
commit 5a486deea3
3 changed files with 148 additions and 28 deletions

View File

@ -122,15 +122,6 @@ UNIMPLEMENTED_NODE(LoadDoubleDataViewElement)
UNIMPLEMENTED_NODE(LoadSignedIntTypedArrayElement, elements_kind_)
UNIMPLEMENTED_NODE(LoadUnsignedIntTypedArrayElement, elements_kind_)
UNIMPLEMENTED_NODE(LoadDoubleTypedArrayElement, elements_kind_)
UNIMPLEMENTED_NODE(CheckedSmiTagUint32)
UNIMPLEMENTED_NODE(CheckedInt32ToUint32)
UNIMPLEMENTED_NODE(CheckedUint32ToInt32)
UNIMPLEMENTED_NODE(ChangeInt32ToFloat64)
UNIMPLEMENTED_NODE(ChangeUint32ToFloat64)
UNIMPLEMENTED_NODE(CheckedTruncateFloat64ToInt32)
UNIMPLEMENTED_NODE(CheckedTruncateFloat64ToUint32)
UNIMPLEMENTED_NODE(TruncateUint32ToInt32)
UNIMPLEMENTED_NODE(TruncateFloat64ToInt32)
UNIMPLEMENTED_NODE(HoleyFloat64Box)
UNIMPLEMENTED_NODE(LogicalNot)
UNIMPLEMENTED_NODE(SetPendingMessage)
@ -242,6 +233,120 @@ void CreateEmptyObjectLiteral::GenerateCode(MaglevAssembler* masm,
}
}
void CheckedInt32ToUint32::SetValueLocationConstraints() {
UseRegister(input());
DefineSameAsFirst(this);
}
void CheckedInt32ToUint32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
Register input_reg = ToRegister(input()).W();
__ Tst(input_reg, input_reg);
__ EmitEagerDeoptIf(mi, DeoptimizeReason::kNotUint32, this);
}
void CheckedUint32ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineSameAsFirst(this);
}
void CheckedUint32ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
Register input_reg = ToRegister(input()).W();
// Check if the top bit is set -- if it is, then this is not a valid int32,
// otherwise it is.
// TODO(victorgomes): I am manually creating an eager deopt here, if this is a
// common pattern, maybe abstract to a helper function.
static_assert(CheckedUint32ToInt32::kProperties.can_eager_deopt());
__ RegisterEagerDeopt(eager_deopt_info(), DeoptimizeReason::kNotInt32);
__ RecordComment("-- Jump to eager deopt");
__ Tbnz(input_reg, 31, eager_deopt_info()->deopt_entry_label());
}
void ChangeInt32ToFloat64::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void ChangeInt32ToFloat64::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
__ Scvtf(ToDoubleRegister(result()), ToRegister(input()).W());
}
void ChangeUint32ToFloat64::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void ChangeUint32ToFloat64::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
__ Ucvtf(ToDoubleRegister(result()), ToRegister(input()).W());
}
void CheckedTruncateFloat64ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void CheckedTruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister input_reg = ToDoubleRegister(input());
Register result_reg = ToRegister(result()).W();
DoubleRegister converted_back = kScratchDoubleReg;
// Convert the input float64 value to int32.
__ Fcvtzs(result_reg, input_reg);
// Convert that int32 value back to float64.
__ Scvtf(converted_back, result_reg);
// Check that the result of the float64->int32->float64 is equal to the input
// (i.e. that the conversion didn't truncate.
__ Fcmp(input_reg, converted_back);
__ EmitEagerDeoptIf(ne, DeoptimizeReason::kNotInt32, this);
// Check if {input} is -0.
Label check_done;
__ Cmp(result_reg, wzr);
__ B(&check_done, ne);
// In case of 0, we need to check the high bits for the IEEE -0 pattern.
UseScratchRegisterScope temps(masm);
Register high_word32_of_input = temps.AcquireW();
__ Umov(high_word32_of_input, input_reg.V2S(), 1);
__ Cmp(high_word32_of_input, wzr);
__ EmitEagerDeoptIf(lt, DeoptimizeReason::kNotInt32, this);
__ bind(&check_done);
}
void CheckedTruncateFloat64ToUint32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void CheckedTruncateFloat64ToUint32::GenerateCode(
MaglevAssembler* masm, const ProcessingState& state) {
DoubleRegister input_reg = ToDoubleRegister(input());
Register result_reg = ToRegister(result()).W();
DoubleRegister converted_back = kScratchDoubleReg;
// Convert the input float64 value to uint32.
__ Fcvtzu(result_reg, input_reg);
// Convert that uint32 value back to float64.
__ Ucvtf(converted_back, result_reg);
// Check that the result of the float64->uint32->float64 is equal to the input
// (i.e. that the conversion didn't truncate.
__ Fcmp(input_reg, converted_back);
__ EmitEagerDeoptIf(ne, DeoptimizeReason::kNotUint32, this);
// Check if {input} is -0.
Label check_done;
__ Cmp(result_reg, wzr);
__ B(&check_done, ne);
// In case of 0, we need to check the high bits for the IEEE -0 pattern.
UseScratchRegisterScope temps(masm);
Register high_word32_of_input = temps.AcquireW();
__ Umov(high_word32_of_input, input_reg.V2S(), 1);
__ Cmp(high_word32_of_input, wzr);
__ EmitEagerDeoptIf(lt, DeoptimizeReason::kNotUint32, this);
__ bind(&check_done);
}
void CheckedTruncateNumberToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
@ -959,6 +1064,21 @@ void CheckedSmiTagInt32::GenerateCode(MaglevAssembler* masm,
__ EmitEagerDeoptIf(vs, DeoptimizeReason::kOverflow, this);
}
void CheckedSmiTagUint32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void CheckedSmiTagUint32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
Register reg = ToRegister(input()).W();
Register result_reg = ToRegister(result()).W();
// Perform an unsigned comparison against Smi::kMaxValue.
__ Cmp(reg, Immediate(Smi::kMaxValue));
__ EmitEagerDeoptIf(hi, DeoptimizeReason::kOverflow, this);
__ Adds(result_reg, reg, reg);
__ Assert(vc, AbortReason::kInputDoesNotFitSmi);
}
void CheckedInternalizedString::SetValueLocationConstraints() {
UseRegister(object_input());
DefineSameAsFirst(this);

View File

@ -1583,6 +1583,25 @@ void ToNumberOrNumeric::GenerateCode(MaglevAssembler* masm,
masm->DefineExceptionHandlerAndLazyDeoptPoint(this);
}
void TruncateUint32ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineSameAsFirst(this);
}
void TruncateUint32ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
// No code emitted -- as far as the machine is concerned, int32 is uint32.
DCHECK_EQ(ToRegister(input()), ToRegister(result()));
}
void TruncateFloat64ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void TruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
__ TruncateDoubleToInt32(ToRegister(result()), ToDoubleRegister(input()));
}
// ---
// Arch agnostic call nodes
// ---

View File

@ -2553,25 +2553,6 @@ void CheckedTruncateFloat64ToUint32::GenerateCode(
__ bind(&check_done);
}
void TruncateUint32ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineSameAsFirst(this);
}
void TruncateUint32ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
// No code emitted -- as far as the machine is concerned, int32 is uint32.
DCHECK_EQ(ToRegister(input()), ToRegister(result()));
}
void TruncateFloat64ToInt32::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void TruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
__ TruncateDoubleToInt32(ToRegister(result()), ToDoubleRegister(input()));
}
int Construct::MaxCallStackArgs() const {
using D = Construct_WithFeedbackDescriptor;
return num_args() + D::GetStackParameterCount();