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