LCOV - code coverage report
Current view: top level - src/compiler - node-matchers.h (source / functions) Hit Total Coverage
Test: app.info Lines: 184 186 98.9 %
Date: 2017-10-20 Functions: 40 42 95.2 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_NODE_MATCHERS_H_
       6             : #define V8_COMPILER_NODE_MATCHERS_H_
       7             : 
       8             : #include <cmath>
       9             : 
      10             : // TODO(turbofan): Move ExternalReference out of assembler.h
      11             : #include "src/assembler.h"
      12             : #include "src/base/compiler-specific.h"
      13             : #include "src/compiler/node.h"
      14             : #include "src/compiler/operator.h"
      15             : #include "src/double.h"
      16             : #include "src/globals.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace compiler {
      21             : 
      22             : // A pattern matcher for nodes.
      23             : struct NodeMatcher {
      24    95272131 :   explicit NodeMatcher(Node* node) : node_(node) {}
      25             : 
      26    43922128 :   Node* node() const { return node_; }
      27    19834185 :   const Operator* op() const { return node()->op(); }
      28    88939130 :   IrOpcode::Value opcode() const { return node()->opcode(); }
      29             : 
      30             :   bool HasProperty(Operator::Property property) const {
      31             :     return op()->HasProperty(property);
      32             :   }
      33             :   Node* InputAt(int index) const { return node()->InputAt(index); }
      34             : 
      35       20679 :   bool Equals(const Node* node) const { return node_ == node; }
      36             : 
      37             :   bool IsComparison() const;
      38             : 
      39             : #define DEFINE_IS_OPCODE(Opcode) \
      40             :   bool Is##Opcode() const { return opcode() == IrOpcode::k##Opcode; }
      41             :   ALL_OP_LIST(DEFINE_IS_OPCODE)
      42             : #undef DEFINE_IS_OPCODE
      43             : 
      44             :  private:
      45             :   Node* node_;
      46             : };
      47             : 
      48             : 
      49             : // A pattern matcher for abitrary value constants.
      50             : template <typename T, IrOpcode::Value kOpcode>
      51             : struct ValueMatcher : public NodeMatcher {
      52             :   typedef T ValueType;
      53             : 
      54             :   explicit ValueMatcher(Node* node)
      55    38310642 :       : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) {
      56    27139102 :     if (has_value_) {
      57    10084148 :       value_ = OpParameter<T>(node);
      58             :     }
      59             :   }
      60             : 
      61             :   bool HasValue() const { return has_value_; }
      62             :   const T& Value() const {
      63             :     DCHECK(HasValue());
      64             :     return value_;
      65             :   }
      66             : 
      67             :  private:
      68             :   T value_;
      69             :   bool has_value_;
      70             : };
      71             : 
      72             : 
      73             : template <>
      74             : inline ValueMatcher<uint32_t, IrOpcode::kInt32Constant>::ValueMatcher(
      75             :     Node* node)
      76             :     : NodeMatcher(node),
      77             :       value_(),
      78     1819148 :       has_value_(opcode() == IrOpcode::kInt32Constant) {
      79     1028692 :   if (has_value_) {
      80      521675 :     value_ = static_cast<uint32_t>(OpParameter<int32_t>(node));
      81             :   }
      82             : }
      83             : 
      84             : 
      85             : template <>
      86             : inline ValueMatcher<int64_t, IrOpcode::kInt64Constant>::ValueMatcher(Node* node)
      87    41993264 :     : NodeMatcher(node), value_(), has_value_(false) {
      88    44518985 :   if (opcode() == IrOpcode::kInt32Constant) {
      89      635558 :     value_ = OpParameter<int32_t>(node);
      90      561069 :     has_value_ = true;
      91    43883427 :   } else if (opcode() == IrOpcode::kInt64Constant) {
      92    18511029 :     value_ = OpParameter<int64_t>(node);
      93    17546258 :     has_value_ = true;
      94             :   }
      95             : }
      96             : 
      97             : 
      98             : template <>
      99             : inline ValueMatcher<uint64_t, IrOpcode::kInt64Constant>::ValueMatcher(
     100             :     Node* node)
     101       63120 :     : NodeMatcher(node), value_(), has_value_(false) {
     102       89330 :   if (opcode() == IrOpcode::kInt32Constant) {
     103          58 :     value_ = static_cast<uint32_t>(OpParameter<int32_t>(node));
     104           6 :     has_value_ = true;
     105       89272 :   } else if (opcode() == IrOpcode::kInt64Constant) {
     106       62638 :     value_ = static_cast<uint64_t>(OpParameter<int64_t>(node));
     107       62638 :     has_value_ = true;
     108             :   }
     109             : }
     110             : 
     111             : 
     112             : // A pattern matcher for integer constants.
     113             : template <typename T, IrOpcode::Value kOpcode>
     114             : struct IntMatcher final : public ValueMatcher<T, kOpcode> {
     115             :   explicit IntMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {}
     116             : 
     117             :   bool Is(const T& value) const {
     118     8378287 :     return this->HasValue() && this->Value() == value;
     119             :   }
     120             :   bool IsInRange(const T& low, const T& high) const {
     121      342210 :     return this->HasValue() && low <= this->Value() && this->Value() <= high;
     122             :   }
     123             :   bool IsMultipleOf(T n) const {
     124       17674 :     return this->HasValue() && (this->Value() % n) == 0;
     125             :   }
     126             :   bool IsPowerOf2() const {
     127             :     return this->HasValue() && this->Value() > 0 &&
     128       11282 :            (this->Value() & (this->Value() - 1)) == 0;
     129             :   }
     130             :   bool IsNegativePowerOf2() const {
     131      465228 :     return this->HasValue() && this->Value() < 0 &&
     132      465228 :            (-this->Value() & (-this->Value() - 1)) == 0;
     133             :   }
     134        2438 :   bool IsNegative() const { return this->HasValue() && this->Value() < 0; }
     135             : };
     136             : 
     137             : typedef IntMatcher<int32_t, IrOpcode::kInt32Constant> Int32Matcher;
     138             : typedef IntMatcher<uint32_t, IrOpcode::kInt32Constant> Uint32Matcher;
     139             : typedef IntMatcher<int64_t, IrOpcode::kInt64Constant> Int64Matcher;
     140             : typedef IntMatcher<uint64_t, IrOpcode::kInt64Constant> Uint64Matcher;
     141             : #if V8_HOST_ARCH_32_BIT
     142             : typedef Int32Matcher IntPtrMatcher;
     143             : typedef Uint32Matcher UintPtrMatcher;
     144             : #else
     145             : typedef Int64Matcher IntPtrMatcher;
     146             : typedef Uint64Matcher UintPtrMatcher;
     147             : #endif
     148             : 
     149             : 
     150             : // A pattern matcher for floating point constants.
     151             : template <typename T, IrOpcode::Value kOpcode>
     152             : struct FloatMatcher final : public ValueMatcher<T, kOpcode> {
     153             :   explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {}
     154             : 
     155             :   bool Is(const T& value) const {
     156      449326 :     return this->HasValue() && this->Value() == value;
     157             :   }
     158             :   bool IsInRange(const T& low, const T& high) const {
     159        2279 :     return this->HasValue() && low <= this->Value() && this->Value() <= high;
     160             :   }
     161       45424 :   bool IsMinusZero() const {
     162       54011 :     return this->Is(0.0) && std::signbit(this->Value());
     163             :   }
     164             :   bool IsNegative() const { return this->HasValue() && this->Value() < 0.0; }
     165      522461 :   bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); }
     166          12 :   bool IsZero() const { return this->Is(0.0) && !std::signbit(this->Value()); }
     167             :   bool IsNormal() const {
     168       36707 :     return this->HasValue() && std::isnormal(this->Value());
     169             :   }
     170             :   bool IsInteger() const {
     171        7852 :     return this->HasValue() && std::nearbyint(this->Value()) == this->Value();
     172             :   }
     173       10104 :   bool IsPositiveOrNegativePowerOf2() const {
     174       10104 :     if (!this->HasValue() || (this->Value() == 0.0)) {
     175             :       return false;
     176             :     }
     177       10104 :     Double value = Double(this->Value());
     178       20208 :     return !value.IsInfinite() && base::bits::IsPowerOfTwo(value.Significand());
     179             :   }
     180             : };
     181             : 
     182             : typedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher;
     183             : typedef FloatMatcher<double, IrOpcode::kFloat64Constant> Float64Matcher;
     184             : typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
     185             : 
     186             : 
     187             : // A pattern matcher for heap object constants.
     188             : struct HeapObjectMatcher final
     189             :     : public ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant> {
     190             :   explicit HeapObjectMatcher(Node* node)
     191             :       : ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant>(node) {}
     192             : 
     193      188890 :   bool Is(Handle<HeapObject> const& value) const {
     194      247870 :     return this->HasValue() && this->Value().address() == value.address();
     195             :   }
     196             : };
     197             : 
     198             : 
     199             : // A pattern matcher for external reference constants.
     200             : struct ExternalReferenceMatcher final
     201             :     : public ValueMatcher<ExternalReference, IrOpcode::kExternalConstant> {
     202             :   explicit ExternalReferenceMatcher(Node* node)
     203             :       : ValueMatcher<ExternalReference, IrOpcode::kExternalConstant>(node) {}
     204             :   bool Is(const ExternalReference& value) const {
     205      666286 :     return this->HasValue() && this->Value() == value;
     206             :   }
     207             : };
     208             : 
     209             : 
     210             : // For shorter pattern matching code, this struct matches the inputs to
     211             : // machine-level load operations.
     212             : template <typename Object>
     213             : struct LoadMatcher : public NodeMatcher {
     214     4213408 :   explicit LoadMatcher(Node* node)
     215     4213408 :       : NodeMatcher(node), object_(InputAt(0)), index_(InputAt(1)) {}
     216             : 
     217             :   typedef Object ObjectMatcher;
     218             : 
     219             :   Object const& object() const { return object_; }
     220             :   IntPtrMatcher const& index() const { return index_; }
     221             : 
     222             :  private:
     223             :   Object const object_;
     224             :   IntPtrMatcher const index_;
     225             : };
     226             : 
     227             : 
     228             : // For shorter pattern matching code, this struct matches both the left and
     229             : // right hand sides of a binary operation and can put constants on the right
     230             : // if they appear on the left hand side of a commutative operation.
     231             : template <typename Left, typename Right>
     232             : struct BinopMatcher : public NodeMatcher {
     233    19834185 :   explicit BinopMatcher(Node* node)
     234             :       : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
     235    19834185 :     if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
     236    19834193 :   }
     237     7277971 :   BinopMatcher(Node* node, bool allow_input_swap)
     238             :       : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
     239     7277971 :     if (allow_input_swap) PutConstantOnRight();
     240     7277977 :   }
     241             : 
     242             :   typedef Left LeftMatcher;
     243             :   typedef Right RightMatcher;
     244             : 
     245             :   const Left& left() const { return left_; }
     246             :   const Right& right() const { return right_; }
     247             : 
     248     5327586 :   bool IsFoldable() const { return left().HasValue() && right().HasValue(); }
     249             :   bool LeftEqualsRight() const { return left().node() == right().node(); }
     250             : 
     251             :  protected:
     252      411564 :   void SwapInputs() {
     253             :     std::swap(left_, right_);
     254             :     // TODO(tebbi): This modification should notify the reducers using
     255             :     // BinopMatcher. Alternatively, all reducers (especially value numbering)
     256             :     // could ignore the ordering for commutative binops.
     257      411564 :     node()->ReplaceInput(0, left().node());
     258      411564 :     node()->ReplaceInput(1, right().node());
     259      411564 :   }
     260             : 
     261             :  private:
     262    17214894 :   void PutConstantOnRight() {
     263    17214894 :     if (left().HasValue() && !right().HasValue()) {
     264      184645 :       SwapInputs();
     265             :     }
     266    17214893 :   }
     267             : 
     268             :   Left left_;
     269             :   Right right_;
     270             : };
     271             : 
     272             : typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher;
     273             : typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher;
     274             : typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher;
     275             : typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher;
     276             : typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher;
     277             : typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher;
     278             : typedef BinopMatcher<Float32Matcher, Float32Matcher> Float32BinopMatcher;
     279             : typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
     280             : typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
     281             : typedef BinopMatcher<HeapObjectMatcher, HeapObjectMatcher>
     282             :     HeapObjectBinopMatcher;
     283             : 
     284             : template <class BinopMatcher, IrOpcode::Value kMulOpcode,
     285             :           IrOpcode::Value kShiftOpcode>
     286             : struct ScaleMatcher {
     287    19817844 :   explicit ScaleMatcher(Node* node, bool allow_power_of_two_plus_one = false)
     288    14543569 :       : scale_(-1), power_of_two_plus_one_(false) {
     289    23812854 :     if (node->InputCount() < 2) return;
     290     5274284 :     BinopMatcher m(node);
     291     5274275 :     if (node->opcode() == kShiftOpcode) {
     292      622333 :       if (m.right().HasValue()) {
     293             :         typename BinopMatcher::RightMatcher::ValueType value =
     294      617189 :             m.right().Value();
     295      617189 :         if (value >= 0 && value <= 3) {
     296      332100 :           scale_ = static_cast<int>(value);
     297             :         }
     298             :       }
     299     4651942 :     } else if (node->opcode() == kMulOpcode) {
     300      112632 :       if (m.right().HasValue()) {
     301             :         typename BinopMatcher::RightMatcher::ValueType value =
     302      110135 :             m.right().Value();
     303      110135 :         if (value == 1) {
     304        1747 :           scale_ = 0;
     305      108388 :         } else if (value == 2) {
     306        2785 :           scale_ = 1;
     307      105603 :         } else if (value == 4) {
     308         357 :           scale_ = 2;
     309      105246 :         } else if (value == 8) {
     310         327 :           scale_ = 3;
     311      104919 :         } else if (allow_power_of_two_plus_one) {
     312      104919 :           if (value == 3) {
     313       52599 :             scale_ = 1;
     314       52599 :             power_of_two_plus_one_ = true;
     315       52320 :           } else if (value == 5) {
     316        2745 :             scale_ = 2;
     317        2745 :             power_of_two_plus_one_ = true;
     318       49575 :           } else if (value == 9) {
     319         337 :             scale_ = 3;
     320         337 :             power_of_two_plus_one_ = true;
     321             :           }
     322             :         }
     323             :       }
     324             :     }
     325             :   }
     326             : 
     327             :   bool matches() const { return scale_ != -1; }
     328             :   int scale() const { return scale_; }
     329             :   bool power_of_two_plus_one() const { return power_of_two_plus_one_; }
     330             : 
     331             :  private:
     332             :   int scale_;
     333             :   bool power_of_two_plus_one_;
     334             : };
     335             : 
     336             : typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul,
     337             :                      IrOpcode::kWord32Shl> Int32ScaleMatcher;
     338             : typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul,
     339             :                      IrOpcode::kWord64Shl> Int64ScaleMatcher;
     340             : 
     341             : template <class BinopMatcher, IrOpcode::Value AddOpcode,
     342             :           IrOpcode::Value SubOpcode, IrOpcode::Value kMulOpcode,
     343             :           IrOpcode::Value kShiftOpcode>
     344             : struct AddMatcher : public BinopMatcher {
     345             :   static const IrOpcode::Value kAddOpcode = AddOpcode;
     346             :   static const IrOpcode::Value kSubOpcode = SubOpcode;
     347             :   typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher;
     348             : 
     349     6910783 :   AddMatcher(Node* node, bool allow_input_swap)
     350             :       : BinopMatcher(node, allow_input_swap),
     351             :         scale_(-1),
     352     6910783 :         power_of_two_plus_one_(false) {
     353     6910806 :     Initialize(node, allow_input_swap);
     354     6910774 :   }
     355      734360 :   explicit AddMatcher(Node* node)
     356             :       : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)),
     357             :         scale_(-1),
     358      367180 :         power_of_two_plus_one_(false) {
     359      367180 :     Initialize(node, node->op()->HasProperty(Operator::kCommutative));
     360      367180 :   }
     361             : 
     362             :   bool HasIndexInput() const { return scale_ != -1; }
     363             :   Node* IndexInput() const {
     364             :     DCHECK(HasIndexInput());
     365             :     return this->left().node()->InputAt(0);
     366             :   }
     367             :   int scale() const {
     368             :     DCHECK(HasIndexInput());
     369             :     return scale_;
     370             :   }
     371             :   bool power_of_two_plus_one() const { return power_of_two_plus_one_; }
     372             : 
     373             :  private:
     374     7277964 :   void Initialize(Node* node, bool allow_input_swap) {
     375     7277964 :     Matcher left_matcher(this->left().node(), true);
     376     7277958 :     if (left_matcher.matches()) {
     377      321892 :       scale_ = left_matcher.scale();
     378      321892 :       power_of_two_plus_one_ = left_matcher.power_of_two_plus_one();
     379      713063 :       return;
     380             :     }
     381             : 
     382     6956066 :     if (!allow_input_swap) {
     383             :       return;
     384             :     }
     385             : 
     386     6932774 :     Matcher right_matcher(this->right().node(), true);
     387     6932772 :     if (right_matcher.matches()) {
     388       45987 :       scale_ = right_matcher.scale();
     389       45987 :       power_of_two_plus_one_ = right_matcher.power_of_two_plus_one();
     390       45987 :       this->SwapInputs();
     391       45987 :       return;
     392             :     }
     393             : 
     394     7051717 :     if (this->right().opcode() == kAddOpcode &&
     395             :         this->left().opcode() != kAddOpcode) {
     396      164127 :       this->SwapInputs();
     397     6739806 :     } else if (this->right().opcode() == kSubOpcode &&
     398             :                this->left().opcode() != kSubOpcode) {
     399       16806 :       this->SwapInputs();
     400             :     }
     401             :   }
     402             : 
     403             :   int scale_;
     404             :   bool power_of_two_plus_one_;
     405             : };
     406             : 
     407             : typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Sub,
     408             :                    IrOpcode::kInt32Mul, IrOpcode::kWord32Shl>
     409             :     Int32AddMatcher;
     410             : typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Sub,
     411             :                    IrOpcode::kInt64Mul, IrOpcode::kWord64Shl>
     412             :     Int64AddMatcher;
     413             : 
     414             : enum DisplacementMode { kPositiveDisplacement, kNegativeDisplacement };
     415             : 
     416             : enum class AddressOption : uint8_t {
     417             :   kAllowNone = 0u,
     418             :   kAllowInputSwap = 1u << 0,
     419             :   kAllowScale = 1u << 1,
     420             :   kAllowAll = kAllowInputSwap | kAllowScale
     421             : };
     422             : 
     423             : typedef base::Flags<AddressOption, uint8_t> AddressOptions;
     424             : DEFINE_OPERATORS_FOR_FLAGS(AddressOptions);
     425             : 
     426             : template <class AddMatcher>
     427             : struct BaseWithIndexAndDisplacementMatcher {
     428             :   BaseWithIndexAndDisplacementMatcher(Node* node, AddressOptions options)
     429             :       : matches_(false),
     430             :         index_(nullptr),
     431             :         scale_(0),
     432             :         base_(nullptr),
     433             :         displacement_(nullptr),
     434     5714478 :         displacement_mode_(kPositiveDisplacement) {
     435     5714478 :     Initialize(node, options);
     436             :   }
     437             : 
     438     2392640 :   explicit BaseWithIndexAndDisplacementMatcher(Node* node)
     439             :       : matches_(false),
     440             :         index_(nullptr),
     441             :         scale_(0),
     442             :         base_(nullptr),
     443             :         displacement_(nullptr),
     444     1196320 :         displacement_mode_(kPositiveDisplacement) {
     445     1196320 :     Initialize(node, AddressOption::kAllowScale |
     446             :                          (node->op()->HasProperty(Operator::kCommutative)
     447             :                               ? AddressOption::kAllowInputSwap
     448     1196320 :                               : AddressOption::kAllowNone));
     449     1196327 :   }
     450             : 
     451             :   bool matches() const { return matches_; }
     452             :   Node* index() const { return index_; }
     453             :   int scale() const { return scale_; }
     454             :   Node* base() const { return base_; }
     455             :   Node* displacement() const { return displacement_; }
     456             :   DisplacementMode displacement_mode() const { return displacement_mode_; }
     457             : 
     458             :  private:
     459             :   bool matches_;
     460             :   Node* index_;
     461             :   int scale_;
     462             :   Node* base_;
     463             :   Node* displacement_;
     464             :   DisplacementMode displacement_mode_;
     465             : 
     466     6910787 :   void Initialize(Node* node, AddressOptions options) {
     467             :     // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of
     468             :     // displacements and scale factors that are used as inputs, so instead of
     469             :     // enumerating all possible patterns by brute force, checking for node
     470             :     // clusters using the following templates in the following order suffices to
     471             :     // find all of the interesting cases (S = index * scale, B = base input, D =
     472             :     // displacement input):
     473             :     // (S + (B + D))
     474             :     // (S + (B + B))
     475             :     // (S + D)
     476             :     // (S + B)
     477             :     // ((S + D) + B)
     478             :     // ((S + B) + D)
     479             :     // ((B + D) + B)
     480             :     // ((B + B) + D)
     481             :     // (B + D)
     482             :     // (B + B)
     483     6910789 :     if (node->InputCount() < 2) return;
     484     6910785 :     AddMatcher m(node, options & AddressOption::kAllowInputSwap);
     485    13461478 :     Node* left = m.left().node();
     486      354497 :     Node* right = m.right().node();
     487     6613027 :     Node* displacement = nullptr;
     488             :     Node* base = nullptr;
     489             :     Node* index = nullptr;
     490             :     Node* scale_expression = nullptr;
     491             :     bool power_of_two_plus_one = false;
     492             :     DisplacementMode displacement_mode = kPositiveDisplacement;
     493             :     int scale = 0;
     494     6910791 :     if (m.HasIndexInput() && left->OwnedByAddressingOperand()) {
     495             :       index = m.IndexInput();
     496      177253 :       scale = m.scale();
     497             :       scale_expression = left;
     498      177253 :       power_of_two_plus_one = m.power_of_two_plus_one();
     499             :       bool match_found = false;
     500      177265 :       if (right->opcode() == AddMatcher::kSubOpcode &&
     501          12 :           right->OwnedByAddressingOperand()) {
     502           8 :         AddMatcher right_matcher(right);
     503           8 :         if (right_matcher.right().HasValue()) {
     504             :           // (S + (B - D))
     505             :           base = right_matcher.left().node();
     506             :           displacement = right_matcher.right().node();
     507             :           displacement_mode = kNegativeDisplacement;
     508             :           match_found = true;
     509             :         }
     510             :       }
     511      177253 :       if (!match_found) {
     512      181650 :         if (right->opcode() == AddMatcher::kAddOpcode &&
     513        4406 :             right->OwnedByAddressingOperand()) {
     514        4381 :           AddMatcher right_matcher(right);
     515        4381 :           if (right_matcher.right().HasValue()) {
     516             :             // (S + (B + D))
     517             :             base = right_matcher.left().node();
     518             :             displacement = right_matcher.right().node();
     519             :           } else {
     520             :             // (S + (B + B))
     521             :             base = right;
     522             :           }
     523      172863 :         } else if (m.right().HasValue()) {
     524             :           // (S + D)
     525             :           displacement = right;
     526             :         } else {
     527             :           // (S + B)
     528             :           base = right;
     529             :         }
     530             :       }
     531             :     } else {
     532             :       bool match_found = false;
     533     6772410 :       if (left->opcode() == AddMatcher::kSubOpcode &&
     534       38872 :           left->OwnedByAddressingOperand()) {
     535       20691 :         AddMatcher left_matcher(left);
     536        1748 :         Node* left_left = left_matcher.left().node();
     537             :         Node* left_right = left_matcher.right().node();
     538       20691 :         if (left_matcher.right().HasValue()) {
     539       17870 :           if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
     540             :             // ((S - D) + B)
     541             :             index = left_matcher.IndexInput();
     542             :             scale = left_matcher.scale();
     543             :             scale_expression = left_left;
     544           0 :             power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     545             :             displacement = left_right;
     546             :             displacement_mode = kNegativeDisplacement;
     547             :             base = right;
     548             :           } else {
     549             :             // ((B - D) + B)
     550             :             index = left_left;
     551             :             displacement = left_right;
     552             :             displacement_mode = kNegativeDisplacement;
     553             :             base = right;
     554             :           }
     555             :           match_found = true;
     556             :         }
     557             :       }
     558     6733538 :       if (!match_found) {
     559     7197573 :         if (left->opcode() == AddMatcher::kAddOpcode &&
     560      480180 :             left->OwnedByAddressingOperand()) {
     561      342100 :           AddMatcher left_matcher(left);
     562      173299 :           Node* left_left = left_matcher.left().node();
     563             :           Node* left_right = left_matcher.right().node();
     564      515399 :           if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
     565      172889 :             if (left_matcher.right().HasValue()) {
     566             :               // ((S + D) + B)
     567             :               index = left_matcher.IndexInput();
     568             :               scale = left_matcher.scale();
     569             :               scale_expression = left_left;
     570      171563 :               power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     571             :               displacement = left_right;
     572             :               base = right;
     573        1326 :             } else if (m.right().HasValue()) {
     574         890 :               if (left->OwnedBy(node)) {
     575             :                 // ((S + B) + D)
     576             :                 index = left_matcher.IndexInput();
     577             :                 scale = left_matcher.scale();
     578             :                 scale_expression = left_left;
     579         844 :                 power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     580             :                 base = left_right;
     581             :                 displacement = right;
     582             :               } else {
     583             :                 // (B + D)
     584             :                 base = left;
     585             :                 displacement = right;
     586             :               }
     587             :             } else {
     588             :               // (B + B)
     589             :               index = left;
     590             :               base = right;
     591             :             }
     592             :           } else {
     593      169211 :             if (left_matcher.right().HasValue()) {
     594             :               // ((B + D) + B)
     595             :               index = left_left;
     596             :               displacement = left_right;
     597             :               base = right;
     598       22307 :             } else if (m.right().HasValue()) {
     599        9657 :               if (left->OwnedBy(node)) {
     600             :                 // ((B + B) + D)
     601             :                 index = left_left;
     602             :                 base = left_right;
     603             :                 displacement = right;
     604             :               } else {
     605             :                 // (B + D)
     606             :                 base = left;
     607             :                 displacement = right;
     608             :               }
     609             :             } else {
     610             :               // (B + B)
     611             :               index = left;
     612             :               base = right;
     613             :             }
     614             :           }
     615             :         } else {
     616     6375293 :           if (m.right().HasValue()) {
     617             :             // (B + D)
     618             :             base = left;
     619             :             displacement = right;
     620             :           } else {
     621             :             // (B + B)
     622             :             base = left;
     623             :             index = right;
     624             :           }
     625             :         }
     626             :       }
     627             :     }
     628             :     int64_t value = 0;
     629     6910791 :     if (displacement != nullptr) {
     630     6613027 :       switch (displacement->opcode()) {
     631             :         case IrOpcode::kInt32Constant: {
     632      523489 :           value = OpParameter<int32_t>(displacement);
     633      523489 :           break;
     634             :         }
     635             :         case IrOpcode::kInt64Constant: {
     636     6089538 :           value = OpParameter<int64_t>(displacement);
     637     6089538 :           break;
     638             :         }
     639             :         default:
     640           0 :           UNREACHABLE();
     641             :           break;
     642             :       }
     643     6613027 :       if (value == 0) {
     644             :         displacement = nullptr;
     645             :       }
     646             :     }
     647     6910791 :     if (power_of_two_plus_one) {
     648       44930 :       if (base != nullptr) {
     649             :         // If the scale requires explicitly using the index as the base, but a
     650             :         // base is already part of the match, then the (1 << N + 1) scale factor
     651             :         // can't be folded into the match and the entire index * scale
     652             :         // calculation must be computed separately.
     653             :         index = scale_expression;
     654             :         scale = 0;
     655             :       } else {
     656             :         base = index;
     657             :       }
     658             :     }
     659     6910791 :     if (!(options & AddressOption::kAllowScale) && scale != 0) {
     660             :       index = scale_expression;
     661             :       scale = 0;
     662             :     }
     663     6910791 :     base_ = base;
     664     6910791 :     displacement_ = displacement;
     665     6910791 :     displacement_mode_ = displacement_mode;
     666     6910791 :     index_ = index;
     667     6910791 :     scale_ = scale;
     668     6910791 :     matches_ = true;
     669             :   }
     670             : };
     671             : 
     672             : typedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher>
     673             :     BaseWithIndexAndDisplacement32Matcher;
     674             : typedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher>
     675             :     BaseWithIndexAndDisplacement64Matcher;
     676             : 
     677             : struct V8_EXPORT_PRIVATE BranchMatcher : public NON_EXPORTED_BASE(NodeMatcher) {
     678             :   explicit BranchMatcher(Node* branch);
     679             : 
     680          15 :   bool Matched() const { return if_true_ && if_false_; }
     681             : 
     682             :   Node* Branch() const { return node(); }
     683             :   Node* IfTrue() const { return if_true_; }
     684             :   Node* IfFalse() const { return if_false_; }
     685             : 
     686             :  private:
     687             :   Node* if_true_;
     688             :   Node* if_false_;
     689             : };
     690             : 
     691             : struct V8_EXPORT_PRIVATE DiamondMatcher
     692             :     : public NON_EXPORTED_BASE(NodeMatcher) {
     693             :   explicit DiamondMatcher(Node* merge);
     694             : 
     695           4 :   bool Matched() const { return branch_; }
     696             :   bool IfProjectionsAreOwned() const {
     697             :     return if_true_->OwnedBy(node()) && if_false_->OwnedBy(node());
     698             :   }
     699             : 
     700             :   Node* Branch() const { return branch_; }
     701             :   Node* IfTrue() const { return if_true_; }
     702             :   Node* IfFalse() const { return if_false_; }
     703             :   Node* Merge() const { return node(); }
     704             : 
     705             :   Node* TrueInputOf(Node* phi) const {
     706             :     DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     707             :     DCHECK_EQ(3, phi->InputCount());
     708             :     DCHECK_EQ(Merge(), phi->InputAt(2));
     709             :     return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 0 : 1);
     710             :   }
     711             : 
     712             :   Node* FalseInputOf(Node* phi) const {
     713             :     DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     714             :     DCHECK_EQ(3, phi->InputCount());
     715             :     DCHECK_EQ(Merge(), phi->InputAt(2));
     716             :     return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 1 : 0);
     717             :   }
     718             : 
     719             :  private:
     720             :   Node* branch_;
     721             :   Node* if_true_;
     722             :   Node* if_false_;
     723             : };
     724             : 
     725             : }  // namespace compiler
     726             : }  // namespace internal
     727             : }  // namespace v8
     728             : 
     729             : #endif  // V8_COMPILER_NODE_MATCHERS_H_

Generated by: LCOV version 1.10