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