Commit e6a08cd9 authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add a checked Float64->Int32 node

This can happen when we have a load from a double field of a value that
canonicalises to a Smi, and we then use that Smi value in Smi-feedback
arithmetic.

Bug: v8:7700
Fixed: v8:13282
Change-Id: I6d8245b8393f7595c3442985087ebb8e806061eb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3890999
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarJakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83210}
parent 1628c905
......@@ -682,8 +682,6 @@ class MaglevGraphBuilder {
case ValueRepresentation::kInt32:
return value;
case ValueRepresentation::kFloat64:
// We should not be able to request an Int32 from a Float64 input,
// unless it's an unboxing of a tagged value or a conversion from int32.
if (value->Is<CheckedFloat64Unbox>()) {
// TODO(leszeks): Maybe convert the CheckedFloat64Unbox to
// ChangeInt32ToFloat64 with this CheckedSmiUntag as the input.
......@@ -692,7 +690,7 @@ class MaglevGraphBuilder {
} else if (value->Is<ChangeInt32ToFloat64>()) {
return value->input(0).node();
}
UNREACHABLE();
return AddNewConversionNode<CheckedTruncateFloat64ToInt32>(reg, value);
}
UNREACHABLE();
}
......
......@@ -152,6 +152,7 @@ class MaglevGraphVerifier {
CheckValueInputIs(node, 0, ValueRepresentation::kInt32);
break;
case Opcode::kFloat64Box:
case Opcode::kCheckedTruncateFloat64ToInt32:
DCHECK_EQ(node->input_count(), 1);
CheckValueInputIs(node, 0, ValueRepresentation::kFloat64);
break;
......
......@@ -2839,6 +2839,40 @@ void ChangeInt32ToFloat64::GenerateCode(MaglevAssembler* masm,
__ Cvtlsi2sd(ToDoubleRegister(result()), ToRegister(input()));
}
void CheckedTruncateFloat64ToInt32::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
UseRegister(input());
DefineAsRegister(vreg_state, this);
}
void CheckedTruncateFloat64ToInt32::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 int32.
__ Cvttsd2si(result_reg, input_reg);
// Convert that int32 value back to float64.
__ Cvtlsi2sd(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.
__ Ucomisd(input_reg, converted_back);
__ EmitEagerDeoptIf(not_equal, DeoptimizeReason::kNotInt32, 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::kNotInt32, this);
__ bind(&check_done);
}
void Phi::AllocateVreg(MaglevVregAllocationState* vreg_state) {
// Phi inputs are processed in the post-process, once loop phis' inputs'
// v-regs are allocated.
......
......@@ -117,68 +117,69 @@ class CompactInterpreterFrameState;
V(RootConstant) \
V(SmiConstant)
#define VALUE_NODE_LIST(V) \
V(Call) \
V(CallBuiltin) \
V(CallRuntime) \
V(CallWithSpread) \
V(Construct) \
V(ConstructWithSpread) \
V(CreateEmptyArrayLiteral) \
V(CreateArrayLiteral) \
V(CreateShallowArrayLiteral) \
V(CreateObjectLiteral) \
V(CreateEmptyObjectLiteral) \
V(CreateShallowObjectLiteral) \
V(CreateFunctionContext) \
V(CreateClosure) \
V(FastCreateClosure) \
V(CreateRegExpLiteral) \
V(DeleteProperty) \
V(ForInPrepare) \
V(ForInNext) \
V(GeneratorRestoreRegister) \
V(GetIterator) \
V(GetSecondReturnedValue) \
V(GetTemplateObject) \
V(InitialValue) \
V(LoadTaggedField) \
V(LoadDoubleField) \
V(LoadTaggedElement) \
V(LoadDoubleElement) \
V(LoadGlobal) \
V(LoadNamedGeneric) \
V(LoadNamedFromSuperGeneric) \
V(SetNamedGeneric) \
V(DefineNamedOwnGeneric) \
V(StoreInArrayLiteralGeneric) \
V(StoreGlobal) \
V(GetKeyedGeneric) \
V(SetKeyedGeneric) \
V(DefineKeyedOwnGeneric) \
V(Phi) \
V(RegisterInput) \
V(CheckedSmiTag) \
V(CheckedSmiUntag) \
V(CheckedInternalizedString) \
V(ChangeInt32ToFloat64) \
V(Float64Box) \
V(CheckedFloat64Unbox) \
V(LogicalNot) \
V(SetPendingMessage) \
V(ToBooleanLogicalNot) \
V(TaggedEqual) \
V(TaggedNotEqual) \
V(TestInstanceOf) \
V(TestUndetectable) \
V(TestTypeOf) \
V(ToName) \
V(ToNumberOrNumeric) \
V(ToObject) \
V(ToString) \
CONSTANT_VALUE_NODE_LIST(V) \
INT32_OPERATIONS_NODE_LIST(V) \
FLOAT64_OPERATIONS_NODE_LIST(V) \
#define VALUE_NODE_LIST(V) \
V(Call) \
V(CallBuiltin) \
V(CallRuntime) \
V(CallWithSpread) \
V(Construct) \
V(ConstructWithSpread) \
V(CreateEmptyArrayLiteral) \
V(CreateArrayLiteral) \
V(CreateShallowArrayLiteral) \
V(CreateObjectLiteral) \
V(CreateEmptyObjectLiteral) \
V(CreateShallowObjectLiteral) \
V(CreateFunctionContext) \
V(CreateClosure) \
V(FastCreateClosure) \
V(CreateRegExpLiteral) \
V(DeleteProperty) \
V(ForInPrepare) \
V(ForInNext) \
V(GeneratorRestoreRegister) \
V(GetIterator) \
V(GetSecondReturnedValue) \
V(GetTemplateObject) \
V(InitialValue) \
V(LoadTaggedField) \
V(LoadDoubleField) \
V(LoadTaggedElement) \
V(LoadDoubleElement) \
V(LoadGlobal) \
V(LoadNamedGeneric) \
V(LoadNamedFromSuperGeneric) \
V(SetNamedGeneric) \
V(DefineNamedOwnGeneric) \
V(StoreInArrayLiteralGeneric) \
V(StoreGlobal) \
V(GetKeyedGeneric) \
V(SetKeyedGeneric) \
V(DefineKeyedOwnGeneric) \
V(Phi) \
V(RegisterInput) \
V(CheckedSmiTag) \
V(CheckedSmiUntag) \
V(CheckedInternalizedString) \
V(ChangeInt32ToFloat64) \
V(CheckedTruncateFloat64ToInt32) \
V(Float64Box) \
V(CheckedFloat64Unbox) \
V(LogicalNot) \
V(SetPendingMessage) \
V(ToBooleanLogicalNot) \
V(TaggedEqual) \
V(TaggedNotEqual) \
V(TestInstanceOf) \
V(TestUndetectable) \
V(TestTypeOf) \
V(ToName) \
V(ToNumberOrNumeric) \
V(ToObject) \
V(ToString) \
CONSTANT_VALUE_NODE_LIST(V) \
INT32_OPERATIONS_NODE_LIST(V) \
FLOAT64_OPERATIONS_NODE_LIST(V) \
GENERIC_OPERATIONS_NODE_LIST(V)
#define GAP_MOVE_NODE_LIST(V) \
......@@ -1746,6 +1747,22 @@ class ChangeInt32ToFloat64
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
};
class CheckedTruncateFloat64ToInt32
: public FixedInputValueNodeT<1, CheckedTruncateFloat64ToInt32> {
using Base = FixedInputValueNodeT<1, CheckedTruncateFloat64ToInt32>;
public:
explicit CheckedTruncateFloat64ToInt32(uint64_t bitfield) : Base(bitfield) {}
static constexpr OpProperties kProperties = OpProperties::EagerDeopt() |
OpProperties::Int32() |
OpProperties::ConversionNode();
Input& input() { return Node::input(0); }
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
};
class CheckedFloat64Unbox
: public FixedInputValueNodeT<1, CheckedFloat64Unbox> {
using Base = FixedInputValueNodeT<1, CheckedFloat64Unbox>;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment