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 { NodeMatcherNodeMatcher17 explicit NodeMatcher(Node* node) : node_(node) {} 18 nodeNodeMatcher19 Node* node() const { return node_; } opNodeMatcher20 const Operator* op() const { return node()->op(); } opcodeNodeMatcher21 IrOpcode::Value opcode() const { return node()->opcode(); } 22 HasPropertyNodeMatcher23 bool HasProperty(Operator::Property property) const { 24 return op()->HasProperty(property); 25 } InputAtNodeMatcher26 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 { ValueMatcherValueMatcher41 explicit ValueMatcher(Node* node) 42 : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) { 43 if (has_value_) { 44 value_ = OpParameter<T>(node); 45 } 46 } 47 HasValueValueMatcher48 bool HasValue() const { return has_value_; } ValueValueMatcher49 const T& Value() const { 50 DCHECK(HasValue()); 51 return value_; 52 } 53 IsValueMatcher54 bool Is(const T& value) const { 55 return this->HasValue() && this->Value() == value; 56 } 57 IsInRangeValueMatcher58 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> { IntMatcherFINAL71 explicit IntMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 72 IsPowerOf2FINAL73 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> { FloatMatcherFINAL88 explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 89 IsNaNFINAL90 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> { HeapObjectMatcherFINAL102 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 { BinopMatcherFINAL112 explicit BinopMatcher(Node* node) 113 : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { 114 if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); 115 } 116 leftFINAL117 const Left& left() const { return left_; } rightFINAL118 const Right& right() const { return right_; } 119 IsFoldableFINAL120 bool IsFoldable() const { return left().HasValue() && right().HasValue(); } LeftEqualsRightFINAL121 bool LeftEqualsRight() const { return left().node() == right().node(); } 122 123 private: PutConstantOnRightFINAL124 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