Chromium Code Reviews| Index: src/compiler/node-matchers.h |
| diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h |
| index a55e7bf0a22b529ac36304b3458ae426ece9eead..514c53dc505b40b2f19aa0c6302e973fa2c6c0cf 100644 |
| --- a/src/compiler/node-matchers.h |
| +++ b/src/compiler/node-matchers.h |
| @@ -116,7 +116,7 @@ struct HeapObjectMatcher FINAL |
| // right hand sides of a binary operation and can put constants on the right |
| // if they appear on the left hand side of a commutative operation. |
| template <typename Left, typename Right> |
| -struct BinopMatcher FINAL : public NodeMatcher { |
| +struct BinopMatcher : public NodeMatcher { |
| explicit BinopMatcher(Node* node) |
| : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { |
| if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); |
| @@ -128,12 +128,17 @@ struct BinopMatcher FINAL : public NodeMatcher { |
| bool IsFoldable() const { return left().HasValue() && right().HasValue(); } |
| bool LeftEqualsRight() const { return left().node() == right().node(); } |
| + protected: |
| + void SwapInputs() { |
| + std::swap(left_, right_); |
| + node()->ReplaceInput(0, left().node()); |
| + node()->ReplaceInput(1, right().node()); |
| + } |
| + |
| private: |
| void PutConstantOnRight() { |
| if (left().HasValue() && !right().HasValue()) { |
| - std::swap(left_, right_); |
| - node()->ReplaceInput(0, left().node()); |
| - node()->ReplaceInput(1, right().node()); |
| + SwapInputs(); |
| } |
| } |
| @@ -150,6 +155,184 @@ typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; |
| typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; |
| typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; |
| +struct Int32AddMatcher : public Int32BinopMatcher { |
| + explicit Int32AddMatcher(Node* node) |
| + : Int32BinopMatcher(node), has_scaled_input_(false), scale_factor_(-1) { |
| + PutScaledInputOnLeft(); |
| + if (HasScaledInput()) { |
| + Int32BinopMatcher m(left().node()); |
| + if (m.opcode() == IrOpcode::kWord32Shl) { |
| + scale_factor_ = 1 << m.right().Value(); |
| + } else { |
| + DCHECK(m.opcode() == IrOpcode::kInt32Mul); |
| + scale_factor_ = m.right().Value(); |
| + } |
| + } |
| + } |
| + |
| + bool HasScaledInput() const { return has_scaled_input_; } |
| + Node* ScaledInput() const { |
| + DCHECK(HasScaledInput()); |
| + return left().node()->InputAt(0); |
| + } |
| + int ScaleFactor() const { |
| + DCHECK(HasScaledInput()); |
| + return scale_factor_; |
| + } |
| + |
| + private: |
| + bool IsScaledInput(Node* node) const { |
|
titzer
2014/11/06 11:47:06
You could also have this method return the scaled
danno
2014/11/06 23:34:07
Done.
|
| + if (node->opcode() == IrOpcode::kWord32Shl) { |
| + Int32BinopMatcher m(node->InputAt(1)); |
| + if (m.right().HasValue()) { |
| + int32_t value = m.right().Value(); |
| + return (value == 0) || (value == 1) || (value == 2) || (value == 3); |
| + } |
| + } else if (node->opcode() == IrOpcode::kInt32Mul) { |
| + Int32BinopMatcher m(node->InputAt(1)); |
| + if (m.right().HasValue()) { |
| + int32_t value = m.right().Value(); |
| + return (value == 1) || (value == 2) || (value == 4) || (value == 8); |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + void PutScaledInputOnLeft() { |
| + if (IsScaledInput(right().node()) && !IsScaledInput(left().node())) { |
| + SwapInputs(); |
| + } |
| + |
| + if (IsScaledInput(left().node())) { |
| + has_scaled_input_ = true; |
| + } else { |
| + if (right().opcode() == IrOpcode::kInt32Add && |
| + left().opcode() != IrOpcode::kInt32Add) { |
| + SwapInputs(); |
| + } |
| + } |
| + } |
| + |
| + bool has_scaled_input_; |
| + int scale_factor_; |
| +}; |
| + |
| +struct ScaledWithOffsetMatcher { |
| + explicit ScaledWithOffsetMatcher(Node* node) |
| + : matches_(false), |
| + scaled_(NULL), |
| + scale_factor_(1), |
| + offset_(NULL), |
| + constant_(NULL) { |
| + if (node->opcode() != IrOpcode::kInt32Add) return; |
| + |
| + // The Int32AddMatcher canonicalizes the order of constants and scale |
| + // factors that are used as inputs, so instead of enumerating all possible |
| + // patterns by brute force, checking for node clusters using the following |
| + // templates in the following order suffices to find all of the interesting |
| + // cases (S = scaled input, O = offset input, C = constant input): |
| + // (S + (O + C)) |
| + // (S + (O + O)) |
| + // (S + C) |
| + // (S + O) |
| + // ((S + C) + O) |
| + // ((S + O) + C) |
| + // ((O + C) + O) |
| + // ((O + O) + C) |
| + // (O + C) |
| + // (O + O) |
| + Int32AddMatcher base_matcher(node); |
| + Node* left = base_matcher.left().node(); |
| + Node* right = base_matcher.right().node(); |
| + if (base_matcher.HasScaledInput() && left->OwnedBy(node)) { |
| + scaled_ = base_matcher.ScaledInput(); |
| + scale_factor_ = base_matcher.ScaleFactor(); |
| + if (right->opcode() == IrOpcode::kInt32Add && right->OwnedBy(node)) { |
| + Int32AddMatcher right_matcher(right); |
| + if (right_matcher.right().HasValue()) { |
| + // (S + (O + C)) |
| + offset_ = right_matcher.left().node(); |
| + constant_ = right_matcher.right().node(); |
| + } else { |
| + // (S + (O + O)) |
| + offset_ = right; |
| + } |
| + } else if (base_matcher.right().HasValue()) { |
| + // (S + C) |
| + constant_ = right; |
| + } else { |
| + // (S + O) |
| + offset_ = right; |
| + } |
| + } else { |
| + if (left->opcode() == IrOpcode::kInt32Add && left->OwnedBy(node)) { |
| + Int32AddMatcher left_matcher(left); |
| + Node* left_left = left_matcher.left().node(); |
| + Node* left_right = left_matcher.right().node(); |
| + if (left_matcher.HasScaledInput() && left_left->OwnedBy(left)) { |
| + scaled_ = left_matcher.ScaledInput(); |
| + scale_factor_ = left_matcher.ScaleFactor(); |
| + if (left_matcher.right().HasValue()) { |
| + // ((S + C) + O) |
| + constant_ = left_right; |
| + offset_ = right; |
| + } else if (base_matcher.right().HasValue()) { |
| + // ((S + O) + C) |
| + offset_ = left_right; |
| + constant_ = right; |
| + } else { |
| + // (O + O) |
| + scaled_ = left; |
| + offset_ = right; |
| + } |
| + } else { |
| + if (left_matcher.right().HasValue()) { |
| + // ((O + C) + O) |
| + scaled_ = left_left; |
| + constant_ = left_right; |
| + offset_ = right; |
| + } else if (base_matcher.right().HasValue()) { |
| + // ((O + O) + C) |
| + scaled_ = left_left; |
| + offset_ = left_right; |
| + constant_ = right; |
| + } else { |
| + // (O + O) |
| + scaled_ = left; |
| + offset_ = right; |
| + } |
| + } |
| + } else { |
| + if (base_matcher.right().HasValue()) { |
| + // (O + C) |
| + offset_ = left; |
| + constant_ = right; |
| + } else { |
| + // (O + O) |
| + offset_ = left; |
| + scaled_ = right; |
| + } |
| + } |
| + } |
| + matches_ = true; |
| + } |
| + |
| + bool Matches() const { return matches_; } |
|
titzer
2014/11/06 11:47:06
Lower case for simple getters.
danno
2014/11/06 23:34:07
Done.
|
| + Node* Scaled() const { return scaled_; } |
| + int ScaleFactor() const { return scale_factor_; } |
| + Node* Offset() const { return offset_; } |
| + Node* Constant() const { return constant_; } |
| + |
| + private: |
| + bool matches_; |
| + |
| + protected: |
| + Node* scaled_; |
| + int scale_factor_; |
| + Node* offset_; |
| + Node* constant_; |
| +}; |
| + |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |