[maglev] Add Int32 Negate, Increment and Decrement

Drive-by: delete repeated DEF_OPERATION_NODE macro.

Bug: v8:7700
Change-Id: Ie98e7166c9dafe802049b10c57831fae3e652e40
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4051244
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84446}
This commit is contained in:
Victor Gomes 2022-11-23 15:59:20 +01:00 committed by V8 LUCI CQ
parent b8f0d2d351
commit 9476523b59
5 changed files with 126 additions and 71 deletions

View File

@ -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<int> 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<Operation::k##op> { \
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 <Operation kOperation>
void MaglevGraphBuilder::BuildInt32UnaryOperationNode() {
// TODO(victorgomes): Get the TruncatedInt32 version when we support
// BitwiseNot.
ValueNode* value = GetAccumulatorInt32();
using OpNodeT = Int32NodeFor<kOperation>;
OpNodeT* result = AddNewNode<OpNodeT>({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<CheckedSmiTagInt32>({result});
SetAccumulator(result);
}
template <Operation kOperation>
ValueNode* MaglevGraphBuilder::TryFoldInt32BinaryOperation(ValueNode* left,
ValueNode* right) {
@ -688,7 +713,20 @@ void MaglevGraphBuilder::BuildFloat64BinaryOperationNode() {
template <Operation kOperation>
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<kOperation>()) {
return BuildInt32UnaryOperationNode<kOperation>();
}
break;
default:
// Fallback to generic node.
break;
}
BuildGenericUnaryOperationNode<kOperation>();
}

View File

@ -1306,6 +1306,8 @@ class MaglevGraphBuilder {
template <Operation kOperation>
ValueNode* TryFoldInt32BinaryOperation(ValueNode* left, int right);
template <Operation kOperation>
void BuildInt32UnaryOperationNode();
template <Operation kOperation>
void BuildInt32BinaryOperationNode();
template <Operation kOperation>

View File

@ -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;

View File

@ -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) {

View File

@ -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<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
@ -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 Derived, Operation kOperation>
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<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
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 Derived, Operation kOperation>
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<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
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 Derived, Operation kOperation>
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<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
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<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
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)