diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc index 853021b503..7267e26002 100644 --- a/src/maglev/maglev-graph-builder.cc +++ b/src/maglev/maglev-graph-builder.cc @@ -384,8 +384,12 @@ constexpr bool BinaryOperationHasInt32FastPath() { case Operation::kLessThanOrEqual: case Operation::kGreaterThan: case Operation::kGreaterThanOrEqual: + case Operation::kDecrement: + case Operation::kIncrement: + case Operation::kNegate: return true; case Operation::kExponentiate: + case Operation::kBitwiseNot: return false; } } @@ -409,19 +413,24 @@ constexpr bool BinaryOperationHasFloat64FastPath() { // - Int32 operation node, // - Identity of int32 operation (e.g, 0 for add/sub and 1 for mul/div), if it // exists, or otherwise {}. -#define MAP_OPERATION_TO_INT32_NODE(V) \ - V(Add, Int32AddWithOverflow, 0) \ - V(Subtract, Int32SubtractWithOverflow, 0) \ - V(Multiply, Int32MultiplyWithOverflow, 1) \ - V(Divide, Int32DivideWithOverflow, 1) \ - V(Modulus, Int32ModulusWithOverflow, {}) \ - V(BitwiseAnd, Int32BitwiseAnd, ~0) \ - V(BitwiseOr, Int32BitwiseOr, 0) \ - V(BitwiseXor, Int32BitwiseXor, 0) \ - V(ShiftLeft, Int32ShiftLeft, 0) \ - V(ShiftRight, Int32ShiftRight, 0) \ +#define MAP_BINARY_OPERATION_TO_INT32_NODE(V) \ + V(Add, Int32AddWithOverflow, 0) \ + V(Subtract, Int32SubtractWithOverflow, 0) \ + V(Multiply, Int32MultiplyWithOverflow, 1) \ + V(Divide, Int32DivideWithOverflow, 1) \ + V(Modulus, Int32ModulusWithOverflow, {}) \ + V(BitwiseAnd, Int32BitwiseAnd, ~0) \ + V(BitwiseOr, Int32BitwiseOr, 0) \ + V(BitwiseXor, Int32BitwiseXor, 0) \ + V(ShiftLeft, Int32ShiftLeft, 0) \ + V(ShiftRight, Int32ShiftRight, 0) \ V(ShiftRightLogical, Int32ShiftRightLogical, {}) +#define MAP_UNARY_OPERATION_TO_INT32_NODE(V) \ + V(Increment, Int32IncrementWithOverflow) \ + V(Decrement, Int32DecrementWithOverflow) \ + V(Negate, Int32NegateWithOverflow) + #define MAP_COMPARE_OPERATION_TO_INT32_NODE(V) \ V(Equal, Int32Equal) \ V(StrictEqual, Int32StrictEqual) \ @@ -444,7 +453,7 @@ static constexpr base::Optional Int32Identity() { #define CASE(op, _, identity) \ case Operation::k##op: \ return identity; - MAP_OPERATION_TO_INT32_NODE(CASE) + MAP_BINARY_OPERATION_TO_INT32_NODE(CASE) #undef CASE default: UNREACHABLE(); @@ -459,7 +468,8 @@ struct Int32NodeForHelper; struct Int32NodeForHelper { \ using type = OpNode; \ }; -MAP_OPERATION_TO_INT32_NODE(SPECIALIZATION) +MAP_UNARY_OPERATION_TO_INT32_NODE(SPECIALIZATION) +MAP_BINARY_OPERATION_TO_INT32_NODE(SPECIALIZATION) MAP_COMPARE_OPERATION_TO_INT32_NODE(SPECIALIZATION) #undef SPECIALIZATION @@ -507,6 +517,21 @@ void MaglevGraphBuilder::BuildGenericBinarySmiOperationNode() { {left, right}, compiler::FeedbackSource{feedback(), slot_index})); } +template +void MaglevGraphBuilder::BuildInt32UnaryOperationNode() { + // TODO(victorgomes): Get the TruncatedInt32 version when we support + // BitwiseNot. + ValueNode* value = GetAccumulatorInt32(); + using OpNodeT = Int32NodeFor; + OpNodeT* result = AddNewNode({value}); + NodeInfo* node_info = known_node_aspects().GetOrCreateInfoFor(result); + node_info->type = NodeType::kSmi; + static_assert(OpNodeT::kProperties.value_representation() == + ValueRepresentation::kInt32); + node_info->tagged_alternative = AddNewNode({result}); + SetAccumulator(result); +} + template ValueNode* MaglevGraphBuilder::TryFoldInt32BinaryOperation(ValueNode* left, ValueNode* right) { @@ -688,7 +713,20 @@ void MaglevGraphBuilder::BuildFloat64BinaryOperationNode() { template void MaglevGraphBuilder::VisitUnaryOperation() { - // TODO(victorgomes): Use feedback info and create optimized versions. + FeedbackNexus nexus = FeedbackNexusForOperand(0); + switch (nexus.GetBinaryOperationFeedback()) { + case BinaryOperationHint::kNone: + return EmitUnconditionalDeopt( + DeoptimizeReason::kInsufficientTypeFeedbackForBinaryOperation); + case BinaryOperationHint::kSignedSmall: + if constexpr (BinaryOperationHasInt32FastPath()) { + return BuildInt32UnaryOperationNode(); + } + break; + default: + // Fallback to generic node. + break; + } BuildGenericUnaryOperationNode(); } diff --git a/src/maglev/maglev-graph-builder.h b/src/maglev/maglev-graph-builder.h index f9ecd96d37..10e838a46e 100644 --- a/src/maglev/maglev-graph-builder.h +++ b/src/maglev/maglev-graph-builder.h @@ -1306,6 +1306,8 @@ class MaglevGraphBuilder { template ValueNode* TryFoldInt32BinaryOperation(ValueNode* left, int right); + template + void BuildInt32UnaryOperationNode(); template void BuildInt32BinaryOperationNode(); template diff --git a/src/maglev/maglev-graph-verifier.h b/src/maglev/maglev-graph-verifier.h index 268414e464..58f40c197f 100644 --- a/src/maglev/maglev-graph-verifier.h +++ b/src/maglev/maglev-graph-verifier.h @@ -180,6 +180,9 @@ class MaglevGraphVerifier { case Opcode::kChangeInt32ToFloat64: case Opcode::kInt32ToNumber: case Opcode::kBuiltinStringFromCharCode: + case Opcode::kInt32IncrementWithOverflow: + case Opcode::kInt32DecrementWithOverflow: + case Opcode::kInt32NegateWithOverflow: DCHECK_EQ(node->input_count(), 1); CheckValueInputIs(node, 0, ValueRepresentation::kInt32); break; diff --git a/src/maglev/maglev-ir.cc b/src/maglev/maglev-ir.cc index 4d060cdbd9..a72b6245b6 100644 --- a/src/maglev/maglev-ir.cc +++ b/src/maglev/maglev-ir.cc @@ -3042,6 +3042,45 @@ void Int32ShiftRightLogical::GenerateCode(MaglevAssembler* masm, __ shrl_cl(left); } +void Int32IncrementWithOverflow::AllocateVreg( + MaglevVregAllocationState* vreg_state) { + UseRegister(value_input()); + DefineSameAsFirst(vreg_state, this); +} + +void Int32IncrementWithOverflow::GenerateCode(MaglevAssembler* masm, + const ProcessingState& state) { + Register value = ToRegister(value_input()); + __ incl(value); + __ EmitEagerDeoptIf(overflow, DeoptimizeReason::kOverflow, this); +} + +void Int32DecrementWithOverflow::AllocateVreg( + MaglevVregAllocationState* vreg_state) { + UseRegister(value_input()); + DefineSameAsFirst(vreg_state, this); +} + +void Int32DecrementWithOverflow::GenerateCode(MaglevAssembler* masm, + const ProcessingState& state) { + Register value = ToRegister(value_input()); + __ decl(value); + __ EmitEagerDeoptIf(overflow, DeoptimizeReason::kOverflow, this); +} + +void Int32NegateWithOverflow::AllocateVreg( + MaglevVregAllocationState* vreg_state) { + UseRegister(value_input()); + DefineSameAsFirst(vreg_state, this); +} + +void Int32NegateWithOverflow::GenerateCode(MaglevAssembler* masm, + const ProcessingState& state) { + Register value = ToRegister(value_input()); + __ negl(value); + __ EmitEagerDeoptIf(overflow, DeoptimizeReason::kOverflow, this); +} + namespace { constexpr Condition ConditionFor(Operation operation) { diff --git a/src/maglev/maglev-ir.h b/src/maglev/maglev-ir.h index af4acaf031..61aadcd948 100644 --- a/src/maglev/maglev-ir.h +++ b/src/maglev/maglev-ir.h @@ -86,9 +86,9 @@ class CompactInterpreterFrameState; V(Int32ShiftRight) \ V(Int32ShiftRightLogical) \ /*V(Int32BitwiseNot) */ \ - /*V(Int32NegateWithOverflow) */ \ - /*V(Int32IncrementWithOverflow)*/ \ - /*V(Int32DecrementWithOverflow)*/ \ + V(Int32NegateWithOverflow) \ + V(Int32IncrementWithOverflow) \ + V(Int32DecrementWithOverflow) \ V(Int32Equal) \ V(Int32StrictEqual) \ V(Int32LessThan) \ @@ -1642,7 +1642,7 @@ class BinaryWithFeedbackNode : public FixedInputValueNodeT<2, Derived> { const compiler::FeedbackSource feedback_; }; -#define DEF_OPERATION_NODE(Name, Super, OpName) \ +#define DEF_OPERATION_WITH_FEEDBACK_NODE(Name, Super, OpName) \ class Name : public Super { \ using Base = Super; \ \ @@ -1655,16 +1655,15 @@ class BinaryWithFeedbackNode : public FixedInputValueNodeT<2, Derived> { }; #define DEF_UNARY_WITH_FEEDBACK_NODE(Name) \ - DEF_OPERATION_NODE(Generic##Name, UnaryWithFeedbackNode, Name) + DEF_OPERATION_WITH_FEEDBACK_NODE(Generic##Name, UnaryWithFeedbackNode, Name) #define DEF_BINARY_WITH_FEEDBACK_NODE(Name) \ - DEF_OPERATION_NODE(Generic##Name, BinaryWithFeedbackNode, Name) + DEF_OPERATION_WITH_FEEDBACK_NODE(Generic##Name, BinaryWithFeedbackNode, Name) UNARY_OPERATION_LIST(DEF_UNARY_WITH_FEEDBACK_NODE) ARITHMETIC_OPERATION_LIST(DEF_BINARY_WITH_FEEDBACK_NODE) COMPARISON_OPERATION_LIST(DEF_BINARY_WITH_FEEDBACK_NODE) #undef DEF_UNARY_WITH_FEEDBACK_NODE #undef DEF_BINARY_WITH_FEEDBACK_NODE - -#undef DEF_OPERATION_NODE +#undef DEF_OPERATION_WITH_FEEDBACK_NODE template class Int32BinaryWithOverflowNode : public FixedInputValueNodeT<2, Derived> { @@ -1723,17 +1722,6 @@ class Int32BinaryNode : public FixedInputValueNodeT<2, Derived> { explicit Int32BinaryNode(uint64_t bitfield) : Base(bitfield) {} }; -#define DEF_OPERATION_NODE(Name, Super, OpName) \ - class Name : public Super { \ - using Base = Super; \ - \ - public: \ - explicit Name(uint64_t bitfield) : Base(bitfield) {} \ - void AllocateVreg(MaglevVregAllocationState*); \ - void GenerateCode(MaglevAssembler*, const ProcessingState&); \ - void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} \ - }; - #define DEF_INT32_BINARY_NODE(Name) \ DEF_OPERATION_NODE(Int32##Name, Int32BinaryNode, Name) DEF_INT32_BINARY_NODE(BitwiseAnd) @@ -1742,9 +1730,29 @@ DEF_INT32_BINARY_NODE(BitwiseXor) DEF_INT32_BINARY_NODE(ShiftLeft) DEF_INT32_BINARY_NODE(ShiftRight) #undef DEF_INT32_BINARY_NODE -// DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Negate) -// DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Increment) -// DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Decrement) + +template +class Int32UnaryWithOverflowNode : public FixedInputValueNodeT<1, Derived> { + using Base = FixedInputValueNodeT<1, Derived>; + + public: + static constexpr OpProperties kProperties = + OpProperties::EagerDeopt() | OpProperties::Int32(); + + static constexpr int kValueIndex = 0; + Input& value_input() { return Node::input(kValueIndex); } + + protected: + explicit Int32UnaryWithOverflowNode(uint64_t bitfield) : Base(bitfield) {} +}; + +#define DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Name) \ + DEF_OPERATION_NODE(Int32##Name##WithOverflow, Int32UnaryWithOverflowNode, \ + Name) +DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Negate) +DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Increment) +DEF_INT32_UNARY_WITH_OVERFLOW_NODE(Decrement) +#undef DEF_INT32_UNARY_WITH_OVERFLOW_NODE class Int32ShiftRightLogical : public FixedInputValueNodeT<2, Int32ShiftRightLogical> { @@ -1784,17 +1792,6 @@ class Int32CompareNode : public FixedInputValueNodeT<2, Derived> { void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} }; -#define DEF_OPERATION_NODE(Name, Super, OpName) \ - class Name : public Super { \ - using Base = Super; \ - \ - public: \ - explicit Name(uint64_t bitfield) : Base(bitfield) {} \ - void AllocateVreg(MaglevVregAllocationState*); \ - void GenerateCode(MaglevAssembler*, const ProcessingState&); \ - void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} \ - }; - #define DEF_INT32_COMPARE_NODE(Name) \ DEF_OPERATION_NODE(Int32##Name, Int32CompareNode, Name) DEF_INT32_COMPARE_NODE(Equal) @@ -1805,8 +1802,6 @@ DEF_INT32_COMPARE_NODE(GreaterThan) DEF_INT32_COMPARE_NODE(GreaterThanOrEqual) #undef DEF_INT32_COMPARE_NODE -#undef DEF_OPERATION_NODE - template class Float64BinaryNode : public FixedInputValueNodeT<2, Derived> { using Base = FixedInputValueNodeT<2, Derived>; @@ -1825,17 +1820,6 @@ class Float64BinaryNode : public FixedInputValueNodeT<2, Derived> { void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} }; -#define DEF_OPERATION_NODE(Name, Super, OpName) \ - class Name : public Super { \ - using Base = Super; \ - \ - public: \ - explicit Name(uint64_t bitfield) : Base(bitfield) {} \ - void AllocateVreg(MaglevVregAllocationState*); \ - void GenerateCode(MaglevAssembler*, const ProcessingState&); \ - void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} \ - }; - #define DEF_FLOAT64_BINARY_NODE(Name) \ DEF_OPERATION_NODE(Float64##Name, Float64BinaryNode, Name) DEF_FLOAT64_BINARY_NODE(Add) @@ -1870,17 +1854,6 @@ class Float64CompareNode : public FixedInputValueNodeT<2, Derived> { void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} }; -#define DEF_OPERATION_NODE(Name, Super, OpName) \ - class Name : public Super { \ - using Base = Super; \ - \ - public: \ - explicit Name(uint64_t bitfield) : Base(bitfield) {} \ - void AllocateVreg(MaglevVregAllocationState*); \ - void GenerateCode(MaglevAssembler*, const ProcessingState&); \ - void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} \ - }; - #define DEF_FLOAT64_COMPARE_NODE(Name) \ DEF_OPERATION_NODE(Float64##Name, Float64CompareNode, Name) DEF_FLOAT64_COMPARE_NODE(Equal)