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#include "ecmascript/compiler/instruction_combine.h"
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder-inl.h"
174514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_matchers.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_ciGateRef InstructionCombine::ReplaceOld(GateRef gate, GateRef newGate)
224514f5e3Sopenharmony_ci{
234514f5e3Sopenharmony_ci    acc_.UpdateAllUses(gate, newGate);
244514f5e3Sopenharmony_ci    return newGate;
254514f5e3Sopenharmony_ci}
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitGate(GateRef gate)
294514f5e3Sopenharmony_ci{
304514f5e3Sopenharmony_ci    OpCode op = acc_.GetOpCode(gate);
314514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
324514f5e3Sopenharmony_ci    ;
334514f5e3Sopenharmony_ci    switch (op) {
344514f5e3Sopenharmony_ci        case OpCode::ADD:
354514f5e3Sopenharmony_ci            result = VisitADD(gate);
364514f5e3Sopenharmony_ci            break;
374514f5e3Sopenharmony_ci        case OpCode::SUB:
384514f5e3Sopenharmony_ci            result = VisitSUB(gate);
394514f5e3Sopenharmony_ci            break;
404514f5e3Sopenharmony_ci        case OpCode::MUL:
414514f5e3Sopenharmony_ci            result = VisitMUL(gate);
424514f5e3Sopenharmony_ci            break;
434514f5e3Sopenharmony_ci        case OpCode::SDIV:
444514f5e3Sopenharmony_ci            result = VisitSDIV(gate);
454514f5e3Sopenharmony_ci            break;
464514f5e3Sopenharmony_ci        case OpCode::FDIV:
474514f5e3Sopenharmony_ci            result = VisitFDIV(gate);
484514f5e3Sopenharmony_ci            break;
494514f5e3Sopenharmony_ci        case OpCode::SMOD:
504514f5e3Sopenharmony_ci            result = VisitSMOD(gate);
514514f5e3Sopenharmony_ci            break;
524514f5e3Sopenharmony_ci        case OpCode::AND:
534514f5e3Sopenharmony_ci            result = VisitAND(gate);
544514f5e3Sopenharmony_ci            break;
554514f5e3Sopenharmony_ci        case OpCode::OR:
564514f5e3Sopenharmony_ci            result = VisitOR(gate);
574514f5e3Sopenharmony_ci            break;
584514f5e3Sopenharmony_ci        case OpCode::XOR:
594514f5e3Sopenharmony_ci            result = VisitXOR(gate);
604514f5e3Sopenharmony_ci            break;
614514f5e3Sopenharmony_ci        case OpCode::ASR:
624514f5e3Sopenharmony_ci            result = VisitASR(gate);
634514f5e3Sopenharmony_ci            break;
644514f5e3Sopenharmony_ci        case OpCode::LSL:
654514f5e3Sopenharmony_ci            result = VisitLSL(gate);
664514f5e3Sopenharmony_ci            break;
674514f5e3Sopenharmony_ci        case OpCode::LSR:
684514f5e3Sopenharmony_ci            result = VisitLSR(gate);
694514f5e3Sopenharmony_ci            break;
704514f5e3Sopenharmony_ci        case OpCode::ICMP:
714514f5e3Sopenharmony_ci            result = VisitICMP(gate);
724514f5e3Sopenharmony_ci            break;
734514f5e3Sopenharmony_ci        case OpCode::REV:
744514f5e3Sopenharmony_ci            result = VisitREV(gate);
754514f5e3Sopenharmony_ci            break;
764514f5e3Sopenharmony_ci        case OpCode::IF_BRANCH:
774514f5e3Sopenharmony_ci            result = VisitBranch(gate);
784514f5e3Sopenharmony_ci            break;
794514f5e3Sopenharmony_ci        case OpCode::EXTRACT_VALUE:
804514f5e3Sopenharmony_ci            return VisitExtractValue(gate);
814514f5e3Sopenharmony_ci        case OpCode::TAGGED_TO_INT64:
824514f5e3Sopenharmony_ci        case OpCode::INT64_TO_TAGGED:
834514f5e3Sopenharmony_ci        case OpCode::SIGNED_INT_TO_FLOAT:
844514f5e3Sopenharmony_ci        case OpCode::FLOAT_TO_SIGNED_INT:
854514f5e3Sopenharmony_ci        case OpCode::UNSIGNED_FLOAT_TO_INT:
864514f5e3Sopenharmony_ci        case OpCode::BITCAST:
874514f5e3Sopenharmony_ci        case OpCode::ZEXT:
884514f5e3Sopenharmony_ci        case OpCode::SEXT:
894514f5e3Sopenharmony_ci        case OpCode::TRUNC:
904514f5e3Sopenharmony_ci        case OpCode::FEXT:
914514f5e3Sopenharmony_ci        case OpCode::FTRUNC:
924514f5e3Sopenharmony_ci            return VisitConvert(gate);
934514f5e3Sopenharmony_ci            break;
944514f5e3Sopenharmony_ci        default:
954514f5e3Sopenharmony_ci            break;
964514f5e3Sopenharmony_ci    }
974514f5e3Sopenharmony_ci    if (enableLog_ && result != Circuit::NullGate()) {
984514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "InstructionCombine opt befor -> afert";
994514f5e3Sopenharmony_ci        acc_.Print(gate);
1004514f5e3Sopenharmony_ci        acc_.Print(result);
1014514f5e3Sopenharmony_ci    }
1024514f5e3Sopenharmony_ci    return result;
1034514f5e3Sopenharmony_ci}
1044514f5e3Sopenharmony_ci
1054514f5e3Sopenharmony_ci// Wait for the implementation of constant folding and partial redundancy elimination.
1064514f5e3Sopenharmony_ci// The Convert-related IR operations need refactoring for more effective optimization.
1074514f5e3Sopenharmony_ci// 1. Merge or differentiate the functionalities of SignIntToFloat and Bitcast
1084514f5e3Sopenharmony_ci//    as both handle Int-to-Float conversions. Int32ToFloat32 also exhibits similar behavior.
1094514f5e3Sopenharmony_ci// 2. Clarify the roles of TruncFloatToInt64 and FTrunc, ensuring they are distinct or unified.
1104514f5e3Sopenharmony_ci// 3. Standardize naming conventions for operations that are inverse or similar to each other
1114514f5e3Sopenharmony_ci//    to avoid confusion. ex: ChangeTaggedPointerToInt64 and Int64ToTaggedPtr perform similar functions,
1124514f5e3Sopenharmony_ci//    yet their names are significantly different
1134514f5e3Sopenharmony_ci// 4. .................
1144514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitConvert(GateRef gate)
1154514f5e3Sopenharmony_ci{
1164514f5e3Sopenharmony_ci    // For the meanings of the following Opcodes, please refer to
1174514f5e3Sopenharmony_ci    // UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH
1184514f5e3Sopenharmony_ci    switch (acc_.GetOpCode(gate)) {
1194514f5e3Sopenharmony_ci        case OpCode::TAGGED_TO_INT64:
1204514f5e3Sopenharmony_ci            {
1214514f5e3Sopenharmony_ci                GateMatcher in(acc_.GetValueIn(gate, 0), circuit_);
1224514f5e3Sopenharmony_ci                if (in.IsInt64ToTagged()) {
1234514f5e3Sopenharmony_ci                    return in.ValueIn(0);
1244514f5e3Sopenharmony_ci                }
1254514f5e3Sopenharmony_ci                break;
1264514f5e3Sopenharmony_ci            }
1274514f5e3Sopenharmony_ci        case OpCode::INT64_TO_TAGGED:
1284514f5e3Sopenharmony_ci            {
1294514f5e3Sopenharmony_ci                GateMatcher in(acc_.GetValueIn(gate, 0), circuit_);
1304514f5e3Sopenharmony_ci                if (in.IsTaggedToInt64()) {
1314514f5e3Sopenharmony_ci                    return in.ValueIn(0);
1324514f5e3Sopenharmony_ci                }
1334514f5e3Sopenharmony_ci                break;
1344514f5e3Sopenharmony_ci            }
1354514f5e3Sopenharmony_ci        case OpCode::SIGNED_INT_TO_FLOAT:
1364514f5e3Sopenharmony_ci            {
1374514f5e3Sopenharmony_ci                GateMatcher in(acc_.GetValueIn(gate, 0), circuit_);
1384514f5e3Sopenharmony_ci                if (in.IsFloatToSignedInt()) {
1394514f5e3Sopenharmony_ci                    return in.ValueIn(0);
1404514f5e3Sopenharmony_ci                }
1414514f5e3Sopenharmony_ci                break;
1424514f5e3Sopenharmony_ci            }
1434514f5e3Sopenharmony_ci        case OpCode::FLOAT_TO_SIGNED_INT:
1444514f5e3Sopenharmony_ci            {
1454514f5e3Sopenharmony_ci                GateMatcher in(acc_.GetValueIn(gate, 0), circuit_);
1464514f5e3Sopenharmony_ci                if (in.IsSignedIntToFloat()) {
1474514f5e3Sopenharmony_ci                    return in.ValueIn(0);
1484514f5e3Sopenharmony_ci                }
1494514f5e3Sopenharmony_ci                break;
1504514f5e3Sopenharmony_ci            }
1514514f5e3Sopenharmony_ci        case OpCode::UNSIGNED_FLOAT_TO_INT:
1524514f5e3Sopenharmony_ci            break;
1534514f5e3Sopenharmony_ci        case OpCode::BITCAST:
1544514f5e3Sopenharmony_ci        case OpCode::ZEXT:
1554514f5e3Sopenharmony_ci        case OpCode::SEXT:
1564514f5e3Sopenharmony_ci        case OpCode::TRUNC:
1574514f5e3Sopenharmony_ci        case OpCode::FEXT:
1584514f5e3Sopenharmony_ci        case OpCode::FTRUNC:
1594514f5e3Sopenharmony_ci            break;
1604514f5e3Sopenharmony_ci        default:
1614514f5e3Sopenharmony_ci            break;
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci    return Circuit::NullGate();
1644514f5e3Sopenharmony_ci}
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitBranch(GateRef gate)
1674514f5e3Sopenharmony_ci{
1684514f5e3Sopenharmony_ci    (void)gate;
1694514f5e3Sopenharmony_ci    return Circuit::NullGate();
1704514f5e3Sopenharmony_ci}
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitREV(GateRef gate)
1734514f5e3Sopenharmony_ci{
1744514f5e3Sopenharmony_ci    // REV Constant => Constant
1754514f5e3Sopenharmony_ci    auto revValue = acc_.GetValueIn(gate, 0);
1764514f5e3Sopenharmony_ci    if (acc_.GetOpCode(revValue) == OpCode::CONSTANT && acc_.GetMachineType(revValue) == I1) {
1774514f5e3Sopenharmony_ci        if (acc_.GetConstantValue(revValue) == 0) {
1784514f5e3Sopenharmony_ci            return builder_.True();
1794514f5e3Sopenharmony_ci        } else {
1804514f5e3Sopenharmony_ci            return builder_.False();
1814514f5e3Sopenharmony_ci        }
1824514f5e3Sopenharmony_ci    }
1834514f5e3Sopenharmony_ci    return Circuit::NullGate();
1844514f5e3Sopenharmony_ci}
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitICMP(GateRef gate)
1874514f5e3Sopenharmony_ci{
1884514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
1894514f5e3Sopenharmony_ci    // Match {EQ ((x or constant1) , constant2)} {((constant1 | constant2) != constant2)} => false
1904514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
1914514f5e3Sopenharmony_ci    if (m.ConditionValue() == static_cast<uint64_t>(ICmpCondition::EQ) && m.Right().HasResolvedValue()) {
1924514f5e3Sopenharmony_ci        // In essence, it's all about comparing I64, so we can optimize further
1934514f5e3Sopenharmony_ci        // Subsequently, considering whether it can be automated within the gateMatcher
1944514f5e3Sopenharmony_ci        if (m.Left().Opcode() == OpCode::INT64_TO_TAGGED) {
1954514f5e3Sopenharmony_ci            m.SetLeft(m.Left().InputAt(0), circuit_);
1964514f5e3Sopenharmony_ci        }
1974514f5e3Sopenharmony_ci
1984514f5e3Sopenharmony_ci        if (m.Left().IsOr()) {
1994514f5e3Sopenharmony_ci            Int64BinopMatcher cmpLeft(m.Left().Gate(), circuit_);
2004514f5e3Sopenharmony_ci            if (cmpLeft.Right().HasResolvedValue()) {
2014514f5e3Sopenharmony_ci                uint64_t constant1 = static_cast<uint64_t>(cmpLeft.Right().ResolvedValue());
2024514f5e3Sopenharmony_ci                uint64_t constant2 = static_cast<uint64_t>(m.Right().ResolvedValue());
2034514f5e3Sopenharmony_ci                bool flag = ((constant1 | constant2) != constant2);
2044514f5e3Sopenharmony_ci                result = flag ? builder_.False() : Circuit::NullGate();
2054514f5e3Sopenharmony_ci            }
2064514f5e3Sopenharmony_ci        }
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_ci        if (result != Circuit::NullGate()) {
2094514f5e3Sopenharmony_ci            return result;
2104514f5e3Sopenharmony_ci        }
2114514f5e3Sopenharmony_ci
2124514f5e3Sopenharmony_ci        // Match {EQ((X or constant1) & constant2, 0)} { (constan2 !=0 && constant1 & constant2 !=0) }=> false
2134514f5e3Sopenharmony_ci        if (m.Left().IsAnd() && m.Right().ResolvedValue() == 0) {
2144514f5e3Sopenharmony_ci            Int64BinopMatcher andOp(m.Left().Gate(), circuit_);
2154514f5e3Sopenharmony_ci            if (andOp.Left().IsOr() && andOp.Right().HasResolvedValue() && andOp.Right().ResolvedValue() != 0) {
2164514f5e3Sopenharmony_ci                // The awkwardness in writing it this way is simply to reduce cyclomatic complexity.
2174514f5e3Sopenharmony_ci                Int64BinopMatcher orOp(andOp.Left().Gate(), circuit_);
2184514f5e3Sopenharmony_ci                auto constant2 = andOp.Right().ResolvedValue();
2194514f5e3Sopenharmony_ci                auto constant1 = orOp.Right().HasResolvedValue() ? orOp.Right().ResolvedValue() : 0;
2204514f5e3Sopenharmony_ci                bool flag = (constant1 & constant2) != 0;
2214514f5e3Sopenharmony_ci                result = flag ? builder_.False() : Circuit::NullGate();
2224514f5e3Sopenharmony_ci            }
2234514f5e3Sopenharmony_ci        }
2244514f5e3Sopenharmony_ci        if (result != Circuit::NullGate()) {
2254514f5e3Sopenharmony_ci            return result;
2264514f5e3Sopenharmony_ci        }
2274514f5e3Sopenharmony_ci    }
2284514f5e3Sopenharmony_ci
2294514f5e3Sopenharmony_ci    return Circuit::NullGate();
2304514f5e3Sopenharmony_ci}
2314514f5e3Sopenharmony_ci
2324514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitADD(GateRef gate)
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
2354514f5e3Sopenharmony_ci    switch (machineType) {
2364514f5e3Sopenharmony_ci        case MachineType::I32:
2374514f5e3Sopenharmony_ci            return ReduceInt32Add(gate);
2384514f5e3Sopenharmony_ci        case MachineType::I64:
2394514f5e3Sopenharmony_ci            return ReduceInt64Add(gate);
2404514f5e3Sopenharmony_ci        case MachineType::F64:
2414514f5e3Sopenharmony_ci            return ReduceDoubleAdd(gate);
2424514f5e3Sopenharmony_ci        default:
2434514f5e3Sopenharmony_ci            break;
2444514f5e3Sopenharmony_ci    }
2454514f5e3Sopenharmony_ci    return Circuit::NullGate();
2464514f5e3Sopenharmony_ci}
2474514f5e3Sopenharmony_ci
2484514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitSUB(GateRef gate)
2494514f5e3Sopenharmony_ci{
2504514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
2514514f5e3Sopenharmony_ci    switch (machineType) {
2524514f5e3Sopenharmony_ci        case MachineType::I32:
2534514f5e3Sopenharmony_ci            return ReduceInt32Sub(gate);
2544514f5e3Sopenharmony_ci        case MachineType::I64:
2554514f5e3Sopenharmony_ci            return ReduceInt64Sub(gate);
2564514f5e3Sopenharmony_ci        case MachineType::F64:
2574514f5e3Sopenharmony_ci            return ReduceDoubleSub(gate);
2584514f5e3Sopenharmony_ci        default:
2594514f5e3Sopenharmony_ci            break;
2604514f5e3Sopenharmony_ci    }
2614514f5e3Sopenharmony_ci    return Circuit::NullGate();
2624514f5e3Sopenharmony_ci}
2634514f5e3Sopenharmony_ci
2644514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitMUL(GateRef gate)
2654514f5e3Sopenharmony_ci{
2664514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
2674514f5e3Sopenharmony_ci    switch (machineType) {
2684514f5e3Sopenharmony_ci        case MachineType::I32:
2694514f5e3Sopenharmony_ci            return ReduceInt32Mul(gate);
2704514f5e3Sopenharmony_ci        case MachineType::I64:
2714514f5e3Sopenharmony_ci            return ReduceInt64Mul(gate);
2724514f5e3Sopenharmony_ci        case MachineType::F64:
2734514f5e3Sopenharmony_ci            return ReduceDoubleMul(gate);
2744514f5e3Sopenharmony_ci        default:
2754514f5e3Sopenharmony_ci            break;
2764514f5e3Sopenharmony_ci    }
2774514f5e3Sopenharmony_ci    return Circuit::NullGate();
2784514f5e3Sopenharmony_ci}
2794514f5e3Sopenharmony_ci
2804514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitSDIV(GateRef gate)
2814514f5e3Sopenharmony_ci{
2824514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
2834514f5e3Sopenharmony_ci    switch (machineType) {
2844514f5e3Sopenharmony_ci        case MachineType::I32:
2854514f5e3Sopenharmony_ci            return ReduceInt32Div(gate);
2864514f5e3Sopenharmony_ci        case MachineType::I64:
2874514f5e3Sopenharmony_ci            return ReduceInt64Div(gate);
2884514f5e3Sopenharmony_ci        default:
2894514f5e3Sopenharmony_ci            break;
2904514f5e3Sopenharmony_ci    }
2914514f5e3Sopenharmony_ci    return Circuit::NullGate();
2924514f5e3Sopenharmony_ci}
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitFDIV(GateRef gate)
2954514f5e3Sopenharmony_ci{
2964514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
2974514f5e3Sopenharmony_ci    switch (machineType) {
2984514f5e3Sopenharmony_ci        case MachineType::F64:
2994514f5e3Sopenharmony_ci            return ReduceDoubleDiv(gate);
3004514f5e3Sopenharmony_ci        default:
3014514f5e3Sopenharmony_ci            break;
3024514f5e3Sopenharmony_ci    }
3034514f5e3Sopenharmony_ci    return Circuit::NullGate();
3044514f5e3Sopenharmony_ci}
3054514f5e3Sopenharmony_ci
3064514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitSMOD(GateRef gate)
3074514f5e3Sopenharmony_ci{
3084514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3094514f5e3Sopenharmony_ci    switch (machineType) {
3104514f5e3Sopenharmony_ci        case MachineType::I32:
3114514f5e3Sopenharmony_ci            return ReduceInt32Mod(gate);
3124514f5e3Sopenharmony_ci        case MachineType::F64:
3134514f5e3Sopenharmony_ci            return ReduceDoubleMod(gate);
3144514f5e3Sopenharmony_ci        default:
3154514f5e3Sopenharmony_ci            break;
3164514f5e3Sopenharmony_ci    }
3174514f5e3Sopenharmony_ci    return Circuit::NullGate();
3184514f5e3Sopenharmony_ci}
3194514f5e3Sopenharmony_ci
3204514f5e3Sopenharmony_ci
3214514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitAND(GateRef gate)
3224514f5e3Sopenharmony_ci{
3234514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3244514f5e3Sopenharmony_ci    switch (machineType) {
3254514f5e3Sopenharmony_ci        case MachineType::I32:
3264514f5e3Sopenharmony_ci            return ReduceWord32And(gate);
3274514f5e3Sopenharmony_ci        case MachineType::I64:
3284514f5e3Sopenharmony_ci            return ReduceWord64And(gate);
3294514f5e3Sopenharmony_ci        default:
3304514f5e3Sopenharmony_ci            break;
3314514f5e3Sopenharmony_ci    }
3324514f5e3Sopenharmony_ci    return Circuit::NullGate();
3334514f5e3Sopenharmony_ci}
3344514f5e3Sopenharmony_ci
3354514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitOR(GateRef gate)
3364514f5e3Sopenharmony_ci{
3374514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3384514f5e3Sopenharmony_ci    switch (machineType) {
3394514f5e3Sopenharmony_ci        case MachineType::I32:
3404514f5e3Sopenharmony_ci            return ReduceWord32Or(gate);
3414514f5e3Sopenharmony_ci        case MachineType::I64:
3424514f5e3Sopenharmony_ci            return ReduceWord64Or(gate);
3434514f5e3Sopenharmony_ci        default:
3444514f5e3Sopenharmony_ci            break;
3454514f5e3Sopenharmony_ci    }
3464514f5e3Sopenharmony_ci    return Circuit::NullGate();
3474514f5e3Sopenharmony_ci}
3484514f5e3Sopenharmony_ci
3494514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitXOR(GateRef gate)
3504514f5e3Sopenharmony_ci{
3514514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3524514f5e3Sopenharmony_ci    switch (machineType) {
3534514f5e3Sopenharmony_ci        case MachineType::I32:
3544514f5e3Sopenharmony_ci            return ReduceWord32Xor(gate);
3554514f5e3Sopenharmony_ci        case MachineType::I64:
3564514f5e3Sopenharmony_ci            return ReduceWord64Xor(gate);
3574514f5e3Sopenharmony_ci        default:
3584514f5e3Sopenharmony_ci            break;
3594514f5e3Sopenharmony_ci    }
3604514f5e3Sopenharmony_ci    return Circuit::NullGate();
3614514f5e3Sopenharmony_ci}
3624514f5e3Sopenharmony_ci
3634514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitLSR(GateRef gate)
3644514f5e3Sopenharmony_ci{
3654514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3664514f5e3Sopenharmony_ci    switch (machineType) {
3674514f5e3Sopenharmony_ci        case MachineType::I32:
3684514f5e3Sopenharmony_ci            return ReduceWord32Lsr(gate);
3694514f5e3Sopenharmony_ci        case MachineType::I64:
3704514f5e3Sopenharmony_ci            return ReduceWord64Lsr(gate);
3714514f5e3Sopenharmony_ci        default:
3724514f5e3Sopenharmony_ci            break;
3734514f5e3Sopenharmony_ci    }
3744514f5e3Sopenharmony_ci    return Circuit::NullGate();
3754514f5e3Sopenharmony_ci}
3764514f5e3Sopenharmony_ci
3774514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitASR(GateRef gate)
3784514f5e3Sopenharmony_ci{
3794514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3804514f5e3Sopenharmony_ci    switch (machineType) {
3814514f5e3Sopenharmony_ci        case MachineType::I32:
3824514f5e3Sopenharmony_ci            return ReduceWord32Asr(gate);
3834514f5e3Sopenharmony_ci        case MachineType::I64:
3844514f5e3Sopenharmony_ci            return ReduceWord64Asr(gate);
3854514f5e3Sopenharmony_ci        default:
3864514f5e3Sopenharmony_ci            break;
3874514f5e3Sopenharmony_ci    }
3884514f5e3Sopenharmony_ci    return Circuit::NullGate();
3894514f5e3Sopenharmony_ci}
3904514f5e3Sopenharmony_ci
3914514f5e3Sopenharmony_ci
3924514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitLSL(GateRef gate)
3934514f5e3Sopenharmony_ci{
3944514f5e3Sopenharmony_ci    auto machineType = acc_.GetMachineType(gate);
3954514f5e3Sopenharmony_ci    switch (machineType) {
3964514f5e3Sopenharmony_ci        case MachineType::I32:
3974514f5e3Sopenharmony_ci            return ReduceWord32Lsl(gate);
3984514f5e3Sopenharmony_ci        case MachineType::I64:
3994514f5e3Sopenharmony_ci            return ReduceWord64Lsl(gate);
4004514f5e3Sopenharmony_ci        default:
4014514f5e3Sopenharmony_ci            break;
4024514f5e3Sopenharmony_ci    }
4034514f5e3Sopenharmony_ci    return Circuit::NullGate();
4044514f5e3Sopenharmony_ci}
4054514f5e3Sopenharmony_ci
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_ciGateRef InstructionCombine::VisitExtractValue(GateRef gate)
4084514f5e3Sopenharmony_ci{
4094514f5e3Sopenharmony_ci    Int32BinopMatcher n(gate, circuit_);
4104514f5e3Sopenharmony_ci    int32_t index = n.Right().ResolvedValue();
4114514f5e3Sopenharmony_ci    int32_t val;
4124514f5e3Sopenharmony_ci    assert(index == 0 || index == 1);
4134514f5e3Sopenharmony_ci    switch (n.Left().Opcode()) {
4144514f5e3Sopenharmony_ci        case OpCode::ADD_WITH_OVERFLOW:
4154514f5e3Sopenharmony_ci            {
4164514f5e3Sopenharmony_ci                Int32BinopMatcher m(n.Left().Gate(), circuit_);
4174514f5e3Sopenharmony_ci                if (m.IsFoldable()) {
4184514f5e3Sopenharmony_ci                    bool ovf = base::SignedAddOverflow32(m.Left().ResolvedValue(), m.Right().ResolvedValue(), &val);
4194514f5e3Sopenharmony_ci                    return index == 0 ? builder_.Int32(val) : builder_.Boolean(ovf);
4204514f5e3Sopenharmony_ci                }
4214514f5e3Sopenharmony_ci                if (m.Right().Is(0)) {
4224514f5e3Sopenharmony_ci                    return (index == 0 ? m.Left().Gate() : builder_.Boolean(false));
4234514f5e3Sopenharmony_ci                }
4244514f5e3Sopenharmony_ci                break;
4254514f5e3Sopenharmony_ci            }
4264514f5e3Sopenharmony_ci        case OpCode::SUB_WITH_OVERFLOW:
4274514f5e3Sopenharmony_ci            {
4284514f5e3Sopenharmony_ci                Int32BinopMatcher m(n.Left().Gate(), circuit_);
4294514f5e3Sopenharmony_ci                if (m.IsFoldable()) {
4304514f5e3Sopenharmony_ci                    bool ovf = base::SignedSubOverflow32(m.Left().ResolvedValue(), m.Right().ResolvedValue(), &val);
4314514f5e3Sopenharmony_ci                    return index == 0 ? builder_.Int32(val) : builder_.Boolean(ovf);
4324514f5e3Sopenharmony_ci                }
4334514f5e3Sopenharmony_ci                if (m.Right().Is(0)) {
4344514f5e3Sopenharmony_ci                    return (index == 0 ? m.Left().Gate() : builder_.Boolean(false));
4354514f5e3Sopenharmony_ci                }
4364514f5e3Sopenharmony_ci                break;
4374514f5e3Sopenharmony_ci            }
4384514f5e3Sopenharmony_ci        case OpCode::MUL_WITH_OVERFLOW:
4394514f5e3Sopenharmony_ci            {
4404514f5e3Sopenharmony_ci                Int32BinopMatcher m(n.Left().Gate(), circuit_);
4414514f5e3Sopenharmony_ci                if (m.IsFoldable()) {
4424514f5e3Sopenharmony_ci                    bool ovf = base::SignedMulOverflow32(m.Left().ResolvedValue(), m.Right().ResolvedValue(), &val);
4434514f5e3Sopenharmony_ci                    return index == 0 ? builder_.Int32(val) : builder_.Boolean(ovf);
4444514f5e3Sopenharmony_ci                }
4454514f5e3Sopenharmony_ci                if (m.Right().Is(0)) {
4464514f5e3Sopenharmony_ci                    return (index == 0 ? builder_.Int32(0) : builder_.Boolean(false));
4474514f5e3Sopenharmony_ci                }
4484514f5e3Sopenharmony_ci                if (m.Right().Is(1)) {
4494514f5e3Sopenharmony_ci                    return (index == 0 ? m.Left().Gate() : builder_.Boolean(false));
4504514f5e3Sopenharmony_ci                }
4514514f5e3Sopenharmony_ci                break;
4524514f5e3Sopenharmony_ci            }
4534514f5e3Sopenharmony_ci        default:
4544514f5e3Sopenharmony_ci            break;
4554514f5e3Sopenharmony_ci    }
4564514f5e3Sopenharmony_ci    return Circuit::NullGate();
4574514f5e3Sopenharmony_ci}
4584514f5e3Sopenharmony_ci
4594514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt64Add(GateRef gate)
4604514f5e3Sopenharmony_ci{
4614514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
4624514f5e3Sopenharmony_ci
4634514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
4644514f5e3Sopenharmony_ci        return m.Left().Gate();
4654514f5e3Sopenharmony_ci    }
4664514f5e3Sopenharmony_ci
4674514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
4684514f5e3Sopenharmony_ci        return builder_.Int64(base::AddWithWraparound(m.Right().ResolvedValue(), m.Left().ResolvedValue()));
4694514f5e3Sopenharmony_ci    }
4704514f5e3Sopenharmony_ci
4714514f5e3Sopenharmony_ci    // (x + Int64Constant(a)) + Int64Constant(b) => x + Int64Constant(a + b)
4724514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt64Add()) {
4734514f5e3Sopenharmony_ci        Int64BinopMatcher mLeft(m.Left().Gate(), circuit_);
4744514f5e3Sopenharmony_ci        if (mLeft.Right().HasResolvedValue() && m.OwnsInput(m.Left().Gate())) {
4754514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, mLeft.Left().Gate(), 0);
4764514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, builder_.Int64(base::AddWithWraparound(
4774514f5e3Sopenharmony_ci                m.Right().ResolvedValue(), mLeft.Right().ResolvedValue())), 1);
4784514f5e3Sopenharmony_ci            return gate;
4794514f5e3Sopenharmony_ci        }
4804514f5e3Sopenharmony_ci    }
4814514f5e3Sopenharmony_ci
4824514f5e3Sopenharmony_ci    return Circuit::NullGate();
4834514f5e3Sopenharmony_ci}
4844514f5e3Sopenharmony_ci
4854514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt32Add(GateRef gate)
4864514f5e3Sopenharmony_ci{
4874514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
4884514f5e3Sopenharmony_ci    // x + 0 => x
4894514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
4904514f5e3Sopenharmony_ci        return m.Left().Gate();
4914514f5e3Sopenharmony_ci    }
4924514f5e3Sopenharmony_ci
4934514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
4944514f5e3Sopenharmony_ci        return builder_.Int32(base::AddWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
4954514f5e3Sopenharmony_ci    }
4964514f5e3Sopenharmony_ci
4974514f5e3Sopenharmony_ci    if (m.Left().IsmInt32Sub()) {
4984514f5e3Sopenharmony_ci        Int32BinopMatcher mleft(m.Left().Gate(), circuit_);
4994514f5e3Sopenharmony_ci        // (0 - x) + y => y - x
5004514f5e3Sopenharmony_ci        if (mleft.Left().Is(0)) {
5014514f5e3Sopenharmony_ci            auto newGate = builder_.Int32Sub(m.Right().Gate(), mleft.Right().Gate());
5024514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
5034514f5e3Sopenharmony_ci        }
5044514f5e3Sopenharmony_ci    }
5054514f5e3Sopenharmony_ci
5064514f5e3Sopenharmony_ci    if (m.Right().IsmInt32Sub()) {
5074514f5e3Sopenharmony_ci        Int32BinopMatcher mright(m.Right().Gate(), circuit_);
5084514f5e3Sopenharmony_ci        // y + (0 - x) => y - x
5094514f5e3Sopenharmony_ci        if (mright.Left().Is(0)) {
5104514f5e3Sopenharmony_ci            auto newGate = builder_.Int32Sub(m.Left().Gate(), mright.Right().Gate());
5114514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
5124514f5e3Sopenharmony_ci        }
5134514f5e3Sopenharmony_ci    }
5144514f5e3Sopenharmony_ci    // (x + Int32Constant(a)) + Int32Constant(b)) => x + Int32Constant(a + b)
5154514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt32Add()) {
5164514f5e3Sopenharmony_ci        Int32BinopMatcher mleft(m.Left().Gate(), circuit_);
5174514f5e3Sopenharmony_ci        if (mleft.Right().HasResolvedValue() && m.OwnsInput(m.Left().Gate())) {
5184514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, mleft.Left().Gate(), 0);
5194514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, builder_.Int32(base::AddWithWraparound(
5204514f5e3Sopenharmony_ci                mleft.Right().ResolvedValue(), m.Right().ResolvedValue())), 1);
5214514f5e3Sopenharmony_ci            return gate;
5224514f5e3Sopenharmony_ci        }
5234514f5e3Sopenharmony_ci    }
5244514f5e3Sopenharmony_ci    return Circuit::NullGate();
5254514f5e3Sopenharmony_ci}
5264514f5e3Sopenharmony_ci
5274514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt64Sub(GateRef gate)
5284514f5e3Sopenharmony_ci{
5294514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
5304514f5e3Sopenharmony_ci    // x - 0 => x
5314514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
5324514f5e3Sopenharmony_ci        return (m.Left().Gate());
5334514f5e3Sopenharmony_ci    }
5344514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
5354514f5e3Sopenharmony_ci        return builder_.Int64(base::SubWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
5364514f5e3Sopenharmony_ci    }
5374514f5e3Sopenharmony_ci    // x - x => 0
5384514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
5394514f5e3Sopenharmony_ci        return builder_.Int64(0);
5404514f5e3Sopenharmony_ci    }
5414514f5e3Sopenharmony_ci    // x - K => x + -K
5424514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue()) {
5434514f5e3Sopenharmony_ci        auto newGate =
5444514f5e3Sopenharmony_ci            builder_.Int64Add(m.Left().Gate(), builder_.Int64(base::NegateWithWraparound(m.Right().ResolvedValue())));
5454514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
5464514f5e3Sopenharmony_ci    }
5474514f5e3Sopenharmony_ci    return Circuit::NullGate();
5484514f5e3Sopenharmony_ci}
5494514f5e3Sopenharmony_ci
5504514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt32Sub(GateRef gate)
5514514f5e3Sopenharmony_ci{
5524514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
5534514f5e3Sopenharmony_ci    // x - 0 => x
5544514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
5554514f5e3Sopenharmony_ci        return (m.Left().Gate());
5564514f5e3Sopenharmony_ci    }
5574514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
5584514f5e3Sopenharmony_ci        return builder_.Int32(base::SubWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
5594514f5e3Sopenharmony_ci    }
5604514f5e3Sopenharmony_ci    // x - x => 0
5614514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
5624514f5e3Sopenharmony_ci        return builder_.Int32(0);
5634514f5e3Sopenharmony_ci    }
5644514f5e3Sopenharmony_ci    // x - K => x + -K
5654514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue()) {
5664514f5e3Sopenharmony_ci        auto newGate =
5674514f5e3Sopenharmony_ci            builder_.Int32Add(m.Left().Gate(), builder_.Int32(base::NegateWithWraparound(m.Right().ResolvedValue())));
5684514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
5694514f5e3Sopenharmony_ci    }
5704514f5e3Sopenharmony_ci    return Circuit::NullGate();
5714514f5e3Sopenharmony_ci}
5724514f5e3Sopenharmony_ci
5734514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt64Mul(GateRef gate)
5744514f5e3Sopenharmony_ci{
5754514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
5764514f5e3Sopenharmony_ci    // x * 0 => 0
5774514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
5784514f5e3Sopenharmony_ci        return m.Right().Gate();
5794514f5e3Sopenharmony_ci    }
5804514f5e3Sopenharmony_ci    // x * 1 => x
5814514f5e3Sopenharmony_ci    if (m.Right().Is(1)) {
5824514f5e3Sopenharmony_ci        return m.Left().Gate();
5834514f5e3Sopenharmony_ci    }
5844514f5e3Sopenharmony_ci    // K * K => K  (K stands for arbitrary constants)
5854514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
5864514f5e3Sopenharmony_ci        return builder_.Int64(base::MulWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
5874514f5e3Sopenharmony_ci    }
5884514f5e3Sopenharmony_ci    // x * -1 => 0 - x
5894514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
5904514f5e3Sopenharmony_ci        auto newGate = builder_.Int64Sub(builder_.Int64(0), m.Left().Gate());
5914514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
5924514f5e3Sopenharmony_ci    }
5934514f5e3Sopenharmony_ci    // x * 2^n => x << n
5944514f5e3Sopenharmony_ci    if (m.Right().IsPowerOf2()) {
5954514f5e3Sopenharmony_ci        auto newGate = builder_.Int64LSL(m.Left().Gate(), builder_.Int64(
5964514f5e3Sopenharmony_ci            base::WhichPowerOfTwo(m.Right().ResolvedValue())));
5974514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
5984514f5e3Sopenharmony_ci    }
5994514f5e3Sopenharmony_ci
6004514f5e3Sopenharmony_ci    // (x * Int64Constant(a)) * Int64Constant(b)) => x * Int64Constant(a * b)
6014514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt64Mul()) {
6024514f5e3Sopenharmony_ci        Int64BinopMatcher n(m.Left().Gate(), circuit_);
6034514f5e3Sopenharmony_ci        if (n.Right().HasResolvedValue() && m.OwnsInput(m.Left().Gate())) {
6044514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, n.Left().Gate(), 0);
6054514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(
6064514f5e3Sopenharmony_ci                gate, builder_.Int64(base::MulWithWraparound(n.Right().ResolvedValue(), m.Right().ResolvedValue())), 1);
6074514f5e3Sopenharmony_ci            return gate;
6084514f5e3Sopenharmony_ci        }
6094514f5e3Sopenharmony_ci    }
6104514f5e3Sopenharmony_ci
6114514f5e3Sopenharmony_ci    return Circuit::NullGate();
6124514f5e3Sopenharmony_ci}
6134514f5e3Sopenharmony_ci
6144514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt32Mul(GateRef gate)
6154514f5e3Sopenharmony_ci{
6164514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
6174514f5e3Sopenharmony_ci    // x * 0 => 0
6184514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
6194514f5e3Sopenharmony_ci        return m.Right().Gate();
6204514f5e3Sopenharmony_ci    }
6214514f5e3Sopenharmony_ci    // x * 1 => x
6224514f5e3Sopenharmony_ci    if (m.Right().Is(1)) {
6234514f5e3Sopenharmony_ci        return m.Left().Gate();
6244514f5e3Sopenharmony_ci    }
6254514f5e3Sopenharmony_ci    // K * K => K  (K stands for arbitrary constants)
6264514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
6274514f5e3Sopenharmony_ci        return builder_.Int32(base::MulWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
6284514f5e3Sopenharmony_ci    }
6294514f5e3Sopenharmony_ci    // x * -1 => 0 - x
6304514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
6314514f5e3Sopenharmony_ci        auto newGate = builder_.Int32Sub(builder_.Int32(0), m.Left().Gate());
6324514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
6334514f5e3Sopenharmony_ci    }
6344514f5e3Sopenharmony_ci    // x * 2^n => x << n
6354514f5e3Sopenharmony_ci    if (m.Right().IsPowerOf2()) {
6364514f5e3Sopenharmony_ci        auto newGate = builder_.Int32LSL(m.Left().Gate(), builder_.Int32(
6374514f5e3Sopenharmony_ci            base::WhichPowerOfTwo(m.Right().ResolvedValue())));
6384514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
6394514f5e3Sopenharmony_ci    }
6404514f5e3Sopenharmony_ci
6414514f5e3Sopenharmony_ci    // (x * Int32Constant(a)) * Int32Constant(b)) => x * Int32Constant(a * b)
6424514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt32Mul()) {
6434514f5e3Sopenharmony_ci        Int32BinopMatcher n(m.Left().Gate(), circuit_);
6444514f5e3Sopenharmony_ci        if (n.Right().HasResolvedValue() && m.OwnsInput(m.Left().Gate())) {
6454514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(gate, n.Left().Gate(), 0);
6464514f5e3Sopenharmony_ci            acc_.ReplaceValueIn(
6474514f5e3Sopenharmony_ci                gate, builder_.Int32(base::MulWithWraparound(n.Right().ResolvedValue(), m.Right().ResolvedValue())), 1);
6484514f5e3Sopenharmony_ci            return gate;
6494514f5e3Sopenharmony_ci        }
6504514f5e3Sopenharmony_ci    }
6514514f5e3Sopenharmony_ci
6524514f5e3Sopenharmony_ci    return Circuit::NullGate();
6534514f5e3Sopenharmony_ci}
6544514f5e3Sopenharmony_ci
6554514f5e3Sopenharmony_ci
6564514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt64Div(GateRef gate)
6574514f5e3Sopenharmony_ci{
6584514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
6594514f5e3Sopenharmony_ci    // 0 / x => 0
6604514f5e3Sopenharmony_ci    if (m.Left().Is(0)) {
6614514f5e3Sopenharmony_ci        return m.Left().Gate();
6624514f5e3Sopenharmony_ci    }
6634514f5e3Sopenharmony_ci    // x / 0 => 0
6644514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
6654514f5e3Sopenharmony_ci        return m.Right().Gate();
6664514f5e3Sopenharmony_ci    }
6674514f5e3Sopenharmony_ci    // x / 1 => x
6684514f5e3Sopenharmony_ci    if (m.Right().Is(1)) {
6694514f5e3Sopenharmony_ci        return m.Left().Gate();
6704514f5e3Sopenharmony_ci    }
6714514f5e3Sopenharmony_ci    // K / K => K
6724514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
6734514f5e3Sopenharmony_ci        return builder_.Int64(base::SignedDiv64(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
6744514f5e3Sopenharmony_ci    }
6754514f5e3Sopenharmony_ci    // x / -1 => 0 - x
6764514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
6774514f5e3Sopenharmony_ci        auto newGate = builder_.Int64Sub(builder_.Int64(0), m.Left().Gate());
6784514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
6794514f5e3Sopenharmony_ci    }
6804514f5e3Sopenharmony_ci
6814514f5e3Sopenharmony_ci    //  x/-K => 0-(x/K)
6824514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue()) {
6834514f5e3Sopenharmony_ci        int64_t const divisor = m.Right().ResolvedValue();
6844514f5e3Sopenharmony_ci        if (divisor < 0) {
6854514f5e3Sopenharmony_ci            auto newDiv = builder_.Int64Div(m.Left().Gate(), builder_.Int64(abs(m.Right().ResolvedValue())));
6864514f5e3Sopenharmony_ci            auto newGate = builder_.Int64Sub(builder_.Int64(0), newDiv);
6874514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
6884514f5e3Sopenharmony_ci        }
6894514f5e3Sopenharmony_ci    }
6904514f5e3Sopenharmony_ci    return Circuit::NullGate();
6914514f5e3Sopenharmony_ci}
6924514f5e3Sopenharmony_ci
6934514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt32Div(GateRef gate)
6944514f5e3Sopenharmony_ci{
6954514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
6964514f5e3Sopenharmony_ci    // 0 / x => 0
6974514f5e3Sopenharmony_ci    if (m.Left().Is(0)) {
6984514f5e3Sopenharmony_ci        return m.Left().Gate();
6994514f5e3Sopenharmony_ci    }
7004514f5e3Sopenharmony_ci    // x / 0 => 0
7014514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
7024514f5e3Sopenharmony_ci        return m.Right().Gate();
7034514f5e3Sopenharmony_ci    }
7044514f5e3Sopenharmony_ci    // x / 1 => x
7054514f5e3Sopenharmony_ci    if (m.Right().Is(1)) {
7064514f5e3Sopenharmony_ci        return m.Left().Gate();
7074514f5e3Sopenharmony_ci    }
7084514f5e3Sopenharmony_ci    // K / K => K
7094514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
7104514f5e3Sopenharmony_ci        return builder_.Int32(base::SignedDiv32(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
7114514f5e3Sopenharmony_ci    }
7124514f5e3Sopenharmony_ci    // x / -1 => 0 - x
7134514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
7144514f5e3Sopenharmony_ci        auto newGate = builder_.Int32Sub(builder_.Int32(0), m.Left().Gate());
7154514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
7164514f5e3Sopenharmony_ci    }
7174514f5e3Sopenharmony_ci
7184514f5e3Sopenharmony_ci    //  x/-K => 0-(x/K)
7194514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue()) {
7204514f5e3Sopenharmony_ci        int32_t const divisor = m.Right().ResolvedValue();
7214514f5e3Sopenharmony_ci        if (divisor < 0) {
7224514f5e3Sopenharmony_ci            auto newDiv = builder_.Int32Div(m.Left().Gate(), builder_.Int32(abs(m.Right().ResolvedValue())));
7234514f5e3Sopenharmony_ci            auto newGate = builder_.Int32Sub(builder_.Int32(0), newDiv);
7244514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
7254514f5e3Sopenharmony_ci        }
7264514f5e3Sopenharmony_ci    }
7274514f5e3Sopenharmony_ci    return Circuit::NullGate();
7284514f5e3Sopenharmony_ci}
7294514f5e3Sopenharmony_ci
7304514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceDoubleAdd(GateRef gate)
7314514f5e3Sopenharmony_ci{
7324514f5e3Sopenharmony_ci    Float64BinopMatcher m(gate, circuit_);
7334514f5e3Sopenharmony_ci    // x + NaN => NaN
7344514f5e3Sopenharmony_ci    if (m.Right().IsNaN()) {
7354514f5e3Sopenharmony_ci        return builder_.NanValue();
7364514f5e3Sopenharmony_ci    }
7374514f5e3Sopenharmony_ci    // NaN + x => NaN
7384514f5e3Sopenharmony_ci    if (m.Left().IsNaN()) {
7394514f5e3Sopenharmony_ci        return builder_.NanValue();
7404514f5e3Sopenharmony_ci    }
7414514f5e3Sopenharmony_ci    // K + K => K  (K stands for arbitrary constants)
7424514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
7434514f5e3Sopenharmony_ci        return builder_.Double(m.Left().ResolvedValue() + m.Right().ResolvedValue());
7444514f5e3Sopenharmony_ci    }
7454514f5e3Sopenharmony_ci    return Circuit::NullGate();
7464514f5e3Sopenharmony_ci}
7474514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceDoubleSub(GateRef gate)
7484514f5e3Sopenharmony_ci{
7494514f5e3Sopenharmony_ci    Float64BinopMatcher m(gate, circuit_);
7504514f5e3Sopenharmony_ci    // x - NaN => NaN
7514514f5e3Sopenharmony_ci    if (m.Right().IsNaN()) {
7524514f5e3Sopenharmony_ci        return builder_.NanValue();
7534514f5e3Sopenharmony_ci    }
7544514f5e3Sopenharmony_ci    // NaN - x => NaN
7554514f5e3Sopenharmony_ci    if (m.Left().IsNaN()) {
7564514f5e3Sopenharmony_ci        return builder_.NanValue();
7574514f5e3Sopenharmony_ci    }
7584514f5e3Sopenharmony_ci    // L - R => (L - R)
7594514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
7604514f5e3Sopenharmony_ci        return builder_.Double(m.Left().ResolvedValue() - m.Right().ResolvedValue());
7614514f5e3Sopenharmony_ci    }
7624514f5e3Sopenharmony_ci    return Circuit::NullGate();
7634514f5e3Sopenharmony_ci}
7644514f5e3Sopenharmony_ci
7654514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceDoubleMul(GateRef gate)
7664514f5e3Sopenharmony_ci{
7674514f5e3Sopenharmony_ci    Float64BinopMatcher m(gate, circuit_);
7684514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) { // x * -1.0 => -0.0 - x
7694514f5e3Sopenharmony_ci        auto newGate = builder_.DoubleSub(builder_.Double(-0.0), m.Left().Gate());
7704514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
7714514f5e3Sopenharmony_ci    }
7724514f5e3Sopenharmony_ci    if (m.Right().IsNaN()) { // x * NaN => NaN
7734514f5e3Sopenharmony_ci        return builder_.NanValue();
7744514f5e3Sopenharmony_ci    }
7754514f5e3Sopenharmony_ci    if (m.IsFoldable()) { // K * K => K  (K stands for arbitrary constants)
7764514f5e3Sopenharmony_ci        return builder_.Double(m.Left().ResolvedValue() * m.Right().ResolvedValue());
7774514f5e3Sopenharmony_ci    }
7784514f5e3Sopenharmony_ci    if (m.Right().Is(2)) { // x * 2.0 => x + x
7794514f5e3Sopenharmony_ci        auto newGate = builder_.DoubleAdd(m.Left().Gate(), m.Left().Gate());
7804514f5e3Sopenharmony_ci        return ReplaceOld(gate, newGate);
7814514f5e3Sopenharmony_ci    }
7824514f5e3Sopenharmony_ci    return Circuit::NullGate();
7834514f5e3Sopenharmony_ci}
7844514f5e3Sopenharmony_ci
7854514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceDoubleDiv(GateRef gate)
7864514f5e3Sopenharmony_ci{
7874514f5e3Sopenharmony_ci    Float64BinopMatcher m(gate, circuit_);
7884514f5e3Sopenharmony_ci
7894514f5e3Sopenharmony_ci    if (m.Right().IsNaN()) { // x / NaN => NaN
7904514f5e3Sopenharmony_ci        return builder_.NanValue();
7914514f5e3Sopenharmony_ci    }
7924514f5e3Sopenharmony_ci    if (m.Left().IsNaN()) { // NaN / x => NaN
7934514f5e3Sopenharmony_ci        return builder_.NanValue();
7944514f5e3Sopenharmony_ci    }
7954514f5e3Sopenharmony_ci    if (m.IsFoldable()) { // K / K => K  (K stands for arbitrary constants)
7964514f5e3Sopenharmony_ci        return builder_.Double(base::Divide(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
7974514f5e3Sopenharmony_ci    }
7984514f5e3Sopenharmony_ci
7994514f5e3Sopenharmony_ci    return Circuit::NullGate();
8004514f5e3Sopenharmony_ci}
8014514f5e3Sopenharmony_ci
8024514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceInt32Mod(GateRef gate)
8034514f5e3Sopenharmony_ci{
8044514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
8054514f5e3Sopenharmony_ci    // 0 % x  => 0
8064514f5e3Sopenharmony_ci    if (m.Left().Is(0)) {
8074514f5e3Sopenharmony_ci        return m.Left().Gate();
8084514f5e3Sopenharmony_ci    }
8094514f5e3Sopenharmony_ci    // x % 0  => 0
8104514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
8114514f5e3Sopenharmony_ci        return m.Right().Gate();
8124514f5e3Sopenharmony_ci    }
8134514f5e3Sopenharmony_ci    // x % 1  => 0
8144514f5e3Sopenharmony_ci    if (m.Right().Is(1)) {
8154514f5e3Sopenharmony_ci        return builder_.Int32(0);
8164514f5e3Sopenharmony_ci    }
8174514f5e3Sopenharmony_ci    // x % -1 => 0
8184514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
8194514f5e3Sopenharmony_ci        return builder_.Int32(0);
8204514f5e3Sopenharmony_ci    }
8214514f5e3Sopenharmony_ci    // x % x  => 0
8224514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
8234514f5e3Sopenharmony_ci        return builder_.Int32(0);
8244514f5e3Sopenharmony_ci    }
8254514f5e3Sopenharmony_ci    // K % K => K  (K stands for arbitrary constants)
8264514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
8274514f5e3Sopenharmony_ci        return builder_.Int32(base::SignedMod32(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
8284514f5e3Sopenharmony_ci    }
8294514f5e3Sopenharmony_ci
8304514f5e3Sopenharmony_ci    return Circuit::NullGate();
8314514f5e3Sopenharmony_ci}
8324514f5e3Sopenharmony_ci
8334514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceDoubleMod(GateRef gate)
8344514f5e3Sopenharmony_ci{
8354514f5e3Sopenharmony_ci    Float64BinopMatcher m(gate, circuit_);
8364514f5e3Sopenharmony_ci    if (m.Right().Is(0)) { // x % 0 => NaN
8374514f5e3Sopenharmony_ci        return builder_.NanValue();
8384514f5e3Sopenharmony_ci    }
8394514f5e3Sopenharmony_ci    if (m.Right().IsNaN()) { // x % NaN => NaN
8404514f5e3Sopenharmony_ci        return builder_.NanValue();
8414514f5e3Sopenharmony_ci    }
8424514f5e3Sopenharmony_ci    if (m.Left().IsNaN()) { // NaN % x => NaN
8434514f5e3Sopenharmony_ci        return builder_.NanValue();
8444514f5e3Sopenharmony_ci    }
8454514f5e3Sopenharmony_ci    return Circuit::NullGate();
8464514f5e3Sopenharmony_ci}
8474514f5e3Sopenharmony_ci
8484514f5e3Sopenharmony_ci
8494514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64And(GateRef gate)
8504514f5e3Sopenharmony_ci{
8514514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
8524514f5e3Sopenharmony_ci    // x & 0  => 0
8534514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
8544514f5e3Sopenharmony_ci        return m.Right().Gate();
8554514f5e3Sopenharmony_ci    }
8564514f5e3Sopenharmony_ci    // x & -1 => x
8574514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
8584514f5e3Sopenharmony_ci        return m.Left().Gate();
8594514f5e3Sopenharmony_ci    }
8604514f5e3Sopenharmony_ci    // CMP & 1 => CMP
8614514f5e3Sopenharmony_ci    if (m.Left().IsIcmp() && m.Right().Is(1)) {
8624514f5e3Sopenharmony_ci        return m.Left().Gate();
8634514f5e3Sopenharmony_ci    }
8644514f5e3Sopenharmony_ci    // K & K  => K  (K stands for arbitrary constants)
8654514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
8664514f5e3Sopenharmony_ci        return builder_.Int64(static_cast<uint64_t>(m.Left().ResolvedValue()) &
8674514f5e3Sopenharmony_ci            static_cast<uint64_t>(m.Right().ResolvedValue()));
8684514f5e3Sopenharmony_ci    }
8694514f5e3Sopenharmony_ci    // x & x => x
8704514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
8714514f5e3Sopenharmony_ci        return m.Left().Gate();
8724514f5e3Sopenharmony_ci    }
8734514f5e3Sopenharmony_ci    // (x & K) & K => x & K
8744514f5e3Sopenharmony_ci    if (m.Left().IsmInt64And() && m.Right().HasResolvedValue()) {
8754514f5e3Sopenharmony_ci        Int64BinopMatcher mleft(m.Left().Gate(), circuit_);
8764514f5e3Sopenharmony_ci        if (mleft.Right().HasResolvedValue()) {
8774514f5e3Sopenharmony_ci            auto newGate = builder_.Int64And(
8784514f5e3Sopenharmony_ci                mleft.Left().Gate(), builder_.Int64(static_cast<uint64_t>(m.Right().ResolvedValue()) &
8794514f5e3Sopenharmony_ci                static_cast<uint64_t>(mleft.Right().ResolvedValue())));
8804514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
8814514f5e3Sopenharmony_ci        }
8824514f5e3Sopenharmony_ci    }
8834514f5e3Sopenharmony_ci    return Circuit::NullGate();
8844514f5e3Sopenharmony_ci}
8854514f5e3Sopenharmony_ci
8864514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32And(GateRef gate)
8874514f5e3Sopenharmony_ci{
8884514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
8894514f5e3Sopenharmony_ci    // x & 0  => 0
8904514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
8914514f5e3Sopenharmony_ci        return m.Right().Gate();
8924514f5e3Sopenharmony_ci    }
8934514f5e3Sopenharmony_ci    // x & -1 => x
8944514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
8954514f5e3Sopenharmony_ci        return m.Left().Gate();
8964514f5e3Sopenharmony_ci    }
8974514f5e3Sopenharmony_ci    // CMP & 1 => CMP
8984514f5e3Sopenharmony_ci    if (m.Left().IsIcmp() && m.Right().Is(1)) {
8994514f5e3Sopenharmony_ci        return m.Left().Gate();
9004514f5e3Sopenharmony_ci    }
9014514f5e3Sopenharmony_ci    // K & K  => K  (K stands for arbitrary constants)
9024514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
9034514f5e3Sopenharmony_ci        return builder_.Int32(static_cast<uint32_t>(m.Left().ResolvedValue()) &
9044514f5e3Sopenharmony_ci            static_cast<uint32_t>(m.Right().ResolvedValue()));
9054514f5e3Sopenharmony_ci    }
9064514f5e3Sopenharmony_ci    // x & x => x
9074514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
9084514f5e3Sopenharmony_ci        return m.Left().Gate();
9094514f5e3Sopenharmony_ci    }
9104514f5e3Sopenharmony_ci    // (x & K) & K => x & K
9114514f5e3Sopenharmony_ci    if (m.Left().IsmInt32And() && m.Right().HasResolvedValue()) {
9124514f5e3Sopenharmony_ci        Int32BinopMatcher mleft(m.Left().Gate(), circuit_);
9134514f5e3Sopenharmony_ci        if (mleft.Right().HasResolvedValue()) {
9144514f5e3Sopenharmony_ci            auto newGate = builder_.Int32And(
9154514f5e3Sopenharmony_ci                mleft.Left().Gate(), builder_.Int32(static_cast<uint32_t>(m.Right().ResolvedValue()) &
9164514f5e3Sopenharmony_ci                static_cast<uint32_t>(mleft.Right().ResolvedValue())));
9174514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
9184514f5e3Sopenharmony_ci        }
9194514f5e3Sopenharmony_ci    }
9204514f5e3Sopenharmony_ci    return Circuit::NullGate();
9214514f5e3Sopenharmony_ci}
9224514f5e3Sopenharmony_ci
9234514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64Or(GateRef gate)
9244514f5e3Sopenharmony_ci{
9254514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
9264514f5e3Sopenharmony_ci    // x | 0  => x
9274514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
9284514f5e3Sopenharmony_ci        return m.Left().Gate();
9294514f5e3Sopenharmony_ci    }
9304514f5e3Sopenharmony_ci    // x | -1 => -1
9314514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
9324514f5e3Sopenharmony_ci        return m.Right().Gate();
9334514f5e3Sopenharmony_ci    }
9344514f5e3Sopenharmony_ci    // K | K  => K  (K stands for arbitrary constants)
9354514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
9364514f5e3Sopenharmony_ci        return builder_.Int64(static_cast<uint64_t>(m.Left().ResolvedValue()) |
9374514f5e3Sopenharmony_ci            static_cast<uint64_t>(m.Right().ResolvedValue()));
9384514f5e3Sopenharmony_ci    }
9394514f5e3Sopenharmony_ci    // x | x => x
9404514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
9414514f5e3Sopenharmony_ci        return m.Left().Gate();
9424514f5e3Sopenharmony_ci    }
9434514f5e3Sopenharmony_ci
9444514f5e3Sopenharmony_ci    // (x & K1) | K2 => x | K2 if K2 has ones for every zero bit in K1.
9454514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt64And()) {
9464514f5e3Sopenharmony_ci        Int64BinopMatcher mand(m.Left().Gate(), circuit_);
9474514f5e3Sopenharmony_ci        if (mand.Right().HasResolvedValue()) {
9484514f5e3Sopenharmony_ci            if ((m.Right().ResolvedValue() | mand.Right().ResolvedValue()) == -1) {
9494514f5e3Sopenharmony_ci                acc_.ReplaceValueIn(gate, mand.Left().Gate(), 0);
9504514f5e3Sopenharmony_ci                return gate;
9514514f5e3Sopenharmony_ci            }
9524514f5e3Sopenharmony_ci        }
9534514f5e3Sopenharmony_ci    }
9544514f5e3Sopenharmony_ci    return Circuit::NullGate();
9554514f5e3Sopenharmony_ci}
9564514f5e3Sopenharmony_ci
9574514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32Or(GateRef gate)
9584514f5e3Sopenharmony_ci{
9594514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
9604514f5e3Sopenharmony_ci    // x | 0  => x
9614514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
9624514f5e3Sopenharmony_ci        return m.Left().Gate();
9634514f5e3Sopenharmony_ci    }
9644514f5e3Sopenharmony_ci    // x | -1 => -1
9654514f5e3Sopenharmony_ci    if (m.Right().Is(-1)) {
9664514f5e3Sopenharmony_ci        return m.Right().Gate();
9674514f5e3Sopenharmony_ci    }
9684514f5e3Sopenharmony_ci    // K | K  => K  (K stands for arbitrary constants)
9694514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
9704514f5e3Sopenharmony_ci        return builder_.Int32(static_cast<uint32_t>(m.Left().ResolvedValue()) |
9714514f5e3Sopenharmony_ci            static_cast<uint32_t>(m.Right().ResolvedValue()));
9724514f5e3Sopenharmony_ci    }
9734514f5e3Sopenharmony_ci    // x | x => x
9744514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
9754514f5e3Sopenharmony_ci        return m.Left().Gate();
9764514f5e3Sopenharmony_ci    }
9774514f5e3Sopenharmony_ci
9784514f5e3Sopenharmony_ci    // (x & K1) | K2 => x | K2 if K2 has ones for every zero bit in K1.
9794514f5e3Sopenharmony_ci    if (m.Right().HasResolvedValue() && m.Left().IsmInt32And()) {
9804514f5e3Sopenharmony_ci        Int32BinopMatcher mand(m.Left().Gate(), circuit_);
9814514f5e3Sopenharmony_ci        if (mand.Right().HasResolvedValue()) {
9824514f5e3Sopenharmony_ci            if ((m.Right().ResolvedValue() | mand.Right().ResolvedValue()) == -1) {
9834514f5e3Sopenharmony_ci                acc_.ReplaceValueIn(gate, mand.Left().Gate(), 0);
9844514f5e3Sopenharmony_ci                return gate;
9854514f5e3Sopenharmony_ci            }
9864514f5e3Sopenharmony_ci        }
9874514f5e3Sopenharmony_ci    }
9884514f5e3Sopenharmony_ci
9894514f5e3Sopenharmony_ci    return Circuit::NullGate();
9904514f5e3Sopenharmony_ci}
9914514f5e3Sopenharmony_ci
9924514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64Xor(GateRef gate)
9934514f5e3Sopenharmony_ci{
9944514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
9954514f5e3Sopenharmony_ci    // x ^ 0 => x
9964514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
9974514f5e3Sopenharmony_ci        return m.Left().Gate();
9984514f5e3Sopenharmony_ci    }
9994514f5e3Sopenharmony_ci    // K ^ K => K  (K stands for arbitrary constants)
10004514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
10014514f5e3Sopenharmony_ci        return builder_.Int64(m.Left().ResolvedValue() ^ m.Right().ResolvedValue());
10024514f5e3Sopenharmony_ci    }
10034514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
10044514f5e3Sopenharmony_ci        return builder_.Int64(0); // x ^ x => 0
10054514f5e3Sopenharmony_ci    }
10064514f5e3Sopenharmony_ci    // (x ^ -1) ^ -1 => x
10074514f5e3Sopenharmony_ci    if (m.Left().IsmInt64Xor() && m.Right().Is(-1)) {
10084514f5e3Sopenharmony_ci        Int64BinopMatcher mleft(m.Left().Gate(), circuit_);
10094514f5e3Sopenharmony_ci        if (mleft.Right().Is(-1)) {
10104514f5e3Sopenharmony_ci            return mleft.Left().Gate();
10114514f5e3Sopenharmony_ci        }
10124514f5e3Sopenharmony_ci    }
10134514f5e3Sopenharmony_ci    return Circuit::NullGate();
10144514f5e3Sopenharmony_ci}
10154514f5e3Sopenharmony_ci
10164514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32Xor(GateRef gate)
10174514f5e3Sopenharmony_ci{
10184514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
10194514f5e3Sopenharmony_ci    // x ^ 0 => x
10204514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
10214514f5e3Sopenharmony_ci        return m.Left().Gate();
10224514f5e3Sopenharmony_ci    }
10234514f5e3Sopenharmony_ci    // K ^ K => K  (K stands for arbitrary constants)
10244514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
10254514f5e3Sopenharmony_ci        return builder_.Int32(m.Left().ResolvedValue() ^ m.Right().ResolvedValue());
10264514f5e3Sopenharmony_ci    }
10274514f5e3Sopenharmony_ci    if (m.LeftEqualsRight()) {
10284514f5e3Sopenharmony_ci        return builder_.Int32(0); // x ^ x => 0
10294514f5e3Sopenharmony_ci    }
10304514f5e3Sopenharmony_ci    // (x ^ -1) ^ -1 => x
10314514f5e3Sopenharmony_ci    if (m.Left().IsmInt32Xor() && m.Right().Is(-1)) {
10324514f5e3Sopenharmony_ci        Int32BinopMatcher mleft(m.Left().Gate(), circuit_);
10334514f5e3Sopenharmony_ci        if (mleft.Right().Is(-1)) {
10344514f5e3Sopenharmony_ci            return mleft.Left().Gate();
10354514f5e3Sopenharmony_ci        }
10364514f5e3Sopenharmony_ci    }
10374514f5e3Sopenharmony_ci    return Circuit::NullGate();
10384514f5e3Sopenharmony_ci}
10394514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64Lsr(GateRef gate)
10404514f5e3Sopenharmony_ci{
10414514f5e3Sopenharmony_ci    Uint64BinopMatcher m(gate, circuit_);
10424514f5e3Sopenharmony_ci
10434514f5e3Sopenharmony_ci    // x >>> 0 => x
10444514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
10454514f5e3Sopenharmony_ci        return m.Left().Gate();
10464514f5e3Sopenharmony_ci    }
10474514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
10484514f5e3Sopenharmony_ci        // 63: The '63' here is used as a mask to limit the shift amount to 0-63 bits, preventing overflow.
10494514f5e3Sopenharmony_ci        return builder_.Int64(m.Left().ResolvedValue() >> (m.Right().ResolvedValue() & 63));
10504514f5e3Sopenharmony_ci    }
10514514f5e3Sopenharmony_ci    return Circuit::NullGate();
10524514f5e3Sopenharmony_ci}
10534514f5e3Sopenharmony_ci
10544514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32Lsr(GateRef gate)
10554514f5e3Sopenharmony_ci{
10564514f5e3Sopenharmony_ci    Uint32BinopMatcher m(gate, circuit_);
10574514f5e3Sopenharmony_ci    // x >>> 0 => x
10584514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
10594514f5e3Sopenharmony_ci        return m.Left().Gate();
10604514f5e3Sopenharmony_ci    }
10614514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
10624514f5e3Sopenharmony_ci        // 31: The '31' here is used as a mask to limit the shift amount to 0-31 bits, preventing overflow.
10634514f5e3Sopenharmony_ci        return builder_.Int32(m.Left().ResolvedValue() >> (m.Right().ResolvedValue() & 31));
10644514f5e3Sopenharmony_ci    }
10654514f5e3Sopenharmony_ci    // (m >>> s) == 0 implies ((x & m) >>> s) == 0
10664514f5e3Sopenharmony_ci    if (m.Left().IsmInt32And() && m.Right().HasResolvedValue()) {
10674514f5e3Sopenharmony_ci        Uint32BinopMatcher mleft(m.Left().Gate(), circuit_);
10684514f5e3Sopenharmony_ci        if (mleft.Right().HasResolvedValue()) {
10694514f5e3Sopenharmony_ci            uint32_t shift = m.Right().ResolvedValue() & 31;
10704514f5e3Sopenharmony_ci            uint32_t mask = mleft.Right().ResolvedValue();
10714514f5e3Sopenharmony_ci            if ((mask >> shift) == 0) {
10724514f5e3Sopenharmony_ci                return builder_.Int32(0);
10734514f5e3Sopenharmony_ci            }
10744514f5e3Sopenharmony_ci        }
10754514f5e3Sopenharmony_ci    }
10764514f5e3Sopenharmony_ci    return Circuit::NullGate();
10774514f5e3Sopenharmony_ci}
10784514f5e3Sopenharmony_ci
10794514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64Asr(GateRef gate)
10804514f5e3Sopenharmony_ci{
10814514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
10824514f5e3Sopenharmony_ci    // x >> 0 => x
10834514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
10844514f5e3Sopenharmony_ci        return m.Left().Gate();
10854514f5e3Sopenharmony_ci    }
10864514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
10874514f5e3Sopenharmony_ci        // 63: The '63' here is used as a mask to limit the shift amount to 0-63 bits, preventing overflow.
10884514f5e3Sopenharmony_ci        return builder_.Int64(m.Left().ResolvedValue() >> (m.Right().ResolvedValue() & 63));
10894514f5e3Sopenharmony_ci    }
10904514f5e3Sopenharmony_ci    return Circuit::NullGate();
10914514f5e3Sopenharmony_ci}
10924514f5e3Sopenharmony_ci
10934514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32Asr(GateRef gate)
10944514f5e3Sopenharmony_ci{
10954514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
10964514f5e3Sopenharmony_ci    // x >> 0 => x
10974514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
10984514f5e3Sopenharmony_ci        return m.Left().Gate();
10994514f5e3Sopenharmony_ci    }
11004514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
11014514f5e3Sopenharmony_ci        // 31: The '31' here is used as a mask to limit the shift amount to 0-31 bits, preventing overflow.
11024514f5e3Sopenharmony_ci        return builder_.Int32(m.Left().ResolvedValue() >> (m.Right().ResolvedValue() & 31));
11034514f5e3Sopenharmony_ci    }
11044514f5e3Sopenharmony_ci    if (m.Left().IsmInt32LSL()) {
11054514f5e3Sopenharmony_ci        Int32BinopMatcher mleft(m.Left().Gate(), circuit_);
11064514f5e3Sopenharmony_ci        if (mleft.Left().IsIcmp()) {
11074514f5e3Sopenharmony_ci            // Check if the right shift amount is 31 (logical shift by 31 bits).
11084514f5e3Sopenharmony_ci            if (m.Right().Is(31) && mleft.Right().Is(31)) {
11094514f5e3Sopenharmony_ci                auto newGate = builder_.Int32Sub(builder_.Int32(0), mleft.Left().Gate());
11104514f5e3Sopenharmony_ci                return ReplaceOld(gate, newGate);
11114514f5e3Sopenharmony_ci            }
11124514f5e3Sopenharmony_ci        } else if (mleft.Left().IsLoad()) {
11134514f5e3Sopenharmony_ci            // Check if the right shift amount is 24 (logical shift by 24 bits).
11144514f5e3Sopenharmony_ci            if (m.Right().Is(24) && mleft.Right().Is(24) &&
11154514f5e3Sopenharmony_ci                acc_.GetMachineType(mleft.Left().Gate()) == MachineType::I8) {
11164514f5e3Sopenharmony_ci                return mleft.Left().Gate();
11174514f5e3Sopenharmony_ci            }
11184514f5e3Sopenharmony_ci        }
11194514f5e3Sopenharmony_ci    }
11204514f5e3Sopenharmony_ci    return Circuit::NullGate();
11214514f5e3Sopenharmony_ci}
11224514f5e3Sopenharmony_ci
11234514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord64Lsl(GateRef gate)
11244514f5e3Sopenharmony_ci{
11254514f5e3Sopenharmony_ci    Int64BinopMatcher m(gate, circuit_);
11264514f5e3Sopenharmony_ci    // x << 0 => x
11274514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
11284514f5e3Sopenharmony_ci        return m.Left().Gate();
11294514f5e3Sopenharmony_ci    }
11304514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
11314514f5e3Sopenharmony_ci        return builder_.Int64(base::ShlWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
11324514f5e3Sopenharmony_ci    }
11334514f5e3Sopenharmony_ci    // Check if the right shift amount is in the range of 1 to 63 bits (inclusive).
11344514f5e3Sopenharmony_ci    if (m.Right().IsInRange(1, 63) && (m.Left().IsmInt64ASR() || m.Left().IsmInt64LSR())) {
11354514f5e3Sopenharmony_ci        Int64BinopMatcher mleft(m.Left().Gate(), circuit_);
11364514f5e3Sopenharmony_ci        // (x >>> K) << K => x & ~(2^K - 1)
11374514f5e3Sopenharmony_ci        // (x >> K) << K => x & ~(2^K - 1)
11384514f5e3Sopenharmony_ci        if (mleft.Right().Is(m.Right().ResolvedValue())) {
11394514f5e3Sopenharmony_ci            auto newGate = builder_.Int64And(
11404514f5e3Sopenharmony_ci                mleft.Left().Gate(), builder_.Int64(std::numeric_limits<uint64_t>::max() << m.Right().ResolvedValue()));
11414514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
11424514f5e3Sopenharmony_ci        }
11434514f5e3Sopenharmony_ci    }
11444514f5e3Sopenharmony_ci    return Circuit::NullGate();
11454514f5e3Sopenharmony_ci}
11464514f5e3Sopenharmony_ciGateRef InstructionCombine::ReduceWord32Lsl(GateRef gate)
11474514f5e3Sopenharmony_ci{
11484514f5e3Sopenharmony_ci    Int32BinopMatcher m(gate, circuit_);
11494514f5e3Sopenharmony_ci    // x << 0 => x
11504514f5e3Sopenharmony_ci    if (m.Right().Is(0)) {
11514514f5e3Sopenharmony_ci        return m.Left().Gate();
11524514f5e3Sopenharmony_ci    }
11534514f5e3Sopenharmony_ci    if (m.IsFoldable()) {
11544514f5e3Sopenharmony_ci        return builder_.Int32(base::ShlWithWraparound(m.Left().ResolvedValue(), m.Right().ResolvedValue()));
11554514f5e3Sopenharmony_ci    }
11564514f5e3Sopenharmony_ci
11574514f5e3Sopenharmony_ci    // Check if the right shift amount is in the range of 1 to 31 bits (inclusive).
11584514f5e3Sopenharmony_ci    if (m.Right().IsInRange(1, 31) && (m.Left().IsmInt32ASR() || m.Left().IsmInt32LSR())) {
11594514f5e3Sopenharmony_ci        Int64BinopMatcher mleft(m.Left().Gate(), circuit_);
11604514f5e3Sopenharmony_ci        // (x >>> K) << K => x & ~(2^K - 1)
11614514f5e3Sopenharmony_ci        // (x >> K) << K => x & ~(2^K - 1)
11624514f5e3Sopenharmony_ci        if (mleft.Right().Is(m.Right().ResolvedValue())) {
11634514f5e3Sopenharmony_ci            auto newGate = builder_.Int32And(
11644514f5e3Sopenharmony_ci                mleft.Left().Gate(), builder_.Int32(std::numeric_limits<uint64_t>::max() << m.Right().ResolvedValue()));
11654514f5e3Sopenharmony_ci            return ReplaceOld(gate, newGate);
11664514f5e3Sopenharmony_ci        }
11674514f5e3Sopenharmony_ci    }
11684514f5e3Sopenharmony_ci    return Circuit::NullGate();
11694514f5e3Sopenharmony_ci}
11704514f5e3Sopenharmony_ci
11714514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu