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