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