• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)22 static 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)34 static 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()49 bool 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)76 bool 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)90 bool 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