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