• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef ECMASCRIPT_COMPILER_PASS_H
17 #define ECMASCRIPT_COMPILER_PASS_H
18 
19 #include "ecmascript/compiler/array_bounds_check_elimination.h"
20 #include "ecmascript/compiler/async_function_lowering.h"
21 #include "ecmascript/compiler/bytecode_circuit_builder.h"
22 #include "ecmascript/compiler/combined_pass_visitor.h"
23 #include "ecmascript/compiler/common_stubs.h"
24 #include "ecmascript/compiler/compiler_log.h"
25 #include "ecmascript/compiler/dead_code_elimination.h"
26 #include "ecmascript/compiler/constant_folding.h"
27 #include "ecmascript/compiler/early_elimination.h"
28 #include "ecmascript/compiler/graph_editor.h"
29 #include "ecmascript/compiler/graph_linearizer.h"
30 #include "ecmascript/compiler/later_elimination.h"
31 #include "ecmascript/compiler/mcr_lowering.h"
32 #include "ecmascript/compiler/lexical_env_specialization_pass.h"
33 #include "ecmascript/compiler/llvm_codegen.h"
34 #include "ecmascript/compiler/loop_analysis.h"
35 #include "ecmascript/compiler/loop_peeling.h"
36 #include "ecmascript/compiler/native_inline_lowering.h"
37 #include "ecmascript/compiler/ntype_bytecode_lowering.h"
38 #include "ecmascript/compiler/ntype_hcr_lowering.h"
39 #include "ecmascript/compiler/number_speculative_runner.h"
40 #include "ecmascript/compiler/scheduler.h"
41 #include "ecmascript/compiler/string_builder_optimizer.h"
42 #include "ecmascript/compiler/slowpath_lowering.h"
43 #include "ecmascript/compiler/state_split_linearizer.h"
44 #include "ecmascript/compiler/ts_class_analysis.h"
45 #include "ecmascript/compiler/ts_inline_lowering.h"
46 #include "ecmascript/compiler/typed_bytecode_lowering.h"
47 #include "ecmascript/compiler/ts_hcr_opt_pass.h"
48 #include "ecmascript/compiler/type_inference/global_type_infer.h"
49 #include "ecmascript/compiler/type_inference/initialization_analysis.h"
50 #include "ecmascript/compiler/type_inference/pgo_type_infer.h"
51 #include "ecmascript/compiler/typed_hcr_lowering.h"
52 #include "ecmascript/compiler/value_numbering.h"
53 #include "ecmascript/compiler/instruction_combine.h"
54 #include "ecmascript/compiler/verifier.h"
55 #include "ecmascript/js_runtime_options.h"
56 
57 #ifdef COMPILE_MAPLE
58 #include "ecmascript/compiler/codegen/maple/litecg_codegen.h"
59 #include "litecg.h"
60 #include "lmir_builder.h"
61 #endif
62 
63 namespace panda::ecmascript::kungfu {
64 class PassContext;
65 
66 class PassData {
67 public:
68     PassData(BytecodeCircuitBuilder *builder, Circuit *circuit, PassContext *ctx, CompilerLog *log,
69              std::string methodName, MethodInfo *methodInfo = nullptr, bool hasTypes = false,
70              const CString &recordName = "", MethodLiteral *methodLiteral = nullptr,
71              uint32_t methodOffset = 0, NativeAreaAllocator *allocator = nullptr,
72              PGOProfilerDecoder *decoder = nullptr, PassOptions *passOptions = nullptr)
builder_(builder)73         : builder_(builder), circuit_(circuit), ctx_(ctx), log_(log), methodName_(methodName),
74           methodInfo_(methodInfo), hasTypes_(hasTypes), recordName_(recordName), methodLiteral_(methodLiteral),
75           methodOffset_(methodOffset), allocator_(allocator), decoder_(decoder), passOptions_(passOptions)
76     {
77     }
78 
79     virtual ~PassData() = default;
80 
GetConstScheduleResult()81     const ControlFlowGraph &GetConstScheduleResult() const
82     {
83         return cfg_;
84     }
85 
GetCfg()86     ControlFlowGraph &GetCfg()
87     {
88         return cfg_;
89     }
90 
GetCircuit()91     virtual Circuit* GetCircuit() const
92     {
93         return circuit_;
94     }
95 
GetBuilder()96     BytecodeCircuitBuilder* GetBuilder() const
97     {
98         return builder_;
99     }
100 
GetPassContext()101     PassContext* GetPassContext() const
102     {
103         return ctx_;
104     }
105 
GetCompilerConfig()106     CompilationConfig* GetCompilerConfig() const
107     {
108         return ctx_->GetCompilerConfig();
109     }
110 
GetTSManager()111     TSManager* GetTSManager() const
112     {
113         return ctx_->GetTSManager();
114     }
115 
GetPTManager()116     PGOTypeManager* GetPTManager() const
117     {
118         return ctx_->GetPTManager();
119     }
120 
GetJSPandaFile()121     const JSPandaFile *GetJSPandaFile() const
122     {
123         return ctx_->GetJSPandaFile();
124     }
125 
GetAotModule()126     IRModule* GetAotModule() const
127     {
128         return ctx_->GetAOTModule();
129     }
130 
GetLog()131     CompilerLog* GetLog() const
132     {
133         return log_;
134     }
135 
GetMethodName()136     const std::string& GetMethodName() const
137     {
138         return methodName_;
139     }
140 
GetMethodLiteral()141     const MethodLiteral* GetMethodLiteral() const
142     {
143         return methodLiteral_;
144     }
145 
GetMethodOffset()146     uint32_t GetMethodOffset() const
147     {
148         return methodOffset_;
149     }
150 
GetMethodInfo()151     MethodInfo* GetMethodInfo() const
152     {
153         return methodInfo_;
154     }
155 
GetMethodInfoIndex()156     size_t GetMethodInfoIndex() const
157     {
158         return methodInfo_->GetMethodInfoIndex();
159     }
160 
HasTypes()161     bool HasTypes() const
162     {
163         return hasTypes_;
164     }
165 
GetRecordName()166     const CString &GetRecordName() const
167     {
168         return recordName_;
169     }
170 
GetNativeAreaAllocator()171     NativeAreaAllocator* GetNativeAreaAllocator() const
172     {
173         return allocator_;
174     }
175 
GetPGOProfilerDecoder()176     PGOProfilerDecoder *GetPGOProfilerDecoder() const
177     {
178         return decoder_;
179     }
180 
GetPassOptions()181     PassOptions *GetPassOptions() const
182     {
183         return passOptions_;
184     }
185 
IsTypeAbort()186     bool IsTypeAbort() const
187     {
188         if (hasTypes_) {
189             // A ts method which has low type percent and not marked as a resolved method
190             // should be skipped from full compilation.
191             if (methodInfo_->IsTypeInferAbort() && !methodInfo_->IsResolvedMethod()) {
192                 return true;
193             }
194         } else {
195             // For js method, type infer pass will be skipped and it don't have a type percent.
196             // If we set an non zero type threshold, js method will be skipped from full compilation.
197             // The default Type threshold is -1.
198             if (ctx_->GetTSManager()->GetTypeThreshold() >= 0) {
199                 return true;
200             }
201         }
202         // when a method will be full compiled, we should confirm its TypeInferAbortBit to be false
203         // maybe it used to be true in the first round of compilation.
204         methodInfo_->SetTypeInferAbort(false);
205         log_->AddCompiledMethod(methodName_, recordName_);
206         return false;
207     }
208 
AbortCompilation()209     void AbortCompilation()
210     {
211         ctx_->GetBytecodeInfo().AddSkippedMethod(methodOffset_);
212         methodInfo_->SetIsCompiled(false);
213         log_->RemoveCompiledMethod(methodName_, recordName_);
214     }
215 
MarkAsTypeAbort()216     void MarkAsTypeAbort()
217     {
218         methodInfo_->SetTypeInferAbort(true);
219     }
220 
221 private:
222     BytecodeCircuitBuilder *builder_ {nullptr};
223     Circuit *circuit_ {nullptr};
224     ControlFlowGraph cfg_;
225     PassContext *ctx_ {nullptr};
226     CompilerLog *log_ {nullptr};
227     std::string methodName_;
228     MethodInfo *methodInfo_ {nullptr};
229     bool hasTypes_;
230     const CString &recordName_;
231     MethodLiteral *methodLiteral_ {nullptr};
232     uint32_t methodOffset_;
233     NativeAreaAllocator *allocator_ {nullptr};
234     PGOProfilerDecoder *decoder_ {nullptr};
235     PassOptions *passOptions_ {nullptr};
236 };
237 
238 template<typename T1>
239 class PassRunner {
240 public:
PassRunner(T1 * data)241     explicit PassRunner(T1* data) : data_(data) {}
242     virtual ~PassRunner() = default;
243     template<typename T2, typename... Args>
RunPass(Args...args)244     bool RunPass(Args... args)
245     {
246         T2 pass;
247         return pass.Run(data_, std::forward<Args>(args)...);
248     }
249 
250 private:
251     T1* data_;
252 };
253 
254 class TypeInferPass {
255 public:
Run(PassData * data)256     bool Run(PassData* data)
257     {
258         PassOptions *passOptions = data->GetPassOptions();
259         if (passOptions != nullptr && !passOptions->EnableTypeInfer()) {
260             return false;
261         }
262         TimeScope timescope("TypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
263         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
264         GlobalTypeInfer globalTypeInfer(data->GetPassContext(), data->GetMethodOffset(), data->GetRecordName(),
265                                         data->GetPGOProfilerDecoder(), passOptions->EnableOptTrackField(),
266                                         enableLog, data->HasTypes());
267         globalTypeInfer.ProcessTypeInference(data->GetBuilder(), data->GetCircuit());
268         return true;
269     }
270 };
271 
272 class PGOTypeInferPass {
273 public:
Run(PassData * data)274     bool Run(PassData* data)
275     {
276         TimeScope timescope("PGOTypeInferPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
277         bool enableLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
278         Chunk chunk(data->GetNativeAreaAllocator());
279         PGOTypeInfer pgoTypeInfer(data->GetCircuit(), data->GetTSManager(), data->GetBuilder(),
280                                   data->GetMethodName(), &chunk, enableLog);
281         pgoTypeInfer.Run();
282         return true;
283     }
284 };
285 
286 class TSClassAnalysisPass {
287 public:
Run(PassData * data)288     bool Run(PassData *data)
289     {
290         TimeScope timescope("TSClassAnalysisPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
291         TSClassAnalysis analyzer(data->GetPassContext()->GetTSManager());
292         analyzer.Run();
293         return true;
294     }
295 };
296 
297 class TypeBytecodeLoweringPass {
298 public:
Run(PassData * data)299     bool Run(PassData* data)
300     {
301         PassOptions *passOptions = data->GetPassOptions();
302         if (!passOptions->EnableTypeLowering()) {
303             return false;
304         }
305         TimeScope timescope("TypeBytecodeLoweringPass", data->GetMethodName(),
306             data->GetMethodOffset(), data->GetLog());
307         bool enableLog = data->GetLog()->EnableMethodCIRLog();
308         bool enableTypeLog = data->GetLog()->GetEnableMethodLog() && data->GetLog()->OutputType();
309         Chunk chunk(data->GetNativeAreaAllocator());
310         TypedBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), &chunk,
311                                       enableLog,
312                                       enableTypeLog,
313                                       data->GetMethodName(),
314                                       passOptions->EnableLoweringBuiltin(),
315                                       data->GetRecordName());
316         bool success = lowering.RunTypedBytecodeLowering();
317         if (!success) {
318             data->MarkAsTypeAbort();
319         }
320         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
321         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
322         TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog,
323                                   data->GetMethodName());
324 
325         visitor.AddPass(&optimization);
326         visitor.AddPass(&deadCodeElimination);
327         visitor.VisitGraph();
328         visitor.PrintLog("TSHCROptPass");
329         return true;
330     }
331 };
332 
333 class NTypeBytecodeLoweringPass {
334 public:
Run(PassData * data)335     bool Run(PassData* data)
336     {
337         PassOptions *passOptions = data->GetPassOptions();
338         if (!passOptions->EnableTypeLowering()) {
339             return false;
340         }
341         TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(),
342             data->GetMethodOffset(), data->GetLog());
343         bool enableLog = data->GetLog()->EnableMethodCIRLog();
344         NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), data->GetTSManager(),
345             enableLog, data->GetMethodName());
346         lowering.RunNTypeBytecodeLowering();
347         Chunk chunk(data->GetNativeAreaAllocator());
348         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
349         DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk);
350         visitor.AddPass(&deadCodeElimination);
351         visitor.VisitGraph();
352         return true;
353     }
354 };
355 
356 class StringOptimizationPass {
357 public:
Run(PassData * data)358     bool Run(PassData* data)
359     {
360         PassOptions *passOptions = data->GetPassOptions();
361         if (!passOptions->EnableOptString()) {
362             return false;
363         }
364         TimeScope timescope("StringOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
365         bool enableLog = data->GetLog()->EnableMethodCIRLog();
366         Chunk chunk(data->GetNativeAreaAllocator());
367         StringBuilderOptimizer stringBuilder(data->GetCircuit(),
368                                              enableLog,
369                                              data->GetMethodName(),
370                                              data->GetCompilerConfig(),
371                                              &chunk);
372         stringBuilder.Run();
373         return true;
374     }
375 };
376 
377 class TypeHCRLoweringPass {
378 public:
Run(PassData * data)379     bool Run(PassData* data)
380     {
381         PassOptions *passOptions = data->GetPassOptions();
382         if (!passOptions->EnableTypeLowering()) {
383             return false;
384         }
385         TimeScope timescope("TypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
386         bool enableLog = data->GetLog()->EnableMethodCIRLog();
387         Chunk chunk(data->GetNativeAreaAllocator());
388         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
389         TypedHCRLowering lowering(data->GetCircuit(),
390                                  &visitor,
391                                  data->GetCompilerConfig(),
392                                  data->GetTSManager(),
393                                  &chunk,
394                                  passOptions->EnableLoweringBuiltin());
395         visitor.AddPass(&lowering);
396         visitor.VisitGraph();
397         visitor.PrintLog("TypedHCRLowering");
398         return true;
399     }
400 };
401 
402 class NTypeHCRLoweringPass {
403 public:
Run(PassData * data)404     bool Run(PassData* data)
405     {
406         PassOptions *passOptions = data->GetPassOptions();
407         if (!passOptions->EnableTypeLowering()) {
408             return false;
409         }
410         TimeScope timescope("NTypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
411         bool enableLog = data->GetLog()->EnableMethodCIRLog();
412         Chunk chunk(data->GetNativeAreaAllocator());
413         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
414         NTypeHCRLowering lowering(data->GetCircuit(), &visitor, data->GetPassContext(),
415                                   data->GetRecordName(), &chunk);
416         visitor.AddPass(&lowering);
417         visitor.VisitGraph();
418         visitor.PrintLog("NTypeHCRLowering");
419         return true;
420     }
421 };
422 
423 class LCRLoweringPass {
424 public:
Run(PassData * data)425     bool Run(PassData* data)
426     {
427         PassOptions *passOptions = data->GetPassOptions();
428         if (!passOptions->EnableTypeLowering()) {
429             return false;
430         }
431         TimeScope timescope("LCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
432         bool enableLog = data->GetLog()->EnableMethodCIRLog();
433         Chunk chunk(data->GetNativeAreaAllocator());
434         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
435         MCRLowering lowering(data->GetCircuit(), &visitor, data->GetCompilerConfig(), &chunk);
436         visitor.AddPass(&lowering);
437         visitor.VisitGraph();
438         visitor.PrintLog("MCRLowering");
439         return true;
440     }
441 };
442 
443 class TSInlineLoweringPass {
444 public:
Run(PassData * data)445     bool Run(PassData* data)
446     {
447         PassOptions *passOptions = data->GetPassOptions();
448         if (!passOptions->EnableOptInlining() || !passOptions->EnableTypeLowering()) {
449             return false;
450         }
451         TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
452         bool enableLog = data->GetLog()->EnableMethodCIRLog();
453         TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
454                                   data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset());
455         inlining.RunTSInlineLowering();
456         if (passOptions->EnableLexenvSpecialization()) {
457             Chunk chunk(data->GetNativeAreaAllocator());
458             {
459                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
460                 GetEnvSpecializationPass getEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk);
461                 visitor.AddPass(&getEnvSpecializationPass);
462                 visitor.VisitGraph();
463                 visitor.PrintLog("getEnvSpecializationPass");
464             }
465             {
466                 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
467                 LexicalEnvSpecializationPass lexicalEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk,
468                                                                           enableLog);
469                 visitor.AddPass(&lexicalEnvSpecializationPass);
470                 visitor.VisitGraph();
471                 visitor.PrintLog("lexicalEnvSpecialization");
472                 lexicalEnvSpecializationPass.PrintSpecializeId();
473             }
474         }
475 
476         if (passOptions->EnableInlineNative()) {
477             NativeInlineLowering nativeInline(data->GetCircuit(), data->GetPassContext(), enableLog,
478                                               data->GetMethodName());
479             nativeInline.RunNativeInlineLowering();
480         }
481         return true;
482     }
483 };
484 
485 class SlowPathLoweringPass {
486 public:
Run(PassData * data)487     bool Run(PassData* data)
488     {
489         TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
490         bool enableLog = data->GetLog()->EnableMethodCIRLog();
491         SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetTSManager(),
492                                   data->GetMethodLiteral(), enableLog, data->GetMethodName());
493         lowering.CallRuntimeLowering();
494         return true;
495     }
496 };
497 
498 class RunFlowCyclesVerifierPass {
499 public:
Run(PassData * data)500     bool Run(PassData* data)
501     {
502         TimeScope timescope("FlowCyclesVerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
503         bool hasFlowCycle = Verifier::RunFlowCyclesFind(data->GetCircuit());
504         if (hasFlowCycle) {
505             LOG_FULL(FATAL) << "FlowCyclesVerifierPass fail";
506             UNREACHABLE();
507         }
508         return !hasFlowCycle;
509     }
510 };
511 
512 class VerifierPass {
513 public:
Run(PassData * data)514     bool Run(PassData* data)
515     {
516         TimeScope timescope("VerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
517         bool enableLog = data->GetLog()->EnableMethodCIRLog();
518         bool isQualified = Verifier::Run(data->GetCircuit(), data->GetMethodName(), enableLog);
519         if (!isQualified) {
520             LOG_FULL(FATAL) << "VerifierPass fail";
521             UNREACHABLE();
522         }
523         return isQualified;
524     }
525 };
526 
527 class NumberSpeculativePass {
528 public:
Run(PassData * data)529     bool Run(PassData* data)
530     {
531         PassOptions *passOptions = data->GetPassOptions();
532         if (!passOptions->EnableTypeLowering()) {
533             return false;
534         }
535         TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
536         Chunk chunk(data->GetNativeAreaAllocator());
537         bool enableLog = data->GetLog()->EnableMethodCIRLog();
538         bool enableArrayBoundsCheckElimination = passOptions->EnableArrayBoundsCheckElimination();
539         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
540         NumberSpeculativeRunner(data->GetCircuit(), enableLog, enableArrayBoundsCheckElimination,
541                                 data->GetMethodName(), &chunk).Run();
542         return true;
543     }
544 };
545 
546 class ConstantFoldingPass {
547 public:
Run(PassData * data)548     bool Run(PassData* data)
549     {
550         PassOptions *passOptions = data->GetPassOptions();
551         if (!passOptions->EnableOptConstantFolding()) {
552             return false;
553         }
554         TimeScope timescope("ConstantFoldingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
555         Chunk chunk(data->GetNativeAreaAllocator());
556         bool enableLog = data->GetLog()->EnableMethodCIRLog();
557         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
558         ConstantFolding constantFolding(data->GetCircuit(), &visitor, data->GetCompilerConfig(), enableLog,
559                                         data->GetMethodName(), &chunk);
560         visitor.AddPass(&constantFolding);
561         visitor.VisitGraph();
562         constantFolding.Print();
563         return true;
564     }
565 };
566 
567 class LoopOptimizationPass {
568 public:
Run(PassData * data)569     bool Run(PassData* data)
570     {
571         TimeScope timescope("LoopOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
572         Chunk chunk(data->GetNativeAreaAllocator());
573         LoopAnalysis loopAnalysis(data->GetBuilder(), data->GetCircuit(), &chunk);
574         loopAnalysis.Run();
575         bool enableLog = data->GetLog()->EnableMethodCIRLog();
576         for (auto loopInfo : loopAnalysis.GetLoopTree()) {
577             loopAnalysis.CollectLoopBody(loopInfo);
578             if (enableLog) {
579                 loopAnalysis.PrintLoop(loopInfo);
580             }
581             if (data->GetPassOptions()->EnableOptLoopPeeling()) {
582                 LoopPeeling(data->GetBuilder(), data->GetCircuit(), enableLog,
583                             data->GetMethodName(), &chunk, loopInfo).Peel();
584             }
585         }
586         loopAnalysis.LoopExitElimination();
587         return true;
588     }
589 };
590 
591 class RedundantPhiEliminationPass {
592 public:
Run(PassData * data)593     bool Run(PassData* data)
594     {
595         TimeScope timescope("RedundantPhiEliminationPass", data->GetMethodName(),
596             data->GetMethodOffset(), data->GetLog());
597         bool enableLog = data->GetLog()->EnableMethodCIRLog();
598         GraphEditor::EliminateRedundantPhi(data->GetCircuit(), enableLog, data->GetMethodName());
599         return true;
600     }
601 };
602 
603 class EarlyEliminationPass {
604 public:
Run(PassData * data)605     bool Run(PassData* data)
606     {
607         PassOptions *passOptions = data->GetPassOptions();
608         if (!passOptions->EnableTypeLowering() || !passOptions->EnableEarlyElimination()) {
609             return false;
610         }
611         TimeScope timescope("EarlyEliminationPass", data->GetMethodName(),
612                             data->GetMethodOffset(), data->GetLog());
613         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
614         Chunk chunk(data->GetNativeAreaAllocator());
615         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
616         EarlyElimination earlyElimination(data->GetCircuit(), &visitor, &chunk);
617         visitor.AddPass(&earlyElimination);
618         visitor.VisitGraph();
619         visitor.PrintLog("early elimination");
620         return true;
621     }
622 };
623 
624 class LaterEliminationPass {
625 public:
Run(PassData * data)626     bool Run(PassData* data)
627     {
628         PassOptions *passOptions = data->GetPassOptions();
629         if (!passOptions->EnableTypeLowering() || !passOptions->EnableLaterElimination()) {
630             return false;
631         }
632         TimeScope timescope("LaterEliminationPass", data->GetMethodName(),
633                             data->GetMethodOffset(), data->GetLog());
634         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
635         Chunk chunk(data->GetNativeAreaAllocator());
636         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
637         LaterElimination laterElimination(data->GetCircuit(), &visitor, &chunk);
638         visitor.AddPass(&laterElimination);
639         visitor.VisitGraph();
640         visitor.PrintLog("later elimination");
641         return true;
642     }
643 };
644 
645 class ValueNumberingPass {
646 public:
Run(PassData * data)647     bool Run(PassData* data)
648     {
649         PassOptions *passOptions = data->GetPassOptions();
650         if (!passOptions->EnableTypeLowering() || !passOptions->EnableValueNumbering()) {
651             return false;
652         }
653         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions();
654         TimeScope timescope("ValueNumberingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
655         Chunk chunk(data->GetNativeAreaAllocator());
656         bool enableLog = data->GetLog()->EnableMethodCIRLog();
657         CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
658         ValueNumbering valueNumbering(data->GetCircuit(), &visitor, &chunk,
659                                       runtimeOption.IsEnableNewValueNumbering(),
660                                       runtimeOption.GetTraceValueNumbering());
661         visitor.AddPass(&valueNumbering);
662         visitor.VisitGraph();
663         visitor.PrintLog("value numbering");
664         return true;
665     }
666 };
667 
668 class InstructionCombinePass {
669 public:
Run(PassData * data)670     bool Run(PassData *data)
671     {
672         JSRuntimeOptions runtimeOption = data->GetPassContext()->GetEcmaVM()->GetJSOptions();
673         if (runtimeOption.IsEnableInstrcutionCombine()) {
674             TimeScope timescope("InstructionCombinePass", data->GetMethodName(), data->GetMethodOffset(),
675                                 data->GetLog());
676             Chunk chunk(data->GetNativeAreaAllocator());
677             bool enableLog = data->GetLog()->EnableMethodCIRLog();
678             CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk);
679             InstructionCombine instructionCombine(data->GetCircuit(), &visitor, &chunk,
680                                                   runtimeOption.GetTraceInstructionCombine());
681             visitor.AddPass(&instructionCombine);
682             visitor.VisitGraph();
683             visitor.PrintLog("Instruction Combine");
684         }
685         return true;
686     }
687 };
688 
689 class SchedulingPass {
690 public:
Run(PassData * data)691     bool Run(PassData* data)
692     {
693         TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
694         bool enableLog = data->GetLog()->EnableMethodCIRLog();
695         Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
696         return true;
697     }
698 };
699 
700 class StateSplitLinearizerPass {
701 public:
Run(PassData * data)702     bool Run(PassData* data)
703     {
704         PassOptions *passOptions = data->GetPassOptions();
705         if (!passOptions->EnableTypeLowering()) {
706             return false;
707         }
708         TimeScope timescope("StateSplitLinearizerPass", data->GetMethodName(),
709                             data->GetMethodOffset(), data->GetLog());
710         Chunk chunk(data->GetNativeAreaAllocator());
711         bool enableLog = data->GetLog()->EnableMethodCIRLog();
712         StateSplitLinearizer(data->GetCircuit(), nullptr, data->GetCompilerConfig(),
713             enableLog, data->GetMethodName(), &chunk).Run();
714         return true;
715     }
716 };
717 
718 class GraphLinearizerPass {
719 public:
Run(PassData * data)720     bool Run(PassData* data)
721     {
722         TimeScope timescope("GraphLinearizerPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
723         Chunk chunk(data->GetNativeAreaAllocator());
724         bool enableLog = data->GetLog()->EnableMethodCIRLog();
725         bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion();
726         bool liteCG = data->GetTSManager()->GetEcmaVM()->GetJSOptions().IsCompilerEnableLiteCG();
727         GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG)
728             .Run(data->GetCfg());
729         return true;
730     }
731 };
732 
733 class CGIRGenPass {
734 public:
CreateCodeGen(IRModule * module,bool enableLog)735     void CreateCodeGen(IRModule *module, bool enableLog)
736     {
737 #ifdef COMPILE_MAPLE
738         if (module->GetModuleKind() == MODULE_LLVM) {
739             cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
740         } else {
741             cgImpl_ = std::make_unique<LiteCGIRGeneratorImpl>(static_cast<LMIRModule*>(module), enableLog);
742         }
743 #else
744         cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog);
745 #endif
746     }
Run(PassData * data)747     bool Run(PassData *data)
748     {
749         auto module = data->GetAotModule();
750         TimeScope timescope("CGIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
751         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
752         PassOptions *passOptions = data->GetPassOptions();
753         bool enableOptInlining = passOptions->EnableOptInlining() && passOptions->EnableTypeLowering();
754         bool enableOptBranchProfiling = passOptions->EnableOptBranchProfiling();
755         CreateCodeGen(module, enableLog);
756         CodeGenerator codegen(cgImpl_, data->GetMethodName());
757         codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), data->GetCompilerConfig(),
758                     data->GetMethodLiteral(), data->GetJSPandaFile(), enableOptInlining, enableOptBranchProfiling);
759         return true;
760     }
761 private:
762     std::unique_ptr<CodeGeneratorImpl> cgImpl_ {nullptr};
763 };
764 
765 class AsyncFunctionLoweringPass {
766 public:
Run(PassData * data)767     bool Run(PassData* data)
768     {
769         TimeScope timescope("AsyncFunctionLoweringPass", data->GetMethodName(),
770                             data->GetMethodOffset(), data->GetLog());
771         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog();
772         AsyncFunctionLowering lowering(data->GetBuilder(), data->GetCircuit(), data->GetCompilerConfig(),
773                                        enableLog, data->GetMethodName());
774         if (lowering.IsAsyncRelated()) {
775             lowering.ProcessAll();
776         }
777         return true;
778     }
779 
780 private:
IsFunctionMain(PassData * data)781     bool IsFunctionMain(PassData* data)
782     {
783         auto methodName = data->GetMethodName();
784         auto pos = methodName.find(JSPandaFile::ENTRY_FUNCTION_NAME);
785         if (pos != std::string::npos) {
786             return true;
787         }
788         return false;
789     }
790 };
791 } // namespace panda::ecmascript::kungfu
792 #endif
793