1 /* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "check_resolver.h" 17 #include "compiler/optimizer/ir/basicblock.h" 18 #include "compiler/optimizer/ir/inst.h" 19 20 namespace ark::bytecodeopt { 21 ReplaceCheck(compiler::Inst * inst)22static void ReplaceCheck(compiler::Inst *inst) 23 { 24 auto op = inst->GetOpcode(); 25 size_t i = (op == compiler::Opcode::BoundsCheck || op == compiler::Opcode::RefTypeCheck) ? 1U : 0U; 26 auto input = inst->GetInput(i).GetInst(); 27 for (auto &user : inst->GetUsers()) { 28 user.GetInst()->SetFlag(compiler::inst_flags::CAN_THROW); 29 } 30 inst->ReplaceUsers(input); 31 inst->ClearFlag(compiler::inst_flags::NO_DCE); // DCE will remove the check inst 32 } 33 MarkLenArray(compiler::Inst * inst)34static void MarkLenArray(compiler::Inst *inst) 35 { 36 bool noDce = !inst->HasUsers(); 37 for (const auto &usr : inst->GetUsers()) { 38 if (!CheckResolver::IsCheck(usr.GetInst())) { 39 noDce = true; 40 break; 41 } 42 } 43 if (noDce) { 44 inst->SetFlag(compiler::inst_flags::NO_DCE); 45 } 46 inst->SetFlag(compiler::inst_flags::NO_HOIST); 47 } 48 RunImpl()49bool CheckResolver::RunImpl() 50 { 51 bool applied = false; 52 for (auto bb : GetGraph()->GetBlocksRPO()) { 53 for (auto inst : bb->Insts()) { 54 // replace check 55 if (IsCheck(inst)) { 56 ReplaceCheck(inst); 57 applied = true; 58 } 59 60 // set NO_DCE for Div, Mod, LoadArray, LoadStatic and LoadObject 61 if (NeedSetNoDCE(inst)) { 62 inst->SetFlag(compiler::inst_flags::NO_DCE); 63 applied = true; 64 } 65 66 // mark LenArray whose users are not all check as no_dce 67 // mark LenArray as no_hoist in all cases 68 if (inst->GetOpcode() == compiler::Opcode::LenArray) { 69 MarkLenArray(inst); 70 } 71 } 72 } 73 return applied; 74 } 75 NeedSetNoDCE(const compiler::Inst * inst)76bool CheckResolver::NeedSetNoDCE(const compiler::Inst *inst) 77 { 78 switch (inst->GetOpcode()) { 79 case compiler::Opcode::Div: 80 case compiler::Opcode::Mod: 81 case compiler::Opcode::LoadArray: 82 case compiler::Opcode::LoadStatic: 83 case compiler::Opcode::LoadObject: 84 return true; 85 default: 86 return false; 87 } 88 } 89 IsCheck(const compiler::Inst * inst)90bool CheckResolver::IsCheck(const compiler::Inst *inst) 91 { 92 switch (inst->GetOpcode()) { 93 case compiler::Opcode::BoundsCheck: 94 case compiler::Opcode::NullCheck: 95 case compiler::Opcode::NegativeCheck: 96 case compiler::Opcode::ZeroCheck: 97 case compiler::Opcode::RefTypeCheck: 98 case compiler::Opcode::BoundsCheckI: 99 return true; 100 default: 101 return false; 102 } 103 } 104 105 } // namespace ark::bytecodeopt 106