14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_COMPILER_GATE_MATCHERS_H
164514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_GATE_MATCHERS_H
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit.h"
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder.h"
204514f5e3Sopenharmony_ci#include "utils/bit_utils.h"
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci// Checks if value is in range [lowerLimit, higherLimit] using a single
264514f5e3Sopenharmony_ci// branch.
274514f5e3Sopenharmony_citemplate <typename T, typename U> inline constexpr bool IsValueInRange(T value, U lowerLimit, U higherLimit)
284514f5e3Sopenharmony_ci{
294514f5e3Sopenharmony_ci    static_assert(sizeof(U) <= sizeof(T));
304514f5e3Sopenharmony_ci    using unsigned_T = typename std::make_unsigned<T>::type;
314514f5e3Sopenharmony_ci    // Use static_cast to support enum classes.
324514f5e3Sopenharmony_ci    return static_cast<unsigned_T>(static_cast<unsigned_T>(value) - static_cast<unsigned_T>(lowerLimit)) <=
334514f5e3Sopenharmony_ci           static_cast<unsigned_T>(static_cast<unsigned_T>(higherLimit) - static_cast<unsigned_T>(lowerLimit));
344514f5e3Sopenharmony_ci}
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ciclass GateMatcher {
374514f5e3Sopenharmony_cipublic:
384514f5e3Sopenharmony_ci    explicit GateMatcher(GateRef gate, Circuit *circuit) : acc_(circuit), gate_(gate)
394514f5e3Sopenharmony_ci    {
404514f5e3Sopenharmony_ci    }
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    GateRef Gate() const
434514f5e3Sopenharmony_ci    {
444514f5e3Sopenharmony_ci        return gate_;
454514f5e3Sopenharmony_ci    }
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci    GateRef ValueIn(uint32_t index)
484514f5e3Sopenharmony_ci    {
494514f5e3Sopenharmony_ci        return acc_.GetValueIn(gate_, index);
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    OpCode Opcode() const
534514f5e3Sopenharmony_ci    {
544514f5e3Sopenharmony_ci        return acc_.GetOpCode(gate_);
554514f5e3Sopenharmony_ci    }
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_ci    MachineType MachineType() const
584514f5e3Sopenharmony_ci    {
594514f5e3Sopenharmony_ci        return acc_.GetMachineType(gate_);
604514f5e3Sopenharmony_ci    }
614514f5e3Sopenharmony_ci    GateRef InputAt(int index) const
624514f5e3Sopenharmony_ci    {
634514f5e3Sopenharmony_ci        return acc_.GetValueIn(gate_, index);
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci#define DECLARE_IS_GATE(NAME, OP, R, S, D, V)                                                                          \
674514f5e3Sopenharmony_ci    bool Is##NAME() const                                                                                              \
684514f5e3Sopenharmony_ci    {                                                                                                                  \
694514f5e3Sopenharmony_ci        return (Opcode() == (OpCode::OP));                                                                             \
704514f5e3Sopenharmony_ci    }
714514f5e3Sopenharmony_ci    IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_IS_GATE)
724514f5e3Sopenharmony_ci    GATE_META_DATA_LIST_WITH_BOOL(DECLARE_IS_GATE)
734514f5e3Sopenharmony_ci    GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_IS_GATE)
744514f5e3Sopenharmony_ci    GATE_META_DATA_LIST_WITH_SIZE(DECLARE_IS_GATE)
754514f5e3Sopenharmony_ci    GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_IS_GATE) GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_IS_GATE)
764514f5e3Sopenharmony_ci        GATE_META_DATA_LIST_FOR_CALL(DECLARE_IS_GATE) GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_IS_GATE)
774514f5e3Sopenharmony_ci        GATE_META_DATA_LIST_FOR_NEW(DECLARE_IS_GATE)
784514f5e3Sopenharmony_ci#undef DECLARE_IS_GATE
794514f5e3Sopenharmony_ci
804514f5e3Sopenharmony_ci#define DECLARE_IS_INST(NAME, OPCODEID, MACHINETYPEID)                                                                 \
814514f5e3Sopenharmony_ci    bool Ism##NAME() const                                                                                             \
824514f5e3Sopenharmony_ci    {                                                                                                                  \
834514f5e3Sopenharmony_ci        return Is##OPCODEID() && MachineType() == (MACHINETYPEID);                                                     \
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci            BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(DECLARE_IS_INST)
864514f5e3Sopenharmony_ci                UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(DECLARE_IS_INST)
874514f5e3Sopenharmony_ci#undef DECLARE_IS_INST
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_ci#define DECLARE_IS_INST(NAME, OPCODEID, CONDITION)                                                                     \
904514f5e3Sopenharmony_ci    bool Ism##NAME() const                                                                                             \
914514f5e3Sopenharmony_ci    {                                                                                                                  \
924514f5e3Sopenharmony_ci        return Is##OPCODEID() && static_cast<uint64_t>(CONDITION) == ConditionValue();                                 \
934514f5e3Sopenharmony_ci    };                                                                                                                 \
944514f5e3Sopenharmony_ci    BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(DECLARE_IS_INST)
954514f5e3Sopenharmony_ci#undef DECLARE_IS_INST
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci    bool Equals(const GateRef gate)
984514f5e3Sopenharmony_ci    {
994514f5e3Sopenharmony_ci        return gate == Gate();
1004514f5e3Sopenharmony_ci    }
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ci    GateAccessor acc_;
1034514f5e3Sopenharmony_ci
1044514f5e3Sopenharmony_ci    BitField ConditionValue()
1054514f5e3Sopenharmony_ci    {
1064514f5e3Sopenharmony_ci        ASSERT(IsFcmp() || IsIcmp());
1074514f5e3Sopenharmony_ci        return acc_.TryGetValue(Gate());
1084514f5e3Sopenharmony_ci    }
1094514f5e3Sopenharmony_ciprivate:
1104514f5e3Sopenharmony_ci    GateRef gate_;
1114514f5e3Sopenharmony_ci};
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_ci// A pattern matcher for abitrary value constants.
1144514f5e3Sopenharmony_ci//
1154514f5e3Sopenharmony_ci// Note that value identities on the input gate are skipped when matching. The
1164514f5e3Sopenharmony_ci// resolved value may not be a parameter of the input gate. The Gate() method
1174514f5e3Sopenharmony_ci// returns the unmodified input gate. This is by design, as reducers may wish to
1184514f5e3Sopenharmony_ci// match value constants but delay reducing the gate until a later phase.
1194514f5e3Sopenharmony_citemplate <typename T, OpCode kOpcode, MachineType kMachineType> struct ValueMatcher : public GateMatcher {
1204514f5e3Sopenharmony_ci    using ValueType = T;
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_ci    explicit ValueMatcher(GateRef gate, Circuit *circuit)
1234514f5e3Sopenharmony_ci        : GateMatcher(gate, circuit), resolvedValue_(), hasResolvedValue_(false)
1244514f5e3Sopenharmony_ci    {
1254514f5e3Sopenharmony_ci        if (acc_.GetOpCode(gate) == kOpcode && acc_.GetMachineType(gate) == kMachineType) {
1264514f5e3Sopenharmony_ci            hasResolvedValue_ = true;
1274514f5e3Sopenharmony_ci        }
1284514f5e3Sopenharmony_ci
1294514f5e3Sopenharmony_ci        if (hasResolvedValue_) {
1304514f5e3Sopenharmony_ci            if (kMachineType == F64) {
1314514f5e3Sopenharmony_ci                resolvedValue_ = acc_.GetFloat64FromConstant(gate);
1324514f5e3Sopenharmony_ci            } else if (kMachineType == I32) {
1334514f5e3Sopenharmony_ci                resolvedValue_ = acc_.GetInt32FromConstant(gate);
1344514f5e3Sopenharmony_ci            } else if (kMachineType == I64) {
1354514f5e3Sopenharmony_ci                resolvedValue_ = acc_.GetConstantValue(gate);
1364514f5e3Sopenharmony_ci            } else {
1374514f5e3Sopenharmony_ci                hasResolvedValue_ = false;
1384514f5e3Sopenharmony_ci            }
1394514f5e3Sopenharmony_ci        }
1404514f5e3Sopenharmony_ci    }
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ci    bool HasResolvedValue() const
1434514f5e3Sopenharmony_ci    {
1444514f5e3Sopenharmony_ci        return hasResolvedValue_;
1454514f5e3Sopenharmony_ci    }
1464514f5e3Sopenharmony_ci    const T &ResolvedValue() const
1474514f5e3Sopenharmony_ci    {
1484514f5e3Sopenharmony_ci        ASSERT(HasResolvedValue());
1494514f5e3Sopenharmony_ci        return resolvedValue_;
1504514f5e3Sopenharmony_ci    }
1514514f5e3Sopenharmony_ci
1524514f5e3Sopenharmony_ciprivate:
1534514f5e3Sopenharmony_ci    T resolvedValue_;
1544514f5e3Sopenharmony_ci    bool hasResolvedValue_;
1554514f5e3Sopenharmony_ci};
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ci// A pattern matcher for integer constants.
1584514f5e3Sopenharmony_citemplate <typename T, OpCode kOpcode, MachineType kMachineType>
1594514f5e3Sopenharmony_cistruct IntMatcher final : public ValueMatcher<T, kOpcode, kMachineType> {
1604514f5e3Sopenharmony_ci    explicit IntMatcher(GateRef gate, Circuit *circuit) : ValueMatcher<T, kOpcode, kMachineType>(gate, circuit)
1614514f5e3Sopenharmony_ci    {
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci
1644514f5e3Sopenharmony_ci    bool Is(const T &value) const
1654514f5e3Sopenharmony_ci    {
1664514f5e3Sopenharmony_ci        return this->HasResolvedValue() && this->ResolvedValue() == value;
1674514f5e3Sopenharmony_ci    }
1684514f5e3Sopenharmony_ci
1694514f5e3Sopenharmony_ci    bool IsInRange(const T &low, const T &high) const
1704514f5e3Sopenharmony_ci    {
1714514f5e3Sopenharmony_ci        return this->HasResolvedValue() && IsValueInRange(this->ResolvedValue(), low, high);
1724514f5e3Sopenharmony_ci    }
1734514f5e3Sopenharmony_ci    bool IsMultipleOf(T n) const
1744514f5e3Sopenharmony_ci    {
1754514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
1764514f5e3Sopenharmony_ci            return false;
1774514f5e3Sopenharmony_ci        }
1784514f5e3Sopenharmony_ci        return (this->ResolvedValue() % n) == 0;
1794514f5e3Sopenharmony_ci    }
1804514f5e3Sopenharmony_ci
1814514f5e3Sopenharmony_ci    bool IsPowerOf2() const
1824514f5e3Sopenharmony_ci    {
1834514f5e3Sopenharmony_ci        if (!this->HasResolvedValue() || this->ResolvedValue() <= 0) {
1844514f5e3Sopenharmony_ci            return false;
1854514f5e3Sopenharmony_ci        }
1864514f5e3Sopenharmony_ci        using unsigned_type = typename std::make_unsigned<T>::type;
1874514f5e3Sopenharmony_ci        const unsigned_type resolvedValue = static_cast<unsigned_type>(this->ResolvedValue());
1884514f5e3Sopenharmony_ci        return (resolvedValue & (resolvedValue - 1)) == 0;
1894514f5e3Sopenharmony_ci    }
1904514f5e3Sopenharmony_ci
1914514f5e3Sopenharmony_ci    bool IsNegativePowerOf2() const
1924514f5e3Sopenharmony_ci    {
1934514f5e3Sopenharmony_ci        if (!this->HasResolvedValue() || this->ResolvedValue() >= 0) {
1944514f5e3Sopenharmony_ci            return false;
1954514f5e3Sopenharmony_ci        }
1964514f5e3Sopenharmony_ci        return ((this->ResolvedValue() == std::numeric_limits<T>::min()) ||
1974514f5e3Sopenharmony_ci                (-this->ResolvedValue() & (-this->ResolvedValue() - 1)) == 0);
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci
2004514f5e3Sopenharmony_ci    bool IsNegative() const
2014514f5e3Sopenharmony_ci    {
2024514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2034514f5e3Sopenharmony_ci            return false;
2044514f5e3Sopenharmony_ci        }
2054514f5e3Sopenharmony_ci        return this->ResolvedValue() < 0;
2064514f5e3Sopenharmony_ci    }
2074514f5e3Sopenharmony_ci};
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ciusing Int32Matcher = IntMatcher<int32_t, OpCode::CONSTANT, MachineType::I32>;
2104514f5e3Sopenharmony_ciusing Uint32Matcher = IntMatcher<uint32_t, OpCode::CONSTANT, MachineType::I32>;
2114514f5e3Sopenharmony_ciusing Int64Matcher = IntMatcher<int64_t, OpCode::CONSTANT, MachineType::I64>;
2124514f5e3Sopenharmony_ciusing Uint64Matcher = IntMatcher<uint64_t, OpCode::CONSTANT, MachineType::I64>;
2134514f5e3Sopenharmony_ci
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ci// A pattern matcher for floating point constants.
2164514f5e3Sopenharmony_citemplate <typename T, OpCode kOpcode, MachineType kMachineType>
2174514f5e3Sopenharmony_cistruct FloatMatcher final : public ValueMatcher<T, kOpcode, kMachineType> {
2184514f5e3Sopenharmony_ci    explicit FloatMatcher(GateRef gate, Circuit *circuit) : ValueMatcher<T, kOpcode, kMachineType>(gate, circuit)
2194514f5e3Sopenharmony_ci    {
2204514f5e3Sopenharmony_ci    }
2214514f5e3Sopenharmony_ci
2224514f5e3Sopenharmony_ci    bool Is(const T &value) const
2234514f5e3Sopenharmony_ci    {
2244514f5e3Sopenharmony_ci        return this->HasResolvedValue() && this->ResolvedValue() == value;
2254514f5e3Sopenharmony_ci    }
2264514f5e3Sopenharmony_ci    bool IsInRange(const T &low, const T &high) const
2274514f5e3Sopenharmony_ci    {
2284514f5e3Sopenharmony_ci        return this->HasResolvedValue() && low <= this->ResolvedValue() && this->ResolvedValue() <= high;
2294514f5e3Sopenharmony_ci    }
2304514f5e3Sopenharmony_ci    bool IsMinusZero() const
2314514f5e3Sopenharmony_ci    {
2324514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2334514f5e3Sopenharmony_ci            return false;
2344514f5e3Sopenharmony_ci        }
2354514f5e3Sopenharmony_ci        return this->Is(0.0) && std::signbit(this->ResolvedValue());
2364514f5e3Sopenharmony_ci    }
2374514f5e3Sopenharmony_ci
2384514f5e3Sopenharmony_ci    bool IsNegative() const
2394514f5e3Sopenharmony_ci    {
2404514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2414514f5e3Sopenharmony_ci            return false;
2424514f5e3Sopenharmony_ci        }
2434514f5e3Sopenharmony_ci        return this->ResolvedValue() < 0.0;
2444514f5e3Sopenharmony_ci    }
2454514f5e3Sopenharmony_ci
2464514f5e3Sopenharmony_ci    bool IsNaN() const
2474514f5e3Sopenharmony_ci    {
2484514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2494514f5e3Sopenharmony_ci            return false;
2504514f5e3Sopenharmony_ci        }
2514514f5e3Sopenharmony_ci        return std::isnan(this->ResolvedValue());
2524514f5e3Sopenharmony_ci    }
2534514f5e3Sopenharmony_ci
2544514f5e3Sopenharmony_ci    bool IsZero() const
2554514f5e3Sopenharmony_ci    {
2564514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2574514f5e3Sopenharmony_ci            return false;
2584514f5e3Sopenharmony_ci        }
2594514f5e3Sopenharmony_ci        return this->Is(0.0) && !std::signbit(this->ResolvedValue());
2604514f5e3Sopenharmony_ci    }
2614514f5e3Sopenharmony_ci
2624514f5e3Sopenharmony_ci    bool IsNormal() const
2634514f5e3Sopenharmony_ci    {
2644514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2654514f5e3Sopenharmony_ci            return false;
2664514f5e3Sopenharmony_ci        }
2674514f5e3Sopenharmony_ci        return std::isnormal(this->ResolvedValue());
2684514f5e3Sopenharmony_ci    }
2694514f5e3Sopenharmony_ci
2704514f5e3Sopenharmony_ci    bool IsInteger() const
2714514f5e3Sopenharmony_ci    {
2724514f5e3Sopenharmony_ci        if (!this->HasResolvedValue()) {
2734514f5e3Sopenharmony_ci            return false;
2744514f5e3Sopenharmony_ci        }
2754514f5e3Sopenharmony_ci        return std::nearbyint(this->ResolvedValue()) == this->ResolvedValue();
2764514f5e3Sopenharmony_ci    }
2774514f5e3Sopenharmony_ci};
2784514f5e3Sopenharmony_ci
2794514f5e3Sopenharmony_ciusing Float32Matcher = FloatMatcher<float, OpCode::CONSTANT, MachineType::F32>;
2804514f5e3Sopenharmony_ciusing Float64Matcher = FloatMatcher<double, OpCode::CONSTANT, MachineType::F64>;
2814514f5e3Sopenharmony_ci
2824514f5e3Sopenharmony_ci
2834514f5e3Sopenharmony_ci// For shorter pattern matching code, this struct matches both the left and
2844514f5e3Sopenharmony_ci// right hand sides of a binary operation and can put constants on the right
2854514f5e3Sopenharmony_ci// if they appear on the left hand side of a commutative operation.
2864514f5e3Sopenharmony_citemplate <typename LeftExpr, typename RightExpr, MachineType rep> struct BinopMatcher : public GateMatcher {
2874514f5e3Sopenharmony_ci    explicit BinopMatcher(GateRef gate, Circuit *circuit)
2884514f5e3Sopenharmony_ci        : GateMatcher(gate, circuit), left_(InputAt(0), circuit), right_(InputAt(1), circuit)
2894514f5e3Sopenharmony_ci    {
2904514f5e3Sopenharmony_ci        if (IsCommutative(Opcode())) {
2914514f5e3Sopenharmony_ci            PutConstantOnRight();
2924514f5e3Sopenharmony_ci        }
2934514f5e3Sopenharmony_ci    }
2944514f5e3Sopenharmony_ci
2954514f5e3Sopenharmony_ci    BinopMatcher(GateRef gate, bool allowInputSwap, Circuit *circuit)
2964514f5e3Sopenharmony_ci        : GateMatcher(gate, circuit), left_(InputAt(0), circuit), right_(InputAt(1), circuit)
2974514f5e3Sopenharmony_ci    {
2984514f5e3Sopenharmony_ci        if (allowInputSwap) {
2994514f5e3Sopenharmony_ci            PutConstantOnRight();
3004514f5e3Sopenharmony_ci        }
3014514f5e3Sopenharmony_ci    }
3024514f5e3Sopenharmony_ci
3034514f5e3Sopenharmony_ci    using LeftMatcher = LeftExpr;
3044514f5e3Sopenharmony_ci    using RightMatcher = RightExpr;
3054514f5e3Sopenharmony_ci
3064514f5e3Sopenharmony_ci    // static constexpr MachineType representation = rep;
3074514f5e3Sopenharmony_ci
3084514f5e3Sopenharmony_ci    const LeftExpr &Left() const
3094514f5e3Sopenharmony_ci    {
3104514f5e3Sopenharmony_ci        return left_;
3114514f5e3Sopenharmony_ci    }
3124514f5e3Sopenharmony_ci
3134514f5e3Sopenharmony_ci    const RightExpr &Right() const
3144514f5e3Sopenharmony_ci    {
3154514f5e3Sopenharmony_ci        return right_;
3164514f5e3Sopenharmony_ci    }
3174514f5e3Sopenharmony_ci
3184514f5e3Sopenharmony_ci    void SetLeft(GateRef left, Circuit* circuit)
3194514f5e3Sopenharmony_ci    {
3204514f5e3Sopenharmony_ci        left_  = LeftExpr(left, circuit);
3214514f5e3Sopenharmony_ci    }
3224514f5e3Sopenharmony_ci
3234514f5e3Sopenharmony_ci    void SetRight(GateRef right, Circuit* circuit)
3244514f5e3Sopenharmony_ci    {
3254514f5e3Sopenharmony_ci        right_ = RightExpr(right, circuit);
3264514f5e3Sopenharmony_ci    }
3274514f5e3Sopenharmony_ci
3284514f5e3Sopenharmony_ci    bool IsFoldable() const
3294514f5e3Sopenharmony_ci    {
3304514f5e3Sopenharmony_ci        return Left().HasResolvedValue() && Right().HasResolvedValue();
3314514f5e3Sopenharmony_ci    }
3324514f5e3Sopenharmony_ci    bool LeftEqualsRight() const
3334514f5e3Sopenharmony_ci    {
3344514f5e3Sopenharmony_ci        return Left().Gate() == Right().Gate();
3354514f5e3Sopenharmony_ci    }
3364514f5e3Sopenharmony_ci
3374514f5e3Sopenharmony_ci    bool OwnsInput(GateRef input)
3384514f5e3Sopenharmony_ci    {
3394514f5e3Sopenharmony_ci        auto use = acc_.Uses(input);
3404514f5e3Sopenharmony_ci        for (auto it = use.begin(); it != use.end(); it++) {
3414514f5e3Sopenharmony_ci            if (*it != Gate()) {
3424514f5e3Sopenharmony_ci                return false;
3434514f5e3Sopenharmony_ci            }
3444514f5e3Sopenharmony_ci        }
3454514f5e3Sopenharmony_ci        return true;
3464514f5e3Sopenharmony_ci    }
3474514f5e3Sopenharmony_ci
3484514f5e3Sopenharmony_ciprotected:
3494514f5e3Sopenharmony_ci    void SwapInputs()
3504514f5e3Sopenharmony_ci    {
3514514f5e3Sopenharmony_ci        std::swap(left_, right_);
3524514f5e3Sopenharmony_ci        acc_.ReplaceValueIn(Gate(), Left().Gate(), 0);
3534514f5e3Sopenharmony_ci        acc_.ReplaceValueIn(Gate(), Right().Gate(), 1);
3544514f5e3Sopenharmony_ci    }
3554514f5e3Sopenharmony_ci
3564514f5e3Sopenharmony_ciprivate:
3574514f5e3Sopenharmony_ci    void PutConstantOnRight()
3584514f5e3Sopenharmony_ci    {
3594514f5e3Sopenharmony_ci        if (Left().HasResolvedValue() && !Right().HasResolvedValue()) {
3604514f5e3Sopenharmony_ci            SwapInputs();
3614514f5e3Sopenharmony_ci        }
3624514f5e3Sopenharmony_ci    }
3634514f5e3Sopenharmony_ci    static bool IsCommutative(OpCode opcode)
3644514f5e3Sopenharmony_ci    {
3654514f5e3Sopenharmony_ci        switch (opcode) {
3664514f5e3Sopenharmony_ci            case OpCode::ADD:
3674514f5e3Sopenharmony_ci            case OpCode::AND:
3684514f5e3Sopenharmony_ci            case OpCode::OR:
3694514f5e3Sopenharmony_ci            case OpCode::XOR:
3704514f5e3Sopenharmony_ci            case OpCode::MUL:
3714514f5e3Sopenharmony_ci            case OpCode::ADD_WITH_OVERFLOW:
3724514f5e3Sopenharmony_ci            case OpCode::MUL_WITH_OVERFLOW:
3734514f5e3Sopenharmony_ci                return true;
3744514f5e3Sopenharmony_ci            default:
3754514f5e3Sopenharmony_ci                return false;
3764514f5e3Sopenharmony_ci        }
3774514f5e3Sopenharmony_ci        return false;
3784514f5e3Sopenharmony_ci    }
3794514f5e3Sopenharmony_ci    LeftExpr left_;
3804514f5e3Sopenharmony_ci    RightExpr right_;
3814514f5e3Sopenharmony_ci};
3824514f5e3Sopenharmony_ci
3834514f5e3Sopenharmony_ciusing Int32BinopMatcher = BinopMatcher<Int32Matcher, Int32Matcher, MachineType::I32>;
3844514f5e3Sopenharmony_ciusing Uint32BinopMatcher = BinopMatcher<Uint32Matcher, Uint32Matcher, MachineType::I32>;
3854514f5e3Sopenharmony_ciusing Int64BinopMatcher = BinopMatcher<Int64Matcher, Int64Matcher, MachineType::I64>;
3864514f5e3Sopenharmony_ciusing Uint64BinopMatcher = BinopMatcher<Uint64Matcher, Uint64Matcher, MachineType::I64>;
3874514f5e3Sopenharmony_ciusing Float32BinopMatcher = BinopMatcher<Float32Matcher, Float32Matcher, MachineType::F32>;
3884514f5e3Sopenharmony_ciusing Float64BinopMatcher = BinopMatcher<Float64Matcher, Float64Matcher, MachineType::F64>;
3894514f5e3Sopenharmony_ci
3904514f5e3Sopenharmony_ci
3914514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu
3924514f5e3Sopenharmony_ci#endif // ECMASCRIPT_COMPILER_GATE_MATCHERS_H