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