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