• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 <iomanip>
17 #include "optimizer/pass_manager.h"
18 #include "compiler_options.h"
19 #include "trace/trace.h"
20 #include "optimizer_run.h"
21 
22 #include "optimizer/code_generator/codegen.h"
23 #include "optimizer/code_generator/codegen_native.h"
24 #include "optimizer/code_generator/method_properties.h"
25 #include "optimizer/ir/graph.h"
26 #include "optimizer/ir/graph_checker.h"
27 #include "optimizer/analysis/alias_analysis.h"
28 #include "optimizer/analysis/bounds_analysis.h"
29 #include "optimizer/analysis/dominators_tree.h"
30 #include "optimizer/analysis/linear_order.h"
31 #include "optimizer/analysis/loop_analyzer.h"
32 #include "optimizer/analysis/rpo.h"
33 #include "optimizer/optimizations/balance_expressions.h"
34 #include "optimizer/optimizations/code_sink.h"
35 #include "optimizer/optimizations/deoptimize_elimination.h"
36 #include "optimizer/optimizations/cleanup.h"
37 #include "optimizer/optimizations/if_conversion.h"
38 #include "optimizer/optimizations/loop_peeling.h"
39 #include "optimizer/optimizations/loop_unroll.h"
40 #include "optimizer/optimizations/lowering.h"
41 #include "optimizer/optimizations/memory_barriers.h"
42 #include "optimizer/optimizations/memory_coalescing.h"
43 #include "optimizer/optimizations/redundant_loop_elimination.h"
44 #include "optimizer/optimizations/regalloc/reg_alloc.h"
45 #include "optimizer/optimizations/scheduler.h"
46 #include "optimizer/optimizations/try_catch_resolving.h"
47 #include "optimizer/optimizations/types_resolving.h"
48 #include "optimizer/optimizations/vn.h"
49 #include "optimizer/optimizations/move_constants.h"
50 #include "optimizer/optimizations/adjust_arefs.h"
51 
52 namespace panda::compiler {
53 
RunCodegenPass(Graph * graph)54 static inline bool RunCodegenPass(Graph *graph)
55 {
56     if (graph->GetMethodProperties().GetRequireFrameSetup()) {
57         return graph->RunPass<Codegen>();
58     }
59     return graph->RunPass<CodegenNative>();
60 }
61 
RunOptimizations(Graph * graph)62 bool RunOptimizations(Graph *graph)
63 {
64     auto finalizer = [graph](void * /* unused */) { graph->GetPassManager()->Finalize(); };
65     std::unique_ptr<void, decltype(finalizer)> pp(&finalizer, finalizer);
66 
67     if (options.WasSetCompilerRegallocRegMask()) {
68         COMPILER_LOG(DEBUG, REGALLOC) << "Regalloc mask force set to " << std::hex
69                                       << options.GetCompilerRegallocRegMask() << "\n";
70         graph->SetArchUsedRegs(options.GetCompilerRegallocRegMask());
71     }
72 
73     if (!options.IsCompilerNonOptimizing()) {
74         // Run optimizations
75 
76         // The problem with inlining in OSR mode can be found in `bitops-nsieve-bits` benchmark and it is in the
77         // following: we inline the method that has user X within a loop, then peepholes optimize datflow and def of
78         // the X become another instruction within inlined method, but SaveStateOsr didn't take it into account, thus,
79         // we don't restore value of this new definition.
80         // TODO(msherstennikov): find way to inline in OSR mode
81         if (!graph->IsOsrMode()) {
82             graph->RunPass<Inlining>();
83         }
84         graph->RunPass<TryCatchResolving>();
85         graph->RunPass<Peepholes>();
86         graph->RunPass<BranchElimination>();
87         graph->RunPass<ValNum>();
88         graph->RunPass<Cleanup>();
89         if (graph->IsAotMode()) {
90             graph->RunPass<Cse>();
91         }
92         if (graph->IsDynamicMethod()) {
93             graph->RunPass<TypesResolving>();
94         }
95         graph->RunPass<Licm>(options.GetCompilerLicmHoistLimit());
96         graph->RunPass<RedundantLoopElimination>();
97         graph->RunPass<LoopPeeling>();
98         graph->RunPass<Lse>();
99         graph->RunPass<ValNum>();
100         if (graph->RunPass<Peepholes>() && graph->RunPass<BranchElimination>()) {
101             graph->RunPass<Peepholes>();
102         }
103         graph->RunPass<Cleanup>();
104         if (graph->IsAotMode()) {
105             graph->RunPass<Cse>();
106         }
107         graph->RunPass<LoopUnroll>(options.GetCompilerLoopUnrollInstLimit(), options.GetCompilerLoopUnrollFactor());
108         graph->RunPass<BalanceExpressions>();
109         if (graph->RunPass<Peepholes>()) {
110             graph->RunPass<BranchElimination>();
111         }
112         graph->RunPass<ValNum>();
113         if (graph->IsAotMode()) {
114             graph->RunPass<Cse>();
115         }
116         if (graph->RunPass<DeoptimizeElimination>()) {
117             graph->RunPass<Peepholes>();
118         }
119 
120 #ifndef NDEBUG
121         graph->SetLowLevelInstructionsEnabled();
122 #endif  // NDEBUG
123         graph->RunPass<Cleanup>();
124         graph->RunPass<Lowering>();
125         graph->RunPass<CodeSink>();
126         graph->RunPass<MemoryCoalescing>(options.IsCompilerMemoryCoalescingAligned());
127         graph->RunPass<IfConversion>(options.GetCompilerIfConversionLimit());
128         graph->RunPass<Scheduler>();
129         // Perform MoveConstants after Scheduler because Scheduler can rearrange constants
130         // and cause spillfill in reg alloc
131         graph->RunPass<MoveConstants>();
132         graph->RunPass<AdjustRefs>();
133         graph->RunPass<OptimizeMemoryBarriers>();
134     } else {
135         // TryCatchResolving is needed in the non-optimizing mode since it removes unreachable for compiler
136         // catch-handlers; After supporting catch-handlers' compilation, this pass can be run in the optimizing mode
137         // only.
138         graph->RunPass<TryCatchResolving>();
139     }
140 
141     bool fatal_on_err = !options.IsCompilerAllowBackendFailures();
142     // Do not try to encode too large graph
143     auto inst_size = graph->GetCurrentInstructionId();
144     auto insts_per_byte = graph->GetEncoder()->MaxArchInstPerEncoded();
145     auto max_bits_in_inst = GetInstructionSizeBits(graph->GetArch());
146     if ((inst_size * insts_per_byte * max_bits_in_inst) > options.GetCompilerMaxGenCodeSize()) {
147         if (fatal_on_err) {
148             LOG(FATAL, COMPILER) << "RunOptimizations failed: code predicted size too big";
149         }
150         return false;
151     }
152     graph->RunPass<Cleanup>();
153     if (!RegAlloc(graph)) {
154         if (fatal_on_err) {
155             LOG(FATAL, COMPILER) << "RunOptimizations failed: register allocation error";
156         }
157         return false;
158     }
159 
160     if (!RunCodegenPass(graph)) {
161         if (fatal_on_err) {
162             LOG(FATAL, COMPILER) << "RunOptimizations failed: code generation error";
163         }
164         return false;
165     }
166 
167     return true;
168 }
169 
170 }  // namespace panda::compiler
171