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 164514f5e3Sopenharmony_ci#include "constantfold.h" 174514f5e3Sopenharmony_ci#include <cmath> 184514f5e3Sopenharmony_ci#include <cfloat> 194514f5e3Sopenharmony_ci#include <climits> 204514f5e3Sopenharmony_ci#include <type_traits> 214514f5e3Sopenharmony_ci#include "mpl_logging.h" 224514f5e3Sopenharmony_ci#include "mir_function.h" 234514f5e3Sopenharmony_ci#include "mir_builder.h" 244514f5e3Sopenharmony_ci#include "global_tables.h" 254514f5e3Sopenharmony_ci#include "me_option.h" 264514f5e3Sopenharmony_ci#include "maple_phase_manager.h" 274514f5e3Sopenharmony_ci#include "mir_type.h" 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_cinamespace maple { 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_cinamespace { 324514f5e3Sopenharmony_ciconstexpr uint32 kByteSizeOfBit64 = 8; // byte number for 64 bit 334514f5e3Sopenharmony_ciconstexpr uint32 kBitSizePerByte = 8; 344514f5e3Sopenharmony_ciconstexpr maple::int32 kMaxOffset = INT_MAX - 8; 354514f5e3Sopenharmony_ci 364514f5e3Sopenharmony_cienum CompareRes : int64 { kLess = -1, kEqual = 0, kGreater = 1 }; 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_cistd::optional<IntVal> operator*(const std::optional<IntVal> &v1, const std::optional<IntVal> &v2) 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci if (!v1 && !v2) { 414514f5e3Sopenharmony_ci return std::nullopt; 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_ci // Perform all calculations in terms of the maximum available signed type. 454514f5e3Sopenharmony_ci // The value will be truncated for an appropriate type when constant is created in PairToExpr function 464514f5e3Sopenharmony_ci return v1 && v2 ? v1->Mul(*v2, PTY_i64) : IntVal(static_cast<uint64>(0), PTY_i64); 474514f5e3Sopenharmony_ci} 484514f5e3Sopenharmony_ci 494514f5e3Sopenharmony_ci// Perform all calculations in terms of the maximum available signed type. 504514f5e3Sopenharmony_ci// The value will be truncated for an appropriate type when constant is created in PairToExpr function 514514f5e3Sopenharmony_cistd::optional<IntVal> AddSub(const std::optional<IntVal> &v1, const std::optional<IntVal> &v2, bool isAdd) 524514f5e3Sopenharmony_ci{ 534514f5e3Sopenharmony_ci if (!v1 && !v2) { 544514f5e3Sopenharmony_ci return std::nullopt; 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_ci if (v1 && v2) { 584514f5e3Sopenharmony_ci return isAdd ? v1->Add(*v2, PTY_i64) : v1->Sub(*v2, PTY_i64); 594514f5e3Sopenharmony_ci } 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci if (v1) { 624514f5e3Sopenharmony_ci return v1->TruncOrExtend(PTY_i64); 634514f5e3Sopenharmony_ci } 644514f5e3Sopenharmony_ci 654514f5e3Sopenharmony_ci // !v1 && v2 664514f5e3Sopenharmony_ci return isAdd ? v2->TruncOrExtend(PTY_i64) : -(v2->TruncOrExtend(PTY_i64)); 674514f5e3Sopenharmony_ci} 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_cistd::optional<IntVal> operator+(const std::optional<IntVal> &v1, const std::optional<IntVal> &v2) 704514f5e3Sopenharmony_ci{ 714514f5e3Sopenharmony_ci return AddSub(v1, v2, true); 724514f5e3Sopenharmony_ci} 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_cistd::optional<IntVal> operator-(const std::optional<IntVal> &v1, const std::optional<IntVal> &v2) 754514f5e3Sopenharmony_ci{ 764514f5e3Sopenharmony_ci return AddSub(v1, v2, false); 774514f5e3Sopenharmony_ci} 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci} // anonymous namespace 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_ci// This phase is designed to achieve compiler optimization by 824514f5e3Sopenharmony_ci// simplifying constant expressions. The constant expression 834514f5e3Sopenharmony_ci// is evaluated and replaced by the value calculated on compile 844514f5e3Sopenharmony_ci// time to save time on runtime. 854514f5e3Sopenharmony_ci// 864514f5e3Sopenharmony_ci// The main procedure shows as following: 874514f5e3Sopenharmony_ci// A. Analyze expression type 884514f5e3Sopenharmony_ci// B. Analysis operator type 894514f5e3Sopenharmony_ci// C. Replace the expression with the result of the operation 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci// true if the constant's bits are made of only one group of contiguous 1's 924514f5e3Sopenharmony_ci// starting at bit 0 934514f5e3Sopenharmony_cistatic bool ContiguousBitsOf1(uint64 x) 944514f5e3Sopenharmony_ci{ 954514f5e3Sopenharmony_ci if (x == 0) { 964514f5e3Sopenharmony_ci return false; 974514f5e3Sopenharmony_ci } 984514f5e3Sopenharmony_ci return (~x & (x + 1)) == (x + 1); 994514f5e3Sopenharmony_ci} 1004514f5e3Sopenharmony_ci 1014514f5e3Sopenharmony_ciinline bool IsPowerOf2(uint64 num) 1024514f5e3Sopenharmony_ci{ 1034514f5e3Sopenharmony_ci if (num == 0) { 1044514f5e3Sopenharmony_ci return false; 1054514f5e3Sopenharmony_ci } 1064514f5e3Sopenharmony_ci return (~(num - 1) & num) == num; 1074514f5e3Sopenharmony_ci} 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_ciBinaryNode *ConstantFold::NewBinaryNode(BinaryNode *old, Opcode op, PrimType primType, BaseNode *lhs, 1104514f5e3Sopenharmony_ci BaseNode *rhs) const 1114514f5e3Sopenharmony_ci{ 1124514f5e3Sopenharmony_ci CHECK_NULL_FATAL(old); 1134514f5e3Sopenharmony_ci BinaryNode *result = nullptr; 1144514f5e3Sopenharmony_ci if (old->GetOpCode() == op && old->GetPrimType() == primType && old->Opnd(0) == lhs && old->Opnd(1) == rhs) { 1154514f5e3Sopenharmony_ci result = old; 1164514f5e3Sopenharmony_ci } else { 1174514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<BinaryNode>(op, primType, lhs, rhs); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci return result; 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ciUnaryNode *ConstantFold::NewUnaryNode(UnaryNode *old, Opcode op, PrimType primType, BaseNode *expr) const 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci CHECK_NULL_FATAL(old); 1254514f5e3Sopenharmony_ci UnaryNode *result = nullptr; 1264514f5e3Sopenharmony_ci if (old->GetOpCode() == op && old->GetPrimType() == primType && old->Opnd(0) == expr) { 1274514f5e3Sopenharmony_ci result = old; 1284514f5e3Sopenharmony_ci } else { 1294514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<UnaryNode>(op, primType, expr); 1304514f5e3Sopenharmony_ci } 1314514f5e3Sopenharmony_ci return result; 1324514f5e3Sopenharmony_ci} 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ciBaseNode *ConstantFold::PairToExpr(PrimType resultType, const std::pair<BaseNode*, std::optional<IntVal>> &pair) const 1354514f5e3Sopenharmony_ci{ 1364514f5e3Sopenharmony_ci CHECK_NULL_FATAL(pair.first); 1374514f5e3Sopenharmony_ci BaseNode *result = pair.first; 1384514f5e3Sopenharmony_ci if (!pair.second || *pair.second == 0 || GetPrimTypeSize(resultType) > k8ByteSize) { 1394514f5e3Sopenharmony_ci return result; 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci if (pair.first->GetOpCode() == OP_neg && !pair.second->GetSignBit()) { 1424514f5e3Sopenharmony_ci // -a, 5 -> 5 - a 1434514f5e3Sopenharmony_ci ConstvalNode *val = mirModule->GetMIRBuilder()->CreateIntConst( 1444514f5e3Sopenharmony_ci static_cast<uint64>(pair.second->GetExtValue()), resultType); 1454514f5e3Sopenharmony_ci BaseNode *r = static_cast<UnaryNode*>(pair.first)->Opnd(0); 1464514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<BinaryNode>(OP_sub, resultType, val, r); 1474514f5e3Sopenharmony_ci } else { 1484514f5e3Sopenharmony_ci if ((!pair.second->GetSignBit() && 1494514f5e3Sopenharmony_ci pair.second->GetSXTValue(static_cast<uint8>(GetPrimTypeBitSize(resultType))) > 0) || 1504514f5e3Sopenharmony_ci pair.second->TruncOrExtend(resultType).IsMinValue() || 1514514f5e3Sopenharmony_ci pair.second->GetSXTValue() == INT64_MIN) { 1524514f5e3Sopenharmony_ci // +-a, 5 -> a + 5 1534514f5e3Sopenharmony_ci ConstvalNode *val = mirModule->GetMIRBuilder()->CreateIntConst( 1544514f5e3Sopenharmony_ci static_cast<uint64>(pair.second->GetExtValue()), resultType); 1554514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<BinaryNode>(OP_add, resultType, pair.first, val); 1564514f5e3Sopenharmony_ci } else { 1574514f5e3Sopenharmony_ci // +-a, -5 -> a + -5 1584514f5e3Sopenharmony_ci ConstvalNode *val = mirModule->GetMIRBuilder()->CreateIntConst( 1594514f5e3Sopenharmony_ci static_cast<uint64>((-pair.second.value()).GetExtValue()), resultType); 1604514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<BinaryNode>(OP_sub, resultType, pair.first, val); 1614514f5e3Sopenharmony_ci } 1624514f5e3Sopenharmony_ci } 1634514f5e3Sopenharmony_ci return result; 1644514f5e3Sopenharmony_ci} 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_cistd::pair<BaseNode *, std::optional<IntVal>> ConstantFold::FoldBase(BaseNode *node) const 1674514f5e3Sopenharmony_ci{ 1684514f5e3Sopenharmony_ci return std::make_pair(node, std::nullopt); 1694514f5e3Sopenharmony_ci} 1704514f5e3Sopenharmony_ci 1714514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::DispatchFold(BaseNode *node) 1724514f5e3Sopenharmony_ci{ 1734514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 1744514f5e3Sopenharmony_ci if (GetPrimTypeSize(node->GetPrimType()) > k8ByteSize) { 1754514f5e3Sopenharmony_ci return {node, std::nullopt}; 1764514f5e3Sopenharmony_ci } 1774514f5e3Sopenharmony_ci switch (node->GetOpCode()) { 1784514f5e3Sopenharmony_ci case OP_abs: 1794514f5e3Sopenharmony_ci case OP_bnot: 1804514f5e3Sopenharmony_ci case OP_lnot: 1814514f5e3Sopenharmony_ci case OP_neg: 1824514f5e3Sopenharmony_ci case OP_sqrt: 1834514f5e3Sopenharmony_ci return FoldUnary(static_cast<UnaryNode*>(node)); 1844514f5e3Sopenharmony_ci case OP_ceil: 1854514f5e3Sopenharmony_ci case OP_floor: 1864514f5e3Sopenharmony_ci case OP_trunc: 1874514f5e3Sopenharmony_ci case OP_cvt: 1884514f5e3Sopenharmony_ci return FoldTypeCvt(static_cast<TypeCvtNode*>(node)); 1894514f5e3Sopenharmony_ci case OP_sext: 1904514f5e3Sopenharmony_ci case OP_zext: 1914514f5e3Sopenharmony_ci case OP_extractbits: 1924514f5e3Sopenharmony_ci return FoldExtractbits(static_cast<ExtractbitsNode*>(node)); 1934514f5e3Sopenharmony_ci case OP_iread: 1944514f5e3Sopenharmony_ci return FoldIread(static_cast<IreadNode*>(node)); 1954514f5e3Sopenharmony_ci case OP_add: 1964514f5e3Sopenharmony_ci case OP_ashr: 1974514f5e3Sopenharmony_ci case OP_band: 1984514f5e3Sopenharmony_ci case OP_bior: 1994514f5e3Sopenharmony_ci case OP_bxor: 2004514f5e3Sopenharmony_ci case OP_div: 2014514f5e3Sopenharmony_ci case OP_lshr: 2024514f5e3Sopenharmony_ci case OP_max: 2034514f5e3Sopenharmony_ci case OP_min: 2044514f5e3Sopenharmony_ci case OP_mul: 2054514f5e3Sopenharmony_ci case OP_rem: 2064514f5e3Sopenharmony_ci case OP_shl: 2074514f5e3Sopenharmony_ci case OP_sub: 2084514f5e3Sopenharmony_ci return FoldBinary(static_cast<BinaryNode*>(node)); 2094514f5e3Sopenharmony_ci case OP_eq: 2104514f5e3Sopenharmony_ci case OP_ne: 2114514f5e3Sopenharmony_ci case OP_ge: 2124514f5e3Sopenharmony_ci case OP_gt: 2134514f5e3Sopenharmony_ci case OP_le: 2144514f5e3Sopenharmony_ci case OP_lt: 2154514f5e3Sopenharmony_ci case OP_cmp: 2164514f5e3Sopenharmony_ci return FoldCompare(static_cast<CompareNode*>(node)); 2174514f5e3Sopenharmony_ci case OP_retype: 2184514f5e3Sopenharmony_ci return FoldRetype(static_cast<RetypeNode*>(node)); 2194514f5e3Sopenharmony_ci default: 2204514f5e3Sopenharmony_ci return FoldBase(static_cast<BaseNode*>(node)); 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci} 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_ciBaseNode *ConstantFold::Negate(BaseNode *node) const 2254514f5e3Sopenharmony_ci{ 2264514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 2274514f5e3Sopenharmony_ci return mirModule->CurFuncCodeMemPool()->New<UnaryNode>(OP_neg, PrimType(node->GetPrimType()), node); 2284514f5e3Sopenharmony_ci} 2294514f5e3Sopenharmony_ci 2304514f5e3Sopenharmony_ciBaseNode *ConstantFold::Negate(UnaryNode *node) const 2314514f5e3Sopenharmony_ci{ 2324514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 2334514f5e3Sopenharmony_ci BaseNode *result = nullptr; 2344514f5e3Sopenharmony_ci if (node->GetOpCode() == OP_neg) { 2354514f5e3Sopenharmony_ci result = static_cast<BaseNode*>(node->Opnd(0)); 2364514f5e3Sopenharmony_ci } else { 2374514f5e3Sopenharmony_ci BaseNode *n = static_cast<BaseNode*>(node); 2384514f5e3Sopenharmony_ci result = NewUnaryNode(node, OP_neg, node->GetPrimType(), n); 2394514f5e3Sopenharmony_ci } 2404514f5e3Sopenharmony_ci return result; 2414514f5e3Sopenharmony_ci} 2424514f5e3Sopenharmony_ci 2434514f5e3Sopenharmony_ciBaseNode *ConstantFold::Negate(const ConstvalNode *node) const 2444514f5e3Sopenharmony_ci{ 2454514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 2464514f5e3Sopenharmony_ci ConstvalNode *copy = node->CloneTree(mirModule->GetCurFuncCodeMPAllocator()); 2474514f5e3Sopenharmony_ci CHECK_NULL_FATAL(copy); 2484514f5e3Sopenharmony_ci copy->GetConstVal()->Neg(); 2494514f5e3Sopenharmony_ci return copy; 2504514f5e3Sopenharmony_ci} 2514514f5e3Sopenharmony_ci 2524514f5e3Sopenharmony_ciBaseNode *ConstantFold::NegateTree(BaseNode *node) const 2534514f5e3Sopenharmony_ci{ 2544514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 2554514f5e3Sopenharmony_ci if (node->IsUnaryNode()) { 2564514f5e3Sopenharmony_ci return Negate(static_cast<UnaryNode*>(node)); 2574514f5e3Sopenharmony_ci } else if (node->GetOpCode() == OP_constval) { 2584514f5e3Sopenharmony_ci return Negate(static_cast<ConstvalNode*>(node)); 2594514f5e3Sopenharmony_ci } else { 2604514f5e3Sopenharmony_ci return Negate(static_cast<BaseNode*>(node)); 2614514f5e3Sopenharmony_ci } 2624514f5e3Sopenharmony_ci} 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ciMIRIntConst *ConstantFold::FoldIntConstComparisonMIRConst(Opcode opcode, PrimType resultType, PrimType opndType, 2654514f5e3Sopenharmony_ci const MIRIntConst &intConst0, 2664514f5e3Sopenharmony_ci const MIRIntConst &intConst1) const 2674514f5e3Sopenharmony_ci{ 2684514f5e3Sopenharmony_ci uint64 result = 0; 2694514f5e3Sopenharmony_ci 2704514f5e3Sopenharmony_ci bool greater = intConst0.GetValue().Greater(intConst1.GetValue(), opndType); 2714514f5e3Sopenharmony_ci bool equal = intConst0.GetValue().Equal(intConst1.GetValue(), opndType); 2724514f5e3Sopenharmony_ci bool less = intConst0.GetValue().Less(intConst1.GetValue(), opndType); 2734514f5e3Sopenharmony_ci 2744514f5e3Sopenharmony_ci switch (opcode) { 2754514f5e3Sopenharmony_ci case OP_eq: { 2764514f5e3Sopenharmony_ci result = equal; 2774514f5e3Sopenharmony_ci break; 2784514f5e3Sopenharmony_ci } 2794514f5e3Sopenharmony_ci case OP_ge: { 2804514f5e3Sopenharmony_ci result = (greater || equal) ? 1 : 0; 2814514f5e3Sopenharmony_ci break; 2824514f5e3Sopenharmony_ci } 2834514f5e3Sopenharmony_ci case OP_gt: { 2844514f5e3Sopenharmony_ci result = greater; 2854514f5e3Sopenharmony_ci break; 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci case OP_le: { 2884514f5e3Sopenharmony_ci result = (less || equal) ? 1 : 0; 2894514f5e3Sopenharmony_ci break; 2904514f5e3Sopenharmony_ci } 2914514f5e3Sopenharmony_ci case OP_lt: { 2924514f5e3Sopenharmony_ci result = less; 2934514f5e3Sopenharmony_ci break; 2944514f5e3Sopenharmony_ci } 2954514f5e3Sopenharmony_ci case OP_ne: { 2964514f5e3Sopenharmony_ci result = !equal; 2974514f5e3Sopenharmony_ci break; 2984514f5e3Sopenharmony_ci } 2994514f5e3Sopenharmony_ci case OP_cmp: { 3004514f5e3Sopenharmony_ci if (greater) { 3014514f5e3Sopenharmony_ci result = kGreater; 3024514f5e3Sopenharmony_ci } else if (equal) { 3034514f5e3Sopenharmony_ci result = kEqual; 3044514f5e3Sopenharmony_ci } else if (less) { 3054514f5e3Sopenharmony_ci result = static_cast<uint64>(kLess); 3064514f5e3Sopenharmony_ci } 3074514f5e3Sopenharmony_ci break; 3084514f5e3Sopenharmony_ci } 3094514f5e3Sopenharmony_ci default: 3104514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldIntConstComparison"); 3114514f5e3Sopenharmony_ci break; 3124514f5e3Sopenharmony_ci } 3134514f5e3Sopenharmony_ci // determine the type 3144514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(resultType); 3154514f5e3Sopenharmony_ci // form the constant 3164514f5e3Sopenharmony_ci MIRIntConst *constValue = GlobalTables::GetIntConstTable().GetOrCreateIntConst(result, type); 3174514f5e3Sopenharmony_ci return constValue; 3184514f5e3Sopenharmony_ci} 3194514f5e3Sopenharmony_ci 3204514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldIntConstComparison(Opcode opcode, PrimType resultType, PrimType opndType, 3214514f5e3Sopenharmony_ci const ConstvalNode &const0, const ConstvalNode &const1) const 3224514f5e3Sopenharmony_ci{ 3234514f5e3Sopenharmony_ci const MIRIntConst *intConst0 = safe_cast<MIRIntConst>(const0.GetConstVal()); 3244514f5e3Sopenharmony_ci const MIRIntConst *intConst1 = safe_cast<MIRIntConst>(const1.GetConstVal()); 3254514f5e3Sopenharmony_ci CHECK_NULL_FATAL(intConst0); 3264514f5e3Sopenharmony_ci CHECK_NULL_FATAL(intConst1); 3274514f5e3Sopenharmony_ci MIRIntConst *constValue = FoldIntConstComparisonMIRConst(opcode, resultType, opndType, *intConst0, *intConst1); 3284514f5e3Sopenharmony_ci // form the ConstvalNode 3294514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 3304514f5e3Sopenharmony_ci resultConst->SetPrimType(resultType); 3314514f5e3Sopenharmony_ci resultConst->SetConstVal(constValue); 3324514f5e3Sopenharmony_ci return resultConst; 3334514f5e3Sopenharmony_ci} 3344514f5e3Sopenharmony_ci 3354514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldIntConstBinaryMIRConst(Opcode opcode, PrimType resultType, const MIRIntConst &intConst0, 3364514f5e3Sopenharmony_ci const MIRIntConst &intConst1) 3374514f5e3Sopenharmony_ci{ 3384514f5e3Sopenharmony_ci IntVal intVal0 = intConst0.GetValue(); 3394514f5e3Sopenharmony_ci IntVal intVal1 = intConst1.GetValue(); 3404514f5e3Sopenharmony_ci IntVal result(static_cast<uint64>(0), resultType); 3414514f5e3Sopenharmony_ci 3424514f5e3Sopenharmony_ci switch (opcode) { 3434514f5e3Sopenharmony_ci case OP_add: { 3444514f5e3Sopenharmony_ci result = intVal0.Add(intVal1, resultType); 3454514f5e3Sopenharmony_ci break; 3464514f5e3Sopenharmony_ci } 3474514f5e3Sopenharmony_ci case OP_sub: { 3484514f5e3Sopenharmony_ci result = intVal0.Sub(intVal1, resultType); 3494514f5e3Sopenharmony_ci break; 3504514f5e3Sopenharmony_ci } 3514514f5e3Sopenharmony_ci case OP_mul: { 3524514f5e3Sopenharmony_ci result = intVal0.Mul(intVal1, resultType); 3534514f5e3Sopenharmony_ci break; 3544514f5e3Sopenharmony_ci } 3554514f5e3Sopenharmony_ci case OP_div: { 3564514f5e3Sopenharmony_ci result = intVal0.Div(intVal1, resultType); 3574514f5e3Sopenharmony_ci break; 3584514f5e3Sopenharmony_ci } 3594514f5e3Sopenharmony_ci case OP_rem: { 3604514f5e3Sopenharmony_ci result = intVal0.Rem(intVal1, resultType); 3614514f5e3Sopenharmony_ci break; 3624514f5e3Sopenharmony_ci } 3634514f5e3Sopenharmony_ci case OP_ashr: { 3644514f5e3Sopenharmony_ci result = intVal0.AShr(intVal1.GetZXTValue() % GetAlignedPrimTypeBitSize(resultType), resultType); 3654514f5e3Sopenharmony_ci break; 3664514f5e3Sopenharmony_ci } 3674514f5e3Sopenharmony_ci case OP_lshr: { 3684514f5e3Sopenharmony_ci result = intVal0.LShr(intVal1.GetZXTValue() % GetAlignedPrimTypeBitSize(resultType), resultType); 3694514f5e3Sopenharmony_ci break; 3704514f5e3Sopenharmony_ci } 3714514f5e3Sopenharmony_ci case OP_shl: { 3724514f5e3Sopenharmony_ci result = intVal0.Shl(intVal1.GetZXTValue() % GetAlignedPrimTypeBitSize(resultType), resultType); 3734514f5e3Sopenharmony_ci break; 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci case OP_max: { 3764514f5e3Sopenharmony_ci result = Max(intVal0, intVal1, resultType); 3774514f5e3Sopenharmony_ci break; 3784514f5e3Sopenharmony_ci } 3794514f5e3Sopenharmony_ci case OP_min: { 3804514f5e3Sopenharmony_ci result = Min(intVal0, intVal1, resultType); 3814514f5e3Sopenharmony_ci break; 3824514f5e3Sopenharmony_ci } 3834514f5e3Sopenharmony_ci case OP_band: { 3844514f5e3Sopenharmony_ci result = intVal0.And(intVal1, resultType); 3854514f5e3Sopenharmony_ci break; 3864514f5e3Sopenharmony_ci } 3874514f5e3Sopenharmony_ci case OP_bior: { 3884514f5e3Sopenharmony_ci result = intVal0.Or(intVal1, resultType); 3894514f5e3Sopenharmony_ci break; 3904514f5e3Sopenharmony_ci } 3914514f5e3Sopenharmony_ci case OP_bxor: { 3924514f5e3Sopenharmony_ci result = intVal0.Xor(intVal1, resultType); 3934514f5e3Sopenharmony_ci break; 3944514f5e3Sopenharmony_ci } 3954514f5e3Sopenharmony_ci default: 3964514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldIntConstBinary"); 3974514f5e3Sopenharmony_ci break; 3984514f5e3Sopenharmony_ci } 3994514f5e3Sopenharmony_ci // determine the type 4004514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(resultType); 4014514f5e3Sopenharmony_ci // form the constant 4024514f5e3Sopenharmony_ci MIRIntConst *constValue = 4034514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(result.GetExtValue()), type); 4044514f5e3Sopenharmony_ci return constValue; 4054514f5e3Sopenharmony_ci} 4064514f5e3Sopenharmony_ci 4074514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldIntConstBinary(Opcode opcode, PrimType resultType, const ConstvalNode &const0, 4084514f5e3Sopenharmony_ci const ConstvalNode &const1) const 4094514f5e3Sopenharmony_ci{ 4104514f5e3Sopenharmony_ci const MIRIntConst *intConst0 = safe_cast<MIRIntConst>(const0.GetConstVal()); 4114514f5e3Sopenharmony_ci const MIRIntConst *intConst1 = safe_cast<MIRIntConst>(const1.GetConstVal()); 4124514f5e3Sopenharmony_ci CHECK_NULL_FATAL(intConst0); 4134514f5e3Sopenharmony_ci CHECK_NULL_FATAL(intConst1); 4144514f5e3Sopenharmony_ci MIRConst *constValue = FoldIntConstBinaryMIRConst(opcode, resultType, *intConst0, *intConst1); 4154514f5e3Sopenharmony_ci // form the ConstvalNode 4164514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 4174514f5e3Sopenharmony_ci resultConst->SetPrimType(resultType); 4184514f5e3Sopenharmony_ci resultConst->SetConstVal(constValue); 4194514f5e3Sopenharmony_ci return resultConst; 4204514f5e3Sopenharmony_ci} 4214514f5e3Sopenharmony_ci 4224514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldFPConstBinary(Opcode opcode, PrimType resultType, const ConstvalNode &const0, 4234514f5e3Sopenharmony_ci const ConstvalNode &const1) const 4244514f5e3Sopenharmony_ci{ 4254514f5e3Sopenharmony_ci DEBUG_ASSERT(const0.GetPrimType() == const1.GetPrimType(), "The types of the operands must match"); 4264514f5e3Sopenharmony_ci const MIRDoubleConst *doubleConst0 = nullptr; 4274514f5e3Sopenharmony_ci const MIRDoubleConst *doubleConst1 = nullptr; 4284514f5e3Sopenharmony_ci const MIRFloatConst *floatConst0 = nullptr; 4294514f5e3Sopenharmony_ci const MIRFloatConst *floatConst1 = nullptr; 4304514f5e3Sopenharmony_ci bool useDouble = (const0.GetPrimType() == PTY_f64); 4314514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 4324514f5e3Sopenharmony_ci resultConst->SetPrimType(resultType); 4334514f5e3Sopenharmony_ci if (useDouble) { 4344514f5e3Sopenharmony_ci doubleConst0 = safe_cast<MIRDoubleConst>(const0.GetConstVal()); 4354514f5e3Sopenharmony_ci doubleConst1 = safe_cast<MIRDoubleConst>(const1.GetConstVal()); 4364514f5e3Sopenharmony_ci CHECK_NULL_FATAL(doubleConst0); 4374514f5e3Sopenharmony_ci CHECK_NULL_FATAL(doubleConst1); 4384514f5e3Sopenharmony_ci } else { 4394514f5e3Sopenharmony_ci floatConst0 = safe_cast<MIRFloatConst>(const0.GetConstVal()); 4404514f5e3Sopenharmony_ci floatConst1 = safe_cast<MIRFloatConst>(const1.GetConstVal()); 4414514f5e3Sopenharmony_ci CHECK_NULL_FATAL(floatConst0); 4424514f5e3Sopenharmony_ci CHECK_NULL_FATAL(floatConst1); 4434514f5e3Sopenharmony_ci } 4444514f5e3Sopenharmony_ci float constValueFloat = 0.0; 4454514f5e3Sopenharmony_ci double constValueDouble = 0.0; 4464514f5e3Sopenharmony_ci switch (opcode) { 4474514f5e3Sopenharmony_ci case OP_add: { 4484514f5e3Sopenharmony_ci if (useDouble) { 4494514f5e3Sopenharmony_ci constValueDouble = doubleConst0->GetValue() + doubleConst1->GetValue(); 4504514f5e3Sopenharmony_ci } else { 4514514f5e3Sopenharmony_ci constValueFloat = floatConst0->GetValue() + floatConst1->GetValue(); 4524514f5e3Sopenharmony_ci } 4534514f5e3Sopenharmony_ci break; 4544514f5e3Sopenharmony_ci } 4554514f5e3Sopenharmony_ci case OP_sub: { 4564514f5e3Sopenharmony_ci if (useDouble) { 4574514f5e3Sopenharmony_ci constValueDouble = doubleConst0->GetValue() - doubleConst1->GetValue(); 4584514f5e3Sopenharmony_ci } else { 4594514f5e3Sopenharmony_ci constValueFloat = floatConst0->GetValue() - floatConst1->GetValue(); 4604514f5e3Sopenharmony_ci } 4614514f5e3Sopenharmony_ci break; 4624514f5e3Sopenharmony_ci } 4634514f5e3Sopenharmony_ci case OP_mul: { 4644514f5e3Sopenharmony_ci if (useDouble) { 4654514f5e3Sopenharmony_ci constValueDouble = doubleConst0->GetValue() * doubleConst1->GetValue(); 4664514f5e3Sopenharmony_ci } else { 4674514f5e3Sopenharmony_ci constValueFloat = floatConst0->GetValue() * floatConst1->GetValue(); 4684514f5e3Sopenharmony_ci } 4694514f5e3Sopenharmony_ci break; 4704514f5e3Sopenharmony_ci } 4714514f5e3Sopenharmony_ci case OP_div: { 4724514f5e3Sopenharmony_ci // for floats div by 0 is well defined 4734514f5e3Sopenharmony_ci if (useDouble) { 4744514f5e3Sopenharmony_ci constValueDouble = doubleConst0->GetValue() / doubleConst1->GetValue(); 4754514f5e3Sopenharmony_ci } else { 4764514f5e3Sopenharmony_ci constValueFloat = floatConst0->GetValue() / floatConst1->GetValue(); 4774514f5e3Sopenharmony_ci } 4784514f5e3Sopenharmony_ci break; 4794514f5e3Sopenharmony_ci } 4804514f5e3Sopenharmony_ci case OP_max: { 4814514f5e3Sopenharmony_ci if (useDouble) { 4824514f5e3Sopenharmony_ci constValueDouble = (doubleConst0->GetValue() >= doubleConst1->GetValue()) ? doubleConst0->GetValue() 4834514f5e3Sopenharmony_ci : doubleConst1->GetValue(); 4844514f5e3Sopenharmony_ci } else { 4854514f5e3Sopenharmony_ci constValueFloat = (floatConst0->GetValue() >= floatConst1->GetValue()) ? floatConst0->GetValue() 4864514f5e3Sopenharmony_ci : floatConst1->GetValue(); 4874514f5e3Sopenharmony_ci } 4884514f5e3Sopenharmony_ci break; 4894514f5e3Sopenharmony_ci } 4904514f5e3Sopenharmony_ci case OP_min: { 4914514f5e3Sopenharmony_ci if (useDouble) { 4924514f5e3Sopenharmony_ci constValueDouble = (doubleConst0->GetValue() <= doubleConst1->GetValue()) ? doubleConst0->GetValue() 4934514f5e3Sopenharmony_ci : doubleConst1->GetValue(); 4944514f5e3Sopenharmony_ci } else { 4954514f5e3Sopenharmony_ci constValueFloat = (floatConst0->GetValue() <= floatConst1->GetValue()) ? floatConst0->GetValue() 4964514f5e3Sopenharmony_ci : floatConst1->GetValue(); 4974514f5e3Sopenharmony_ci } 4984514f5e3Sopenharmony_ci break; 4994514f5e3Sopenharmony_ci } 5004514f5e3Sopenharmony_ci case OP_rem: 5014514f5e3Sopenharmony_ci case OP_ashr: 5024514f5e3Sopenharmony_ci case OP_lshr: 5034514f5e3Sopenharmony_ci case OP_shl: 5044514f5e3Sopenharmony_ci case OP_band: 5054514f5e3Sopenharmony_ci case OP_bior: 5064514f5e3Sopenharmony_ci case OP_bxor: { 5074514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unexpected opcode in FoldFPConstBinary"); 5084514f5e3Sopenharmony_ci break; 5094514f5e3Sopenharmony_ci } 5104514f5e3Sopenharmony_ci default: 5114514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldFPConstBinary"); 5124514f5e3Sopenharmony_ci break; 5134514f5e3Sopenharmony_ci } 5144514f5e3Sopenharmony_ci if (resultType == PTY_f64) { 5154514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(constValueDouble)); 5164514f5e3Sopenharmony_ci } else { 5174514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateFloatConst(constValueFloat)); 5184514f5e3Sopenharmony_ci } 5194514f5e3Sopenharmony_ci return resultConst; 5204514f5e3Sopenharmony_ci} 5214514f5e3Sopenharmony_ci 5224514f5e3Sopenharmony_cibool ConstantFold::ConstValueEqual(int64 leftValue, int64 rightValue) const 5234514f5e3Sopenharmony_ci{ 5244514f5e3Sopenharmony_ci return (leftValue == rightValue); 5254514f5e3Sopenharmony_ci} 5264514f5e3Sopenharmony_ci 5274514f5e3Sopenharmony_cibool ConstantFold::ConstValueEqual(float leftValue, float rightValue) const 5284514f5e3Sopenharmony_ci{ 5294514f5e3Sopenharmony_ci auto result = fabs(leftValue - rightValue); 5304514f5e3Sopenharmony_ci return leftValue <= FLT_MIN && rightValue <= FLT_MIN ? result < FLT_MIN : result <= FLT_MIN; 5314514f5e3Sopenharmony_ci} 5324514f5e3Sopenharmony_ci 5334514f5e3Sopenharmony_cibool ConstantFold::ConstValueEqual(double leftValue, double rightValue) const 5344514f5e3Sopenharmony_ci{ 5354514f5e3Sopenharmony_ci auto result = fabs(leftValue - rightValue); 5364514f5e3Sopenharmony_ci return leftValue <= DBL_MIN && rightValue <= DBL_MIN ? result < DBL_MIN : result <= DBL_MIN; 5374514f5e3Sopenharmony_ci} 5384514f5e3Sopenharmony_ci 5394514f5e3Sopenharmony_citemplate<typename T> 5404514f5e3Sopenharmony_cibool ConstantFold::FullyEqual(T leftValue, T rightValue) const 5414514f5e3Sopenharmony_ci{ 5424514f5e3Sopenharmony_ci if (std::isinf(leftValue) && std::isinf(rightValue)) { 5434514f5e3Sopenharmony_ci // (inf == inf), add the judgement here in case of the subtraction between float type inf 5444514f5e3Sopenharmony_ci return true; 5454514f5e3Sopenharmony_ci } else { 5464514f5e3Sopenharmony_ci return ConstValueEqual(leftValue, rightValue); 5474514f5e3Sopenharmony_ci } 5484514f5e3Sopenharmony_ci} 5494514f5e3Sopenharmony_ci 5504514f5e3Sopenharmony_citemplate<typename T> 5514514f5e3Sopenharmony_ciint64 ConstantFold::ComparisonResult(Opcode op, T *leftConst, T *rightConst) const 5524514f5e3Sopenharmony_ci{ 5534514f5e3Sopenharmony_ci DEBUG_ASSERT(leftConst != nullptr, "leftConst should not be nullptr"); 5544514f5e3Sopenharmony_ci typename T::value_type leftValue = leftConst->GetValue(); 5554514f5e3Sopenharmony_ci DEBUG_ASSERT(rightConst != nullptr, "rightConst should not be nullptr"); 5564514f5e3Sopenharmony_ci typename T::value_type rightValue = rightConst->GetValue(); 5574514f5e3Sopenharmony_ci int64 result = 0; 5584514f5e3Sopenharmony_ci switch (op) { 5594514f5e3Sopenharmony_ci case OP_eq: { 5604514f5e3Sopenharmony_ci result = FullyEqual(leftValue, rightValue); 5614514f5e3Sopenharmony_ci break; 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci case OP_ge: { 5644514f5e3Sopenharmony_ci result = (leftValue > rightValue) || FullyEqual(leftValue, rightValue); 5654514f5e3Sopenharmony_ci break; 5664514f5e3Sopenharmony_ci } 5674514f5e3Sopenharmony_ci case OP_gt: { 5684514f5e3Sopenharmony_ci result = (leftValue > rightValue); 5694514f5e3Sopenharmony_ci break; 5704514f5e3Sopenharmony_ci } 5714514f5e3Sopenharmony_ci case OP_le: { 5724514f5e3Sopenharmony_ci result = (leftValue < rightValue) || FullyEqual(leftValue, rightValue); 5734514f5e3Sopenharmony_ci break; 5744514f5e3Sopenharmony_ci } 5754514f5e3Sopenharmony_ci case OP_lt: { 5764514f5e3Sopenharmony_ci result = (leftValue < rightValue); 5774514f5e3Sopenharmony_ci break; 5784514f5e3Sopenharmony_ci } 5794514f5e3Sopenharmony_ci case OP_ne: { 5804514f5e3Sopenharmony_ci result = !FullyEqual(leftValue, rightValue); 5814514f5e3Sopenharmony_ci break; 5824514f5e3Sopenharmony_ci } 5834514f5e3Sopenharmony_ci [[clang::fallthrough]]; 5844514f5e3Sopenharmony_ci case OP_cmp: { 5854514f5e3Sopenharmony_ci if (leftValue > rightValue) { 5864514f5e3Sopenharmony_ci result = kGreater; 5874514f5e3Sopenharmony_ci } else if (FullyEqual(leftValue, rightValue)) { 5884514f5e3Sopenharmony_ci result = kEqual; 5894514f5e3Sopenharmony_ci } else { 5904514f5e3Sopenharmony_ci result = kLess; 5914514f5e3Sopenharmony_ci } 5924514f5e3Sopenharmony_ci break; 5934514f5e3Sopenharmony_ci } 5944514f5e3Sopenharmony_ci default: 5954514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for Comparison"); 5964514f5e3Sopenharmony_ci break; 5974514f5e3Sopenharmony_ci } 5984514f5e3Sopenharmony_ci return result; 5994514f5e3Sopenharmony_ci} 6004514f5e3Sopenharmony_ci 6014514f5e3Sopenharmony_ciMIRIntConst *ConstantFold::FoldFPConstComparisonMIRConst(Opcode opcode, PrimType resultType, PrimType opndType, 6024514f5e3Sopenharmony_ci const MIRConst &leftConst, const MIRConst &rightConst) const 6034514f5e3Sopenharmony_ci{ 6044514f5e3Sopenharmony_ci int64 result = 0; 6054514f5e3Sopenharmony_ci bool useDouble = (opndType == PTY_f64); 6064514f5e3Sopenharmony_ci if (useDouble) { 6074514f5e3Sopenharmony_ci result = 6084514f5e3Sopenharmony_ci ComparisonResult(opcode, safe_cast<MIRDoubleConst>(&leftConst), safe_cast<MIRDoubleConst>(&rightConst)); 6094514f5e3Sopenharmony_ci } else { 6104514f5e3Sopenharmony_ci result = ComparisonResult(opcode, safe_cast<MIRFloatConst>(&leftConst), safe_cast<MIRFloatConst>(&rightConst)); 6114514f5e3Sopenharmony_ci } 6124514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(resultType); 6134514f5e3Sopenharmony_ci MIRIntConst *resultConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(result), type); 6144514f5e3Sopenharmony_ci return resultConst; 6154514f5e3Sopenharmony_ci} 6164514f5e3Sopenharmony_ci 6174514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldFPConstComparison(Opcode opcode, PrimType resultType, PrimType opndType, 6184514f5e3Sopenharmony_ci const ConstvalNode &const0, const ConstvalNode &const1) const 6194514f5e3Sopenharmony_ci{ 6204514f5e3Sopenharmony_ci DEBUG_ASSERT(const0.GetPrimType() == const1.GetPrimType(), "The types of the operands must match"); 6214514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 6224514f5e3Sopenharmony_ci resultConst->SetPrimType(resultType); 6234514f5e3Sopenharmony_ci resultConst->SetConstVal( 6244514f5e3Sopenharmony_ci FoldFPConstComparisonMIRConst(opcode, resultType, opndType, *const0.GetConstVal(), *const1.GetConstVal())); 6254514f5e3Sopenharmony_ci return resultConst; 6264514f5e3Sopenharmony_ci} 6274514f5e3Sopenharmony_ci 6284514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldConstComparisonMIRConst(Opcode opcode, PrimType resultType, PrimType opndType, 6294514f5e3Sopenharmony_ci const MIRConst &const0, const MIRConst &const1) const 6304514f5e3Sopenharmony_ci{ 6314514f5e3Sopenharmony_ci MIRConst *returnValue = nullptr; 6324514f5e3Sopenharmony_ci if (IsPrimitiveInteger(opndType)) { 6334514f5e3Sopenharmony_ci const auto *intConst0 = safe_cast<MIRIntConst>(&const0); 6344514f5e3Sopenharmony_ci const auto *intConst1 = safe_cast<MIRIntConst>(&const1); 6354514f5e3Sopenharmony_ci ASSERT_NOT_NULL(intConst0); 6364514f5e3Sopenharmony_ci ASSERT_NOT_NULL(intConst1); 6374514f5e3Sopenharmony_ci returnValue = FoldIntConstComparisonMIRConst(opcode, resultType, opndType, *intConst0, *intConst1); 6384514f5e3Sopenharmony_ci } else if (opndType == PTY_f32 || opndType == PTY_f64) { 6394514f5e3Sopenharmony_ci returnValue = FoldFPConstComparisonMIRConst(opcode, resultType, opndType, const0, const1); 6404514f5e3Sopenharmony_ci } else { 6414514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unhandled case for FoldConstComparisonMIRConst"); 6424514f5e3Sopenharmony_ci } 6434514f5e3Sopenharmony_ci return returnValue; 6444514f5e3Sopenharmony_ci} 6454514f5e3Sopenharmony_ci 6464514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldConstComparison(Opcode opcode, PrimType resultType, PrimType opndType, 6474514f5e3Sopenharmony_ci const ConstvalNode &const0, const ConstvalNode &const1) const 6484514f5e3Sopenharmony_ci{ 6494514f5e3Sopenharmony_ci ConstvalNode *returnValue = nullptr; 6504514f5e3Sopenharmony_ci if (IsPrimitiveInteger(opndType)) { 6514514f5e3Sopenharmony_ci returnValue = FoldIntConstComparison(opcode, resultType, opndType, const0, const1); 6524514f5e3Sopenharmony_ci } else if (opndType == PTY_f32 || opndType == PTY_f64) { 6534514f5e3Sopenharmony_ci returnValue = FoldFPConstComparison(opcode, resultType, opndType, const0, const1); 6544514f5e3Sopenharmony_ci } else { 6554514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unhandled case for FoldConstComparison"); 6564514f5e3Sopenharmony_ci } 6574514f5e3Sopenharmony_ci return returnValue; 6584514f5e3Sopenharmony_ci} 6594514f5e3Sopenharmony_ci 6604514f5e3Sopenharmony_ciCompareNode *ConstantFold::FoldConstComparisonReverse(Opcode opcode, PrimType resultType, PrimType opndType, 6614514f5e3Sopenharmony_ci BaseNode &l, BaseNode &r) const 6624514f5e3Sopenharmony_ci{ 6634514f5e3Sopenharmony_ci CompareNode *result = nullptr; 6644514f5e3Sopenharmony_ci Opcode op = opcode; 6654514f5e3Sopenharmony_ci switch (opcode) { 6664514f5e3Sopenharmony_ci case OP_gt: { 6674514f5e3Sopenharmony_ci op = OP_lt; 6684514f5e3Sopenharmony_ci break; 6694514f5e3Sopenharmony_ci } 6704514f5e3Sopenharmony_ci case OP_lt: { 6714514f5e3Sopenharmony_ci op = OP_gt; 6724514f5e3Sopenharmony_ci break; 6734514f5e3Sopenharmony_ci } 6744514f5e3Sopenharmony_ci case OP_ge: { 6754514f5e3Sopenharmony_ci op = OP_le; 6764514f5e3Sopenharmony_ci break; 6774514f5e3Sopenharmony_ci } 6784514f5e3Sopenharmony_ci case OP_le: { 6794514f5e3Sopenharmony_ci op = OP_ge; 6804514f5e3Sopenharmony_ci break; 6814514f5e3Sopenharmony_ci } 6824514f5e3Sopenharmony_ci case OP_eq: { 6834514f5e3Sopenharmony_ci break; 6844514f5e3Sopenharmony_ci } 6854514f5e3Sopenharmony_ci case OP_ne: { 6864514f5e3Sopenharmony_ci break; 6874514f5e3Sopenharmony_ci } 6884514f5e3Sopenharmony_ci default: 6894514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldConstComparisonReverse"); 6904514f5e3Sopenharmony_ci break; 6914514f5e3Sopenharmony_ci } 6924514f5e3Sopenharmony_ci 6934514f5e3Sopenharmony_ci result = 6944514f5e3Sopenharmony_ci mirModule->CurFuncCodeMemPool()->New<CompareNode>(Opcode(op), PrimType(resultType), PrimType(opndType), &r, &l); 6954514f5e3Sopenharmony_ci return result; 6964514f5e3Sopenharmony_ci} 6974514f5e3Sopenharmony_ci 6984514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldConstBinary(Opcode opcode, PrimType resultType, const ConstvalNode &const0, 6994514f5e3Sopenharmony_ci const ConstvalNode &const1) const 7004514f5e3Sopenharmony_ci{ 7014514f5e3Sopenharmony_ci ConstvalNode *returnValue = nullptr; 7024514f5e3Sopenharmony_ci if (IsPrimitiveInteger(resultType)) { 7034514f5e3Sopenharmony_ci returnValue = FoldIntConstBinary(opcode, resultType, const0, const1); 7044514f5e3Sopenharmony_ci } else if (resultType == PTY_f32 || resultType == PTY_f64) { 7054514f5e3Sopenharmony_ci returnValue = FoldFPConstBinary(opcode, resultType, const0, const1); 7064514f5e3Sopenharmony_ci } else { 7074514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unhandled case for FoldConstBinary"); 7084514f5e3Sopenharmony_ci } 7094514f5e3Sopenharmony_ci return returnValue; 7104514f5e3Sopenharmony_ci} 7114514f5e3Sopenharmony_ci 7124514f5e3Sopenharmony_ciMIRIntConst *ConstantFold::FoldIntConstUnaryMIRConst(Opcode opcode, PrimType resultType, const MIRIntConst *constNode) 7134514f5e3Sopenharmony_ci{ 7144514f5e3Sopenharmony_ci CHECK_NULL_FATAL(constNode); 7154514f5e3Sopenharmony_ci IntVal result = constNode->GetValue().TruncOrExtend(resultType); 7164514f5e3Sopenharmony_ci switch (opcode) { 7174514f5e3Sopenharmony_ci case OP_abs: { 7184514f5e3Sopenharmony_ci if (IsSignedInteger(constNode->GetType().GetPrimType()) && result.GetSignBit()) { 7194514f5e3Sopenharmony_ci result = -result; 7204514f5e3Sopenharmony_ci } 7214514f5e3Sopenharmony_ci break; 7224514f5e3Sopenharmony_ci } 7234514f5e3Sopenharmony_ci case OP_bnot: { 7244514f5e3Sopenharmony_ci result = ~result; 7254514f5e3Sopenharmony_ci break; 7264514f5e3Sopenharmony_ci } 7274514f5e3Sopenharmony_ci case OP_lnot: { 7284514f5e3Sopenharmony_ci uint64 resultInt = result == 0 ? 1 : 0; 7294514f5e3Sopenharmony_ci result = {resultInt, resultType}; 7304514f5e3Sopenharmony_ci break; 7314514f5e3Sopenharmony_ci } 7324514f5e3Sopenharmony_ci case OP_neg: { 7334514f5e3Sopenharmony_ci result = -result; 7344514f5e3Sopenharmony_ci break; 7354514f5e3Sopenharmony_ci } 7364514f5e3Sopenharmony_ci case OP_sext: // handled in FoldExtractbits 7374514f5e3Sopenharmony_ci case OP_zext: // handled in FoldExtractbits 7384514f5e3Sopenharmony_ci case OP_extractbits: // handled in FoldExtractbits 7394514f5e3Sopenharmony_ci case OP_sqrt: { 7404514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unexpected opcode in FoldIntConstUnaryMIRConst"); 7414514f5e3Sopenharmony_ci break; 7424514f5e3Sopenharmony_ci } 7434514f5e3Sopenharmony_ci default: 7444514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldIntConstUnaryMIRConst"); 7454514f5e3Sopenharmony_ci break; 7464514f5e3Sopenharmony_ci } 7474514f5e3Sopenharmony_ci // determine the type 7484514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(resultType); 7494514f5e3Sopenharmony_ci // form the constant 7504514f5e3Sopenharmony_ci MIRIntConst *constValue = 7514514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(result.GetExtValue()), type); 7524514f5e3Sopenharmony_ci return constValue; 7534514f5e3Sopenharmony_ci} 7544514f5e3Sopenharmony_ci 7554514f5e3Sopenharmony_citemplate <typename T> 7564514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldFPConstUnary(Opcode opcode, PrimType resultType, ConstvalNode *constNode) const 7574514f5e3Sopenharmony_ci{ 7584514f5e3Sopenharmony_ci CHECK_NULL_FATAL(constNode); 7594514f5e3Sopenharmony_ci double constValue = 0; 7604514f5e3Sopenharmony_ci T *fpCst = static_cast<T*>(constNode->GetConstVal()); 7614514f5e3Sopenharmony_ci switch (opcode) { 7624514f5e3Sopenharmony_ci case OP_neg: { 7634514f5e3Sopenharmony_ci constValue = typename T::value_type(-fpCst->GetValue()); 7644514f5e3Sopenharmony_ci break; 7654514f5e3Sopenharmony_ci } 7664514f5e3Sopenharmony_ci case OP_abs: { 7674514f5e3Sopenharmony_ci constValue = typename T::value_type(fabs(fpCst->GetValue())); 7684514f5e3Sopenharmony_ci break; 7694514f5e3Sopenharmony_ci } 7704514f5e3Sopenharmony_ci case OP_sqrt: { 7714514f5e3Sopenharmony_ci constValue = typename T::value_type(sqrt(fpCst->GetValue())); 7724514f5e3Sopenharmony_ci break; 7734514f5e3Sopenharmony_ci } 7744514f5e3Sopenharmony_ci case OP_bnot: 7754514f5e3Sopenharmony_ci case OP_lnot: 7764514f5e3Sopenharmony_ci case OP_sext: 7774514f5e3Sopenharmony_ci case OP_zext: 7784514f5e3Sopenharmony_ci case OP_extractbits: { 7794514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unexpected opcode in FoldFPConstUnary"); 7804514f5e3Sopenharmony_ci break; 7814514f5e3Sopenharmony_ci } 7824514f5e3Sopenharmony_ci default: 7834514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unknown opcode for FoldFPConstUnary"); 7844514f5e3Sopenharmony_ci break; 7854514f5e3Sopenharmony_ci } 7864514f5e3Sopenharmony_ci auto *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 7874514f5e3Sopenharmony_ci resultConst->SetPrimType(resultType); 7884514f5e3Sopenharmony_ci if (resultType == PTY_f32) { 7894514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateFloatConst(static_cast<float>(constValue))); 7904514f5e3Sopenharmony_ci } else if (resultType == PTY_f64) { 7914514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(constValue)); 7924514f5e3Sopenharmony_ci } else { 7934514f5e3Sopenharmony_ci CHECK_FATAL(false, "PrimType for MIRFloatConst / MIRDoubleConst should be PTY_f32 / PTY_f64"); 7944514f5e3Sopenharmony_ci } 7954514f5e3Sopenharmony_ci return resultConst; 7964514f5e3Sopenharmony_ci} 7974514f5e3Sopenharmony_ci 7984514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldConstUnary(Opcode opcode, PrimType resultType, ConstvalNode &constNode) const 7994514f5e3Sopenharmony_ci{ 8004514f5e3Sopenharmony_ci ConstvalNode *returnValue = nullptr; 8014514f5e3Sopenharmony_ci if (IsPrimitiveInteger(resultType)) { 8024514f5e3Sopenharmony_ci const MIRIntConst *cst = safe_cast<MIRIntConst>(constNode.GetConstVal()); 8034514f5e3Sopenharmony_ci auto constValue = FoldIntConstUnaryMIRConst(opcode, resultType, cst); 8044514f5e3Sopenharmony_ci returnValue = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 8054514f5e3Sopenharmony_ci returnValue->SetPrimType(resultType); 8064514f5e3Sopenharmony_ci returnValue->SetConstVal(constValue); 8074514f5e3Sopenharmony_ci } else if (resultType == PTY_f32) { 8084514f5e3Sopenharmony_ci returnValue = FoldFPConstUnary<MIRFloatConst>(opcode, resultType, &constNode); 8094514f5e3Sopenharmony_ci } else if (resultType == PTY_f64) { 8104514f5e3Sopenharmony_ci returnValue = FoldFPConstUnary<MIRDoubleConst>(opcode, resultType, &constNode); 8114514f5e3Sopenharmony_ci } else { 8124514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unhandled case for FoldConstUnary"); 8134514f5e3Sopenharmony_ci } 8144514f5e3Sopenharmony_ci return returnValue; 8154514f5e3Sopenharmony_ci} 8164514f5e3Sopenharmony_ci 8174514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldRetype(RetypeNode *node) 8184514f5e3Sopenharmony_ci{ 8194514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 8204514f5e3Sopenharmony_ci BaseNode *result = node; 8214514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node->Opnd(0)); 8224514f5e3Sopenharmony_ci if (node->Opnd(0) != p.first) { 8234514f5e3Sopenharmony_ci RetypeNode *newRetNode = node->CloneTree(mirModule->GetCurFuncCodeMPAllocator()); 8244514f5e3Sopenharmony_ci CHECK_FATAL(newRetNode != nullptr, "newRetNode is null in ConstantFold::FoldRetype"); 8254514f5e3Sopenharmony_ci newRetNode->SetOpnd(PairToExpr(node->Opnd(0)->GetPrimType(), p), 0); 8264514f5e3Sopenharmony_ci result = newRetNode; 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 8294514f5e3Sopenharmony_ci} 8304514f5e3Sopenharmony_ci 8314514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldUnary(UnaryNode *node) 8324514f5e3Sopenharmony_ci{ 8334514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 8344514f5e3Sopenharmony_ci BaseNode *result = nullptr; 8354514f5e3Sopenharmony_ci std::optional<IntVal> sum = std::nullopt; 8364514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node->Opnd(0)); 8374514f5e3Sopenharmony_ci ConstvalNode *cst = safe_cast<ConstvalNode>(p.first); 8384514f5e3Sopenharmony_ci if (cst != nullptr) { 8394514f5e3Sopenharmony_ci result = FoldConstUnary(node->GetOpCode(), node->GetPrimType(), *cst); 8404514f5e3Sopenharmony_ci } else { 8414514f5e3Sopenharmony_ci bool isInt = IsPrimitiveInteger(node->GetPrimType()); 8424514f5e3Sopenharmony_ci // The neg node will be recreated regardless of whether the folding is successful or not. And the neg node's 8434514f5e3Sopenharmony_ci // primType will be set to opnd type. There will be problems in some cases. For example: 8444514f5e3Sopenharmony_ci // before cf: 8454514f5e3Sopenharmony_ci // neg i32 (eq u1 f32 (dread f32 %f_4_2, constval f32 0f)) 8464514f5e3Sopenharmony_ci // after cf: 8474514f5e3Sopenharmony_ci // neg u1 (eq u1 f32 (dread f32 %f_4_2, constval f32 0f)) # wrong! 8484514f5e3Sopenharmony_ci // As a workaround, we exclude u1 opnd type 8494514f5e3Sopenharmony_ci if (isInt && node->GetOpCode() == OP_neg && p.first->GetPrimType() != PTY_u1) { 8504514f5e3Sopenharmony_ci result = NegateTree(p.first); 8514514f5e3Sopenharmony_ci if (result->GetOpCode() == OP_neg) { 8524514f5e3Sopenharmony_ci PrimType origPtyp = node->GetPrimType(); 8534514f5e3Sopenharmony_ci PrimType newPtyp = result->GetPrimType(); 8544514f5e3Sopenharmony_ci if (newPtyp == origPtyp) { 8554514f5e3Sopenharmony_ci if (static_cast<UnaryNode*>(result)->Opnd(0) == node->Opnd(0)) { 8564514f5e3Sopenharmony_ci // NegateTree returned an UnaryNode quivalent to `n`, so keep the 8574514f5e3Sopenharmony_ci // original UnaryNode to preserve identity 8584514f5e3Sopenharmony_ci result = node; 8594514f5e3Sopenharmony_ci } 8604514f5e3Sopenharmony_ci } else { 8614514f5e3Sopenharmony_ci if (GetPrimTypeSize(newPtyp) != GetPrimTypeSize(origPtyp)) { 8624514f5e3Sopenharmony_ci // do not fold explicit cvt 8634514f5e3Sopenharmony_ci result = NewUnaryNode(node, node->GetOpCode(), node->GetPrimType(), 8644514f5e3Sopenharmony_ci PairToExpr(node->Opnd(0)->GetPrimType(), p)); 8654514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 8664514f5e3Sopenharmony_ci } else { 8674514f5e3Sopenharmony_ci result->SetPrimType(origPtyp); 8684514f5e3Sopenharmony_ci } 8694514f5e3Sopenharmony_ci } 8704514f5e3Sopenharmony_ci } 8714514f5e3Sopenharmony_ci if (p.second) { 8724514f5e3Sopenharmony_ci sum = -(*p.second); 8734514f5e3Sopenharmony_ci } 8744514f5e3Sopenharmony_ci } else { 8754514f5e3Sopenharmony_ci result = 8764514f5e3Sopenharmony_ci NewUnaryNode(node, node->GetOpCode(), node->GetPrimType(), PairToExpr(node->Opnd(0)->GetPrimType(), p)); 8774514f5e3Sopenharmony_ci } 8784514f5e3Sopenharmony_ci } 8794514f5e3Sopenharmony_ci return std::make_pair(result, sum); 8804514f5e3Sopenharmony_ci} 8814514f5e3Sopenharmony_ci 8824514f5e3Sopenharmony_cistatic bool FloatToIntOverflow(float fval, PrimType totype) 8834514f5e3Sopenharmony_ci{ 8844514f5e3Sopenharmony_ci static const float safeFloatMaxToInt32 = 2147483520.0f; // 2^31 - 128 8854514f5e3Sopenharmony_ci static const float safeFloatMinToInt32 = -2147483520.0f; 8864514f5e3Sopenharmony_ci static const float safeFloatMaxToInt64 = 9223372036854775680.0f; // 2^63 - 128 8874514f5e3Sopenharmony_ci static const float safeFloatMinToInt64 = -9223372036854775680.0f; 8884514f5e3Sopenharmony_ci if (!std::isfinite(fval)) { 8894514f5e3Sopenharmony_ci return true; 8904514f5e3Sopenharmony_ci } 8914514f5e3Sopenharmony_ci if (totype == PTY_i64 || totype == PTY_u64) { 8924514f5e3Sopenharmony_ci if (fval < safeFloatMinToInt64 || fval > safeFloatMaxToInt64) { 8934514f5e3Sopenharmony_ci return true; 8944514f5e3Sopenharmony_ci } 8954514f5e3Sopenharmony_ci } else { 8964514f5e3Sopenharmony_ci if (fval < safeFloatMinToInt32 || fval > safeFloatMaxToInt32) { 8974514f5e3Sopenharmony_ci return true; 8984514f5e3Sopenharmony_ci } 8994514f5e3Sopenharmony_ci } 9004514f5e3Sopenharmony_ci return false; 9014514f5e3Sopenharmony_ci} 9024514f5e3Sopenharmony_ci 9034514f5e3Sopenharmony_cistatic bool DoubleToIntOverflow(double dval, PrimType totype) 9044514f5e3Sopenharmony_ci{ 9054514f5e3Sopenharmony_ci static const double safeDoubleMaxToInt32 = 2147482624.0; // 2^31 - 1024 9064514f5e3Sopenharmony_ci static const double safeDoubleMinToInt32 = -2147482624.0; 9074514f5e3Sopenharmony_ci static const double safeDoubleMaxToInt64 = 9223372036854774784.0; // 2^63 - 1024 9084514f5e3Sopenharmony_ci static const double safeDoubleMinToInt64 = -9223372036854774784.0; 9094514f5e3Sopenharmony_ci if (!std::isfinite(dval)) { 9104514f5e3Sopenharmony_ci return true; 9114514f5e3Sopenharmony_ci } 9124514f5e3Sopenharmony_ci if (totype == PTY_i64 || totype == PTY_u64) { 9134514f5e3Sopenharmony_ci if (dval < safeDoubleMinToInt64 || dval > safeDoubleMaxToInt64) { 9144514f5e3Sopenharmony_ci return true; 9154514f5e3Sopenharmony_ci } 9164514f5e3Sopenharmony_ci } else { 9174514f5e3Sopenharmony_ci if (dval < safeDoubleMinToInt32 || dval > safeDoubleMaxToInt32) { 9184514f5e3Sopenharmony_ci return true; 9194514f5e3Sopenharmony_ci } 9204514f5e3Sopenharmony_ci } 9214514f5e3Sopenharmony_ci return false; 9224514f5e3Sopenharmony_ci} 9234514f5e3Sopenharmony_ci 9244514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldCeil(const ConstvalNode &cst, PrimType fromType, PrimType toType) const 9254514f5e3Sopenharmony_ci{ 9264514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 9274514f5e3Sopenharmony_ci resultConst->SetPrimType(toType); 9284514f5e3Sopenharmony_ci MIRType &resultType = *GlobalTables::GetTypeTable().GetPrimType(toType); 9294514f5e3Sopenharmony_ci if (fromType == PTY_f32) { 9304514f5e3Sopenharmony_ci const MIRFloatConst *constValue = safe_cast<MIRFloatConst>(cst.GetConstVal()); 9314514f5e3Sopenharmony_ci ASSERT_NOT_NULL(constValue); 9324514f5e3Sopenharmony_ci float floatValue = ceil(constValue->GetValue()); 9334514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 9344514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue)); 9354514f5e3Sopenharmony_ci } else if (FloatToIntOverflow(floatValue, toType)) { 9364514f5e3Sopenharmony_ci return nullptr; 9374514f5e3Sopenharmony_ci } else { 9384514f5e3Sopenharmony_ci resultConst->SetConstVal( 9394514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(floatValue), resultType)); 9404514f5e3Sopenharmony_ci } 9414514f5e3Sopenharmony_ci } else { 9424514f5e3Sopenharmony_ci const MIRDoubleConst *constValue = safe_cast<MIRDoubleConst>(cst.GetConstVal()); 9434514f5e3Sopenharmony_ci ASSERT_NOT_NULL(constValue); 9444514f5e3Sopenharmony_ci double doubleValue = ceil(constValue->GetValue()); 9454514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 9464514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue)); 9474514f5e3Sopenharmony_ci } else if (DoubleToIntOverflow(doubleValue, toType)) { 9484514f5e3Sopenharmony_ci return nullptr; 9494514f5e3Sopenharmony_ci } else { 9504514f5e3Sopenharmony_ci resultConst->SetConstVal( 9514514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(doubleValue), resultType)); 9524514f5e3Sopenharmony_ci } 9534514f5e3Sopenharmony_ci } 9544514f5e3Sopenharmony_ci return resultConst; 9554514f5e3Sopenharmony_ci} 9564514f5e3Sopenharmony_ci 9574514f5e3Sopenharmony_citemplate <class T> 9584514f5e3Sopenharmony_ciT ConstantFold::CalIntValueFromFloatValue(T value, const MIRType &resultType) const 9594514f5e3Sopenharmony_ci{ 9604514f5e3Sopenharmony_ci DEBUG_ASSERT(kByteSizeOfBit64 >= resultType.GetSize(), "unsupported type"); 9614514f5e3Sopenharmony_ci size_t shiftNum = (kByteSizeOfBit64 - resultType.GetSize()) * kBitSizePerByte; 9624514f5e3Sopenharmony_ci bool isSigned = IsSignedInteger(resultType.GetPrimType()); 9634514f5e3Sopenharmony_ci int64 max = (IntVal(std::numeric_limits<int64>::max(), PTY_i64) >> shiftNum).GetExtValue(); 9644514f5e3Sopenharmony_ci uint64 umax = std::numeric_limits<uint64>::max() >> shiftNum; 9654514f5e3Sopenharmony_ci int64 min = isSigned ? (IntVal(std::numeric_limits<int64>::min(), PTY_i64) >> shiftNum).GetExtValue() : 0; 9664514f5e3Sopenharmony_ci if (isSigned && (value > max)) { 9674514f5e3Sopenharmony_ci return static_cast<T>(max); 9684514f5e3Sopenharmony_ci } else if (!isSigned && (value > umax)) { 9694514f5e3Sopenharmony_ci return static_cast<T>(umax); 9704514f5e3Sopenharmony_ci } else if (value < min) { 9714514f5e3Sopenharmony_ci return static_cast<T>(min); 9724514f5e3Sopenharmony_ci } 9734514f5e3Sopenharmony_ci return value; 9744514f5e3Sopenharmony_ci} 9754514f5e3Sopenharmony_ci 9764514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldFloorMIRConst(const MIRConst &cst, PrimType fromType, PrimType toType, bool isFloor) const 9774514f5e3Sopenharmony_ci{ 9784514f5e3Sopenharmony_ci MIRType &resultType = *GlobalTables::GetTypeTable().GetPrimType(toType); 9794514f5e3Sopenharmony_ci if (fromType == PTY_f32) { 9804514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRFloatConst&>(cst); 9814514f5e3Sopenharmony_ci float floatValue = constValue.GetValue(); 9824514f5e3Sopenharmony_ci if (isFloor) { 9834514f5e3Sopenharmony_ci floatValue = floor(constValue.GetValue()); 9844514f5e3Sopenharmony_ci } 9854514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 9864514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue); 9874514f5e3Sopenharmony_ci } 9884514f5e3Sopenharmony_ci if (FloatToIntOverflow(floatValue, toType)) { 9894514f5e3Sopenharmony_ci return nullptr; 9904514f5e3Sopenharmony_ci } 9914514f5e3Sopenharmony_ci floatValue = CalIntValueFromFloatValue(floatValue, resultType); 9924514f5e3Sopenharmony_ci return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(floatValue), resultType); 9934514f5e3Sopenharmony_ci } else { 9944514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRDoubleConst&>(cst); 9954514f5e3Sopenharmony_ci double doubleValue = constValue.GetValue(); 9964514f5e3Sopenharmony_ci if (isFloor) { 9974514f5e3Sopenharmony_ci doubleValue = floor(constValue.GetValue()); 9984514f5e3Sopenharmony_ci } 9994514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 10004514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue); 10014514f5e3Sopenharmony_ci } 10024514f5e3Sopenharmony_ci if (DoubleToIntOverflow(doubleValue, toType)) { 10034514f5e3Sopenharmony_ci return nullptr; 10044514f5e3Sopenharmony_ci } 10054514f5e3Sopenharmony_ci doubleValue = CalIntValueFromFloatValue(doubleValue, resultType); 10064514f5e3Sopenharmony_ci // gcc/clang have bugs convert double to unsigned long, must convert to signed long first; 10074514f5e3Sopenharmony_ci return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<int64>(doubleValue), resultType); 10084514f5e3Sopenharmony_ci } 10094514f5e3Sopenharmony_ci} 10104514f5e3Sopenharmony_ci 10114514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldFloor(const ConstvalNode &cst, PrimType fromType, PrimType toType) const 10124514f5e3Sopenharmony_ci{ 10134514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 10144514f5e3Sopenharmony_ci resultConst->SetPrimType(toType); 10154514f5e3Sopenharmony_ci resultConst->SetConstVal(FoldFloorMIRConst(*cst.GetConstVal(), fromType, toType)); 10164514f5e3Sopenharmony_ci return resultConst; 10174514f5e3Sopenharmony_ci} 10184514f5e3Sopenharmony_ci 10194514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldRoundMIRConst(const MIRConst &cst, PrimType fromType, PrimType toType) const 10204514f5e3Sopenharmony_ci{ 10214514f5e3Sopenharmony_ci MIRType &resultType = *GlobalTables::GetTypeTable().GetPrimType(toType); 10224514f5e3Sopenharmony_ci if (fromType == PTY_f32) { 10234514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRFloatConst&>(cst); 10244514f5e3Sopenharmony_ci float floatValue = round(constValue.GetValue()); 10254514f5e3Sopenharmony_ci if (FloatToIntOverflow(floatValue, toType)) { 10264514f5e3Sopenharmony_ci return nullptr; 10274514f5e3Sopenharmony_ci } 10284514f5e3Sopenharmony_ci return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<int64>(floatValue), resultType); 10294514f5e3Sopenharmony_ci } else if (fromType == PTY_f64) { 10304514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRDoubleConst&>(cst); 10314514f5e3Sopenharmony_ci double doubleValue = round(constValue.GetValue()); 10324514f5e3Sopenharmony_ci if (DoubleToIntOverflow(doubleValue, toType)) { 10334514f5e3Sopenharmony_ci return nullptr; 10344514f5e3Sopenharmony_ci } 10354514f5e3Sopenharmony_ci return GlobalTables::GetIntConstTable().GetOrCreateIntConst( 10364514f5e3Sopenharmony_ci static_cast<uint64>(static_cast<int64>(doubleValue)), resultType); 10374514f5e3Sopenharmony_ci } else if (toType == PTY_f32 && IsPrimitiveInteger(fromType)) { 10384514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRIntConst&>(cst); 10394514f5e3Sopenharmony_ci if (IsSignedInteger(fromType)) { 10404514f5e3Sopenharmony_ci int64 fromValue = constValue.GetExtValue(); 10414514f5e3Sopenharmony_ci float floatValue = round(static_cast<float>(fromValue)); 10424514f5e3Sopenharmony_ci if (static_cast<int64>(floatValue) == fromValue) { 10434514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue); 10444514f5e3Sopenharmony_ci } 10454514f5e3Sopenharmony_ci } else { 10464514f5e3Sopenharmony_ci uint64 fromValue = static_cast<uint64>(constValue.GetExtValue()); 10474514f5e3Sopenharmony_ci float floatValue = round(static_cast<float>(fromValue)); 10484514f5e3Sopenharmony_ci if (static_cast<uint64>(floatValue) == fromValue) { 10494514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue); 10504514f5e3Sopenharmony_ci } 10514514f5e3Sopenharmony_ci } 10524514f5e3Sopenharmony_ci } else if (toType == PTY_f64 && IsPrimitiveInteger(fromType)) { 10534514f5e3Sopenharmony_ci const auto &constValue = static_cast<const MIRIntConst&>(cst); 10544514f5e3Sopenharmony_ci if (IsSignedInteger(fromType)) { 10554514f5e3Sopenharmony_ci int64 fromValue = constValue.GetExtValue(); 10564514f5e3Sopenharmony_ci double doubleValue = round(static_cast<double>(fromValue)); 10574514f5e3Sopenharmony_ci if (static_cast<int64>(doubleValue) == fromValue) { 10584514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue); 10594514f5e3Sopenharmony_ci } 10604514f5e3Sopenharmony_ci } else { 10614514f5e3Sopenharmony_ci uint64 fromValue = static_cast<uint64>(constValue.GetExtValue()); 10624514f5e3Sopenharmony_ci double doubleValue = round(static_cast<double>(fromValue)); 10634514f5e3Sopenharmony_ci if (static_cast<uint64>(doubleValue) == fromValue) { 10644514f5e3Sopenharmony_ci return GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue); 10654514f5e3Sopenharmony_ci } 10664514f5e3Sopenharmony_ci } 10674514f5e3Sopenharmony_ci } 10684514f5e3Sopenharmony_ci return nullptr; 10694514f5e3Sopenharmony_ci} 10704514f5e3Sopenharmony_ci 10714514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldRound(const ConstvalNode &cst, PrimType fromType, PrimType toType) const 10724514f5e3Sopenharmony_ci{ 10734514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 10744514f5e3Sopenharmony_ci resultConst->SetPrimType(toType); 10754514f5e3Sopenharmony_ci resultConst->SetConstVal(FoldRoundMIRConst(*cst.GetConstVal(), fromType, toType)); 10764514f5e3Sopenharmony_ci return resultConst; 10774514f5e3Sopenharmony_ci} 10784514f5e3Sopenharmony_ci 10794514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldTrunc(const ConstvalNode &cst, PrimType fromType, PrimType toType) const 10804514f5e3Sopenharmony_ci{ 10814514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 10824514f5e3Sopenharmony_ci resultConst->SetPrimType(toType); 10834514f5e3Sopenharmony_ci MIRType &resultType = *GlobalTables::GetTypeTable().GetPrimType(toType); 10844514f5e3Sopenharmony_ci if (fromType == PTY_f32) { 10854514f5e3Sopenharmony_ci const MIRFloatConst *constValue = safe_cast<MIRFloatConst>(cst.GetConstVal()); 10864514f5e3Sopenharmony_ci CHECK_NULL_FATAL(constValue); 10874514f5e3Sopenharmony_ci float floatValue = trunc(constValue->GetValue()); 10884514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 10894514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue)); 10904514f5e3Sopenharmony_ci } else if (FloatToIntOverflow(floatValue, toType)) { 10914514f5e3Sopenharmony_ci return nullptr; 10924514f5e3Sopenharmony_ci } else { 10934514f5e3Sopenharmony_ci resultConst->SetConstVal( 10944514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(floatValue), resultType)); 10954514f5e3Sopenharmony_ci } 10964514f5e3Sopenharmony_ci } else { 10974514f5e3Sopenharmony_ci const MIRDoubleConst *constValue = safe_cast<MIRDoubleConst>(cst.GetConstVal()); 10984514f5e3Sopenharmony_ci CHECK_NULL_FATAL(constValue); 10994514f5e3Sopenharmony_ci double doubleValue = trunc(constValue->GetValue()); 11004514f5e3Sopenharmony_ci if (IsPrimitiveFloat(toType)) { 11014514f5e3Sopenharmony_ci resultConst->SetConstVal(GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue)); 11024514f5e3Sopenharmony_ci } else if (DoubleToIntOverflow(doubleValue, toType)) { 11034514f5e3Sopenharmony_ci return nullptr; 11044514f5e3Sopenharmony_ci } else { 11054514f5e3Sopenharmony_ci resultConst->SetConstVal( 11064514f5e3Sopenharmony_ci GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast<uint64>(doubleValue), resultType)); 11074514f5e3Sopenharmony_ci } 11084514f5e3Sopenharmony_ci } 11094514f5e3Sopenharmony_ci return resultConst; 11104514f5e3Sopenharmony_ci} 11114514f5e3Sopenharmony_ci 11124514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldTypeCvtMIRConst(const MIRConst &cst, PrimType fromType, PrimType toType) const 11134514f5e3Sopenharmony_ci{ 11144514f5e3Sopenharmony_ci if (IsPrimitiveInteger(fromType) && IsPrimitiveInteger(toType)) { 11154514f5e3Sopenharmony_ci MIRConst *toConst = nullptr; 11164514f5e3Sopenharmony_ci uint32 fromSize = GetPrimTypeBitSize(fromType); 11174514f5e3Sopenharmony_ci uint32 toSize = GetPrimTypeBitSize(toType); 11184514f5e3Sopenharmony_ci // GetPrimTypeBitSize(PTY_u1) will return 8, which is not expected here. 11194514f5e3Sopenharmony_ci if (fromType == PTY_u1) { 11204514f5e3Sopenharmony_ci fromSize = 1; 11214514f5e3Sopenharmony_ci } 11224514f5e3Sopenharmony_ci if (toType == PTY_u1) { 11234514f5e3Sopenharmony_ci toSize = 1; 11244514f5e3Sopenharmony_ci } 11254514f5e3Sopenharmony_ci if (toSize > fromSize) { 11264514f5e3Sopenharmony_ci Opcode op = OP_zext; 11274514f5e3Sopenharmony_ci if (IsSignedInteger(fromType)) { 11284514f5e3Sopenharmony_ci op = OP_sext; 11294514f5e3Sopenharmony_ci } 11304514f5e3Sopenharmony_ci const MIRIntConst *constVal = safe_cast<MIRIntConst>(cst); 11314514f5e3Sopenharmony_ci ASSERT_NOT_NULL(constVal); 11324514f5e3Sopenharmony_ci toConst = FoldSignExtendMIRConst(op, toType, static_cast<uint8>(fromSize), 11334514f5e3Sopenharmony_ci constVal->GetValue().TruncOrExtend(fromType)); 11344514f5e3Sopenharmony_ci } else { 11354514f5e3Sopenharmony_ci const MIRIntConst *constVal = safe_cast<MIRIntConst>(cst); 11364514f5e3Sopenharmony_ci ASSERT_NOT_NULL(constVal); 11374514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(toType); 11384514f5e3Sopenharmony_ci toConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst( 11394514f5e3Sopenharmony_ci static_cast<uint64>(constVal->GetExtValue()), type); 11404514f5e3Sopenharmony_ci } 11414514f5e3Sopenharmony_ci return toConst; 11424514f5e3Sopenharmony_ci } 11434514f5e3Sopenharmony_ci if (IsPrimitiveFloat(fromType) && IsPrimitiveFloat(toType)) { 11444514f5e3Sopenharmony_ci MIRConst *toConst = nullptr; 11454514f5e3Sopenharmony_ci if (GetPrimTypeBitSize(toType) < GetPrimTypeBitSize(fromType)) { 11464514f5e3Sopenharmony_ci DEBUG_ASSERT(GetPrimTypeBitSize(toType) == 32, "We suppot F32 and F64"); // just support 32 or 64 11474514f5e3Sopenharmony_ci const MIRDoubleConst *fromValue = safe_cast<MIRDoubleConst>(cst); 11484514f5e3Sopenharmony_ci ASSERT_NOT_NULL(fromValue); 11494514f5e3Sopenharmony_ci float floatValue = static_cast<float>(fromValue->GetValue()); 11504514f5e3Sopenharmony_ci MIRFloatConst *toValue = GlobalTables::GetFpConstTable().GetOrCreateFloatConst(floatValue); 11514514f5e3Sopenharmony_ci toConst = toValue; 11524514f5e3Sopenharmony_ci } else { 11534514f5e3Sopenharmony_ci DEBUG_ASSERT(GetPrimTypeBitSize(toType) == 64, "We suppot F32 and F64"); // just support 32 or 64 11544514f5e3Sopenharmony_ci const MIRFloatConst *fromValue = safe_cast<MIRFloatConst>(cst); 11554514f5e3Sopenharmony_ci ASSERT_NOT_NULL(fromValue); 11564514f5e3Sopenharmony_ci double doubleValue = static_cast<double>(fromValue->GetValue()); 11574514f5e3Sopenharmony_ci MIRDoubleConst *toValue = GlobalTables::GetFpConstTable().GetOrCreateDoubleConst(doubleValue); 11584514f5e3Sopenharmony_ci toConst = toValue; 11594514f5e3Sopenharmony_ci } 11604514f5e3Sopenharmony_ci return toConst; 11614514f5e3Sopenharmony_ci } 11624514f5e3Sopenharmony_ci if (IsPrimitiveFloat(fromType) && IsPrimitiveInteger(toType)) { 11634514f5e3Sopenharmony_ci return FoldFloorMIRConst(cst, fromType, toType, false); 11644514f5e3Sopenharmony_ci } 11654514f5e3Sopenharmony_ci if (IsPrimitiveInteger(fromType) && IsPrimitiveFloat(toType)) { 11664514f5e3Sopenharmony_ci return FoldRoundMIRConst(cst, fromType, toType); 11674514f5e3Sopenharmony_ci } 11684514f5e3Sopenharmony_ci CHECK_FATAL(false, "Unexpected case in ConstFoldTypeCvt"); 11694514f5e3Sopenharmony_ci return nullptr; 11704514f5e3Sopenharmony_ci} 11714514f5e3Sopenharmony_ci 11724514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldTypeCvt(const ConstvalNode &cst, PrimType fromType, PrimType toType) const 11734514f5e3Sopenharmony_ci{ 11744514f5e3Sopenharmony_ci MIRConst *toConstValue = FoldTypeCvtMIRConst(*cst.GetConstVal(), fromType, toType); 11754514f5e3Sopenharmony_ci if (toConstValue == nullptr) { 11764514f5e3Sopenharmony_ci return nullptr; 11774514f5e3Sopenharmony_ci } 11784514f5e3Sopenharmony_ci ConstvalNode *toConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 11794514f5e3Sopenharmony_ci toConst->SetPrimType(toConstValue->GetType().GetPrimType()); 11804514f5e3Sopenharmony_ci toConst->SetConstVal(toConstValue); 11814514f5e3Sopenharmony_ci return toConst; 11824514f5e3Sopenharmony_ci} 11834514f5e3Sopenharmony_ci 11844514f5e3Sopenharmony_ci// return a primType with bit size >= bitSize (and the nearest one), 11854514f5e3Sopenharmony_ci// and its signed/float type is the same as ptyp 11864514f5e3Sopenharmony_ciPrimType GetNearestSizePtyp(uint8 bitSize, PrimType ptyp) 11874514f5e3Sopenharmony_ci{ 11884514f5e3Sopenharmony_ci bool isSigned = IsSignedInteger(ptyp); 11894514f5e3Sopenharmony_ci bool isFloat = IsPrimitiveFloat(ptyp); 11904514f5e3Sopenharmony_ci if (bitSize == 1) { // 1 bit 11914514f5e3Sopenharmony_ci return PTY_u1; 11924514f5e3Sopenharmony_ci } 11934514f5e3Sopenharmony_ci if (bitSize <= 8) { // 8 bit 11944514f5e3Sopenharmony_ci return isSigned ? PTY_i8 : PTY_u8; 11954514f5e3Sopenharmony_ci } 11964514f5e3Sopenharmony_ci if (bitSize <= 16) { // 16 bit 11974514f5e3Sopenharmony_ci return isSigned ? PTY_i16 : PTY_u16; 11984514f5e3Sopenharmony_ci } 11994514f5e3Sopenharmony_ci if (bitSize <= 32) { // 32 bit 12004514f5e3Sopenharmony_ci return isFloat ? PTY_f32 : (isSigned ? PTY_i32 : PTY_u32); 12014514f5e3Sopenharmony_ci } 12024514f5e3Sopenharmony_ci if (bitSize <= 64) { // 64 bit 12034514f5e3Sopenharmony_ci return isFloat ? PTY_f64 : (isSigned ? PTY_i64 : PTY_u64); 12044514f5e3Sopenharmony_ci } 12054514f5e3Sopenharmony_ci return ptyp; 12064514f5e3Sopenharmony_ci} 12074514f5e3Sopenharmony_ci 12084514f5e3Sopenharmony_cisize_t GetIntPrimTypeMax(PrimType ptyp) 12094514f5e3Sopenharmony_ci{ 12104514f5e3Sopenharmony_ci switch (ptyp) { 12114514f5e3Sopenharmony_ci case PTY_u1: 12124514f5e3Sopenharmony_ci return 1; 12134514f5e3Sopenharmony_ci case PTY_u8: 12144514f5e3Sopenharmony_ci return UINT8_MAX; 12154514f5e3Sopenharmony_ci case PTY_i8: 12164514f5e3Sopenharmony_ci return INT8_MAX; 12174514f5e3Sopenharmony_ci case PTY_u16: 12184514f5e3Sopenharmony_ci return UINT16_MAX; 12194514f5e3Sopenharmony_ci case PTY_i16: 12204514f5e3Sopenharmony_ci return INT16_MAX; 12214514f5e3Sopenharmony_ci case PTY_u32: 12224514f5e3Sopenharmony_ci return UINT32_MAX; 12234514f5e3Sopenharmony_ci case PTY_i32: 12244514f5e3Sopenharmony_ci return INT32_MAX; 12254514f5e3Sopenharmony_ci case PTY_u64: 12264514f5e3Sopenharmony_ci return UINT64_MAX; 12274514f5e3Sopenharmony_ci case PTY_i64: 12284514f5e3Sopenharmony_ci return INT64_MAX; 12294514f5e3Sopenharmony_ci default: 12304514f5e3Sopenharmony_ci CHECK_FATAL(false, "NYI"); 12314514f5e3Sopenharmony_ci } 12324514f5e3Sopenharmony_ci} 12334514f5e3Sopenharmony_ci 12344514f5e3Sopenharmony_cissize_t GetIntPrimTypeMin(PrimType ptyp) 12354514f5e3Sopenharmony_ci{ 12364514f5e3Sopenharmony_ci if (IsUnsignedInteger(ptyp)) { 12374514f5e3Sopenharmony_ci return 0; 12384514f5e3Sopenharmony_ci } 12394514f5e3Sopenharmony_ci switch (ptyp) { 12404514f5e3Sopenharmony_ci case PTY_i8: 12414514f5e3Sopenharmony_ci return INT8_MIN; 12424514f5e3Sopenharmony_ci case PTY_i16: 12434514f5e3Sopenharmony_ci return INT16_MIN; 12444514f5e3Sopenharmony_ci case PTY_i32: 12454514f5e3Sopenharmony_ci return INT32_MIN; 12464514f5e3Sopenharmony_ci case PTY_i64: 12474514f5e3Sopenharmony_ci return INT64_MIN; 12484514f5e3Sopenharmony_ci default: 12494514f5e3Sopenharmony_ci CHECK_FATAL(false, "NYI"); 12504514f5e3Sopenharmony_ci } 12514514f5e3Sopenharmony_ci} 12524514f5e3Sopenharmony_ci 12534514f5e3Sopenharmony_cistatic bool IsCvtEliminatable(PrimType fromPtyp, PrimType destPtyp, Opcode op, Opcode opndOp) 12544514f5e3Sopenharmony_ci{ 12554514f5e3Sopenharmony_ci if (op != OP_cvt || (opndOp == OP_zext || opndOp == OP_sext)) { 12564514f5e3Sopenharmony_ci return false; 12574514f5e3Sopenharmony_ci } 12584514f5e3Sopenharmony_ci if (GetPrimTypeSize(fromPtyp) != GetPrimTypeSize(destPtyp)) { 12594514f5e3Sopenharmony_ci return false; 12604514f5e3Sopenharmony_ci } 12614514f5e3Sopenharmony_ci return (IsPossible64BitAddress(fromPtyp) && IsPossible64BitAddress(destPtyp)) || 12624514f5e3Sopenharmony_ci (IsPossible32BitAddress(fromPtyp) && IsPossible32BitAddress(destPtyp)) || 12634514f5e3Sopenharmony_ci (IsPrimitivePureScalar(fromPtyp) && IsPrimitivePureScalar(destPtyp)); 12644514f5e3Sopenharmony_ci} 12654514f5e3Sopenharmony_ci 12664514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldTypeCvt(TypeCvtNode *node) 12674514f5e3Sopenharmony_ci{ 12684514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 12694514f5e3Sopenharmony_ci BaseNode *result = nullptr; 12704514f5e3Sopenharmony_ci if (GetPrimTypeSize(node->GetPrimType()) > k8ByteSize) { 12714514f5e3Sopenharmony_ci return {node, std::nullopt}; 12724514f5e3Sopenharmony_ci } 12734514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node->Opnd(0)); 12744514f5e3Sopenharmony_ci ConstvalNode *cst = safe_cast<ConstvalNode>(p.first); 12754514f5e3Sopenharmony_ci PrimType destPtyp = node->GetPrimType(); 12764514f5e3Sopenharmony_ci PrimType fromPtyp = node->FromType(); 12774514f5e3Sopenharmony_ci if (cst != nullptr) { 12784514f5e3Sopenharmony_ci switch (node->GetOpCode()) { 12794514f5e3Sopenharmony_ci case OP_ceil: { 12804514f5e3Sopenharmony_ci result = FoldCeil(*cst, fromPtyp, destPtyp); 12814514f5e3Sopenharmony_ci break; 12824514f5e3Sopenharmony_ci } 12834514f5e3Sopenharmony_ci case OP_cvt: { 12844514f5e3Sopenharmony_ci result = FoldTypeCvt(*cst, fromPtyp, destPtyp); 12854514f5e3Sopenharmony_ci break; 12864514f5e3Sopenharmony_ci } 12874514f5e3Sopenharmony_ci case OP_floor: { 12884514f5e3Sopenharmony_ci result = FoldFloor(*cst, fromPtyp, destPtyp); 12894514f5e3Sopenharmony_ci break; 12904514f5e3Sopenharmony_ci } 12914514f5e3Sopenharmony_ci case OP_trunc: { 12924514f5e3Sopenharmony_ci result = FoldTrunc(*cst, fromPtyp, destPtyp); 12934514f5e3Sopenharmony_ci break; 12944514f5e3Sopenharmony_ci } 12954514f5e3Sopenharmony_ci default: 12964514f5e3Sopenharmony_ci DEBUG_ASSERT(false, "Unexpected opcode in TypeCvtNodeConstFold"); 12974514f5e3Sopenharmony_ci break; 12984514f5e3Sopenharmony_ci } 12994514f5e3Sopenharmony_ci } else if (IsCvtEliminatable(fromPtyp, destPtyp, node->GetOpCode(), p.first->GetOpCode())) { 13004514f5e3Sopenharmony_ci // the cvt is redundant 13014514f5e3Sopenharmony_ci return std::make_pair(p.first, p.second ? IntVal(*p.second, node->GetPrimType()) : p.second); 13024514f5e3Sopenharmony_ci } 13034514f5e3Sopenharmony_ci if (result == nullptr) { 13044514f5e3Sopenharmony_ci BaseNode *e = PairToExpr(node->Opnd(0)->GetPrimType(), p); 13054514f5e3Sopenharmony_ci if (e != node->Opnd(0)) { 13064514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>( 13074514f5e3Sopenharmony_ci Opcode(node->GetOpCode()), PrimType(node->GetPrimType()), PrimType(node->FromType()), e); 13084514f5e3Sopenharmony_ci } else { 13094514f5e3Sopenharmony_ci result = node; 13104514f5e3Sopenharmony_ci } 13114514f5e3Sopenharmony_ci } 13124514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 13134514f5e3Sopenharmony_ci} 13144514f5e3Sopenharmony_ci 13154514f5e3Sopenharmony_ciMIRConst *ConstantFold::FoldSignExtendMIRConst(Opcode opcode, PrimType resultType, uint8 size, const IntVal &val) const 13164514f5e3Sopenharmony_ci{ 13174514f5e3Sopenharmony_ci uint64 result = opcode == OP_sext ? static_cast<uint64>(val.GetSXTValue(size)) : val.GetZXTValue(size); 13184514f5e3Sopenharmony_ci MIRType &type = *GlobalTables::GetTypeTable().GetPrimType(resultType); 13194514f5e3Sopenharmony_ci MIRIntConst *constValue = GlobalTables::GetIntConstTable().GetOrCreateIntConst(result, type); 13204514f5e3Sopenharmony_ci return constValue; 13214514f5e3Sopenharmony_ci} 13224514f5e3Sopenharmony_ci 13234514f5e3Sopenharmony_ciConstvalNode *ConstantFold::FoldSignExtend(Opcode opcode, PrimType resultType, uint8 size, 13244514f5e3Sopenharmony_ci const ConstvalNode &cst) const 13254514f5e3Sopenharmony_ci{ 13264514f5e3Sopenharmony_ci ConstvalNode *resultConst = mirModule->CurFuncCodeMemPool()->New<ConstvalNode>(); 13274514f5e3Sopenharmony_ci const auto *intCst = safe_cast<MIRIntConst>(cst.GetConstVal()); 13284514f5e3Sopenharmony_ci ASSERT_NOT_NULL(intCst); 13294514f5e3Sopenharmony_ci IntVal val = intCst->GetValue().TruncOrExtend(size, opcode == OP_sext); 13304514f5e3Sopenharmony_ci MIRConst *toConst = FoldSignExtendMIRConst(opcode, resultType, size, val); 13314514f5e3Sopenharmony_ci resultConst->SetPrimType(toConst->GetType().GetPrimType()); 13324514f5e3Sopenharmony_ci resultConst->SetConstVal(toConst); 13334514f5e3Sopenharmony_ci return resultConst; 13344514f5e3Sopenharmony_ci} 13354514f5e3Sopenharmony_ci 13364514f5e3Sopenharmony_ci// check if truncation is redundant due to dread or iread having same effect 13374514f5e3Sopenharmony_cistatic bool ExtractbitsRedundant(const ExtractbitsNode &x, MIRFunction &f) 13384514f5e3Sopenharmony_ci{ 13394514f5e3Sopenharmony_ci if (GetPrimTypeSize(x.GetPrimType()) == k8ByteSize) { 13404514f5e3Sopenharmony_ci return false; // this is trying to be conservative 13414514f5e3Sopenharmony_ci } 13424514f5e3Sopenharmony_ci BaseNode *opnd = x.Opnd(0); 13434514f5e3Sopenharmony_ci MIRType *mirType = nullptr; 13444514f5e3Sopenharmony_ci if (opnd->GetOpCode() == OP_dread) { 13454514f5e3Sopenharmony_ci DreadNode *dread = static_cast<DreadNode*>(opnd); 13464514f5e3Sopenharmony_ci MIRSymbol *sym = f.GetLocalOrGlobalSymbol(dread->GetStIdx()); 13474514f5e3Sopenharmony_ci ASSERT_NOT_NULL(sym); 13484514f5e3Sopenharmony_ci mirType = sym->GetType(); 13494514f5e3Sopenharmony_ci } else if (opnd->GetOpCode() == OP_iread) { 13504514f5e3Sopenharmony_ci IreadNode *iread = static_cast<IreadNode*>(opnd); 13514514f5e3Sopenharmony_ci MIRPtrType *ptrType = 13524514f5e3Sopenharmony_ci dynamic_cast<MIRPtrType*>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(iread->GetTyIdx())); 13534514f5e3Sopenharmony_ci if (ptrType == nullptr) { 13544514f5e3Sopenharmony_ci return false; 13554514f5e3Sopenharmony_ci } 13564514f5e3Sopenharmony_ci mirType = ptrType->GetPointedType(); 13574514f5e3Sopenharmony_ci } else if (opnd->GetOpCode() == OP_extractbits && 13584514f5e3Sopenharmony_ci x.GetBitsSize() > static_cast<ExtractbitsNode*>(opnd)->GetBitsSize()) { 13594514f5e3Sopenharmony_ci return (x.GetOpCode() == OP_zext && x.GetPrimType() == opnd->GetPrimType() && 13604514f5e3Sopenharmony_ci IsUnsignedInteger(opnd->GetPrimType())); 13614514f5e3Sopenharmony_ci } else { 13624514f5e3Sopenharmony_ci return false; 13634514f5e3Sopenharmony_ci } 13644514f5e3Sopenharmony_ci return IsPrimitiveInteger(mirType->GetPrimType()) && 13654514f5e3Sopenharmony_ci ((x.GetOpCode() == OP_zext && IsUnsignedInteger(opnd->GetPrimType())) || 13664514f5e3Sopenharmony_ci (x.GetOpCode() == OP_sext && IsSignedInteger(opnd->GetPrimType()))) && 13674514f5e3Sopenharmony_ci mirType->GetSize() * kBitSizePerByte == x.GetBitsSize() && 13684514f5e3Sopenharmony_ci mirType->GetPrimType() == x.GetPrimType(); 13694514f5e3Sopenharmony_ci} 13704514f5e3Sopenharmony_ci 13714514f5e3Sopenharmony_ci// sext and zext also handled automatically 13724514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldExtractbits(ExtractbitsNode *node) 13734514f5e3Sopenharmony_ci{ 13744514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 13754514f5e3Sopenharmony_ci BaseNode *result = nullptr; 13764514f5e3Sopenharmony_ci uint8 offset = node->GetBitsOffset(); 13774514f5e3Sopenharmony_ci uint8 size = node->GetBitsSize(); 13784514f5e3Sopenharmony_ci Opcode opcode = node->GetOpCode(); 13794514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node->Opnd(0)); 13804514f5e3Sopenharmony_ci ConstvalNode *cst = safe_cast<ConstvalNode>(p.first); 13814514f5e3Sopenharmony_ci if (cst != nullptr && (opcode == OP_sext || opcode == OP_zext)) { 13824514f5e3Sopenharmony_ci result = FoldSignExtend(opcode, node->GetPrimType(), size, *cst); 13834514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 13844514f5e3Sopenharmony_ci } 13854514f5e3Sopenharmony_ci BaseNode *e = PairToExpr(node->Opnd(0)->GetPrimType(), p); 13864514f5e3Sopenharmony_ci if (e != node->Opnd(0)) { 13874514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<ExtractbitsNode>(opcode, PrimType(node->GetPrimType()), offset, 13884514f5e3Sopenharmony_ci size, e); 13894514f5e3Sopenharmony_ci } else { 13904514f5e3Sopenharmony_ci result = node; 13914514f5e3Sopenharmony_ci } 13924514f5e3Sopenharmony_ci // check for consecutive and redundant extraction of same bits 13934514f5e3Sopenharmony_ci BaseNode *opnd = result->Opnd(0); 13944514f5e3Sopenharmony_ci DEBUG_ASSERT(opnd != nullptr, "opnd shoule not be null"); 13954514f5e3Sopenharmony_ci Opcode opndOp = opnd->GetOpCode(); 13964514f5e3Sopenharmony_ci if (opndOp == OP_extractbits || opndOp == OP_sext || opndOp == OP_zext) { 13974514f5e3Sopenharmony_ci uint8 opndOffset = static_cast<ExtractbitsNode*>(opnd)->GetBitsOffset(); 13984514f5e3Sopenharmony_ci uint8 opndSize = static_cast<ExtractbitsNode*>(opnd)->GetBitsSize(); 13994514f5e3Sopenharmony_ci if (offset == opndOffset && size == opndSize) { 14004514f5e3Sopenharmony_ci result->SetOpnd(opnd->Opnd(0), 0); // delete the redundant extraction 14014514f5e3Sopenharmony_ci } 14024514f5e3Sopenharmony_ci } 14034514f5e3Sopenharmony_ci if (offset == 0 && size >= k8ByteSize && IsPowerOf2(size)) { 14044514f5e3Sopenharmony_ci if (ExtractbitsRedundant(*static_cast<ExtractbitsNode*>(result), *mirModule->CurFunction())) { 14054514f5e3Sopenharmony_ci return std::make_pair(result->Opnd(0), std::nullopt); 14064514f5e3Sopenharmony_ci } 14074514f5e3Sopenharmony_ci } 14084514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 14094514f5e3Sopenharmony_ci} 14104514f5e3Sopenharmony_ci 14114514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldIread(IreadNode *node) 14124514f5e3Sopenharmony_ci{ 14134514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 14144514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node->Opnd(0)); 14154514f5e3Sopenharmony_ci BaseNode *e = PairToExpr(node->Opnd(0)->GetPrimType(), p); 14164514f5e3Sopenharmony_ci node->SetOpnd(e, 0); 14174514f5e3Sopenharmony_ci BaseNode *result = node; 14184514f5e3Sopenharmony_ci if (e->GetOpCode() != OP_addrof) { 14194514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 14204514f5e3Sopenharmony_ci } 14214514f5e3Sopenharmony_ci 14224514f5e3Sopenharmony_ci AddrofNode *addrofNode = static_cast<AddrofNode*>(e); 14234514f5e3Sopenharmony_ci MIRSymbol *msy = mirModule->CurFunction()->GetLocalOrGlobalSymbol(addrofNode->GetStIdx()); 14244514f5e3Sopenharmony_ci DEBUG_ASSERT(msy != nullptr, "nullptr check"); 14254514f5e3Sopenharmony_ci TyIdx typeId = msy->GetTyIdx(); 14264514f5e3Sopenharmony_ci CHECK_FATAL(!GlobalTables::GetTypeTable().GetTypeTable().empty(), "container check"); 14274514f5e3Sopenharmony_ci MIRType *msyType = GlobalTables::GetTypeTable().GetTypeTable()[typeId]; 14284514f5e3Sopenharmony_ci MIRPtrType *ptrType = static_cast<MIRPtrType *>(GlobalTables::GetTypeTable().GetTypeFromTyIdx(node->GetTyIdx())); 14294514f5e3Sopenharmony_ci // If the high level type of iaddrof/iread doesn't match 14304514f5e3Sopenharmony_ci // the type of addrof's rhs, this optimization cannot be done. 14314514f5e3Sopenharmony_ci if (ptrType->GetPointedType() != msyType) { 14324514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 14334514f5e3Sopenharmony_ci } 14344514f5e3Sopenharmony_ci 14354514f5e3Sopenharmony_ci Opcode op = node->GetOpCode(); 14364514f5e3Sopenharmony_ci if (op == OP_iread) { 14374514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<AddrofNode>(OP_dread, node->GetPrimType(), addrofNode->GetStIdx(), 14384514f5e3Sopenharmony_ci node->GetFieldID() + addrofNode->GetFieldID()); 14394514f5e3Sopenharmony_ci } 14404514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 14414514f5e3Sopenharmony_ci} 14424514f5e3Sopenharmony_ci 14434514f5e3Sopenharmony_cibool ConstantFold::IntegerOpIsOverflow(Opcode op, PrimType primType, int64 cstA, int64 cstB) 14444514f5e3Sopenharmony_ci{ 14454514f5e3Sopenharmony_ci switch (op) { 14464514f5e3Sopenharmony_ci case OP_add: { 14474514f5e3Sopenharmony_ci int64 res = static_cast<int64>(static_cast<uint64>(cstA) + static_cast<uint64>(cstB)); 14484514f5e3Sopenharmony_ci if (IsUnsignedInteger(primType)) { 14494514f5e3Sopenharmony_ci return static_cast<uint64>(res) < static_cast<uint64>(cstA); 14504514f5e3Sopenharmony_ci } 14514514f5e3Sopenharmony_ci auto rightShiftNumToGetSignFlag = GetPrimTypeBitSize(primType) - 1; 14524514f5e3Sopenharmony_ci return (static_cast<uint64>(res) >> rightShiftNumToGetSignFlag != 14534514f5e3Sopenharmony_ci static_cast<uint64>(cstA) >> rightShiftNumToGetSignFlag) && 14544514f5e3Sopenharmony_ci (static_cast<uint64>(res) >> rightShiftNumToGetSignFlag != 14554514f5e3Sopenharmony_ci static_cast<uint64>(cstB) >> rightShiftNumToGetSignFlag); 14564514f5e3Sopenharmony_ci } 14574514f5e3Sopenharmony_ci case OP_sub: { 14584514f5e3Sopenharmony_ci if (IsUnsignedInteger(primType)) { 14594514f5e3Sopenharmony_ci return cstA < cstB; 14604514f5e3Sopenharmony_ci } 14614514f5e3Sopenharmony_ci int64 res = static_cast<int64>(static_cast<uint64>(cstA) - static_cast<uint64>(cstB)); 14624514f5e3Sopenharmony_ci auto rightShiftNumToGetSignFlag = GetPrimTypeBitSize(primType) - 1; 14634514f5e3Sopenharmony_ci return (static_cast<uint64>(cstA) >> rightShiftNumToGetSignFlag != 14644514f5e3Sopenharmony_ci static_cast<uint64>(cstB) >> rightShiftNumToGetSignFlag) && 14654514f5e3Sopenharmony_ci (static_cast<uint64>(res) >> rightShiftNumToGetSignFlag != 14664514f5e3Sopenharmony_ci static_cast<uint64>(cstA) >> rightShiftNumToGetSignFlag); 14674514f5e3Sopenharmony_ci } 14684514f5e3Sopenharmony_ci default: { 14694514f5e3Sopenharmony_ci return false; 14704514f5e3Sopenharmony_ci } 14714514f5e3Sopenharmony_ci } 14724514f5e3Sopenharmony_ci} 14734514f5e3Sopenharmony_ci 14744514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldBinary(BinaryNode *node) 14754514f5e3Sopenharmony_ci{ 14764514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 14774514f5e3Sopenharmony_ci BaseNode *result = nullptr; 14784514f5e3Sopenharmony_ci std::optional<IntVal> sum = std::nullopt; 14794514f5e3Sopenharmony_ci Opcode op = node->GetOpCode(); 14804514f5e3Sopenharmony_ci PrimType primType = node->GetPrimType(); 14814514f5e3Sopenharmony_ci PrimType lPrimTypes = node->Opnd(0)->GetPrimType(); 14824514f5e3Sopenharmony_ci PrimType rPrimTypes = node->Opnd(1)->GetPrimType(); 14834514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> lp = DispatchFold(node->Opnd(0)); 14844514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> rp = DispatchFold(node->Opnd(1)); 14854514f5e3Sopenharmony_ci BaseNode *l = lp.first; 14864514f5e3Sopenharmony_ci BaseNode *r = rp.first; 14874514f5e3Sopenharmony_ci ASSERT_NOT_NULL(r); 14884514f5e3Sopenharmony_ci ConstvalNode *lConst = safe_cast<ConstvalNode>(l); 14894514f5e3Sopenharmony_ci ConstvalNode *rConst = safe_cast<ConstvalNode>(r); 14904514f5e3Sopenharmony_ci bool isInt = IsPrimitiveInteger(primType); 14914514f5e3Sopenharmony_ci 14924514f5e3Sopenharmony_ci if (lConst != nullptr && rConst != nullptr) { 14934514f5e3Sopenharmony_ci MIRConst *lConstVal = lConst->GetConstVal(); 14944514f5e3Sopenharmony_ci MIRConst *rConstVal = rConst->GetConstVal(); 14954514f5e3Sopenharmony_ci ASSERT_NOT_NULL(lConstVal); 14964514f5e3Sopenharmony_ci ASSERT_NOT_NULL(rConstVal); 14974514f5e3Sopenharmony_ci // Don't fold div by 0, for floats div by 0 is well defined. 14984514f5e3Sopenharmony_ci if ((op == OP_div || op == OP_rem) && isInt && 14994514f5e3Sopenharmony_ci !IsDivSafe(static_cast<MIRIntConst &>(*lConstVal), static_cast<MIRIntConst &>(*rConstVal), primType)) { 15004514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, lConst, rConst); 15014514f5e3Sopenharmony_ci } else { 15024514f5e3Sopenharmony_ci // 4 + 2 -> return a pair(result = ConstValNode(6), sum = 0) 15034514f5e3Sopenharmony_ci // Create a new ConstvalNode for 6 but keep the sum = 0. This simplify the 15044514f5e3Sopenharmony_ci // logic since the alternative is to return pair(result = nullptr, sum = 6). 15054514f5e3Sopenharmony_ci // Doing so would introduce many nullptr checks in the code. See previous 15064514f5e3Sopenharmony_ci // commits that implemented that logic for a comparison. 15074514f5e3Sopenharmony_ci result = FoldConstBinary(op, primType, *lConst, *rConst); 15084514f5e3Sopenharmony_ci } 15094514f5e3Sopenharmony_ci } else if (lConst != nullptr && isInt) { 15104514f5e3Sopenharmony_ci MIRIntConst *mcst = safe_cast<MIRIntConst>(lConst->GetConstVal()); 15114514f5e3Sopenharmony_ci ASSERT_NOT_NULL(mcst); 15124514f5e3Sopenharmony_ci PrimType cstTyp = mcst->GetType().GetPrimType(); 15134514f5e3Sopenharmony_ci IntVal cst = mcst->GetValue(); 15144514f5e3Sopenharmony_ci if (op == OP_add) { 15154514f5e3Sopenharmony_ci if (IsSignedInteger(cstTyp) && rp.second && 15164514f5e3Sopenharmony_ci IntegerOpIsOverflow(OP_add, cstTyp, cst.GetExtValue(), rp.second->GetExtValue())) { 15174514f5e3Sopenharmony_ci // do not introduce signed integer overflow 15184514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, l, PairToExpr(rPrimTypes, rp)); 15194514f5e3Sopenharmony_ci } else { 15204514f5e3Sopenharmony_ci sum = cst + rp.second; 15214514f5e3Sopenharmony_ci result = r; 15224514f5e3Sopenharmony_ci } 15234514f5e3Sopenharmony_ci } else if (op == OP_sub && r->GetPrimType() != PTY_u1) { 15244514f5e3Sopenharmony_ci // We exclude u1 type for fixing the following wrong example: 15254514f5e3Sopenharmony_ci // before cf: 15264514f5e3Sopenharmony_ci // sub i32 (constval i32 17, eq u1 i32 (dread i32 %i, constval i32 16))) 15274514f5e3Sopenharmony_ci // after cf: 15284514f5e3Sopenharmony_ci // add i32 (cvt i32 u1 (neg u1 (eq u1 i32 (dread i32 %i, constval i32 16))), constval i32 17)) 15294514f5e3Sopenharmony_ci sum = cst - rp.second; 15304514f5e3Sopenharmony_ci if (GetPrimTypeSize(r->GetPrimType()) < GetPrimTypeSize(primType)) { 15314514f5e3Sopenharmony_ci r = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, r->GetPrimType(), r); 15324514f5e3Sopenharmony_ci } 15334514f5e3Sopenharmony_ci result = NegateTree(r); 15344514f5e3Sopenharmony_ci } else if ((op == OP_mul || op == OP_div || op == OP_rem || op == OP_ashr || op == OP_lshr || op == OP_shl || 15354514f5e3Sopenharmony_ci op == OP_band) && 15364514f5e3Sopenharmony_ci cst == 0) { 15374514f5e3Sopenharmony_ci // 0 * X -> 0 15384514f5e3Sopenharmony_ci // 0 / X -> 0 15394514f5e3Sopenharmony_ci // 0 % X -> 0 15404514f5e3Sopenharmony_ci // 0 >> X -> 0 15414514f5e3Sopenharmony_ci // 0 << X -> 0 15424514f5e3Sopenharmony_ci // 0 & X -> 0 15434514f5e3Sopenharmony_ci // 0 && X -> 0 15444514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateIntConst(0, cstTyp); 15454514f5e3Sopenharmony_ci } else if (op == OP_mul && cst == 1) { 15464514f5e3Sopenharmony_ci // 1 * X --> X 15474514f5e3Sopenharmony_ci sum = rp.second; 15484514f5e3Sopenharmony_ci result = r; 15494514f5e3Sopenharmony_ci } else if (op == OP_bior && cst == -1) { 15504514f5e3Sopenharmony_ci // (-1) | X -> -1 15514514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateIntConst(static_cast<uint64>(-1), cstTyp); 15524514f5e3Sopenharmony_ci } else if (op == OP_mul && rp.second.has_value() && *rp.second != 0) { 15534514f5e3Sopenharmony_ci // lConst * (X + konst) -> the pair [(lConst*X), (lConst*konst)] 15544514f5e3Sopenharmony_ci sum = cst * rp.second; 15554514f5e3Sopenharmony_ci if (GetPrimTypeSize(primType) > GetPrimTypeSize(rp.first->GetPrimType())) { 15564514f5e3Sopenharmony_ci rp.first = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, PTY_i32, rp.first); 15574514f5e3Sopenharmony_ci } 15584514f5e3Sopenharmony_ci result = NewBinaryNode(node, OP_mul, primType, lConst, rp.first); 15594514f5e3Sopenharmony_ci } else if ((op == OP_bior || op == OP_bxor) && cst == 0) { 15604514f5e3Sopenharmony_ci // 0 | X -> X 15614514f5e3Sopenharmony_ci // 0 ^ X -> X 15624514f5e3Sopenharmony_ci sum = rp.second; 15634514f5e3Sopenharmony_ci result = r; 15644514f5e3Sopenharmony_ci } else { 15654514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, l, PairToExpr(rPrimTypes, rp)); 15664514f5e3Sopenharmony_ci } 15674514f5e3Sopenharmony_ci if (!IsNoCvtNeeded(result->GetPrimType(), primType)) { 15684514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, result->GetPrimType(), result); 15694514f5e3Sopenharmony_ci } 15704514f5e3Sopenharmony_ci } else if (rConst != nullptr && isInt) { 15714514f5e3Sopenharmony_ci MIRIntConst *mcst = safe_cast<MIRIntConst>(rConst->GetConstVal()); 15724514f5e3Sopenharmony_ci ASSERT_NOT_NULL(mcst); 15734514f5e3Sopenharmony_ci PrimType cstTyp = mcst->GetType().GetPrimType(); 15744514f5e3Sopenharmony_ci IntVal cst = mcst->GetValue(); 15754514f5e3Sopenharmony_ci if (op == OP_add) { 15764514f5e3Sopenharmony_ci if (lp.second && IntegerOpIsOverflow(op, cstTyp, lp.second->GetExtValue(), cst.GetExtValue())) { 15774514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), PairToExpr(rPrimTypes, rp)); 15784514f5e3Sopenharmony_ci } else { 15794514f5e3Sopenharmony_ci result = l; 15804514f5e3Sopenharmony_ci sum = lp.second + cst; 15814514f5e3Sopenharmony_ci } 15824514f5e3Sopenharmony_ci } else if (op == OP_sub && (!cst.IsSigned() || !cst.IsMinValue())) { 15834514f5e3Sopenharmony_ci result = l; 15844514f5e3Sopenharmony_ci sum = lp.second - cst; 15854514f5e3Sopenharmony_ci } else if ((op == OP_mul || op == OP_band) && cst == 0) { 15864514f5e3Sopenharmony_ci // X * 0 -> 0 15874514f5e3Sopenharmony_ci // X & 0 -> 0 15884514f5e3Sopenharmony_ci // X && 0 -> 0 15894514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateIntConst(0, cstTyp); 15904514f5e3Sopenharmony_ci } else if ((op == OP_mul || op == OP_div) && cst == 1) { 15914514f5e3Sopenharmony_ci // case [X * 1 -> X] 15924514f5e3Sopenharmony_ci // case [X / 1 = X] 15934514f5e3Sopenharmony_ci sum = lp.second; 15944514f5e3Sopenharmony_ci result = l; 15954514f5e3Sopenharmony_ci } else if (op == OP_div && !lp.second.has_value() && l->GetOpCode() == OP_mul && 15964514f5e3Sopenharmony_ci IsSignedInteger(primType) && IsSignedInteger(lPrimTypes) && IsSignedInteger(rPrimTypes)) { 15974514f5e3Sopenharmony_ci // temporary fix for constfold of mul/div in DejaGnu 15984514f5e3Sopenharmony_ci // Later we need a more formal interface for pattern match 15994514f5e3Sopenharmony_ci // X * Y / Y -> X 16004514f5e3Sopenharmony_ci BaseNode *x = l->Opnd(0); 16014514f5e3Sopenharmony_ci BaseNode *y = l->Opnd(1); 16024514f5e3Sopenharmony_ci ConstvalNode *xConst = safe_cast<ConstvalNode>(x); 16034514f5e3Sopenharmony_ci ConstvalNode *yConst = safe_cast<ConstvalNode>(y); 16044514f5e3Sopenharmony_ci bool foldMulDiv = false; 16054514f5e3Sopenharmony_ci if (yConst != nullptr && xConst == nullptr && 16064514f5e3Sopenharmony_ci IsSignedInteger(x->GetPrimType()) && IsSignedInteger(y->GetPrimType())) { 16074514f5e3Sopenharmony_ci MIRIntConst *yCst = safe_cast<MIRIntConst>(yConst->GetConstVal()); 16084514f5e3Sopenharmony_ci ASSERT_NOT_NULL(yCst); 16094514f5e3Sopenharmony_ci IntVal mulCst = yCst->GetValue(); 16104514f5e3Sopenharmony_ci if (mulCst.GetBitWidth() == cst.GetBitWidth() && mulCst.IsSigned() == cst.IsSigned() && 16114514f5e3Sopenharmony_ci mulCst.GetExtValue() == cst.GetExtValue()) { 16124514f5e3Sopenharmony_ci foldMulDiv = true; 16134514f5e3Sopenharmony_ci result = x; 16144514f5e3Sopenharmony_ci } 16154514f5e3Sopenharmony_ci } else if (xConst != nullptr && yConst == nullptr && 16164514f5e3Sopenharmony_ci IsSignedInteger(x->GetPrimType()) && IsSignedInteger(y->GetPrimType())) { 16174514f5e3Sopenharmony_ci MIRIntConst *xCst = safe_cast<MIRIntConst>(xConst->GetConstVal()); 16184514f5e3Sopenharmony_ci ASSERT_NOT_NULL(xCst); 16194514f5e3Sopenharmony_ci IntVal mulCst = xCst->GetValue(); 16204514f5e3Sopenharmony_ci if (mulCst.GetBitWidth() == cst.GetBitWidth() && mulCst.IsSigned() == cst.IsSigned() && 16214514f5e3Sopenharmony_ci mulCst.GetExtValue() == cst.GetExtValue()) { 16224514f5e3Sopenharmony_ci foldMulDiv = true; 16234514f5e3Sopenharmony_ci result = y; 16244514f5e3Sopenharmony_ci } 16254514f5e3Sopenharmony_ci } 16264514f5e3Sopenharmony_ci if (!foldMulDiv) { 16274514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), r); 16284514f5e3Sopenharmony_ci } 16294514f5e3Sopenharmony_ci } else if (op == OP_mul && lp.second.has_value() && *lp.second != 0 && lp.second->GetSXTValue() > -kMaxOffset) { 16304514f5e3Sopenharmony_ci // (X + konst) * rConst -> the pair [(X*rConst), (konst*rConst)] 16314514f5e3Sopenharmony_ci sum = lp.second * cst; 16324514f5e3Sopenharmony_ci if (GetPrimTypeSize(primType) > GetPrimTypeSize(lp.first->GetPrimType())) { 16334514f5e3Sopenharmony_ci lp.first = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, PTY_i32, lp.first); 16344514f5e3Sopenharmony_ci } 16354514f5e3Sopenharmony_ci if (lp.first->GetOpCode() == OP_neg && cst == -1) { 16364514f5e3Sopenharmony_ci // special case: ((-X) + konst) * (-1) -> the pair [(X), -konst] 16374514f5e3Sopenharmony_ci result = lp.first->Opnd(0); 16384514f5e3Sopenharmony_ci } else { 16394514f5e3Sopenharmony_ci result = NewBinaryNode(node, OP_mul, primType, lp.first, rConst); 16404514f5e3Sopenharmony_ci } 16414514f5e3Sopenharmony_ci } else if (op == OP_band && cst == -1) { 16424514f5e3Sopenharmony_ci // X & (-1) -> X 16434514f5e3Sopenharmony_ci sum = lp.second; 16444514f5e3Sopenharmony_ci result = l; 16454514f5e3Sopenharmony_ci } else if (op == OP_band && ContiguousBitsOf1(cst.GetZXTValue()) && 16464514f5e3Sopenharmony_ci (!lp.second.has_value() || lp.second == 0)) { 16474514f5e3Sopenharmony_ci bool fold2extractbits = false; 16484514f5e3Sopenharmony_ci if (l->GetOpCode() == OP_ashr || l->GetOpCode() == OP_lshr) { 16494514f5e3Sopenharmony_ci BinaryNode *shrNode = static_cast<BinaryNode *>(l); 16504514f5e3Sopenharmony_ci if (shrNode->Opnd(1)->GetOpCode() == OP_constval) { 16514514f5e3Sopenharmony_ci ConstvalNode *shrOpnd = static_cast<ConstvalNode *>(shrNode->Opnd(1)); 16524514f5e3Sopenharmony_ci int64 shrAmt = static_cast<MIRIntConst*>(shrOpnd->GetConstVal())->GetExtValue(); 16534514f5e3Sopenharmony_ci uint64 ucst = cst.GetZXTValue(); 16544514f5e3Sopenharmony_ci uint32 bsize = 0; 16554514f5e3Sopenharmony_ci do { 16564514f5e3Sopenharmony_ci bsize++; 16574514f5e3Sopenharmony_ci ucst >>= 1; 16584514f5e3Sopenharmony_ci } while (ucst != 0); 16594514f5e3Sopenharmony_ci if (shrAmt + static_cast<int64>(bsize) <= 16604514f5e3Sopenharmony_ci static_cast<int64>(GetPrimTypeSize(primType) * kBitSizePerByte) && 16614514f5e3Sopenharmony_ci static_cast<uint64>(shrAmt) < GetPrimTypeSize(primType) * kBitSizePerByte) { 16624514f5e3Sopenharmony_ci fold2extractbits = true; 16634514f5e3Sopenharmony_ci // change to use extractbits 16644514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateExprExtractbits(OP_extractbits, 16654514f5e3Sopenharmony_ci GetUnsignedPrimType(primType), static_cast<uint32>(shrAmt), bsize, shrNode->Opnd(0)); 16664514f5e3Sopenharmony_ci sum = std::nullopt; 16674514f5e3Sopenharmony_ci } 16684514f5e3Sopenharmony_ci } 16694514f5e3Sopenharmony_ci } 16704514f5e3Sopenharmony_ci if (!fold2extractbits) { 16714514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), r); 16724514f5e3Sopenharmony_ci sum = std::nullopt; 16734514f5e3Sopenharmony_ci } 16744514f5e3Sopenharmony_ci } else if (op == OP_bior && cst == -1) { 16754514f5e3Sopenharmony_ci // X | (-1) -> -1 16764514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateIntConst(-1ULL, cstTyp); 16774514f5e3Sopenharmony_ci } else if ((op == OP_ashr || op == OP_lshr || op == OP_shl || op == OP_bior || op == OP_bxor) && cst == 0) { 16784514f5e3Sopenharmony_ci // X >> 0 -> X 16794514f5e3Sopenharmony_ci // X << 0 -> X 16804514f5e3Sopenharmony_ci // X | 0 -> X 16814514f5e3Sopenharmony_ci // X ^ 0 -> X 16824514f5e3Sopenharmony_ci sum = lp.second; 16834514f5e3Sopenharmony_ci result = l; 16844514f5e3Sopenharmony_ci } else if (op == OP_bxor && cst == 1 && primType != PTY_u1) { 16854514f5e3Sopenharmony_ci // bxor i32 ( 16864514f5e3Sopenharmony_ci // cvt i32 u1 (regread u1 %13), 16874514f5e3Sopenharmony_ci // constValue i32 1), 16884514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), PairToExpr(rPrimTypes, rp)); 16894514f5e3Sopenharmony_ci if (l->GetOpCode() == OP_cvt && (!lp.second || lp.second == 0)) { 16904514f5e3Sopenharmony_ci TypeCvtNode *cvtNode = static_cast<TypeCvtNode*>(l); 16914514f5e3Sopenharmony_ci if (cvtNode->Opnd(0)->GetPrimType() == PTY_u1) { 16924514f5e3Sopenharmony_ci BaseNode *base = cvtNode->Opnd(0); 16934514f5e3Sopenharmony_ci BaseNode *constValue = mirModule->GetMIRBuilder()->CreateIntConst(1, base->GetPrimType()); 16944514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(base); 16954514f5e3Sopenharmony_ci BinaryNode *temp = NewBinaryNode(node, op, PTY_u1, PairToExpr(base->GetPrimType(), p), constValue); 16964514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, PTY_u1, temp); 16974514f5e3Sopenharmony_ci } 16984514f5e3Sopenharmony_ci } 16994514f5e3Sopenharmony_ci } else if (op == OP_rem && cst == 1) { 17004514f5e3Sopenharmony_ci // X % 1 -> 0 17014514f5e3Sopenharmony_ci result = mirModule->GetMIRBuilder()->CreateIntConst(0, cstTyp); 17024514f5e3Sopenharmony_ci } else { 17034514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), r); 17044514f5e3Sopenharmony_ci } 17054514f5e3Sopenharmony_ci if (!IsNoCvtNeeded(result->GetPrimType(), primType)) { 17064514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<TypeCvtNode>(OP_cvt, primType, result->GetPrimType(), result); 17074514f5e3Sopenharmony_ci } 17084514f5e3Sopenharmony_ci } else if (isInt && (op == OP_add || op == OP_sub)) { 17094514f5e3Sopenharmony_ci if (op == OP_add) { 17104514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, l, r); 17114514f5e3Sopenharmony_ci sum = lp.second + rp.second; 17124514f5e3Sopenharmony_ci } else if (r != nullptr && node->Opnd(1)->GetOpCode() == OP_sub && r->GetOpCode() == OP_neg) { 17134514f5e3Sopenharmony_ci // if fold is (x - (y - z)) -> (x - neg(z)) - y 17144514f5e3Sopenharmony_ci // (x - neg(z)) Could cross the int limit 17154514f5e3Sopenharmony_ci // return node 17164514f5e3Sopenharmony_ci result = node; 17174514f5e3Sopenharmony_ci } else { 17184514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, l, r); 17194514f5e3Sopenharmony_ci sum = lp.second - rp.second; 17204514f5e3Sopenharmony_ci } 17214514f5e3Sopenharmony_ci } else { 17224514f5e3Sopenharmony_ci result = NewBinaryNode(node, op, primType, PairToExpr(lPrimTypes, lp), PairToExpr(rPrimTypes, rp)); 17234514f5e3Sopenharmony_ci } 17244514f5e3Sopenharmony_ci return std::make_pair(result, sum); 17254514f5e3Sopenharmony_ci} 17264514f5e3Sopenharmony_ci 17274514f5e3Sopenharmony_ciBaseNode *ConstantFold::SimplifyDoubleConstvalCompare(CompareNode &node, bool isRConstval, bool isGtOrLt) const 17284514f5e3Sopenharmony_ci{ 17294514f5e3Sopenharmony_ci if (isRConstval) { 17304514f5e3Sopenharmony_ci ConstvalNode *constNode = static_cast<ConstvalNode*>(node.Opnd(1)); 17314514f5e3Sopenharmony_ci if (constNode->GetConstVal()->GetKind() == kConstInt && constNode->GetConstVal()->IsZero()) { 17324514f5e3Sopenharmony_ci const CompareNode *compNode = static_cast<CompareNode*>(node.Opnd(0)); 17334514f5e3Sopenharmony_ci return mirModule->CurFuncCodeMemPool()->New<CompareNode>(node.GetOpCode(), 17344514f5e3Sopenharmony_ci node.GetPrimType(), compNode->GetOpndType(), compNode->Opnd(0), compNode->Opnd(1)); 17354514f5e3Sopenharmony_ci } 17364514f5e3Sopenharmony_ci } else { 17374514f5e3Sopenharmony_ci ConstvalNode *constNode = static_cast<ConstvalNode*>(node.Opnd(0)); 17384514f5e3Sopenharmony_ci if (constNode->GetConstVal()->GetKind() == kConstInt && constNode->GetConstVal()->IsZero()) { 17394514f5e3Sopenharmony_ci const CompareNode *compNode = static_cast<CompareNode*>(node.Opnd(1)); 17404514f5e3Sopenharmony_ci if (isGtOrLt) { 17414514f5e3Sopenharmony_ci return mirModule->CurFuncCodeMemPool()->New<CompareNode>(node.GetOpCode(), 17424514f5e3Sopenharmony_ci node.GetPrimType(), compNode->GetOpndType(), compNode->Opnd(1), compNode->Opnd(0)); 17434514f5e3Sopenharmony_ci } else { 17444514f5e3Sopenharmony_ci return mirModule->CurFuncCodeMemPool()->New<CompareNode>(node.GetOpCode(), 17454514f5e3Sopenharmony_ci node.GetPrimType(), compNode->GetOpndType(), compNode->Opnd(0), compNode->Opnd(1)); 17464514f5e3Sopenharmony_ci } 17474514f5e3Sopenharmony_ci } 17484514f5e3Sopenharmony_ci } 17494514f5e3Sopenharmony_ci return &node; 17504514f5e3Sopenharmony_ci} 17514514f5e3Sopenharmony_ci 17524514f5e3Sopenharmony_ciBaseNode *ConstantFold::SimplifyDoubleCompare(CompareNode &compareNode) const 17534514f5e3Sopenharmony_ci{ 17544514f5e3Sopenharmony_ci // See arm manual B.cond(P2993) and FCMP(P1091) 17554514f5e3Sopenharmony_ci CompareNode *node = &compareNode; 17564514f5e3Sopenharmony_ci BaseNode *result = node; 17574514f5e3Sopenharmony_ci BaseNode *l = node->Opnd(0); 17584514f5e3Sopenharmony_ci BaseNode *r = node->Opnd(1); 17594514f5e3Sopenharmony_ci if (node->GetOpCode() == OP_ne || node->GetOpCode() == OP_eq) { 17604514f5e3Sopenharmony_ci if ((l->GetOpCode() == OP_cmp && r->GetOpCode() == OP_constval) || 17614514f5e3Sopenharmony_ci (r->GetOpCode() == OP_cmp && l->GetOpCode() == OP_constval)) { 17624514f5e3Sopenharmony_ci result = SimplifyDoubleConstvalCompare(*node, (l->GetOpCode() == OP_cmp && r->GetOpCode() == OP_constval)); 17634514f5e3Sopenharmony_ci } else if (node->GetOpCode() == OP_ne && r->GetOpCode() == OP_constval) { 17644514f5e3Sopenharmony_ci // ne (u1 x, constValue 0) <==> x 17654514f5e3Sopenharmony_ci ConstvalNode *constNode = static_cast<ConstvalNode*>(r); 17664514f5e3Sopenharmony_ci if (constNode->GetConstVal()->GetKind() == kConstInt && constNode->GetConstVal()->IsZero()) { 17674514f5e3Sopenharmony_ci BaseNode *opnd = l; 17684514f5e3Sopenharmony_ci do { 17694514f5e3Sopenharmony_ci if (opnd->GetPrimType() == PTY_u1 || (l->GetOpCode() == OP_ne || l->GetOpCode() == OP_eq)) { 17704514f5e3Sopenharmony_ci result = opnd; 17714514f5e3Sopenharmony_ci break; 17724514f5e3Sopenharmony_ci } else if (opnd->GetOpCode() == OP_cvt) { 17734514f5e3Sopenharmony_ci TypeCvtNode *cvtNode = static_cast<TypeCvtNode*>(opnd); 17744514f5e3Sopenharmony_ci opnd = cvtNode->Opnd(0); 17754514f5e3Sopenharmony_ci } else { 17764514f5e3Sopenharmony_ci opnd = nullptr; 17774514f5e3Sopenharmony_ci } 17784514f5e3Sopenharmony_ci } while (opnd != nullptr); 17794514f5e3Sopenharmony_ci } 17804514f5e3Sopenharmony_ci } else if (node->GetOpCode() == OP_eq && r->GetOpCode() == OP_constval) { 17814514f5e3Sopenharmony_ci ConstvalNode *constNode = static_cast<ConstvalNode*>(r); 17824514f5e3Sopenharmony_ci if (constNode->GetConstVal()->GetKind() == kConstInt && constNode->GetConstVal()->IsZero() && 17834514f5e3Sopenharmony_ci (l->GetOpCode() == OP_ne || l->GetOpCode() == OP_eq)) { 17844514f5e3Sopenharmony_ci auto resOp = l->GetOpCode() == OP_ne ? OP_eq : OP_ne; 17854514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<CompareNode>( 17864514f5e3Sopenharmony_ci resOp, l->GetPrimType(), static_cast<CompareNode*>(l)->GetOpndType(), l->Opnd(0), l->Opnd(1)); 17874514f5e3Sopenharmony_ci } 17884514f5e3Sopenharmony_ci } 17894514f5e3Sopenharmony_ci } else if (node->GetOpCode() == OP_gt || node->GetOpCode() == OP_lt) { 17904514f5e3Sopenharmony_ci if ((l->GetOpCode() == OP_cmp && r->GetOpCode() == OP_constval) || 17914514f5e3Sopenharmony_ci (r->GetOpCode() == OP_cmp && l->GetOpCode() == OP_constval)) { 17924514f5e3Sopenharmony_ci result = SimplifyDoubleConstvalCompare(*node, 17934514f5e3Sopenharmony_ci (l->GetOpCode() == OP_cmp && r->GetOpCode() == OP_constval), true); 17944514f5e3Sopenharmony_ci } 17954514f5e3Sopenharmony_ci } 17964514f5e3Sopenharmony_ci return result; 17974514f5e3Sopenharmony_ci} 17984514f5e3Sopenharmony_ci 17994514f5e3Sopenharmony_cistd::pair<BaseNode*, std::optional<IntVal>> ConstantFold::FoldCompare(CompareNode *node) 18004514f5e3Sopenharmony_ci{ 18014514f5e3Sopenharmony_ci CHECK_NULL_FATAL(node); 18024514f5e3Sopenharmony_ci BaseNode *result = nullptr; 18034514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> lp = DispatchFold(node->Opnd(0)); 18044514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> rp = DispatchFold(node->Opnd(1)); 18054514f5e3Sopenharmony_ci ConstvalNode *lConst = safe_cast<ConstvalNode>(lp.first); 18064514f5e3Sopenharmony_ci ConstvalNode *rConst = safe_cast<ConstvalNode>(rp.first); 18074514f5e3Sopenharmony_ci Opcode opcode = node->GetOpCode(); 18084514f5e3Sopenharmony_ci if (lConst != nullptr && rConst != nullptr) { 18094514f5e3Sopenharmony_ci result = FoldConstComparison(node->GetOpCode(), node->GetPrimType(), node->GetOpndType(), *lConst, *rConst); 18104514f5e3Sopenharmony_ci } else if (lConst != nullptr && rConst == nullptr && opcode != OP_cmp && 18114514f5e3Sopenharmony_ci lConst->GetConstVal()->GetKind() == kConstInt) { 18124514f5e3Sopenharmony_ci BaseNode *l = lp.first; 18134514f5e3Sopenharmony_ci BaseNode *r = PairToExpr(node->Opnd(1)->GetPrimType(), rp); 18144514f5e3Sopenharmony_ci result = FoldConstComparisonReverse(opcode, node->GetPrimType(), node->GetOpndType(), *l, *r); 18154514f5e3Sopenharmony_ci } else { 18164514f5e3Sopenharmony_ci BaseNode *l = PairToExpr(node->Opnd(0)->GetPrimType(), lp); 18174514f5e3Sopenharmony_ci BaseNode *r = PairToExpr(node->Opnd(1)->GetPrimType(), rp); 18184514f5e3Sopenharmony_ci if (l != node->Opnd(0) || r != node->Opnd(1)) { 18194514f5e3Sopenharmony_ci result = mirModule->CurFuncCodeMemPool()->New<CompareNode>( 18204514f5e3Sopenharmony_ci Opcode(node->GetOpCode()), PrimType(node->GetPrimType()), PrimType(node->GetOpndType()), l, r); 18214514f5e3Sopenharmony_ci } else { 18224514f5e3Sopenharmony_ci result = node; 18234514f5e3Sopenharmony_ci } 18244514f5e3Sopenharmony_ci auto *compareNode = static_cast<CompareNode*>(result); 18254514f5e3Sopenharmony_ci CHECK_NULL_FATAL(compareNode); 18264514f5e3Sopenharmony_ci result = SimplifyDoubleCompare(*compareNode); 18274514f5e3Sopenharmony_ci } 18284514f5e3Sopenharmony_ci return std::make_pair(result, std::nullopt); 18294514f5e3Sopenharmony_ci} 18304514f5e3Sopenharmony_ci 18314514f5e3Sopenharmony_ciBaseNode *ConstantFold::Fold(BaseNode *node) 18324514f5e3Sopenharmony_ci{ 18334514f5e3Sopenharmony_ci if (node == nullptr || kOpcodeInfo.IsStmt(node->GetOpCode())) { 18344514f5e3Sopenharmony_ci return nullptr; 18354514f5e3Sopenharmony_ci } 18364514f5e3Sopenharmony_ci std::pair<BaseNode*, std::optional<IntVal>> p = DispatchFold(node); 18374514f5e3Sopenharmony_ci BaseNode *result = PairToExpr(node->GetPrimType(), p); 18384514f5e3Sopenharmony_ci if (result == node) { 18394514f5e3Sopenharmony_ci result = nullptr; 18404514f5e3Sopenharmony_ci } 18414514f5e3Sopenharmony_ci return result; 18424514f5e3Sopenharmony_ci} 18434514f5e3Sopenharmony_ci 18444514f5e3Sopenharmony_ci} // namespace maple 1845