• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "compiler_logger.h"
17 #include "savestate_optimization.h"
18 #include "optimizer/analysis/alias_analysis.h"
19 #include "optimizer/analysis/dominators_tree.h"
20 #include "optimizer/ir/analysis.h"
21 
22 namespace ark::compiler {
23 
RunImpl()24 bool SaveStateOptimization::RunImpl()
25 {
26     if (g_options.IsCompilerEnforceSafepointPlacement()) {
27         return false;
28     }
29     uint64_t instsNumber = VisitGraphAndCount();
30     if (!HaveCalls() && instsNumber <= g_options.GetCompilerSafepointEliminationLimit()) {
31         RemoveSafePoints();
32     }
33     return IsApplied();
34 }
35 
RemoveSafePoints()36 void SaveStateOptimization::RemoveSafePoints()
37 {
38     auto block = GetGraph()->GetStartBlock();
39     ASSERT(block != nullptr && block->IsStartBlock());
40     for (auto sp : block->Insts()) {
41         if (sp->GetOpcode() == Opcode::SafePoint) {
42             sp->ClearFlag(inst_flags::NO_DCE);
43             SetApplied();
44             COMPILER_LOG(DEBUG, SAVESTATE_OPT) << "SafePoint " << sp->GetId() << " is deleted from start block";
45             block->GetGraph()->GetEventWriter().EventSaveStateOptimization(GetOpcodeString(sp->GetOpcode()),
46                                                                            sp->GetId(), sp->GetPc());
47         }
48     }
49 }
50 
RequireRegMap(Inst * inst)51 bool SaveStateOptimization::RequireRegMap(Inst *inst)
52 {
53     for (auto &user : inst->GetUsers()) {
54         auto userInst = user.GetInst();
55         if (userInst->RequireRegMap()) {
56             return true;
57         }
58         auto opcode = userInst->GetOpcode();
59         if (opcode == Opcode::CallStatic || opcode == Opcode::CallVirtual || opcode == Opcode::CallResolvedVirtual ||
60             opcode == Opcode::CallDynamic || opcode == Opcode::CallResolvedStatic) {
61             // Inlined method can contain Deoptimize or DeoptimizeIf
62             if (static_cast<CallInst *>(userInst)->IsInlined()) {
63                 return true;
64             }
65         }
66     }
67     return false;
68 }
69 
VisitDefault(Inst * inst)70 void SaveStateOptimization::VisitDefault(Inst *inst)
71 {
72     if (inst->GetType() != DataType::REFERENCE) {
73         return;
74     }
75     for (auto &user : inst->GetUsers()) {
76         auto userInst = user.GetInst();
77         if (!userInst->IsSaveState()) {
78             return;
79         }
80         if (userInst->GetOpcode() == Opcode::SafePoint) {
81             if (g_options.IsCompilerSafePointsRequireRegMap()) {
82                 return;
83             }
84             continue;
85         }
86         if (RequireRegMap(userInst)) {
87             return;
88         }
89     }
90 
91     inst->RemoveUsers<true>();
92 
93     SetApplied();
94     COMPILER_LOG(DEBUG, SAVESTATE_OPT) << "All users of the instructions " << inst->GetId() << " are SaveStates";
95     inst->GetBasicBlock()->GetGraph()->GetEventWriter().EventSaveStateOptimization(GetOpcodeString(inst->GetOpcode()),
96                                                                                    inst->GetId(), inst->GetPc());
97 }
98 
VisitSaveState(GraphVisitor * v,Inst * inst)99 void SaveStateOptimization::VisitSaveState(GraphVisitor *v, Inst *inst)
100 {
101     auto visitor = static_cast<SaveStateOptimization *>(v);
102     if (visitor->TryToRemoveRedundantSaveState(inst)) {
103         return;
104     }
105 
106     if (visitor->RequireRegMap(inst)) {
107         return;
108     }
109 
110     auto ss = inst->CastToSaveState();
111     if (ss->RemoveNumericInputs()) {
112         visitor->SetApplied();
113         COMPILER_LOG(DEBUG, SAVESTATE_OPT) << "SaveState " << ss->GetId() << " numeric inputs were deleted";
114         ss->GetBasicBlock()->GetGraph()->GetEventWriter().EventSaveStateOptimization(GetOpcodeString(ss->GetOpcode()),
115                                                                                      ss->GetId(), ss->GetPc());
116         ss->SetInputsWereDeleted();
117     }
118 }
119 
VisitSaveStateDeoptimize(GraphVisitor * v,Inst * inst)120 void SaveStateOptimization::VisitSaveStateDeoptimize(GraphVisitor *v, Inst *inst)
121 {
122     static_cast<SaveStateOptimization *>(v)->TryToRemoveRedundantSaveState(inst);
123 }
124 
TryToRemoveRedundantSaveState(Inst * inst)125 bool SaveStateOptimization::TryToRemoveRedundantSaveState(Inst *inst)
126 {
127     if (!inst->HasUsers()) {
128         auto block = inst->GetBasicBlock();
129         block->ReplaceInst(inst, block->GetGraph()->CreateInstNOP());
130         inst->RemoveInputs();
131         SetApplied();
132         COMPILER_LOG(DEBUG, SAVESTATE_OPT) << "SaveState " << inst->GetId() << " without users is deleted";
133         block->GetGraph()->GetEventWriter().EventSaveStateOptimization(GetOpcodeString(inst->GetOpcode()),
134                                                                        inst->GetId(), inst->GetPc());
135         return true;
136     }
137     return false;
138 }
139 }  // namespace ark::compiler
140