From 25db0417aa1ffa9da42d9e8a5f59398d6af68bce Mon Sep 17 00:00:00 2001 From: Victor Gomes Date: Wed, 28 Jun 2023 08:53:21 +0200 Subject: [PATCH] [maglev] Add MaglevAssembler::TryTruncateDoubleToUint32 Bug: v8:7700 Change-Id: I3e60c174a8e429ee9a20c479a5f17d360ac8db50 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4651871 Reviewed-by: Leszek Swirski Auto-Submit: Victor Gomes Commit-Queue: Leszek Swirski Cr-Commit-Position: refs/heads/main@{#88524} --- src/maglev/arm/maglev-assembler-arm.cc | 36 ++++++++++++++++++++++ src/maglev/arm/maglev-ir-arm.cc | 9 ------ src/maglev/arm64/maglev-assembler-arm64.cc | 27 ++++++++++++++++ src/maglev/arm64/maglev-ir-arm64.cc | 33 -------------------- src/maglev/maglev-assembler.h | 1 + src/maglev/maglev-ir.cc | 11 +++++++ src/maglev/x64/maglev-assembler-x64.cc | 29 +++++++++++++++++ src/maglev/x64/maglev-ir-x64.cc | 35 --------------------- 8 files changed, 104 insertions(+), 77 deletions(-) diff --git a/src/maglev/arm/maglev-assembler-arm.cc b/src/maglev/arm/maglev-assembler-arm.cc index 861841f4aaa7..b2e95913e1c4 100644 --- a/src/maglev/arm/maglev-assembler-arm.cc +++ b/src/maglev/arm/maglev-assembler-arm.cc @@ -509,6 +509,42 @@ void MaglevAssembler::TryTruncateDoubleToInt32(Register dst, DoubleRegister src, bind(&done); } +void MaglevAssembler::TryTruncateDoubleToUint32(Register dst, + DoubleRegister src, + Label* fail) { + UseScratchRegisterScope temps(this); + LowDwVfpRegister low_double = temps.AcquireLowD(); + SwVfpRegister temp_vfps = low_double.low(); + DoubleRegister converted_back = low_double; + Label done; + + // Convert the input float64 value to uint32. + vcvt_u32_f64(temp_vfps, src); + vmov(dst, temp_vfps); + + // Convert that uint32 value back to float64. + vcvt_f64_u32(converted_back, temp_vfps); + + // Check that the result of the float64->uint32->float64 is equal to the input + // (i.e. that the conversion didn't truncate. + VFPCompareAndSetFlags(src, converted_back); + JumpIf(kNotEqual, fail); + + // Check if {input} is -0. + tst(dst, dst); + JumpIf(kNotEqual, &done); + + // In case of 0, we need to check the high bits for the IEEE -0 pattern. + { + Register high_word32_of_input = temps.Acquire(); + VmovHigh(high_word32_of_input, src); + cmp(high_word32_of_input, Operand(0)); + JumpIf(kLessThan, fail); + } + + bind(&done); +} + void MaglevAssembler::TryChangeFloat64ToIndex(Register result, DoubleRegister value, Label* success, Label* fail) { diff --git a/src/maglev/arm/maglev-ir-arm.cc b/src/maglev/arm/maglev-ir-arm.cc index b5e8e7b0d8e4..e98bed2299e3 100644 --- a/src/maglev/arm/maglev-ir-arm.cc +++ b/src/maglev/arm/maglev-ir-arm.cc @@ -152,15 +152,6 @@ void FoldedAllocation::GenerateCode(MaglevAssembler* masm, __ add(ToRegister(result()), ToRegister(raw_allocation()), Operand(offset())); } -void CheckedTruncateFloat64ToUint32::SetValueLocationConstraints() { - UseRegister(input()); - DefineAsRegister(this); -} -void CheckedTruncateFloat64ToUint32::GenerateCode( - MaglevAssembler* masm, const ProcessingState& state) { - MAGLEV_NODE_NOT_IMPLEMENTED(CheckedTruncateFloat64ToUint32); -} - void CheckNumber::SetValueLocationConstraints() { UseRegister(receiver_input()); } diff --git a/src/maglev/arm64/maglev-assembler-arm64.cc b/src/maglev/arm64/maglev-assembler-arm64.cc index 96441b153078..5c6b662761ec 100644 --- a/src/maglev/arm64/maglev-assembler-arm64.cc +++ b/src/maglev/arm64/maglev-assembler-arm64.cc @@ -556,6 +556,33 @@ void MaglevAssembler::TryTruncateDoubleToInt32(Register dst, DoubleRegister src, Bind(&check_done); } +void MaglevAssembler::TryTruncateDoubleToUint32(Register dst, + DoubleRegister src, + Label* fail) { + ScratchRegisterScope temps(this); + DoubleRegister converted_back = temps.AcquireDouble(); + + // Convert the input float64 value to uint32. + Fcvtzu(dst, src); + // Convert that uint32 value back to float64. + Ucvtf(converted_back, dst); + // Check that the result of the float64->uint32->float64 is equal to the input + // (i.e. that the conversion didn't truncate. + Fcmp(src, converted_back); + JumpIf(ne, fail); + + // Check if {input} is -0. + Label check_done; + Cbnz(dst, &check_done); + + // In case of 0, we need to check for the IEEE 0 pattern (which is all zeros). + Register input_bits = temps.Acquire(); + Fmov(input_bits, src); + Cbnz(input_bits, fail); + + Bind(&check_done); +} + void MaglevAssembler::TryChangeFloat64ToIndex(Register result, DoubleRegister value, Label* success, Label* fail) { diff --git a/src/maglev/arm64/maglev-ir-arm64.cc b/src/maglev/arm64/maglev-ir-arm64.cc index 4d3c3d25ee60..c0b6eeeb76ae 100644 --- a/src/maglev/arm64/maglev-ir-arm64.cc +++ b/src/maglev/arm64/maglev-ir-arm64.cc @@ -151,39 +151,6 @@ void FoldedAllocation::GenerateCode(MaglevAssembler* masm, __ Add(ToRegister(result()), ToRegister(raw_allocation()), offset()); } -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(); - - MaglevAssembler::ScratchRegisterScope temps(masm); - DoubleRegister converted_back = temps.AcquireDouble(); - - // 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; - __ Cbnz(result_reg, &check_done); - - // In case of 0, we need to check for the IEEE 0 pattern (which is all zeros). - Register input_bits = temps.Acquire(); - __ Fmov(input_bits, input_reg); - __ Cbnz(input_bits, __ GetDeoptLabel(this, DeoptimizeReason::kNotUint32)); - - __ Bind(&check_done); -} - void CheckNumber::SetValueLocationConstraints() { UseRegister(receiver_input()); } diff --git a/src/maglev/maglev-assembler.h b/src/maglev/maglev-assembler.h index 53c385819646..262b89ad5954 100644 --- a/src/maglev/maglev-assembler.h +++ b/src/maglev/maglev-assembler.h @@ -277,6 +277,7 @@ class MaglevAssembler : public MacroAssembler { void TruncateDoubleToInt32(Register dst, DoubleRegister src); void TryTruncateDoubleToInt32(Register dst, DoubleRegister src, Label* fail); + void TryTruncateDoubleToUint32(Register dst, DoubleRegister src, Label* fail); void TryChangeFloat64ToIndex(Register result, DoubleRegister value, Label* success, Label* fail); diff --git a/src/maglev/maglev-ir.cc b/src/maglev/maglev-ir.cc index d4cee704fbc3..f0e77ac63873 100644 --- a/src/maglev/maglev-ir.cc +++ b/src/maglev/maglev-ir.cc @@ -4040,6 +4040,17 @@ void CheckedTruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm, __ GetDeoptLabel(this, DeoptimizeReason::kNotInt32)); } +void CheckedTruncateFloat64ToUint32::SetValueLocationConstraints() { + UseRegister(input()); + DefineAsRegister(this); +} +void CheckedTruncateFloat64ToUint32::GenerateCode( + MaglevAssembler* masm, const ProcessingState& state) { + __ TryTruncateDoubleToUint32( + ToRegister(result()), ToDoubleRegister(input()), + __ GetDeoptLabel(this, DeoptimizeReason::kNotUint32)); +} + void UnsafeTruncateFloat64ToInt32::SetValueLocationConstraints() { UseRegister(input()); DefineAsRegister(this); diff --git a/src/maglev/x64/maglev-assembler-x64.cc b/src/maglev/x64/maglev-assembler-x64.cc index e84970f3bafc..206b96304b0e 100644 --- a/src/maglev/x64/maglev-assembler-x64.cc +++ b/src/maglev/x64/maglev-assembler-x64.cc @@ -349,6 +349,35 @@ void MaglevAssembler::TryTruncateDoubleToInt32(Register dst, DoubleRegister src, bind(&check_done); } +void MaglevAssembler::TryTruncateDoubleToUint32(Register dst, + DoubleRegister src, + Label* fail) { + DoubleRegister converted_back = kScratchDoubleReg; + + // Convert the input float64 value to uint32. + Cvttsd2ui(dst, src, fail); + // Convert that uint32 value back to float64. + Cvtlui2sd(converted_back, dst); + // Check that the result of the float64->uint32->float64 is equal to the input + // (i.e. that the conversion didn't truncate. + Ucomisd(src, converted_back); + JumpIf(parity_even, fail); + JumpIf(not_equal, fail); + + // Check if {input} is -0. + Label check_done; + cmpl(dst, Immediate(0)); + j(not_equal, &check_done); + + // In case of 0, we need to check the high bits for the IEEE -0 pattern. + Register high_word32_of_input = kScratchRegister; + Pextrd(high_word32_of_input, src, 1); + cmpl(high_word32_of_input, Immediate(0)); + JumpIf(less, fail); + + bind(&check_done); +} + void MaglevAssembler::TryChangeFloat64ToIndex(Register result, DoubleRegister value, Label* success, Label* fail) { diff --git a/src/maglev/x64/maglev-ir-x64.cc b/src/maglev/x64/maglev-ir-x64.cc index 926d771c6ecd..dafe4ca77b10 100644 --- a/src/maglev/x64/maglev-ir-x64.cc +++ b/src/maglev/x64/maglev-ir-x64.cc @@ -1031,41 +1031,6 @@ void HoleyFloat64ToMaybeNanFloat64::GenerateCode(MaglevAssembler* masm, __ Subsd(value, kScratchDoubleReg); } -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()); - DoubleRegister converted_back = kScratchDoubleReg; - - // Convert the input float64 value to uint32. - Label* deopt = __ GetDeoptLabel(this, DeoptimizeReason::kNotUint32); - __ Cvttsd2ui(result_reg, input_reg, deopt); - // Convert that uint32 value back to float64. - __ Cvtlui2sd(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. - __ Ucomisd(input_reg, converted_back); - __ EmitEagerDeoptIf(parity_even, DeoptimizeReason::kNotUint32, this); - __ EmitEagerDeoptIf(not_equal, DeoptimizeReason::kNotUint32, this); - - // Check if {input} is -0. - Label check_done; - __ cmpl(result_reg, Immediate(0)); - __ j(not_equal, &check_done); - - // In case of 0, we need to check the high bits for the IEEE -0 pattern. - Register high_word32_of_input = kScratchRegister; - __ Pextrd(high_word32_of_input, input_reg, 1); - __ cmpl(high_word32_of_input, Immediate(0)); - __ EmitEagerDeoptIf(less, DeoptimizeReason::kNotUint32, this); - - __ bind(&check_done); -} - namespace { enum class ReduceInterruptBudgetType { kLoop, kReturn };