[turbofan] Support subtraction displacements in BaseWithIndexAndDisplacementMatcher
Previously, the following schedule fragment: 1: Parameter[0](0) 2: Parameter[1](0) 7: Int32Constant[1] 8: Int32Sub(2, 7) 9: Load[kRepTagged|kTypeAny](1, 8) would generate the following code (on ia32): mov eax,[ebp+0x8] mov ecx,[ebp+0xc] sub eax,0x1 mov eax,[eax+ecx*1] Now it generates: mov eax,[ebp+0x8] mov ecx,[ebp+0xc] mov eax,[eax+ecx*1-1] Similar pattern matching also now works on x64. BUG=v8:5192 LOG=N Review-Url: https://codereview.chromium.org/2137323003 Cr-Commit-Position: refs/heads/master@{#37701}
This commit is contained in:
parent
fd420203ec
commit
574f6fe127
@ -82,12 +82,16 @@ class IA32OperandGenerator final : public OperandGenerator {
|
||||
|
||||
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base,
|
||||
Node* displacement_node,
|
||||
DisplacementMode displacement_mode,
|
||||
InstructionOperand inputs[],
|
||||
size_t* input_count) {
|
||||
AddressingMode mode = kMode_MRI;
|
||||
int32_t displacement = (displacement_node == nullptr)
|
||||
? 0
|
||||
: OpParameter<int32_t>(displacement_node);
|
||||
if (displacement_mode == kNegativeDisplacement) {
|
||||
displacement = -displacement;
|
||||
}
|
||||
if (base != nullptr) {
|
||||
if (base->opcode() == IrOpcode::kInt32Constant) {
|
||||
displacement += OpParameter<int32_t>(base);
|
||||
@ -145,8 +149,9 @@ class IA32OperandGenerator final : public OperandGenerator {
|
||||
BaseWithIndexAndDisplacement32Matcher m(node, true);
|
||||
DCHECK(m.matches());
|
||||
if ((m.displacement() == nullptr || CanBeImmediate(m.displacement()))) {
|
||||
return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(),
|
||||
m.displacement(), inputs, input_count);
|
||||
return GenerateMemoryOperandInputs(
|
||||
m.index(), m.scale(), m.base(), m.displacement(),
|
||||
m.displacement_mode(), inputs, input_count);
|
||||
} else {
|
||||
inputs[(*input_count)++] = UseRegister(node->InputAt(0));
|
||||
inputs[(*input_count)++] = UseRegister(node->InputAt(1));
|
||||
@ -577,12 +582,14 @@ void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
|
||||
}
|
||||
|
||||
void EmitLea(InstructionSelector* selector, Node* result, Node* index,
|
||||
int scale, Node* base, Node* displacement) {
|
||||
int scale, Node* base, Node* displacement,
|
||||
DisplacementMode displacement_mode) {
|
||||
IA32OperandGenerator g(selector);
|
||||
InstructionOperand inputs[4];
|
||||
size_t input_count = 0;
|
||||
AddressingMode mode = g.GenerateMemoryOperandInputs(
|
||||
index, scale, base, displacement, inputs, &input_count);
|
||||
AddressingMode mode =
|
||||
g.GenerateMemoryOperandInputs(index, scale, base, displacement,
|
||||
displacement_mode, inputs, &input_count);
|
||||
|
||||
DCHECK_NE(0u, input_count);
|
||||
DCHECK_GE(arraysize(inputs), input_count);
|
||||
@ -603,7 +610,7 @@ void InstructionSelector::VisitWord32Shl(Node* node) {
|
||||
if (m.matches()) {
|
||||
Node* index = node->InputAt(0);
|
||||
Node* base = m.power_of_two_plus_one() ? index : nullptr;
|
||||
EmitLea(this, node, index, m.scale(), base, nullptr);
|
||||
EmitLea(this, node, index, m.scale(), base, nullptr, kPositiveDisplacement);
|
||||
return;
|
||||
}
|
||||
VisitShift(this, node, kIA32Shl);
|
||||
@ -743,7 +750,8 @@ void InstructionSelector::VisitInt32Add(Node* node) {
|
||||
InstructionOperand inputs[4];
|
||||
size_t input_count = 0;
|
||||
AddressingMode mode = g.GenerateMemoryOperandInputs(
|
||||
m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count);
|
||||
m.index(), m.scale(), m.base(), m.displacement(), m.displacement_mode(),
|
||||
inputs, &input_count);
|
||||
|
||||
DCHECK_NE(0u, input_count);
|
||||
DCHECK_GE(arraysize(inputs), input_count);
|
||||
@ -777,7 +785,7 @@ void InstructionSelector::VisitInt32Mul(Node* node) {
|
||||
if (m.matches()) {
|
||||
Node* index = node->InputAt(0);
|
||||
Node* base = m.power_of_two_plus_one() ? index : nullptr;
|
||||
EmitLea(this, node, index, m.scale(), base, nullptr);
|
||||
EmitLea(this, node, index, m.scale(), base, nullptr, kPositiveDisplacement);
|
||||
return;
|
||||
}
|
||||
IA32OperandGenerator g(this);
|
||||
|
@ -143,6 +143,10 @@ class OperandGenerator {
|
||||
return sequence()->AddImmediate(ToConstant(node));
|
||||
}
|
||||
|
||||
InstructionOperand UseNegatedImmediate(Node* node) {
|
||||
return sequence()->AddImmediate(ToNegatedConstant(node));
|
||||
}
|
||||
|
||||
InstructionOperand UseLocation(Node* node, LinkageLocation location) {
|
||||
return Use(node, ToUnallocatedOperand(location, GetVReg(node)));
|
||||
}
|
||||
@ -225,6 +229,19 @@ class OperandGenerator {
|
||||
return Constant(static_cast<int32_t>(0));
|
||||
}
|
||||
|
||||
static Constant ToNegatedConstant(const Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kInt32Constant:
|
||||
return Constant(-OpParameter<int32_t>(node));
|
||||
case IrOpcode::kInt64Constant:
|
||||
return Constant(-OpParameter<int64_t>(node));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return Constant(static_cast<int32_t>(0));
|
||||
}
|
||||
|
||||
UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
|
||||
DCHECK_NOT_NULL(node);
|
||||
DCHECK_EQ(operand.virtual_register(), GetVReg(node));
|
||||
|
@ -318,11 +318,12 @@ typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul,
|
||||
typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul,
|
||||
IrOpcode::kWord64Shl> Int64ScaleMatcher;
|
||||
|
||||
|
||||
template <class BinopMatcher, IrOpcode::Value kAddOpcode,
|
||||
IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode>
|
||||
template <class BinopMatcher, IrOpcode::Value AddOpcode,
|
||||
IrOpcode::Value SubOpcode, IrOpcode::Value kMulOpcode,
|
||||
IrOpcode::Value kShiftOpcode>
|
||||
struct AddMatcher : public BinopMatcher {
|
||||
static const IrOpcode::Value kOpcode = kAddOpcode;
|
||||
static const IrOpcode::Value kAddOpcode = AddOpcode;
|
||||
static const IrOpcode::Value kSubOpcode = SubOpcode;
|
||||
typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher;
|
||||
|
||||
AddMatcher(Node* node, bool allow_input_swap)
|
||||
@ -373,6 +374,9 @@ struct AddMatcher : public BinopMatcher {
|
||||
if (this->right().opcode() == kAddOpcode &&
|
||||
this->left().opcode() != kAddOpcode) {
|
||||
this->SwapInputs();
|
||||
} else if (this->right().opcode() == kSubOpcode &&
|
||||
this->left().opcode() != kSubOpcode) {
|
||||
this->SwapInputs();
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,11 +384,14 @@ struct AddMatcher : public BinopMatcher {
|
||||
bool power_of_two_plus_one_;
|
||||
};
|
||||
|
||||
typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul,
|
||||
IrOpcode::kWord32Shl> Int32AddMatcher;
|
||||
typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul,
|
||||
IrOpcode::kWord64Shl> Int64AddMatcher;
|
||||
typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Sub,
|
||||
IrOpcode::kInt32Mul, IrOpcode::kWord32Shl>
|
||||
Int32AddMatcher;
|
||||
typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Sub,
|
||||
IrOpcode::kInt64Mul, IrOpcode::kWord64Shl>
|
||||
Int64AddMatcher;
|
||||
|
||||
enum DisplacementMode { kPositiveDisplacement, kNegativeDisplacement };
|
||||
|
||||
template <class AddMatcher>
|
||||
struct BaseWithIndexAndDisplacementMatcher {
|
||||
@ -393,7 +400,8 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
index_(nullptr),
|
||||
scale_(0),
|
||||
base_(nullptr),
|
||||
displacement_(nullptr) {
|
||||
displacement_(nullptr),
|
||||
displacement_mode_(kPositiveDisplacement) {
|
||||
Initialize(node, allow_input_swap);
|
||||
}
|
||||
|
||||
@ -402,7 +410,8 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
index_(nullptr),
|
||||
scale_(0),
|
||||
base_(nullptr),
|
||||
displacement_(nullptr) {
|
||||
displacement_(nullptr),
|
||||
displacement_mode_(kPositiveDisplacement) {
|
||||
Initialize(node, node->op()->HasProperty(Operator::kCommutative));
|
||||
}
|
||||
|
||||
@ -411,6 +420,7 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
int scale() const { return scale_; }
|
||||
Node* base() const { return base_; }
|
||||
Node* displacement() const { return displacement_; }
|
||||
DisplacementMode displacement_mode() const { return displacement_mode_; }
|
||||
|
||||
private:
|
||||
bool matches_;
|
||||
@ -418,6 +428,7 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
int scale_;
|
||||
Node* base_;
|
||||
Node* displacement_;
|
||||
DisplacementMode displacement_mode_;
|
||||
|
||||
void Initialize(Node* node, bool allow_input_swap) {
|
||||
// The BaseWithIndexAndDisplacementMatcher canonicalizes the order of
|
||||
@ -445,82 +456,123 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
Node* index = nullptr;
|
||||
Node* scale_expression = nullptr;
|
||||
bool power_of_two_plus_one = false;
|
||||
DisplacementMode displacement_mode = kPositiveDisplacement;
|
||||
int scale = 0;
|
||||
if (m.HasIndexInput() && left->OwnedBy(node)) {
|
||||
index = m.IndexInput();
|
||||
scale = m.scale();
|
||||
scale_expression = left;
|
||||
power_of_two_plus_one = m.power_of_two_plus_one();
|
||||
if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) {
|
||||
bool match_found = false;
|
||||
if (right->opcode() == AddMatcher::kSubOpcode && right->OwnedBy(node)) {
|
||||
AddMatcher right_matcher(right);
|
||||
if (right_matcher.right().HasValue()) {
|
||||
// (S + (B + D))
|
||||
// (S + (B - D))
|
||||
base = right_matcher.left().node();
|
||||
displacement = right_matcher.right().node();
|
||||
displacement_mode = kNegativeDisplacement;
|
||||
match_found = true;
|
||||
}
|
||||
}
|
||||
if (!match_found) {
|
||||
if (right->opcode() == AddMatcher::kAddOpcode && right->OwnedBy(node)) {
|
||||
AddMatcher right_matcher(right);
|
||||
if (right_matcher.right().HasValue()) {
|
||||
// (S + (B + D))
|
||||
base = right_matcher.left().node();
|
||||
displacement = right_matcher.right().node();
|
||||
} else {
|
||||
// (S + (B + B))
|
||||
base = right;
|
||||
}
|
||||
} else if (m.right().HasValue()) {
|
||||
// (S + D)
|
||||
displacement = right;
|
||||
} else {
|
||||
// (S + (B + B))
|
||||
// (S + B)
|
||||
base = right;
|
||||
}
|
||||
} else if (m.right().HasValue()) {
|
||||
// (S + D)
|
||||
displacement = right;
|
||||
} else {
|
||||
// (S + B)
|
||||
base = right;
|
||||
}
|
||||
} else {
|
||||
if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) {
|
||||
bool match_found = false;
|
||||
if (left->opcode() == AddMatcher::kSubOpcode && left->OwnedBy(node)) {
|
||||
AddMatcher left_matcher(left);
|
||||
Node* left_left = left_matcher.left().node();
|
||||
Node* left_right = left_matcher.right().node();
|
||||
if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
|
||||
if (left_matcher.right().HasValue()) {
|
||||
// ((S + D) + B)
|
||||
if (left_matcher.right().HasValue()) {
|
||||
if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
|
||||
// ((S - D) + B)
|
||||
index = left_matcher.IndexInput();
|
||||
scale = left_matcher.scale();
|
||||
scale_expression = left_left;
|
||||
power_of_two_plus_one = left_matcher.power_of_two_plus_one();
|
||||
displacement = left_right;
|
||||
displacement_mode = kNegativeDisplacement;
|
||||
base = right;
|
||||
} else if (m.right().HasValue()) {
|
||||
// ((S + B) + D)
|
||||
index = left_matcher.IndexInput();
|
||||
scale = left_matcher.scale();
|
||||
scale_expression = left_left;
|
||||
power_of_two_plus_one = left_matcher.power_of_two_plus_one();
|
||||
base = left_right;
|
||||
displacement = right;
|
||||
} else {
|
||||
// (B + B)
|
||||
index = left;
|
||||
base = right;
|
||||
}
|
||||
} else {
|
||||
if (left_matcher.right().HasValue()) {
|
||||
// ((B + D) + B)
|
||||
// ((B - D) + B)
|
||||
index = left_left;
|
||||
displacement = left_right;
|
||||
base = right;
|
||||
} else if (m.right().HasValue()) {
|
||||
// ((B + B) + D)
|
||||
index = left_left;
|
||||
base = left_right;
|
||||
displacement = right;
|
||||
} else {
|
||||
// (B + B)
|
||||
index = left;
|
||||
displacement_mode = kNegativeDisplacement;
|
||||
base = right;
|
||||
}
|
||||
match_found = true;
|
||||
}
|
||||
} else {
|
||||
if (m.right().HasValue()) {
|
||||
// (B + D)
|
||||
base = left;
|
||||
displacement = right;
|
||||
}
|
||||
if (!match_found) {
|
||||
if (left->opcode() == AddMatcher::kAddOpcode && left->OwnedBy(node)) {
|
||||
AddMatcher left_matcher(left);
|
||||
Node* left_left = left_matcher.left().node();
|
||||
Node* left_right = left_matcher.right().node();
|
||||
if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
|
||||
if (left_matcher.right().HasValue()) {
|
||||
// ((S + D) + B)
|
||||
index = left_matcher.IndexInput();
|
||||
scale = left_matcher.scale();
|
||||
scale_expression = left_left;
|
||||
power_of_two_plus_one = left_matcher.power_of_two_plus_one();
|
||||
displacement = left_right;
|
||||
base = right;
|
||||
} else if (m.right().HasValue()) {
|
||||
// ((S + B) + D)
|
||||
index = left_matcher.IndexInput();
|
||||
scale = left_matcher.scale();
|
||||
scale_expression = left_left;
|
||||
power_of_two_plus_one = left_matcher.power_of_two_plus_one();
|
||||
base = left_right;
|
||||
displacement = right;
|
||||
} else {
|
||||
// (B + B)
|
||||
index = left;
|
||||
base = right;
|
||||
}
|
||||
} else {
|
||||
if (left_matcher.right().HasValue()) {
|
||||
// ((B + D) + B)
|
||||
index = left_left;
|
||||
displacement = left_right;
|
||||
base = right;
|
||||
} else if (m.right().HasValue()) {
|
||||
// ((B + B) + D)
|
||||
index = left_left;
|
||||
base = left_right;
|
||||
displacement = right;
|
||||
} else {
|
||||
// (B + B)
|
||||
index = left;
|
||||
base = right;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// (B + B)
|
||||
base = left;
|
||||
index = right;
|
||||
if (m.right().HasValue()) {
|
||||
// (B + D)
|
||||
base = left;
|
||||
displacement = right;
|
||||
} else {
|
||||
// (B + B)
|
||||
base = left;
|
||||
index = right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -557,6 +609,7 @@ struct BaseWithIndexAndDisplacementMatcher {
|
||||
}
|
||||
base_ = base;
|
||||
displacement_ = displacement;
|
||||
displacement_mode_ = displacement_mode;
|
||||
index_ = index;
|
||||
scale_ = scale;
|
||||
matches_ = true;
|
||||
|
@ -70,6 +70,7 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
|
||||
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent,
|
||||
Node* base, Node* displacement,
|
||||
DisplacementMode displacement_mode,
|
||||
InstructionOperand inputs[],
|
||||
size_t* input_count) {
|
||||
AddressingMode mode = kMode_MRI;
|
||||
@ -79,7 +80,9 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
DCHECK(scale_exponent >= 0 && scale_exponent <= 3);
|
||||
inputs[(*input_count)++] = UseRegister(index);
|
||||
if (displacement != nullptr) {
|
||||
inputs[(*input_count)++] = UseImmediate(displacement);
|
||||
inputs[(*input_count)++] = displacement_mode
|
||||
? UseNegatedImmediate(displacement)
|
||||
: UseImmediate(displacement);
|
||||
static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I,
|
||||
kMode_MR4I, kMode_MR8I};
|
||||
mode = kMRnI_modes[scale_exponent];
|
||||
@ -92,7 +95,9 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
if (displacement == nullptr) {
|
||||
mode = kMode_MR;
|
||||
} else {
|
||||
inputs[(*input_count)++] = UseImmediate(displacement);
|
||||
inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement
|
||||
? UseNegatedImmediate(displacement)
|
||||
: UseImmediate(displacement);
|
||||
mode = kMode_MRI;
|
||||
}
|
||||
}
|
||||
@ -101,7 +106,9 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
DCHECK(scale_exponent >= 0 && scale_exponent <= 3);
|
||||
inputs[(*input_count)++] = UseRegister(index);
|
||||
if (displacement != nullptr) {
|
||||
inputs[(*input_count)++] = UseImmediate(displacement);
|
||||
inputs[(*input_count)++] = displacement_mode == kNegativeDisplacement
|
||||
? UseNegatedImmediate(displacement)
|
||||
: UseImmediate(displacement);
|
||||
static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I,
|
||||
kMode_M4I, kMode_M8I};
|
||||
mode = kMnI_modes[scale_exponent];
|
||||
@ -124,8 +131,9 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
BaseWithIndexAndDisplacement64Matcher m(operand, true);
|
||||
DCHECK(m.matches());
|
||||
if ((m.displacement() == nullptr || CanBeImmediate(m.displacement()))) {
|
||||
return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(),
|
||||
m.displacement(), inputs, input_count);
|
||||
return GenerateMemoryOperandInputs(
|
||||
m.index(), m.scale(), m.base(), m.displacement(),
|
||||
m.displacement_mode(), inputs, input_count);
|
||||
} else {
|
||||
inputs[(*input_count)++] = UseRegister(operand->InputAt(0));
|
||||
inputs[(*input_count)++] = UseRegister(operand->InputAt(1));
|
||||
@ -542,16 +550,16 @@ void VisitWord64Shift(InstructionSelector* selector, Node* node,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EmitLea(InstructionSelector* selector, InstructionCode opcode,
|
||||
Node* result, Node* index, int scale, Node* base,
|
||||
Node* displacement) {
|
||||
Node* displacement, DisplacementMode displacement_mode) {
|
||||
X64OperandGenerator g(selector);
|
||||
|
||||
InstructionOperand inputs[4];
|
||||
size_t input_count = 0;
|
||||
AddressingMode mode = g.GenerateMemoryOperandInputs(
|
||||
index, scale, base, displacement, inputs, &input_count);
|
||||
AddressingMode mode =
|
||||
g.GenerateMemoryOperandInputs(index, scale, base, displacement,
|
||||
displacement_mode, inputs, &input_count);
|
||||
|
||||
DCHECK_NE(0u, input_count);
|
||||
DCHECK_GE(arraysize(inputs), input_count);
|
||||
@ -572,7 +580,8 @@ void InstructionSelector::VisitWord32Shl(Node* node) {
|
||||
if (m.matches()) {
|
||||
Node* index = node->InputAt(0);
|
||||
Node* base = m.power_of_two_plus_one() ? index : nullptr;
|
||||
EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr);
|
||||
EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr,
|
||||
kPositiveDisplacement);
|
||||
return;
|
||||
}
|
||||
VisitWord32Shift(this, node, kX64Shl32);
|
||||
@ -756,7 +765,7 @@ void InstructionSelector::VisitInt32Add(Node* node) {
|
||||
if (m.matches() &&
|
||||
(m.displacement() == nullptr || g.CanBeImmediate(m.displacement()))) {
|
||||
EmitLea(this, kX64Lea32, node, m.index(), m.scale(), m.base(),
|
||||
m.displacement());
|
||||
m.displacement(), m.displacement_mode());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -881,7 +890,8 @@ void InstructionSelector::VisitInt32Mul(Node* node) {
|
||||
if (m.matches()) {
|
||||
Node* index = node->InputAt(0);
|
||||
Node* base = m.power_of_two_plus_one() ? index : nullptr;
|
||||
EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr);
|
||||
EmitLea(this, kX64Lea32, node, index, m.scale(), base, nullptr,
|
||||
kPositiveDisplacement);
|
||||
return;
|
||||
}
|
||||
VisitMul(this, node, kX64Imul32);
|
||||
|
@ -30,13 +30,15 @@ class NodeMatcherTest : public GraphTest {
|
||||
namespace {
|
||||
|
||||
template <class Matcher>
|
||||
void CheckBaseWithIndexAndDisplacement(Matcher* matcher, Node* index, int scale,
|
||||
Node* base, Node* displacement) {
|
||||
void CheckBaseWithIndexAndDisplacement(
|
||||
Matcher* matcher, Node* index, int scale, Node* base, Node* displacement,
|
||||
DisplacementMode displacement_mode = kPositiveDisplacement) {
|
||||
EXPECT_TRUE(matcher->matches());
|
||||
EXPECT_EQ(index, matcher->index());
|
||||
EXPECT_EQ(scale, matcher->scale());
|
||||
EXPECT_EQ(base, matcher->base());
|
||||
EXPECT_EQ(displacement, matcher->displacement());
|
||||
EXPECT_EQ(displacement_mode, matcher->displacement_mode());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -90,6 +92,9 @@ TEST_F(NodeMatcherTest, ScaledWithOffset32Matcher) {
|
||||
const Operator* a_op = machine()->Int32Add();
|
||||
USE(a_op);
|
||||
|
||||
const Operator* sub_op = machine()->Int32Sub();
|
||||
USE(sub_op);
|
||||
|
||||
const Operator* m_op = machine()->Int32Mul();
|
||||
Node* m1 = graph()->NewNode(m_op, p1, d1);
|
||||
Node* m2 = graph()->NewNode(m_op, p1, d2);
|
||||
@ -354,7 +359,25 @@ TEST_F(NodeMatcherTest, ScaledWithOffset32Matcher) {
|
||||
graph()->NewNode(a_op, s3, graph()->NewNode(a_op, b0, d15)));
|
||||
CheckBaseWithIndexAndDisplacement(&match43, p1, 3, b0, d15);
|
||||
|
||||
// Check that scales that require using the base address work dorrectly.
|
||||
// S3 + (B0 - D15) -> [p1, 2, b0, d15, true]
|
||||
s3 = graph()->NewNode(s_op, p1, d3);
|
||||
BaseWithIndexAndDisplacement32Matcher match44(
|
||||
graph()->NewNode(a_op, s3, graph()->NewNode(sub_op, b0, d15)));
|
||||
CheckBaseWithIndexAndDisplacement(&match44, p1, 3, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
|
||||
// B0 + (B1 - D15) -> [p1, 2, b0, d15, true]
|
||||
BaseWithIndexAndDisplacement32Matcher match45(
|
||||
graph()->NewNode(a_op, b0, graph()->NewNode(sub_op, b1, d15)));
|
||||
CheckBaseWithIndexAndDisplacement(&match45, b1, 0, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
|
||||
// (B0 - D15) + S3 -> [p1, 2, b0, d15, true]
|
||||
s3 = graph()->NewNode(s_op, p1, d3);
|
||||
BaseWithIndexAndDisplacement32Matcher match46(
|
||||
graph()->NewNode(a_op, graph()->NewNode(sub_op, b0, d15), s3));
|
||||
CheckBaseWithIndexAndDisplacement(&match46, p1, 3, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
}
|
||||
|
||||
|
||||
@ -409,6 +432,9 @@ TEST_F(NodeMatcherTest, ScaledWithOffset64Matcher) {
|
||||
const Operator* a_op = machine()->Int64Add();
|
||||
USE(a_op);
|
||||
|
||||
const Operator* sub_op = machine()->Int64Sub();
|
||||
USE(sub_op);
|
||||
|
||||
const Operator* m_op = machine()->Int64Mul();
|
||||
Node* m1 = graph()->NewNode(m_op, p1, d1);
|
||||
Node* m2 = graph()->NewNode(m_op, p1, d2);
|
||||
@ -726,8 +752,27 @@ TEST_F(NodeMatcherTest, ScaledWithOffset64Matcher) {
|
||||
BaseWithIndexAndDisplacement64Matcher match50(
|
||||
graph()->NewNode(a_op, m3, temp));
|
||||
CheckBaseWithIndexAndDisplacement(&match50, m3, 0, b0, d15);
|
||||
}
|
||||
|
||||
// S3 + (B0 - D15) -> [p1, 2, b0, d15, true]
|
||||
s3 = graph()->NewNode(s_op, p1, d3);
|
||||
BaseWithIndexAndDisplacement64Matcher match51(
|
||||
graph()->NewNode(a_op, s3, graph()->NewNode(sub_op, b0, d15)));
|
||||
CheckBaseWithIndexAndDisplacement(&match51, p1, 3, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
|
||||
// B0 + (B1 - D15) -> [p1, 2, b0, d15, true]
|
||||
BaseWithIndexAndDisplacement64Matcher match52(
|
||||
graph()->NewNode(a_op, b0, graph()->NewNode(sub_op, b1, d15)));
|
||||
CheckBaseWithIndexAndDisplacement(&match52, b1, 0, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
|
||||
// (B0 - D15) + S3 -> [p1, 2, b0, d15, true]
|
||||
s3 = graph()->NewNode(s_op, p1, d3);
|
||||
BaseWithIndexAndDisplacement64Matcher match53(
|
||||
graph()->NewNode(a_op, graph()->NewNode(sub_op, b0, d15), s3));
|
||||
CheckBaseWithIndexAndDisplacement(&match53, p1, 3, b0, d15,
|
||||
kNegativeDisplacement);
|
||||
}
|
||||
|
||||
TEST_F(NodeMatcherTest, BranchMatcher_match) {
|
||||
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
||||
|
Loading…
Reference in New Issue
Block a user