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