From 0720a622c127a14699250bd679aee08b9c2850c3 Mon Sep 17 00:00:00 2001 From: Lixuanwang Date: Mon, 18 Aug 2025 22:14:21 +0800 Subject: [PATCH] =?UTF-8?q?[backend]=E5=AE=8C=E5=96=84=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=EF=BC=8C=E6=9C=AC=E5=9C=B0=E4=BB=85?= =?UTF-8?q?=E5=89=A9h/39=E4=B8=8D=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/RISCv64/RISCv64Backend.cpp | 159 +++++++++---------- src/include/backend/RISCv64/RISCv64Backend.h | 2 +- 2 files changed, 75 insertions(+), 86 deletions(-) diff --git a/src/backend/RISCv64/RISCv64Backend.cpp b/src/backend/RISCv64/RISCv64Backend.cpp index ca82458..8dc2d92 100644 --- a/src/backend/RISCv64/RISCv64Backend.cpp +++ b/src/backend/RISCv64/RISCv64Backend.cpp @@ -198,10 +198,6 @@ std::string RISCv64CodeGen::module_gen() { } std::string RISCv64CodeGen::function_gen(Function* func) { - DEBUG = 0; - DEEPDEBUG = 0; - // === 完整的后端处理流水线 === - // 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) RISCv64ISel isel; std::unique_ptr mfunc = isel.runOnFunction(func); @@ -214,9 +210,8 @@ std::string RISCv64CodeGen::function_gen(Function* func) { std::cerr << "====== Intermediate Representation after Instruction Selection ======\n" << ss_after_isel.str(); } - + // 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移) - // 这个Pass必须在寄存器分配之前运行 EliminateFrameIndicesPass efi_pass; efi_pass.runOnMachineFunction(mfunc.get()); @@ -229,89 +224,83 @@ std::string RISCv64CodeGen::function_gen(Function* func) { << ss_after_eli.str(); } - // // 阶段 2: 除法强度削弱优化 (Division Strength Reduction) - // DivStrengthReduction div_strength_reduction; - // div_strength_reduction.runOnMachineFunction(mfunc.get()); + // 阶段 2.1: 除法强度削弱优化 (Division Strength Reduction) + DivStrengthReduction div_strength_reduction; + div_strength_reduction.runOnMachineFunction(mfunc.get()); - // // 阶段 2.1: 指令调度 (Instruction Scheduling) - // PreRA_Scheduler scheduler; - // scheduler.runOnMachineFunction(mfunc.get()); + // 阶段 2.2: 指令调度 (Instruction Scheduling) + PreRA_Scheduler scheduler; + scheduler.runOnMachineFunction(mfunc.get()); // 阶段 3: 物理寄存器分配 (Register Allocation) - // 首先尝试图着色分配器 - // int fooo = 0; - int fooo = 1; - // DEBUG = 1; - // DEEPDEBUG = 1; - if (fooo) { - RISCv64SimpleRegAlloc simple_alloc(mfunc.get()); - simple_alloc.run(); - DEBUG = 0; - DEEPDEBUG = 0; - } else - {if (DEBUG) std::cerr << "Attempting Register Allocation with Graph Coloring...\n"; - if (!gc_failed) { - RISCv64RegAlloc gc_alloc(mfunc.get()); - - bool success_gc = gc_alloc.run(); - - if (!success_gc) { - gc_failed = 1; // 后续不再尝试图着色分配器 - std::cerr << "Warning: Graph coloring register allocation failed function '" - << func->getName() - << "'. Switching to Linear Scan allocator." - << std::endl; - - RISCv64ISel isel_gc_fallback; - mfunc = isel_gc_fallback.runOnFunction(func); - EliminateFrameIndicesPass efi_pass_gc_fallback; - efi_pass_gc_fallback.runOnMachineFunction(mfunc.get()); - RISCv64LinearScan ls_alloc(mfunc.get()); - bool success = ls_alloc.run(); - if (!success) { - // 如果线性扫描最终失败,则调用基本块分配器作为终极后备 - std::cerr << "Info: Linear Scan failed. Switching to Basic Block Allocator as final fallback.\n"; - - // 注意:我们需要在一个“干净”的MachineFunction上运行。 - // 最安全的方式是重新运行指令选择。 - RISCv64ISel isel_fallback; - mfunc = isel_fallback.runOnFunction(func); - EliminateFrameIndicesPass efi_pass_fallback; - efi_pass_fallback.runOnMachineFunction(mfunc.get()); - if (DEBUG) { - std::cerr << "====== stack info after reg alloc ======\n"; - } - RISCv64BasicBlockAlloc bb_alloc(mfunc.get()); - bb_alloc.run(); - } + bool allocation_succeeded = false; + // 尝试迭代图着色 (IRC) + if (!irc_failed) { + if (DEBUG) std::cerr << "Attempting Register Allocation with Iterated Register Coloring (IRC)...\n"; + RISCv64RegAlloc irc_alloc(mfunc.get()); + if (irc_alloc.run()) { + allocation_succeeded = true; + if (DEBUG) std::cerr << "IRC allocation succeeded.\n"; } else { - // 图着色成功完成 - if (DEBUG) std::cerr << "Graph Coloring allocation completed successfully.\n"; + std::cerr << "Warning: IRC failed for function '" << func->getName() + << "'. Blacklisting IRC for subsequent functions and falling back.\n"; + irc_failed = true; // 拉黑IRC,后续函数不再尝试 } - } else { - std::cerr << "Info: Graph Coloring allocation failed in last function. Switching to Linear Scan allocator...\n"; - RISCv64LinearScan ls_alloc(mfunc.get()); - bool success = ls_alloc.run(); - if (!success) { - // 如果线性扫描最终失败,则调用基本块分配器作为终极后备 - std::cerr << "Info: Linear Scan failed. Switching to Basic Block Allocator as final fallback.\n"; - - // 注意:我们需要在一个“干净”的MachineFunction上运行。 - // 最安全的方式是重新运行指令选择。 - RISCv64ISel isel_fallback; - mfunc = isel_fallback.runOnFunction(func); - EliminateFrameIndicesPass efi_pass_fallback; - efi_pass_fallback.runOnMachineFunction(mfunc.get()); - if (DEBUG) { - std::cerr << "====== stack info after reg alloc ======\n"; - } - RISCv64BasicBlockAlloc bb_alloc(mfunc.get()); - bb_alloc.run(); - } - }} - + } + // 尝试简单图着色 (SGC) 并设置超时 + if (!allocation_succeeded) { + // 如果是从IRC失败回退过来的,需要重新创建干净的mfunc和ISel + RISCv64ISel isel_for_sgc; + if (irc_failed) { + if (DEBUG) std::cerr << "Info: Resetting MachineFunction for SGC attempt.\n"; + mfunc = isel_for_sgc.runOnFunction(func); + EliminateFrameIndicesPass efi_pass_for_sgc; + efi_pass_for_sgc.runOnMachineFunction(mfunc.get()); + } + + if (DEBUG) std::cerr << "Attempting Register Allocation with Simple Graph Coloring (SGC)...\n"; + + bool sgc_completed_in_time = false; + { + RISCv64SimpleRegAlloc sgc_alloc(mfunc.get()); + auto future = std::async(std::launch::async, &RISCv64SimpleRegAlloc::run, &sgc_alloc); + std::future_status status = future.wait_for(std::chrono::seconds(20)); + + if (status == std::future_status::ready) { + try { + future.get(); // 检查是否有异常 + sgc_completed_in_time = true; + if (DEBUG) std::cerr << "SGC allocation completed successfully within the time limit.\n"; + } catch (const std::exception& e) { + std::cerr << "Error: SGC allocation threw an exception: " << e.what() << std::endl; + } + } + } + + if (sgc_completed_in_time) { + allocation_succeeded = true; + } else { + std::cerr << "Warning: SGC allocation timed out or failed for function '" << func->getName() + << "'. Falling back.\n"; + } + } + + // 策略三:如果以上所有策略都失败了,则使用基本块分配器 (BBA) + if (!allocation_succeeded) { + // 为BBA准备干净的mfunc和ISel + std::cerr << "Info: Resetting MachineFunction for BBA fallback.\n"; + RISCv64ISel isel_for_bba; + mfunc = isel_for_bba.runOnFunction(func); + EliminateFrameIndicesPass efi_pass_for_bba; + efi_pass_for_bba.runOnMachineFunction(mfunc.get()); + + std::cerr << "Info: Using Basic Block Allocator as final fallback.\n"; + RISCv64BasicBlockAlloc bb_alloc(mfunc.get()); + bb_alloc.run(); + } + if (DEBUG) { std::cerr << "====== stack info after reg alloc ======\n"; mfunc->dumpStackFrameInfo(std::cerr); @@ -326,9 +315,9 @@ std::string RISCv64CodeGen::function_gen(Function* func) { mfunc->dumpStackFrameInfo(std::cerr); } - // // 阶段 4: 窥孔优化 (Peephole Optimization) - // PeepholeOptimizer peephole; - // peephole.runOnMachineFunction(mfunc.get()); + // 阶段 4: 窥孔优化 (Peephole Optimization) + PeepholeOptimizer peephole; + peephole.runOnMachineFunction(mfunc.get()); // 阶段 5: 局部指令调度 (Local Scheduling) PostRA_Scheduler local_scheduler; diff --git a/src/include/backend/RISCv64/RISCv64Backend.h b/src/include/backend/RISCv64/RISCv64Backend.h index 28458c9..8f02e5b 100644 --- a/src/include/backend/RISCv64/RISCv64Backend.h +++ b/src/include/backend/RISCv64/RISCv64Backend.h @@ -26,7 +26,7 @@ private: unsigned getTypeSizeInBytes(Type* type); Module* module; - bool gc_failed = false; + bool irc_failed = false; }; } // namespace sysy