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 8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <cmath> 9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TODO(turbofan): Move ExternalReference out of assembler.h 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assembler.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/operator.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A pattern matcher for nodes. 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct NodeMatcher { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit NodeMatcher(Node* node) : node_(node) {} 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* node() const { return node_; } 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operator* op() const { return node()->op(); } 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IrOpcode::Value opcode() const { return node()->opcode(); } 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool HasProperty(Operator::Property property) const { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return op()->HasProperty(property); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* InputAt(int index) const { return node()->InputAt(index); } 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Equals(const Node* node) const { return node_ == node; } 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsComparison() const; 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_IS_OPCODE(Opcode) \ 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool Is##Opcode() const { return opcode() == IrOpcode::k##Opcode; } 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ALL_OP_LIST(DEFINE_IS_OPCODE) 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_IS_OPCODE 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* node_; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A pattern matcher for abitrary value constants. 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T, IrOpcode::Value kOpcode> 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct ValueMatcher : public NodeMatcher { 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef T ValueType; 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit ValueMatcher(Node* node) 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NodeMatcher(node), value_(), has_value_(opcode() == kOpcode) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_value_) { 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value_ = OpParameter<T>(node); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool HasValue() const { return has_value_; } 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const T& Value() const { 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(HasValue()); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value_; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T value_; 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_value_; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <> 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochinline ValueMatcher<uint32_t, IrOpcode::kInt32Constant>::ValueMatcher( 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* node) 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : NodeMatcher(node), 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch value_(), 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch has_value_(opcode() == IrOpcode::kInt32Constant) { 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (has_value_) { 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch value_ = static_cast<uint32_t>(OpParameter<int32_t>(node)); 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <> 83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierinline ValueMatcher<int64_t, IrOpcode::kInt64Constant>::ValueMatcher(Node* node) 84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : NodeMatcher(node), value_(), has_value_(false) { 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (opcode() == IrOpcode::kInt32Constant) { 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value_ = OpParameter<int32_t>(node); 87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier has_value_ = true; 88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (opcode() == IrOpcode::kInt64Constant) { 89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value_ = OpParameter<int64_t>(node); 90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier has_value_ = true; 91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <> 96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierinline ValueMatcher<uint64_t, IrOpcode::kInt64Constant>::ValueMatcher( 97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* node) 98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : NodeMatcher(node), value_(), has_value_(false) { 99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (opcode() == IrOpcode::kInt32Constant) { 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch value_ = static_cast<uint32_t>(OpParameter<int32_t>(node)); 101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier has_value_ = true; 102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (opcode() == IrOpcode::kInt64Constant) { 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch value_ = static_cast<uint64_t>(OpParameter<int64_t>(node)); 104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier has_value_ = true; 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A pattern matcher for integer constants. 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T, IrOpcode::Value kOpcode> 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct IntMatcher final : public ValueMatcher<T, kOpcode> { 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit IntMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Is(const T& value) const { 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this->HasValue() && this->Value() == value; 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsInRange(const T& low, const T& high) const { 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this->HasValue() && low <= this->Value() && this->Value() <= high; 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool IsMultipleOf(T n) const { 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return this->HasValue() && (this->Value() % n) == 0; 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsPowerOf2() const { 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return this->HasValue() && this->Value() > 0 && 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (this->Value() & (this->Value() - 1)) == 0; 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool IsNegativePowerOf2() const { 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return this->HasValue() && this->Value() < 0 && 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier (-this->Value() & (-this->Value() - 1)) == 0; 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef IntMatcher<int32_t, IrOpcode::kInt32Constant> Int32Matcher; 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef IntMatcher<uint32_t, IrOpcode::kInt32Constant> Uint32Matcher; 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef IntMatcher<int64_t, IrOpcode::kInt64Constant> Int64Matcher; 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef IntMatcher<uint64_t, IrOpcode::kInt64Constant> Uint64Matcher; 137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_HOST_ARCH_32_BIT 138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef Int32Matcher IntPtrMatcher; 139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef Uint32Matcher UintPtrMatcher; 140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else 141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef Int64Matcher IntPtrMatcher; 142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef Uint64Matcher UintPtrMatcher; 143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A pattern matcher for floating point constants. 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T, IrOpcode::Value kOpcode> 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct FloatMatcher final : public ValueMatcher<T, kOpcode> { 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Is(const T& value) const { 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this->HasValue() && this->Value() == value; 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsInRange(const T& low, const T& high) const { 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this->HasValue() && low <= this->Value() && this->Value() <= high; 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool IsMinusZero() const { 158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return this->Is(0.0) && std::signbit(this->Value()); 159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); } 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IsZero() const { return this->Is(0.0) && !std::signbit(this->Value()); } 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FloatMatcher<double, IrOpcode::kFloat64Constant> Float64Matcher; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher; 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A pattern matcher for heap object constants. 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct HeapObjectMatcher final 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : public ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant> { 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit HeapObjectMatcher(Node* node) 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : ValueMatcher<Handle<HeapObject>, IrOpcode::kHeapConstant>(node) {} 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A pattern matcher for external reference constants. 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct ExternalReferenceMatcher final 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : public ValueMatcher<ExternalReference, IrOpcode::kExternalConstant> { 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit ExternalReferenceMatcher(Node* node) 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : ValueMatcher<ExternalReference, IrOpcode::kExternalConstant>(node) {} 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Is(const ExternalReference& value) const { 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return this->HasValue() && this->Value() == value; 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// For shorter pattern matching code, this struct matches the inputs to 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// machine-level load operations. 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename Object> 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct LoadMatcher : public NodeMatcher { 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit LoadMatcher(Node* node) 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : NodeMatcher(node), object_(InputAt(0)), index_(InputAt(1)) {} 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch typedef Object ObjectMatcher; 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object const& object() const { return object_; } 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IntPtrMatcher const& index() const { return index_; } 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object const object_; 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IntPtrMatcher const index_; 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For shorter pattern matching code, this struct matches both the left and 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// right hand sides of a binary operation and can put constants on the right 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// if they appear on the left hand side of a commutative operation. 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename Left, typename Right> 210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct BinopMatcher : public NodeMatcher { 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BinopMatcher(Node* node) 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinopMatcher(Node* node, bool allow_input_swap) 216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { 217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (allow_input_swap) PutConstantOnRight(); 218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef Left LeftMatcher; 221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef Right RightMatcher; 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Left& left() const { return left_; } 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Right& right() const { return right_; } 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsFoldable() const { return left().HasValue() && right().HasValue(); } 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool LeftEqualsRight() const { return left().node() == right().node(); } 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier protected: 230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void SwapInputs() { 231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier std::swap(left_, right_); 232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier node()->ReplaceInput(0, left().node()); 233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier node()->ReplaceInput(1, right().node()); 234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PutConstantOnRight() { 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (left().HasValue() && !right().HasValue()) { 239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SwapInputs(); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Left left_; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Right right_; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BinopMatcher<Int32Matcher, Int32Matcher> Int32BinopMatcher; 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BinopMatcher<Uint32Matcher, Uint32Matcher> Uint32BinopMatcher; 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BinopMatcher<Int64Matcher, Int64Matcher> Int64BinopMatcher; 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BinopMatcher<Uint64Matcher, Uint64Matcher> Uint64BinopMatcher; 251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BinopMatcher<IntPtrMatcher, IntPtrMatcher> IntPtrBinopMatcher; 252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BinopMatcher<UintPtrMatcher, UintPtrMatcher> UintPtrBinopMatcher; 253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef BinopMatcher<Float32Matcher, Float32Matcher> Float32BinopMatcher; 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher; 255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher; 256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <class BinopMatcher, IrOpcode::Value kMulOpcode, 259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::Value kShiftOpcode> 260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct ScaleMatcher { 261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier explicit ScaleMatcher(Node* node, bool allow_power_of_two_plus_one = false) 262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : scale_(-1), power_of_two_plus_one_(false) { 263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (node->InputCount() < 2) return; 264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BinopMatcher m(node); 265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (node->opcode() == kShiftOpcode) { 266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (m.right().HasValue()) { 267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typename BinopMatcher::RightMatcher::ValueType value = 268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier m.right().Value(); 269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (value >= 0 && value <= 3) { 270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = static_cast<int>(value); 271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (node->opcode() == kMulOpcode) { 274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (m.right().HasValue()) { 275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typename BinopMatcher::RightMatcher::ValueType value = 276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier m.right().Value(); 277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (value == 1) { 278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 0; 279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value == 2) { 280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 1; 281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value == 4) { 282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 2; 283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value == 8) { 284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 3; 285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (allow_power_of_two_plus_one) { 286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (value == 3) { 287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 1; 288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_ = true; 289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value == 5) { 290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 2; 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_ = true; 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (value == 9) { 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = 3; 294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_ = true; 295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool matches() const { return scale_ != -1; } 302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale() const { return scale_; } 303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool power_of_two_plus_one() const { return power_of_two_plus_one_; } 304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private: 306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale_; 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool power_of_two_plus_one_; 308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}; 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul, 311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::kWord32Shl> Int32ScaleMatcher; 312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul, 313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::kWord64Shl> Int64ScaleMatcher; 314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <class BinopMatcher, IrOpcode::Value kAddOpcode, 317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::Value kMulOpcode, IrOpcode::Value kShiftOpcode> 318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct AddMatcher : public BinopMatcher { 319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier static const IrOpcode::Value kOpcode = kAddOpcode; 320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier typedef ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode> Matcher; 321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddMatcher(Node* node, bool allow_input_swap) 323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : BinopMatcher(node, allow_input_swap), 324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_(-1), 325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_(false) { 326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Initialize(node, allow_input_swap); 327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier explicit AddMatcher(Node* node) 329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)), 330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_(-1), 331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_(false) { 332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Initialize(node, node->op()->HasProperty(Operator::kCommutative)); 333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool HasIndexInput() const { return scale_ != -1; } 336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* IndexInput() const { 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(HasIndexInput()); 338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return this->left().node()->InputAt(0); 339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale() const { 341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(HasIndexInput()); 342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return scale_; 343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool power_of_two_plus_one() const { return power_of_two_plus_one_; } 345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private: 347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void Initialize(Node* node, bool allow_input_swap) { 348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Matcher left_matcher(this->left().node(), true); 349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left_matcher.matches()) { 350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = left_matcher.scale(); 351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_ = left_matcher.power_of_two_plus_one(); 352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return; 353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!allow_input_swap) { 356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return; 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Matcher right_matcher(this->right().node(), true); 360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (right_matcher.matches()) { 361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = right_matcher.scale(); 362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one_ = right_matcher.power_of_two_plus_one(); 363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier this->SwapInputs(); 364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return; 365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (this->right().opcode() == kAddOpcode && 368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier this->left().opcode() != kAddOpcode) { 369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier this->SwapInputs(); 370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale_; 374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool power_of_two_plus_one_; 375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}; 376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Mul, 378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::kWord32Shl> Int32AddMatcher; 379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Mul, 380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier IrOpcode::kWord64Shl> Int64AddMatcher; 381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <class AddMatcher> 384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstruct BaseWithIndexAndDisplacementMatcher { 385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BaseWithIndexAndDisplacementMatcher(Node* node, bool allow_input_swap) 386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : matches_(false), 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch index_(nullptr), 388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_(0), 389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base_(nullptr), 390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch displacement_(nullptr) { 391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Initialize(node, allow_input_swap); 392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier explicit BaseWithIndexAndDisplacementMatcher(Node* node) 395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : matches_(false), 396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch index_(nullptr), 397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_(0), 398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base_(nullptr), 399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch displacement_(nullptr) { 400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Initialize(node, node->op()->HasProperty(Operator::kCommutative)); 401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool matches() const { return matches_; } 404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* index() const { return index_; } 405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale() const { return scale_; } 406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* base() const { return base_; } 407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* displacement() const { return displacement_; } 408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private: 410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool matches_; 411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* index_; 412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale_; 413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* base_; 414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* displacement_; 415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier void Initialize(Node* node, bool allow_input_swap) { 417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of 418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // displacements and scale factors that are used as inputs, so instead of 419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // enumerating all possible patterns by brute force, checking for node 420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // clusters using the following templates in the following order suffices to 421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // find all of the interesting cases (S = index * scale, B = base input, D = 422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // displacement input): 423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + (B + D)) 424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + (B + B)) 425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + D) 426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + B) 427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((S + D) + B) 428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((S + B) + D) 429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((B + D) + B) 430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((B + B) + D) 431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + D) 432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + B) 433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (node->InputCount() < 2) return; 434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddMatcher m(node, allow_input_swap); 435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* left = m.left().node(); 436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* right = m.right().node(); 437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* displacement = nullptr; 438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* base = nullptr; 439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* index = nullptr; 440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* scale_expression = nullptr; 441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier bool power_of_two_plus_one = false; 442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int scale = 0; 443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (m.HasIndexInput() && left->OwnedBy(node)) { 444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = m.IndexInput(); 445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale = m.scale(); 446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_expression = left; 447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one = m.power_of_two_plus_one(); 448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (right->opcode() == AddMatcher::kOpcode && right->OwnedBy(node)) { 449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddMatcher right_matcher(right); 450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (right_matcher.right().HasValue()) { 451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + (B + D)) 452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right_matcher.left().node(); 453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = right_matcher.right().node(); 454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + (B + B)) 456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (m.right().HasValue()) { 459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + D) 460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = right; 461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (S + B) 463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left->opcode() == AddMatcher::kOpcode && left->OwnedBy(node)) { 467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier AddMatcher left_matcher(left); 468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* left_left = left_matcher.left().node(); 469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Node* left_right = left_matcher.right().node(); 470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left_matcher.HasIndexInput() && left_left->OwnedBy(left)) { 471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left_matcher.right().HasValue()) { 472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((S + D) + B) 473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left_matcher.IndexInput(); 474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale = left_matcher.scale(); 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_expression = left_left; 476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one = left_matcher.power_of_two_plus_one(); 477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = left_right; 478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (m.right().HasValue()) { 480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((S + B) + D) 481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left_matcher.IndexInput(); 482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale = left_matcher.scale(); 483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_expression = left_left; 484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier power_of_two_plus_one = left_matcher.power_of_two_plus_one(); 485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = left_right; 486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = right; 487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + B) 489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left; 490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (left_matcher.right().HasValue()) { 494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((B + D) + B) 495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left_left; 496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = left_right; 497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else if (m.right().HasValue()) { 499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // ((B + B) + D) 500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left_left; 501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = left_right; 502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = right; 503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + B) 505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = left; 506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = right; 507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (m.right().HasValue()) { 511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + D) 512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = left; 513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement = right; 514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // (B + B) 516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = left; 517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = right; 518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int64_t value = 0; 522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (displacement != nullptr) { 523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (displacement->opcode()) { 524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case IrOpcode::kInt32Constant: { 525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value = OpParameter<int32_t>(displacement); 526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case IrOpcode::kInt64Constant: { 529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier value = OpParameter<int64_t>(displacement); 530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier default: 533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (value == 0) { 537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch displacement = nullptr; 538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (power_of_two_plus_one) { 541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (base != nullptr) { 542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // If the scale requires explicitly using the index as the base, but a 543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // base is already part of the match, then the (1 << N + 1) scale factor 544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // can't be folded into the match and the entire index * scale 545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // calculation must be computed separately. 546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index = scale_expression; 547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale = 0; 548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base = index; 550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base_ = base; 553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier displacement_ = displacement; 554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier index_ = index; 555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier scale_ = scale; 556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier matches_ = true; 557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}; 559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BaseWithIndexAndDisplacementMatcher<Int32AddMatcher> 561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BaseWithIndexAndDisplacement32Matcher; 562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef BaseWithIndexAndDisplacementMatcher<Int64AddMatcher> 563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier BaseWithIndexAndDisplacement64Matcher; 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct BranchMatcher : public NodeMatcher { 566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit BranchMatcher(Node* branch); 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Matched() const { return if_true_ && if_false_; } 569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* Branch() const { return node(); } 571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* IfTrue() const { return if_true_; } 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* IfFalse() const { return if_false_; } 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* if_true_; 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* if_false_; 577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct DiamondMatcher : public NodeMatcher { 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch explicit DiamondMatcher(Node* merge); 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool Matched() const { return branch_; } 584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool IfProjectionsAreOwned() const { 585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return if_true_->OwnedBy(node()) && if_false_->OwnedBy(node()); 586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* Branch() const { return branch_; } 589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* IfTrue() const { return if_true_; } 590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* IfFalse() const { return if_false_; } 591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* Merge() const { return node(); } 592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* TrueInputOf(Node* phi) const { 594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); 595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(3, phi->InputCount()); 596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(Merge(), phi->InputAt(2)); 597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 0 : 1); 598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* FalseInputOf(Node* phi) const { 601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); 602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(3, phi->InputCount()); 603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(Merge(), phi->InputAt(2)); 604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 1 : 0); 605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private: 608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* branch_; 609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* if_true_; 610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Node* if_false_; 611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace compiler 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace internal 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_COMPILER_NODE_MATCHERS_H_ 618