// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_COMPILER_NODE_MATCHERS_H_ #define V8_COMPILER_NODE_MATCHERS_H_ #include "src/compiler/node.h" #include "src/compiler/operator.h" #include "src/unique.h" namespace v8 { namespace internal { namespace compiler { // A pattern matcher for nodes. struct NodeMatcher { explicit NodeMatcher(Node* node) : node_(node) {} Node* node() const { return node_; } const Operator* op() const { return node()->op(); } IrOpcode::Value opcode() const { return node()->opcode(); } bool HasProperty(Operator::Property property) const { return op()->HasProperty(property); } Node* InputAt(int index) const { return node()->InputAt(index); } #define DEFINE_IS_OPCODE(Opcode) \ bool Is##Opcode() const { return opcode() == IrOpcode::k##Opcode; } ALL_OP_LIST(DEFINE_IS_OPCODE) #undef DEFINE_IS_OPCODE private: Node* node_; }; // A pattern matcher for abitrary value constants. template struct ValueMatcher : public NodeMatcher { explicit ValueMatcher(Node* node) : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) { if (has_value_) { value_ = OpParameter(node); } } bool HasValue() const { return has_value_; } const T& Value() const { DCHECK(HasValue()); return value_; } bool Is(const T& value) const { return this->HasValue() && this->Value() == value; } bool IsInRange(const T& low, const T& high) const { return this->HasValue() && low <= this->Value() && this->Value() <= high; } private: T value_; bool has_value_; }; // A pattern matcher for integer constants. template struct IntMatcher FINAL : public ValueMatcher { explicit IntMatcher(Node* node) : ValueMatcher(node) {} bool IsPowerOf2() const { return this->HasValue() && this->Value() > 0 && (this->Value() & (this->Value() - 1)) == 0; } }; typedef IntMatcher Int32Matcher; typedef IntMatcher Uint32Matcher; typedef IntMatcher Int64Matcher; typedef IntMatcher Uint64Matcher; // A pattern matcher for floating point constants. template struct FloatMatcher FINAL : public ValueMatcher { explicit FloatMatcher(Node* node) : ValueMatcher(node) {} bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); } }; typedef FloatMatcher Float32Matcher; typedef FloatMatcher Float64Matcher; typedef FloatMatcher NumberMatcher; // A pattern matcher for heap object constants. template struct HeapObjectMatcher FINAL : public ValueMatcher, IrOpcode::kHeapConstant> { explicit HeapObjectMatcher(Node* node) : ValueMatcher, IrOpcode::kHeapConstant>(node) {} }; // For shorter pattern matching code, this struct matches both the left and // right hand sides of a binary operation and can put constants on the right // if they appear on the left hand side of a commutative operation. template struct BinopMatcher FINAL : public NodeMatcher { explicit BinopMatcher(Node* node) : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); } const Left& left() const { return left_; } const Right& right() const { return right_; } bool IsFoldable() const { return left().HasValue() && right().HasValue(); } bool LeftEqualsRight() const { return left().node() == right().node(); } private: void PutConstantOnRight() { if (left().HasValue() && !right().HasValue()) { std::swap(left_, right_); node()->ReplaceInput(0, left().node()); node()->ReplaceInput(1, right().node()); } } Left left_; Right right_; }; typedef BinopMatcher Int32BinopMatcher; typedef BinopMatcher Uint32BinopMatcher; typedef BinopMatcher Int64BinopMatcher; typedef BinopMatcher Uint64BinopMatcher; typedef BinopMatcher Float64BinopMatcher; // Fairly intel-specify node matcher used for matching scale factors in // addressing modes. // Matches nodes of form [x * N] for N in {1,2,4,8} class ScaleFactorMatcher : public NodeMatcher { public: static const int kMatchedFactors[4]; explicit ScaleFactorMatcher(Node* node); bool Matches() const { return left_ != NULL; } int Power() const { DCHECK(Matches()); return power_; } Node* Left() const { DCHECK(Matches()); return left_; } private: Node* left_; int power_; }; // Fairly intel-specify node matcher used for matching index and displacement // operands in addressing modes. // Matches nodes of form: // [x * N] // [x * N + K] // [x + K] // [x] -- fallback case // for N in {1,2,4,8} and K int32_t class IndexAndDisplacementMatcher : public NodeMatcher { public: explicit IndexAndDisplacementMatcher(Node* node); Node* index_node() const { return index_node_; } int displacement() const { return displacement_; } int power() const { return power_; } private: Node* index_node_; int displacement_; int power_; }; // Fairly intel-specify node matcher used for matching multiplies that can be // transformed to lea instructions. // Matches nodes of form: // [x * N] // for N in {1,2,3,4,5,8,9} class LeaMultiplyMatcher : public NodeMatcher { public: static const int kMatchedFactors[7]; explicit LeaMultiplyMatcher(Node* node); bool Matches() const { return left_ != NULL; } int Power() const { DCHECK(Matches()); return power_; } Node* Left() const { DCHECK(Matches()); return left_; } // Displacement will be either 0 or 1. int32_t Displacement() const { DCHECK(Matches()); return displacement_; } private: Node* left_; int power_; int displacement_; }; } // namespace compiler } // namespace internal } // namespace v8 #endif // V8_COMPILER_NODE_MATCHERS_H_