[backend]引入后端pass管理器
This commit is contained in:
@ -31,6 +31,7 @@ add_executable(sysyc
|
||||
RISCv64ISel.cpp
|
||||
RISCv64RegAlloc.cpp
|
||||
RISCv64AsmPrinter.cpp
|
||||
RISCv64Passes.cpp
|
||||
)
|
||||
|
||||
# 设置 include 路径,包含 ANTLR 运行时库和项目头文件
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "RISCv64ISel.h"
|
||||
#include "RISCv64RegAlloc.h"
|
||||
#include "RISCv64AsmPrinter.h"
|
||||
#include "RISCv64Passes.h" // 包含优化Pass的头文件
|
||||
#include <sstream>
|
||||
|
||||
namespace sysy {
|
||||
@ -11,7 +12,7 @@ std::string RISCv64CodeGen::code_gen() {
|
||||
return module_gen();
|
||||
}
|
||||
|
||||
// 模块级代码生成 (移植自原文件,处理.data段和驱动函数生成)
|
||||
// 模块级代码生成
|
||||
std::string RISCv64CodeGen::module_gen() {
|
||||
std::stringstream ss;
|
||||
|
||||
@ -52,17 +53,31 @@ std::string RISCv64CodeGen::module_gen() {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// function_gen 现在是新的、模块化的处理流水线
|
||||
// function_gen 现在是包含具体优化名称的、完整的处理流水线
|
||||
std::string RISCv64CodeGen::function_gen(Function* func) {
|
||||
// === 完整的后端处理流水线 ===
|
||||
|
||||
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
|
||||
RISCv64ISel isel;
|
||||
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
|
||||
|
||||
// 阶段 2: 寄存器分配 (包含栈帧布局, 活跃性分析, 图着色, spill/rewrite)
|
||||
// 阶段 2: 指令调度 (Instruction Scheduling)
|
||||
PreRA_Scheduler scheduler;
|
||||
scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 3: 物理寄存器分配 (Register Allocation)
|
||||
RISCv64RegAlloc reg_alloc(mfunc.get());
|
||||
reg_alloc.run();
|
||||
|
||||
// 阶段 3: 代码发射 (LLIR with physical regs -> Assembly Text)
|
||||
// 阶段 4: 窥孔优化 (Peephole Optimization)
|
||||
PeepholeOptimizer peephole;
|
||||
peephole.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 5: 局部指令调度 (Local Scheduling)
|
||||
PostRA_Scheduler local_scheduler;
|
||||
local_scheduler.runOnMachineFunction(mfunc.get());
|
||||
|
||||
// 阶段 6: 代码发射 (Code Emission)
|
||||
std::stringstream ss;
|
||||
RISCv64AsmPrinter printer(mfunc.get());
|
||||
printer.run(ss);
|
||||
|
||||
@ -1,8 +1,54 @@
|
||||
// RISCv64Passes.cpp
|
||||
#include "RISCv64Passes.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 此处为未来优化Pass的实现
|
||||
// --- 寄存器分配前优化 ---
|
||||
|
||||
void PreRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
// TODO: 在此实现寄存器分配前的指令调度。
|
||||
// 遍历mfunc中的每一个MachineBasicBlock。
|
||||
// 对每个基本块内的MachineInstr列表进行重排。
|
||||
//
|
||||
// 实现思路:
|
||||
// 1. 分析每个基本块内指令的数据依赖关系,构建依赖图(DAG)。
|
||||
// 2. 根据目标处理器的流水线特性(指令延迟等),使用列表调度等算法对指令进行重排。
|
||||
// 3. 此时操作的是虚拟寄存器,只存在真依赖,调度自由度最大。
|
||||
//
|
||||
// std::cout << "Running Pre-RA Instruction Scheduler..." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// --- 寄存器分配后优化 ---
|
||||
|
||||
void PeepholeOptimizer::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
// TODO: 在此实现窥孔优化。
|
||||
// 遍历mfunc中的每一个MachineBasicBlock。
|
||||
// 对每个基本块内的MachineInstr列表进行扫描和替换。
|
||||
//
|
||||
// 实现思路:
|
||||
// 1. 维护一个大小固定(例如3-5条指令)的滑动窗口。
|
||||
// 2. 识别特定的冗余模式,例如:
|
||||
// - `mv a0, a1` 后紧跟 `mv a1, a0` (可消除的交换)
|
||||
// - `sw t0, 12(s0)` 后紧跟 `lw t1, 12(s0)` (冗余加载)
|
||||
// - 强度削减: `mul x, x, 2` -> `slli x, x, 1`
|
||||
// 3. 识别后,直接修改MachineInstr列表(删除、替换或插入指令)。
|
||||
//
|
||||
// std::cout << "Running Post-RA Peephole Optimizer..." << std::endl;
|
||||
}
|
||||
|
||||
void PostRA_Scheduler::runOnMachineFunction(MachineFunction* mfunc) {
|
||||
// TODO: 在此实现寄存器分配后的局部指令调度。
|
||||
// 遍历mfunc中的每一个MachineBasicBlock。
|
||||
// 重点关注由寄存器分配器插入的spill/fill代码。
|
||||
//
|
||||
// 实现思路:
|
||||
// 1. 识别出用于spill/fill的lw/sw指令。
|
||||
// 2. 在不违反数据依赖(包括物理寄存器引入的伪依赖)的前提下,
|
||||
// 尝试将lw指令向上移动,使其与使用它的指令之间有足够的距离,以隐藏访存延迟。
|
||||
// 3. 同样,可以尝试将sw指令向下移动。
|
||||
//
|
||||
// std::cout << "Running Post-RA Local Scheduler..." << std::endl;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -1,4 +1,3 @@
|
||||
// RISCv64Passes.h
|
||||
#ifndef RISCV64_PASSES_H
|
||||
#define RISCV64_PASSES_H
|
||||
|
||||
@ -6,12 +5,56 @@
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 此处为未来优化Pass的基类或独立类定义
|
||||
// 例如:
|
||||
// class PeepholeOptimizer {
|
||||
// public:
|
||||
// void runOnMachineFunction(MachineFunction* mfunc);
|
||||
// };
|
||||
/**
|
||||
* @class Pass
|
||||
* @brief 所有优化Pass的抽象基类 (可选,但推荐)
|
||||
* * 定义一个通用的接口,所有优化都应该实现它。
|
||||
*/
|
||||
class Pass {
|
||||
public:
|
||||
virtual ~Pass() = default;
|
||||
virtual void runOnMachineFunction(MachineFunction* mfunc) = 0;
|
||||
};
|
||||
|
||||
|
||||
// --- 寄存器分配前优化 ---
|
||||
|
||||
/**
|
||||
* @class PreRA_Scheduler
|
||||
* @brief 寄存器分配前的指令调度器
|
||||
* * 在虚拟寄存器上进行操作,此时调度自由度最大,
|
||||
* 主要目标是隐藏指令延迟,提高流水线效率。
|
||||
*/
|
||||
class PreRA_Scheduler : public Pass {
|
||||
public:
|
||||
void runOnMachineFunction(MachineFunction* mfunc) override;
|
||||
};
|
||||
|
||||
|
||||
// --- 寄存器分配后优化 ---
|
||||
|
||||
/**
|
||||
* @class PeepholeOptimizer
|
||||
* @brief 窥孔优化器
|
||||
* * 在已分配物理寄存器的指令流上,通过一个小的滑动窗口来查找
|
||||
* 并替换掉一些冗余或低效的指令模式。
|
||||
*/
|
||||
class PeepholeOptimizer : public Pass {
|
||||
public:
|
||||
void runOnMachineFunction(MachineFunction* mfunc) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PostRA_Scheduler
|
||||
* @brief 寄存器分配后的局部指令调度器
|
||||
* * 主要目标是优化寄存器分配器插入的spill/fill代码(lw/sw),
|
||||
* 尝试将加载指令提前,以隐藏其访存延迟。
|
||||
*/
|
||||
class PostRA_Scheduler : public Pass {
|
||||
public:
|
||||
void runOnMachineFunction(MachineFunction* mfunc) override;
|
||||
};
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ TESTDATA_DIR="${SCRIPT_DIR}/../testdata"
|
||||
BUILD_BIN_DIR="${SCRIPT_DIR}/../build/bin"
|
||||
LIB_DIR="${SCRIPT_DIR}/../lib"
|
||||
# TMP_DIR="${SCRIPT_DIR}/tmp"
|
||||
TMP_DIR="/home/ladev987/paraComp/debug/share_folder/tmp"
|
||||
TMP_DIR="${SCRIPT_DIR}/tmp"
|
||||
|
||||
# 定义编译器和模拟器
|
||||
SYSYC="${BUILD_BIN_DIR}/sysyc"
|
||||
|
||||
Reference in New Issue
Block a user