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