Home | History | Annotate | Download | only in compiler
      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 "src/compiler/node.h"
      9 #include "src/compiler/operator.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 // A pattern matcher for nodes.
     16 struct NodeMatcher {
     17   explicit NodeMatcher(Node* node) : node_(node) {}
     18 
     19   Node* node() const { return node_; }
     20   const Operator* op() const { return node()->op(); }
     21   IrOpcode::Value opcode() const { return node()->opcode(); }
     22 
     23   bool HasProperty(Operator::Property property) const {
     24     return op()->HasProperty(property);
     25   }
     26   Node* InputAt(int index) const { return node()->InputAt(index); }
     27 
     28 #define DEFINE_IS_OPCODE(Opcode) \
     29   bool Is##Opcode() const { return opcode() == IrOpcode::k##Opcode; }
     30   ALL_OP_LIST(DEFINE_IS_OPCODE)
     31 #undef DEFINE_IS_OPCODE
     32 
     33  private:
     34   Node* node_;
     35 };
     36 
     37 
     38 // A pattern matcher for abitrary value constants.
     39 template <typename T, IrOpcode::Value kOpcode>
     40 struct ValueMatcher : public NodeMatcher {
     41   explicit ValueMatcher(Node* node)
     42       : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) {
     43     if (has_value_) {
     44       value_ = OpParameter<T>(node);
     45     }
     46   }
     47 
     48   bool HasValue() const { return has_value_; }
     49   const T& Value() const {
     50     DCHECK(HasValue());
     51     return value_;
     52   }
     53 
     54   bool Is(const T& value) const {
     55     return this->HasValue() && this->Value() == value;
     56   }
     57 
     58   bool IsInRange(const T& low, const T& high) const {
     59     return this->HasValue() && low <= this->Value() && this->Value() <= high;
     60   }
     61 
     62  private:
     63   T value_;
     64   bool has_value_;
     65 };
     66 
     67 
     68 // A pattern matcher for integer constants.
     69 template <typename T, IrOpcode::Value kOpcode>
     70 struct IntMatcher FINAL : public ValueMatcher<T, kOpcode> {
     71   explicit IntMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {}
     72 
     73   bool IsPowerOf2() const {
     74     return this->HasValue() && this->Value() > 0 &&
     75            (this->Value() & (this->Value() - 1)) == 0;
     76   }
     77 };
     78 
     79 typedef IntMatcher<int32_t, IrOpcode::kInt32Constant> Int32Matcher;
     80 typedef IntMatcher<uint32_t, IrOpcode::kInt32Constant> Uint32Matcher;
     81 typedef IntMatcher<int64_t, IrOpcode::kInt64Constant> Int64Matcher;
     82 typedef IntMatcher<uint64_t, IrOpcode::kInt64Constant> Uint64Matcher;
     83 
     84 
     85 // A pattern matcher for floating point constants.
     86 template <typename T, IrOpcode::Value kOpcode>
     87 struct FloatMatcher FINAL : public ValueMatcher<T, kOpcode> {
     88   explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {}
     89 
     90   bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); }
     91 };
     92 
     93 typedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher;
     94 typedef FloatMatcher<double, IrOpcode::kFloat64Constant> Float64Matcher;
     95 typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
     96 
     97 
     98 // A pattern matcher for heap object constants.
     99 template <typename T>
    100 struct HeapObjectMatcher FINAL
    101     : public ValueMatcher<Unique<T>, IrOpcode::kHeapConstant> {
    102   explicit HeapObjectMatcher(Node* node)
    103       : ValueMatcher<Unique<T>, IrOpcode::kHeapConstant>(node) {}
    104 };
    105 
    106 
    107 // For shorter pattern matching code, this struct matches both the left and
    108 // right hand sides of a binary operation and can put constants on the right
    109 // if they appear on the left hand side of a commutative operation.
    110 template <typename Left, typename Right>
    111 struct BinopMatcher FINAL : public NodeMatcher {
    112   explicit BinopMatcher(Node* node)
    113       : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) {
    114     if (HasProperty(Operator::kCommutative)) PutConstantOnRight();
    115   }
    116 
    117   const Left& left() const { return left_; }
    118   const Right& right() const { return right_; }
    119 
    120   bool IsFoldable() const { return left().HasValue() && right().HasValue(); }
    121   bool LeftEqualsRight() const { return left().node() == right().node(); }
    122 
    123  private:
    124   void PutConstantOnRight() {
    125     if (left().HasValue() && !right().HasValue()) {
    126       std::swap(left_, right_);
    127       node()->ReplaceInput(0, left().node());
    128       node()->ReplaceInput(1, right().node());
    129     }
    130   }
    131 
    132   Left left_;
    133   Right right_;
    134 };
    135 
    136 typedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher;
    137 typedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher;
    138 typedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher;
    139 typedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher;
    140 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
    141 
    142 }  // namespace compiler
    143 }  // namespace internal
    144 }  // namespace v8
    145 
    146 #endif  // V8_COMPILER_NODE_MATCHERS_H_
    147