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 passOptions->EnableMergePoly(), 334 passOptions->EnableLazyDeopt(), 335 data->GetRecordName(), 336 data->GetCallMethodFlagMap(), 337 data->GetPGOProfilerDecoder(), 338 data->GetOptBCRange(), 339 data->GetMethodLiteral()); 340 lowering.RunTypedBytecodeLowering(); 341 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 342 DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk); 343 TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog, 344 data->GetMethodName()); 345 346 visitor.AddPass(&optimization); 347 visitor.AddPass(&deadCodeElimination); 348 visitor.VisitGraph(); 349 visitor.PrintLog("TSHCROptPass"); 350 return true; 351 } 352 }; 353 354 class NTypeBytecodeLoweringPass { 355 public: Run(PassData * data)356 bool Run(PassData* data) 357 { 358 PassOptions *passOptions = data->GetPassOptions(); 359 if (!passOptions->EnableTypeLowering()) { 360 return false; 361 } 362 TimeScope timescope("NTypeBytecodeLoweringPass", data->GetMethodName(), 363 data->GetMethodOffset(), data->GetLog()); 364 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 365 NTypeBytecodeLowering lowering(data->GetCircuit(), data->GetPassContext(), enableLog, 366 passOptions->EnableLazyDeopt(), data->GetMethodName(), data->GetRecordName()); 367 lowering.RunNTypeBytecodeLowering(); 368 Chunk chunk(data->GetNativeAreaAllocator()); 369 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 370 DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk); 371 visitor.AddPass(&deadCodeElimination); 372 visitor.VisitGraph(); 373 return true; 374 } 375 }; 376 377 class StringOptimizationPass { 378 public: Run(PassData * data)379 bool Run(PassData* data) 380 { 381 PassOptions *passOptions = data->GetPassOptions(); 382 if (!passOptions->EnableOptString()) { 383 return false; 384 } 385 TimeScope timescope("StringOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 386 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 387 Chunk chunk(data->GetNativeAreaAllocator()); 388 StringBuilderOptimizer stringBuilder(data->GetCircuit(), 389 enableLog, 390 data->GetMethodName(), 391 data->GetCompilerConfig(), 392 &chunk); 393 stringBuilder.Run(); 394 return true; 395 } 396 }; 397 398 class TypeHCRLoweringPass { 399 public: Run(PassData * data)400 bool Run(PassData* data) 401 { 402 PassOptions *passOptions = data->GetPassOptions(); 403 if (!passOptions->EnableTypeLowering()) { 404 return false; 405 } 406 { 407 TimeScope timescope("TypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 408 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 409 Chunk chunk(data->GetNativeAreaAllocator()); 410 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 411 TypedHCRLowering lowering(data->GetCircuit(), 412 data->GetPassContext()->GetCompilationEnv(), 413 &visitor, 414 data->GetCompilerConfig(), 415 &chunk, 416 passOptions->EnableLoweringBuiltin()); 417 visitor.AddPass(&lowering); 418 visitor.VisitGraph(); 419 visitor.PrintLog("TypedHCRLowering"); 420 } 421 422 { 423 TimeScope timescope("TypedNativeInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), 424 data->GetLog()); 425 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 426 Chunk chunk(data->GetNativeAreaAllocator()); 427 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 428 TypedNativeInlineLowering lowering(data->GetCircuit(), 429 &visitor, 430 data->GetPassContext(), 431 data->GetCompilerConfig(), 432 &chunk); 433 visitor.AddPass(&lowering); 434 visitor.VisitGraph(); 435 visitor.PrintLog("TypedNativeInlineLowering"); 436 } 437 438 return true; 439 } 440 }; 441 442 class NTypeHCRLoweringPass { 443 public: Run(PassData * data)444 bool Run(PassData* data) 445 { 446 PassOptions *passOptions = data->GetPassOptions(); 447 if (!passOptions->EnableTypeLowering()) { 448 return false; 449 } 450 TimeScope timescope("NTypeHCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 451 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 452 Chunk chunk(data->GetNativeAreaAllocator()); 453 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 454 JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); 455 NTypeHCRLowering lowering(data->GetCircuit(), &visitor, data->GetPassContext(), 456 data->GetRecordName(), data->GetMethodLiteral(), runtimeOption.IsCompilerEnablePgoSpace(), &chunk); 457 visitor.AddPass(&lowering); 458 visitor.VisitGraph(); 459 visitor.PrintLog("NTypeHCRLowering"); 460 return true; 461 } 462 }; 463 464 class LCRLoweringPass { 465 public: Run(PassData * data)466 bool Run(PassData* data) 467 { 468 PassOptions *passOptions = data->GetPassOptions(); 469 if (!passOptions->EnableTypeLowering()) { 470 return false; 471 } 472 TimeScope timescope("LCRLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 473 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 474 Chunk chunk(data->GetNativeAreaAllocator()); 475 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 476 MCRLowering lowering(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), &visitor, 477 data->GetCompilerConfig(), &chunk); 478 visitor.AddPass(&lowering); 479 visitor.VisitGraph(); 480 visitor.PrintLog("MCRLowering"); 481 return true; 482 } 483 }; 484 485 class TSInlineLoweringPass { 486 public: Run(PassData * data)487 bool Run(PassData* data) 488 { 489 PassOptions *passOptions = data->GetPassOptions(); 490 if (!passOptions->EnableOptInlining() || !passOptions->EnableTypeLowering()) { 491 return false; 492 } 493 TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 494 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 495 TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(), 496 data->GetNativeAreaAllocator(), passOptions, data->GetMethodOffset(), 497 data->GetCallMethodFlagMap()); 498 inlining.RunTSInlineLowering(); 499 Chunk chunk(data->GetNativeAreaAllocator()); 500 if (passOptions->EnableLexenvSpecialization()) { 501 { 502 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 503 GetEnvSpecializationPass getEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk); 504 visitor.AddPass(&getEnvSpecializationPass); 505 visitor.VisitGraph(); 506 visitor.PrintLog("getEnvSpecializationPass"); 507 } 508 { 509 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 510 LexicalEnvSpecializationPass lexicalEnvSpecializationPass(data->GetCircuit(), &visitor, &chunk, 511 enableLog); 512 visitor.AddPass(&lexicalEnvSpecializationPass); 513 visitor.VisitGraph(); 514 visitor.PrintLog("lexicalEnvSpecialization"); 515 lexicalEnvSpecializationPass.PrintSpecializeId(); 516 } 517 } 518 519 if (passOptions->EnableInlineNative()) { 520 NativeInlineLowering nativeInline(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(), 521 enableLog, data->GetMethodName(), &chunk); 522 nativeInline.RunNativeInlineLowering(); 523 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 524 DeadCodeElimination deadCodeElimination(data->GetCircuit(), &visitor, &chunk); 525 TSHCROptPass optimization(data->GetCircuit(), &visitor, &chunk, data->GetPassContext(), enableLog, 526 data->GetMethodName()); 527 528 visitor.AddPass(&optimization); 529 visitor.AddPass(&deadCodeElimination); 530 visitor.VisitGraph(); 531 visitor.PrintLog("TSHCROptPass"); 532 } 533 return true; 534 } 535 }; 536 537 class SlowPathLoweringPass { 538 public: Run(PassData * data)539 bool Run(PassData* data) 540 { 541 TimeScope timescope("SlowPathLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 542 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 543 SlowPathLowering lowering(data->GetCircuit(), data->GetCompilerConfig(), data->GetPassContext(), 544 data->GetMethodLiteral(), enableLog, data->GetMethodName(), data->GetRecordName()); 545 lowering.CallRuntimeLowering(); 546 return true; 547 } 548 }; 549 550 class RunFlowCyclesVerifierPass { 551 public: Run(PassData * data)552 bool Run(PassData* data) 553 { 554 TimeScope timescope("FlowCyclesVerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 555 bool hasFlowCycle = Verifier::RunFlowCyclesFind(data->GetCircuit()); 556 if (hasFlowCycle) { 557 LOG_FULL(FATAL) << "FlowCyclesVerifierPass fail"; 558 UNREACHABLE(); 559 } 560 return !hasFlowCycle; 561 } 562 }; 563 564 class VerifierPass { 565 public: Run(PassData * data)566 bool Run(PassData* data) 567 { 568 TimeScope timescope("VerifierPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 569 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 570 bool isQualified = Verifier::Run(data->GetCircuit(), data->GetMethodName(), enableLog); 571 if (!isQualified) { 572 LOG_FULL(FATAL) << "VerifierPass fail"; 573 UNREACHABLE(); 574 } 575 return isQualified; 576 } 577 }; 578 579 class NumberSpeculativePass { 580 public: Run(PassData * data)581 bool Run(PassData* data) 582 { 583 PassOptions *passOptions = data->GetPassOptions(); 584 if (!passOptions->EnableTypeLowering()) { 585 return false; 586 } 587 TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 588 Chunk chunk(data->GetNativeAreaAllocator()); 589 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 590 bool enableArrayBoundsCheckElimination = passOptions->EnableArrayBoundsCheckElimination(); 591 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 592 NumberSpeculativeRunner(data->GetCircuit(), data->GetCompilerConfig(), enableLog, 593 enableArrayBoundsCheckElimination, data->GetMethodName(), &chunk).Run(); 594 return true; 595 } 596 }; 597 598 class ConstantFoldingPass { 599 public: Run(PassData * data)600 bool Run(PassData* data) 601 { 602 PassOptions *passOptions = data->GetPassOptions(); 603 if (!passOptions->EnableOptConstantFolding()) { 604 return false; 605 } 606 TimeScope timescope("ConstantFoldingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 607 Chunk chunk(data->GetNativeAreaAllocator()); 608 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 609 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 610 ConstantFolding constantFolding(data->GetCircuit(), &visitor, data->GetCompilerConfig(), enableLog, 611 data->GetMethodName(), &chunk); 612 visitor.AddPass(&constantFolding); 613 visitor.VisitGraph(); 614 constantFolding.Print(); 615 return true; 616 } 617 }; 618 619 class LoopOptimizationPass { 620 public: Run(PassData * data)621 bool Run(PassData* data) 622 { 623 TimeScope timescope("LoopOptimizationPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 624 Chunk chunk(data->GetNativeAreaAllocator()); 625 LoopAnalysis loopAnalysis(data->GetBuilder(), data->GetCircuit(), &chunk); 626 loopAnalysis.Run(); 627 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 628 for (auto loopInfo : loopAnalysis.GetLoopTree()) { 629 loopAnalysis.CollectLoopBody(loopInfo); 630 if (enableLog) { 631 loopAnalysis.PrintLoop(loopInfo); 632 } 633 if (data->GetPassOptions()->EnableOptLoopPeeling()) { 634 LoopPeeling(data->GetBuilder(), data->GetCircuit(), enableLog, 635 data->GetMethodName(), &chunk, loopInfo).Peel(); 636 } 637 } 638 loopAnalysis.LoopExitElimination(); 639 return true; 640 } 641 }; 642 643 class RedundantPhiEliminationPass { 644 public: Run(PassData * data)645 bool Run(PassData* data) 646 { 647 TimeScope timescope("RedundantPhiEliminationPass", data->GetMethodName(), 648 data->GetMethodOffset(), data->GetLog()); 649 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 650 GraphEditor::EliminateRedundantPhi(data->GetCircuit(), enableLog, data->GetMethodName()); 651 return true; 652 } 653 }; 654 655 class EarlyEliminationPass { 656 public: Run(PassData * data)657 bool Run(PassData* data) 658 { 659 PassOptions *passOptions = data->GetPassOptions(); 660 if (!passOptions->EnableTypeLowering() || !passOptions->EnableEarlyElimination()) { 661 return false; 662 } 663 TimeScope timescope("EarlyEliminationPass", data->GetMethodName(), 664 data->GetMethodOffset(), data->GetLog()); 665 bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog(); 666 Chunk chunk(data->GetNativeAreaAllocator()); 667 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 668 JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); 669 EarlyElimination earlyElimination(data->GetCircuit(), &visitor, &chunk, 670 runtimeOption.IsEnableMemoryAnalysis(), runtimeOption.IsEnableFrameStateElimination()); 671 visitor.AddPass(&earlyElimination); 672 visitor.VisitGraph(); 673 visitor.PrintLog("early elimination"); 674 return true; 675 } 676 }; 677 678 class LaterEliminationPass { 679 public: Run(PassData * data)680 bool Run(PassData* data) 681 { 682 PassOptions *passOptions = data->GetPassOptions(); 683 if (!passOptions->EnableTypeLowering() || !passOptions->EnableLaterElimination()) { 684 return false; 685 } 686 TimeScope timescope("LaterEliminationPass", data->GetMethodName(), 687 data->GetMethodOffset(), data->GetLog()); 688 bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog(); 689 Chunk chunk(data->GetNativeAreaAllocator()); 690 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 691 LaterElimination laterElimination(data->GetCircuit(), &visitor, &chunk); 692 visitor.AddPass(&laterElimination); 693 visitor.VisitGraph(); 694 visitor.PrintLog("later elimination"); 695 return true; 696 } 697 }; 698 699 class UselessGateEliminationPass { 700 public: Run(PassData * data)701 bool Run(PassData* data) 702 { 703 TimeScope timescope("UselessGateEliminationPass", data->GetMethodName(), 704 data->GetMethodOffset(), data->GetLog()); 705 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 706 UselessGateElimination uselessGateElimination(data->GetCircuit(), enableLog, data->GetMethodName()); 707 uselessGateElimination.Run(); 708 return true; 709 } 710 }; 711 712 class ValueNumberingPass { 713 public: Run(PassData * data)714 bool Run(PassData* data) 715 { 716 PassOptions *passOptions = data->GetPassOptions(); 717 if (!passOptions->EnableTypeLowering() || !passOptions->EnableValueNumbering()) { 718 return false; 719 } 720 JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); 721 TimeScope timescope("ValueNumberingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 722 Chunk chunk(data->GetNativeAreaAllocator()); 723 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 724 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 725 ValueNumbering valueNumbering(data->GetCircuit(), &visitor, &chunk, 726 runtimeOption.IsEnableNewValueNumbering(), 727 runtimeOption.GetTraceValueNumbering()); 728 visitor.AddPass(&valueNumbering); 729 visitor.VisitGraph(); 730 visitor.PrintLog("value numbering"); 731 return true; 732 } 733 }; 734 735 class InstructionCombinePass { 736 public: Run(PassData * data)737 bool Run(PassData *data) 738 { 739 JSRuntimeOptions runtimeOption = data->GetPassContext()->GetCompilationEnv()->GetJSOptions(); 740 if (runtimeOption.IsEnableInstrcutionCombine()) { 741 TimeScope timescope("InstructionCombinePass", data->GetMethodName(), data->GetMethodOffset(), 742 data->GetLog()); 743 Chunk chunk(data->GetNativeAreaAllocator()); 744 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 745 CombinedPassVisitor visitor(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk); 746 InstructionCombine instructionCombine(data->GetCircuit(), &visitor, &chunk, 747 runtimeOption.GetTraceInstructionCombine()); 748 visitor.AddPass(&instructionCombine); 749 visitor.VisitGraph(); 750 visitor.PrintLog("Instruction Combine"); 751 } 752 return true; 753 } 754 }; 755 756 class SchedulingPass { 757 public: Run(PassData * data,bool isStwCopyStub)758 bool Run(PassData* data, bool isStwCopyStub) 759 { 760 TimeScope timescope("SchedulingPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 761 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 762 Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog); 763 Chunk chunk(data->GetNativeAreaAllocator()); 764 CompilationEnv *env = nullptr; 765 if (data->GetPassContext() != nullptr) { 766 env = data->GetPassContext()->GetCompilationEnv(); 767 } 768 if (isStwCopyStub) { 769 #if ENABLE_NEXT_OPTIMIZATION 770 PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, true, isStwCopyStub) 771 .Run(data->GetCfg()); 772 #else 773 PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, false, isStwCopyStub) 774 .Run(data->GetCfg()); 775 #endif 776 } else { 777 PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, env, false, isStwCopyStub) 778 .Run(data->GetCfg()); 779 } 780 return true; 781 } 782 }; 783 784 class StateSplitLinearizerPass { 785 public: Run(PassData * data)786 bool Run(PassData* data) 787 { 788 PassOptions *passOptions = data->GetPassOptions(); 789 if (!passOptions->EnableTypeLowering()) { 790 return false; 791 } 792 TimeScope timescope("StateSplitLinearizerPass", data->GetMethodName(), 793 data->GetMethodOffset(), data->GetLog()); 794 Chunk chunk(data->GetNativeAreaAllocator()); 795 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 796 StateSplitLinearizer(data->GetPassContext()->GetCompilationEnv(), data->GetCircuit(), nullptr, 797 data->GetCompilerConfig(), enableLog, data->GetMethodName(), &chunk) 798 .Run(); 799 return true; 800 } 801 }; 802 803 class GraphLinearizerPass { 804 public: Run(PassData * data,bool isStwCopyStub)805 bool Run(PassData* data, bool isStwCopyStub) 806 { 807 TimeScope timescope("GraphLinearizerPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 808 Chunk chunk(data->GetNativeAreaAllocator()); 809 bool enableLog = data->GetLog()->EnableMethodCIRLog(); 810 bool licm = data->GetPassOptions()->EnableOptLoopInvariantCodeMotion(); 811 bool liteCG = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsCompilerEnableLiteCG(); 812 bool enableStoreBarrier = data->GetPassContext()->GetCompilationEnv()->GetJSOptions().IsStoreBarrierOpt(); 813 GraphLinearizer(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false, licm, liteCG) 814 .Run(data->GetCfg()); 815 PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, 816 data->GetPassContext()->GetCompilationEnv(), enableStoreBarrier, isStwCopyStub) 817 .Run(data->GetCfg()); 818 return true; 819 } 820 }; 821 822 class CGIRGenPass { 823 public: CreateCodeGen(IRModule * module,bool enableLog)824 void CreateCodeGen(IRModule *module, bool enableLog) 825 { 826 #ifdef COMPILE_MAPLE 827 if (module->GetModuleKind() == MODULE_LLVM) { 828 cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog); 829 } else { 830 cgImpl_ = std::make_unique<LiteCGIRGeneratorImpl>(static_cast<LMIRModule*>(module), enableLog); 831 } 832 #else 833 cgImpl_ = std::make_unique<LLVMIRGeneratorImpl>(static_cast<LLVMModule*>(module), enableLog); 834 #endif 835 } Run(PassData * data)836 bool Run(PassData *data) 837 { 838 auto module = data->GetAotModule(); 839 TimeScope timescope("CGIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog()); 840 bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog(); 841 PassOptions *passOptions = data->GetPassOptions(); 842 bool enableOptInlining = passOptions->EnableOptInlining() && passOptions->EnableTypeLowering(); 843 bool enableOptBranchProfiling = passOptions->EnableOptBranchProfiling(); 844 CreateCodeGen(module, enableLog); 845 CodeGenerator codegen(cgImpl_, data->GetMethodName()); 846 codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), data->GetCompilerConfig(), 847 data->GetMethodLiteral(), data->GetJSPandaFile(), data->GetCircuit()->GetFrameType(), 848 enableOptInlining, enableOptBranchProfiling); 849 return true; 850 } 851 private: 852 std::unique_ptr<CodeGeneratorImpl> cgImpl_ {nullptr}; 853 }; 854 855 class AsyncFunctionLoweringPass { 856 public: Run(PassData * data)857 bool Run(PassData* data) 858 { 859 TimeScope timescope("AsyncFunctionLoweringPass", data->GetMethodName(), 860 data->GetMethodOffset(), data->GetLog()); 861 bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->EnableMethodASMLog(); 862 AsyncFunctionLowering lowering(data->GetBuilder(), data->GetCircuit(), data->GetCompilerConfig(), 863 enableLog, data->GetMethodName()); 864 if (lowering.IsAsyncRelated()) { 865 lowering.ProcessAll(); 866 } 867 return true; 868 } 869 870 private: IsFunctionMain(PassData * data)871 bool IsFunctionMain(PassData* data) 872 { 873 auto methodName = data->GetMethodName(); 874 auto pos = methodName.find(JSPandaFile::ENTRY_FUNCTION_NAME); 875 if (pos != std::string::npos) { 876 return true; 877 } 878 return false; 879 } 880 }; 881 } // namespace panda::ecmascript::kungfu 882 #endif 883