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