11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_NODE_MATCHERS_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_NODE_MATCHERS_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <cmath> 91cb0ef41Sopenharmony_ci#include <limits> 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci#include "src/base/bounds.h" 121cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 131cb0ef41Sopenharmony_ci#include "src/base/numbers/double.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/external-reference.h" 151cb0ef41Sopenharmony_ci#include "src/common/globals.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/machine-operator.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 191cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h" 201cb0ef41Sopenharmony_ci#include "src/compiler/operator.h" 211cb0ef41Sopenharmony_ci#include "src/objects/heap-object.h" 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace v8 { 241cb0ef41Sopenharmony_cinamespace internal { 251cb0ef41Sopenharmony_cinamespace compiler { 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciclass JSHeapBroker; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci// A pattern matcher for nodes. 301cb0ef41Sopenharmony_cistruct NodeMatcher { 311cb0ef41Sopenharmony_ci explicit NodeMatcher(Node* node) : node_(node) {} 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci Node* node() const { return node_; } 341cb0ef41Sopenharmony_ci const Operator* op() const { return node()->op(); } 351cb0ef41Sopenharmony_ci IrOpcode::Value opcode() const { return node()->opcode(); } 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci bool HasProperty(Operator::Property property) const { 381cb0ef41Sopenharmony_ci return op()->HasProperty(property); 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci Node* InputAt(int index) const { return node()->InputAt(index); } 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci bool Equals(const Node* node) const { return node_ == node; } 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci bool IsComparison() const; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci#define DEFINE_IS_OPCODE(Opcode, ...) \ 471cb0ef41Sopenharmony_ci bool Is##Opcode() const { return opcode() == IrOpcode::k##Opcode; } 481cb0ef41Sopenharmony_ci ALL_OP_LIST(DEFINE_IS_OPCODE) 491cb0ef41Sopenharmony_ci#undef DEFINE_IS_OPCODE 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci private: 521cb0ef41Sopenharmony_ci Node* node_; 531cb0ef41Sopenharmony_ci}; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ciinline Node* SkipValueIdentities(Node* node) { 561cb0ef41Sopenharmony_ci#ifdef DEBUG 571cb0ef41Sopenharmony_ci bool seen_fold_constant = false; 581cb0ef41Sopenharmony_ci#endif 591cb0ef41Sopenharmony_ci do { 601cb0ef41Sopenharmony_ci#ifdef DEBUG 611cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kFoldConstant) { 621cb0ef41Sopenharmony_ci DCHECK(!seen_fold_constant); 631cb0ef41Sopenharmony_ci seen_fold_constant = true; 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci#endif 661cb0ef41Sopenharmony_ci } while (NodeProperties::IsValueIdentity(node, &node)); 671cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(node); 681cb0ef41Sopenharmony_ci return node; 691cb0ef41Sopenharmony_ci} 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci// A pattern matcher for abitrary value constants. 721cb0ef41Sopenharmony_ci// 731cb0ef41Sopenharmony_ci// Note that value identities on the input node are skipped when matching. The 741cb0ef41Sopenharmony_ci// resolved value may not be a parameter of the input node. The node() method 751cb0ef41Sopenharmony_ci// returns the unmodified input node. This is by design, as reducers may wish to 761cb0ef41Sopenharmony_ci// match value constants but delay reducing the node until a later phase. For 771cb0ef41Sopenharmony_ci// example, binary operator reducers may opt to keep FoldConstant operands while 781cb0ef41Sopenharmony_ci// applying a reduction that match on the constant value of the FoldConstant. 791cb0ef41Sopenharmony_citemplate <typename T, IrOpcode::Value kOpcode> 801cb0ef41Sopenharmony_cistruct ValueMatcher : public NodeMatcher { 811cb0ef41Sopenharmony_ci using ValueType = T; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci explicit ValueMatcher(Node* node) 841cb0ef41Sopenharmony_ci : NodeMatcher(node), resolved_value_(), has_resolved_value_(false) { 851cb0ef41Sopenharmony_ci node = SkipValueIdentities(node); 861cb0ef41Sopenharmony_ci has_resolved_value_ = node->opcode() == kOpcode; 871cb0ef41Sopenharmony_ci if (has_resolved_value_) { 881cb0ef41Sopenharmony_ci resolved_value_ = OpParameter<T>(node->op()); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci bool HasResolvedValue() const { return has_resolved_value_; } 931cb0ef41Sopenharmony_ci const T& ResolvedValue() const { 941cb0ef41Sopenharmony_ci CHECK(HasResolvedValue()); 951cb0ef41Sopenharmony_ci return resolved_value_; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci private: 991cb0ef41Sopenharmony_ci T resolved_value_; 1001cb0ef41Sopenharmony_ci bool has_resolved_value_; 1011cb0ef41Sopenharmony_ci}; 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_citemplate <> 1041cb0ef41Sopenharmony_ciinline ValueMatcher<uint32_t, IrOpcode::kInt32Constant>::ValueMatcher( 1051cb0ef41Sopenharmony_ci Node* node) 1061cb0ef41Sopenharmony_ci : NodeMatcher(node), resolved_value_(), has_resolved_value_(false) { 1071cb0ef41Sopenharmony_ci node = SkipValueIdentities(node); 1081cb0ef41Sopenharmony_ci has_resolved_value_ = node->opcode() == IrOpcode::kInt32Constant; 1091cb0ef41Sopenharmony_ci if (has_resolved_value_) { 1101cb0ef41Sopenharmony_ci resolved_value_ = static_cast<uint32_t>(OpParameter<int32_t>(node->op())); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_citemplate <> 1151cb0ef41Sopenharmony_ciinline ValueMatcher<int64_t, IrOpcode::kInt64Constant>::ValueMatcher(Node* node) 1161cb0ef41Sopenharmony_ci : NodeMatcher(node), resolved_value_(), has_resolved_value_(false) { 1171cb0ef41Sopenharmony_ci node = SkipValueIdentities(node); 1181cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kInt32Constant) { 1191cb0ef41Sopenharmony_ci resolved_value_ = OpParameter<int32_t>(node->op()); 1201cb0ef41Sopenharmony_ci has_resolved_value_ = true; 1211cb0ef41Sopenharmony_ci } else if (node->opcode() == IrOpcode::kInt64Constant) { 1221cb0ef41Sopenharmony_ci resolved_value_ = OpParameter<int64_t>(node->op()); 1231cb0ef41Sopenharmony_ci has_resolved_value_ = true; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_citemplate <> 1281cb0ef41Sopenharmony_ciinline ValueMatcher<uint64_t, IrOpcode::kInt64Constant>::ValueMatcher( 1291cb0ef41Sopenharmony_ci Node* node) 1301cb0ef41Sopenharmony_ci : NodeMatcher(node), resolved_value_(), has_resolved_value_(false) { 1311cb0ef41Sopenharmony_ci node = SkipValueIdentities(node); 1321cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kInt32Constant) { 1331cb0ef41Sopenharmony_ci resolved_value_ = static_cast<uint32_t>(OpParameter<int32_t>(node->op())); 1341cb0ef41Sopenharmony_ci has_resolved_value_ = true; 1351cb0ef41Sopenharmony_ci } else if (node->opcode() == IrOpcode::kInt64Constant) { 1361cb0ef41Sopenharmony_ci resolved_value_ = static_cast<uint64_t>(OpParameter<int64_t>(node->op())); 1371cb0ef41Sopenharmony_ci has_resolved_value_ = true; 1381cb0ef41Sopenharmony_ci } 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci// A pattern matcher for integer constants. 1421cb0ef41Sopenharmony_citemplate <typename T, IrOpcode::Value kOpcode> 1431cb0ef41Sopenharmony_cistruct IntMatcher final : public ValueMatcher<T, kOpcode> { 1441cb0ef41Sopenharmony_ci explicit IntMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci bool Is(const T& value) const { 1471cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() == value; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci bool IsInRange(const T& low, const T& high) const { 1501cb0ef41Sopenharmony_ci return this->HasResolvedValue() && 1511cb0ef41Sopenharmony_ci base::IsInRange(this->ResolvedValue(), low, high); 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci bool IsMultipleOf(T n) const { 1541cb0ef41Sopenharmony_ci return this->HasResolvedValue() && (this->ResolvedValue() % n) == 0; 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci bool IsPowerOf2() const { 1571cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() > 0 && 1581cb0ef41Sopenharmony_ci (this->ResolvedValue() & (this->ResolvedValue() - 1)) == 0; 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci bool IsNegativePowerOf2() const { 1611cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() < 0 && 1621cb0ef41Sopenharmony_ci ((this->ResolvedValue() == std::numeric_limits<T>::min()) || 1631cb0ef41Sopenharmony_ci (-this->ResolvedValue() & (-this->ResolvedValue() - 1)) == 0); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci bool IsNegative() const { 1661cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() < 0; 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci}; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ciusing Int32Matcher = IntMatcher<int32_t, IrOpcode::kInt32Constant>; 1711cb0ef41Sopenharmony_ciusing Uint32Matcher = IntMatcher<uint32_t, IrOpcode::kInt32Constant>; 1721cb0ef41Sopenharmony_ciusing Int64Matcher = IntMatcher<int64_t, IrOpcode::kInt64Constant>; 1731cb0ef41Sopenharmony_ciusing Uint64Matcher = IntMatcher<uint64_t, IrOpcode::kInt64Constant>; 1741cb0ef41Sopenharmony_ciusing V128ConstMatcher = 1751cb0ef41Sopenharmony_ci ValueMatcher<S128ImmediateParameter, IrOpcode::kS128Const>; 1761cb0ef41Sopenharmony_ci#if V8_HOST_ARCH_32_BIT 1771cb0ef41Sopenharmony_ciusing IntPtrMatcher = Int32Matcher; 1781cb0ef41Sopenharmony_ciusing UintPtrMatcher = Uint32Matcher; 1791cb0ef41Sopenharmony_ci#else 1801cb0ef41Sopenharmony_ciusing IntPtrMatcher = Int64Matcher; 1811cb0ef41Sopenharmony_ciusing UintPtrMatcher = Uint64Matcher; 1821cb0ef41Sopenharmony_ci#endif 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci// A pattern matcher for floating point constants. 1861cb0ef41Sopenharmony_citemplate <typename T, IrOpcode::Value kOpcode> 1871cb0ef41Sopenharmony_cistruct FloatMatcher final : public ValueMatcher<T, kOpcode> { 1881cb0ef41Sopenharmony_ci explicit FloatMatcher(Node* node) : ValueMatcher<T, kOpcode>(node) {} 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci bool Is(const T& value) const { 1911cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() == value; 1921cb0ef41Sopenharmony_ci } 1931cb0ef41Sopenharmony_ci bool IsInRange(const T& low, const T& high) const { 1941cb0ef41Sopenharmony_ci return this->HasResolvedValue() && low <= this->ResolvedValue() && 1951cb0ef41Sopenharmony_ci this->ResolvedValue() <= high; 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci bool IsMinusZero() const { 1981cb0ef41Sopenharmony_ci return this->Is(0.0) && std::signbit(this->ResolvedValue()); 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci bool IsNegative() const { 2011cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() < 0.0; 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci bool IsNaN() const { 2041cb0ef41Sopenharmony_ci return this->HasResolvedValue() && std::isnan(this->ResolvedValue()); 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci bool IsZero() const { 2071cb0ef41Sopenharmony_ci return this->Is(0.0) && !std::signbit(this->ResolvedValue()); 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci bool IsNormal() const { 2101cb0ef41Sopenharmony_ci return this->HasResolvedValue() && std::isnormal(this->ResolvedValue()); 2111cb0ef41Sopenharmony_ci } 2121cb0ef41Sopenharmony_ci bool IsInteger() const { 2131cb0ef41Sopenharmony_ci return this->HasResolvedValue() && 2141cb0ef41Sopenharmony_ci std::nearbyint(this->ResolvedValue()) == this->ResolvedValue(); 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci bool IsPositiveOrNegativePowerOf2() const { 2171cb0ef41Sopenharmony_ci if (!this->HasResolvedValue() || (this->ResolvedValue() == 0.0)) { 2181cb0ef41Sopenharmony_ci return false; 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci base::Double value = base::Double(this->ResolvedValue()); 2211cb0ef41Sopenharmony_ci return !value.IsInfinite() && base::bits::IsPowerOfTwo(value.Significand()); 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci}; 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ciusing Float32Matcher = FloatMatcher<float, IrOpcode::kFloat32Constant>; 2261cb0ef41Sopenharmony_ciusing Float64Matcher = FloatMatcher<double, IrOpcode::kFloat64Constant>; 2271cb0ef41Sopenharmony_ciusing NumberMatcher = FloatMatcher<double, IrOpcode::kNumberConstant>; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci// A pattern matcher for heap object constants. 2301cb0ef41Sopenharmony_citemplate <IrOpcode::Value kHeapConstantOpcode> 2311cb0ef41Sopenharmony_cistruct HeapObjectMatcherImpl final 2321cb0ef41Sopenharmony_ci : public ValueMatcher<Handle<HeapObject>, kHeapConstantOpcode> { 2331cb0ef41Sopenharmony_ci explicit HeapObjectMatcherImpl(Node* node) 2341cb0ef41Sopenharmony_ci : ValueMatcher<Handle<HeapObject>, kHeapConstantOpcode>(node) {} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci bool Is(Handle<HeapObject> const& value) const { 2371cb0ef41Sopenharmony_ci return this->HasResolvedValue() && 2381cb0ef41Sopenharmony_ci this->ResolvedValue().address() == value.address(); 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci HeapObjectRef Ref(JSHeapBroker* broker) const { 2421cb0ef41Sopenharmony_ci // TODO(jgruber,chromium:1209798): Using kAssumeMemoryFence works around 2431cb0ef41Sopenharmony_ci // the fact that the graph stores handles (and not refs). The assumption is 2441cb0ef41Sopenharmony_ci // that any handle inserted into the graph is safe to read; but we don't 2451cb0ef41Sopenharmony_ci // preserve the reason why it is safe to read. Thus we must over-approximate 2461cb0ef41Sopenharmony_ci // here and assume the existence of a memory fence. In the future, we should 2471cb0ef41Sopenharmony_ci // consider having the graph store ObjectRefs or ObjectData pointer instead, 2481cb0ef41Sopenharmony_ci // which would make new ref construction here unnecessary. 2491cb0ef41Sopenharmony_ci return MakeRefAssumeMemoryFence(broker, this->ResolvedValue()); 2501cb0ef41Sopenharmony_ci } 2511cb0ef41Sopenharmony_ci}; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ciusing HeapObjectMatcher = HeapObjectMatcherImpl<IrOpcode::kHeapConstant>; 2541cb0ef41Sopenharmony_ciusing CompressedHeapObjectMatcher = 2551cb0ef41Sopenharmony_ci HeapObjectMatcherImpl<IrOpcode::kCompressedHeapConstant>; 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci// A pattern matcher for external reference constants. 2581cb0ef41Sopenharmony_cistruct ExternalReferenceMatcher final 2591cb0ef41Sopenharmony_ci : public ValueMatcher<ExternalReference, IrOpcode::kExternalConstant> { 2601cb0ef41Sopenharmony_ci explicit ExternalReferenceMatcher(Node* node) 2611cb0ef41Sopenharmony_ci : ValueMatcher<ExternalReference, IrOpcode::kExternalConstant>(node) {} 2621cb0ef41Sopenharmony_ci bool Is(const ExternalReference& value) const { 2631cb0ef41Sopenharmony_ci return this->HasResolvedValue() && this->ResolvedValue() == value; 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci}; 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci// For shorter pattern matching code, this struct matches the inputs to 2691cb0ef41Sopenharmony_ci// machine-level load operations. 2701cb0ef41Sopenharmony_citemplate <typename Object> 2711cb0ef41Sopenharmony_cistruct LoadMatcher : public NodeMatcher { 2721cb0ef41Sopenharmony_ci explicit LoadMatcher(Node* node) 2731cb0ef41Sopenharmony_ci : NodeMatcher(node), object_(InputAt(0)), index_(InputAt(1)) {} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci using ObjectMatcher = Object; 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci Object const& object() const { return object_; } 2781cb0ef41Sopenharmony_ci IntPtrMatcher const& index() const { return index_; } 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci private: 2811cb0ef41Sopenharmony_ci Object const object_; 2821cb0ef41Sopenharmony_ci IntPtrMatcher const index_; 2831cb0ef41Sopenharmony_ci}; 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci// For shorter pattern matching code, this struct matches both the left and 2871cb0ef41Sopenharmony_ci// right hand sides of a binary operation and can put constants on the right 2881cb0ef41Sopenharmony_ci// if they appear on the left hand side of a commutative operation. 2891cb0ef41Sopenharmony_citemplate <typename Left, typename Right> 2901cb0ef41Sopenharmony_cistruct BinopMatcher : public NodeMatcher { 2911cb0ef41Sopenharmony_ci explicit BinopMatcher(Node* node) 2921cb0ef41Sopenharmony_ci : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { 2931cb0ef41Sopenharmony_ci if (HasProperty(Operator::kCommutative)) PutConstantOnRight(); 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci BinopMatcher(Node* node, bool allow_input_swap) 2961cb0ef41Sopenharmony_ci : NodeMatcher(node), left_(InputAt(0)), right_(InputAt(1)) { 2971cb0ef41Sopenharmony_ci if (allow_input_swap) PutConstantOnRight(); 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci using LeftMatcher = Left; 3011cb0ef41Sopenharmony_ci using RightMatcher = Right; 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci const Left& left() const { return left_; } 3041cb0ef41Sopenharmony_ci const Right& right() const { return right_; } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci bool IsFoldable() const { 3071cb0ef41Sopenharmony_ci return left().HasResolvedValue() && right().HasResolvedValue(); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci bool LeftEqualsRight() const { return left().node() == right().node(); } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci bool OwnsInput(Node* input) { 3121cb0ef41Sopenharmony_ci for (Node* use : input->uses()) { 3131cb0ef41Sopenharmony_ci if (use != node()) { 3141cb0ef41Sopenharmony_ci return false; 3151cb0ef41Sopenharmony_ci } 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci return true; 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci protected: 3211cb0ef41Sopenharmony_ci void SwapInputs() { 3221cb0ef41Sopenharmony_ci std::swap(left_, right_); 3231cb0ef41Sopenharmony_ci // TODO(turbofan): This modification should notify the reducers using 3241cb0ef41Sopenharmony_ci // BinopMatcher. Alternatively, all reducers (especially value numbering) 3251cb0ef41Sopenharmony_ci // could ignore the ordering for commutative binops. 3261cb0ef41Sopenharmony_ci node()->ReplaceInput(0, left().node()); 3271cb0ef41Sopenharmony_ci node()->ReplaceInput(1, right().node()); 3281cb0ef41Sopenharmony_ci } 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci private: 3311cb0ef41Sopenharmony_ci void PutConstantOnRight() { 3321cb0ef41Sopenharmony_ci if (left().HasResolvedValue() && !right().HasResolvedValue()) { 3331cb0ef41Sopenharmony_ci SwapInputs(); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci Left left_; 3381cb0ef41Sopenharmony_ci Right right_; 3391cb0ef41Sopenharmony_ci}; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ciusing Int32BinopMatcher = BinopMatcher<Int32Matcher, Int32Matcher>; 3421cb0ef41Sopenharmony_ciusing Uint32BinopMatcher = BinopMatcher<Uint32Matcher, Uint32Matcher>; 3431cb0ef41Sopenharmony_ciusing Int64BinopMatcher = BinopMatcher<Int64Matcher, Int64Matcher>; 3441cb0ef41Sopenharmony_ciusing Uint64BinopMatcher = BinopMatcher<Uint64Matcher, Uint64Matcher>; 3451cb0ef41Sopenharmony_ciusing IntPtrBinopMatcher = BinopMatcher<IntPtrMatcher, IntPtrMatcher>; 3461cb0ef41Sopenharmony_ciusing UintPtrBinopMatcher = BinopMatcher<UintPtrMatcher, UintPtrMatcher>; 3471cb0ef41Sopenharmony_ciusing Float32BinopMatcher = BinopMatcher<Float32Matcher, Float32Matcher>; 3481cb0ef41Sopenharmony_ciusing Float64BinopMatcher = BinopMatcher<Float64Matcher, Float64Matcher>; 3491cb0ef41Sopenharmony_ciusing NumberBinopMatcher = BinopMatcher<NumberMatcher, NumberMatcher>; 3501cb0ef41Sopenharmony_ciusing HeapObjectBinopMatcher = 3511cb0ef41Sopenharmony_ci BinopMatcher<HeapObjectMatcher, HeapObjectMatcher>; 3521cb0ef41Sopenharmony_ciusing CompressedHeapObjectBinopMatcher = 3531cb0ef41Sopenharmony_ci BinopMatcher<CompressedHeapObjectMatcher, CompressedHeapObjectMatcher>; 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_citemplate <class BinopMatcher, IrOpcode::Value kMulOpcode, 3561cb0ef41Sopenharmony_ci IrOpcode::Value kShiftOpcode> 3571cb0ef41Sopenharmony_cistruct ScaleMatcher { 3581cb0ef41Sopenharmony_ci explicit ScaleMatcher(Node* node, bool allow_power_of_two_plus_one = false) 3591cb0ef41Sopenharmony_ci : scale_(-1), power_of_two_plus_one_(false) { 3601cb0ef41Sopenharmony_ci if (node->InputCount() < 2) return; 3611cb0ef41Sopenharmony_ci BinopMatcher m(node); 3621cb0ef41Sopenharmony_ci if (node->opcode() == kShiftOpcode) { 3631cb0ef41Sopenharmony_ci if (m.right().HasResolvedValue()) { 3641cb0ef41Sopenharmony_ci typename BinopMatcher::RightMatcher::ValueType value = 3651cb0ef41Sopenharmony_ci m.right().ResolvedValue(); 3661cb0ef41Sopenharmony_ci if (value >= 0 && value <= 3) { 3671cb0ef41Sopenharmony_ci scale_ = static_cast<int>(value); 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci } else if (node->opcode() == kMulOpcode) { 3711cb0ef41Sopenharmony_ci if (m.right().HasResolvedValue()) { 3721cb0ef41Sopenharmony_ci typename BinopMatcher::RightMatcher::ValueType value = 3731cb0ef41Sopenharmony_ci m.right().ResolvedValue(); 3741cb0ef41Sopenharmony_ci if (value == 1) { 3751cb0ef41Sopenharmony_ci scale_ = 0; 3761cb0ef41Sopenharmony_ci } else if (value == 2) { 3771cb0ef41Sopenharmony_ci scale_ = 1; 3781cb0ef41Sopenharmony_ci } else if (value == 4) { 3791cb0ef41Sopenharmony_ci scale_ = 2; 3801cb0ef41Sopenharmony_ci } else if (value == 8) { 3811cb0ef41Sopenharmony_ci scale_ = 3; 3821cb0ef41Sopenharmony_ci } else if (allow_power_of_two_plus_one) { 3831cb0ef41Sopenharmony_ci if (value == 3) { 3841cb0ef41Sopenharmony_ci scale_ = 1; 3851cb0ef41Sopenharmony_ci power_of_two_plus_one_ = true; 3861cb0ef41Sopenharmony_ci } else if (value == 5) { 3871cb0ef41Sopenharmony_ci scale_ = 2; 3881cb0ef41Sopenharmony_ci power_of_two_plus_one_ = true; 3891cb0ef41Sopenharmony_ci } else if (value == 9) { 3901cb0ef41Sopenharmony_ci scale_ = 3; 3911cb0ef41Sopenharmony_ci power_of_two_plus_one_ = true; 3921cb0ef41Sopenharmony_ci } 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci bool matches() const { return scale_ != -1; } 3991cb0ef41Sopenharmony_ci int scale() const { return scale_; } 4001cb0ef41Sopenharmony_ci bool power_of_two_plus_one() const { return power_of_two_plus_one_; } 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci private: 4031cb0ef41Sopenharmony_ci int scale_; 4041cb0ef41Sopenharmony_ci bool power_of_two_plus_one_; 4051cb0ef41Sopenharmony_ci}; 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ciusing Int32ScaleMatcher = 4081cb0ef41Sopenharmony_ci ScaleMatcher<Int32BinopMatcher, IrOpcode::kInt32Mul, IrOpcode::kWord32Shl>; 4091cb0ef41Sopenharmony_ciusing Int64ScaleMatcher = 4101cb0ef41Sopenharmony_ci ScaleMatcher<Int64BinopMatcher, IrOpcode::kInt64Mul, IrOpcode::kWord64Shl>; 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_citemplate <class BinopMatcher, IrOpcode::Value AddOpcode, 4131cb0ef41Sopenharmony_ci IrOpcode::Value SubOpcode, IrOpcode::Value kMulOpcode, 4141cb0ef41Sopenharmony_ci IrOpcode::Value kShiftOpcode> 4151cb0ef41Sopenharmony_cistruct AddMatcher : public BinopMatcher { 4161cb0ef41Sopenharmony_ci static const IrOpcode::Value kAddOpcode = AddOpcode; 4171cb0ef41Sopenharmony_ci static const IrOpcode::Value kSubOpcode = SubOpcode; 4181cb0ef41Sopenharmony_ci using Matcher = ScaleMatcher<BinopMatcher, kMulOpcode, kShiftOpcode>; 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci AddMatcher(Node* node, bool allow_input_swap) 4211cb0ef41Sopenharmony_ci : BinopMatcher(node, allow_input_swap), 4221cb0ef41Sopenharmony_ci scale_(-1), 4231cb0ef41Sopenharmony_ci power_of_two_plus_one_(false) { 4241cb0ef41Sopenharmony_ci Initialize(node, allow_input_swap); 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci explicit AddMatcher(Node* node) 4271cb0ef41Sopenharmony_ci : BinopMatcher(node, node->op()->HasProperty(Operator::kCommutative)), 4281cb0ef41Sopenharmony_ci scale_(-1), 4291cb0ef41Sopenharmony_ci power_of_two_plus_one_(false) { 4301cb0ef41Sopenharmony_ci Initialize(node, node->op()->HasProperty(Operator::kCommutative)); 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci bool HasIndexInput() const { return scale_ != -1; } 4341cb0ef41Sopenharmony_ci Node* IndexInput() const { 4351cb0ef41Sopenharmony_ci DCHECK(HasIndexInput()); 4361cb0ef41Sopenharmony_ci return this->left().node()->InputAt(0); 4371cb0ef41Sopenharmony_ci } 4381cb0ef41Sopenharmony_ci int scale() const { 4391cb0ef41Sopenharmony_ci DCHECK(HasIndexInput()); 4401cb0ef41Sopenharmony_ci return scale_; 4411cb0ef41Sopenharmony_ci } 4421cb0ef41Sopenharmony_ci bool power_of_two_plus_one() const { return power_of_two_plus_one_; } 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci private: 4451cb0ef41Sopenharmony_ci void Initialize(Node* node, bool allow_input_swap) { 4461cb0ef41Sopenharmony_ci Matcher left_matcher(this->left().node(), true); 4471cb0ef41Sopenharmony_ci if (left_matcher.matches()) { 4481cb0ef41Sopenharmony_ci scale_ = left_matcher.scale(); 4491cb0ef41Sopenharmony_ci power_of_two_plus_one_ = left_matcher.power_of_two_plus_one(); 4501cb0ef41Sopenharmony_ci return; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci if (!allow_input_swap) { 4541cb0ef41Sopenharmony_ci return; 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci Matcher right_matcher(this->right().node(), true); 4581cb0ef41Sopenharmony_ci if (right_matcher.matches()) { 4591cb0ef41Sopenharmony_ci scale_ = right_matcher.scale(); 4601cb0ef41Sopenharmony_ci power_of_two_plus_one_ = right_matcher.power_of_two_plus_one(); 4611cb0ef41Sopenharmony_ci this->SwapInputs(); 4621cb0ef41Sopenharmony_ci return; 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci if ((this->left().opcode() != kSubOpcode && 4661cb0ef41Sopenharmony_ci this->left().opcode() != kAddOpcode) && 4671cb0ef41Sopenharmony_ci (this->right().opcode() == kAddOpcode || 4681cb0ef41Sopenharmony_ci this->right().opcode() == kSubOpcode)) { 4691cb0ef41Sopenharmony_ci this->SwapInputs(); 4701cb0ef41Sopenharmony_ci } 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci int scale_; 4741cb0ef41Sopenharmony_ci bool power_of_two_plus_one_; 4751cb0ef41Sopenharmony_ci}; 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ciusing Int32AddMatcher = 4781cb0ef41Sopenharmony_ci AddMatcher<Int32BinopMatcher, IrOpcode::kInt32Add, IrOpcode::kInt32Sub, 4791cb0ef41Sopenharmony_ci IrOpcode::kInt32Mul, IrOpcode::kWord32Shl>; 4801cb0ef41Sopenharmony_ciusing Int64AddMatcher = 4811cb0ef41Sopenharmony_ci AddMatcher<Int64BinopMatcher, IrOpcode::kInt64Add, IrOpcode::kInt64Sub, 4821cb0ef41Sopenharmony_ci IrOpcode::kInt64Mul, IrOpcode::kWord64Shl>; 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_cienum DisplacementMode { kPositiveDisplacement, kNegativeDisplacement }; 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_cienum class AddressOption : uint8_t { 4871cb0ef41Sopenharmony_ci kAllowNone = 0u, 4881cb0ef41Sopenharmony_ci kAllowInputSwap = 1u << 0, 4891cb0ef41Sopenharmony_ci kAllowScale = 1u << 1, 4901cb0ef41Sopenharmony_ci kAllowAll = kAllowInputSwap | kAllowScale 4911cb0ef41Sopenharmony_ci}; 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ciusing AddressOptions = base::Flags<AddressOption, uint8_t>; 4941cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(AddressOptions) 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_citemplate <class AddMatcher> 4971cb0ef41Sopenharmony_cistruct BaseWithIndexAndDisplacementMatcher { 4981cb0ef41Sopenharmony_ci BaseWithIndexAndDisplacementMatcher(Node* node, AddressOptions options) 4991cb0ef41Sopenharmony_ci : matches_(false), 5001cb0ef41Sopenharmony_ci index_(nullptr), 5011cb0ef41Sopenharmony_ci scale_(0), 5021cb0ef41Sopenharmony_ci base_(nullptr), 5031cb0ef41Sopenharmony_ci displacement_(nullptr), 5041cb0ef41Sopenharmony_ci displacement_mode_(kPositiveDisplacement) { 5051cb0ef41Sopenharmony_ci Initialize(node, options); 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci explicit BaseWithIndexAndDisplacementMatcher(Node* node) 5091cb0ef41Sopenharmony_ci : matches_(false), 5101cb0ef41Sopenharmony_ci index_(nullptr), 5111cb0ef41Sopenharmony_ci scale_(0), 5121cb0ef41Sopenharmony_ci base_(nullptr), 5131cb0ef41Sopenharmony_ci displacement_(nullptr), 5141cb0ef41Sopenharmony_ci displacement_mode_(kPositiveDisplacement) { 5151cb0ef41Sopenharmony_ci Initialize(node, AddressOption::kAllowScale | 5161cb0ef41Sopenharmony_ci (node->op()->HasProperty(Operator::kCommutative) 5171cb0ef41Sopenharmony_ci ? AddressOption::kAllowInputSwap 5181cb0ef41Sopenharmony_ci : AddressOption::kAllowNone)); 5191cb0ef41Sopenharmony_ci } 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci bool matches() const { return matches_; } 5221cb0ef41Sopenharmony_ci Node* index() const { return index_; } 5231cb0ef41Sopenharmony_ci int scale() const { return scale_; } 5241cb0ef41Sopenharmony_ci Node* base() const { return base_; } 5251cb0ef41Sopenharmony_ci Node* displacement() const { return displacement_; } 5261cb0ef41Sopenharmony_ci DisplacementMode displacement_mode() const { return displacement_mode_; } 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci private: 5291cb0ef41Sopenharmony_ci bool matches_; 5301cb0ef41Sopenharmony_ci Node* index_; 5311cb0ef41Sopenharmony_ci int scale_; 5321cb0ef41Sopenharmony_ci Node* base_; 5331cb0ef41Sopenharmony_ci Node* displacement_; 5341cb0ef41Sopenharmony_ci DisplacementMode displacement_mode_; 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci void Initialize(Node* node, AddressOptions options) { 5371cb0ef41Sopenharmony_ci // The BaseWithIndexAndDisplacementMatcher canonicalizes the order of 5381cb0ef41Sopenharmony_ci // displacements and scale factors that are used as inputs, so instead of 5391cb0ef41Sopenharmony_ci // enumerating all possible patterns by brute force, checking for node 5401cb0ef41Sopenharmony_ci // clusters using the following templates in the following order suffices to 5411cb0ef41Sopenharmony_ci // find all of the interesting cases (S = index * scale, B = base input, D = 5421cb0ef41Sopenharmony_ci // displacement input): 5431cb0ef41Sopenharmony_ci // (S + (B + D)) 5441cb0ef41Sopenharmony_ci // (S + (B + B)) 5451cb0ef41Sopenharmony_ci // (S + D) 5461cb0ef41Sopenharmony_ci // (S + B) 5471cb0ef41Sopenharmony_ci // ((S + D) + B) 5481cb0ef41Sopenharmony_ci // ((S + B) + D) 5491cb0ef41Sopenharmony_ci // ((B + D) + B) 5501cb0ef41Sopenharmony_ci // ((B + B) + D) 5511cb0ef41Sopenharmony_ci // (B + D) 5521cb0ef41Sopenharmony_ci // (B + B) 5531cb0ef41Sopenharmony_ci if (node->InputCount() < 2) return; 5541cb0ef41Sopenharmony_ci AddMatcher m(node, options & AddressOption::kAllowInputSwap); 5551cb0ef41Sopenharmony_ci Node* left = m.left().node(); 5561cb0ef41Sopenharmony_ci Node* right = m.right().node(); 5571cb0ef41Sopenharmony_ci Node* displacement = nullptr; 5581cb0ef41Sopenharmony_ci Node* base = nullptr; 5591cb0ef41Sopenharmony_ci Node* index = nullptr; 5601cb0ef41Sopenharmony_ci Node* scale_expression = nullptr; 5611cb0ef41Sopenharmony_ci bool power_of_two_plus_one = false; 5621cb0ef41Sopenharmony_ci DisplacementMode displacement_mode = kPositiveDisplacement; 5631cb0ef41Sopenharmony_ci int scale = 0; 5641cb0ef41Sopenharmony_ci if (m.HasIndexInput() && OwnedByAddressingOperand(left)) { 5651cb0ef41Sopenharmony_ci index = m.IndexInput(); 5661cb0ef41Sopenharmony_ci scale = m.scale(); 5671cb0ef41Sopenharmony_ci scale_expression = left; 5681cb0ef41Sopenharmony_ci power_of_two_plus_one = m.power_of_two_plus_one(); 5691cb0ef41Sopenharmony_ci bool match_found = false; 5701cb0ef41Sopenharmony_ci if (right->opcode() == AddMatcher::kSubOpcode && 5711cb0ef41Sopenharmony_ci OwnedByAddressingOperand(right)) { 5721cb0ef41Sopenharmony_ci AddMatcher right_matcher(right); 5731cb0ef41Sopenharmony_ci if (right_matcher.right().HasResolvedValue()) { 5741cb0ef41Sopenharmony_ci // (S + (B - D)) 5751cb0ef41Sopenharmony_ci base = right_matcher.left().node(); 5761cb0ef41Sopenharmony_ci displacement = right_matcher.right().node(); 5771cb0ef41Sopenharmony_ci displacement_mode = kNegativeDisplacement; 5781cb0ef41Sopenharmony_ci match_found = true; 5791cb0ef41Sopenharmony_ci } 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci if (!match_found) { 5821cb0ef41Sopenharmony_ci if (right->opcode() == AddMatcher::kAddOpcode && 5831cb0ef41Sopenharmony_ci OwnedByAddressingOperand(right)) { 5841cb0ef41Sopenharmony_ci AddMatcher right_matcher(right); 5851cb0ef41Sopenharmony_ci if (right_matcher.right().HasResolvedValue()) { 5861cb0ef41Sopenharmony_ci // (S + (B + D)) 5871cb0ef41Sopenharmony_ci base = right_matcher.left().node(); 5881cb0ef41Sopenharmony_ci displacement = right_matcher.right().node(); 5891cb0ef41Sopenharmony_ci } else { 5901cb0ef41Sopenharmony_ci // (S + (B + B)) 5911cb0ef41Sopenharmony_ci base = right; 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci } else if (m.right().HasResolvedValue()) { 5941cb0ef41Sopenharmony_ci // (S + D) 5951cb0ef41Sopenharmony_ci displacement = right; 5961cb0ef41Sopenharmony_ci } else { 5971cb0ef41Sopenharmony_ci // (S + B) 5981cb0ef41Sopenharmony_ci base = right; 5991cb0ef41Sopenharmony_ci } 6001cb0ef41Sopenharmony_ci } 6011cb0ef41Sopenharmony_ci } else { 6021cb0ef41Sopenharmony_ci bool match_found = false; 6031cb0ef41Sopenharmony_ci if (left->opcode() == AddMatcher::kSubOpcode && 6041cb0ef41Sopenharmony_ci OwnedByAddressingOperand(left)) { 6051cb0ef41Sopenharmony_ci AddMatcher left_matcher(left); 6061cb0ef41Sopenharmony_ci Node* left_left = left_matcher.left().node(); 6071cb0ef41Sopenharmony_ci Node* left_right = left_matcher.right().node(); 6081cb0ef41Sopenharmony_ci if (left_matcher.right().HasResolvedValue()) { 6091cb0ef41Sopenharmony_ci if (left_matcher.HasIndexInput() && 6101cb0ef41Sopenharmony_ci OwnedByAddressingOperand(left_left)) { 6111cb0ef41Sopenharmony_ci // ((S - D) + B) 6121cb0ef41Sopenharmony_ci index = left_matcher.IndexInput(); 6131cb0ef41Sopenharmony_ci scale = left_matcher.scale(); 6141cb0ef41Sopenharmony_ci scale_expression = left_left; 6151cb0ef41Sopenharmony_ci power_of_two_plus_one = left_matcher.power_of_two_plus_one(); 6161cb0ef41Sopenharmony_ci displacement = left_right; 6171cb0ef41Sopenharmony_ci displacement_mode = kNegativeDisplacement; 6181cb0ef41Sopenharmony_ci base = right; 6191cb0ef41Sopenharmony_ci } else { 6201cb0ef41Sopenharmony_ci // ((B - D) + B) 6211cb0ef41Sopenharmony_ci index = left_left; 6221cb0ef41Sopenharmony_ci displacement = left_right; 6231cb0ef41Sopenharmony_ci displacement_mode = kNegativeDisplacement; 6241cb0ef41Sopenharmony_ci base = right; 6251cb0ef41Sopenharmony_ci } 6261cb0ef41Sopenharmony_ci match_found = true; 6271cb0ef41Sopenharmony_ci } 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci if (!match_found) { 6301cb0ef41Sopenharmony_ci if (left->opcode() == AddMatcher::kAddOpcode && 6311cb0ef41Sopenharmony_ci OwnedByAddressingOperand(left)) { 6321cb0ef41Sopenharmony_ci AddMatcher left_matcher(left); 6331cb0ef41Sopenharmony_ci Node* left_left = left_matcher.left().node(); 6341cb0ef41Sopenharmony_ci Node* left_right = left_matcher.right().node(); 6351cb0ef41Sopenharmony_ci if (left_matcher.HasIndexInput() && 6361cb0ef41Sopenharmony_ci OwnedByAddressingOperand(left_left)) { 6371cb0ef41Sopenharmony_ci if (left_matcher.right().HasResolvedValue()) { 6381cb0ef41Sopenharmony_ci // ((S + D) + B) 6391cb0ef41Sopenharmony_ci index = left_matcher.IndexInput(); 6401cb0ef41Sopenharmony_ci scale = left_matcher.scale(); 6411cb0ef41Sopenharmony_ci scale_expression = left_left; 6421cb0ef41Sopenharmony_ci power_of_two_plus_one = left_matcher.power_of_two_plus_one(); 6431cb0ef41Sopenharmony_ci displacement = left_right; 6441cb0ef41Sopenharmony_ci base = right; 6451cb0ef41Sopenharmony_ci } else if (m.right().HasResolvedValue()) { 6461cb0ef41Sopenharmony_ci if (left->OwnedBy(node)) { 6471cb0ef41Sopenharmony_ci // ((S + B) + D) 6481cb0ef41Sopenharmony_ci index = left_matcher.IndexInput(); 6491cb0ef41Sopenharmony_ci scale = left_matcher.scale(); 6501cb0ef41Sopenharmony_ci scale_expression = left_left; 6511cb0ef41Sopenharmony_ci power_of_two_plus_one = left_matcher.power_of_two_plus_one(); 6521cb0ef41Sopenharmony_ci base = left_right; 6531cb0ef41Sopenharmony_ci displacement = right; 6541cb0ef41Sopenharmony_ci } else { 6551cb0ef41Sopenharmony_ci // (B + D) 6561cb0ef41Sopenharmony_ci base = left; 6571cb0ef41Sopenharmony_ci displacement = right; 6581cb0ef41Sopenharmony_ci } 6591cb0ef41Sopenharmony_ci } else { 6601cb0ef41Sopenharmony_ci // (B + B) 6611cb0ef41Sopenharmony_ci index = left; 6621cb0ef41Sopenharmony_ci base = right; 6631cb0ef41Sopenharmony_ci } 6641cb0ef41Sopenharmony_ci } else { 6651cb0ef41Sopenharmony_ci if (left_matcher.right().HasResolvedValue()) { 6661cb0ef41Sopenharmony_ci // ((B + D) + B) 6671cb0ef41Sopenharmony_ci index = left_left; 6681cb0ef41Sopenharmony_ci displacement = left_right; 6691cb0ef41Sopenharmony_ci base = right; 6701cb0ef41Sopenharmony_ci } else if (m.right().HasResolvedValue()) { 6711cb0ef41Sopenharmony_ci if (left->OwnedBy(node)) { 6721cb0ef41Sopenharmony_ci // ((B + B) + D) 6731cb0ef41Sopenharmony_ci index = left_left; 6741cb0ef41Sopenharmony_ci base = left_right; 6751cb0ef41Sopenharmony_ci displacement = right; 6761cb0ef41Sopenharmony_ci } else { 6771cb0ef41Sopenharmony_ci // (B + D) 6781cb0ef41Sopenharmony_ci base = left; 6791cb0ef41Sopenharmony_ci displacement = right; 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci } else { 6821cb0ef41Sopenharmony_ci // (B + B) 6831cb0ef41Sopenharmony_ci index = left; 6841cb0ef41Sopenharmony_ci base = right; 6851cb0ef41Sopenharmony_ci } 6861cb0ef41Sopenharmony_ci } 6871cb0ef41Sopenharmony_ci } else { 6881cb0ef41Sopenharmony_ci if (m.right().HasResolvedValue()) { 6891cb0ef41Sopenharmony_ci // (B + D) 6901cb0ef41Sopenharmony_ci base = left; 6911cb0ef41Sopenharmony_ci displacement = right; 6921cb0ef41Sopenharmony_ci } else { 6931cb0ef41Sopenharmony_ci // (B + B) 6941cb0ef41Sopenharmony_ci base = left; 6951cb0ef41Sopenharmony_ci index = right; 6961cb0ef41Sopenharmony_ci } 6971cb0ef41Sopenharmony_ci } 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci } 7001cb0ef41Sopenharmony_ci int64_t value = 0; 7011cb0ef41Sopenharmony_ci if (displacement != nullptr) { 7021cb0ef41Sopenharmony_ci switch (displacement->opcode()) { 7031cb0ef41Sopenharmony_ci case IrOpcode::kInt32Constant: { 7041cb0ef41Sopenharmony_ci value = OpParameter<int32_t>(displacement->op()); 7051cb0ef41Sopenharmony_ci break; 7061cb0ef41Sopenharmony_ci } 7071cb0ef41Sopenharmony_ci case IrOpcode::kInt64Constant: { 7081cb0ef41Sopenharmony_ci value = OpParameter<int64_t>(displacement->op()); 7091cb0ef41Sopenharmony_ci break; 7101cb0ef41Sopenharmony_ci } 7111cb0ef41Sopenharmony_ci default: 7121cb0ef41Sopenharmony_ci UNREACHABLE(); 7131cb0ef41Sopenharmony_ci break; 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci if (value == 0) { 7161cb0ef41Sopenharmony_ci displacement = nullptr; 7171cb0ef41Sopenharmony_ci } 7181cb0ef41Sopenharmony_ci } 7191cb0ef41Sopenharmony_ci if (power_of_two_plus_one) { 7201cb0ef41Sopenharmony_ci if (base != nullptr) { 7211cb0ef41Sopenharmony_ci // If the scale requires explicitly using the index as the base, but a 7221cb0ef41Sopenharmony_ci // base is already part of the match, then the (1 << N + 1) scale factor 7231cb0ef41Sopenharmony_ci // can't be folded into the match and the entire index * scale 7241cb0ef41Sopenharmony_ci // calculation must be computed separately. 7251cb0ef41Sopenharmony_ci index = scale_expression; 7261cb0ef41Sopenharmony_ci scale = 0; 7271cb0ef41Sopenharmony_ci } else { 7281cb0ef41Sopenharmony_ci base = index; 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci } 7311cb0ef41Sopenharmony_ci if (!(options & AddressOption::kAllowScale) && scale != 0) { 7321cb0ef41Sopenharmony_ci index = scale_expression; 7331cb0ef41Sopenharmony_ci scale = 0; 7341cb0ef41Sopenharmony_ci } 7351cb0ef41Sopenharmony_ci base_ = base; 7361cb0ef41Sopenharmony_ci displacement_ = displacement; 7371cb0ef41Sopenharmony_ci displacement_mode_ = displacement_mode; 7381cb0ef41Sopenharmony_ci index_ = index; 7391cb0ef41Sopenharmony_ci scale_ = scale; 7401cb0ef41Sopenharmony_ci matches_ = true; 7411cb0ef41Sopenharmony_ci } 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci // Warning: When {node} is used by a Add/Sub instruction, this function does 7441cb0ef41Sopenharmony_ci // not guarantee the Add/Sub will be part of a addressing operand. 7451cb0ef41Sopenharmony_ci static bool OwnedByAddressingOperand(Node* node) { 7461cb0ef41Sopenharmony_ci for (auto use : node->use_edges()) { 7471cb0ef41Sopenharmony_ci Node* from = use.from(); 7481cb0ef41Sopenharmony_ci switch (from->opcode()) { 7491cb0ef41Sopenharmony_ci case IrOpcode::kLoad: 7501cb0ef41Sopenharmony_ci case IrOpcode::kLoadImmutable: 7511cb0ef41Sopenharmony_ci case IrOpcode::kProtectedLoad: 7521cb0ef41Sopenharmony_ci case IrOpcode::kInt32Add: 7531cb0ef41Sopenharmony_ci case IrOpcode::kInt64Add: 7541cb0ef41Sopenharmony_ci // Skip addressing uses. 7551cb0ef41Sopenharmony_ci break; 7561cb0ef41Sopenharmony_ci case IrOpcode::kInt32Sub: 7571cb0ef41Sopenharmony_ci // If the subtrahend is not a constant, it is not an addressing use. 7581cb0ef41Sopenharmony_ci if (from->InputAt(1)->opcode() != IrOpcode::kInt32Constant) 7591cb0ef41Sopenharmony_ci return false; 7601cb0ef41Sopenharmony_ci break; 7611cb0ef41Sopenharmony_ci case IrOpcode::kInt64Sub: 7621cb0ef41Sopenharmony_ci // If the subtrahend is not a constant, it is not an addressing use. 7631cb0ef41Sopenharmony_ci if (from->InputAt(1)->opcode() != IrOpcode::kInt64Constant) 7641cb0ef41Sopenharmony_ci return false; 7651cb0ef41Sopenharmony_ci break; 7661cb0ef41Sopenharmony_ci case IrOpcode::kStore: 7671cb0ef41Sopenharmony_ci case IrOpcode::kProtectedStore: 7681cb0ef41Sopenharmony_ci // If the stored value is this node, it is not an addressing use. 7691cb0ef41Sopenharmony_ci if (from->InputAt(2) == node) return false; 7701cb0ef41Sopenharmony_ci // Otherwise it is used as an address and skipped. 7711cb0ef41Sopenharmony_ci break; 7721cb0ef41Sopenharmony_ci default: 7731cb0ef41Sopenharmony_ci // Non-addressing use found. 7741cb0ef41Sopenharmony_ci return false; 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci } 7771cb0ef41Sopenharmony_ci return true; 7781cb0ef41Sopenharmony_ci } 7791cb0ef41Sopenharmony_ci}; 7801cb0ef41Sopenharmony_ci 7811cb0ef41Sopenharmony_ciusing BaseWithIndexAndDisplacement32Matcher = 7821cb0ef41Sopenharmony_ci BaseWithIndexAndDisplacementMatcher<Int32AddMatcher>; 7831cb0ef41Sopenharmony_ciusing BaseWithIndexAndDisplacement64Matcher = 7841cb0ef41Sopenharmony_ci BaseWithIndexAndDisplacementMatcher<Int64AddMatcher>; 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_cistruct V8_EXPORT_PRIVATE BranchMatcher : public NON_EXPORTED_BASE(NodeMatcher) { 7871cb0ef41Sopenharmony_ci explicit BranchMatcher(Node* branch); 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci bool Matched() const { return if_true_ && if_false_; } 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_ci Node* Branch() const { return node(); } 7921cb0ef41Sopenharmony_ci Node* IfTrue() const { return if_true_; } 7931cb0ef41Sopenharmony_ci Node* IfFalse() const { return if_false_; } 7941cb0ef41Sopenharmony_ci 7951cb0ef41Sopenharmony_ci private: 7961cb0ef41Sopenharmony_ci Node* if_true_; 7971cb0ef41Sopenharmony_ci Node* if_false_; 7981cb0ef41Sopenharmony_ci}; 7991cb0ef41Sopenharmony_ci 8001cb0ef41Sopenharmony_cistruct V8_EXPORT_PRIVATE DiamondMatcher 8011cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(NodeMatcher) { 8021cb0ef41Sopenharmony_ci explicit DiamondMatcher(Node* merge); 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ci bool Matched() const { return branch_; } 8051cb0ef41Sopenharmony_ci bool IfProjectionsAreOwned() const { 8061cb0ef41Sopenharmony_ci return if_true_->OwnedBy(node()) && if_false_->OwnedBy(node()); 8071cb0ef41Sopenharmony_ci } 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci Node* Branch() const { return branch_; } 8101cb0ef41Sopenharmony_ci Node* IfTrue() const { return if_true_; } 8111cb0ef41Sopenharmony_ci Node* IfFalse() const { return if_false_; } 8121cb0ef41Sopenharmony_ci Node* Merge() const { return node(); } 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci Node* TrueInputOf(Node* phi) const { 8151cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); 8161cb0ef41Sopenharmony_ci DCHECK_EQ(3, phi->InputCount()); 8171cb0ef41Sopenharmony_ci DCHECK_EQ(Merge(), phi->InputAt(2)); 8181cb0ef41Sopenharmony_ci return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 0 : 1); 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci 8211cb0ef41Sopenharmony_ci Node* FalseInputOf(Node* phi) const { 8221cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsPhiOpcode(phi->opcode())); 8231cb0ef41Sopenharmony_ci DCHECK_EQ(3, phi->InputCount()); 8241cb0ef41Sopenharmony_ci DCHECK_EQ(Merge(), phi->InputAt(2)); 8251cb0ef41Sopenharmony_ci return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 1 : 0); 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci private: 8291cb0ef41Sopenharmony_ci Node* branch_; 8301cb0ef41Sopenharmony_ci Node* if_true_; 8311cb0ef41Sopenharmony_ci Node* if_false_; 8321cb0ef41Sopenharmony_ci}; 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_cistruct LoadTransformMatcher 8351cb0ef41Sopenharmony_ci : ValueMatcher<LoadTransformParameters, IrOpcode::kLoadTransform> { 8361cb0ef41Sopenharmony_ci explicit LoadTransformMatcher(Node* node) : ValueMatcher(node) {} 8371cb0ef41Sopenharmony_ci bool Is(LoadTransformation t) { 8381cb0ef41Sopenharmony_ci return HasResolvedValue() && ResolvedValue().transformation == t; 8391cb0ef41Sopenharmony_ci } 8401cb0ef41Sopenharmony_ci}; 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_ci} // namespace compiler 8431cb0ef41Sopenharmony_ci} // namespace internal 8441cb0ef41Sopenharmony_ci} // namespace v8 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ci#endif // V8_COMPILER_NODE_MATCHERS_H_ 847