[maglev] Addition Smi nodes
If we have a smi operation in the feedback vector, we emit SmiTag Int32AddWithOverflow and SmiUntag nodes, instead of a generic operation binary node. Change-Id: Idb9ce2b60289fbe492bf269793660b32de23e2b3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3560641 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Auto-Submit: Victor Gomes <victorgomes@chromium.org> Commit-Queue: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/main@{#79775}
This commit is contained in:
parent
8502508962
commit
3eeea13cf7
@ -155,6 +155,25 @@ void MaglevGraphBuilder::VisitUnaryOperation() {
|
||||
|
||||
template <Operation kOperation>
|
||||
void MaglevGraphBuilder::VisitBinaryOperation() {
|
||||
FeedbackNexus nexus = feedback_nexus(1);
|
||||
|
||||
if (nexus.ic_state() == InlineCacheState::MONOMORPHIC) {
|
||||
if (nexus.kind() == FeedbackSlotKind::kBinaryOp) {
|
||||
BinaryOperationHint hint = nexus.GetBinaryOperationFeedback();
|
||||
|
||||
if (hint == BinaryOperationHint::kSignedSmall) {
|
||||
ValueNode* left = AddNewNode<CheckedSmiUntag>({LoadRegister(0)});
|
||||
ValueNode* right = AddNewNode<CheckedSmiUntag>({GetAccumulator()});
|
||||
|
||||
if (kOperation == Operation::kAdd) {
|
||||
ValueNode* result = AddNewNode<Int32AddWithOverflow>({left, right});
|
||||
SetAccumulatorToNewNode<CheckedSmiTag>({result});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(victorgomes): Use feedback info and create optimized versions.
|
||||
BuildGenericBinaryOperationNode<kOperation>();
|
||||
}
|
||||
|
@ -65,10 +65,7 @@ void DefineAsFixed(MaglevVregAllocationState* vreg_state, Node* node,
|
||||
vreg_state->AllocateVirtualRegister());
|
||||
}
|
||||
|
||||
// TODO(victorgomes): Use this for smi binary operation and remove attribute
|
||||
// [[maybe_unused]].
|
||||
[[maybe_unused]] void DefineSameAsFirst(MaglevVregAllocationState* vreg_state,
|
||||
Node* node) {
|
||||
void DefineSameAsFirst(MaglevVregAllocationState* vreg_state, Node* node) {
|
||||
node->result().SetUnallocated(vreg_state->AllocateVirtualRegister(), 0);
|
||||
}
|
||||
|
||||
@ -703,6 +700,46 @@ void BinaryWithFeedbackNode<Derived, kOperation>::GenerateCode(
|
||||
GENERIC_OPERATIONS_NODE_LIST(DEF_OPERATION)
|
||||
#undef DEF_OPERATION
|
||||
|
||||
void CheckedSmiUntag::AllocateVreg(MaglevVregAllocationState* vreg_state,
|
||||
const ProcessingState& state) {
|
||||
UseRegister(input());
|
||||
DefineSameAsFirst(vreg_state, this);
|
||||
}
|
||||
|
||||
void CheckedSmiUntag::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
__ sarl(ToRegister(input()), Immediate(1));
|
||||
EmitEagerDeoptIf(carry, code_gen_state, this);
|
||||
}
|
||||
|
||||
void CheckedSmiTag::AllocateVreg(MaglevVregAllocationState* vreg_state,
|
||||
const ProcessingState& state) {
|
||||
UseRegister(input());
|
||||
DefineSameAsFirst(vreg_state, this);
|
||||
}
|
||||
|
||||
void CheckedSmiTag::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
Register reg = ToRegister(input());
|
||||
__ addl(reg, reg);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
}
|
||||
|
||||
void Int32AddWithOverflow::AllocateVreg(MaglevVregAllocationState* vreg_state,
|
||||
const ProcessingState& state) {
|
||||
UseRegister(left_input());
|
||||
UseRegister(right_input());
|
||||
DefineSameAsFirst(vreg_state, this);
|
||||
}
|
||||
|
||||
void Int32AddWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
Register left = ToRegister(left_input());
|
||||
Register right = ToRegister(right_input());
|
||||
__ addl(left, right);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
}
|
||||
|
||||
void Phi::AllocateVreg(MaglevVregAllocationState* vreg_state,
|
||||
const ProcessingState& state) {
|
||||
// Phi inputs are processed in the post-process, once loop phis' inputs'
|
||||
|
@ -76,6 +76,9 @@ class CompactInterpreterFrameState;
|
||||
V(RegisterInput) \
|
||||
V(RootConstant) \
|
||||
V(SmiConstant) \
|
||||
V(CheckedSmiTag) \
|
||||
V(CheckedSmiUntag) \
|
||||
V(Int32AddWithOverflow) \
|
||||
GENERIC_OPERATIONS_NODE_LIST(V)
|
||||
|
||||
#define NODE_LIST(V) \
|
||||
@ -918,6 +921,55 @@ COMPARISON_OPERATION_LIST(DEF_BINARY_WITH_FEEDBACK_NODE)
|
||||
#undef DEF_UNARY_WITH_FEEDBACK_NODE
|
||||
#undef DEF_BINARY_WITH_FEEDBACK_NODE
|
||||
|
||||
class CheckedSmiTag : public FixedInputValueNodeT<1, CheckedSmiTag> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedSmiTag>;
|
||||
|
||||
public:
|
||||
explicit CheckedSmiTag(uint32_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
Input& input() { return Node::input(0); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
|
||||
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class CheckedSmiUntag : public FixedInputValueNodeT<1, CheckedSmiUntag> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedSmiUntag>;
|
||||
|
||||
public:
|
||||
explicit CheckedSmiUntag(uint32_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
Input& input() { return Node::input(0); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
|
||||
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class Int32AddWithOverflow
|
||||
: public FixedInputValueNodeT<2, Int32AddWithOverflow> {
|
||||
using Base = FixedInputValueNodeT<2, Int32AddWithOverflow>;
|
||||
|
||||
public:
|
||||
explicit Int32AddWithOverflow(uint32_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
static constexpr int kLeftIndex = 0;
|
||||
static constexpr int kRightIndex = 1;
|
||||
Input& left_input() { return Node::input(kLeftIndex); }
|
||||
Input& right_input() { return Node::input(kRightIndex); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*, const ProcessingState&);
|
||||
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class InitialValue : public FixedInputValueNodeT<0, InitialValue> {
|
||||
using Base = FixedInputValueNodeT<0, InitialValue>;
|
||||
|
||||
|
41
test/mjsunit/maglev/add-smi.js
Normal file
41
test/mjsunit/maglev/add-smi.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --maglev --no-stress-opt
|
||||
|
||||
// Checks Smi add operation and deopt while untagging.
|
||||
(function() {
|
||||
function add(x, y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(add);
|
||||
assertEquals(3, add(1, 2));
|
||||
|
||||
%OptimizeMaglevOnNextCall(add);
|
||||
assertEquals(3, add(1, 2));
|
||||
assertTrue(isMaglevved(add));
|
||||
|
||||
// We should deopt here in SmiUntag.
|
||||
assertEquals(0x40000000, add(1, 0x3FFFFFFF));
|
||||
assertFalse(isMaglevved(add));
|
||||
})();
|
||||
|
||||
// Checks when we deopt due to tagging.
|
||||
(function() {
|
||||
function add(x, y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(add);
|
||||
assertEquals(3, add(1, 2));
|
||||
|
||||
%OptimizeMaglevOnNextCall(add);
|
||||
assertEquals(3, add(1, 2));
|
||||
assertTrue(isMaglevved(add));
|
||||
|
||||
// We should deopt here in SmiTag.
|
||||
assertEquals(3.2, add(1.2, 2));
|
||||
assertFalse(isMaglevved(add));
|
||||
})();
|
Loading…
Reference in New Issue
Block a user