LCOV - code coverage report
Current view: top level - src/compiler - node-matchers.h (source / functions) Hit Total Coverage
Test: app.info Lines: 180 184 97.8 %
Date: 2017-04-26 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    93693956 :   explicit NodeMatcher(Node* node) : node_(node) {}
      25             : 
      26    43312960 :   Node* node() const { return node_; }
      27    19470244 :   const Operator* op() const { return node()->op(); }
      28    87039301 :   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        2665 :   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    38188176 :       : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) {
      56    27040962 :     if (has_value_) {
      57    10625905 :       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     1731735 :       has_value_(opcode() == IrOpcode::kInt32Constant) {
      79      981823 :   if (has_value_) {
      80      612917 :     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    40696980 :     : NodeMatcher(node), value_(), has_value_(false) {
      88    43188364 :   if (opcode() == IrOpcode::kInt32Constant) {
      89      411705 :     value_ = OpParameter<int32_t>(node);
      90      409636 :     has_value_ = true;
      91    42776659 :   } else if (opcode() == IrOpcode::kInt64Constant) {
      92    18760304 :     value_ = OpParameter<int64_t>(node);
      93    17766662 :     has_value_ = true;
      94             :   }
      95             : }
      96             : 
      97             : 
      98             : template <>
      99             : inline ValueMatcher<uint64_t, IrOpcode::kInt64Constant>::ValueMatcher(
     100             :     Node* node)
     101       70486 :     : NodeMatcher(node), value_(), has_value_(false) {
     102       70486 :   if (opcode() == IrOpcode::kInt32Constant) {
     103           7 :     value_ = static_cast<uint32_t>(OpParameter<int32_t>(node));
     104           7 :     has_value_ = true;
     105       70479 :   } else if (opcode() == IrOpcode::kInt64Constant) {
     106       69758 :     value_ = static_cast<uint64_t>(OpParameter<int64_t>(node));
     107       69758 :     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     8161260 :     return this->HasValue() && this->Value() == value;
     119             :   }
     120             :   bool IsInRange(const T& low, const T& high) const {
     121      368168 :     return this->HasValue() && low <= this->Value() && this->Value() <= high;
     122             :   }
     123             :   bool IsMultipleOf(T n) const {
     124       18596 :     return this->HasValue() && (this->Value() % n) == 0;
     125             :   }
     126             :   bool IsPowerOf2() const {
     127             :     return this->HasValue() && this->Value() > 0 &&
     128       14692 :            (this->Value() & (this->Value() - 1)) == 0;
     129             :   }
     130             :   bool IsNegativePowerOf2() const {
     131      497274 :     return this->HasValue() && this->Value() < 0 &&
     132      497274 :            (-this->Value() & (-this->Value() - 1)) == 0;
     133             :   }
     134        2112 :   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      494468 :     return this->HasValue() && this->Value() == value;
     157             :   }
     158             :   bool IsInRange(const T& low, const T& high) const {
     159          58 :     return this->HasValue() && low <= this->Value() && this->Value() <= high;
     160             :   }
     161       53153 :   bool IsMinusZero() const {
     162       62729 :     return this->Is(0.0) && std::signbit(this->Value());
     163             :   }
     164             :   bool IsNegative() const { return this->HasValue() && this->Value() < 0.0; }
     165      570780 :   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       42507 :     return this->HasValue() && std::isnormal(this->Value());
     169             :   }
     170             :   bool IsInteger() const {
     171         133 :     return this->HasValue() && std::nearbyint(this->Value()) == this->Value();
     172             :   }
     173       12659 :   bool IsPositiveOrNegativePowerOf2() const {
     174       12659 :     if (!this->HasValue() || (this->Value() == 0.0)) {
     175             :       return false;
     176             :     }
     177       12659 :     Double value = Double(this->Value());
     178             :     return !value.IsInfinite() &&
     179       25318 :            base::bits::IsPowerOfTwo64(value.Significand());
     180             :   }
     181             : };
     182             : 
     183             : typedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher;
     184             : typedef FloatMatcher<double, IrOpcode::kFloat64Constant> Float64Matcher;
     185             : typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
     186             : 
     187             : 
     188             : // A pattern matcher for heap object constants.
     189             : struct HeapObjectMatcher final
     190             :     : public ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant> {
     191             :   explicit HeapObjectMatcher(Node* node)
     192             :       : ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant>(node) {}
     193             : 
     194      205706 :   bool Is(Handle<HeapObject> const& value) const {
     195      279339 :     return this->HasValue() && this->Value().address() == value.address();
     196             :   }
     197             : };
     198             : 
     199             : 
     200             : // A pattern matcher for external reference constants.
     201             : struct ExternalReferenceMatcher final
     202             :     : public ValueMatcher<ExternalReference, IrOpcode::kExternalConstant> {
     203             :   explicit ExternalReferenceMatcher(Node* node)
     204             :       : ValueMatcher<ExternalReference, IrOpcode::kExternalConstant>(node) {}
     205             :   bool Is(const ExternalReference& value) const {
     206      523250 :     return this->HasValue() && this->Value() == value;
     207             :   }
     208             : };
     209             : 
     210             : 
     211             : // For shorter pattern matching code, this struct matches the inputs to
     212             : // machine-level load operations.
     213             : template <typename Object>
     214             : struct LoadMatcher : public NodeMatcher {
     215     4605010 :   explicit LoadMatcher(Node* node)
     216     4605010 :       : NodeMatcher(node), object_(InputAt(0)), index_(InputAt(1)) {}
     217             : 
     218             :   typedef Object ObjectMatcher;
     219             : 
     220             :   Object const& object() const { return object_; }
     221             :   IntPtrMatcher const& index() const { return index_; }
     222             : 
     223             :  private:
     224             :   Object const object_;
     225             :   IntPtrMatcher const index_;
     226             : };
     227             : 
     228             : 
     229             : // For shorter pattern matching code, this struct matches both the left and
     230             : // right hand sides of a binary operation and can put constants on the right
     231             : // if they appear on the left hand side of a commutative operation.
     232             : template <typename Left, typename Right>
     233             : struct BinopMatcher : public NodeMatcher {
     234    19470244 :   explicit BinopMatcher(Node* node)
     235             :       : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
     236    19470244 :     if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
     237    19470240 :   }
     238     6791069 :   BinopMatcher(Node* node, bool allow_input_swap)
     239             :       : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
     240     6791069 :     if (allow_input_swap) PutConstantOnRight();
     241     6791066 :   }
     242             : 
     243             :   typedef Left LeftMatcher;
     244             :   typedef Right RightMatcher;
     245             : 
     246             :   const Left& left() const { return left_; }
     247             :   const Right& right() const { return right_; }
     248             : 
     249     6031619 :   bool IsFoldable() const { return left().HasValue() && right().HasValue(); }
     250             :   bool LeftEqualsRight() const { return left().node() == right().node(); }
     251             : 
     252             :  protected:
     253      795750 :   void SwapInputs() {
     254             :     std::swap(left_, right_);
     255             :     // TODO(tebbi): This modification should notify the reducers using
     256             :     // BinopMatcher. Alternatively, all reducers (especially value numbering)
     257             :     // could ignore the ordering for commutative binops.
     258      795750 :     node()->ReplaceInput(0, left().node());
     259      795750 :     node()->ReplaceInput(1, right().node());
     260      795750 :   }
     261             : 
     262             :  private:
     263    17130384 :   void PutConstantOnRight() {
     264    17130384 :     if (left().HasValue() && !right().HasValue()) {
     265      398625 :       SwapInputs();
     266             :     }
     267    17130384 :   }
     268             : 
     269             :   Left left_;
     270             :   Right right_;
     271             : };
     272             : 
     273             : typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher;
     274             : typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher;
     275             : typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher;
     276             : typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher;
     277             : typedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher;
     278             : typedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher;
     279             : typedef BinopMatcher<Float32Matcher, Float32Matcher> Float32BinopMatcher;
     280             : typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
     281             : typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
     282             : typedef BinopMatcher<HeapObjectMatcher, HeapObjectMatcher>
     283             :     HeapObjectBinopMatcher;
     284             : 
     285             : template <class BinopMatcher, IrOpcode::Value kMulOpcode,
     286             :           IrOpcode::Value kShiftOpcode>
     287             : struct ScaleMatcher {
     288    18220068 :   explicit ScaleMatcher(Node* node, bool allow_power_of_two_plus_one = false)
     289    13584785 :       : scale_(-1), power_of_two_plus_one_(false) {
     290    22534295 :     if (node->InputCount() < 2) return;
     291     4635275 :     BinopMatcher m(node);
     292     4635283 :     if (node->opcode() == kShiftOpcode) {
     293      624418 :       if (m.right().HasValue()) {
     294             :         typename BinopMatcher::RightMatcher::ValueType value =
     295      619247 :             m.right().Value();
     296      619247 :         if (value >= 0 && value <= 3) {
     297      332550 :           scale_ = static_cast<int>(value);
     298             :         }
     299             :       }
     300     4010865 :     } else if (node->opcode() == kMulOpcode) {
     301      109524 :       if (m.right().HasValue()) {
     302             :         typename BinopMatcher::RightMatcher::ValueType value =
     303      107403 :             m.right().Value();
     304      107403 :         if (value == 1) {
     305        1998 :           scale_ = 0;
     306      105405 :         } else if (value == 2) {
     307        6399 :           scale_ = 1;
     308       99006 :         } else if (value == 4) {
     309         337 :           scale_ = 2;
     310       98669 :         } else if (value == 8) {
     311        6424 :           scale_ = 3;
     312       92245 :         } else if (allow_power_of_two_plus_one) {
     313       92245 :           if (value == 3) {
     314       37320 :             scale_ = 1;
     315       37320 :             power_of_two_plus_one_ = true;
     316       54925 :           } else if (value == 5) {
     317        2080 :             scale_ = 2;
     318        2080 :             power_of_two_plus_one_ = true;
     319       52845 :           } else if (value == 9) {
     320         390 :             scale_ = 3;
     321         390 :             power_of_two_plus_one_ = true;
     322             :           }
     323             :         }
     324             :       }
     325             :     }
     326             :   }
     327             : 
     328             :   bool matches() const { return scale_ != -1; }
     329             :   int scale() const { return scale_; }
     330             :   bool power_of_two_plus_one() const { return power_of_two_plus_one_; }
     331             : 
     332             :  private:
     333             :   int scale_;
     334             :   bool power_of_two_plus_one_;
     335             : };
     336             : 
     337             : typedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul,
     338             :                      IrOpcode::kWord32Shl> Int32ScaleMatcher;
     339             : typedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul,
     340             :                      IrOpcode::kWord64Shl> Int64ScaleMatcher;
     341             : 
     342             : template <class BinopMatcher, IrOpcode::Value AddOpcode,
     343             :           IrOpcode::Value SubOpcode, IrOpcode::Value kMulOpcode,
     344             :           IrOpcode::Value kShiftOpcode>
     345             : struct AddMatcher : public BinopMatcher {
     346             :   static const IrOpcode::Value kAddOpcode = AddOpcode;
     347             :   static const IrOpcode::Value kSubOpcode = SubOpcode;
     348             :   typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher;
     349             : 
     350     6389127 :   AddMatcher(Node* node, bool allow_input_swap)
     351             :       : BinopMatcher(node, allow_input_swap),
     352             :         scale_(-1),
     353     6389127 :         power_of_two_plus_one_(false) {
     354     6389168 :     Initialize(node, allow_input_swap);
     355     6389151 :   }
     356      803854 :   explicit AddMatcher(Node* node)
     357             :       : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)),
     358             :         scale_(-1),
     359      401927 :         power_of_two_plus_one_(false) {
     360      401927 :     Initialize(node, node->op()->HasProperty(Operator::kCommutative));
     361      401927 :   }
     362             : 
     363             :   bool HasIndexInput() const { return scale_ != -1; }
     364             :   Node* IndexInput() const {
     365             :     DCHECK(HasIndexInput());
     366             :     return this->left().node()->InputAt(0);
     367             :   }
     368             :   int scale() const {
     369             :     DCHECK(HasIndexInput());
     370             :     return scale_;
     371             :   }
     372             :   bool power_of_two_plus_one() const { return power_of_two_plus_one_; }
     373             : 
     374             :  private:
     375     6791089 :   void Initialize(Node* node, bool allow_input_swap) {
     376     6791089 :     Matcher left_matcher(this->left().node(), true);
     377     6791086 :     if (left_matcher.matches()) {
     378      312426 :       scale_ = left_matcher.scale();
     379      312426 :       power_of_two_plus_one_ = left_matcher.power_of_two_plus_one();
     380      699087 :       return;
     381             :     }
     382             : 
     383     6478660 :     if (!allow_input_swap) {
     384             :       return;
     385             :     }
     386             : 
     387     6463538 :     Matcher right_matcher(this->right().node(), true);
     388     6463531 :     if (right_matcher.matches()) {
     389       59113 :       scale_ = right_matcher.scale();
     390       59113 :       power_of_two_plus_one_ = right_matcher.power_of_two_plus_one();
     391       59113 :       this->SwapInputs();
     392       59113 :       return;
     393             :     }
     394             : 
     395     6720777 :     if (this->right().opcode() == kAddOpcode &&
     396             :         this->left().opcode() != kAddOpcode) {
     397      315407 :       this->SwapInputs();
     398     6111632 :     } else if (this->right().opcode() == kSubOpcode &&
     399             :                this->left().opcode() != kSubOpcode) {
     400       22605 :       this->SwapInputs();
     401             :     }
     402             :   }
     403             : 
     404             :   int scale_;
     405             :   bool power_of_two_plus_one_;
     406             : };
     407             : 
     408             : typedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Sub,
     409             :                    IrOpcode::kInt32Mul, IrOpcode::kWord32Shl>
     410             :     Int32AddMatcher;
     411             : typedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Sub,
     412             :                    IrOpcode::kInt64Mul, IrOpcode::kWord64Shl>
     413             :     Int64AddMatcher;
     414             : 
     415             : enum DisplacementMode { kPositiveDisplacement, kNegativeDisplacement };
     416             : 
     417             : enum class AddressOption : uint8_t {
     418             :   kAllowNone = 0u,
     419             :   kAllowInputSwap = 1u << 0,
     420             :   kAllowScale = 1u << 1,
     421             :   kAllowAll = kAllowInputSwap | kAllowScale
     422             : };
     423             : 
     424             : typedef base::Flags<AddressOption, uint8_t> AddressOptions;
     425             : DEFINE_OPERATORS_FOR_FLAGS(AddressOptions);
     426             : 
     427             : template <class AddMatcher>
     428             : struct BaseWithIndexAndDisplacementMatcher {
     429             :   BaseWithIndexAndDisplacementMatcher(Node* node, AddressOptions options)
     430             :       : matches_(false),
     431             :         index_(nullptr),
     432             :         scale_(0),
     433             :         base_(nullptr),
     434             :         displacement_(nullptr),
     435     5173401 :         displacement_mode_(kPositiveDisplacement) {
     436     5173401 :     Initialize(node, options);
     437             :   }
     438             : 
     439     2431688 :   explicit BaseWithIndexAndDisplacementMatcher(Node* node)
     440             :       : matches_(false),
     441             :         index_(nullptr),
     442             :         scale_(0),
     443             :         base_(nullptr),
     444             :         displacement_(nullptr),
     445     1215844 :         displacement_mode_(kPositiveDisplacement) {
     446     1215844 :     Initialize(node, AddressOption::kAllowScale |
     447             :                          (node->op()->HasProperty(Operator::kCommutative)
     448             :                               ? AddressOption::kAllowInputSwap
     449     1215844 :                               : AddressOption::kAllowNone));
     450     1215863 :   }
     451             : 
     452             :   bool matches() const { return matches_; }
     453             :   Node* index() const { return index_; }
     454             :   int scale() const { return scale_; }
     455             :   Node* base() const { return base_; }
     456             :   Node* displacement() const { return displacement_; }
     457             :   DisplacementMode displacement_mode() const { return displacement_mode_; }
     458             : 
     459             :  private:
     460             :   bool matches_;
     461             :   Node* index_;
     462             :   int scale_;
     463             :   Node* base_;
     464             :   Node* displacement_;
     465             :   DisplacementMode displacement_mode_;
     466             : 
     467     6389125 :   void Initialize(Node* node, AddressOptions options) {
     468             :     // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of
     469             :     // displacements and scale factors that are used as inputs, so instead of
     470             :     // enumerating all possible patterns by brute force, checking for node
     471             :     // clusters using the following templates in the following order suffices to
     472             :     // find all of the interesting cases (S = index * scale, B = base input, D =
     473             :     // displacement input):
     474             :     // (S + (B + D))
     475             :     // (S + (B + B))
     476             :     // (S + D)
     477             :     // (S + B)
     478             :     // ((S + D) + B)
     479             :     // ((S + B) + D)
     480             :     // ((B + D) + B)
     481             :     // ((B + B) + D)
     482             :     // (B + D)
     483             :     // (B + B)
     484     6389125 :     if (node->InputCount() < 2) return;
     485     6389125 :     AddMatcher m(node, options & AddressOption::kAllowInputSwap);
     486    12501441 :     Node* left = m.left().node();
     487      270662 :     Node* right = m.right().node();
     488     6184729 :     Node* displacement = nullptr;
     489             :     Node* base = nullptr;
     490             :     Node* index = nullptr;
     491             :     Node* scale_expression = nullptr;
     492             :     bool power_of_two_plus_one = false;
     493             :     DisplacementMode displacement_mode = kPositiveDisplacement;
     494             :     int scale = 0;
     495     6389152 :     if (m.HasIndexInput() && left->OwnedByAddressingOperand()) {
     496             :       index = m.IndexInput();
     497      135331 :       scale = m.scale();
     498             :       scale_expression = left;
     499      135331 :       power_of_two_plus_one = m.power_of_two_plus_one();
     500             :       bool match_found = false;
     501      135331 :       if (right->opcode() == AddMatcher::kSubOpcode &&
     502           0 :           right->OwnedByAddressingOperand()) {
     503           0 :         AddMatcher right_matcher(right);
     504           0 :         if (right_matcher.right().HasValue()) {
     505             :           // (S + (B - D))
     506             :           base = right_matcher.left().node();
     507             :           displacement = right_matcher.right().node();
     508             :           displacement_mode = kNegativeDisplacement;
     509             :           match_found = true;
     510             :         }
     511             :       }
     512      135331 :       if (!match_found) {
     513      139555 :         if (right->opcode() == AddMatcher::kAddOpcode &&
     514        4224 :             right->OwnedByAddressingOperand()) {
     515        4217 :           AddMatcher right_matcher(right);
     516        4217 :           if (right_matcher.right().HasValue()) {
     517             :             // (S + (B + D))
     518             :             base = right_matcher.left().node();
     519             :             displacement = right_matcher.right().node();
     520             :           } else {
     521             :             // (S + (B + B))
     522             :             base = right;
     523             :           }
     524      131114 :         } else if (m.right().HasValue()) {
     525             :           // (S + D)
     526             :           displacement = right;
     527             :         } else {
     528             :           // (S + B)
     529             :           base = right;
     530             :         }
     531             :       }
     532             :     } else {
     533             :       bool match_found = false;
     534     6281148 :       if (left->opcode() == AddMatcher::kSubOpcode &&
     535       27327 :           left->OwnedByAddressingOperand()) {
     536       13324 :         AddMatcher left_matcher(left);
     537        1347 :         Node* left_left = left_matcher.left().node();
     538             :         Node* left_right = left_matcher.right().node();
     539       13324 :         if (left_matcher.right().HasValue()) {
     540       12892 :           if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
     541             :             // ((S - D) + B)
     542             :             index = left_matcher.IndexInput();
     543             :             scale = left_matcher.scale();
     544             :             scale_expression = left_left;
     545          43 :             power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     546             :             displacement = left_right;
     547             :             displacement_mode = kNegativeDisplacement;
     548             :             base = right;
     549             :           } else {
     550             :             // ((B - D) + B)
     551             :             index = left_left;
     552             :             displacement = left_right;
     553             :             displacement_mode = kNegativeDisplacement;
     554             :             base = right;
     555             :           }
     556             :           match_found = true;
     557             :         }
     558             :       }
     559     6253821 :       if (!match_found) {
     560     6749299 :         if (left->opcode() == AddMatcher::kAddOpcode &&
     561      507038 :             left->OwnedByAddressingOperand()) {
     562      384386 :           AddMatcher left_matcher(left);
     563      226518 :           Node* left_left = left_matcher.left().node();
     564             :           Node* left_right = left_matcher.right().node();
     565      610904 :           if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) {
     566      226101 :             if (left_matcher.right().HasValue()) {
     567             :               // ((S + D) + B)
     568             :               index = left_matcher.IndexInput();
     569             :               scale = left_matcher.scale();
     570             :               scale_expression = left_left;
     571      225018 :               power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     572             :               displacement = left_right;
     573             :               base = right;
     574        1083 :             } else if (m.right().HasValue()) {
     575         578 :               if (left->OwnedBy(node)) {
     576             :                 // ((S + B) + D)
     577             :                 index = left_matcher.IndexInput();
     578             :                 scale = left_matcher.scale();
     579             :                 scale_expression = left_left;
     580         534 :                 power_of_two_plus_one = left_matcher.power_of_two_plus_one();
     581             :                 base = left_right;
     582             :                 displacement = right;
     583             :               } else {
     584             :                 // (B + D)
     585             :                 base = left;
     586             :                 displacement = right;
     587             :               }
     588             :             } else {
     589             :               // (B + B)
     590             :               index = left;
     591             :               base = right;
     592             :             }
     593             :           } else {
     594      158285 :             if (left_matcher.right().HasValue()) {
     595             :               // ((B + D) + B)
     596             :               index = left_left;
     597             :               displacement = left_right;
     598             :               base = right;
     599       14941 :             } else if (m.right().HasValue()) {
     600        4781 :               if (left->OwnedBy(node)) {
     601             :                 // ((B + B) + D)
     602             :                 index = left_left;
     603             :                 base = left_right;
     604             :                 displacement = right;
     605             :               } else {
     606             :                 // (B + D)
     607             :                 base = left;
     608             :                 displacement = right;
     609             :               }
     610             :             } else {
     611             :               // (B + B)
     612             :               index = left;
     613             :               base = right;
     614             :             }
     615             :           }
     616             :         } else {
     617     5857875 :           if (m.right().HasValue()) {
     618             :             // (B + D)
     619             :             base = left;
     620             :             displacement = right;
     621             :           } else {
     622             :             // (B + B)
     623             :             base = left;
     624             :             index = right;
     625             :           }
     626             :         }
     627             :       }
     628             :     }
     629             :     int64_t value = 0;
     630     6389152 :     if (displacement != nullptr) {
     631     6184729 :       switch (displacement->opcode()) {
     632             :         case IrOpcode::kInt32Constant: {
     633      449276 :           value = OpParameter<int32_t>(displacement);
     634      449276 :           break;
     635             :         }
     636             :         case IrOpcode::kInt64Constant: {
     637     5735453 :           value = OpParameter<int64_t>(displacement);
     638     5735453 :           break;
     639             :         }
     640             :         default:
     641           0 :           UNREACHABLE();
     642             :           break;
     643             :       }
     644     6184729 :       if (value == 0) {
     645             :         displacement = nullptr;
     646             :       }
     647             :     }
     648     6389152 :     if (power_of_two_plus_one) {
     649       31857 :       if (base != nullptr) {
     650             :         // If the scale requires explicitly using the index as the base, but a
     651             :         // base is already part of the match, then the (1 << N + 1) scale factor
     652             :         // can't be folded into the match and the entire index * scale
     653             :         // calculation must be computed separately.
     654             :         index = scale_expression;
     655             :         scale = 0;
     656             :       } else {
     657             :         base = index;
     658             :       }
     659             :     }
     660     6389152 :     if (!(options & AddressOption::kAllowScale) && scale != 0) {
     661             :       index = scale_expression;
     662             :       scale = 0;
     663             :     }
     664     6389152 :     base_ = base;
     665     6389152 :     displacement_ = displacement;
     666     6389152 :     displacement_mode_ = displacement_mode;
     667     6389152 :     index_ = index;
     668     6389152 :     scale_ = scale;
     669     6389152 :     matches_ = true;
     670             :   }
     671             : };
     672             : 
     673             : typedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher>
     674             :     BaseWithIndexAndDisplacement32Matcher;
     675             : typedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher>
     676             :     BaseWithIndexAndDisplacement64Matcher;
     677             : 
     678             : struct V8_EXPORT_PRIVATE BranchMatcher : public NON_EXPORTED_BASE(NodeMatcher) {
     679             :   explicit BranchMatcher(Node* branch);
     680             : 
     681             :   bool Matched() const { return if_true_ && if_false_; }
     682             : 
     683             :   Node* Branch() const { return node(); }
     684             :   Node* IfTrue() const { return if_true_; }
     685             :   Node* IfFalse() const { return if_false_; }
     686             : 
     687             :  private:
     688             :   Node* if_true_;
     689             :   Node* if_false_;
     690             : };
     691             : 
     692             : struct V8_EXPORT_PRIVATE DiamondMatcher
     693             :     : public NON_EXPORTED_BASE(NodeMatcher) {
     694             :   explicit DiamondMatcher(Node* merge);
     695             : 
     696             :   bool Matched() const { return branch_; }
     697             :   bool IfProjectionsAreOwned() const {
     698             :     return if_true_->OwnedBy(node()) && if_false_->OwnedBy(node());
     699             :   }
     700             : 
     701             :   Node* Branch() const { return branch_; }
     702             :   Node* IfTrue() const { return if_true_; }
     703             :   Node* IfFalse() const { return if_false_; }
     704             :   Node* Merge() const { return node(); }
     705             : 
     706             :   Node* TrueInputOf(Node* phi) const {
     707             :     DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     708             :     DCHECK_EQ(3, phi->InputCount());
     709             :     DCHECK_EQ(Merge(), phi->InputAt(2));
     710             :     return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 0 : 1);
     711             :   }
     712             : 
     713             :   Node* FalseInputOf(Node* phi) const {
     714             :     DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     715             :     DCHECK_EQ(3, phi->InputCount());
     716             :     DCHECK_EQ(Merge(), phi->InputAt(2));
     717             :     return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 1 : 0);
     718             :   }
     719             : 
     720             :  private:
     721             :   Node* branch_;
     722             :   Node* if_true_;
     723             :   Node* if_false_;
     724             : };
     725             : 
     726             : }  // namespace compiler
     727             : }  // namespace internal
     728             : }  // namespace v8
     729             : 
     730             : #endif  // V8_COMPILER_NODE_MATCHERS_H_

Generated by: LCOV version 1.10