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 "ecmascript/compiler/array_bounds_check_elimination.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
194514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::Run()
204514f5e3Sopenharmony_ci{
214514f5e3Sopenharmony_ci    bounds_.resize(circuit_->GetMaxGateId() + 1, nullptr); // 1: +1 for size
224514f5e3Sopenharmony_ci    indexCheckInfo_.resize(circuit_->GetMaxGateId() + 1, nullptr);
234514f5e3Sopenharmony_ci    graphLinearizer_.SetScheduleJSOpcode();
244514f5e3Sopenharmony_ci    graphLinearizer_.LinearizeGraph();
254514f5e3Sopenharmony_ci    CalcBounds(graphLinearizer_.GetEntryRegion(), nullptr);
264514f5e3Sopenharmony_ci}
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ci/*
294514f5e3Sopenharmony_ci    i_lower + c_lower <= x <= i_upper + c_upper
304514f5e3Sopenharmony_ci    Initially, when nothing about the bounds is known yet, every instrution has the bounds:
314514f5e3Sopenharmony_ci        MIN <= x <= MAX
324514f5e3Sopenharmony_ci*/
334514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound::Bound()
344514f5e3Sopenharmony_ci{
354514f5e3Sopenharmony_ci    lower_ = INT_MIN;
364514f5e3Sopenharmony_ci    upper_ = INT_MAX;
374514f5e3Sopenharmony_ci    lowerGate_ = Circuit::NullGate();
384514f5e3Sopenharmony_ci    upperGate_ = Circuit::NullGate();
394514f5e3Sopenharmony_ci}
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound::Bound(int lower, GateRef lowerGate, int upper, GateRef upperGate)
424514f5e3Sopenharmony_ci{
434514f5e3Sopenharmony_ci    lower_ = lower;
444514f5e3Sopenharmony_ci    upper_ = upper;
454514f5e3Sopenharmony_ci    lowerGate_ = lowerGate;
464514f5e3Sopenharmony_ci    upperGate_ = upperGate;
474514f5e3Sopenharmony_ci}
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound::Bound(TypedBinOp op, GateRef gate, int constant)
504514f5e3Sopenharmony_ci{
514514f5e3Sopenharmony_ci    switch (op) {
524514f5e3Sopenharmony_ci        case TypedBinOp::TYPED_EQ: {
534514f5e3Sopenharmony_ci            lower_ = constant;
544514f5e3Sopenharmony_ci            lowerGate_ = gate;
554514f5e3Sopenharmony_ci            upper_ = constant;
564514f5e3Sopenharmony_ci            upperGate_ = gate;
574514f5e3Sopenharmony_ci            break;
584514f5e3Sopenharmony_ci        }
594514f5e3Sopenharmony_ci        case TypedBinOp::TYPED_NOTEQ: {
604514f5e3Sopenharmony_ci            lower_ = INT_MIN;
614514f5e3Sopenharmony_ci            lowerGate_ = Circuit::NullGate();
624514f5e3Sopenharmony_ci            upper_ = INT_MAX;
634514f5e3Sopenharmony_ci            upperGate_ = Circuit::NullGate();
644514f5e3Sopenharmony_ci            if (gate == Circuit::NullGate()) {
654514f5e3Sopenharmony_ci                if (constant == INT_MIN) {
664514f5e3Sopenharmony_ci                    lower_++;
674514f5e3Sopenharmony_ci                }
684514f5e3Sopenharmony_ci                if (constant == INT_MAX) {
694514f5e3Sopenharmony_ci                    upper_--;
704514f5e3Sopenharmony_ci                }
714514f5e3Sopenharmony_ci            }
724514f5e3Sopenharmony_ci            break;
734514f5e3Sopenharmony_ci        }
744514f5e3Sopenharmony_ci        case TypedBinOp::TYPED_GREATEREQ: {
754514f5e3Sopenharmony_ci            lower_ = constant;
764514f5e3Sopenharmony_ci            lowerGate_ = gate;
774514f5e3Sopenharmony_ci            upper_ = INT_MAX;
784514f5e3Sopenharmony_ci            upperGate_ = Circuit::NullGate();
794514f5e3Sopenharmony_ci            break;
804514f5e3Sopenharmony_ci        }
814514f5e3Sopenharmony_ci        case TypedBinOp::TYPED_LESSEQ: {
824514f5e3Sopenharmony_ci            lower_ = INT_MIN;
834514f5e3Sopenharmony_ci            lowerGate_ = Circuit::NullGate();
844514f5e3Sopenharmony_ci            upper_ = constant;
854514f5e3Sopenharmony_ci            upperGate_ = gate;
864514f5e3Sopenharmony_ci            break;
874514f5e3Sopenharmony_ci        }
884514f5e3Sopenharmony_ci        default: {
894514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "unknown binary op";
904514f5e3Sopenharmony_ci            UNREACHABLE();
914514f5e3Sopenharmony_ci        }
924514f5e3Sopenharmony_ci    }
934514f5e3Sopenharmony_ci}
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::AndOp(Bound *bound, Bound *b)
964514f5e3Sopenharmony_ci{
974514f5e3Sopenharmony_ci    // Update lower bound
984514f5e3Sopenharmony_ci    if (bound->lowerGate_ == b->lowerGate_) {
994514f5e3Sopenharmony_ci        bound->lower_ = std::max(bound->lower_, b->lower_);
1004514f5e3Sopenharmony_ci    }
1014514f5e3Sopenharmony_ci    if (b->HasLower()) {
1024514f5e3Sopenharmony_ci        bool set = true;
1034514f5e3Sopenharmony_ci        if (bound->lowerGate_ != Circuit::NullGate() && b->lowerGate_ != Circuit::NullGate()) {
1044514f5e3Sopenharmony_ci            auto boundLowerGateRegion = graphLinearizer_.GateToRegion(bound->lowerGate_);
1054514f5e3Sopenharmony_ci            auto bLowerGateRegion = graphLinearizer_.GateToRegion(b->lowerGate_);
1064514f5e3Sopenharmony_ci            int32_t boundLowerDominatorDepth = -1;
1074514f5e3Sopenharmony_ci            if (boundLowerGateRegion) {
1084514f5e3Sopenharmony_ci                boundLowerDominatorDepth = boundLowerGateRegion->GetDepth();
1094514f5e3Sopenharmony_ci            }
1104514f5e3Sopenharmony_ci            int32_t bLowerDominatorDepth = -1;
1114514f5e3Sopenharmony_ci            if (bLowerGateRegion) {
1124514f5e3Sopenharmony_ci                bLowerDominatorDepth = bLowerGateRegion->GetDepth();
1134514f5e3Sopenharmony_ci            }
1144514f5e3Sopenharmony_ci            set = (boundLowerDominatorDepth < bLowerDominatorDepth);
1154514f5e3Sopenharmony_ci        }
1164514f5e3Sopenharmony_ci        if (set) {
1174514f5e3Sopenharmony_ci            bound->lower_ = b->lower_;
1184514f5e3Sopenharmony_ci            bound->lowerGate_ = b->lowerGate_;
1194514f5e3Sopenharmony_ci        }
1204514f5e3Sopenharmony_ci    }
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_ci    // Update upper bound
1234514f5e3Sopenharmony_ci    if (bound->upperGate_ == b->upperGate_) {
1244514f5e3Sopenharmony_ci        bound->upper_ = std::min(bound->upper_, b->upper_);
1254514f5e3Sopenharmony_ci    }
1264514f5e3Sopenharmony_ci    if (b->HasUpper()) {
1274514f5e3Sopenharmony_ci        bool set = true;
1284514f5e3Sopenharmony_ci        if (bound->upperGate_ != Circuit::NullGate() && b->upperGate_ != Circuit::NullGate()) {
1294514f5e3Sopenharmony_ci            auto boundUpperGateRegion = graphLinearizer_.GateToRegion(bound->upperGate_);
1304514f5e3Sopenharmony_ci            auto bUpperGateRegion = graphLinearizer_.GateToRegion(b->upperGate_);
1314514f5e3Sopenharmony_ci            int32_t boundUpperDominatorDepth = -1;
1324514f5e3Sopenharmony_ci            if (boundUpperGateRegion) {
1334514f5e3Sopenharmony_ci                boundUpperDominatorDepth = boundUpperGateRegion->GetDepth();
1344514f5e3Sopenharmony_ci            }
1354514f5e3Sopenharmony_ci            int32_t bUpperDominatorDepth = -1;
1364514f5e3Sopenharmony_ci            if (bUpperGateRegion) {
1374514f5e3Sopenharmony_ci                bUpperDominatorDepth = bUpperGateRegion->GetDepth();
1384514f5e3Sopenharmony_ci            }
1394514f5e3Sopenharmony_ci            set = (boundUpperDominatorDepth < bUpperDominatorDepth);
1404514f5e3Sopenharmony_ci        }
1414514f5e3Sopenharmony_ci        if (set) {
1424514f5e3Sopenharmony_ci            bound->upper_ = b->upper_;
1434514f5e3Sopenharmony_ci            bound->upperGate_ = b->upperGate_;
1444514f5e3Sopenharmony_ci        }
1454514f5e3Sopenharmony_ci    }
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ci    return bound;
1484514f5e3Sopenharmony_ci}
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::OrOp(Bound *bound, Bound *b)
1514514f5e3Sopenharmony_ci{
1524514f5e3Sopenharmony_ci    // Update lower bound
1534514f5e3Sopenharmony_ci    if (bound->lowerGate_ != b->lowerGate_) {
1544514f5e3Sopenharmony_ci        bound->lowerGate_ = Circuit::NullGate();
1554514f5e3Sopenharmony_ci        bound->lower_ = INT_MIN;
1564514f5e3Sopenharmony_ci    } else {
1574514f5e3Sopenharmony_ci        bound->lower_ = std::min(bound->lower_, b->lower_);
1584514f5e3Sopenharmony_ci    }
1594514f5e3Sopenharmony_ci    // Update upper bound
1604514f5e3Sopenharmony_ci    if (bound->upperGate_ != b->upperGate_) {
1614514f5e3Sopenharmony_ci        bound->upperGate_ = Circuit::NullGate();
1624514f5e3Sopenharmony_ci        bound->upper_ = INT_MAX;
1634514f5e3Sopenharmony_ci    } else {
1644514f5e3Sopenharmony_ci        bound->upper_ = std::max(bound->upper_, b->upper_);
1654514f5e3Sopenharmony_ci    }
1664514f5e3Sopenharmony_ci
1674514f5e3Sopenharmony_ci    return bound;
1684514f5e3Sopenharmony_ci}
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::DoConstant(GateRef gate)
1714514f5e3Sopenharmony_ci{
1724514f5e3Sopenharmony_ci    int constValue = static_cast<int>(acc_.GetConstantValue(gate));
1734514f5e3Sopenharmony_ci    return chunk_->New<Bound>(constValue, Circuit::NullGate(), constValue, Circuit::NullGate());
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::DoBinaryArithmeticOp(GateRef gate)
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    auto op = acc_.GetTypedBinaryOp(gate);
1794514f5e3Sopenharmony_ci    auto x = FindBoundGate(acc_.GetValueIn(gate, 0));
1804514f5e3Sopenharmony_ci    auto y = FindBoundGate(acc_.GetValueIn(gate, 1));
1814514f5e3Sopenharmony_ci    if (!acc_.IsConstant(x) || !acc_.IsConstant(y)) { // One of the operands must be non-constant!
1824514f5e3Sopenharmony_ci        if (op == TypedBinOp::TYPED_AND && (acc_.IsConstant(x) || acc_.IsConstant(y))) {
1834514f5e3Sopenharmony_ci            int constValue = 0;
1844514f5e3Sopenharmony_ci            if (acc_.IsConstant(x)) {
1854514f5e3Sopenharmony_ci                constValue = static_cast<int>(acc_.GetConstantValue(x));
1864514f5e3Sopenharmony_ci            } else {
1874514f5e3Sopenharmony_ci                constValue = static_cast<int>(acc_.GetConstantValue(y));
1884514f5e3Sopenharmony_ci            }
1894514f5e3Sopenharmony_ci            if (constValue >= 0) {
1904514f5e3Sopenharmony_ci                return chunk_->New<Bound>(0, Circuit::NullGate(), constValue, Circuit::NullGate());
1914514f5e3Sopenharmony_ci            }
1924514f5e3Sopenharmony_ci        } else if (op == TypedBinOp::TYPED_MOD) {
1934514f5e3Sopenharmony_ci            Bound *xBound = GetBound(x);
1944514f5e3Sopenharmony_ci            if (xBound->Lower() >= 0 && xBound->LowerGate() == Circuit::NullGate() && IsArrayLength(y)) {
1954514f5e3Sopenharmony_ci                return chunk_->New<Bound>(0, Circuit::NullGate(), -1, y);
1964514f5e3Sopenharmony_ci            } else if (xBound->HasLower() && xBound->Lower() >= 0 && acc_.IsConstant(y)
1974514f5e3Sopenharmony_ci                        && acc_.GetConstantValue(y) != 0) {
1984514f5e3Sopenharmony_ci                int constValue = static_cast<int>(acc_.GetConstantValue(y));
1994514f5e3Sopenharmony_ci                if (constValue != INT_MIN) {
2004514f5e3Sopenharmony_ci                    return chunk_->New<Bound>(0, Circuit::NullGate(), abs(constValue) - 1, Circuit::NullGate());
2014514f5e3Sopenharmony_ci                } else {
2024514f5e3Sopenharmony_ci                    return chunk_->New<Bound>();
2034514f5e3Sopenharmony_ci                }
2044514f5e3Sopenharmony_ci            } else {
2054514f5e3Sopenharmony_ci                return chunk_->New<Bound>();
2064514f5e3Sopenharmony_ci            }
2074514f5e3Sopenharmony_ci        } else if (((acc_.IsConstant(x) || acc_.IsConstant(y)) && op == TypedBinOp::TYPED_ADD) ||
2084514f5e3Sopenharmony_ci            (acc_.IsConstant(y) && op == TypedBinOp::TYPED_SUB)) {
2094514f5e3Sopenharmony_ci            // x is constant, y is variable.
2104514f5e3Sopenharmony_ci            if (acc_.IsConstant(y)) {
2114514f5e3Sopenharmony_ci                std::swap(x, y);
2124514f5e3Sopenharmony_ci            }
2134514f5e3Sopenharmony_ci
2144514f5e3Sopenharmony_ci            // Add, Constant now in x
2154514f5e3Sopenharmony_ci            int constValue = static_cast<int>(acc_.GetConstantValue(x));
2164514f5e3Sopenharmony_ci            if (op == TypedBinOp::TYPED_SUB) {
2174514f5e3Sopenharmony_ci                constValue = -constValue;
2184514f5e3Sopenharmony_ci            }
2194514f5e3Sopenharmony_ci
2204514f5e3Sopenharmony_ci            Bound *bound = GetBound(y);
2214514f5e3Sopenharmony_ci            if (bound == nullptr) {
2224514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "ArrayBoundsCheckElimination::DoBinaryArithmeticOp:bound is nullptr";
2234514f5e3Sopenharmony_ci                UNREACHABLE();
2244514f5e3Sopenharmony_ci            }
2254514f5e3Sopenharmony_ci            if (!bound->HasUpper() || !bound->HasLower()) {
2264514f5e3Sopenharmony_ci                return chunk_->New<Bound>();
2274514f5e3Sopenharmony_ci            }
2284514f5e3Sopenharmony_ci
2294514f5e3Sopenharmony_ci            int lower = bound->Lower();
2304514f5e3Sopenharmony_ci            int upper = bound->Upper();
2314514f5e3Sopenharmony_ci            int newLower = lower + constValue;
2324514f5e3Sopenharmony_ci            int newUpper = upper + constValue;
2334514f5e3Sopenharmony_ci            bool overflow = ((constValue < 0 && (newLower > lower)) ||
2344514f5e3Sopenharmony_ci                                (constValue > 0 && (newUpper < upper)));
2354514f5e3Sopenharmony_ci            if (overflow) {
2364514f5e3Sopenharmony_ci                return chunk_->New<Bound>();
2374514f5e3Sopenharmony_ci            } else {
2384514f5e3Sopenharmony_ci                return chunk_->New<Bound>(newLower, bound->LowerGate(), newUpper, bound->UpperGate());
2394514f5e3Sopenharmony_ci            }
2404514f5e3Sopenharmony_ci        } else if (op == TypedBinOp::TYPED_SUB) {
2414514f5e3Sopenharmony_ci            Bound *bound = GetBound(x);
2424514f5e3Sopenharmony_ci            if (bound == nullptr) {
2434514f5e3Sopenharmony_ci                LOG_ECMA(FATAL) << "ArrayBoundsCheckElimination::DoBinaryArithmeticOp:bound is nullptr";
2444514f5e3Sopenharmony_ci                UNREACHABLE();
2454514f5e3Sopenharmony_ci            }
2464514f5e3Sopenharmony_ci            if (bound->LowerGate() == y) {
2474514f5e3Sopenharmony_ci                return chunk_->New<Bound>(TypedBinOp::TYPED_GREATEREQ, Circuit::NullGate(), bound->Lower());
2484514f5e3Sopenharmony_ci            } else {
2494514f5e3Sopenharmony_ci                return chunk_->New<Bound>();
2504514f5e3Sopenharmony_ci            }
2514514f5e3Sopenharmony_ci        } else {
2524514f5e3Sopenharmony_ci            return chunk_->New<Bound>();
2534514f5e3Sopenharmony_ci        }
2544514f5e3Sopenharmony_ci    }
2554514f5e3Sopenharmony_ci    return nullptr;
2564514f5e3Sopenharmony_ci}
2574514f5e3Sopenharmony_ci
2584514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::DoUnaryArithmeticOp(GateRef gate)
2594514f5e3Sopenharmony_ci{
2604514f5e3Sopenharmony_ci    auto op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
2614514f5e3Sopenharmony_ci    auto x = FindBoundGate(acc_.GetValueIn(gate, 0));
2624514f5e3Sopenharmony_ci    int constValue = 0;
2634514f5e3Sopenharmony_ci    if (op == TypedUnOp::TYPED_INC) {
2644514f5e3Sopenharmony_ci        constValue = 1;
2654514f5e3Sopenharmony_ci    } else if (op == TypedUnOp::TYPED_DEC) {
2664514f5e3Sopenharmony_ci        constValue = -1;
2674514f5e3Sopenharmony_ci    } else {
2684514f5e3Sopenharmony_ci        return chunk_->New<Bound>();
2694514f5e3Sopenharmony_ci    }
2704514f5e3Sopenharmony_ci    Bound *bound = GetBound(x);
2714514f5e3Sopenharmony_ci    // only support which bounds has been calculated
2724514f5e3Sopenharmony_ci    if (!bound->HasUpper() || !bound->HasLower()) {
2734514f5e3Sopenharmony_ci        return chunk_->New<Bound>();
2744514f5e3Sopenharmony_ci    }
2754514f5e3Sopenharmony_ci
2764514f5e3Sopenharmony_ci    int lower = bound->Lower();
2774514f5e3Sopenharmony_ci    int upper = bound->Upper();
2784514f5e3Sopenharmony_ci    int newLower = lower + constValue;
2794514f5e3Sopenharmony_ci    int newUpper = upper + constValue;
2804514f5e3Sopenharmony_ci    bool overflow = ((constValue < 0 && (newLower > lower)) ||
2814514f5e3Sopenharmony_ci                        (constValue > 0 && (newUpper < upper)));
2824514f5e3Sopenharmony_ci    if (overflow) {
2834514f5e3Sopenharmony_ci        return chunk_->New<Bound>();
2844514f5e3Sopenharmony_ci    } else {
2854514f5e3Sopenharmony_ci        return chunk_->New<Bound>(newLower, bound->LowerGate(), newUpper, bound->UpperGate());
2864514f5e3Sopenharmony_ci    }
2874514f5e3Sopenharmony_ci}
2884514f5e3Sopenharmony_ci
2894514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::InLoop(GateRef loopHeader, GateRef gate)
2904514f5e3Sopenharmony_ci{
2914514f5e3Sopenharmony_ci    while (gate != acc_.GetStateRoot()) {
2924514f5e3Sopenharmony_ci        if (gate == loopHeader) {
2934514f5e3Sopenharmony_ci            return true;
2944514f5e3Sopenharmony_ci        } else {
2954514f5e3Sopenharmony_ci            gate = acc_.GetState(gate, 0);
2964514f5e3Sopenharmony_ci        }
2974514f5e3Sopenharmony_ci    }
2984514f5e3Sopenharmony_ci    return false;
2994514f5e3Sopenharmony_ci}
3004514f5e3Sopenharmony_ci
3014514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::DoPhi(GateRef gate)
3024514f5e3Sopenharmony_ci{
3034514f5e3Sopenharmony_ci    Bound *bound = nullptr;
3044514f5e3Sopenharmony_ci    size_t valueSize = acc_.GetInValueCount(gate);
3054514f5e3Sopenharmony_ci    GateRef stateIn = acc_.GetState(gate);
3064514f5e3Sopenharmony_ci    bool isLoopHead = acc_.IsLoopHead(stateIn);
3074514f5e3Sopenharmony_ci    bool hasUpper = true;
3084514f5e3Sopenharmony_ci    bool hasLower = true;
3094514f5e3Sopenharmony_ci    for (size_t i = 0; i < valueSize; i++) {
3104514f5e3Sopenharmony_ci        GateRef value = FindBoundGate(acc_.GetValueIn(gate, i));
3114514f5e3Sopenharmony_ci        // Check if instruction is connected with phi itself
3124514f5e3Sopenharmony_ci        if (isLoopHead && acc_.GetOpCode(value) == OpCode::TYPED_UNARY_OP
3134514f5e3Sopenharmony_ci            && InLoop(stateIn, value)) {
3144514f5e3Sopenharmony_ci            auto unOp = acc_.GetTypedUnAccessor(value).GetTypedUnOp();
3154514f5e3Sopenharmony_ci            switch (unOp) {
3164514f5e3Sopenharmony_ci                case TypedUnOp::TYPED_INC: {
3174514f5e3Sopenharmony_ci                    hasUpper = false;
3184514f5e3Sopenharmony_ci                    break;
3194514f5e3Sopenharmony_ci                }
3204514f5e3Sopenharmony_ci                case TypedUnOp::TYPED_DEC: {
3214514f5e3Sopenharmony_ci                    hasLower = false;
3224514f5e3Sopenharmony_ci                    break;
3234514f5e3Sopenharmony_ci                }
3244514f5e3Sopenharmony_ci                default:
3254514f5e3Sopenharmony_ci                    break;
3264514f5e3Sopenharmony_ci            }
3274514f5e3Sopenharmony_ci            continue;
3284514f5e3Sopenharmony_ci        }
3294514f5e3Sopenharmony_ci
3304514f5e3Sopenharmony_ci        Bound *vBound = GetBound(value);
3314514f5e3Sopenharmony_ci        if (vBound == nullptr) {
3324514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "ArrayBoundsCheckElimination::DoPhi:vBound is nullptr";
3334514f5e3Sopenharmony_ci            UNREACHABLE();
3344514f5e3Sopenharmony_ci        }
3354514f5e3Sopenharmony_ci        Bound *curBound;
3364514f5e3Sopenharmony_ci        GateRef curGate;
3374514f5e3Sopenharmony_ci        int curConstant;
3384514f5e3Sopenharmony_ci        GetInstrAndConstValueFromOp(value, curGate, curConstant);
3394514f5e3Sopenharmony_ci        if (!vBound->HasUpper() || !vBound->HasLower()) {
3404514f5e3Sopenharmony_ci            curBound = chunk_->New<Bound>(curConstant, curGate, curConstant, curGate);
3414514f5e3Sopenharmony_ci        } else {
3424514f5e3Sopenharmony_ci            curBound = vBound;
3434514f5e3Sopenharmony_ci        }
3444514f5e3Sopenharmony_ci
3454514f5e3Sopenharmony_ci        if (curBound) {
3464514f5e3Sopenharmony_ci            if (!bound) {
3474514f5e3Sopenharmony_ci                bound = curBound->Copy(chunk_);
3484514f5e3Sopenharmony_ci            } else {
3494514f5e3Sopenharmony_ci                bound = OrOp(bound, curBound);
3504514f5e3Sopenharmony_ci            }
3514514f5e3Sopenharmony_ci        } else {
3524514f5e3Sopenharmony_ci            bound = chunk_->New<Bound>();
3534514f5e3Sopenharmony_ci            break;
3544514f5e3Sopenharmony_ci        }
3554514f5e3Sopenharmony_ci    }
3564514f5e3Sopenharmony_ci
3574514f5e3Sopenharmony_ci    if (!hasUpper) {
3584514f5e3Sopenharmony_ci        bound->RemoveUpper();
3594514f5e3Sopenharmony_ci    }
3604514f5e3Sopenharmony_ci    if (!hasLower) {
3614514f5e3Sopenharmony_ci        bound->RemoveLower();
3624514f5e3Sopenharmony_ci    }
3634514f5e3Sopenharmony_ci    return bound;
3644514f5e3Sopenharmony_ci}
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::VisitGate(GateRef gate)
3674514f5e3Sopenharmony_ci{
3684514f5e3Sopenharmony_ci    OpCode op = acc_.GetOpCode(gate);
3694514f5e3Sopenharmony_ci    switch (op) {
3704514f5e3Sopenharmony_ci        case OpCode::CONSTANT:
3714514f5e3Sopenharmony_ci            return DoConstant(gate);
3724514f5e3Sopenharmony_ci        case OpCode::TYPED_BINARY_OP:
3734514f5e3Sopenharmony_ci            return DoBinaryArithmeticOp(gate);
3744514f5e3Sopenharmony_ci        case OpCode::TYPED_UNARY_OP:
3754514f5e3Sopenharmony_ci            return DoUnaryArithmeticOp(gate);
3764514f5e3Sopenharmony_ci        case OpCode::VALUE_SELECTOR:
3774514f5e3Sopenharmony_ci            return DoPhi(gate);
3784514f5e3Sopenharmony_ci        default:
3794514f5e3Sopenharmony_ci            return nullptr;
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci    return nullptr;
3824514f5e3Sopenharmony_ci}
3834514f5e3Sopenharmony_ci
3844514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::GetInstrAndConstValueFromBinaryOp(GateRef gate, GateRef& other, int& value)
3854514f5e3Sopenharmony_ci{
3864514f5e3Sopenharmony_ci    ASSERT(acc_.GetOpCode(gate) == OpCode::TYPED_BINARY_OP);
3874514f5e3Sopenharmony_ci    auto op = acc_.GetTypedBinaryOp(gate);
3884514f5e3Sopenharmony_ci    auto x = FindBoundGate(acc_.GetValueIn(gate, 0));
3894514f5e3Sopenharmony_ci    auto y = FindBoundGate(acc_.GetValueIn(gate, 1));
3904514f5e3Sopenharmony_ci    other = x;
3914514f5e3Sopenharmony_ci    if ((op == TypedBinOp::TYPED_ADD && (acc_.IsConstant(x) || acc_.IsConstant(y)))
3924514f5e3Sopenharmony_ci        || (op == TypedBinOp::TYPED_SUB && acc_.IsConstant(y))) {
3934514f5e3Sopenharmony_ci        if (acc_.IsConstant(x)) {
3944514f5e3Sopenharmony_ci            value = static_cast<int>(acc_.GetConstantValue(x));
3954514f5e3Sopenharmony_ci            other = y;
3964514f5e3Sopenharmony_ci        } else {
3974514f5e3Sopenharmony_ci            value = static_cast<int>(acc_.GetConstantValue(y));
3984514f5e3Sopenharmony_ci            other = x;
3994514f5e3Sopenharmony_ci        }
4004514f5e3Sopenharmony_ci        if (op == TypedBinOp::TYPED_SUB) {
4014514f5e3Sopenharmony_ci            value = -value;
4024514f5e3Sopenharmony_ci        }
4034514f5e3Sopenharmony_ci    } else {
4044514f5e3Sopenharmony_ci        return false;
4054514f5e3Sopenharmony_ci    }
4064514f5e3Sopenharmony_ci    return true;
4074514f5e3Sopenharmony_ci}
4084514f5e3Sopenharmony_ci
4094514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::GetInstrAndConstValueFromUnaryOp(GateRef gate, GateRef& other, int& value)
4104514f5e3Sopenharmony_ci{
4114514f5e3Sopenharmony_ci    ASSERT(acc_.GetOpCode(gate) == OpCode::TYPED_UNARY_OP);
4124514f5e3Sopenharmony_ci    auto op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
4134514f5e3Sopenharmony_ci    auto x = FindBoundGate(acc_.GetValueIn(gate, 0));
4144514f5e3Sopenharmony_ci    if (op == TypedUnOp::TYPED_INC) {
4154514f5e3Sopenharmony_ci        value = 1;
4164514f5e3Sopenharmony_ci        other = x;
4174514f5e3Sopenharmony_ci    } else if (op == TypedUnOp::TYPED_DEC) {
4184514f5e3Sopenharmony_ci        value = -1;
4194514f5e3Sopenharmony_ci        other = x;
4204514f5e3Sopenharmony_ci    } else {
4214514f5e3Sopenharmony_ci        return false;
4224514f5e3Sopenharmony_ci    }
4234514f5e3Sopenharmony_ci    return true;
4244514f5e3Sopenharmony_ci}
4254514f5e3Sopenharmony_ci
4264514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::GetInstrAndConstValueFromOp(GateRef gate, GateRef& instrValue, int& constValue)
4274514f5e3Sopenharmony_ci{
4284514f5e3Sopenharmony_ci    int base = 0;
4294514f5e3Sopenharmony_ci    constValue = 0;
4304514f5e3Sopenharmony_ci    instrValue = gate;
4314514f5e3Sopenharmony_ci    if (acc_.IsConstant(gate)) {
4324514f5e3Sopenharmony_ci        constValue = static_cast<int>(acc_.GetConstantValue(gate));
4334514f5e3Sopenharmony_ci        instrValue = Circuit::NullGate();
4344514f5e3Sopenharmony_ci        return ;
4354514f5e3Sopenharmony_ci    }
4364514f5e3Sopenharmony_ci
4374514f5e3Sopenharmony_ci    while (acc_.GetOpCode(gate) == OpCode::TYPED_BINARY_OP ||
4384514f5e3Sopenharmony_ci           acc_.GetOpCode(gate) == OpCode::TYPED_UNARY_OP) {
4394514f5e3Sopenharmony_ci        bool flag = false;
4404514f5e3Sopenharmony_ci        int value = 0;
4414514f5e3Sopenharmony_ci        GateRef other = Circuit::NullGate();
4424514f5e3Sopenharmony_ci        if (acc_.GetOpCode(gate) == OpCode::TYPED_BINARY_OP) {
4434514f5e3Sopenharmony_ci            flag = GetInstrAndConstValueFromBinaryOp(gate, other, value);
4444514f5e3Sopenharmony_ci        } else if (acc_.GetOpCode(gate) == OpCode::TYPED_UNARY_OP) {
4454514f5e3Sopenharmony_ci            flag = GetInstrAndConstValueFromUnaryOp(gate, other, value);
4464514f5e3Sopenharmony_ci        }
4474514f5e3Sopenharmony_ci        if (!flag) {
4484514f5e3Sopenharmony_ci            break;
4494514f5e3Sopenharmony_ci        }
4504514f5e3Sopenharmony_ci        if (acc_.IsConstant(other)) {
4514514f5e3Sopenharmony_ci            base += value + static_cast<int>(acc_.GetConstantValue(other));
4524514f5e3Sopenharmony_ci            constValue = base;
4534514f5e3Sopenharmony_ci            instrValue = Circuit::NullGate();
4544514f5e3Sopenharmony_ci            break ;
4554514f5e3Sopenharmony_ci        } else {
4564514f5e3Sopenharmony_ci            base += value;
4574514f5e3Sopenharmony_ci            constValue = base;
4584514f5e3Sopenharmony_ci            instrValue = other;
4594514f5e3Sopenharmony_ci            gate = other;
4604514f5e3Sopenharmony_ci        }
4614514f5e3Sopenharmony_ci    }
4624514f5e3Sopenharmony_ci}
4634514f5e3Sopenharmony_ci
4644514f5e3Sopenharmony_ciArrayBoundsCheckElimination::Bound *ArrayBoundsCheckElimination::GetBound(GateRef gate)
4654514f5e3Sopenharmony_ci{
4664514f5e3Sopenharmony_ci    if (gate == Circuit::NullGate()) {
4674514f5e3Sopenharmony_ci        return nullptr;
4684514f5e3Sopenharmony_ci    }
4694514f5e3Sopenharmony_ci    if (!bounds_[acc_.GetId(gate)]) {
4704514f5e3Sopenharmony_ci        bounds_[acc_.GetId(gate)] = chunk_->New<BoundStack>(chunk_);
4714514f5e3Sopenharmony_ci        Bound *bound = VisitGate(gate);
4724514f5e3Sopenharmony_ci        if (bound) {
4734514f5e3Sopenharmony_ci            bounds_[acc_.GetId(gate)]->push_back(bound);
4744514f5e3Sopenharmony_ci        }
4754514f5e3Sopenharmony_ci        if (bounds_[acc_.GetId(gate)]->size() == 0) {
4764514f5e3Sopenharmony_ci            bounds_[acc_.GetId(gate)]->push_back(chunk_->New<Bound>());
4774514f5e3Sopenharmony_ci        }
4784514f5e3Sopenharmony_ci    } else if (bounds_[acc_.GetId(gate)]->size() == 0) {
4794514f5e3Sopenharmony_ci        return chunk_->New<Bound>();
4804514f5e3Sopenharmony_ci    }
4814514f5e3Sopenharmony_ci    return bounds_[acc_.GetId(gate)]->back();
4824514f5e3Sopenharmony_ci}
4834514f5e3Sopenharmony_ci
4844514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::UpdateBound(IntegerStack &pushed, GateRef gate, Bound *bound)
4854514f5e3Sopenharmony_ci{
4864514f5e3Sopenharmony_ci    if (acc_.IsConstant(gate)) {
4874514f5e3Sopenharmony_ci        // No bound update for constants
4884514f5e3Sopenharmony_ci        return;
4894514f5e3Sopenharmony_ci    }
4904514f5e3Sopenharmony_ci    if (!bounds_[acc_.GetId(gate)]) {
4914514f5e3Sopenharmony_ci        GetBound(gate);
4924514f5e3Sopenharmony_ci    }
4934514f5e3Sopenharmony_ci    Bound* top = nullptr;
4944514f5e3Sopenharmony_ci    if (bounds_[acc_.GetId(gate)]->size() > 0) {
4954514f5e3Sopenharmony_ci        top = bounds_[acc_.GetId(gate)]->back();
4964514f5e3Sopenharmony_ci    }
4974514f5e3Sopenharmony_ci    if (top) {
4984514f5e3Sopenharmony_ci        bound = AndOp(bound, top);
4994514f5e3Sopenharmony_ci    }
5004514f5e3Sopenharmony_ci    bounds_[acc_.GetId(gate)]->push_back(bound);
5014514f5e3Sopenharmony_ci    pushed.push_back(acc_.GetId(gate));
5024514f5e3Sopenharmony_ci}
5034514f5e3Sopenharmony_ci
5044514f5e3Sopenharmony_ci/*
5054514f5e3Sopenharmony_cix op y + constValue
5064514f5e3Sopenharmony_cifor example:
5074514f5e3Sopenharmony_ci    x >= Circuit::NullGate() + 0
5084514f5e3Sopenharmony_ci    x < Length + 0
5094514f5e3Sopenharmony_ci*/
5104514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::UpdateBound(IntegerStack &pushed, GateRef x, TypedBinOp op,
5114514f5e3Sopenharmony_ci                                              GateRef instrValue, int constValue)
5124514f5e3Sopenharmony_ci{
5134514f5e3Sopenharmony_ci    if (op == TypedBinOp::TYPED_GREATER) { // x < 3 -> x <= 4
5144514f5e3Sopenharmony_ci        op = TypedBinOp::TYPED_GREATEREQ;
5154514f5e3Sopenharmony_ci        // Cannot Represent c > INT_MAX, do not update bounds
5164514f5e3Sopenharmony_ci        if (constValue == INT_MAX && instrValue == Circuit::NullGate()) {
5174514f5e3Sopenharmony_ci            return;
5184514f5e3Sopenharmony_ci        }
5194514f5e3Sopenharmony_ci        constValue++;
5204514f5e3Sopenharmony_ci    } else if (op == TypedBinOp::TYPED_LESS) { // x > 3 -> x >= 2
5214514f5e3Sopenharmony_ci        op = TypedBinOp::TYPED_LESSEQ;
5224514f5e3Sopenharmony_ci        // Cannot Represent c < INT_MIN, do not update bounds
5234514f5e3Sopenharmony_ci        if (constValue == INT_MIN && instrValue == Circuit::NullGate()) {
5244514f5e3Sopenharmony_ci            return;
5254514f5e3Sopenharmony_ci        }
5264514f5e3Sopenharmony_ci        constValue--;
5274514f5e3Sopenharmony_ci    }
5284514f5e3Sopenharmony_ci    Bound *bound = chunk_->New<Bound>(op, instrValue, constValue);
5294514f5e3Sopenharmony_ci    UpdateBound(pushed, x, bound);
5304514f5e3Sopenharmony_ci}
5314514f5e3Sopenharmony_ci
5324514f5e3Sopenharmony_ci// Add if condition when x is a variable, x op y
5334514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::AddIfCondition(IntegerStack &pushed, GateRef x, GateRef y, TypedBinOp op)
5344514f5e3Sopenharmony_ci{
5354514f5e3Sopenharmony_ci    if (acc_.IsConstant(x)) { // x must be non-constant!
5364514f5e3Sopenharmony_ci        return;
5374514f5e3Sopenharmony_ci    }
5384514f5e3Sopenharmony_ci    int constValue;
5394514f5e3Sopenharmony_ci    GateRef instrValue;
5404514f5e3Sopenharmony_ci    GetInstrAndConstValueFromOp(y, instrValue, constValue);
5414514f5e3Sopenharmony_ci    UpdateBound(pushed, x, op, instrValue, constValue);
5424514f5e3Sopenharmony_ci}
5434514f5e3Sopenharmony_ci
5444514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::IsArrayLength(GateRef gate)
5454514f5e3Sopenharmony_ci{
5464514f5e3Sopenharmony_ci    if (gate == Circuit::NullGate()) {
5474514f5e3Sopenharmony_ci        return false;
5484514f5e3Sopenharmony_ci    }
5494514f5e3Sopenharmony_ci    OpCode op = acc_.GetOpCode(gate);
5504514f5e3Sopenharmony_ci    switch (op) {
5514514f5e3Sopenharmony_ci        case OpCode::LOAD_ARRAY_LENGTH:
5524514f5e3Sopenharmony_ci        case OpCode::LOAD_TYPED_ARRAY_LENGTH:
5534514f5e3Sopenharmony_ci            return true;
5544514f5e3Sopenharmony_ci        default:
5554514f5e3Sopenharmony_ci            return false;
5564514f5e3Sopenharmony_ci    }
5574514f5e3Sopenharmony_ci    UNREACHABLE();
5584514f5e3Sopenharmony_ci    return false;
5594514f5e3Sopenharmony_ci}
5604514f5e3Sopenharmony_ci
5614514f5e3Sopenharmony_ciGateRef ArrayBoundsCheckElimination::FindBoundGate(GateRef gate)
5624514f5e3Sopenharmony_ci{
5634514f5e3Sopenharmony_ci    OpCode op = acc_.GetOpCode(gate);
5644514f5e3Sopenharmony_ci    switch (op) {
5654514f5e3Sopenharmony_ci        // skip gate
5664514f5e3Sopenharmony_ci        case OpCode::RANGE_GUARD:
5674514f5e3Sopenharmony_ci            gate = FindBoundGate(acc_.GetValueIn(gate, 0));
5684514f5e3Sopenharmony_ci            break;
5694514f5e3Sopenharmony_ci        case OpCode::INDEX_CHECK: // get index
5704514f5e3Sopenharmony_ci            gate = FindBoundGate(acc_.GetValueIn(gate, 1));
5714514f5e3Sopenharmony_ci            break;
5724514f5e3Sopenharmony_ci        default:
5734514f5e3Sopenharmony_ci            break;
5744514f5e3Sopenharmony_ci    }
5754514f5e3Sopenharmony_ci    return gate;
5764514f5e3Sopenharmony_ci}
5774514f5e3Sopenharmony_ci
5784514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::InArrayBound(Bound *bound, GateRef length, GateRef array)
5794514f5e3Sopenharmony_ci{
5804514f5e3Sopenharmony_ci    if (!bound || array == Circuit::NullGate()) {
5814514f5e3Sopenharmony_ci        return false;
5824514f5e3Sopenharmony_ci    }
5834514f5e3Sopenharmony_ci
5844514f5e3Sopenharmony_ci    if (bound->Lower() >= 0 && bound->LowerGate() == Circuit::NullGate() &&
5854514f5e3Sopenharmony_ci        bound->Upper() < 0 && bound->UpperGate() != Circuit::NullGate()) {
5864514f5e3Sopenharmony_ci        if (length != Circuit::NullGate() && bound->UpperGate() == length) {
5874514f5e3Sopenharmony_ci            return true;
5884514f5e3Sopenharmony_ci        }
5894514f5e3Sopenharmony_ci    }
5904514f5e3Sopenharmony_ci
5914514f5e3Sopenharmony_ci    return false;
5924514f5e3Sopenharmony_ci}
5934514f5e3Sopenharmony_ci
5944514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::RemoveIndexCheck(GateRef gate)
5954514f5e3Sopenharmony_ci{
5964514f5e3Sopenharmony_ci    ASSERT(acc_.GetDependCount(gate) == 1);
5974514f5e3Sopenharmony_ci    ASSERT(acc_.GetStateCount(gate) == 1);
5984514f5e3Sopenharmony_ci    ASSERT(acc_.GetInValueCount(gate) == 2); // 2: ValueCount
5994514f5e3Sopenharmony_ci
6004514f5e3Sopenharmony_ci    GateRef depend = acc_.GetDep(gate);
6014514f5e3Sopenharmony_ci    GateRef state = acc_.GetState(gate);
6024514f5e3Sopenharmony_ci    GateRef value = acc_.GetValueIn(gate, 1); // Index
6034514f5e3Sopenharmony_ci
6044514f5e3Sopenharmony_ci    acc_.ReplaceGate(gate, state, depend, value);
6054514f5e3Sopenharmony_ci}
6064514f5e3Sopenharmony_ci
6074514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::CheckLoop(GateRef array, GateRef lowerGate, int lower, GateRef upperGate, int upper)
6084514f5e3Sopenharmony_ci{
6094514f5e3Sopenharmony_ci    if (IsArrayLength(upperGate) && FindBoundGate(acc_.GetValueIn(upperGate, 0)) == array) {
6104514f5e3Sopenharmony_ci        if (upper >= 0) {
6114514f5e3Sopenharmony_ci            return false;
6124514f5e3Sopenharmony_ci        }
6134514f5e3Sopenharmony_ci    }
6144514f5e3Sopenharmony_ci    if (IsArrayLength(lowerGate) && FindBoundGate(acc_.GetValueIn(lowerGate, 0)) == array) {
6154514f5e3Sopenharmony_ci        if (lower >= 0) {
6164514f5e3Sopenharmony_ci            return false;
6174514f5e3Sopenharmony_ci        }
6184514f5e3Sopenharmony_ci    }
6194514f5e3Sopenharmony_ci    return true;
6204514f5e3Sopenharmony_ci}
6214514f5e3Sopenharmony_ci
6224514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::LoopInvariant(GateRegion *loopHeader, GateRef gate)
6234514f5e3Sopenharmony_ci{
6244514f5e3Sopenharmony_ci    if (gate == Circuit::NullGate()) {
6254514f5e3Sopenharmony_ci        return true;
6264514f5e3Sopenharmony_ci    }
6274514f5e3Sopenharmony_ci    auto gateRegion = graphLinearizer_.GateToRegion(gate);
6284514f5e3Sopenharmony_ci    GateRegion* g = loopHeader->GetDominator();
6294514f5e3Sopenharmony_ci    while (g != nullptr) {
6304514f5e3Sopenharmony_ci        if (g == gateRegion) {
6314514f5e3Sopenharmony_ci            return true;
6324514f5e3Sopenharmony_ci        }
6334514f5e3Sopenharmony_ci        if (g == g->GetDominator()) { // entry
6344514f5e3Sopenharmony_ci            break ;
6354514f5e3Sopenharmony_ci        }
6364514f5e3Sopenharmony_ci        g = g->GetDominator();
6374514f5e3Sopenharmony_ci    }
6384514f5e3Sopenharmony_ci    return false;
6394514f5e3Sopenharmony_ci}
6404514f5e3Sopenharmony_ci
6414514f5e3Sopenharmony_ciGateRef ArrayBoundsCheckElimination::Predicate(GateRef left, TypedBinOp cond, GateRef right)
6424514f5e3Sopenharmony_ci{
6434514f5e3Sopenharmony_ci    return builder_.InsertRangeCheckPredicate(left, cond, right);
6444514f5e3Sopenharmony_ci}
6454514f5e3Sopenharmony_ci
6464514f5e3Sopenharmony_ciGateRef ArrayBoundsCheckElimination::PredicateCmpWithConst(GateRef left, TypedBinOp cond, int32_t right)
6474514f5e3Sopenharmony_ci{
6484514f5e3Sopenharmony_ci    GateRef constGate = builder_.Int32(right);
6494514f5e3Sopenharmony_ci    return Predicate(left, cond, constGate);
6504514f5e3Sopenharmony_ci}
6514514f5e3Sopenharmony_ci
6524514f5e3Sopenharmony_ciGateRef ArrayBoundsCheckElimination::PredicateAdd(GateRef left, int32_t leftConst, TypedBinOp cond, GateRef right)
6534514f5e3Sopenharmony_ci{
6544514f5e3Sopenharmony_ci    GateRef constGate = builder_.Int32(leftConst);
6554514f5e3Sopenharmony_ci    GateRef binaryOpGate = builder_.InsertTypedBinaryop(left, constGate, TypedBinOp::TYPED_ADD);
6564514f5e3Sopenharmony_ci    return Predicate(binaryOpGate, cond, right);
6574514f5e3Sopenharmony_ci}
6584514f5e3Sopenharmony_ci
6594514f5e3Sopenharmony_ciGateRef ArrayBoundsCheckElimination::PredicateAddCmpWithConst(GateRef left, int32_t leftConst,
6604514f5e3Sopenharmony_ci                                                              TypedBinOp cond, int32_t right)
6614514f5e3Sopenharmony_ci{
6624514f5e3Sopenharmony_ci    GateRef constGate = builder_.Int32(right);
6634514f5e3Sopenharmony_ci    return PredicateAdd(left, leftConst, cond, constGate);
6644514f5e3Sopenharmony_ci}
6654514f5e3Sopenharmony_ci
6664514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::LoopInvariantMotionForIndexCheck(GateRef array, GateRef length,
6674514f5e3Sopenharmony_ci    GateRef lengthMetaData, GateRef lowerGate, int lower, GateRef upperGate, int upper, bool isTypedArray)
6684514f5e3Sopenharmony_ci{
6694514f5e3Sopenharmony_ci    // lower > 0
6704514f5e3Sopenharmony_ci    if (lowerGate != Circuit::NullGate()) {
6714514f5e3Sopenharmony_ci        if (lower == 0) {
6724514f5e3Sopenharmony_ci            // lowerGate >= 0
6734514f5e3Sopenharmony_ci            PredicateCmpWithConst(lowerGate, TypedBinOp::TYPED_GREATEREQ, 0);
6744514f5e3Sopenharmony_ci        } else if (lower > 0) {
6754514f5e3Sopenharmony_ci            // lowerGate + lower >= 0
6764514f5e3Sopenharmony_ci            PredicateAddCmpWithConst(lowerGate, lower, TypedBinOp::TYPED_GREATEREQ, 0);
6774514f5e3Sopenharmony_ci        } else {
6784514f5e3Sopenharmony_ci            // lowerGate + lower < 0
6794514f5e3Sopenharmony_ci            // lower < 0
6804514f5e3Sopenharmony_ci            // lowerGate < -lower
6814514f5e3Sopenharmony_ci            lower++;
6824514f5e3Sopenharmony_ci            lower = -lower;
6834514f5e3Sopenharmony_ci            PredicateCmpWithConst(lowerGate, TypedBinOp::TYPED_GREATER, lower);
6844514f5e3Sopenharmony_ci        }
6854514f5e3Sopenharmony_ci    }
6864514f5e3Sopenharmony_ci
6874514f5e3Sopenharmony_ci    // LOAD LENGTH if necessary
6884514f5e3Sopenharmony_ci    if (length == Circuit::NullGate()) {
6894514f5e3Sopenharmony_ci        length = builder_.InsertLoadArrayLength(array, lengthMetaData, isTypedArray);
6904514f5e3Sopenharmony_ci    }
6914514f5e3Sopenharmony_ci
6924514f5e3Sopenharmony_ci    if (upperGate == Circuit::NullGate()) {
6934514f5e3Sopenharmony_ci        ASSERT(upper >= 0);
6944514f5e3Sopenharmony_ci        PredicateCmpWithConst(length, TypedBinOp::TYPED_GREATER, upper);
6954514f5e3Sopenharmony_ci    } else {
6964514f5e3Sopenharmony_ci        if (upper == 0) {
6974514f5e3Sopenharmony_ci            Predicate(upperGate, TypedBinOp::TYPED_LESS, length);
6984514f5e3Sopenharmony_ci        } else if (upper > 0) {
6994514f5e3Sopenharmony_ci            // upperGate + upper < length
7004514f5e3Sopenharmony_ci            PredicateAdd(upperGate, upper, TypedBinOp::TYPED_LESS, length);
7014514f5e3Sopenharmony_ci        } else {
7024514f5e3Sopenharmony_ci            // upperGate + upper < length
7034514f5e3Sopenharmony_ci            // upper < 0
7044514f5e3Sopenharmony_ci            // upperGate < length + (-upper)
7054514f5e3Sopenharmony_ci            PredicateAdd(length, -upper, TypedBinOp::TYPED_GREATER, upperGate);
7064514f5e3Sopenharmony_ci        }
7074514f5e3Sopenharmony_ci    }
7084514f5e3Sopenharmony_ci}
7094514f5e3Sopenharmony_ci
7104514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::ProcessIndexCheck(GateRegion *loopHeader, GateRef gate)
7114514f5e3Sopenharmony_ci{
7124514f5e3Sopenharmony_ci    auto length = FindBoundGate(acc_.GetValueIn(gate, 0));
7134514f5e3Sopenharmony_ci    auto array = FindBoundGate(acc_.GetValueIn(length, 0));
7144514f5e3Sopenharmony_ci    auto index = FindBoundGate(acc_.GetValueIn(gate, 1));
7154514f5e3Sopenharmony_ci    Bound *indexBound = GetBound(index);
7164514f5e3Sopenharmony_ci    if (!indexBound->HasLower() || !indexBound->HasUpper()) {
7174514f5e3Sopenharmony_ci        return;
7184514f5e3Sopenharmony_ci    }
7194514f5e3Sopenharmony_ci
7204514f5e3Sopenharmony_ci    if (InArrayBound(indexBound, length, array)) {
7214514f5e3Sopenharmony_ci        RemoveIndexCheck(gate);
7224514f5e3Sopenharmony_ci    } else if (loopHeader) {
7234514f5e3Sopenharmony_ci        if (!LoopInvariant(loopHeader, array)
7244514f5e3Sopenharmony_ci            || !LoopInvariant(loopHeader, indexBound->LowerGate())
7254514f5e3Sopenharmony_ci            || !LoopInvariant(loopHeader, indexBound->UpperGate())
7264514f5e3Sopenharmony_ci            || (indexBound->LowerGate() == Circuit::NullGate() && indexBound->Lower() < 0)
7274514f5e3Sopenharmony_ci            || (indexBound->UpperGate() == Circuit::NullGate() && indexBound->Upper() < 0)) {
7284514f5e3Sopenharmony_ci            return;
7294514f5e3Sopenharmony_ci        }
7304514f5e3Sopenharmony_ci
7314514f5e3Sopenharmony_ci        ASSERT(length != Circuit::NullGate());
7324514f5e3Sopenharmony_ci        GateRef lengthMetaData = length;
7334514f5e3Sopenharmony_ci        bool isTypedArray = false;
7344514f5e3Sopenharmony_ci        if (acc_.GetOpCode(length) == OpCode::LOAD_TYPED_ARRAY_LENGTH) {
7354514f5e3Sopenharmony_ci            isTypedArray = true;
7364514f5e3Sopenharmony_ci        }
7374514f5e3Sopenharmony_ci
7384514f5e3Sopenharmony_ci        // Length instrution
7394514f5e3Sopenharmony_ci        if (!LoopInvariant(loopHeader, length)) {
7404514f5e3Sopenharmony_ci            // Generate length instruction yourself
7414514f5e3Sopenharmony_ci            length = Circuit::NullGate();
7424514f5e3Sopenharmony_ci        }
7434514f5e3Sopenharmony_ci
7444514f5e3Sopenharmony_ci        // Insert Before loopHeader State, and if find IF_TRUE and IF_FALSE, insert after the DEPEND_RELAY
7454514f5e3Sopenharmony_ci        // if find MERGE, insert after DEPEND_SELECTOR
7464514f5e3Sopenharmony_ci        GateRef insertAfter = acc_.GetState(loopHeader->GetState(), 0); // after end
7474514f5e3Sopenharmony_ci        GateRef stateIn = insertAfter;
7484514f5e3Sopenharmony_ci        GateRef dependIn = insertAfter;
7494514f5e3Sopenharmony_ci        acc_.GetStateInAndDependIn(insertAfter, stateIn, dependIn);
7504514f5e3Sopenharmony_ci
7514514f5e3Sopenharmony_ci        if (!CheckLoop(array, indexBound->LowerGate(), indexBound->Lower(),
7524514f5e3Sopenharmony_ci                       indexBound->UpperGate(), indexBound->Upper())) {
7534514f5e3Sopenharmony_ci            return;
7544514f5e3Sopenharmony_ci        }
7554514f5e3Sopenharmony_ci
7564514f5e3Sopenharmony_ci        Environment env(stateIn, dependIn, {}, circuit_, &builder_);
7574514f5e3Sopenharmony_ci        LoopInvariantMotionForIndexCheck(array, length, lengthMetaData, indexBound->LowerGate(),
7584514f5e3Sopenharmony_ci            indexBound->Lower(), indexBound->UpperGate(), indexBound->Upper(), isTypedArray);
7594514f5e3Sopenharmony_ci        RemoveIndexCheck(gate);
7604514f5e3Sopenharmony_ci    }
7614514f5e3Sopenharmony_ci}
7624514f5e3Sopenharmony_ci
7634514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::ProcessIf(IntegerStack &pushed, GateRegion *parent, OpCode cond)
7644514f5e3Sopenharmony_ci{
7654514f5e3Sopenharmony_ci    auto& gateLists = parent->GetGates();
7664514f5e3Sopenharmony_ci    for (int i = static_cast<int>(gateLists.size()) - 1; i >= 0; i--) { // Found the last BinaryOp
7674514f5e3Sopenharmony_ci        GateRef gate = gateLists[i];
7684514f5e3Sopenharmony_ci        if (gate == Circuit::NullGate()) continue;
7694514f5e3Sopenharmony_ci        OpCode opGate = acc_.GetOpCode(gate);
7704514f5e3Sopenharmony_ci        if (opGate != OpCode::TYPED_BINARY_OP) {
7714514f5e3Sopenharmony_ci            continue ;
7724514f5e3Sopenharmony_ci        }
7734514f5e3Sopenharmony_ci
7744514f5e3Sopenharmony_ci        TypedBinOp op = acc_.GetTypedBinaryOp(gate);
7754514f5e3Sopenharmony_ci        GateRef x = FindBoundGate(acc_.GetValueIn(gate, 0));
7764514f5e3Sopenharmony_ci        GateRef y = FindBoundGate(acc_.GetValueIn(gate, 1));
7774514f5e3Sopenharmony_ci
7784514f5e3Sopenharmony_ci        switch (op) {
7794514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_LESS:
7804514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_LESSEQ:
7814514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_GREATER:
7824514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_GREATEREQ:
7834514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_EQ:
7844514f5e3Sopenharmony_ci            case TypedBinOp::TYPED_NOTEQ: {
7854514f5e3Sopenharmony_ci                if (cond == OpCode::IF_TRUE) {
7864514f5e3Sopenharmony_ci                    op = acc_.GetRevCompareOpForTypedBinOp(op);
7874514f5e3Sopenharmony_ci                }
7884514f5e3Sopenharmony_ci                AddIfCondition(pushed, x, y, op);
7894514f5e3Sopenharmony_ci                AddIfCondition(pushed, y, x, acc_.GetSwapCompareOpForTypedBinOp(op));
7904514f5e3Sopenharmony_ci                break;
7914514f5e3Sopenharmony_ci            }
7924514f5e3Sopenharmony_ci            default:
7934514f5e3Sopenharmony_ci                break;
7944514f5e3Sopenharmony_ci        }
7954514f5e3Sopenharmony_ci        break;
7964514f5e3Sopenharmony_ci    }
7974514f5e3Sopenharmony_ci}
7984514f5e3Sopenharmony_ci
7994514f5e3Sopenharmony_cibool ArrayBoundsCheckElimination::Contain(GateLists &gateLists, GateRef gate)
8004514f5e3Sopenharmony_ci{
8014514f5e3Sopenharmony_ci    for (size_t i = 0; i < gateLists.size(); i++) {
8024514f5e3Sopenharmony_ci        if (gateLists[i] == gate) {
8034514f5e3Sopenharmony_ci            return true;
8044514f5e3Sopenharmony_ci        }
8054514f5e3Sopenharmony_ci    }
8064514f5e3Sopenharmony_ci    return false;
8074514f5e3Sopenharmony_ci}
8084514f5e3Sopenharmony_ci
8094514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::AddAccessIndexedInfo(GateLists &indices, GateRef gate, int idx, GateRef indexCheck)
8104514f5e3Sopenharmony_ci{
8114514f5e3Sopenharmony_ci    IndexCheckInfo *indexCheckInfo = indexCheckInfo_[acc_.GetId(gate)];
8124514f5e3Sopenharmony_ci    if (indexCheckInfo == nullptr) {
8134514f5e3Sopenharmony_ci        indexCheckInfo = chunk_->New<IndexCheckInfo>(chunk_);
8144514f5e3Sopenharmony_ci        indexCheckInfo_[acc_.GetId(gate)] = indexCheckInfo;
8154514f5e3Sopenharmony_ci        indices.push_back(gate);
8164514f5e3Sopenharmony_ci        indexCheckInfo->min_ = idx;
8174514f5e3Sopenharmony_ci        indexCheckInfo->max_ = idx;
8184514f5e3Sopenharmony_ci    } else if (idx >= indexCheckInfo->min_ && idx <= indexCheckInfo->max_) {
8194514f5e3Sopenharmony_ci        RemoveIndexCheck(indexCheck);
8204514f5e3Sopenharmony_ci        return;
8214514f5e3Sopenharmony_ci    }
8224514f5e3Sopenharmony_ci    indexCheckInfo->min_ = std::min(indexCheckInfo->min_, idx);
8234514f5e3Sopenharmony_ci    indexCheckInfo->max_ = std::max(indexCheckInfo->max_, idx);
8244514f5e3Sopenharmony_ci    indexCheckInfo->list_.push_back(indexCheck);
8254514f5e3Sopenharmony_ci}
8264514f5e3Sopenharmony_ci
8274514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::InBlockMotion(GateLists &indexChecked, GateLists &arrays)
8284514f5e3Sopenharmony_ci{
8294514f5e3Sopenharmony_ci    GateLists indices(chunk_);
8304514f5e3Sopenharmony_ci    for (size_t i = 0; i < arrays.size(); i++) {
8314514f5e3Sopenharmony_ci        int maxConstant = -1;
8324514f5e3Sopenharmony_ci        GateLists listConstant(chunk_);
8334514f5e3Sopenharmony_ci        GateRef arrayGate = arrays[i];
8344514f5e3Sopenharmony_ci        for (size_t j = 0; j < indexChecked.size(); j++) {
8354514f5e3Sopenharmony_ci            GateRef indexCheck = indexChecked[j];
8364514f5e3Sopenharmony_ci            // INDEX_CHECK may be dead
8374514f5e3Sopenharmony_ci            if (acc_.GetOpCode(indexCheck) != OpCode::INDEX_CHECK) {
8384514f5e3Sopenharmony_ci                continue;
8394514f5e3Sopenharmony_ci            }
8404514f5e3Sopenharmony_ci            GateRef length = FindBoundGate(acc_.GetValueIn(indexCheck, 0));
8414514f5e3Sopenharmony_ci            GateRef index = FindBoundGate(acc_.GetValueIn(indexCheck, 1));
8424514f5e3Sopenharmony_ci            GateRef array = FindBoundGate(acc_.GetValueIn(length, 0));
8434514f5e3Sopenharmony_ci            if (array != arrayGate) {
8444514f5e3Sopenharmony_ci                continue;
8454514f5e3Sopenharmony_ci            }
8464514f5e3Sopenharmony_ci            if (acc_.IsConstant(index)) {
8474514f5e3Sopenharmony_ci                int constValue = static_cast<int>(acc_.GetConstantValue(index));
8484514f5e3Sopenharmony_ci                if (constValue >= 0 && constValue <= maxConstant) {
8494514f5e3Sopenharmony_ci                    RemoveIndexCheck(indexCheck);
8504514f5e3Sopenharmony_ci                } else if (constValue >= 0 && constValue > maxConstant) {
8514514f5e3Sopenharmony_ci                    maxConstant = constValue;
8524514f5e3Sopenharmony_ci                    listConstant.push_back(indexCheck);
8534514f5e3Sopenharmony_ci                }
8544514f5e3Sopenharmony_ci            } else {
8554514f5e3Sopenharmony_ci                int lastInteger;
8564514f5e3Sopenharmony_ci                GateRef lastGate;
8574514f5e3Sopenharmony_ci                GetInstrAndConstValueFromOp(index, lastGate, lastInteger);
8584514f5e3Sopenharmony_ci                if (lastInteger >= 0 && lastGate == Circuit::NullGate()) { // IsConstant
8594514f5e3Sopenharmony_ci                    if (lastInteger <= maxConstant) {
8604514f5e3Sopenharmony_ci                        RemoveIndexCheck(indexCheck);
8614514f5e3Sopenharmony_ci                    } else {
8624514f5e3Sopenharmony_ci                        maxConstant = lastInteger;
8634514f5e3Sopenharmony_ci                        listConstant.push_back(indexCheck);
8644514f5e3Sopenharmony_ci                    }
8654514f5e3Sopenharmony_ci                } else if (lastGate != Circuit::NullGate()) {
8664514f5e3Sopenharmony_ci                    AddAccessIndexedInfo(indices, lastGate, lastInteger, indexCheck);
8674514f5e3Sopenharmony_ci                } // when lastInteger < 0, dont remove IndexCheck
8684514f5e3Sopenharmony_ci            }
8694514f5e3Sopenharmony_ci        }
8704514f5e3Sopenharmony_ci
8714514f5e3Sopenharmony_ci        // Iterate over all different indices
8724514f5e3Sopenharmony_ci        for (size_t j = 0; j < indices.size(); j++) {
8734514f5e3Sopenharmony_ci            GateRef index = indices[j];
8744514f5e3Sopenharmony_ci
8754514f5e3Sopenharmony_ci            IndexCheckInfo *info = indexCheckInfo_[acc_.GetId(index)];
8764514f5e3Sopenharmony_ci            ASSERT(info != nullptr);
8774514f5e3Sopenharmony_ci
8784514f5e3Sopenharmony_ci            // maybe index < 0, max > 0
8794514f5e3Sopenharmony_ci            // max + index in [0, a.length)
8804514f5e3Sopenharmony_ci            // min + index overflow !!!, min + index > 0
8814514f5e3Sopenharmony_ci            // so, min + index >= INT_MIN, min >= INT_MIN - index
8824514f5e3Sopenharmony_ci            // max in [-index, a.length - index)
8834514f5e3Sopenharmony_ci            // min >= INT_MIN + max
8844514f5e3Sopenharmony_ci            bool rangeCond = (info->max_ < 0 || info->max_ + INT_MIN <= info->min_);
8854514f5e3Sopenharmony_ci            if (info->list_.size() > 2 && rangeCond) { // 2: size
8864514f5e3Sopenharmony_ci                GateRef insertAfter = info->list_.front();
8874514f5e3Sopenharmony_ci                GateRef length = FindBoundGate(acc_.GetValueIn(insertAfter, 0));
8884514f5e3Sopenharmony_ci                ASSERT(length != Circuit::NullGate());
8894514f5e3Sopenharmony_ci
8904514f5e3Sopenharmony_ci                Environment env(insertAfter, circuit_, &builder_);
8914514f5e3Sopenharmony_ci
8924514f5e3Sopenharmony_ci                // Calculate lower bound
8934514f5e3Sopenharmony_ci                GateRef lowerCompare = index;
8944514f5e3Sopenharmony_ci                if (info->min_ > 0) {
8954514f5e3Sopenharmony_ci                    GateRef minGate = builder_.Int32(info->min_);
8964514f5e3Sopenharmony_ci                    lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate, TypedBinOp::TYPED_ADD);
8974514f5e3Sopenharmony_ci                } else if (info->min_ < 0) {
8984514f5e3Sopenharmony_ci                    GateRef minGate = builder_.Int32(-info->min_);
8994514f5e3Sopenharmony_ci                    lowerCompare = builder_.InsertTypedBinaryop(lowerCompare, minGate, TypedBinOp::TYPED_SUB);
9004514f5e3Sopenharmony_ci                }
9014514f5e3Sopenharmony_ci
9024514f5e3Sopenharmony_ci                PredicateCmpWithConst(lowerCompare, TypedBinOp::TYPED_GREATEREQ, 0);
9034514f5e3Sopenharmony_ci
9044514f5e3Sopenharmony_ci                // Calculate upper bound
9054514f5e3Sopenharmony_ci                GateRef upperCompare = index;
9064514f5e3Sopenharmony_ci                if (info->max_ != 0) {
9074514f5e3Sopenharmony_ci                    if (info->max_ > 0) {
9084514f5e3Sopenharmony_ci                        GateRef maxGate = builder_.Int32(info->max_);
9094514f5e3Sopenharmony_ci                        upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate, TypedBinOp::TYPED_ADD);
9104514f5e3Sopenharmony_ci                    } else if (info->max_ < 0) {
9114514f5e3Sopenharmony_ci                        GateRef maxGate = builder_.Int32(-info->max_);
9124514f5e3Sopenharmony_ci                        upperCompare = builder_.InsertTypedBinaryop(upperCompare, maxGate, TypedBinOp::TYPED_SUB);
9134514f5e3Sopenharmony_ci                    }
9144514f5e3Sopenharmony_ci                }
9154514f5e3Sopenharmony_ci
9164514f5e3Sopenharmony_ci                Predicate(upperCompare, TypedBinOp::TYPED_LESS, length);
9174514f5e3Sopenharmony_ci                for (auto& indexCheck: (info->list_)) {
9184514f5e3Sopenharmony_ci                    RemoveIndexCheck(indexCheck);
9194514f5e3Sopenharmony_ci                }
9204514f5e3Sopenharmony_ci            }
9214514f5e3Sopenharmony_ci        }
9224514f5e3Sopenharmony_ci
9234514f5e3Sopenharmony_ci        // index only constant
9244514f5e3Sopenharmony_ci        if (listConstant.size() > 1) {
9254514f5e3Sopenharmony_ci            GateRef firIndexCheckGate = listConstant.front();
9264514f5e3Sopenharmony_ci            Environment env(firIndexCheckGate, circuit_, &builder_);
9274514f5e3Sopenharmony_ci            GateRef length = FindBoundGate(acc_.GetValueIn(firIndexCheckGate, 0));
9284514f5e3Sopenharmony_ci            ASSERT(length != Circuit::NullGate());
9294514f5e3Sopenharmony_ci            ASSERT(maxConstant >= 0);
9304514f5e3Sopenharmony_ci            PredicateCmpWithConst(length, TypedBinOp::TYPED_GREATER, maxConstant); // length > index
9314514f5e3Sopenharmony_ci            for (size_t j = 0; j < listConstant.size(); j++) {
9324514f5e3Sopenharmony_ci                GateRef indexCheck = listConstant[j];
9334514f5e3Sopenharmony_ci                RemoveIndexCheck(indexCheck);
9344514f5e3Sopenharmony_ci            }
9354514f5e3Sopenharmony_ci        }
9364514f5e3Sopenharmony_ci
9374514f5e3Sopenharmony_ci        for (size_t j = 0; j < indices.size(); j++) {
9384514f5e3Sopenharmony_ci            indexCheckInfo_[acc_.GetId(indices[j])] = nullptr;
9394514f5e3Sopenharmony_ci        }
9404514f5e3Sopenharmony_ci        indices.clear();
9414514f5e3Sopenharmony_ci    }
9424514f5e3Sopenharmony_ci}
9434514f5e3Sopenharmony_ci
9444514f5e3Sopenharmony_civoid ArrayBoundsCheckElimination::CalcBounds(GateRegion *block, GateRegion *loopHeader)
9454514f5e3Sopenharmony_ci{
9464514f5e3Sopenharmony_ci    // Pushed stack for condition
9474514f5e3Sopenharmony_ci    IntegerStack pushed(chunk_);
9484514f5e3Sopenharmony_ci
9494514f5e3Sopenharmony_ci    // Process If
9504514f5e3Sopenharmony_ci    GateRegion *parent = block->GetDominator();
9514514f5e3Sopenharmony_ci    if (parent != nullptr) {
9524514f5e3Sopenharmony_ci        auto gate = block->GetGates().front();
9534514f5e3Sopenharmony_ci        auto op = acc_.GetOpCode(gate);
9544514f5e3Sopenharmony_ci        if (op == OpCode::IF_TRUE || op == OpCode::IF_FALSE) { // Recognize If (including the condition in forloop)
9554514f5e3Sopenharmony_ci            ProcessIf(pushed, parent, op);
9564514f5e3Sopenharmony_ci        }
9574514f5e3Sopenharmony_ci    }
9584514f5e3Sopenharmony_ci
9594514f5e3Sopenharmony_ci    GateLists indexChecked(chunk_);
9604514f5e3Sopenharmony_ci    GateLists arrays(chunk_);
9614514f5e3Sopenharmony_ci
9624514f5e3Sopenharmony_ci    auto& gateList_ = block->GetGates();
9634514f5e3Sopenharmony_ci    for (size_t i = 0; i < gateList_.size(); i++) { // Visit GateUnion
9644514f5e3Sopenharmony_ci        GateRef gate = gateList_[i];
9654514f5e3Sopenharmony_ci        auto op = acc_.GetOpCode(gate);
9664514f5e3Sopenharmony_ci        if (op == OpCode::INDEX_CHECK) {
9674514f5e3Sopenharmony_ci            auto length = FindBoundGate(acc_.GetValueIn(gate, 0));
9684514f5e3Sopenharmony_ci            auto index = FindBoundGate(acc_.GetValueIn(gate, 1));
9694514f5e3Sopenharmony_ci            auto array = FindBoundGate(acc_.GetValueIn(length, 0));
9704514f5e3Sopenharmony_ci
9714514f5e3Sopenharmony_ci            ProcessIndexCheck(loopHeader, gate);
9724514f5e3Sopenharmony_ci            indexChecked.push_back(gate);
9734514f5e3Sopenharmony_ci
9744514f5e3Sopenharmony_ci            if (!Contain(arrays, array)) {
9754514f5e3Sopenharmony_ci                arrays.push_back(array);
9764514f5e3Sopenharmony_ci            }
9774514f5e3Sopenharmony_ci
9784514f5e3Sopenharmony_ci            // Give IndexCheck a bound [0, Length - 1]
9794514f5e3Sopenharmony_ci            Bound *b = GetBound(index);
9804514f5e3Sopenharmony_ci            if (b->LowerGate() == Circuit::NullGate()) { // LowerBound is the Constant !!!
9814514f5e3Sopenharmony_ci                UpdateBound(pushed, index, TypedBinOp::TYPED_GREATEREQ, Circuit::NullGate(), 0);
9824514f5e3Sopenharmony_ci            }
9834514f5e3Sopenharmony_ci            if (!b->HasUpper() && length != Circuit::NullGate()) { // default dont know the Length
9844514f5e3Sopenharmony_ci                UpdateBound(pushed, index, TypedBinOp::TYPED_LESS, length, 0);
9854514f5e3Sopenharmony_ci            }
9864514f5e3Sopenharmony_ci        }
9874514f5e3Sopenharmony_ci    }
9884514f5e3Sopenharmony_ci
9894514f5e3Sopenharmony_ci    InBlockMotion(indexChecked, arrays);
9904514f5e3Sopenharmony_ci
9914514f5e3Sopenharmony_ci    auto& dominatedRegions_ = block->GetDominatedRegions();
9924514f5e3Sopenharmony_ci    for (size_t i = 0; i < dominatedRegions_.size(); i++) {
9934514f5e3Sopenharmony_ci        GateRegion *nex = dominatedRegions_[i];
9944514f5e3Sopenharmony_ci        if (block->IsLoopHead() && (block->GetLoopIndex() == nex->GetLoopIndex()
9954514f5e3Sopenharmony_ci            || nex->GetLoopDepth() > block->GetLoopDepth())) {
9964514f5e3Sopenharmony_ci            CalcBounds(nex, block);
9974514f5e3Sopenharmony_ci        } else {
9984514f5e3Sopenharmony_ci            CalcBounds(nex, loopHeader);
9994514f5e3Sopenharmony_ci        }
10004514f5e3Sopenharmony_ci    }
10014514f5e3Sopenharmony_ci
10024514f5e3Sopenharmony_ci    for (size_t i = 0; i < pushed.size(); i++) {
10034514f5e3Sopenharmony_ci        bounds_[pushed[i]]->pop_back();
10044514f5e3Sopenharmony_ci    }
10054514f5e3Sopenharmony_ci}
10064514f5e3Sopenharmony_ci}
1007