Index: src/compiler/node-matchers.h |
diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h |
index d6d0615150dcb0dec114a3adb9c8e643c23328c8..f77e7b073c6087b3db1ca9b6063ff3d507461de6 100644 |
--- a/src/compiler/node-matchers.h |
+++ b/src/compiler/node-matchers.h |
@@ -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,83 +456,124 @@ 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; |
+ displacement_mode = kNegativeDisplacement; |
base = right; |
- } else if (m.right().HasValue()) { |
- // ((B + B) + D) |
- index = left_left; |
- base = left_right; |
+ } |
+ match_found = true; |
+ } |
+ } |
+ 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 { |
+ if (m.right().HasValue()) { |
+ // (B + D) |
+ base = left; |
displacement = right; |
} else { |
// (B + B) |
- index = left; |
- base = right; |
+ base = left; |
+ index = right; |
} |
} |
- } else { |
- if (m.right().HasValue()) { |
- // (B + D) |
- base = left; |
- displacement = right; |
- } else { |
- // (B + B) |
- base = left; |
- index = right; |
- } |
} |
} |
int64_t value = 0; |
@@ -557,6 +609,7 @@ struct BaseWithIndexAndDisplacementMatcher { |
} |
base_ = base; |
displacement_ = displacement; |
+ displacement_mode_ = displacement_mode; |
index_ = index; |
scale_ = scale; |
matches_ = true; |