Compare commits

...

43 Commits

Author SHA1 Message Date
Lixuanwang
ba7c581da5 Merge branch 'backend' into deploy-20250804 2025-08-04 21:58:51 +08:00
Lixuanwang
f7f1cf2b41 [backend]浮点逻辑与gcc保持一致 2025-08-04 21:54:24 +08:00
Lixuanwang
881c2a9723 [backend]强化了线性扫描逻辑 2025-08-04 19:28:15 +08:00
Lixuanwang
b5f14d9385 [backend]在后端主函数中添加了调试逻辑 2025-08-04 18:17:09 +08:00
Lixuanwang
72b06c67ca [backend]为图着色引入保底修复 2025-08-04 18:13:09 +08:00
Lixuanwang
f4ba1df93b Merge branch 'backend' into deploy-20250804 2025-08-04 16:50:57 +08:00
Lixuanwang
4db3cc3fb5 Merge branch 'midend' into backend 2025-08-04 16:48:30 +08:00
Lixuanwang
17f1bed310 Merge branch 'backend-lag' into backend 2025-08-04 16:43:43 +08:00
rain2133
b848ffca5a [midend]在生成IR时引进了简单的CSE(二元一元loadgep的cse) 2025-08-04 16:38:12 +08:00
Lixuanwang
603506d142 Merge branch 'backend' of gitee.com:lixuanwang/mysysy into backend 2025-08-04 16:34:22 +08:00
Lixuanwang
0179c13cf4 [backend]添加了一些工具函数 2025-08-04 16:32:54 +08:00
7e5f6800b7 [backend]修复寄存器分配算法死循环bug,89通过 2025-08-04 16:04:35 +08:00
Lixuanwang
64ba25a77e [backend]移除了冗余的keepalive伪指令 2025-08-04 14:11:27 +08:00
Lixuanwang
6dc74b173b [deploy]部署版本4 2025-08-04 02:42:55 +08:00
Lixuanwang
208d5528b5 Merge branch 'midend' into backend 2025-08-04 02:37:27 +08:00
Lixuanwang
a269366ac5 [backend]修复了较小全零全局数组未显示初始化导致未定义行为的问题 2025-08-04 02:31:18 +08:00
Lixuanwang
1b9a7a4827 [backend]修复了函数序言处理错误且与尾声栈不匹配的bug 2025-08-04 01:57:34 +08:00
b2c2f3289d [backend]修改了编译器后端 RISCv64ISel.cpp,在 kFtoI 的处理逻辑中,用一段指令序列模拟了正确的“向零取整”行为。95 h35 h37 h38通过。 2025-08-04 01:35:26 +08:00
0ecd47f0ac 修复IR打印器中浮点比较指令的类型错误,确保生成正确的LLVM IR代码 2025-08-04 01:35:26 +08:00
6550c8a25b [backend-LAG]添加新的LargeArrayToGlobal中端Pass,以及栈保护逻辑 2025-08-04 01:01:29 +08:00
rain2133
f24cc7ec88 [midend]修复replaceAllUsesWith中由于setOperand 间接调用 removeUse 或 addUse导致的迭代器失效问题 2025-08-04 00:59:39 +08:00
Lixuanwang
c8a8bf9a37 [backend]修复了溢出位置错误的问题 2025-08-03 23:28:38 +08:00
rain2133
446a6a6fcb [midend]修复phi指令接口,优化遍适配 2025-08-03 22:18:00 +08:00
rain2133
d8b004e5e5 [midend]修改use关系相关的函数,使其能自动的正确维护,修改了phi指令的各种接口 2025-08-03 22:16:40 +08:00
Lixuanwang
cd814de495 Merge commit 'e4ad23a1a594a9da6b96655d4256352d5f6d277d' into midend 2025-08-03 18:37:36 +08:00
Lixuanwang
e4ad23a1a5 [backend]修复了寄存器分配器在处理全物理寄存器操作数时的bug 2025-08-03 18:37:08 +08:00
Lixuanwang
58c8cd53f5 Merge branch 'midend' of gitee.com:lixuanwang/mysysy into midend 2025-08-03 17:26:38 +08:00
Lixuanwang
ec91a4e259 [backend]更新脚本,现在会拷贝.sy文件到tmp目录 2025-08-03 17:26:09 +08:00
rain2133
91f755959b [midend]修改中端流水线 2025-08-03 17:25:05 +08:00
Lixuanwang
92c89f7616 [midend]修正了脚本错误 2025-08-03 17:12:39 +08:00
Lixuanwang
66047dc6a3 Merge branch 'buildcfg' into midend 2025-08-03 16:40:48 +08:00
rain2133
22cf18a1d6 [midend-BuildCFG]修复逻辑 2025-08-03 16:14:31 +08:00
Lixuanwang
19a433c94f [midend]为脚本添加了-O1参数,支持测试性能 2025-08-03 15:41:29 +08:00
Lixuanwang
45dfbc8d59 Merge branch 'backend' into midend 2025-08-03 15:25:51 +08:00
Lixuanwang
f8e423f579 合并backend、backend-IRC到midend 2025-08-03 15:18:52 +08:00
Lixuanwang
5b43f208ac Merge branch 'backend-divopt' into midend 2025-08-03 14:53:22 +08:00
Lixuanwang
845f969c2e [backend-IRC]修复了现场管理与溢出处理的栈偏移量错误问题 2025-08-03 14:42:19 +08:00
9c5d9ea78c [optimize]删除多余测试文件 2025-08-03 14:38:27 +08:00
0ce742a86e [optimize]添加更为通用的除法强度削减Pass, 不受除数限制替换div指令,不影响当前分数 2025-08-03 14:37:33 +08:00
f312792fe9 [optimze]添加基础的除法指令优化,目前只对除以2的幂数生效 2025-08-03 13:46:42 +08:00
rain2133
32ea24df56 [midend]修复entryBB和funcBodyEntry的初始化,Dom计算引进逆后续遍历和LT算法,Pass先默认关掉CFGOpt 2025-08-03 00:51:49 +08:00
歪比歪比
a1cf60c420 [midend-BuildCFG]新增BuildCFG优化通道,实现控制流图的构建与分析 2025-08-02 22:48:21 +08:00
Lixuanwang
f879a0f521 [midend]修复了后端不适配中端全局变量定义的问题 2025-08-02 22:06:37 +08:00
560 changed files with 2592 additions and 708122 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 KiB

View File

@@ -1,169 +0,0 @@
这个头文件定义了一个用于生成中间表示IR的数据结构主要用于编译器前端将抽象语法树AST转换为中间代码。以下是文件中定义的主要类和功能的整理和解释
---
### **1. 类型系统Type System**
#### **1.1 `Type` 类**
- **作用**:表示所有基本标量类型(如 `int``float``void` 等)以及指针类型和函数类型。
- **成员**
- `Kind` 枚举:表示类型的种类(如 `kInt``kFloat``kPointer` 等)。
- `kind`:当前类型的种类。
- 构造函数:`Type(Kind kind)`,用于初始化类型。
- 静态方法:如 `getIntType()``getFloatType()` 等,用于获取特定类型的单例对象。
- 类型检查方法:如 `isInt()``isFloat()` 等,用于检查当前类型是否为某种类型。
- `getSize()`:获取类型的大小。
- `as<T>()`:将当前类型动态转换为派生类(如 `PointerType``FunctionType`)。
#### **1.2 `PointerType` 类**
- **作用**:表示指针类型,派生自 `Type`
- **成员**
- `baseType`:指针指向的基础类型。
- 静态方法:`get(Type *baseType)`,用于获取指向 `baseType` 的指针类型。
- `getBaseType()`:获取指针指向的基础类型。
#### **1.3 `FunctionType` 类**
- **作用**:表示函数类型,派生自 `Type`
- **成员**
- `returnType`:函数的返回类型。
- `paramTypes`:函数的参数类型列表。
- 静态方法:`get(Type *returnType, const std::vector<Type *> &paramTypes)`,用于获取函数类型。
- `getReturnType()`:获取函数的返回类型。
- `getParamTypes()`:获取函数的参数类型列表。
---
### **2. 中间表示IR**
#### **2.1 `Value` 类**
- **作用**:表示 IR 中的所有值(如指令、常量、参数等)。
- **成员**
- `Kind` 枚举:表示值的种类(如 `kAdd``kSub``kConstant` 等)。
- `kind`:当前值的种类。
- `type`:值的类型。
- `name`:值的名称。
- `uses`:值的用途列表(表示哪些指令使用了该值)。
- 构造函数:`Value(Kind kind, Type *type, const std::string &name)`
- 类型检查方法:如 `isInt()``isFloat()` 等。
- `getUses()`:获取值的用途列表。
- `replaceAllUsesWith(Value *value)`:将该值的所有用途替换为另一个值。
- `print(std::ostream &os)`:打印值的表示。
#### **2.2 `ConstantValue` 类**
- **作用**:表示编译时常量(如整数常量、浮点数常量)。
- **成员**
- `iScalar``fScalar`:分别存储整数和浮点数常量的值。
- 静态方法:`get(int value)``get(float value)`,用于获取常量值。
- `getInt()``getFloat()`:获取常量的值。
#### **2.3 `Argument` 类**
- **作用**:表示函数或基本块的参数。
- **成员**
- `block`:参数所属的基本块。
- `index`:参数的索引。
- 构造函数:`Argument(Type *type, BasicBlock *block, int index, const std::string &name)`
- `getParent()`:获取参数所属的基本块。
- `getIndex()`:获取参数的索引。
#### **2.4 `BasicBlock` 类**
- **作用**:表示基本块,包含一系列指令。
- **成员**
- `parent`:基本块所属的函数。
- `instructions`:基本块中的指令列表。
- `arguments`:基本块的参数列表。
- `successors``predecessors`:基本块的后继和前驱列表。
- 构造函数:`BasicBlock(Function *parent, const std::string &name)`
- `getParent()`:获取基本块所属的函数。
- `getInstructions()`:获取基本块中的指令列表。
- `createArgument()`:为基本块创建一个参数。
#### **2.5 `Instruction` 类**
- **作用**:表示 IR 中的指令,派生自 `User`
- **成员**
- `Kind` 枚举:表示指令的种类(如 `kAdd``kSub``kLoad` 等)。
- `kind`:当前指令的种类。
- `parent`:指令所属的基本块。
- 构造函数:`Instruction(Kind kind, Type *type, BasicBlock *parent, const std::string &name)`
- `getParent()`:获取指令所属的基本块。
- `getFunction()`:获取指令所属的函数。
- 指令分类方法:如 `isBinary()``isUnary()``isMemory()` 等。
#### **2.6 `User` 类**
- **作用**:表示使用其他值的指令或全局值,派生自 `Value`
- **成员**
- `operands`:指令的操作数列表。
- 构造函数:`User(Kind kind, Type *type, const std::string &name)`
- `getOperand(int index)`:获取指定索引的操作数。
- `addOperand(Value *value)`:添加一个操作数。
- `replaceOperand(int index, Value *value)`:替换指定索引的操作数。
#### **2.7 具体指令类**
- **`CallInst`**:表示函数调用指令。
- **`UnaryInst`**:表示一元操作指令(如取反、类型转换)。
- **`BinaryInst`**:表示二元操作指令(如加法、减法)。
- **`ReturnInst`**:表示返回指令。
- **`UncondBrInst`**:表示无条件跳转指令。
- **`CondBrInst`**:表示条件跳转指令。
- **`AllocaInst`**:表示栈内存分配指令。
- **`LoadInst`**:表示从内存加载值的指令。
- **`StoreInst`**:表示将值存储到内存的指令。
---
### **3. 模块和函数**
#### **3.1 `Function` 类**
- **作用**:表示函数,包含多个基本块。
- **成员**
- `parent`:函数所属的模块。
- `blocks`:函数中的基本块列表。
- 构造函数:`Function(Module *parent, Type *type, const std::string &name)`
- `getReturnType()`:获取函数的返回类型。
- `getParamTypes()`:获取函数的参数类型列表。
- `addBasicBlock()`:为函数添加一个基本块。
#### **3.2 `GlobalValue` 类**
- **作用**:表示全局变量或常量。
- **成员**
- `parent`:全局值所属的模块。
- `hasInit`:是否有初始化值。
- `isConst`:是否是常量。
- 构造函数:`GlobalValue(Module *parent, Type *type, const std::string &name, const std::vector<Value *> &dims, Value *init)`
- `init()`:获取全局值的初始化值。
#### **3.3 `Module` 类**
- **作用**:表示整个编译单元(如一个源文件)。
- **成员**
- `children`:模块中的所有值(如函数、全局变量)。
- `functions`:模块中的函数列表。
- `globals`:模块中的全局变量列表。
- `createFunction()`:创建一个函数。
- `createGlobalValue()`:创建一个全局变量。
- `getFunction()`:获取指定名称的函数。
- `getGlobalValue()`:获取指定名称的全局变量。
---
### **4. 工具类**
#### **4.1 `Use` 类**
- **作用**:表示值与其使用者之间的关系。
- **成员**
- `index`:值在使用者操作数列表中的索引。
- `user`:使用者。
- `value`:被使用的值。
- 构造函数:`Use(int index, User *user, Value *value)`
- `getValue()`:获取被使用的值。
#### **4.2 `range` 类**
- **作用**:封装迭代器对 `[begin, end)`,用于遍历容器。
- **成员**
- `begin()``end()`:返回范围的起始和结束迭代器。
- `size()`:返回范围的大小。
- `empty()`:判断范围是否为空。
---
### **5. 总结**
- **类型系统**`Type``PointerType``FunctionType` 用于表示 IR 中的类型。
- **中间表示**`Value``ConstantValue``Instruction` 等用于表示 IR 中的值和指令。
- **模块和函数**`Module``Function``GlobalValue` 用于组织 IR 的结构。
- **工具类**`Use``range` 用于辅助实现 IR 的数据结构和遍历。
这个头文件定义了一个完整的 IR 数据结构,适用于编译器前端将 AST 转换为中间代码,并支持后续的优化和目标代码生成。

View File

@@ -1,156 +0,0 @@
`IRBuilder.h` 文件定义了一个 `IRBuilder`用于简化中间表示IR的构建过程。`IRBuilder` 提供了创建各种 IR 指令的便捷方法,并将这些指令插入到指定的基本块中。以下是对文件中主要内容的整理和解释:
---
### **1. `IRBuilder` 类的作用**
`IRBuilder` 是一个工具类用于在生成中间表示IR时简化指令的创建和插入操作。它的主要功能包括
- 提供创建各种 IR 指令的工厂方法。
- 将创建的指令插入到指定的基本块中。
- 支持在基本块的任意位置插入指令。
---
### **2. 主要成员**
#### **2.1 成员变量**
- **`block`**:当前操作的基本块。
- **`position`**:当前操作的插入位置(基本块中的迭代器)。
#### **2.2 构造函数**
- **默认构造函数**`IRBuilder()`
- **带参数的构造函数**
- `IRBuilder(BasicBlock *block)`:初始化 `IRBuilder`,并设置当前基本块和插入位置(默认在基本块末尾)。
- `IRBuilder(BasicBlock *block, BasicBlock::iterator position)`:初始化 `IRBuilder`,并设置当前基本块和插入位置。
#### **2.3 设置方法**
- **`setPosition(BasicBlock *block, BasicBlock::iterator position)`**:设置当前基本块和插入位置。
- **`setPosition(BasicBlock::iterator position)`**:设置当前插入位置。
#### **2.4 获取方法**
- **`getBasicBlock()`**:获取当前基本块。
- **`getPosition()`**:获取当前插入位置。
---
### **3. 指令创建方法**
`IRBuilder` 提供了多种工厂方法,用于创建不同类型的 IR 指令。这些方法会将创建的指令插入到当前基本块的指定位置。
#### **3.1 函数调用指令**
- **`createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name)`**
- 创建一个函数调用指令。
- 参数:
- `callee`:被调用的函数。
- `args`:函数参数列表。
- `name`:指令的名称(可选)。
- 返回:`CallInst*`
#### **3.2 一元操作指令**
- **`createUnaryInst(Instruction::Kind kind, Type *type, Value *operand, const std::string &name)`**
- 创建一个一元操作指令(如取反、类型转换)。
- 参数:
- `kind`:指令的类型(如 `kNeg``kFtoI` 等)。
- `type`:指令的结果类型。
- `operand`:操作数。
- `name`:指令的名称(可选)。
- 返回:`UnaryInst*`
- **具体一元操作指令**
- `createNegInst(Value *operand, const std::string &name)`:创建整数取反指令。
- `createNotInst(Value *operand, const std::string &name)`:创建逻辑取反指令。
- `createFtoIInst(Value *operand, const std::string &name)`:创建浮点数转整数指令。
- `createFNegInst(Value *operand, const std::string &name)`:创建浮点数取反指令。
- `createIToFInst(Value *operand, const std::string &name)`:创建整数转浮点数指令。
#### **3.3 二元操作指令**
- **`createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs, Value *rhs, const std::string &name)`**
- 创建一个二元操作指令(如加法、减法)。
- 参数:
- `kind`:指令的类型(如 `kAdd``kSub` 等)。
- `type`:指令的结果类型。
- `lhs``rhs`:左操作数和右操作数。
- `name`:指令的名称(可选)。
- 返回:`BinaryInst*`
- **具体二元操作指令**
- 整数运算:
- `createAddInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数加法指令。
- `createSubInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数减法指令。
- `createMulInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数乘法指令。
- `createDivInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数除法指令。
- `createRemInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数取余指令。
- 整数比较:
- `createICmpEQInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数相等比较指令。
- `createICmpNEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数不等比较指令。
- `createICmpLTInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数小于比较指令。
- `createICmpLEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数小于等于比较指令。
- `createICmpGTInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数大于比较指令。
- `createICmpGEInst(Value *lhs, Value *rhs, const std::string &name)`:创建整数大于等于比较指令。
- 浮点数运算:
- `createFAddInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数加法指令。
- `createFSubInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数减法指令。
- `createFMulInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数乘法指令。
- `createFDivInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数除法指令。
- `createFRemInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数取余指令。
- 浮点数比较:
- `createFCmpEQInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数相等比较指令。
- `createFCmpNEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数不等比较指令。
- `createFCmpLTInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数小于比较指令。
- `createFCmpLEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数小于等于比较指令。
- `createFCmpGTInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数大于比较指令。
- `createFCmpGEInst(Value *lhs, Value *rhs, const std::string &name)`:创建浮点数大于等于比较指令。
#### **3.4 控制流指令**
- **`createReturnInst(Value *value)`**
- 创建返回指令。
- 参数:
- `value`:返回值(可选)。
- 返回:`ReturnInst*`
- **`createUncondBrInst(BasicBlock *block, std::vector<Value *> args)`**
- 创建无条件跳转指令。
- 参数:
- `block`:目标基本块。
- `args`:跳转参数(可选)。
- 返回:`UncondBrInst*`
- **`createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock, const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs)`**
- 创建条件跳转指令。
- 参数:
- `condition`:跳转条件。
- `thenBlock`:条件为真时的目标基本块。
- `elseBlock`:条件为假时的目标基本块。
- `thenArgs``elseArgs`:跳转参数(可选)。
- 返回:`CondBrInst*`
#### **3.5 内存操作指令**
- **`createAllocaInst(Type *type, const std::vector<Value *> &dims, const std::string &name)`**
- 创建栈内存分配指令。
- 参数:
- `type`:分配的类型。
- `dims`:数组维度(可选)。
- `name`:指令的名称(可选)。
- 返回:`AllocaInst*`
- **`createLoadInst(Value *pointer, const std::vector<Value *> &indices, const std::string &name)`**
- 创建加载指令。
- 参数:
- `pointer`:指针值。
- `indices`:数组索引(可选)。
- `name`:指令的名称(可选)。
- 返回:`LoadInst*`
- **`createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices, const std::string &name)`**
- 创建存储指令。
- 参数:
- `value`:要存储的值。
- `pointer`:指针值。
- `indices`:数组索引(可选)。
- `name`:指令的名称(可选)。
- 返回:`StoreInst*`
---
### **4. 总结**
- `IRBuilder` 是一个用于简化 IR 构建的工具类,提供了创建各种 IR 指令的工厂方法。
- 通过 `IRBuilder`,可以方便地在指定基本块的任意位置插入指令。
- 该类的设计使得 IR 的生成更加模块化和易于维护。

View File

@@ -1,121 +0,0 @@
这个 `IR.cpp` 文件实现了 `IR.h` 中定义的中间表示IR数据结构的功能。它包含了类型系统、值、指令、基本块、函数和模块的具体实现以及一些辅助函数用于打印 IR 的内容。以下是对文件中主要内容的整理和解释:
---
### **1. 辅助函数**
#### **1.1 `interleave` 函数**
- **作用**:用于在输出流中插入分隔符(如逗号)来打印容器中的元素。
- **示例**
```cpp
interleave(os, container, ", ");
```
#### **1.2 打印函数**
- **`printVarName`**:打印变量名,全局变量以 `@` 开头,局部变量以 `%` 开头。
- **`printBlockName`**:打印基本块名,以 `^` 开头。
- **`printFunctionName`**:打印函数名,以 `@` 开头。
- **`printOperand`**:打印操作数,如果是常量则直接打印值,否则打印变量名。
---
### **2. 类型系统**
#### **2.1 `Type` 类的实现**
- **静态方法**
- `getIntType()`、`getFloatType()`、`getVoidType()`、`getLabelType()`:返回对应类型的单例对象。
- `getPointerType(Type *baseType)`:返回指向 `baseType` 的指针类型。
- `getFunctionType(Type *returnType, const vector<Type *> &paramTypes)`:返回函数类型。
- **`getSize()`**:返回类型的大小(如 `int` 和 `float` 为 4 字节,指针为 8 字节)。
- **`print()`**:打印类型的表示。
#### **2.2 `PointerType` 类的实现**
- **静态方法**
- `get(Type *baseType)`:返回指向 `baseType` 的指针类型,使用 `std::map` 缓存已创建的指针类型。
- **`getBaseType()`**:返回指针指向的基础类型。
#### **2.3 `FunctionType` 类的实现**
- **静态方法**
- `get(Type *returnType, const vector<Type *> &paramTypes)`:返回函数类型,使用 `std::set` 缓存已创建的函数类型。
- **`getReturnType()`** 和 `getParamTypes()`:分别返回函数的返回类型和参数类型列表。
---
### **3. 值Value**
#### **3.1 `Value` 类的实现**
- **`replaceAllUsesWith(Value *value)`**:将该值的所有用途替换为另一个值。
- **`isConstant()`**:判断值是否为常量(包括常量值、全局值和函数)。
#### **3.2 `ConstantValue` 类的实现**
- **静态方法**
- `get(int value)``get(float value)`:返回整数或浮点数常量,使用 `std::map` 缓存已创建的常量。
- **`getInt()``getFloat()`**:返回常量的值。
- **`print()`**:打印常量的值。
#### **3.3 `Argument` 类的实现**
- **构造函数**:初始化参数的类型、所属基本块和索引。
- **`print()`**:打印参数的表示。
---
### **4. 基本块BasicBlock**
#### **4.1 `BasicBlock` 类的实现**
- **构造函数**:初始化基本块的名称和所属函数。
- **`print()`**:打印基本块的表示,包括参数和指令。
---
### **5. 指令Instruction**
#### **5.1 `Instruction` 类的实现**
- **构造函数**:初始化指令的类型、所属基本块和名称。
- **`print()`**:由具体指令类实现。
#### **5.2 具体指令类的实现**
- **`CallInst`**:表示函数调用指令。
- **`print()`**:打印函数调用的表示。
- **`UnaryInst`**:表示一元操作指令(如取反、类型转换)。
- **`print()`**:打印一元操作的表示。
- **`BinaryInst`**:表示二元操作指令(如加法、减法)。
- **`print()`**:打印二元操作的表示。
- **`ReturnInst`**:表示返回指令。
- **`print()`**:打印返回指令的表示。
- **`UncondBrInst`**:表示无条件跳转指令。
- **`print()`**:打印无条件跳转的表示。
- **`CondBrInst`**:表示条件跳转指令。
- **`print()`**:打印条件跳转的表示。
- **`AllocaInst`**:表示栈内存分配指令。
- **`print()`**:打印内存分配的表示。
- **`LoadInst`**:表示从内存加载值的指令。
- **`print()`**:打印加载指令的表示。
- **`StoreInst`**:表示将值存储到内存的指令。
- **`print()`**:打印存储指令的表示。
---
### **6. 函数Function**
#### **6.1 `Function` 类的实现**
- **构造函数**:初始化函数的名称、返回类型和参数类型。
- **`print()`**:打印函数的表示,包括基本块和指令。
---
### **7. 模块Module**
#### **7.1 `Module` 类的实现**
- **`print()`**:打印模块的表示,包括所有函数和全局变量。
---
### **8. 用户User**
#### **8.1 `User` 类的实现**
- **`setOperand(int index, Value *value)`**:设置指定索引的操作数。
- **`replaceOperand(int index, Value *value)`**:替换指定索引的操作数,并更新用途列表。
---
### **9. 总结**
- **类型系统**:实现了 `Type``PointerType``FunctionType`,用于表示 IR 中的类型。
- **值**:实现了 `Value``ConstantValue``Argument`,用于表示 IR 中的值和参数。
- **基本块**:实现了 `BasicBlock`,用于组织指令。
- **指令**:实现了多种具体指令类(如 `CallInst``BinaryInst` 等),用于表示 IR 中的操作。
- **函数和模块**:实现了 `Function``Module`,用于组织 IR 的结构。
- **打印功能**:通过 `print()` 方法,可以将 IR 的内容输出为可读的文本格式。
这个文件是编译器中间表示的核心实现能够将抽象语法树AST转换为中间代码并支持后续的优化和目标代码生成。

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -60,11 +60,7 @@ display_file_content() {
# 清理临时文件的函数 # 清理临时文件的函数
clean_tmp() { clean_tmp() {
echo "正在清理临时目录: ${TMP_DIR}" echo "正在清理临时目录: ${TMP_DIR}"
rm -rf "${TMP_DIR}"/*.s \ rm -rf "${TMP_DIR}"/*
"${TMP_DIR}"/*_sysyc_riscv64 \
"${TMP_DIR}"/*_sysyc_riscv64.actual_out \
"${TMP_DIR}"/*_sysyc_riscv64.expected_stdout \
"${TMP_DIR}"/*_sysyc_riscv64.o
echo "清理完成。" echo "清理完成。"
} }

View File

@@ -21,6 +21,7 @@ QEMU_RISCV64="qemu-riscv64"
# --- 初始化变量 --- # --- 初始化变量 ---
EXECUTE_MODE=false EXECUTE_MODE=false
CLEAN_MODE=false CLEAN_MODE=false
OPTIMIZE_FLAG="" # 用于存储 -O1 标志
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒) SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒) GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒) EXEC_TIMEOUT=5 # qemu 自动化执行超时 (秒)
@@ -39,6 +40,7 @@ show_help() {
echo "选项:" echo "选项:"
echo " -e, --executable 编译为可执行文件并运行测试 (必须)。" echo " -e, --executable 编译为可执行文件并运行测试 (必须)。"
echo " -c, --clean 清理 tmp 临时目录下的所有文件。" echo " -c, --clean 清理 tmp 临时目录下的所有文件。"
echo " -O1 启用 sysyc 的 -O1 优化。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。" echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。" echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
echo " -et N 设置 qemu 自动化执行超时为 N 秒 (默认: 5)。" echo " -et N 设置 qemu 自动化执行超时为 N 秒 (默认: 5)。"
@@ -80,6 +82,10 @@ while [[ "$#" -gt 0 ]]; do
CLEAN_MODE=true CLEAN_MODE=true
shift # 消耗选项 shift # 消耗选项
;; ;;
-O1)
OPTIMIZE_FLAG="-O1"
shift # 消耗选项
;;
-sct) -sct)
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then SYSYC_TIMEOUT="$2"; shift 2; else echo "错误: -sct 需要一个正整数参数。" >&2; exit 1; fi
;; ;;
@@ -144,6 +150,7 @@ mkdir -p "${TMP_DIR}"
TOTAL_CASES=${#SY_FILES[@]} TOTAL_CASES=${#SY_FILES[@]}
echo "SysY 单例测试运行器启动..." echo "SysY 单例测试运行器启动..."
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s" echo "超时设置: sysyc=${SYSYC_TIMEOUT}s, gcc=${GCC_TIMEOUT}s, qemu=${EXEC_TIMEOUT}s"
echo "失败输出最大行数: ${MAX_OUTPUT_LINES}" echo "失败输出最大行数: ${MAX_OUTPUT_LINES}"
echo "" echo ""
@@ -173,10 +180,12 @@ for sy_file in "${SY_FILES[@]}"; do
if [ -f "${output_reference_file}" ]; then if [ -f "${output_reference_file}" ]; then
cp "${output_reference_file}" "${TMP_DIR}/$(basename "${output_reference_file}")" cp "${output_reference_file}" "${TMP_DIR}/$(basename "${output_reference_file}")"
fi fi
# 步骤 1: sysyc 编译 # 步骤 1: sysyc 编译
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..." echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" > "${ir_file}" timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" ${OPTIMIZE_FLAG} -o "${assembly_file}"
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s ir "${sy_file}" ${OPTIMIZE_FLAG} > "${ir_file}"
# timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s asmd "${sy_file}" > "${assembly_debug_file}" 2>&1
SYSYC_STATUS=$? SYSYC_STATUS=$?
if [ $SYSYC_STATUS -eq 124 ]; then if [ $SYSYC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR超时\e[0m" echo -e "\e[31m错误: SysY 编译 ${sy_file} IR超时\e[0m"
@@ -185,12 +194,10 @@ for sy_file in "${SY_FILES[@]}"; do
echo -e "\e[31m错误: SysY 编译 ${sy_file} IR失败退出码: ${SYSYC_STATUS}\e[0m" echo -e "\e[31m错误: SysY 编译 ${sy_file} IR失败退出码: ${SYSYC_STATUS}\e[0m"
is_passed=0 is_passed=0
fi fi
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo -e "\e[31m错误: SysY 编译失败或超时。\e[0m" echo -e "\e[31m错误: SysY 编译失败或超时。\e[0m"
is_passed=0 is_passed=0
fi fi
# timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -s asmd "${sy_file}" > "${assembly_debug_file}" 2>&1
# 步骤 2: GCC 编译 # 步骤 2: GCC 编译
if [ "$is_passed" -eq 1 ]; then if [ "$is_passed" -eq 1 ]; then

View File

@@ -16,8 +16,8 @@ SYSYC="${BUILD_BIN_DIR}/sysyc"
GCC_RISCV64="riscv64-linux-gnu-gcc" GCC_RISCV64="riscv64-linux-gnu-gcc"
QEMU_RISCV64="qemu-riscv64" QEMU_RISCV64="qemu-riscv64"
# --- 新增功能: 初始化变量 ---
EXECUTE_MODE=false EXECUTE_MODE=false
OPTIMIZE_FLAG="" # 用于存储 -O1 标志
SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒) SYSYC_TIMEOUT=10 # sysyc 编译超时 (秒)
GCC_TIMEOUT=10 # gcc 编译超时 (秒) GCC_TIMEOUT=10 # gcc 编译超时 (秒)
EXEC_TIMEOUT=5 # qemu 执行超时 (秒) EXEC_TIMEOUT=5 # qemu 执行超时 (秒)
@@ -35,6 +35,7 @@ show_help() {
echo "选项:" echo "选项:"
echo " -e, --executable 编译为可执行文件并运行测试。" echo " -e, --executable 编译为可执行文件并运行测试。"
echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。" echo " -c, --clean 清理 'tmp' 目录下的所有生成文件。"
echo " -O1 启用 sysyc 的 -O1 优化。"
echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。" echo " -set [f|h|p|all]... 指定要运行的测试集 (functional, h_functional, performance)。可多选,默认为 all。"
echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。" echo " -sct N 设置 sysyc 编译超时为 N 秒 (默认: 10)。"
echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。" echo " -gct N 设置 gcc 交叉编译超时为 N 秒 (默认: 10)。"
@@ -85,9 +86,12 @@ while [[ "$#" -gt 0 ]]; do
clean_tmp clean_tmp
exit 0 exit 0
;; ;;
-O1)
OPTIMIZE_FLAG="-O1"
shift
;;
-set) -set)
shift # 移过 '-set' shift # 移过 '-set'
# 消耗所有后续参数直到遇到下一个选项
while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do while [[ "$#" -gt 0 && ! "$1" =~ ^- ]]; do
TEST_SETS+=("$1") TEST_SETS+=("$1")
shift shift
@@ -125,7 +129,6 @@ SET_MAP[p]="performance"
SEARCH_PATHS=() SEARCH_PATHS=()
# 如果未指定测试集,或指定了 'all',则搜索所有目录
if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then if [ ${#TEST_SETS[@]} -eq 0 ] || [[ " ${TEST_SETS[@]} " =~ " all " ]]; then
SEARCH_PATHS+=("${TESTDATA_DIR}") SEARCH_PATHS+=("${TESTDATA_DIR}")
else else
@@ -138,13 +141,13 @@ else
done done
fi fi
# 如果没有有效的搜索路径,则退出
if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then if [ ${#SEARCH_PATHS[@]} -eq 0 ]; then
echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m" echo -e "\e[31m错误: 没有找到有效的测试集目录,测试中止。\e[0m"
exit 1 exit 1
fi fi
echo "SysY 测试运行器启动..." echo "SysY 测试运行器启动..."
if [ -n "$OPTIMIZE_FLAG" ]; then echo "优化等级: ${OPTIMIZE_FLAG}"; fi
echo "输入目录: ${SEARCH_PATHS[@]}" echo "输入目录: ${SEARCH_PATHS[@]}"
echo "临时目录: ${TMP_DIR}" echo "临时目录: ${TMP_DIR}"
echo "执行模式: ${EXECUTE_MODE}" echo "执行模式: ${EXECUTE_MODE}"
@@ -154,7 +157,6 @@ if ${EXECUTE_MODE}; then
fi fi
echo "" echo ""
# 使用构建好的路径查找 .sy 文件并排序
sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V) sy_files=$(find "${SEARCH_PATHS[@]}" -name "*.sy" | sort -V)
if [ -z "$sy_files" ]; then if [ -z "$sy_files" ]; then
echo "在指定目录中未找到任何 .sy 文件。" echo "在指定目录中未找到任何 .sy 文件。"
@@ -162,7 +164,6 @@ if [ -z "$sy_files" ]; then
fi fi
TOTAL_CASES=$(echo "$sy_files" | wc -w) TOTAL_CASES=$(echo "$sy_files" | wc -w)
# --- 修复: 使用 here-string (<<<) 代替管道 (|) 来避免子 shell 问题 ---
while IFS= read -r sy_file; do while IFS= read -r sy_file; do
is_passed=1 # 1 表示通过, 0 表示失败 is_passed=1 # 1 表示通过, 0 表示失败
@@ -176,10 +177,8 @@ while IFS= read -r sy_file; do
output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out" output_actual_file="${TMP_DIR}/${output_base_name}_sysyc_riscv64.actual_out"
echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)" echo "正在处理: $(basename "$sy_file") (路径: ${relative_path_no_ext}.sy)"
# 步骤 1: 使用 sysyc 编译 .sy 到 .s
echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..." echo " 使用 sysyc 编译 (超时 ${SYSYC_TIMEOUT}s)..."
timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}" timeout -s KILL ${SYSYC_TIMEOUT} "${SYSYC}" -S "${sy_file}" -o "${assembly_file}" ${OPTIMIZE_FLAG}
SYSYC_STATUS=$? SYSYC_STATUS=$?
if [ $SYSYC_STATUS -eq 124 ]; then if [ $SYSYC_STATUS -eq 124 ]; then
echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m" echo -e "\e[31m错误: SysY 编译 ${sy_file} 超时\e[0m"
@@ -189,9 +188,7 @@ while IFS= read -r sy_file; do
is_passed=0 is_passed=0
fi fi
# 只有当 EXECUTE_MODE 为 true 且上一步成功时才继续
if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then if ${EXECUTE_MODE} && [ "$is_passed" -eq 1 ]; then
# 步骤 2: 使用 riscv64-linux-gnu-gcc 编译 .s 到可执行文件
echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..." echo " 使用 gcc 编译 (超时 ${GCC_TIMEOUT}s)..."
timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static timeout -s KILL ${GCC_TIMEOUT} "${GCC_RISCV64}" "${assembly_file}" -o "${executable_file}" -L"${LIB_DIR}" -lsysy_riscv -static
GCC_STATUS=$? GCC_STATUS=$?
@@ -213,7 +210,6 @@ while IFS= read -r sy_file; do
continue continue
fi fi
# 步骤 3, 4, 5: 只有当编译都成功时才执行
if [ "$is_passed" -eq 1 ]; then if [ "$is_passed" -eq 1 ]; then
echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..." echo " 正在执行 (超时 ${EXEC_TIMEOUT}s)..."

View File

@@ -5,6 +5,7 @@ add_library(riscv64_backend_lib STATIC
RISCv64ISel.cpp RISCv64ISel.cpp
RISCv64LLIR.cpp RISCv64LLIR.cpp
RISCv64RegAlloc.cpp RISCv64RegAlloc.cpp
RISCv64LinearScan.cpp
Handler/CalleeSavedHandler.cpp Handler/CalleeSavedHandler.cpp
Handler/LegalizeImmediates.cpp Handler/LegalizeImmediates.cpp
Handler/PrologueEpilogueInsertion.cpp Handler/PrologueEpilogueInsertion.cpp
@@ -12,6 +13,7 @@ add_library(riscv64_backend_lib STATIC
Optimize/Peephole.cpp Optimize/Peephole.cpp
Optimize/PostRA_Scheduler.cpp Optimize/PostRA_Scheduler.cpp
Optimize/PreRA_Scheduler.cpp Optimize/PreRA_Scheduler.cpp
Optimize/DivStrengthReduction.cpp
) )
# 包含后端模块所需的头文件路径 # 包含后端模块所需的头文件路径

View File

@@ -41,7 +41,7 @@ void CalleeSavedHandler::runOnMachineFunction(MachineFunction* mfunc) {
}); });
frame_info.callee_saved_regs_to_store = sorted_regs; frame_info.callee_saved_regs_to_store = sorted_regs;
// 3. [关键修正] 更新栈帧总大小。 // 3. 更新栈帧总大小。
// 这是初步计算PEI Pass 会进行最终的对齐。 // 这是初步计算PEI Pass 会进行最终的对齐。
frame_info.total_size = frame_info.locals_size + frame_info.total_size = frame_info.locals_size +
frame_info.spill_size + frame_info.spill_size +

View File

@@ -1,7 +1,7 @@
#include "EliminateFrameIndices.h" #include "EliminateFrameIndices.h"
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include <cassert> #include <cassert>
#include <vector> // [新增] 为插入指令而包含 #include <vector>
namespace sysy { namespace sysy {
@@ -33,11 +33,7 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
Function* F = mfunc->getFunc(); Function* F = mfunc->getFunc();
RISCv64ISel* isel = mfunc->getISel(); RISCv64ISel* isel = mfunc->getISel();
// 1. [已移除] 不再处理栈传递的参数 // 在这里处理栈传递的参数以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 原先处理栈参数 (arg_idx >= 8) 的逻辑已被移除。
// 这项职责已完全转移到 PrologueEpilogueInsertionPass以避免逻辑冲突和错误。
// [注释更新] -> 上述注释已过时。根据新方案,我们将在这里处理栈传递的参数,
// 以便在寄存器分配前就将数据流显式化修复溢出逻辑的BUG。
// 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量 // 2. 只为局部变量(AllocaInst)分配栈空间和计算偏移量
// 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后 // 局部变量从 s0 下方(负偏移量)开始分配,紧接着为 ra 和 s0 预留的16字节之后
@@ -50,9 +46,13 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType(); Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
int size = getTypeSizeInBytes(allocated_type); int size = getTypeSizeInBytes(allocated_type);
// RISC-V要求栈地址8字节对齐 // 优化栈帧大小对于大数组使用4字节对齐小对象使用8字节对齐
size = (size + 7) & ~7; if (size >= 256) { // 大数组优化
if (size == 0) size = 8; // 至少分配8字节 size = (size + 3) & ~3; // 4字节对齐
} else {
size = (size + 7) & ~7; // 8字节对齐
}
if (size == 0) size = 4; // 最小4字节
local_var_offset += size; local_var_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca); unsigned alloca_vreg = isel->getVReg(alloca);
@@ -65,13 +65,17 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
// 记录仅由AllocaInst分配的局部变量的总大小 // 记录仅由AllocaInst分配的局部变量的总大小
frame_info.locals_size = local_var_offset - 16; frame_info.locals_size = local_var_offset - 16;
// 记录局部变量区域分配结束的最终偏移量
frame_info.locals_end_offset = -local_var_offset;
// 3. [核心修改] 在函数入口为所有栈传递的参数插入load指令 // 在函数入口为所有栈传递的参数插入load指令
// 这个步骤至关重要它在寄存器分配之前为这些参数的vreg创建了明确的“定义(def)”指令。 // 这个步骤至关重要它在寄存器分配之前为这些参数的vreg创建了明确的“定义(def)”指令。
// 这解决了在高寄存器压力下当这些vreg被溢出时`rewriteProgram`找不到其定义点而崩溃的问题。 // 这解决了在高寄存器压力下当这些vreg被溢出时`rewriteProgram`找不到其定义点而崩溃的问题。
if (F && isel && !mfunc->getBlocks().empty()) { if (F && isel && !mfunc->getBlocks().empty()) {
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs; std::vector<std::unique_ptr<MachineInstr>> arg_load_instrs;
// 步骤 3.1: 生成所有加载栈参数的指令,暂存起来
int arg_idx = 0; int arg_idx = 0;
for (Argument* arg : F->getArguments()) { for (Argument* arg : F->getArguments()) {
// 根据ABI前8个整型/指针参数通过寄存器传递,这里只处理超出部分。 // 根据ABI前8个整型/指针参数通过寄存器传递,这里只处理超出部分。
@@ -104,17 +108,50 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) {
arg_idx++; arg_idx++;
} }
// 将所有新创建的参数加载指令一次性插入到入口块的起始位置 //仅当有需要加载的栈参数时,才执行插入逻辑
auto& entry_instrs = entry_block->getInstructions(); if (!arg_load_instrs.empty()) {
entry_instrs.insert(entry_instrs.begin(), auto& entry_instrs = entry_block->getInstructions();
std::make_move_iterator(arg_load_instrs.begin()), auto insertion_point = entry_instrs.begin(); // 默认插入点为块的开头
std::make_move_iterator(arg_load_instrs.end())); auto last_arg_save_it = entry_instrs.end();
// 步骤 3.2: 寻找一个安全的插入点。
// 遍历入口块的指令,找到最后一条保存“寄存器传递参数”的伪指令。
// 这样可以确保我们在所有 a0-a7 参数被保存之后,才执行可能覆盖它们的加载指令。
for (auto it = entry_instrs.begin(); it != entry_instrs.end(); ++it) {
MachineInstr* instr = it->get();
// 寻找代表保存参数到栈的伪指令
if (instr->getOpcode() == RVOpcodes::FRAME_STORE_W ||
instr->getOpcode() == RVOpcodes::FRAME_STORE_D ||
instr->getOpcode() == RVOpcodes::FRAME_STORE_F) {
// 检查被保存的值是否是寄存器参数 (arg_no < 8)
auto& operands = instr->getOperands();
if (operands.empty() || operands[0]->getKind() != MachineOperand::KIND_REG) continue;
unsigned src_vreg = static_cast<RegOperand*>(operands[0].get())->getVRegNum();
Value* ir_value = isel->getVRegValueMap().count(src_vreg) ? isel->getVRegValueMap().at(src_vreg) : nullptr;
if (auto ir_arg = dynamic_cast<Argument*>(ir_value)) {
if (ir_arg->getIndex() < 8) {
last_arg_save_it = it; // 找到了一个保存寄存器参数的指令,更新位置
}
}
}
}
// 如果找到了这样的保存指令,我们的插入点就在它之后
if (last_arg_save_it != entry_instrs.end()) {
insertion_point = std::next(last_arg_save_it);
}
// 步骤 3.3: 在计算出的安全位置,一次性插入所有新创建的参数加载指令
entry_instrs.insert(insertion_point,
std::make_move_iterator(arg_load_instrs.begin()),
std::make_move_iterator(arg_load_instrs.end()));
}
} }
// 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令 // 4. 遍历所有机器指令,将访问局部变量的伪指令展开为真实指令
// 由于处理参数的逻辑已移除,这里的展开现在只针对局部变量,因此是正确的。
// [注释更新] -> 上述注释已过时。此部分逻辑保持不变,它正确地处理了局部变量。
for (auto& mbb : mfunc->getBlocks()) { for (auto& mbb : mfunc->getBlocks()) {
std::vector<std::unique_ptr<MachineInstr>> new_instructions; std::vector<std::unique_ptr<MachineInstr>> new_instructions;
for (auto& instr_ptr : mbb->getInstructions()) { for (auto& instr_ptr : mbb->getInstructions()) {

View File

@@ -27,8 +27,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
); );
} }
// 2. [新增] 确定需要保存的被调用者保存寄存器 (callee-saved) // 2. 确定需要保存的被调用者保存寄存器 (callee-saved)
// 这部分逻辑从 CalleeSavedHandler Pass 移入,以集中管理序言生成
auto& vreg_to_preg_map = frame_info.vreg_to_preg_map; auto& vreg_to_preg_map = frame_info.vreg_to_preg_map;
std::set<PhysicalReg> used_callee_saved_regs_set; std::set<PhysicalReg> used_callee_saved_regs_set;
const auto& callee_saved_int = getCalleeSavedIntRegs(); const auto& callee_saved_int = getCalleeSavedIntRegs();
@@ -36,38 +35,44 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
for (const auto& pair : vreg_to_preg_map) { for (const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second; PhysicalReg preg = pair.second;
// 检查是否在整数或浮点 callee-saved 集合中
// 注意s0作为帧指针由序言/尾声逻辑特殊处理,不在此处保存
bool is_int_cs = std::find(callee_saved_int.begin(), callee_saved_int.end(), preg) != callee_saved_int.end(); bool is_int_cs = std::find(callee_saved_int.begin(), callee_saved_int.end(), preg) != callee_saved_int.end();
bool is_fp_cs = std::find(callee_saved_fp.begin(), callee_saved_fp.end(), preg) != callee_saved_fp.end(); bool is_fp_cs = std::find(callee_saved_fp.begin(), callee_saved_fp.end(), preg) != callee_saved_fp.end();
if ((is_int_cs && preg != PhysicalReg::S0) || is_fp_cs) { if ((is_int_cs && preg != PhysicalReg::S0) || is_fp_cs) {
used_callee_saved_regs_set.insert(preg); used_callee_saved_regs_set.insert(preg);
} }
} }
// 为了确定性排序,并存入 frame_info 供尾声使用
frame_info.callee_saved_regs_to_store.assign( frame_info.callee_saved_regs_to_store.assign(
used_callee_saved_regs_set.begin(), used_callee_saved_regs_set.end() used_callee_saved_regs_set.begin(), used_callee_saved_regs_set.end()
); );
std::sort(frame_info.callee_saved_regs_to_store.begin(), frame_info.callee_saved_regs_to_store.end()); std::sort(frame_info.callee_saved_regs_to_store.begin(), frame_info.callee_saved_regs_to_store.end());
frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8; // 每个寄存器8字节 frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8;
// 3. 计算最终的栈帧总大小 // 3. 计算最终的栈帧总大小,包含栈溢出保护
int total_stack_size = frame_info.locals_size + int total_stack_size = frame_info.locals_size +
frame_info.spill_size + frame_info.spill_size +
frame_info.callee_saved_size + frame_info.callee_saved_size +
16; // 为 ra 和 s0 固定的16字节 16;
int aligned_stack_size = (total_stack_size + 15) & ~15; // 16字节对齐 // 栈溢出保护:增加最大栈帧大小以容纳大型数组
const int MAX_STACK_FRAME_SIZE = 8192; // 8KB to handle large arrays like 256*4*2 = 2048 bytes
if (total_stack_size > MAX_STACK_FRAME_SIZE) {
// 如果仍然超过限制,尝试优化对齐方式
std::cerr << "Warning: Stack frame size " << total_stack_size
<< " exceeds recommended limit " << MAX_STACK_FRAME_SIZE << " for function "
<< mfunc->getName() << std::endl;
}
// 优化减少对齐开销使用16字节对齐而非更大的对齐
int aligned_stack_size = (total_stack_size + 15) & ~15;
frame_info.total_size = aligned_stack_size; frame_info.total_size = aligned_stack_size;
// 只有在需要分配栈空间时才生成序言和尾声
if (aligned_stack_size > 0) { if (aligned_stack_size > 0) {
// --- 4. 插入完整的序言 --- // --- 4. 插入完整的序言 ---
MachineBasicBlock* entry_block = mfunc->getBlocks().front().get(); MachineBasicBlock* entry_block = mfunc->getBlocks().front().get();
auto& entry_instrs = entry_block->getInstructions(); auto& entry_instrs = entry_block->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> prologue_instrs; std::vector<std::unique_ptr<MachineInstr>> prologue_instrs;
// 4.1. 分配栈帧: addi sp, sp, -aligned_stack_size // 4.1. 分配栈帧
auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI); auto alloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP)); alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP)); alloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
@@ -75,7 +80,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
prologue_instrs.push_back(std::move(alloc_stack)); prologue_instrs.push_back(std::move(alloc_stack));
// 4.2. 保存 ra 和 s0 // 4.2. 保存 ra 和 s0
// sd ra, (aligned_stack_size - 8)(sp)
auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD); auto save_ra = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA)); save_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
save_ra->addOperand(std::make_unique<MemOperand>( save_ra->addOperand(std::make_unique<MemOperand>(
@@ -83,7 +87,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_unique<ImmOperand>(aligned_stack_size - 8) std::make_unique<ImmOperand>(aligned_stack_size - 8)
)); ));
prologue_instrs.push_back(std::move(save_ra)); prologue_instrs.push_back(std::move(save_ra));
// sd s0, (aligned_stack_size - 16)(sp)
auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD); auto save_fp = std::make_unique<MachineInstr>(RVOpcodes::SD);
save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0)); save_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
save_fp->addOperand(std::make_unique<MemOperand>( save_fp->addOperand(std::make_unique<MemOperand>(
@@ -92,60 +95,55 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
)); ));
prologue_instrs.push_back(std::move(save_fp)); prologue_instrs.push_back(std::move(save_fp));
// 4.3. 设置新的帧指针 s0: addi s0, sp, aligned_stack_size // 4.3. 设置新的帧指针 s0
auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI); auto set_fp = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0)); set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP)); set_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size)); set_fp->addOperand(std::make_unique<ImmOperand>(aligned_stack_size));
prologue_instrs.push_back(std::move(set_fp)); prologue_instrs.push_back(std::move(set_fp));
// 4.4. [新增] 保存所有使用到的被调用者保存寄存器 // 4.4. 保存所有使用到的被调用者保存寄存器
// 它们保存在 s0 下方,紧接着 ra/s0 的位置 int next_available_offset = -(16 + frame_info.locals_size + frame_info.spill_size);
int callee_saved_offset = -16;
for (const auto& reg : frame_info.callee_saved_regs_to_store) { for (const auto& reg : frame_info.callee_saved_regs_to_store) {
callee_saved_offset -= 8; // 改为“先更新,后使用”逻辑
RVOpcodes store_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FSD : RVOpcodes::SD; next_available_offset -= 8; // 先为当前寄存器分配下一个可用槽位
RVOpcodes store_op = isFPR(reg) ? RVOpcodes::FSD : RVOpcodes::SD;
auto save_cs_reg = std::make_unique<MachineInstr>(store_op); auto save_cs_reg = std::make_unique<MachineInstr>(store_op);
save_cs_reg->addOperand(std::make_unique<RegOperand>(reg)); save_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
save_cs_reg->addOperand(std::make_unique<MemOperand>( save_cs_reg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(callee_saved_offset) std::make_unique<ImmOperand>(next_available_offset) // 使用新计算出的正确偏移
)); ));
prologue_instrs.push_back(std::move(save_cs_reg)); prologue_instrs.push_back(std::move(save_cs_reg));
// 不再需要在循环末尾递减
} }
// 4.5. [核心修改] 加载栈传递参数的逻辑已从此移除 // 4.5. 将所有生成的序言指令一次性插入到函数入口
// 这项工作已经前移至 `EliminateFrameIndicesPass` 中完成,
// 以确保在寄存器分配前就将相关虚拟寄存器定义从而修复溢出逻辑的bug。
// 4.6. 将所有生成的序言指令一次性插入到函数入口
entry_instrs.insert(entry_instrs.begin(), entry_instrs.insert(entry_instrs.begin(),
std::make_move_iterator(prologue_instrs.begin()), std::make_move_iterator(prologue_instrs.begin()),
std::make_move_iterator(prologue_instrs.end())); std::make_move_iterator(prologue_instrs.end()));
// --- 5. 插入完整的尾声 --- // --- 5. 插入完整的尾声 ---
for (auto& mbb : mfunc->getBlocks()) { for (auto& mbb : mfunc->getBlocks()) {
// [修正] 使用前向迭代器查找RET指令以确保在正确的位置RET之前插入尾声。
for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) { for (auto it = mbb->getInstructions().begin(); it != mbb->getInstructions().end(); ++it) {
if ((*it)->getOpcode() == RVOpcodes::RET) { if ((*it)->getOpcode() == RVOpcodes::RET) {
std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs; std::vector<std::unique_ptr<MachineInstr>> epilogue_instrs;
// 5.1. [新增] 恢复被调用者保存寄存器 // 5.1. 恢复被调用者保存寄存器
callee_saved_offset = -16; int next_available_offset_restore = -(16 + frame_info.locals_size + frame_info.spill_size);
for (const auto& reg : frame_info.callee_saved_regs_to_store) { for (const auto& reg : frame_info.callee_saved_regs_to_store) {
callee_saved_offset -= 8; next_available_offset_restore -= 8; // 为下一个寄存器准备偏移
RVOpcodes load_op = (reg >= PhysicalReg::F0 && reg <= PhysicalReg::F31) ? RVOpcodes::FLD : RVOpcodes::LD; RVOpcodes load_op = isFPR(reg) ? RVOpcodes::FLD : RVOpcodes::LD;
auto restore_cs_reg = std::make_unique<MachineInstr>(load_op); auto restore_cs_reg = std::make_unique<MachineInstr>(load_op);
restore_cs_reg->addOperand(std::make_unique<RegOperand>(reg)); restore_cs_reg->addOperand(std::make_unique<RegOperand>(reg));
restore_cs_reg->addOperand(std::make_unique<MemOperand>( restore_cs_reg->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0), std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(callee_saved_offset) std::make_unique<ImmOperand>(next_available_offset_restore) // 使用当前偏移
)); ));
epilogue_instrs.push_back(std::move(restore_cs_reg)); epilogue_instrs.push_back(std::move(restore_cs_reg));
} }
// 5.2. 恢复 ra 和 s0 (注意基址现在是sp) // 5.2. 恢复 ra 和 s0
// ld ra, (aligned_stack_size - 8)(sp)
auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD); auto restore_ra = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA)); restore_ra->addOperand(std::make_unique<RegOperand>(PhysicalReg::RA));
restore_ra->addOperand(std::make_unique<MemOperand>( restore_ra->addOperand(std::make_unique<MemOperand>(
@@ -153,7 +151,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_unique<ImmOperand>(aligned_stack_size - 8) std::make_unique<ImmOperand>(aligned_stack_size - 8)
)); ));
epilogue_instrs.push_back(std::move(restore_ra)); epilogue_instrs.push_back(std::move(restore_ra));
// ld s0, (aligned_stack_size - 16)(sp)
auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD); auto restore_fp = std::make_unique<MachineInstr>(RVOpcodes::LD);
restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0)); restore_fp->addOperand(std::make_unique<RegOperand>(PhysicalReg::S0));
restore_fp->addOperand(std::make_unique<MemOperand>( restore_fp->addOperand(std::make_unique<MemOperand>(
@@ -162,7 +159,7 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
)); ));
epilogue_instrs.push_back(std::move(restore_fp)); epilogue_instrs.push_back(std::move(restore_fp));
// 5.3. 释放栈帧: addi sp, sp, aligned_stack_size // 5.3. 释放栈帧
auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI); auto dealloc_stack = std::make_unique<MachineInstr>(RVOpcodes::ADDI);
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP)); dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP)); dealloc_stack->addOperand(std::make_unique<RegOperand>(PhysicalReg::SP));
@@ -174,7 +171,6 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
std::make_move_iterator(epilogue_instrs.begin()), std::make_move_iterator(epilogue_instrs.begin()),
std::make_move_iterator(epilogue_instrs.end())); std::make_move_iterator(epilogue_instrs.end()));
// 一个基本块通常只有一个终止指令,处理完就可以跳到下一个块
goto next_block; goto next_block;
} }
} }

View File

@@ -0,0 +1,282 @@
#include "DivStrengthReduction.h"
#include <cmath>
#include <cstdint>
namespace sysy {
char DivStrengthReduction::ID = 0;
bool DivStrengthReduction::runOnFunction(Function *F, AnalysisManager& AM) {
// This pass works on MachineFunction level, not IR level
return false;
}
void DivStrengthReduction::runOnMachineFunction(MachineFunction *mfunc) {
if (!mfunc)
return;
bool debug = false; // Set to true for debugging
if (debug)
std::cout << "Running DivStrengthReduction optimization..." << std::endl;
int next_temp_reg = 1000;
auto createTempReg = [&]() -> int {
return next_temp_reg++;
};
struct MagicInfo {
int64_t magic;
int shift;
};
auto computeMagic = [](int64_t d, bool is_32bit) -> MagicInfo {
int word_size = is_32bit ? 32 : 64;
uint64_t ad = std::abs(d);
if (ad == 0) return {0, 0};
int l = std::floor(std::log2(ad));
if ((ad & (ad - 1)) == 0) { // power of 2
l = 0; // special case for power of 2, shift will be calculated differently
}
__int128_t one = 1;
__int128_t num;
int total_shift;
if (is_32bit) {
total_shift = 31 + l;
num = one << total_shift;
} else {
total_shift = 63 + l;
num = one << total_shift;
}
__int128_t den = ad;
int64_t magic = (num / den) + 1;
return {magic, total_shift};
};
auto isPowerOfTwo = [](int64_t n) -> bool {
return n > 0 && (n & (n - 1)) == 0;
};
auto getPowerOfTwoExponent = [](int64_t n) -> int {
if (n <= 0 || (n & (n - 1)) != 0) return -1;
int shift = 0;
while (n > 1) {
n >>= 1;
shift++;
}
return shift;
};
struct InstructionReplacement {
size_t index;
size_t count_to_erase;
std::vector<std::unique_ptr<MachineInstr>> newInstrs;
};
for (auto &mbb_uptr : mfunc->getBlocks()) {
auto &mbb = *mbb_uptr;
auto &instrs = mbb.getInstructions();
std::vector<InstructionReplacement> replacements;
for (size_t i = 0; i < instrs.size(); ++i) {
auto *instr = instrs[i].get();
bool is_32bit = (instr->getOpcode() == RVOpcodes::DIVW);
if (instr->getOpcode() != RVOpcodes::DIV && !is_32bit) {
continue;
}
if (instr->getOperands().size() != 3) {
continue;
}
auto *dst_op = instr->getOperands()[0].get();
auto *src1_op = instr->getOperands()[1].get();
auto *src2_op = instr->getOperands()[2].get();
int64_t divisor = 0;
bool const_divisor_found = false;
size_t instructions_to_replace = 1;
if (src2_op->getKind() == MachineOperand::KIND_IMM) {
divisor = static_cast<ImmOperand *>(src2_op)->getValue();
const_divisor_found = true;
} else if (src2_op->getKind() == MachineOperand::KIND_REG) {
if (i > 0) {
auto *prev_instr = instrs[i - 1].get();
if (prev_instr->getOpcode() == RVOpcodes::LI && prev_instr->getOperands().size() == 2) {
auto *li_dst_op = prev_instr->getOperands()[0].get();
auto *li_imm_op = prev_instr->getOperands()[1].get();
if (li_dst_op->getKind() == MachineOperand::KIND_REG && li_imm_op->getKind() == MachineOperand::KIND_IMM) {
auto *div_reg_op = static_cast<RegOperand *>(src2_op);
auto *li_dst_reg_op = static_cast<RegOperand *>(li_dst_op);
if (div_reg_op->isVirtual() && li_dst_reg_op->isVirtual() &&
div_reg_op->getVRegNum() == li_dst_reg_op->getVRegNum()) {
divisor = static_cast<ImmOperand *>(li_imm_op)->getValue();
const_divisor_found = true;
instructions_to_replace = 2;
}
}
}
}
}
if (!const_divisor_found) {
continue;
}
auto *dst_reg = static_cast<RegOperand *>(dst_op);
auto *src1_reg = static_cast<RegOperand *>(src1_op);
if (divisor == 0) continue;
std::vector<std::unique_ptr<MachineInstr>> newInstrs;
if (divisor == 1) {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
else if (divisor == -1) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
newInstrs.push_back(std::move(negInstr));
}
else if (isPowerOfTwo(std::abs(divisor))) {
int shift = getPowerOfTwoExponent(std::abs(divisor));
int temp_reg = createTempReg();
auto sraSignInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraSignInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraSignInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
sraSignInstr->addOperand(std::make_unique<ImmOperand>(is_32bit ? 31 : 63));
newInstrs.push_back(std::move(sraSignInstr));
auto srlInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRLIW : RVOpcodes::SRLI);
srlInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
srlInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
srlInstr->addOperand(std::make_unique<ImmOperand>((is_32bit ? 32 : 64) - shift));
newInstrs.push_back(std::move(srlInstr));
auto addInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
addInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
addInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
addInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(addInstr));
auto sraInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(shift));
newInstrs.push_back(std::move(sraInstr));
if (divisor < 0) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(negInstr));
} else {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
}
else {
auto magic_info = computeMagic(divisor, is_32bit);
int magic_reg = createTempReg();
int temp_reg = createTempReg();
auto loadInstr = std::make_unique<MachineInstr>(RVOpcodes::LI);
loadInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
loadInstr->addOperand(std::make_unique<ImmOperand>(magic_info.magic));
newInstrs.push_back(std::move(loadInstr));
if (is_32bit) {
auto mulInstr = std::make_unique<MachineInstr>(RVOpcodes::MUL);
mulInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
mulInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
mulInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
newInstrs.push_back(std::move(mulInstr));
auto sraInstr = std::make_unique<MachineInstr>(RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(magic_info.shift));
newInstrs.push_back(std::move(sraInstr));
} else {
auto mulhInstr = std::make_unique<MachineInstr>(RVOpcodes::MULH);
mulhInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
mulhInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
mulhInstr->addOperand(std::make_unique<RegOperand>(magic_reg));
newInstrs.push_back(std::move(mulhInstr));
int post_shift = magic_info.shift - 63;
if (post_shift > 0) {
auto sraInstr = std::make_unique<MachineInstr>(RVOpcodes::SRAI);
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
sraInstr->addOperand(std::make_unique<ImmOperand>(post_shift));
newInstrs.push_back(std::move(sraInstr));
}
}
int sign_reg = createTempReg();
auto sraSignInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SRAIW : RVOpcodes::SRAI);
sraSignInstr->addOperand(std::make_unique<RegOperand>(sign_reg));
sraSignInstr->addOperand(std::make_unique<RegOperand>(*src1_reg));
sraSignInstr->addOperand(std::make_unique<ImmOperand>(is_32bit ? 31 : 63));
newInstrs.push_back(std::move(sraSignInstr));
auto subInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
subInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
subInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
subInstr->addOperand(std::make_unique<RegOperand>(sign_reg));
newInstrs.push_back(std::move(subInstr));
if (divisor < 0) {
auto negInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::SUBW : RVOpcodes::SUB);
negInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
negInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
negInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
newInstrs.push_back(std::move(negInstr));
} else {
auto moveInstr = std::make_unique<MachineInstr>(is_32bit ? RVOpcodes::ADDW : RVOpcodes::ADD);
moveInstr->addOperand(std::make_unique<RegOperand>(*dst_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(temp_reg));
moveInstr->addOperand(std::make_unique<RegOperand>(PhysicalReg::ZERO));
newInstrs.push_back(std::move(moveInstr));
}
}
if (!newInstrs.empty()) {
size_t start_index = i;
if (instructions_to_replace == 2) {
start_index = i - 1;
}
replacements.push_back({start_index, instructions_to_replace, std::move(newInstrs)});
}
}
for (auto it = replacements.rbegin(); it != replacements.rend(); ++it) {
instrs.erase(instrs.begin() + it->index, instrs.begin() + it->index + it->count_to_erase);
instrs.insert(instrs.begin() + it->index,
std::make_move_iterator(it->newInstrs.begin()),
std::make_move_iterator(it->newInstrs.end()));
}
}
}
} // namespace sysy

View File

@@ -1,7 +1,8 @@
#include "RISCv64AsmPrinter.h" #include "RISCv64AsmPrinter.h"
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include <stdexcept> #include <stdexcept>
#include <sstream>
#include <iostream>
namespace sysy { namespace sysy {
// 检查是否为内存加载/存储指令,以处理特殊的打印格式 // 检查是否为内存加载/存储指令,以处理特殊的打印格式
@@ -60,7 +61,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::ADD: *OS << "add "; break; case RVOpcodes::ADDI: *OS << "addi "; break; case RVOpcodes::ADD: *OS << "add "; break; case RVOpcodes::ADDI: *OS << "addi "; break;
case RVOpcodes::ADDW: *OS << "addw "; break; case RVOpcodes::ADDIW: *OS << "addiw "; break; case RVOpcodes::ADDW: *OS << "addw "; break; case RVOpcodes::ADDIW: *OS << "addiw "; break;
case RVOpcodes::SUB: *OS << "sub "; break; case RVOpcodes::SUBW: *OS << "subw "; break; case RVOpcodes::SUB: *OS << "sub "; break; case RVOpcodes::SUBW: *OS << "subw "; break;
case RVOpcodes::MUL: *OS << "mul "; break; case RVOpcodes::MULW: *OS << "mulw "; break; case RVOpcodes::MUL: *OS << "mul "; break; case RVOpcodes::MULW: *OS << "mulw "; break; case RVOpcodes::MULH: *OS << "mulh "; break;
case RVOpcodes::DIV: *OS << "div "; break; case RVOpcodes::DIVW: *OS << "divw "; break; case RVOpcodes::DIV: *OS << "div "; break; case RVOpcodes::DIVW: *OS << "divw "; break;
case RVOpcodes::REM: *OS << "rem "; break; case RVOpcodes::REMW: *OS << "remw "; break; case RVOpcodes::REM: *OS << "rem "; break; case RVOpcodes::REMW: *OS << "remw "; break;
case RVOpcodes::XOR: *OS << "xor "; break; case RVOpcodes::XORI: *OS << "xori "; break; case RVOpcodes::XOR: *OS << "xor "; break; case RVOpcodes::XORI: *OS << "xori "; break;
@@ -81,7 +82,7 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break; case RVOpcodes::SB: *OS << "sb "; break; case RVOpcodes::LD: *OS << "ld "; break;
case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break; case RVOpcodes::SD: *OS << "sd "; break; case RVOpcodes::FLW: *OS << "flw "; break;
case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break; case RVOpcodes::FSW: *OS << "fsw "; break; case RVOpcodes::FLD: *OS << "fld "; break;
case RVOpcodes::FSD: *OS << "fsd "; break; case RVOpcodes::FSD: *OS << "fsd "; break;
case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break; case RVOpcodes::J: *OS << "j "; break; case RVOpcodes::JAL: *OS << "jal "; break;
case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break; case RVOpcodes::JALR: *OS << "jalr "; break; case RVOpcodes::RET: *OS << "ret"; break;
case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break; case RVOpcodes::BEQ: *OS << "beq "; break; case RVOpcodes::BNE: *OS << "bne "; break;
@@ -101,10 +102,11 @@ void RISCv64AsmPrinter::printInstruction(MachineInstr* instr, bool debug) {
case RVOpcodes::FLE_S: *OS << "fle.s "; break; case RVOpcodes::FLE_S: *OS << "fle.s "; break;
case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break; case RVOpcodes::FCVT_S_W: *OS << "fcvt.s.w "; break;
case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break; case RVOpcodes::FCVT_W_S: *OS << "fcvt.w.s "; break;
case RVOpcodes::FCVT_W_S_RTZ: *OS << "fcvt.w.s "; break;
case RVOpcodes::FMV_S: *OS << "fmv.s "; break; case RVOpcodes::FMV_S: *OS << "fmv.s "; break;
case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break; case RVOpcodes::FMV_W_X: *OS << "fmv.w.x "; break;
case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break; case RVOpcodes::FMV_X_W: *OS << "fmv.x.w "; break;
case RVOpcodes::CALL: { // [核心修改] 为CALL指令添加特殊处理逻辑 case RVOpcodes::CALL: { // 为CALL指令添加特殊处理逻辑
*OS << "call "; *OS << "call ";
// 遍历所有操作数,只寻找并打印函数名标签 // 遍历所有操作数,只寻找并打印函数名标签
for (const auto& op : instr->getOperands()) { for (const auto& op : instr->getOperands()) {
@@ -236,4 +238,30 @@ std::string RISCv64AsmPrinter::regToString(PhysicalReg reg) {
} }
} }
std::string RISCv64AsmPrinter::formatInstr(const MachineInstr* instr) {
if (!instr) return "(null instr)";
// 使用 stringstream 作为临时的输出目标
std::stringstream ss;
// 关键: 临时将类成员 'OS' 指向我们的 stringstream
std::ostream* old_os = this->OS;
this->OS = &ss;
// 修正: 调用正确的内部打印函数 printMachineInstr
printInstruction(const_cast<MachineInstr*>(instr), false);
// 恢复旧的 ostream 指针
this->OS = old_os;
// 获取stringstream的内容并做一些清理
std::string result = ss.str();
size_t endpos = result.find_last_not_of(" \t\n\r");
if (std::string::npos != endpos) {
result = result.substr(0, endpos + 1);
}
return result;
}
} // namespace sysy } // namespace sysy

View File

@@ -1,10 +1,13 @@
#include "RISCv64Backend.h" #include "RISCv64Backend.h"
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include "RISCv64RegAlloc.h" #include "RISCv64RegAlloc.h"
#include "RISCv64LinearScan.h" // <--- 新增此行
#include "RISCv64AsmPrinter.h" #include "RISCv64AsmPrinter.h"
#include "RISCv64Passes.h" #include "RISCv64Passes.h"
#include <sstream> #include <sstream>
#include <future> // <--- 新增此行
#include <chrono> // <--- 新增此行
#include <iostream> // <--- 新增此行,用于打印超时警告
namespace sysy { namespace sysy {
// 顶层入口 // 顶层入口
@@ -73,7 +76,7 @@ std::string RISCv64CodeGen::module_gen() {
for (const auto& global_ptr : module->getGlobals()) { for (const auto& global_ptr : module->getGlobals()) {
GlobalValue* global = global_ptr.get(); GlobalValue* global = global_ptr.get();
// [核心修改] 使用更健壮的逻辑来判断是否为大型零初始化数组 // 使用更健壮的逻辑来判断是否为大型零初始化数组
bool is_all_zeros = true; bool is_all_zeros = true;
const auto& init_values = global->getInitValues(); const auto& init_values = global->getInitValues();
@@ -139,7 +142,29 @@ std::string RISCv64CodeGen::module_gen() {
ss << ".type " << global->getName() << ", @object\n"; ss << ".type " << global->getName() << ", @object\n";
ss << ".size " << global->getName() << ", " << total_size << "\n"; ss << ".size " << global->getName() << ", " << total_size << "\n";
ss << global->getName() << ":\n"; ss << global->getName() << ":\n";
printInitializer(ss, global->getInitValues()); bool is_all_zeros = true;
const auto& init_values = global->getInitValues();
if (init_values.getValues().empty()) {
is_all_zeros = true;
} else {
for (auto val : init_values.getValues()) {
if (auto const_val = dynamic_cast<ConstantValue*>(val)) {
if (!const_val->isZero()) {
is_all_zeros = false;
break;
}
} else {
is_all_zeros = false;
break;
}
}
}
if (is_all_zeros) {
ss << " .zero " << total_size << "\n";
} else {
// 对于有非零初始值的变量,保持原有的打印逻辑。
printInitializer(ss, global->getInitValues());
}
} }
// b. 处理全局常量 (ConstantVariable) // b. 处理全局常量 (ConstantVariable)
@@ -171,222 +196,84 @@ std::string RISCv64CodeGen::module_gen() {
} }
std::string RISCv64CodeGen::function_gen(Function* func) { std::string RISCv64CodeGen::function_gen(Function* func) {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
if (DEBUG) { if (DEBUG) {
// === 完整的后端处理流水线 === std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers)
DEBUG = 0;
DEEPDEBUG = 0;
RISCv64ISel isel;
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func);
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
// if (DEBUG) {
// std::cout << ss_after_isel.str();
// }
DEBUG = 0;
DEEPDEBUG = 0;
DEBUG = 1;
DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// DEBUG = 0;
// DEEPDEBUG = 0;
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
// std::stringstream ss_after_eli;
// printer_isel.run(ss_after_eli, true);
// std::cerr << "====== LLIR after eliminate frame indices ======\n"
// << ss_after_eli.str();
}
// // 阶段 2: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// DEBUG = 0;
// DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
// DEBUG = 0;
// DEEPDEBUG = 0;
DEBUG = 1;
DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
// PostRA_Scheduler local_scheduler;
// local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) {
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
<< ss_after_isel.str();
}
DEBUG = 1;
DEEPDEBUG = 1;
return ss.str();
} }
// 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
else {
// === 完整的后端处理流水线 ===
// 阶段 1: 指令选择 (sysy::IR -> LLIR with virtual registers) if (DEBUG) {
DEBUG = 0; std::cerr << "====== stack info after eliminate frame indices ======\n";
DEEPDEBUG = 0; mfunc->dumpStackFrameInfo(std::cerr);
std::stringstream ss_after_eli;
RISCv64ISel isel; printer_isel.run(ss_after_eli, true);
std::unique_ptr<MachineFunction> mfunc = isel.runOnFunction(func); std::cerr << "====== LLIR after eliminate frame indices ======\n"
<< ss_after_eli.str();
// 第一次调试打印输出
std::stringstream ss_after_isel;
RISCv64AsmPrinter printer_isel(mfunc.get());
printer_isel.run(ss_after_isel, true);
// if (DEBUG) {
// std::cout << ss_after_isel.str();
// }
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== Intermediate Representation after Instruction Selection ======\n"
<< ss_after_isel.str();
}
// DEBUG = 0;
// DEEPDEBUG = 0;
// [新增] 阶段 2: 消除帧索引 (展开伪指令,计算局部变量偏移)
// 这个Pass必须在寄存器分配之前运行
EliminateFrameIndicesPass efi_pass;
efi_pass.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after eliminate frame indices ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
std::stringstream ss_after_eli;
printer_isel.run(ss_after_eli, true);
std::cerr << "====== LLIR after eliminate frame indices ======\n"
<< ss_after_eli.str();
}
// // 阶段 2: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
DEBUG = 0;
DEEPDEBUG = 0;
// DEBUG = 1;
// DEEPDEBUG = 1;
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
// PostRA_Scheduler local_scheduler;
// local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
DEBUG = 0;
DEEPDEBUG = 0;
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
if (DEBUG) {
ss << "\n\n; --- Intermediate Representation after Instruction Selection ---\n"
<< ss_after_isel.str();
}
return ss.str();
} }
// // 阶段 2: 除法强度削弱优化 (Division Strength Reduction)
// DivStrengthReduction div_strength_reduction;
// div_strength_reduction.runOnMachineFunction(mfunc.get());
// // 阶段 2.1: 指令调度 (Instruction Scheduling)
// PreRA_Scheduler scheduler;
// scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation)
RISCv64RegAlloc reg_alloc(mfunc.get());
reg_alloc.run();
if (DEBUG) {
std::cerr << "====== stack info after reg alloc ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// 阶段 3.1: 处理被调用者保存寄存器
CalleeSavedHandler callee_handler;
callee_handler.runOnMachineFunction(mfunc.get());
if (DEBUG) {
std::cerr << "====== stack info after callee handler ======\n";
mfunc->dumpStackFrameInfo(std::cerr);
}
// // 阶段 4: 窥孔优化 (Peephole Optimization)
// PeepholeOptimizer peephole;
// peephole.runOnMachineFunction(mfunc.get());
// 阶段 5: 局部指令调度 (Local Scheduling)
PostRA_Scheduler local_scheduler;
local_scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3.2: 插入序言和尾声
PrologueEpilogueInsertionPass pei_pass;
pei_pass.runOnMachineFunction(mfunc.get());
// 阶段 3.3: 大立即数合法化
LegalizeImmediatesPass legalizer;
legalizer.runOnMachineFunction(mfunc.get());
// 阶段 6: 代码发射 (Code Emission)
std::stringstream ss;
RISCv64AsmPrinter printer(mfunc.get());
printer.run(ss);
return ss.str();
} }
} // namespace sysy } // namespace sysy

View File

@@ -1,9 +1,10 @@
#include "RISCv64ISel.h" #include "RISCv64ISel.h"
#include "IR.h" // For GlobalValue
#include <stdexcept> #include <stdexcept>
#include <set> #include <set>
#include <functional> #include <functional>
#include <cmath> // For std::fabs #include <cmath>
#include <limits> // For std::numeric_limits #include <limits>
#include <iostream> #include <iostream>
namespace sysy { namespace sysy {
@@ -167,33 +168,6 @@ void RISCv64ISel::selectBasicBlock(BasicBlock* bb) {
select_recursive(node_to_select); select_recursive(node_to_select);
} }
} }
if (CurMBB == MFunc->getBlocks().front().get()) { // 只对入口块操作
auto keepalive = std::make_unique<MachineInstr>(RVOpcodes::PSEUDO_KEEPALIVE);
for (Argument* arg : F->getArguments()) {
keepalive->addOperand(std::make_unique<RegOperand>(getVReg(arg)));
}
auto& instrs = CurMBB->getInstructions();
auto insert_pos = instrs.end();
// 关键:检查基本块是否以一个“终止指令”结尾
if (!instrs.empty()) {
RVOpcodes last_op = instrs.back()->getOpcode();
// 扩充了判断条件,涵盖所有可能的终止指令
if (last_op == RVOpcodes::J || last_op == RVOpcodes::RET ||
last_op == RVOpcodes::BEQ || last_op == RVOpcodes::BNE ||
last_op == RVOpcodes::BLT || last_op == RVOpcodes::BGE ||
last_op == RVOpcodes::BLTU || last_op == RVOpcodes::BGEU)
{
// 如果是,插入点就在这个终止指令之前
insert_pos = std::prev(instrs.end());
}
}
// 在计算出的正确位置插入伪指令
instrs.insert(insert_pos, std::move(keepalive));
}
} }
// 核心函数为DAG节点选择并生成MachineInstr (已修复和增强的完整版本) // 核心函数为DAG节点选择并生成MachineInstr (已修复和增强的完整版本)
@@ -209,8 +183,12 @@ void RISCv64ISel::selectNode(DAGNode* node) {
case DAGNode::CONSTANT: case DAGNode::CONSTANT:
case DAGNode::ALLOCA_ADDR: case DAGNode::ALLOCA_ADDR:
if (node->value) { if (node->value) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。 // GlobalValue objects (global variables) should not get virtual registers
getVReg(node->value); // since they represent memory addresses, not register-allocated values
if (dynamic_cast<GlobalValue*>(node->value) == nullptr) {
// 确保它有一个关联的虚拟寄存器即可,不生成代码。
getVReg(node->value);
}
} }
break; break;
@@ -402,7 +380,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
Value* base = nullptr; Value* base = nullptr;
Value* offset = nullptr; Value* offset = nullptr;
// [修改] 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue // 扩展基地址的判断,使其可以识别 AllocaInst 或 GlobalValue
if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) { if (dynamic_cast<AllocaInst*>(lhs) || dynamic_cast<GlobalValue*>(lhs)) {
base = lhs; base = lhs;
offset = rhs; offset = rhs;
@@ -421,7 +399,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(li)); CurMBB->addInstruction(std::move(li));
} }
// 2. [修改] 根据基地址的类型,生成不同的指令来获取基地址 // 2. 根据基地址的类型,生成不同的指令来获取基地址
auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址 auto base_addr_vreg = getNewVReg(Type::getIntType()); // 创建一个新的临时vreg来存放基地址
// 情况一:基地址是局部栈变量 // 情况一:基地址是局部栈变量
@@ -452,7 +430,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
} }
// [V2优点] 在BINARY节点内部按需加载常量操作数。 // 在BINARY节点内部按需加载常量操作数。
auto load_val_if_const = [&](Value* val) { auto load_val_if_const = [&](Value* val) {
if (auto c = dynamic_cast<ConstantValue*>(val)) { if (auto c = dynamic_cast<ConstantValue*>(val)) {
if (DEBUG) { if (DEBUG) {
@@ -483,7 +461,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto dest_vreg = getVReg(bin); auto dest_vreg = getVReg(bin);
auto lhs_vreg = getVReg(lhs); auto lhs_vreg = getVReg(lhs);
// [V2优点] 融合 ADDIW 优化。 // 融合 ADDIW 优化。
if (rhs_is_imm_opt) { if (rhs_is_imm_opt) {
auto rhs_const = dynamic_cast<ConstantValue*>(rhs); auto rhs_const = dynamic_cast<ConstantValue*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW); auto instr = std::make_unique<MachineInstr>(RVOpcodes::ADDIW);
@@ -539,6 +517,15 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case Instruction::kSRA: {
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
instr->addOperand(std::make_unique<RegOperand>(lhs_vreg));
instr->addOperand(std::make_unique<ImmOperand>(rhs_const->getInt()));
CurMBB->addInstruction(std::move(instr));
break;
}
case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz) case BinaryInst::kICmpEQ: { // 等于 (a == b) -> (subw; seqz)
auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW); auto sub = std::make_unique<MachineInstr>(RVOpcodes::SUBW);
sub->addOperand(std::make_unique<RegOperand>(dest_vreg)); sub->addOperand(std::make_unique<RegOperand>(dest_vreg));
@@ -758,8 +745,9 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
break; break;
} }
case Instruction::kFtoI: { // 浮点 to 整数 case Instruction::kFtoI: { // 浮点 to 整数 (使用硬件指令进行向零截断)
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S); // 直接生成一条带有 rtz 舍入模式的转换指令
auto instr = std::make_unique<MachineInstr>(RVOpcodes::FCVT_W_S_RTZ);
instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); // 目标是整数vreg
instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg instr->addOperand(std::make_unique<RegOperand>(src_vreg)); // 源是浮点vreg
CurMBB->addInstruction(std::move(instr)); CurMBB->addInstruction(std::move(instr));
@@ -943,7 +931,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// --- 步骤 3: 生成CALL指令 --- // --- 步骤 3: 生成CALL指令 ---
auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL); auto call_instr = std::make_unique<MachineInstr>(RVOpcodes::CALL);
// [协议] 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数 // 如果函数有返回值,将它的目标虚拟寄存器作为第一个操作数
if (!call->getType()->isVoid()) { if (!call->getType()->isVoid()) {
unsigned dest_vreg = getVReg(call); unsigned dest_vreg = getVReg(call);
call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg)); call_instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
@@ -1020,7 +1008,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} else { } else {
// --- 处理整数/指针返回值 --- // --- 处理整数/指针返回值 ---
// 返回值需要被放入 a0 // 返回值需要被放入 a0
// [V2优点] 在RETURN节点内加载常量返回值 // 在RETURN节点内加载常量返回值
if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) { if (auto const_val = dynamic_cast<ConstantValue*>(ret_val)) {
auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li_instr = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0)); li_instr->addOperand(std::make_unique<RegOperand>(PhysicalReg::A0));
@@ -1034,7 +1022,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
} }
} }
// [V1设计保留] 函数尾声epilogue不由RETURN节点生成 // 函数尾声epilogue不由RETURN节点生成
// 而是由后续的AsmPrinter或其它Pass统一处理这是一种常见且有效的模块化设计。 // 而是由后续的AsmPrinter或其它Pass统一处理这是一种常见且有效的模块化设计。
auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET); auto ret_mi = std::make_unique<MachineInstr>(RVOpcodes::RET);
CurMBB->addInstruction(std::move(ret_mi)); CurMBB->addInstruction(std::move(ret_mi));
@@ -1048,7 +1036,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto then_bb_name = cond_br->getThenBlock()->getName(); auto then_bb_name = cond_br->getThenBlock()->getName();
auto else_bb_name = cond_br->getElseBlock()->getName(); auto else_bb_name = cond_br->getElseBlock()->getName();
// [优化] 检查分支条件是否为编译期常量 // 检查分支条件是否为编译期常量
if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) { if (auto const_cond = dynamic_cast<ConstantValue*>(condition)) {
// 如果条件是常量直接生成一个无条件跳转J而不是BNE // 如果条件是常量直接生成一个无条件跳转J而不是BNE
if (const_cond->getInt() != 0) { // 条件为 true if (const_cond->getInt() != 0) { // 条件为 true
@@ -1063,7 +1051,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
// 如果条件不是常量,则执行标准流程 // 如果条件不是常量,则执行标准流程
else { else {
// [修复] 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了) // 为条件变量生成加载指令(如果它是常量的话,尽管上面已经处理了)
// 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获 // 这一步是为了逻辑完整,以防有其他类型的常量没有被捕获
if (auto const_val = dynamic_cast<ConstantValue*>(condition)) { if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
@@ -1097,7 +1085,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
} }
case DAGNode::MEMSET: { case DAGNode::MEMSET: {
// [V1设计保留] Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。 // Memset的核心展开逻辑在虚拟寄存器层面是正确的无需修改。
// 之前的bug是由于其输入地址、值、大小的虚拟寄存器未被正确初始化。 // 之前的bug是由于其输入地址、值、大小的虚拟寄存器未被正确初始化。
// 在修复了CONSTANT/ALLOCA_ADDR的加载问题后此处的逻辑现在可以正常工作。 // 在修复了CONSTANT/ALLOCA_ADDR的加载问题后此处的逻辑现在可以正常工作。
@@ -1143,10 +1131,11 @@ void RISCv64ISel::selectNode(DAGNode* node) {
auto r_value_byte = getVReg(memset->getValue()); auto r_value_byte = getVReg(memset->getValue());
// 为memset内部逻辑创建新的临时虚拟寄存器 // 为memset内部逻辑创建新的临时虚拟寄存器
auto r_counter = getNewVReg(); Type* ptr_type = Type::getPointerType(Type::getIntType());
auto r_end_addr = getNewVReg(); auto r_counter = getNewVReg(ptr_type);
auto r_current_addr = getNewVReg(); auto r_end_addr = getNewVReg(ptr_type);
auto r_temp_val = getNewVReg(); auto r_current_addr = getNewVReg(ptr_type);
auto r_temp_val = getNewVReg(Type::getIntType());
// 定义一系列lambda表达式来简化指令创建 // 定义一系列lambda表达式来简化指令创建
auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) { auto add_instr = [&](RVOpcodes op, unsigned rd, unsigned rs1, unsigned rs2) {
@@ -1237,7 +1226,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) --- // --- Step 1: 获取基地址 (此部分逻辑正确,保持不变) ---
auto base_ptr_node = node->operands[0]; auto base_ptr_node = node->operands[0];
auto current_addr_vreg = getNewVReg(); auto current_addr_vreg = getNewVReg(gep->getType());
if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) { if (auto alloca_base = dynamic_cast<AllocaInst*>(base_ptr_node->value)) {
auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR); auto frame_addr_instr = std::make_unique<MachineInstr>(RVOpcodes::FRAME_ADDR);
@@ -1279,15 +1268,20 @@ void RISCv64ISel::selectNode(DAGNode* node) {
// 如果步长为0例如对一个void类型或空结构体索引则不产生任何偏移 // 如果步长为0例如对一个void类型或空结构体索引则不产生任何偏移
if (stride != 0) { if (stride != 0) {
// --- 为当前索引和步长生成偏移计算指令 --- // --- 为当前索引和步长生成偏移计算指令 ---
auto offset_vreg = getNewVReg(); auto offset_vreg = getNewVReg(Type::getIntType());
auto index_vreg = getVReg(indexValue);
// 处理索引 - 区分常量与动态值
// 如果索引是常量,先用 LI 指令加载到虚拟寄存器 unsigned index_vreg;
if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) { if (auto const_index = dynamic_cast<ConstantValue*>(indexValue)) {
// 对于常量索引,直接创建新的虚拟寄存器
index_vreg = getNewVReg(Type::getIntType());
auto li = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li = std::make_unique<MachineInstr>(RVOpcodes::LI);
li->addOperand(std::make_unique<RegOperand>(index_vreg)); li->addOperand(std::make_unique<RegOperand>(index_vreg));
li->addOperand(std::make_unique<ImmOperand>(const_index->getInt())); li->addOperand(std::make_unique<ImmOperand>(const_index->getInt()));
CurMBB->addInstruction(std::move(li)); CurMBB->addInstruction(std::move(li));
} else {
// 对于动态索引,使用已存在的虚拟寄存器
index_vreg = getVReg(indexValue);
} }
// 优化如果步长是1可以直接移动(MV)作为偏移量,无需乘法 // 优化如果步长是1可以直接移动(MV)作为偏移量,无需乘法
@@ -1298,7 +1292,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
CurMBB->addInstruction(std::move(mv)); CurMBB->addInstruction(std::move(mv));
} else { } else {
// 步长不为1需要生成乘法指令 // 步长不为1需要生成乘法指令
auto size_vreg = getNewVReg(); auto size_vreg = getNewVReg(Type::getIntType());
auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI); auto li_size = std::make_unique<MachineInstr>(RVOpcodes::LI);
li_size->addOperand(std::make_unique<RegOperand>(size_vreg)); li_size->addOperand(std::make_unique<RegOperand>(size_vreg));
li_size->addOperand(std::make_unique<ImmOperand>(stride)); li_size->addOperand(std::make_unique<ImmOperand>(stride));
@@ -1445,7 +1439,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
// 依次添加所有索引作为后续的操作数 // 依次添加所有索引作为后续的操作数
for (auto index : gep->getIndices()) { for (auto index : gep->getIndices()) {
// [修复] 从 Use 对象中获取真正的 Value* // 从 Use 对象中获取真正的 Value*
gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage)); gep_node->operands.push_back(get_operand_node(index->getValue(), value_to_node, nodes_storage));
} }
} else if (auto load = dynamic_cast<LoadInst*>(inst)) { } else if (auto load = dynamic_cast<LoadInst*>(inst)) {
@@ -1473,7 +1467,7 @@ std::vector<std::unique_ptr<RISCv64ISel::DAGNode>> RISCv64ISel::build_dag(BasicB
} }
} }
} }
if (bin->getKind() >= Instruction::kFAdd) { // 假设浮点指令枚举值更大 if (bin->isFPBinary()) { // 假设浮点指令枚举值更大
auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage); auto fbin_node = create_node(DAGNode::FBINARY, bin, value_to_node, nodes_storage);
fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage)); fbin_node->operands.push_back(get_operand_node(bin->getLhs(), value_to_node, nodes_storage));
fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage)); fbin_node->operands.push_back(get_operand_node(bin->getRhs(), value_to_node, nodes_storage));
@@ -1549,7 +1543,7 @@ unsigned RISCv64ISel::getTypeSizeInBytes(Type* type) {
} }
} }
// [新] 打印DAG图以供调试的辅助函数 // 打印DAG图以供调试的辅助函数
void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) { void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, const std::string& bb_name) {
// 检查是否有DEBUG宏或者全局变量避免在非调试模式下打印 // 检查是否有DEBUG宏或者全局变量避免在非调试模式下打印
// if (!DEBUG) return; // if (!DEBUG) return;
@@ -1645,4 +1639,8 @@ void RISCv64ISel::print_dag(const std::vector<std::unique_ptr<DAGNode>>& dag, co
std::cerr << "======================================\n\n"; std::cerr << "======================================\n\n";
} }
unsigned int RISCv64ISel::getVRegCounter() const {
return vreg_counter;
}
} // namespace sysy } // namespace sysy

View File

@@ -44,7 +44,7 @@ std::string regToString(PhysicalReg reg) {
} }
} }
// [新增] 打印栈帧信息的完整实现 // 打印栈帧信息的完整实现
void MachineFunction::dumpStackFrameInfo(std::ostream& os) const { void MachineFunction::dumpStackFrameInfo(std::ostream& os) const {
const StackFrameInfo& info = frame_info; const StackFrameInfo& info = frame_info;

View File

@@ -0,0 +1,517 @@
#include "RISCv64LinearScan.h"
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h"
#include <iostream>
#include <set>
extern int DEBUG;
namespace sysy {
RISCv64LinearScan::RISCv64LinearScan(MachineFunction* mfunc)
: MFunc(mfunc),
ISel(mfunc->getISel()),
vreg_type_map(ISel->getVRegTypeMap()) {
// 初始化可用的物理寄存器池,与图着色版本保持一致
// 整数寄存器
allocable_int_regs = {
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, /*T5保留作为大立即数加载寄存器*/ PhysicalReg::T6,
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7,
PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5, PhysicalReg::S6, PhysicalReg::S7,
PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11,
};
// 浮点寄存器
allocable_fp_regs = {
PhysicalReg::F0, PhysicalReg::F1, PhysicalReg::F2, PhysicalReg::F3, PhysicalReg::F4, PhysicalReg::F5, PhysicalReg::F6, PhysicalReg::F7,
PhysicalReg::F10, PhysicalReg::F11, PhysicalReg::F12, PhysicalReg::F13, PhysicalReg::F14, PhysicalReg::F15, PhysicalReg::F16, PhysicalReg::F17,
PhysicalReg::F8, PhysicalReg::F9, PhysicalReg::F18, PhysicalReg::F19, PhysicalReg::F20, PhysicalReg::F21, PhysicalReg::F22,
PhysicalReg::F23, PhysicalReg::F24, PhysicalReg::F25, PhysicalReg::F26, PhysicalReg::F27,
PhysicalReg::F28, PhysicalReg::F29, PhysicalReg::F30, PhysicalReg::F31,
};
// 新增识别所有通过寄存器传递的参数并建立vreg到物理寄存器(preg)的映射
// 这等同于图着色算法中的“预着色”步骤。
if (MFunc->getFunc()) {
int int_arg_idx = 0;
int fp_arg_idx = 0;
for (Argument* arg : MFunc->getFunc()->getArguments()) {
unsigned arg_vreg = ISel->getVReg(arg);
if (arg->getType()->isFloat()) {
if (fp_arg_idx < 8) { // fa0-fa7
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::F10) + fp_arg_idx);
abi_vreg_map[arg_vreg] = preg;
fp_arg_idx++;
}
} else { // 整数或指针
if (int_arg_idx < 8) { // a0-a7
auto preg = static_cast<PhysicalReg>(static_cast<int>(PhysicalReg::A0) + int_arg_idx);
abi_vreg_map[arg_vreg] = preg;
int_arg_idx++;
}
}
}
}
}
void RISCv64LinearScan::run() {
if (DEBUG) std::cerr << "===== Running Linear Scan Register Allocation for function: " << MFunc->getName() << " =====\n";
bool changed = true;
while(changed) {
// 1. 准备阶段
linearizeBlocks();
computeLiveIntervals();
// 2. 执行线性扫描
changed = linearScan();
// 3. 如果有溢出,重写代码,然后下一轮重新开始
if (changed) {
rewriteProgram();
if (DEBUG) std::cerr << "--- Spilling detected, re-running linear scan ---\n";
}
}
// 4. 将最终分配结果应用到机器指令
applyAllocation();
// 5. 收集用到的被调用者保存寄存器
MFunc->getFrameInfo().vreg_to_preg_map = this->vreg_to_preg_map;
collectUsedCalleeSavedRegs();
if (DEBUG) std::cerr << "===== Finished Linear Scan Register Allocation =====\n\n";
}
// 步骤 1.1: 对基本块进行线性化,这里我们简单地按现有顺序排列
void RISCv64LinearScan::linearizeBlocks() {
linear_order_blocks.clear();
for (auto& mbb : MFunc->getBlocks()) {
linear_order_blocks.push_back(mbb.get());
}
}
// RISCv64LinearScan.cpp
void RISCv64LinearScan::computeLiveIntervals() {
instr_numbering.clear();
live_intervals.clear();
unhandled.clear();
// a. 对所有指令进行线性编号并记录CALL指令的位置
int num = 0;
std::set<int> call_locations;
for (auto* mbb : linear_order_blocks) {
for (auto& instr : mbb->getInstructions()) {
instr_numbering[instr.get()] = num;
if (instr->getOpcode() == RVOpcodes::CALL) {
call_locations.insert(num);
}
num += 2; // 指令编号间隔为2方便在溢出重写时插入指令
}
}
// b. 遍历所有指令记录每个vreg首次和末次出现的位置
std::map<unsigned, std::pair<int, int>> vreg_ranges; // vreg -> {first_instr_num, last_instr_num}
for (auto* mbb : linear_order_blocks) {
for (auto& instr_ptr : mbb->getInstructions()) {
const MachineInstr* instr = instr_ptr.get();
int instr_num = instr_numbering.at(instr);
std::set<unsigned> use, def;
getInstrUseDef(instr, use, def);
auto all_vregs = use;
all_vregs.insert(def.begin(), def.end());
for (unsigned vreg : all_vregs) {
if (vreg_ranges.find(vreg) == vreg_ranges.end()) {
vreg_ranges[vreg] = {instr_num, instr_num};
} else {
vreg_ranges[vreg].second = std::max(vreg_ranges[vreg].second, instr_num);
}
}
}
}
// c. 根据记录的边界创建LiveInterval对象并检查是否跨越CALL
for (auto const& [vreg, range] : vreg_ranges) {
live_intervals.emplace(vreg, LiveInterval(vreg));
auto& interval = live_intervals.at(vreg);
interval.start = range.first;
interval.end = range.second;
// 检查此区间是否跨越了任何CALL指令
auto it = call_locations.lower_bound(interval.start);
if (it != call_locations.end() && *it < interval.end) {
interval.crosses_call = true;
}
}
// d. 将所有计算出的活跃区间放入 unhandled 列表
for (auto& pair : live_intervals) {
unhandled.push_back(&pair.second);
}
std::sort(unhandled.begin(), unhandled.end(), [](const LiveInterval* a, const LiveInterval* b){
return a->start < b->start;
});
}
// RISCv64LinearScan.cpp
// 在类的定义中添加一个辅助函数来判断寄存器类型
bool isCalleeSaved(PhysicalReg preg) {
if (preg >= PhysicalReg::S1 && preg <= PhysicalReg::S11) return true;
if (preg == PhysicalReg::S0) return true; // s0 通常也作为被调用者保存
// 浮点寄存器
if (preg >= PhysicalReg::F8 && preg <= PhysicalReg::F9) return true;
if (preg >= PhysicalReg::F18 && preg <= PhysicalReg::F27) return true;
return false;
}
// 线性扫描主算法
bool RISCv64LinearScan::linearScan() {
active.clear();
spilled_vregs.clear();
vreg_to_preg_map.clear();
// 将寄存器池分为调用者保存和被调用者保存两类
std::set<PhysicalReg> free_caller_int_regs, free_callee_int_regs;
std::set<PhysicalReg> free_caller_fp_regs, free_callee_fp_regs;
for (auto preg : allocable_int_regs) {
if (isCalleeSaved(preg)) free_callee_int_regs.insert(preg);
else free_caller_int_regs.insert(preg);
}
for (auto preg : allocable_fp_regs) {
if (isCalleeSaved(preg)) free_callee_fp_regs.insert(preg);
else free_caller_fp_regs.insert(preg);
}
// 预处理ABI参数寄存器
vreg_to_preg_map.insert(abi_vreg_map.begin(), abi_vreg_map.end());
std::vector<LiveInterval*> normal_unhandled;
for(LiveInterval* interval : unhandled) {
if(abi_vreg_map.count(interval->vreg)) {
active.push_back(interval);
PhysicalReg preg = abi_vreg_map.at(interval->vreg);
if (isFPVReg(interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.erase(preg); else free_caller_fp_regs.erase(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.erase(preg); else free_caller_int_regs.erase(preg);
}
} else {
normal_unhandled.push_back(interval);
}
}
unhandled = normal_unhandled;
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
// 主循环
for (LiveInterval* current : unhandled) {
// a. 释放active列表中已结束的区间
std::vector<LiveInterval*> new_active;
for (LiveInterval* active_interval : active) {
if (active_interval->end < current->start) {
PhysicalReg preg = vreg_to_preg_map.at(active_interval->vreg);
if (isFPVReg(active_interval->vreg)) {
if(isCalleeSaved(preg)) free_callee_fp_regs.insert(preg); else free_caller_fp_regs.insert(preg);
} else {
if(isCalleeSaved(preg)) free_callee_int_regs.insert(preg); else free_caller_int_regs.insert(preg);
}
} else {
new_active.push_back(active_interval);
}
}
active = new_active;
// b. 约束化地为当前区间分配寄存器
bool is_fp = isFPVReg(current->vreg);
auto& free_caller = is_fp ? free_caller_fp_regs : free_caller_int_regs;
auto& free_callee = is_fp ? free_callee_fp_regs : free_callee_int_regs;
PhysicalReg allocated_preg = PhysicalReg::INVALID;
if (current->crosses_call) {
// 跨调用区间:必须使用被调用者保存寄存器
if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
} else {
// 非跨调用区间:优先使用调用者保存寄存器
if (!free_caller.empty()) {
allocated_preg = *free_caller.begin();
free_caller.erase(allocated_preg);
} else if (!free_callee.empty()) {
allocated_preg = *free_callee.begin();
free_callee.erase(allocated_preg);
}
}
if (allocated_preg != PhysicalReg::INVALID) {
vreg_to_preg_map[current->vreg] = allocated_preg;
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
} else {
// c. 没有可用寄存器,需要溢出
spillAtInterval(current);
}
}
return !spilled_vregs.empty();
}
void RISCv64LinearScan::chooseRegForInterval(LiveInterval* current) {
bool is_fp = isFPVReg(current->vreg);
auto& free_regs = is_fp ? free_fp_regs : free_int_regs;
if (!free_regs.empty()) {
// 有可用寄存器
PhysicalReg preg = *free_regs.begin();
free_regs.erase(free_regs.begin());
vreg_to_preg_map[current->vreg] = preg;
active.push_back(current);
// 保持 active 列表按结束点排序
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){
return a->end < b->end;
});
} else {
// 没有可用寄存器,需要溢出
spillAtInterval(current);
}
}
void RISCv64LinearScan::spillAtInterval(LiveInterval* current) {
LiveInterval* spill_candidate = nullptr;
// 启发式溢出:
// 如果current需要callee-saved则从active中找一个占用callee-saved且结束最晚的区间比较
// 否则找active中结束最晚的区间
// 这里简化处理总是找active中结束最晚的区间
auto last_active = active.back();
if (last_active->end > current->end) {
// 溢出active中的区间
spill_candidate = last_active;
PhysicalReg preg = vreg_to_preg_map.at(spill_candidate->vreg);
vreg_to_preg_map[current->vreg] = preg; // 把换出的寄存器给current
// 更新active列表
active.pop_back();
active.push_back(current);
std::sort(active.begin(), active.end(), [](const LiveInterval* a, const LiveInterval* b){ return a->end < b->end; });
spilled_vregs.insert(spill_candidate->vreg);
} else {
// 溢出当前区间
spilled_vregs.insert(current->vreg);
}
}
// 步骤 3: 重写程序,插入溢出代码
void RISCv64LinearScan::rewriteProgram() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
int spill_offset = frame_info.locals_size; // 溢出区域接在局部变量之后
for (unsigned vreg : spilled_vregs) {
if (frame_info.spill_offsets.count(vreg)) continue; // 避免重复分配
int size = isFPVReg(vreg) ? 4 : (vreg_type_map.at(vreg)->isPointer() ? 8 : 4);
spill_offset += size;
spill_offset = (spill_offset + 7) & ~7; // 8字节对齐
frame_info.spill_offsets[vreg] = -(16 + spill_offset);
}
frame_info.spill_size = spill_offset - frame_info.locals_size;
for (auto& mbb : MFunc->getBlocks()) {
auto& instrs = mbb->getInstructions();
std::vector<std::unique_ptr<MachineInstr>> new_instrs;
for (auto it = instrs.begin(); it != instrs.end(); ++it) {
auto& instr = *it;
std::set<unsigned> use_vregs, def_vregs;
getInstrUseDef(instr.get(), use_vregs, def_vregs);
// 建立溢出vreg到新临时vreg的映射
std::map<unsigned, unsigned> use_remap;
std::map<unsigned, unsigned> def_remap;
// 1. 为所有溢出的USE创建LOAD指令和映射
for (unsigned old_vreg : use_vregs) {
if (spilled_vregs.count(old_vreg) && use_remap.find(old_vreg) == use_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
use_remap[old_vreg] = new_temp_vreg;
RVOpcodes load_op = isFPVReg(old_vreg) ? RVOpcodes::FLW : (type->isPointer() ? RVOpcodes::LD : RVOpcodes::LW);
auto load = std::make_unique<MachineInstr>(load_op);
load->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
load->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
));
new_instrs.push_back(std::move(load));
}
}
// 2. 为所有溢出的DEF创建映射
for (unsigned old_vreg : def_vregs) {
if (spilled_vregs.count(old_vreg) && def_remap.find(old_vreg) == def_remap.end()) {
Type* type = vreg_type_map.at(old_vreg);
unsigned new_temp_vreg = ISel->getNewVReg(type);
def_remap[old_vreg] = new_temp_vreg;
}
}
// 3. 基于角色精确地替换原指令中的操作数
auto opcode = instr->getOpcode();
auto& operands = instr->getOperands();
auto replace_reg_op = [](RegOperand* reg_op, const std::map<unsigned, unsigned>& remap) {
if (reg_op->isVirtual() && remap.count(reg_op->getVRegNum())) {
reg_op->setVRegNum(remap.at(reg_op->getVRegNum()));
}
};
if (op_info.count(opcode)) {
const auto& info = op_info.at(opcode);
// 替换 Defs
for (int idx : info.first) {
if (idx < operands.size() && operands[idx]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), def_remap);
}
}
// 替换 Uses
for (int idx : info.second) {
if (idx < operands.size()) {
if (operands[idx]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[idx].get()), use_remap);
} else if (operands[idx]->getKind() == MachineOperand::KIND_MEM) {
replace_reg_op(static_cast<MemOperand*>(operands[idx].get())->getBase(), use_remap);
}
}
}
} else if (opcode == RVOpcodes::CALL) {
// 特殊处理 CALL 指令
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[0].get()), def_remap);
}
for (size_t i = 1; i < operands.size(); ++i) {
if (operands[i]->getKind() == MachineOperand::KIND_REG) {
replace_reg_op(static_cast<RegOperand*>(operands[i].get()), use_remap);
}
}
}
// 4. 将修改后的指令放入新列表
new_instrs.push_back(std::move(instr));
// 5. 为所有溢出的DEF创建STORE指令
for(const auto& pair : def_remap) {
unsigned old_vreg = pair.first;
unsigned new_temp_vreg = pair.second;
Type* type = vreg_type_map.at(old_vreg);
RVOpcodes store_op = isFPVReg(old_vreg) ? RVOpcodes::FSW : (type->isPointer() ? RVOpcodes::SD : RVOpcodes::SW);
auto store = std::make_unique<MachineInstr>(store_op);
store->addOperand(std::make_unique<RegOperand>(new_temp_vreg));
store->addOperand(std::make_unique<MemOperand>(
std::make_unique<RegOperand>(PhysicalReg::S0),
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
));
new_instrs.push_back(std::move(store));
}
}
instrs = std::move(new_instrs);
}
}
// 步骤 4: 应用最终分配结果
void RISCv64LinearScan::applyAllocation() {
for (auto& mbb : MFunc->getBlocks()) {
for (auto& instr_ptr : mbb->getInstructions()) {
for (auto& op_ptr : instr_ptr->getOperands()) {
if (op_ptr->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<RegOperand*>(op_ptr.get());
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
// 如果一个vreg最终没有颜色这通常意味着它是一个短生命周期的临时变量
// 在溢出重写中产生,但在下一轮分配前就被优化掉了。
// 或者是一个从未被使用的定义。
// 给他一个临时寄存器以防万一。
reg_op->setPReg(PhysicalReg::T5);
}
}
} else if (op_ptr->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<MemOperand*>(op_ptr.get());
auto reg_op = mem_op->getBase();
if (reg_op->isVirtual()) {
unsigned vreg = reg_op->getVRegNum();
if (vreg_to_preg_map.count(vreg)) {
reg_op->setPReg(vreg_to_preg_map.at(vreg));
} else {
reg_op->setPReg(PhysicalReg::T5);
}
}
}
}
}
}
}
void RISCv64LinearScan::getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def) {
// 这个函数与图着色版本中的 getInstrUseDef 逻辑完全相同,此处直接复用
auto opcode = instr->getOpcode();
const auto& operands = instr->getOperands();
// op_info 的定义已被移到函数外部的命名空间中
auto get_vreg_id_if_virtual = [&](const MachineOperand* op, std::set<unsigned>& s) {
if (op->getKind() == MachineOperand::KIND_REG) {
auto reg_op = static_cast<const RegOperand*>(op);
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
} else if (op->getKind() == MachineOperand::KIND_MEM) {
auto mem_op = static_cast<const MemOperand*>(op);
auto reg_op = mem_op->getBase();
if (reg_op->isVirtual()) s.insert(reg_op->getVRegNum());
}
};
if (op_info.count(opcode)) {
const auto& info = op_info.at(opcode);
for (int idx : info.first) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), def);
for (int idx : info.second) if (idx < operands.size()) get_vreg_id_if_virtual(operands[idx].get(), use);
// MemOperand 的基址寄存器总是一个 use
for (const auto& op : operands) if (op->getKind() == MachineOperand::KIND_MEM) get_vreg_id_if_virtual(op.get(), use);
} else if (opcode == RVOpcodes::CALL) {
// CALL指令的特殊处理
// 第一个操作数如果有是def返回值
if (!operands.empty() && operands[0]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[0].get(), def);
// 后续的寄存器操作数是use参数
for (size_t i = 1; i < operands.size(); ++i) if (operands[i]->getKind() == MachineOperand::KIND_REG) get_vreg_id_if_virtual(operands[i].get(), use);
}
}
// 辅助函数: 判断是否为浮点vreg
bool RISCv64LinearScan::isFPVReg(unsigned vreg) const {
return vreg_type_map.count(vreg) && vreg_type_map.at(vreg)->isFloat();
}
// 辅助函数: 收集被使用的被调用者保存寄存器
void RISCv64LinearScan::collectUsedCalleeSavedRegs() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
frame_info.used_callee_saved_regs.clear();
const auto& callee_saved_int = getCalleeSavedIntRegs();
const auto& callee_saved_fp = getCalleeSavedFpRegs();
std::set<PhysicalReg> callee_saved_set(callee_saved_int.begin(), callee_saved_int.end());
callee_saved_set.insert(callee_saved_fp.begin(), callee_saved_fp.end());
callee_saved_set.insert(PhysicalReg::S0); // s0总是被用作帧指针
for(const auto& pair : vreg_to_preg_map) {
PhysicalReg preg = pair.second;
if(callee_saved_set.count(preg)) {
frame_info.used_callee_saved_regs.insert(preg);
}
}
}
} // namespace sysy

View File

@@ -93,7 +93,7 @@ bool RISCv64RegAlloc::doAllocation() {
} }
void RISCv64RegAlloc::precolorByCallingConvention() { void RISCv64RegAlloc::precolorByCallingConvention() {
// [新增] 在处理前,先清空颜色相关的状态,确保重试时不会出错 // 在处理前,先清空颜色相关的状态,确保重试时不会出错
color_map.clear(); color_map.clear();
coloredNodes.clear(); coloredNodes.clear();
@@ -122,30 +122,6 @@ void RISCv64RegAlloc::precolorByCallingConvention() {
} }
} }
// // --- 部分2为CALL指令的返回值预着色 ---
// for (auto& mbb : MFunc->getBlocks()) {
// for (auto& instr : mbb->getInstructions()) {
// if (instr->getOpcode() == RVOpcodes::CALL) {
// if (!instr->getOperands().empty() &&
// instr->getOperands().front()->getKind() == MachineOperand::KIND_REG)
// {
// auto reg_op = static_cast<RegOperand*>(instr->getOperands().front().get());
// if (reg_op->isVirtual()) {
// unsigned ret_vreg = reg_op->getVRegNum();
// assert(vreg_to_value_map.count(ret_vreg) && "Return vreg not found!");
// Value* ret_val = vreg_to_value_map.at(ret_vreg);
// if (ret_val->getType()->isFloat()) {
// color_map[ret_vreg] = PhysicalReg::F10; // fa0
// } else {
// color_map[ret_vreg] = PhysicalReg::A0; // a0
// }
// }
// }
// }
// }
// }
// 将所有预着色的vreg视为已着色节点 // 将所有预着色的vreg视为已着色节点
for(const auto& pair : color_map) { for(const auto& pair : color_map) {
coloredNodes.insert(pair.first); coloredNodes.insert(pair.first);
@@ -168,7 +144,7 @@ void RISCv64RegAlloc::initialize() {
spillWorklist.clear(); spillWorklist.clear();
spilledNodes.clear(); spilledNodes.clear();
coalescedNodes.clear(); coalescedNodes.clear();
coloredNodes.clear(); // [修正] 恢复对这两个集合的清除 coloredNodes.clear();
selectStack.clear(); selectStack.clear();
coalescedMoves.clear(); coalescedMoves.clear();
@@ -181,7 +157,7 @@ void RISCv64RegAlloc::initialize() {
degree.clear(); degree.clear();
moveList.clear(); moveList.clear();
alias.clear(); alias.clear();
color_map.clear(); // [修正] 恢复对 color_map 的清除 color_map.clear();
} }
// 活跃性分析(此部分为标准数据流分析,与现有版本类似但更精细) // 活跃性分析(此部分为标准数据流分析,与现有版本类似但更精细)
@@ -197,7 +173,6 @@ void RISCv64RegAlloc::analyzeLiveness() {
VRegSet uses, defs; VRegSet uses, defs;
for (const auto& instr_ptr : mbb->getInstructions()) { for (const auto& instr_ptr : mbb->getInstructions()) {
VRegSet instr_use, instr_def; VRegSet instr_use, instr_def;
// 使用新的、能看到物理寄存器的版本
getInstrUseDef_Liveness(instr_ptr.get(), instr_use, instr_def); getInstrUseDef_Liveness(instr_ptr.get(), instr_use, instr_def);
for (unsigned u : instr_use) { for (unsigned u : instr_use) {
if (defs.find(u) == defs.end()) uses.insert(u); if (defs.find(u) == defs.end()) uses.insert(u);
@@ -238,7 +213,7 @@ void RISCv64RegAlloc::analyzeLiveness() {
const MachineInstr* instr = instr_it->get(); const MachineInstr* instr = instr_it->get();
live_out_map[instr] = current_live; live_out_map[instr] = current_live;
VRegSet use, def; VRegSet use, def;
// 使用新的、能看到物理寄存器的版本
getInstrUseDef_Liveness(instr, use, def); getInstrUseDef_Liveness(instr, use, def);
for(auto d : def) current_live.erase(d); for(auto d : def) current_live.erase(d);
for(auto u : use) current_live.insert(u); for(auto u : use) current_live.insert(u);
@@ -247,7 +222,6 @@ void RISCv64RegAlloc::analyzeLiveness() {
} }
} }
// [最终修正] 包含了所有正确逻辑和您已有调试代码的完整版本
void RISCv64RegAlloc::build() { void RISCv64RegAlloc::build() {
initial.clear(); initial.clear();
RISCv64AsmPrinter printer_inside_build(MFunc); RISCv64AsmPrinter printer_inside_build(MFunc);
@@ -403,15 +377,33 @@ void RISCv64RegAlloc::build() {
} }
// --- 规则 3: Live_Out 集合内部的【虚拟寄存器】形成完全图 --- // --- 规则 3: Live_Out 集合内部的【虚拟寄存器】形成完全图 ---
// [优化与修正] 使用更高效的遍历,避免重复调用 addEdge(A,B) 和 addEdge(B,A) // 使用更高效的遍历,避免重复调用 addEdge(A,B) 和 addEdge(B,A)
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) { // 添加限制以防止过度密集的图
unsigned l1 = *it1; const size_t MAX_LIVE_OUT_SIZE = 32; // 限制最大活跃变量数
// [关键修正] 只为虚拟寄存器 l1 添加边 if (live_out.size() > MAX_LIVE_OUT_SIZE) {
if (precolored.count(l1)) continue; // 对于大量活跃变量,使用更保守的边添加策略
// 只添加必要的边,而不是完全图
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) {
unsigned l1 = *it1;
if (precolored.count(l1)) continue;
// 只添加与定义变量相关的边
for (unsigned d : def) {
if (d != l1 && !precolored.count(d)) {
addEdge(l1, d);
}
}
}
} else {
// 对于较小的集合,使用原来的完全图方法
for (auto it1 = live_out.begin(); it1 != live_out.end(); ++it1) {
unsigned l1 = *it1;
if (precolored.count(l1)) continue;
for (auto it2 = std::next(it1); it2 != live_out.end(); ++it2) { for (auto it2 = std::next(it1); it2 != live_out.end(); ++it2) {
unsigned l2 = *it2; unsigned l2 = *it2;
addEdge(l1, l2); addEdge(l1, l2);
}
} }
} }
} }
@@ -463,6 +455,17 @@ void RISCv64RegAlloc::coalesce() {
unsigned y = getAlias(*use.begin()); unsigned y = getAlias(*use.begin());
unsigned u, v; unsigned u, v;
if (precolored.count(y)) { u = y; v = x; } else { u = x; v = y; } if (precolored.count(y)) { u = y; v = x; } else { u = x; v = y; }
// 防御性检查,处理物理寄存器之间的传送指令
if (precolored.count(u) && precolored.count(v)) {
// 如果 u 和 v 都是物理寄存器,我们不能合并它们。
// 这通常是一条寄存器拷贝指令,例如 `mv a2, a1`。
// 把它加入 constrainedMoves 列表,然后直接返回,不再处理。
constrainedMoves.insert(move);
// addWorklist(u) 和 addWorklist(v) 在这里也不需要调用,
// 因为它们只对虚拟寄存器有意义。
return;
}
if (DEEPERDEBUG) std::cerr << "[Coalesce] Processing move between " << regIdToString(x) if (DEEPERDEBUG) std::cerr << "[Coalesce] Processing move between " << regIdToString(x)
<< " and " << regIdToString(y) << " (aliases " << regIdToString(u) << " and " << regIdToString(y) << " (aliases " << regIdToString(u)
@@ -484,8 +487,6 @@ void RISCv64RegAlloc::coalesce() {
addWorklist(v); addWorklist(v);
return; // 立即返回,不再进行后续检查 return; // 立即返回,不再进行后续检查
} }
// --- 新的、拆分后的启发式检查逻辑 ---
bool pre_interfere = adjList.at(v).count(u); bool pre_interfere = adjList.at(v).count(u);
@@ -504,8 +505,6 @@ void RISCv64RegAlloc::coalesce() {
// --- 场景1u是物理寄存器使用 George 启发式 --- // --- 场景1u是物理寄存器使用 George 启发式 ---
if (DEEPERDEBUG) std::cerr << " -> Trying George Heuristic (u is precolored)...\n"; if (DEEPERDEBUG) std::cerr << " -> Trying George Heuristic (u is precolored)...\n";
// ==================== [展开的 std::all_of 逻辑] ====================
// 步骤 1: 独立调用 adjacent(v) 获取邻居集合 // 步骤 1: 独立调用 adjacent(v) 获取邻居集合
VRegSet neighbors_of_v = adjacent(v); VRegSet neighbors_of_v = adjacent(v);
if (DEEPERDEBUG) { if (DEEPERDEBUG) {
@@ -537,7 +536,6 @@ void RISCv64RegAlloc::coalesce() {
if (DEEPERDEBUG) { if (DEEPERDEBUG) {
std::cerr << " -> George Heuristic final result: " << (george_ok ? "OK" : "FAIL") << "\n"; std::cerr << " -> George Heuristic final result: " << (george_ok ? "OK" : "FAIL") << "\n";
} }
// =================================================================
if (george_ok) { if (george_ok) {
can_coalesce = true; can_coalesce = true;
@@ -622,11 +620,11 @@ void RISCv64RegAlloc::assignColors() {
} }
} }
// 步骤 2: [最终修正] 完整、正确地处理 coalescedNodes // 步骤 2: 处理 coalescedNodes
for (unsigned n : coalescedNodes) { for (unsigned n : coalescedNodes) {
unsigned root_alias = getAlias(n); unsigned root_alias = getAlias(n);
// --- 新的、健壮的逻辑,处理所有三种可能性 --- // --- 处理所有三种可能性 ---
// 情况 1: 别名本身就是物理寄存器 (修复当前bug) // 情况 1: 别名本身就是物理寄存器 (修复当前bug)
if (precolored.count(root_alias)) { if (precolored.count(root_alias)) {
@@ -649,9 +647,13 @@ void RISCv64RegAlloc::assignColors() {
// 重写程序,插入溢出代码 // 重写程序,插入溢出代码
void RISCv64RegAlloc::rewriteProgram() { void RISCv64RegAlloc::rewriteProgram() {
// 1. 为溢出的旧vreg在栈上分配空间
StackFrameInfo& frame_info = MFunc->getFrameInfo(); StackFrameInfo& frame_info = MFunc->getFrameInfo();
int spill_base_offset = frame_info.locals_size + frame_info.callee_saved_size; // 使用 EFI Pass 确定的 locals_end_offset 作为溢出分配的基准。
// locals_end_offset 本身是负数,代表局部变量区域的下边界地址。
int spill_current_offset = frame_info.locals_end_offset - frame_info.spill_size;
// 保存溢出区域的起始点,用于最后计算总的 spill_size
const int spill_start_offset = frame_info.locals_end_offset;
for (unsigned vreg : spilledNodes) { for (unsigned vreg : spilledNodes) {
if (frame_info.spill_offsets.count(vreg)) continue; if (frame_info.spill_offsets.count(vreg)) continue;
@@ -663,11 +665,19 @@ void RISCv64RegAlloc::rewriteProgram() {
size = 8; // pointer size = 8; // pointer
} }
spill_base_offset += size; // 在当前偏移基础上继续向下(地址变得更负)分配空间
spill_base_offset = (spill_base_offset + 7) & ~7; spill_current_offset -= size;
frame_info.spill_offsets[vreg] = -spill_base_offset; // [修正] 溢出槽也使用负偏移量
// 对齐新的、更小的地址RISC-V 要求8字节对齐
spill_current_offset = spill_current_offset & ~7;
// 将计算出的、不会冲突的正确偏移量存入 spill_offsets
frame_info.spill_offsets[vreg] = spill_current_offset;
} }
frame_info.spill_size = spill_base_offset - (frame_info.locals_size + frame_info.callee_saved_size);
// 更新总的溢出区域大小。
// spill_size = -(结束偏移 - 开始偏移)
frame_info.spill_size = -(spill_current_offset - spill_start_offset);
// 2. 遍历所有指令,重写代码 // 2. 遍历所有指令,重写代码
for (auto& mbb : MFunc->getBlocks()) { for (auto& mbb : MFunc->getBlocks()) {
@@ -711,7 +721,7 @@ void RISCv64RegAlloc::rewriteProgram() {
} }
} }
// c. [核心修正] 创建一条全新的指令用新vreg替换旧vreg // c. 创建一条全新的指令用新vreg替换旧vreg
auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode()); auto new_instr = std::make_unique<MachineInstr>(instr_ptr->getOpcode());
for (const auto& op : instr_ptr->getOperands()) { for (const auto& op : instr_ptr->getOperands()) {
if (op->getKind() == MachineOperand::KIND_REG) { if (op->getKind() == MachineOperand::KIND_REG) {
@@ -771,6 +781,11 @@ void RISCv64RegAlloc::rewriteProgram() {
std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg)) std::make_unique<ImmOperand>(frame_info.spill_offsets.at(old_vreg))
)); ));
new_instructions.push_back(std::move(store)); new_instructions.push_back(std::move(store));
if (DEEPERDEBUG) {
std::cerr << "[Spill] Inserted spill store for %vreg" << old_vreg
<< " at offset " << frame_info.spill_offsets.at(old_vreg)
<< " with new temp vreg " << regIdToString(new_temp_vreg) << ".\n";
}
} }
} }
mbb->getInstructions() = std::move(new_instructions); mbb->getInstructions() = std::move(new_instructions);
@@ -781,7 +796,7 @@ void RISCv64RegAlloc::rewriteProgram() {
} }
/** /**
* @brief [最终修正] 获取一条指令完整的【虚拟】使用/定义寄存器集合 * @brief 获取一条指令完整的【虚拟】使用/定义寄存器集合
* 这个函数将服务于图的构建收集initial节点等 * 这个函数将服务于图的构建收集initial节点等
*/ */
void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def) { void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VRegSet& def) {
@@ -832,10 +847,8 @@ void RISCv64RegAlloc::getInstrUseDef(const MachineInstr* instr, VRegSet& use, VR
} }
} }
// in file: RISCv64RegAlloc.cpp
/** /**
* @brief [最终修复版] 获取一条指令完整的、包含物理寄存器的Use/Def集合 * @brief 获取一条指令完整的、包含物理寄存器的Use/Def集合
* 这个函数专门服务于活跃性分析,现已补全所有指令(包括伪指令)的逻辑。 * 这个函数专门服务于活跃性分析,现已补全所有指令(包括伪指令)的逻辑。
*/ */
void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) { void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet& use, VRegSet& def) {
@@ -943,7 +956,6 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
else if (opcode == RVOpcodes::JALR) { else if (opcode == RVOpcodes::JALR) {
// JALR rd, rs1, imm. Def: rd, Use: rs1. // JALR rd, rs1, imm. Def: rd, Use: rs1.
// 同时也隐式定义了ra(x1)但通常rd就是ra。为精确我们只处理显式操作数。 // 同时也隐式定义了ra(x1)但通常rd就是ra。为精确我们只处理显式操作数。
// 旧版本逻辑def.insert(ra); first_reg_is_def = false; -> 这是不精确的
def.insert(get_any_reg_id(operands[0].get())); def.insert(get_any_reg_id(operands[0].get()));
use.insert(get_any_reg_id(operands[1].get())); use.insert(get_any_reg_id(operands[1].get()));
} }
@@ -952,7 +964,7 @@ void RISCv64RegAlloc::getInstrUseDef_Liveness(const MachineInstr* instr, VRegSet
use.insert(offset + static_cast<unsigned>(PhysicalReg::A0)); use.insert(offset + static_cast<unsigned>(PhysicalReg::A0));
use.insert(offset + static_cast<unsigned>(PhysicalReg::F10)); // F10 is fa0 use.insert(offset + static_cast<unsigned>(PhysicalReg::F10)); // F10 is fa0
} }
// [关键Bug修复] 添加对 PSEUDO_KEEPALIVE 的处理 // 添加对 PSEUDO_KEEPALIVE 的处理
else if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) { else if (opcode == RVOpcodes::PSEUDO_KEEPALIVE) {
// keepalive的所有操作数都是use以确保它们的生命周期延续到该点 // keepalive的所有操作数都是use以确保它们的生命周期延续到该点
for (const auto& op : operands) { for (const auto& op : operands) {
@@ -1212,7 +1224,7 @@ bool RISCv64RegAlloc::briggsHeuristic(unsigned u, unsigned v) {
// George启发式 // George启发式
bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) { bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
// 关键修正:如果 t 不是一个待分配的虚拟寄存器(即它是物理寄存器), // 如果 t 不是一个待分配的虚拟寄存器(即它是物理寄存器),
// 那么它已经被预着色,总是满足 George 启发式条件。 // 那么它已经被预着色,总是满足 George 启发式条件。
// 我们通过检查 degree.count(t) 来判断 t 是否在我们的虚拟寄存器工作集中。 // 我们通过检查 degree.count(t) 来判断 t 是否在我们的虚拟寄存器工作集中。
if (degree.count(t) == 0) { if (degree.count(t) == 0) {
@@ -1224,44 +1236,6 @@ bool RISCv64RegAlloc::georgeHeuristic(unsigned t, unsigned u) {
return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u); return degree.at(t) < K || precolored.count(u) || adjList.at(t).count(u);
} }
// void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
// // 1. 从相应的工作列表中移除即将被合并的节点 v
// if (freezeWorklist.count(v)) {
// freezeWorklist.erase(v);
// } else {
// spillWorklist.erase(v);
// }
// // 2. 将 v 加入 coalescedNodes 集合,并设置其别名
// coalescedNodes.insert(v);
// alias[v] = u;
// // 3. 将 v 的传送指令列表合并到 u
// if (moveList.count(u) && moveList.count(v)) {
// moveList.at(u).insert(moveList.at(v).begin(), moveList.at(v).end());
// } else if (moveList.count(v)) {
// moveList[u] = moveList.at(v);
// }
// // [Bug修复] 移除了论文伪代码中不存在的 enableMoves({v}) 调用。
// // 4. [核心Bug修复] 遍历 v 的“当前有效”邻居 t (使用 adjacent(v) 而非 adjList.at(v))
// // 将它们与 u 连接,并更新它们的度数。
// for (unsigned t : adjacent(v)) {
// addEdge(t, u);
// decrementDegree(t);
// }
// // 5. 检查合并后的节点 u 的状态,如果其度数变高,可能需要将其移到 spillWorklist
// if (!precolored.count(u)) {
// int K = isFPVReg(u) ? K_fp : K_int;
// if (degree.at(u) >= K && freezeWorklist.count(u)) {
// freezeWorklist.erase(u);
// spillWorklist.insert(u);
// }
// }
// }
void RISCv64RegAlloc::combine(unsigned u, unsigned v) { void RISCv64RegAlloc::combine(unsigned u, unsigned v) {
freezeWorklist.erase(v); freezeWorklist.erase(v);
spillWorklist.erase(v); spillWorklist.erase(v);
@@ -1377,9 +1351,9 @@ void RISCv64RegAlloc::applyColoring() {
// 使用 setPReg 将虚拟寄存器转换为物理寄存器 // 使用 setPReg 将虚拟寄存器转换为物理寄存器
reg_op->setPReg(color_map.at(vreg)); reg_op->setPReg(color_map.at(vreg));
} else { } else {
// 如果一个vreg在成功分配后仍然没有颜色这是一个错误 // 如果一个vreg在成功分配后仍然没有颜色可能是紧急溢出
std::cerr << "FATAL: Virtual register %vreg" << vreg << " has no color after allocation!\n"; // std::cerr << "WARNING: Virtual register %vreg" << vreg << " has no color after allocation, treating as spilled\n";
assert(false && "Virtual register has no color after allocation!"); // 在紧急溢出情况下,使用临时寄存器
reg_op->setPReg(PhysicalReg::T6); reg_op->setPReg(PhysicalReg::T6);
} }
} }
@@ -1391,7 +1365,7 @@ void RISCv64RegAlloc::applyColoring() {
if (color_map.count(vreg)) { if (color_map.count(vreg)) {
reg_op->setPReg(color_map.at(vreg)); reg_op->setPReg(color_map.at(vreg));
} else { } else {
assert(false && "Virtual register in memory operand has no color!"); // std::cerr << "WARNING: Virtual register in memory operand has no color, using T6\n";
reg_op->setPReg(PhysicalReg::T6); reg_op->setPReg(PhysicalReg::T6);
} }
} }
@@ -1483,7 +1457,6 @@ std::string RISCv64RegAlloc::regToString(PhysicalReg reg) {
std::string RISCv64RegAlloc::regIdToString(unsigned id) { std::string RISCv64RegAlloc::regIdToString(unsigned id) {
const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID); const unsigned offset = static_cast<unsigned>(PhysicalReg::PHYS_REG_START_ID);
// 使用更健壮的检查方式
if (id >= offset && precolored.count(id)) { if (id >= offset && precolored.count(id)) {
// 先减去偏移量,得到原始的、小的枚举值 // 先减去偏移量,得到原始的、小的枚举值
PhysicalReg reg = static_cast<PhysicalReg>(id - offset); PhysicalReg reg = static_cast<PhysicalReg>(id - offset);

View File

@@ -0,0 +1,30 @@
#ifndef RISCV64_DIV_STRENGTH_REDUCTION_H
#define RISCV64_DIV_STRENGTH_REDUCTION_H
#include "RISCv64LLIR.h"
#include "Pass.h"
namespace sysy {
/**
* @class DivStrengthReduction
* @brief 除法强度削弱优化器
* * 将除法运算转换为乘法运算使用magic number算法
* 适用于除数为常数的情况,可以显著提高性能
*/
class DivStrengthReduction : public Pass {
public:
static char ID;
DivStrengthReduction() : Pass("div-strength-reduction", Granularity::Function, PassKind::Optimization) {}
void *getPassID() const override { return &ID; }
bool runOnFunction(Function *F, AnalysisManager& AM) override;
void runOnMachineFunction(MachineFunction* mfunc);
};
} // namespace sysy
#endif // RISCV64_DIV_STRENGTH_REDUCTION_H

View File

@@ -20,6 +20,8 @@ public:
void setStream(std::ostream& os) { OS = &os; } void setStream(std::ostream& os) { OS = &os; }
// 辅助函数 // 辅助函数
std::string regToString(PhysicalReg reg); std::string regToString(PhysicalReg reg);
std::string formatInstr(const MachineInstr *instr);
private: private:
// 打印各个部分 // 打印各个部分
void printBasicBlock(MachineBasicBlock* mbb, bool debug = false); void printBasicBlock(MachineBasicBlock* mbb, bool debug = false);

View File

@@ -24,7 +24,7 @@ private:
// 私有辅助函数,用于根据类型计算其占用的字节数。 // 私有辅助函数,用于根据类型计算其占用的字节数。
unsigned getTypeSizeInBytes(Type* type); unsigned getTypeSizeInBytes(Type* type);
Module* module; Module* module;
}; };

View File

@@ -3,6 +3,12 @@
#include "RISCv64LLIR.h" #include "RISCv64LLIR.h"
// Forward declarations
namespace sysy {
class GlobalValue;
class Value;
}
extern int DEBUG; extern int DEBUG;
extern int DEEPDEBUG; extern int DEEPDEBUG;
@@ -16,8 +22,8 @@ public:
// 公开接口以便后续模块如RegAlloc可以查询或创建vreg // 公开接口以便后续模块如RegAlloc可以查询或创建vreg
unsigned getVReg(Value* val); unsigned getVReg(Value* val);
unsigned getNewVReg() { return vreg_counter++; } unsigned getNewVReg(Type* type);
unsigned getNewVReg(Type* type); unsigned getVRegCounter() const;
// 获取 vreg_map 的公共接口 // 获取 vreg_map 的公共接口
const std::map<Value*, unsigned>& getVRegMap() const { return vreg_map; } const std::map<Value*, unsigned>& getVRegMap() const { return vreg_map; }
const std::map<unsigned, Value*>& getVRegValueMap() const { return vreg_to_value_map; } const std::map<unsigned, Value*>& getVRegValueMap() const { return vreg_to_value_map; }

View File

@@ -39,14 +39,16 @@ enum class PhysicalReg {
// 用于内部表示物理寄存器在干扰图中的节点ID一个简单的特殊ID确保不与vreg_counter冲突 // 用于内部表示物理寄存器在干扰图中的节点ID一个简单的特殊ID确保不与vreg_counter冲突
// 假设 vreg_counter 不会达到这么大的值 // 假设 vreg_counter 不会达到这么大的值
PHYS_REG_START_ID = 100000, PHYS_REG_START_ID = 1000000,
PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间 PHYS_REG_END_ID = PHYS_REG_START_ID + 320, // 预留足够的空间
INVALID, ///< 无效寄存器标记
}; };
// RISC-V 指令操作码枚举 // RISC-V 指令操作码枚举
enum class RVOpcodes { enum class RVOpcodes {
// 算术指令 // 算术指令
ADD, ADDI, ADDW, ADDIW, SUB, SUBW, MUL, MULW, DIV, DIVW, REM, REMW, ADD, ADDI, ADDW, ADDIW, SUB, SUBW, MUL, MULW, MULH, DIV, DIVW, REM, REMW,
// 逻辑指令 // 逻辑指令
XOR, XORI, OR, ORI, AND, ANDI, XOR, XORI, OR, ORI, AND, ANDI,
// 移位指令 // 移位指令
@@ -86,6 +88,7 @@ enum class RVOpcodes {
// 浮点转换 // 浮点转换
FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点) FCVT_S_W, // fcvt.s.w rd, rs1 (有符号整数 -> 单精度浮点)
FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数) FCVT_W_S, // fcvt.w.s rd, rs1 (单精度浮点 -> 有符号整数)
FCVT_W_S_RTZ, // fcvt.w.s rd, rs1, rtz (使用向零截断模式)
// 浮点传送/移动 // 浮点传送/移动
FMV_S, // fmv.s rd, rs1 (浮点寄存器之间) FMV_S, // fmv.s rd, rs1 (浮点寄存器之间)
@@ -280,14 +283,15 @@ private:
// 栈帧信息 // 栈帧信息
struct StackFrameInfo { struct StackFrameInfo {
int locals_size = 0; // 仅为AllocaInst分配的大小 int locals_size = 0; // 仅为AllocaInst分配的大小
int locals_end_offset = 0; // 记录局部变量分配结束后的偏移量(相对于s0为负)
int spill_size = 0; // 仅为溢出分配的大小 int spill_size = 0; // 仅为溢出分配的大小
int total_size = 0; // 总大小 int total_size = 0; // 总大小
int callee_saved_size = 0; // 保存寄存器的大小 int callee_saved_size = 0; // 保存寄存器的大小
std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移> std::map<unsigned, int> alloca_offsets; // <AllocaInst的vreg, 栈偏移>
std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移> std::map<unsigned, int> spill_offsets; // <溢出vreg, 栈偏移>
std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器 std::set<PhysicalReg> used_callee_saved_regs; // 使用的保存寄存器
std::map<unsigned, PhysicalReg> vreg_to_preg_map; // [新增] RegAlloc最终的分配结果 std::map<unsigned, PhysicalReg> vreg_to_preg_map; // RegAlloc最终的分配结果
std::vector<PhysicalReg> callee_saved_regs_to_store; // [新增] 已排序的、需要存取的被调用者保存寄存器 std::vector<PhysicalReg> callee_saved_regs_to_store; // 已排序的、需要存取的被调用者保存寄存器
}; };
// 机器函数 // 机器函数

View File

@@ -0,0 +1,104 @@
#ifndef RISCV64_LINEARSCAN_H
#define RISCV64_LINEARSCAN_H
#include "RISCv64LLIR.h"
#include "RISCv64ISel.h"
#include <vector>
#include <map>
#include <set>
#include <algorithm>
namespace sysy {
// 前向声明
class MachineBasicBlock;
class MachineFunction;
class RISCv64ISel;
/**
* @brief 表示一个虚拟寄存器的活跃区间。
* 包含起始和结束指令编号。为了简化,我们不处理有“洞”的区间。
*/
struct LiveInterval {
unsigned vreg = 0;
int start = -1;
int end = -1;
bool crosses_call = false;
LiveInterval(unsigned vreg) : vreg(vreg) {}
// 用于排序,按起始点从小到大
bool operator<(const LiveInterval& other) const {
return start < other.start;
}
};
class RISCv64LinearScan {
public:
RISCv64LinearScan(MachineFunction* mfunc);
void run();
private:
// --- 核心算法流程 ---
void linearizeBlocks();
void computeLiveIntervals();
bool linearScan();
void rewriteProgram();
void applyAllocation();
void chooseRegForInterval(LiveInterval* current);
void spillAtInterval(LiveInterval* current);
// --- 辅助函数 ---
void getInstrUseDef(const MachineInstr* instr, std::set<unsigned>& use, std::set<unsigned>& def);
bool isFPVReg(unsigned vreg) const;
void collectUsedCalleeSavedRegs();
MachineFunction* MFunc;
RISCv64ISel* ISel;
// --- 线性扫描数据结构 ---
std::vector<MachineBasicBlock*> linear_order_blocks;
std::map<const MachineInstr*, int> instr_numbering;
std::map<unsigned, LiveInterval> live_intervals;
std::vector<LiveInterval*> unhandled;
std::vector<LiveInterval*> active; // 活跃且已分配物理寄存器的区间
std::set<unsigned> spilled_vregs; // 记录在本轮被决定溢出的vreg
// --- 寄存器池和分配结果 ---
std::vector<PhysicalReg> allocable_int_regs;
std::vector<PhysicalReg> allocable_fp_regs;
std::set<PhysicalReg> free_int_regs;
std::set<PhysicalReg> free_fp_regs;
std::map<unsigned, PhysicalReg> vreg_to_preg_map;
std::map<unsigned, PhysicalReg> abi_vreg_map;
const std::map<unsigned, Type*>& vreg_type_map;
};
static const std::map<RVOpcodes, std::pair<std::vector<int>, std::vector<int>>> op_info = {
{RVOpcodes::ADD, {{0}, {1, 2}}}, {RVOpcodes::SUB, {{0}, {1, 2}}}, {RVOpcodes::MUL, {{0}, {1, 2}}},
{RVOpcodes::DIV, {{0}, {1, 2}}}, {RVOpcodes::REM, {{0}, {1, 2}}}, {RVOpcodes::ADDW, {{0}, {1, 2}}},
{RVOpcodes::SUBW, {{0}, {1, 2}}}, {RVOpcodes::MULW, {{0}, {1, 2}}}, {RVOpcodes::DIVW, {{0}, {1, 2}}},
{RVOpcodes::REMW, {{0}, {1, 2}}}, {RVOpcodes::SLT, {{0}, {1, 2}}}, {RVOpcodes::SLTU, {{0}, {1, 2}}},
{RVOpcodes::ADDI, {{0}, {1}}}, {RVOpcodes::ADDIW, {{0}, {1}}}, {RVOpcodes::XORI, {{0}, {1}}},
{RVOpcodes::SLTI, {{0}, {1}}}, {RVOpcodes::SLTIU, {{0}, {1}}}, {RVOpcodes::LB, {{0}, {}}},
{RVOpcodes::LH, {{0}, {}}}, {RVOpcodes::LW, {{0}, {}}}, {RVOpcodes::LD, {{0}, {}}},
{RVOpcodes::LBU, {{0}, {}}}, {RVOpcodes::LHU, {{0}, {}}}, {RVOpcodes::LWU, {{0}, {}}},
{RVOpcodes::FLW, {{0}, {}}}, {RVOpcodes::FLD, {{0}, {}}}, {RVOpcodes::SB, {{}, {0, 1}}},
{RVOpcodes::SH, {{}, {0, 1}}}, {RVOpcodes::SW, {{}, {0, 1}}}, {RVOpcodes::SD, {{}, {0, 1}}},
{RVOpcodes::FSW, {{}, {0, 1}}}, {RVOpcodes::FSD, {{}, {0, 1}}}, {RVOpcodes::BEQ, {{}, {0, 1}}},
{RVOpcodes::BNE, {{}, {0, 1}}}, {RVOpcodes::BLT, {{}, {0, 1}}}, {RVOpcodes::BGE, {{}, {0, 1}}},
{RVOpcodes::JALR, {{0}, {1}}}, {RVOpcodes::LI, {{0}, {}}}, {RVOpcodes::LA, {{0}, {}}},
{RVOpcodes::MV, {{0}, {1}}}, {RVOpcodes::SEQZ, {{0}, {1}}}, {RVOpcodes::SNEZ, {{0}, {1}}},
{RVOpcodes::RET, {{}, {}}}, {RVOpcodes::FADD_S, {{0}, {1, 2}}}, {RVOpcodes::FSUB_S, {{0}, {1, 2}}},
{RVOpcodes::FMUL_S, {{0}, {1, 2}}}, {RVOpcodes::FDIV_S, {{0}, {1, 2}}}, {RVOpcodes::FEQ_S, {{0}, {1, 2}}},
{RVOpcodes::FLT_S, {{0}, {1, 2}}}, {RVOpcodes::FLE_S, {{0}, {1, 2}}}, {RVOpcodes::FCVT_S_W, {{0}, {1}}},
{RVOpcodes::FCVT_W_S, {{0}, {1}}}, {RVOpcodes::FMV_S, {{0}, {1}}}, {RVOpcodes::FMV_W_X, {{0}, {1}}},
{RVOpcodes::FMV_X_W, {{0}, {1}}}, {RVOpcodes::FNEG_S, {{0}, {1}}}
};
} // namespace sysy
#endif // RISCV64_LINEARSCAN_H

View File

@@ -10,6 +10,8 @@
#include "PrologueEpilogueInsertion.h" #include "PrologueEpilogueInsertion.h"
#include "EliminateFrameIndices.h" #include "EliminateFrameIndices.h"
#include "Pass.h" #include "Pass.h"
#include "DivStrengthReduction.h"
namespace sysy { namespace sysy {

View File

@@ -202,6 +202,7 @@ class Use {
public: public:
unsigned getIndex() const { return index; } ///< 返回value在User操作数中的位置 unsigned getIndex() const { return index; } ///< 返回value在User操作数中的位置
void setIndex(int newIndex) { index = newIndex; } ///< 设置value在User操作数中的位置
User* getUser() const { return user; } ///< 返回使用者 User* getUser() const { return user; } ///< 返回使用者
Value* getValue() const { return value; } ///< 返回被使用的值 Value* getValue() const { return value; } ///< 返回被使用的值
void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue void setValue(Value *newValue) { value = newValue; } ///< 将被使用的值设置为newValue
@@ -229,7 +230,14 @@ class Value {
std::list<std::shared_ptr<Use>>& getUses() { return uses; } ///< 获取使用关系列表 std::list<std::shared_ptr<Use>>& getUses() { return uses; } ///< 获取使用关系列表
void addUse(const std::shared_ptr<Use> &use) { uses.push_back(use); } ///< 添加使用关系 void addUse(const std::shared_ptr<Use> &use) { uses.push_back(use); } ///< 添加使用关系
void replaceAllUsesWith(Value *value); ///< 将原来使用该value的使用者全变为使用给定参数value并修改相应use关系 void replaceAllUsesWith(Value *value); ///< 将原来使用该value的使用者全变为使用给定参数value并修改相应use关系
void removeUse(const std::shared_ptr<Use> &use) { uses.remove(use); } ///< 删除使用关系use void removeUse(const std::shared_ptr<Use> &use) {
assert(use != nullptr && "Use cannot be null");
assert(use->getValue() == this && "Use being removed does NOT point to this Value!");
auto it = std::find(uses.begin(), uses.end(), use);
assert(it != uses.end() && "Use not found in Value's uses");
uses.remove(use);
} ///< 删除使用关系use
void removeAllUses();
}; };
/** /**
@@ -633,21 +641,6 @@ class User : public Value {
explicit User(Type *type, const std::string &name = "") : Value(type, name) {} explicit User(Type *type, const std::string &name = "") : Value(type, name) {}
public: public:
// ~User() override {
// // 当 User 对象被销毁时例如LoadInst 或 StoreInst 被删除时),
// // 它必须通知它所使用的所有 Value将对应的 Use 关系从它们的 uses 列表中移除。
// // 这样可以防止 Value 的 uses 列表中出现悬空的 Use 对象。
// for (const auto &use_ptr : operands) {
// // 确保 use_ptr 非空,并且其内部指向的 Value* 也非空
// // (虽然通常情况下不会为空,但为了健壮性考虑)
// if (use_ptr && use_ptr->getValue()) {
// use_ptr->getValue()->removeUse(use_ptr);
// }
// }
// // operands 向量本身是 std::vector<std::shared_ptr<Use>>
// // 在此析构函数结束后operands 向量会被销毁,其内部的 shared_ptr 也会被释放,
// // 如果 shared_ptr 引用计数降为0Use 对象本身也会被销毁。
// }
unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量 unsigned getNumOperands() const { return operands.size(); } ///< 获取操作数数量
auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器 auto operand_begin() const { return operands.begin(); } ///< 返回操作数列表的开头迭代器
auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器 auto operand_end() const { return operands.end(); } ///< 返回操作数列表的结尾迭代器
@@ -657,11 +650,7 @@ class User : public Value {
operands.emplace_back(std::make_shared<Use>(operands.size(), this, value)); operands.emplace_back(std::make_shared<Use>(operands.size(), this, value));
value->addUse(operands.back()); value->addUse(operands.back());
} ///< 增加操作数 } ///< 增加操作数
void removeOperand(unsigned index) { void removeOperand(unsigned index);
auto value = getOperand(index);
value->removeUse(operands[index]);
operands.erase(operands.begin() + index);
} ///< 移除操作数
template <typename ContainerT> template <typename ContainerT>
void addOperands(const ContainerT &newoperands) { void addOperands(const ContainerT &newoperands) {
for (auto value : newoperands) { for (auto value : newoperands) {
@@ -728,6 +717,8 @@ class Instruction : public User {
kPhi = 0x1UL << 39, kPhi = 0x1UL << 39,
kBitItoF = 0x1UL << 40, kBitItoF = 0x1UL << 40,
kBitFtoI = 0x1UL << 41, kBitFtoI = 0x1UL << 41,
kSRA = 0x1UL << 42,
kMulh = 0x1UL << 43
}; };
protected: protected:
@@ -824,6 +815,12 @@ public:
return "Memset"; return "Memset";
case kPhi: case kPhi:
return "Phi"; return "Phi";
case kBitItoF:
return "BitItoF";
case kBitFtoI:
return "BitFtoI";
case kSRA:
return "SRA";
default: default:
return "Unknown"; return "Unknown";
} }
@@ -835,11 +832,15 @@ public:
bool isBinary() const { bool isBinary() const {
static constexpr uint64_t BinaryOpMask = static constexpr uint64_t BinaryOpMask =
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr) | (kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSRA | kMulh) |
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE) | (kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
return kind & BinaryOpMask;
}
bool isFPBinary() const {
static constexpr uint64_t FPBinaryOpMask =
(kFAdd | kFSub | kFMul | kFDiv) | (kFAdd | kFSub | kFMul | kFDiv) |
(kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE); (kFCmpEQ | kFCmpNE | kFCmpLT | kFCmpGT | kFCmpLE | kFCmpGE);
return kind & BinaryOpMask; return kind & FPBinaryOpMask;
} }
bool isUnary() const { bool isUnary() const {
static constexpr uint64_t UnaryOpMask = static constexpr uint64_t UnaryOpMask =
@@ -907,57 +908,54 @@ class PhiInst : public Instruction {
const std::string &name = "") const std::string &name = "")
: Instruction(Kind::kPhi, type, parent, name), vsize(rhs.size()) { : Instruction(Kind::kPhi, type, parent, name), vsize(rhs.size()) {
assert(rhs.size() == Blocks.size() && "PhiInst: rhs and Blocks must have the same size"); assert(rhs.size() == Blocks.size() && "PhiInst: rhs and Blocks must have the same size");
for(size_t i = 0; i < rhs.size(); ++i) { for(size_t i = 0; i < vsize; ++i) {
addOperand(rhs[i]); addOperand(rhs[i]);
addOperand(Blocks[i]);
blk2val[Blocks[i]] = rhs[i]; blk2val[Blocks[i]] = rhs[i];
} }
} }
public: public:
Value* getValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
//增加llvm同名方法实现获取value和block
Value* getIncomingValue(unsigned k) const {return getOperand(2 * k);} ///< 获取位置为k的值
BasicBlock* getIncomingBlock(unsigned k) const {return dynamic_cast<BasicBlock*>(getOperand(2 * k + 1));}
Value* getIncomingValue(BasicBlock* blk) const {
return getvalfromBlk(blk);
} ///< 获取指定基本块的传入值
BasicBlock* getIncomingBlock(Value* val) const {
return getBlkfromVal(val);
} ///< 获取指定值的传入基本块
void replaceIncoming(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue){
delBlk(oldBlock);
addIncoming(newValue, newBlock);
}
auto& getincomings() const {return blk2val;} ///< 获取所有的基本块和对应的值
Value* getvalfromBlk(BasicBlock* blk) const ;
BasicBlock* getBlkfromVal(Value* val) const ;
unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量 unsigned getNumIncomingValues() const { return vsize; } ///< 获取传入值的数量
Value *getIncomingValue(unsigned Idx) const { return getOperand(Idx * 2); } ///< 获取指定位置的传入值
BasicBlock *getIncomingBlock(unsigned Idx) const {return dynamic_cast<BasicBlock *>(getOperand(Idx * 2 + 1)); } ///< 获取指定位置的传入基本块
Value* getValfromBlk(BasicBlock* block);
BasicBlock* getBlkfromVal(Value* value);
void addIncoming(Value *value, BasicBlock *block) { void addIncoming(Value *value, BasicBlock *block) {
assert(value && block && "PhiInst: value and block must not be null"); assert(value && block && "PhiInst: value and block cannot be null");
addOperand(value); addOperand(value);
addOperand(block); addOperand(block);
blk2val[block] = value; blk2val[block] = value;
vsize++; vsize++;
} ///< 添加传入值和对应的基本块 } ///< 添加传入值和对应的基本块
void removeIncoming(unsigned Idx) {
void removeIncoming(BasicBlock *block){ assert(Idx < vsize && "PhiInst: Index out of bounds");
delBlk(block); auto blk = getIncomingBlock(Idx);
} removeOperand(Idx * 2 + 1); // Remove block
removeOperand(Idx * 2); // Remove value
void delValue(Value* val); blk2val.erase(blk);
void delBlk(BasicBlock* blk); vsize--;
} ///< 移除指定位置的传入值和对应的基本块
void replaceBlk(BasicBlock* newBlk, unsigned k); // 移除指定的传入值或基本块
void replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk); void removeIncomingValue(Value *value);
void refreshB2VMap(); void removeIncomingBlock(BasicBlock *block);
// 设置指定位置的传入值或基本块
void setIncomingValue(unsigned Idx, Value *value);
void setIncomingBlock(unsigned Idx, BasicBlock *block);
// 替换指定位置的传入值或基本块(原理是删除再添加)保留旧块或者旧值
void replaceIncomingValue(Value *oldValue, Value *newValue);
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock);
// 替换指定位置的传入值或基本块(原理是删除再添加)
void replaceIncomingValue(Value *oldValue, Value *newValue, BasicBlock *newBlock);
void replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue);
void refreshMap() {
blk2val.clear();
for (unsigned i = 0; i < vsize; ++i) {
blk2val[getIncomingBlock(i)] = getIncomingValue(i);
}
} ///< 刷新块到值的映射关系
auto getValues() { return make_range(std::next(operand_begin()), operand_end()); } auto getValues() { return make_range(std::next(operand_begin()), operand_end()); }
}; };

View File

@@ -217,6 +217,12 @@ class IRBuilder {
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") { BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name); return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
} ///< 创建按位或指令 } ///< 创建按位或指令
BinaryInst * createSRAInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kSRA, Type::getIntType(), lhs, rhs, name);
} ///< 创建算术右移指令
BinaryInst * createMulhInst(Value *lhs, Value *rhs, const std::string &name = "") {
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
} ///< 创建高位乘法指令
CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") { CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") {
std::string newName; std::string newName;
if (name.empty() && callee->getReturnType() != Type::getVoidType()) { if (name.empty() && callee->getReturnType() != Type::getVoidType()) {

View File

@@ -6,30 +6,82 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <functional>
namespace sysy { namespace sysy {
// 支配树分析结果类 (保持不变) // 支配树分析结果类
class DominatorTree : public AnalysisResultBase { class DominatorTree : public AnalysisResultBase {
public: public:
DominatorTree(Function* F); DominatorTree(Function* F);
// 获取指定基本块的所有支配者
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const; const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
BasicBlock* getImmediateDominator(BasicBlock* BB) const; // 获取指定基本块的即时支配者 (Immediate Dominator)
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const; BasicBlock* getImmediateDominator(BasicBlock* BB) const;
// 获取指定基本块的支配边界 (Dominance Frontier)
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
// 获取指定基本块在支配树中的子节点
const std::set<BasicBlock*>* getDominatorTreeChildren(BasicBlock* BB) const; const std::set<BasicBlock*>* getDominatorTreeChildren(BasicBlock* BB) const;
// 额外的 Getter获取所有支配者、即时支配者和支配边界的完整映射可选主要用于调试或特定场景
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; } const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; } const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; } const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
// 计算所有基本块的支配者集合
void computeDominators(Function* F); void computeDominators(Function* F);
void computeIDoms(Function* F); // 计算所有基本块的即时支配者(内部使用 Lengauer-Tarjan 算法)
void computeIDoms(Function* F);
// 计算所有基本块的支配边界
void computeDominanceFrontiers(Function* F); void computeDominanceFrontiers(Function* F);
// 计算支配树的结构(即每个节点的直接子节点)
void computeDominatorTreeChildren(Function* F); void computeDominatorTreeChildren(Function* F);
private: private:
// 与该支配树关联的函数
Function* AssociatedFunction; Function* AssociatedFunction;
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators; std::map<BasicBlock*, std::set<BasicBlock*>> Dominators; // 每个基本块的支配者集合
std::map<BasicBlock*, BasicBlock*> IDoms; std::map<BasicBlock*, BasicBlock*> IDoms; // 每个基本块的即时支配者
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers; std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers; // 每个基本块的支配边界
std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren; std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren; // 支配树中每个基本块的子节点
// ==========================================================
// Lengauer-Tarjan 算法内部所需的数据结构和辅助函数
// 这些成员是私有的,以封装 LT 算法的复杂性并避免命名空间污染
// ==========================================================
// DFS 遍历相关:
std::map<BasicBlock*, int> dfnum_map; // 存储每个基本块的 DFS 编号
std::vector<BasicBlock*> vertex_vec; // 通过 DFS 编号反向查找对应的基本块指针
std::map<BasicBlock*, BasicBlock*> parent_map; // 存储 DFS 树中每个基本块的父节点
int df_counter; // DFS 计数器,也代表 DFS 遍历的总节点数 (N)
// 半支配者 (Semi-dominator) 相关:
std::map<BasicBlock*, BasicBlock*> sdom_map; // 存储每个基本块的半支配者
std::map<BasicBlock*, BasicBlock*> idom_map; // 存储每个基本块的即时支配者 (IDom)
std::map<BasicBlock*, std::vector<BasicBlock*>> bucket_map; // 桶结构,用于存储具有相同半支配者的节点,以延迟 IDom 计算
// 并查集 (Union-Find) 相关(用于 evalAndCompress 函数):
std::map<BasicBlock*, BasicBlock*> ancestor_map; // 并查集中的父节点(用于路径压缩)
std::map<BasicBlock*, BasicBlock*> label_map; // 并查集中,每个集合的代表节点(或其路径上 sdom 最小的节点)
// ==========================================================
// 辅助计算函数 (私有)
// ==========================================================
// 计算基本块的逆后序遍历 (Reverse Post Order, RPO) 顺序
// RPO 用于优化支配者计算和 LT 算法的效率
std::vector<BasicBlock*> computeReversePostOrder(Function* F);
// Lengauer-Tarjan 算法特定的辅助 DFS 函数
// 用于初始化 dfnum_map, vertex_vec, parent_map
void dfs_lt_helper(BasicBlock* u);
// 结合了并查集的 Find 操作和 LT 算法的 Eval 操作
// 用于在路径压缩时更新 label找到路径上 sdom 最小的节点
BasicBlock* evalAndCompress_lt_helper(BasicBlock* i);
// 并查集的 Link 操作
// 将 v_child 挂载到 u_parent 的并查集树下
void link_lt_helper(BasicBlock* u_parent, BasicBlock* v_child);
}; };

View File

@@ -0,0 +1,20 @@
#pragma once
#include "IR.h"
#include "Pass.h"
#include <queue>
#include <set>
namespace sysy {
class BuildCFG : public OptimizationPass {
public:
static void *ID;
BuildCFG() : OptimizationPass("BuildCFG", Granularity::Function) {}
bool runOnFunction(Function *F, AnalysisManager &AM) override;
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
void *getPassID() const override { return &ID; }
};
} // namespace sysy

View File

@@ -0,0 +1,24 @@
#pragma once
#include "../Pass.h"
namespace sysy {
class LargeArrayToGlobalPass : public OptimizationPass {
public:
static void *ID;
LargeArrayToGlobalPass() : OptimizationPass("LargeArrayToGlobal", Granularity::Module) {}
bool runOnModule(Module *M, AnalysisManager &AM) override;
void *getPassID() const override {
return &ID;
}
private:
unsigned calculateTypeSize(Type *type);
void convertAllocaToGlobal(AllocaInst *alloca, Function *F, Module *M);
std::string generateUniqueGlobalName(AllocaInst *alloca, Function *F);
};
} // namespace sysy

View File

@@ -48,13 +48,6 @@ public:
} }
} }
} }
// 清空 User 的 operands 向量。这会递减 User 持有的 shared_ptr<Use> 的引用计数。
// 当引用计数降为 0 时Use 对象本身将被销毁。
// User::operands.clear(); // 这个步骤会在 Instruction 的析构函数中自动完成,因为它是 vector 成员
// 或者我们可以在 User::removeOperand 方法中确保 Use 对象从 operands 中移除。
// 实际上,只要 Value::removeUse(use_ptr) 被调用了,
// 当 Instruction 所在的 unique_ptr 销毁时,它的 operands vector 也会被销毁。
// 所以这里不需要显式 clear()
} }
static void usedelete(Instruction *inst) { static void usedelete(Instruction *inst) {
assert(inst && "Instruction to delete cannot be null."); assert(inst && "Instruction to delete cannot be null.");
@@ -75,7 +68,7 @@ public:
// 步骤3: 物理删除指令 // 步骤3: 物理删除指令
// 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。 // 这会导致 Instruction 对象的 unique_ptr 销毁,从而调用其析构函数链。
parentBlock->removeInst(inst); parentBlock->removeInst(inst);
} }
static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) { static BasicBlock::iterator usedelete(BasicBlock::iterator inst_it) {
Instruction *inst_to_delete = inst_it->get(); Instruction *inst_to_delete = inst_it->get();
@@ -92,7 +85,7 @@ public:
// 步骤3: 物理删除指令并返回下一个迭代器 // 步骤3: 物理删除指令并返回下一个迭代器
return parentBlock->removeInst(inst_it); return parentBlock->removeInst(inst_it);
} }
// 判断是否是全局变量 // 判断是否是全局变量
static bool isGlobal(Value *val) { static bool isGlobal(Value *val) {

View File

@@ -279,7 +279,7 @@ private:
IRBuilder *pBuilder; IRBuilder *pBuilder;
public: public:
PassManager() = default; PassManager() = delete;
~PassManager() = default; ~PassManager() = default;
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {} PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}

View File

@@ -86,7 +86,60 @@ private:
case LPAREN: case RPAREN: return 0; // Parentheses have lowest precedence for stack logic case LPAREN: case RPAREN: return 0; // Parentheses have lowest precedence for stack logic
default: return -1; // Unknown operator default: return -1; // Unknown operator
} }
} };
struct ExpKey {
BinaryOp op; ///< 操作符
Value *left; ///< 左操作数
Value *right; ///< 右操作数
ExpKey(BinaryOp op, Value *left, Value *right) : op(op), left(left), right(right) {}
bool operator<(const ExpKey &other) const {
if (op != other.op)
return op < other.op; ///< 比较操作符
if (left != other.left)
return left < other.left; ///< 比较左操作
return right < other.right; ///< 比较右操作数
} ///< 重载小于运算符用于比较ExpKey
};
struct UnExpKey {
BinaryOp op; ///< 一元操作符
Value *operand; ///< 操作数
UnExpKey(BinaryOp op, Value *operand) : op(op), operand(operand) {}
bool operator<(const UnExpKey &other) const {
if (op != other.op)
return op < other.op; ///< 比较操作符
return operand < other.operand; ///< 比较操作数
} ///< 重载小于运算符用于比较UnExpKey
};
struct GEPKey {
Value *basePointer;
std::vector<Value *> indices;
// 为 std::map 定义比较运算符,使得 GEPKey 可以作为键
bool operator<(const GEPKey &other) const {
if (basePointer != other.basePointer) {
return basePointer < other.basePointer;
}
// 逐个比较索引,确保顺序一致
if (indices.size() != other.indices.size()) {
return indices.size() < other.indices.size();
}
for (size_t i = 0; i < indices.size(); ++i) {
if (indices[i] != other.indices[i]) {
return indices[i] < other.indices[i];
}
}
return false; // 如果 basePointer 和所有索引都相同,则认为相等
}
};
std::map<GEPKey, Value*> availableGEPs; ///< 用于存储 GEP 的缓存
std::map<ExpKey, Value*> availableBinaryExpressions;
std::map<UnExpKey, Value*> availableUnaryExpressions;
std::map<Value*, Value*> availableLoads;
public: public:
SysYIRGenerator() = default; SysYIRGenerator() = default;
@@ -167,6 +220,15 @@ public:
Value* computeExp(SysYParser::ExpContext *ctx, Type* targetType = nullptr); Value* computeExp(SysYParser::ExpContext *ctx, Type* targetType = nullptr);
Value* computeAddExp(SysYParser::AddExpContext *ctx, Type* targetType = nullptr); Value* computeAddExp(SysYParser::AddExpContext *ctx, Type* targetType = nullptr);
void compute(); void compute();
// 参数是发生 store 操作的目标地址/变量的 Value*
void invalidateExpressionsOnStore(Value* storedAddress);
// 清除因函数调用而失效的表达式缓存(保守策略)
void invalidateExpressionsOnCall();
// 在进入新的基本块时清空所有表达式缓存
void enterNewBasicBlock();
public: public:
// 获取GEP指令的地址 // 获取GEP指令的地址
Value* getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices); Value* getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices);

View File

@@ -11,6 +11,8 @@ add_library(midend_lib STATIC
Pass/Optimize/Reg2Mem.cpp Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/SysYIRCFGOpt.cpp Pass/Optimize/SysYIRCFGOpt.cpp
Pass/Optimize/SCCP.cpp Pass/Optimize/SCCP.cpp
Pass/Optimize/BuildCFG.cpp
Pass/Optimize/LargeArrayToGlobal.cpp
) )
# 包含中端模块所需的头文件路径 # 包含中端模块所需的头文件路径

View File

@@ -118,13 +118,45 @@ ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
return result.first->get(); return result.first->get();
} }
// void Value::replaceAllUsesWith(Value *value) {
// for (auto &use : uses) {
// auto user = use->getUser();
// assert(user && "Use's user cannot be null");
// user->setOperand(use->getIndex(), value);
// }
// uses.clear();
// }
void Value::replaceAllUsesWith(Value *value) { void Value::replaceAllUsesWith(Value *value) {
for (auto &use : uses) { // 1. 创建 uses 列表的副本进行迭代。
use->getUser()->setOperand(use->getIndex(), value); // 这样做是为了避免在迭代过程中,由于 setOperand 间接调用 removeUse 或 addUse
} // 导致原列表被修改,从而引发迭代器失效问题。
uses.clear(); std::list<std::shared_ptr<Use>> uses_copy = uses;
}
for (auto &use_ptr : uses_copy) { // 遍历副本
// 2. 检查 shared_ptr<Use> 本身是否为空。这是最常见的崩溃原因之一。
if (use_ptr == nullptr) {
std::cerr << "Warning: Encountered a null std::shared_ptr<Use> in Value::uses list. Skipping this entry." << std::endl;
// 在一个健康的 IR 中,这种情况不应该发生。如果经常出现,说明你的 Use 创建或管理有问题。
continue; // 跳过空的智能指针
}
// 3. 检查 Use 对象内部的 User* 是否为空。
User* user_val = use_ptr->getUser();
if (user_val == nullptr) {
std::cerr << "Warning: Use object (" << use_ptr.get() << ") has a null User* in replaceAllUsesWith. Skipping this entry. This indicates IR corruption." << std::endl;
// 同样,在一个健康的 IR 中Use 对象的 User* 不应该为空。
continue; // 跳过用户指针为空的 Use 对象
}
// 如果走到这里use_ptr 和 user_val 都是有效的,可以安全调用 setOperand
user_val->setOperand(use_ptr->getIndex(), value);
}
// 4. 处理完所有 use 之后,清空原始的 uses 列表。
// replaceAllUsesWith 的目的就是将所有使用关系从当前 Value 转移走,
// 所以最后清空列表是正确的。
uses.clear();
}
// Implementations for static members // Implementations for static members
@@ -182,377 +214,45 @@ auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
} }
return result; return result;
} }
// 函数克隆,后续函数级优化(内联等)需要用到
Function * Function::clone(const std::string &suffix) const {
std::stringstream ss;
std::map<BasicBlock *, BasicBlock *> oldNewBlockMap;
IRBuilder builder;
auto newFunction = new Function(parent, type, name);
newFunction->getEntryBlock()->setName(blocks.front()->getName());
oldNewBlockMap.emplace(blocks.front().get(), newFunction->getEntryBlock());
auto oldBlockListIter = std::next(blocks.begin());
while (oldBlockListIter != blocks.end()) {
auto newBlock = newFunction->addBasicBlock(oldBlockListIter->get()->getName());
oldNewBlockMap.emplace(oldBlockListIter->get(), newBlock);
oldBlockListIter++;
}
for (const auto &oldNewBlockItem : oldNewBlockMap) { void Value::removeAllUses() {
auto oldBlock = oldNewBlockItem.first; while (!uses.empty()) {
auto newBlock = oldNewBlockItem.second; auto use = uses.back();
for (const auto &oldPred : oldBlock->getPredecessors()) { uses.pop_back();
newBlock->addPredecessor(oldNewBlockMap.at(oldPred)); if (use && use->getUser()) {
} auto user = use->getUser();
for (const auto &oldSucc : oldBlock->getSuccessors()) { int index = use->getIndex();
newBlock->addSuccessor(oldNewBlockMap.at(oldSucc)); user->removeOperand(index); ///< 从User中移除该操作数
} else {
// 如果use或user为null输出警告信息
assert(use != nullptr && "Use cannot be null");
assert(use->getUser() != nullptr && "Use's user cannot be null");
} }
} }
uses.clear();
std::map<Value *, Value *> oldNewValueMap;
std::map<Value *, bool> isAddedToCreate;
std::map<Value *, bool> isCreated;
std::queue<Value *> toCreate;
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
isAddedToCreate.emplace(inst.get(), false);
isCreated.emplace(inst.get(), false);
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
if (oldAllocInst != nullptr) {
std::vector<Value *> dims;
// TODO: 这里的dims用type推断
// for (const auto &dim : oldAllocInst->getDims()) {
// dims.emplace_back(dim->getValue());
// }
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
if (inst->getKind() == Instruction::kAlloca) {
if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
std::vector<Value *> dims;
// TODO: 这里的dims用type推断
// for (const auto &dim : oldAllocInst->getDims()) {
// dims.emplace_back(dim->getValue());
// }
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto globalValue = dynamic_cast<GlobalValue *>(value);
auto constVariable = dynamic_cast<ConstantVariable *>(value);
auto constantValue = dynamic_cast<ConstantValue *>(value);
auto functionValue = dynamic_cast<Function *>(value);
if (globalValue != nullptr || constantValue != nullptr || constVariable != nullptr ||
functionValue != nullptr) {
if (functionValue == this) {
oldNewValueMap.emplace(value, newFunction);
} else {
oldNewValueMap.emplace(value, value);
}
isCreated.emplace(value, true);
isAddedToCreate.emplace(value, true);
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
if (inst->getKind() != Instruction::kAlloca) {
bool isReady = true;
for (const auto &use : inst->getOperands()) {
auto value = use->getValue();
if (dynamic_cast<BasicBlock *>(value) == nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (isReady) {
toCreate.push(inst.get());
isAddedToCreate.at(inst.get()) = true;
}
}
}
}
while (!toCreate.empty()) {
auto inst = dynamic_cast<Instruction *>(toCreate.front());
toCreate.pop();
bool isReady = true;
for (const auto &valueUse : inst->getOperands()) {
auto value = dynamic_cast<Instruction *>(valueUse->getValue());
if (value != nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (!isReady) {
toCreate.push(inst);
continue;
}
isCreated.at(inst) = true;
switch (inst->getKind()) {
case Instruction::kAdd:
case Instruction::kSub:
case Instruction::kMul:
case Instruction::kDiv:
case Instruction::kRem:
case Instruction::kICmpEQ:
case Instruction::kICmpNE:
case Instruction::kICmpLT:
case Instruction::kICmpGT:
case Instruction::kICmpLE:
case Instruction::kICmpGE:
case Instruction::kAnd:
case Instruction::kOr:
case Instruction::kFAdd:
case Instruction::kFSub:
case Instruction::kFMul:
case Instruction::kFDiv:
case Instruction::kFCmpEQ:
case Instruction::kFCmpNE:
case Instruction::kFCmpLT:
case Instruction::kFCmpGT:
case Instruction::kFCmpLE:
case Instruction::kFCmpGE: {
auto oldBinaryInst = dynamic_cast<BinaryInst *>(inst);
auto lhs = oldBinaryInst->getLhs();
auto rhs = oldBinaryInst->getRhs();
Value *newLhs;
Value *newRhs;
newLhs = oldNewValueMap[lhs];
newRhs = oldNewValueMap[rhs];
ss << oldBinaryInst->getName() << suffix;
auto newBinaryInst = new BinaryInst(oldBinaryInst->getKind(), oldBinaryInst->getType(), newLhs, newRhs,
oldNewBlockMap.at(oldBinaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldBinaryInst, newBinaryInst);
break;
}
case Instruction::kNeg:
case Instruction::kNot:
case Instruction::kFNeg:
case Instruction::kFNot:
case Instruction::kItoF:
case Instruction::kFtoI: {
auto oldUnaryInst = dynamic_cast<UnaryInst *>(inst);
auto hs = oldUnaryInst->getOperand();
Value *newHs;
newHs = oldNewValueMap.at(hs);
ss << oldUnaryInst->getName() << suffix;
auto newUnaryInst = new UnaryInst(oldUnaryInst->getKind(), oldUnaryInst->getType(), newHs,
oldNewBlockMap.at(oldUnaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldUnaryInst, newUnaryInst);
break;
}
case Instruction::kCall: {
auto oldCallInst = dynamic_cast<CallInst *>(inst);
std::vector<Value *> newArgumnts;
for (const auto &arg : oldCallInst->getArguments()) {
newArgumnts.emplace_back(oldNewValueMap.at(arg->getValue()));
}
ss << oldCallInst->getName() << suffix;
CallInst *newCallInst;
newCallInst =
new CallInst(oldCallInst->getCallee(), newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()), ss.str());
ss.str("");
// if (oldCallInst->getCallee() != this) {
// newCallInst = new CallInst(oldCallInst->getCallee(), newArgumnts,
// oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// } else {
// newCallInst = new CallInst(newFunction, newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// }
oldNewValueMap.emplace(oldCallInst, newCallInst);
break;
}
case Instruction::kCondBr: {
auto oldCondBrInst = dynamic_cast<CondBrInst *>(inst);
auto oldCond = oldCondBrInst->getCondition();
Value *newCond;
newCond = oldNewValueMap.at(oldCond);
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
oldNewBlockMap.at(oldCondBrInst->getElseBlock()),
oldNewBlockMap.at(oldCondBrInst->getParent()));
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
break;
}
case Instruction::kBr: {
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
auto newBrInst =
new UncondBrInst(oldNewBlockMap.at(oldBrInst->getBlock()), oldNewBlockMap.at(oldBrInst->getParent()));
oldNewValueMap.emplace(oldBrInst, newBrInst);
break;
}
case Instruction::kReturn: {
auto oldReturnInst = dynamic_cast<ReturnInst *>(inst);
auto oldRval = oldReturnInst->getReturnValue();
Value *newRval = nullptr;
if (oldRval != nullptr) {
newRval = oldNewValueMap.at(oldRval);
}
auto newReturnInst =
new ReturnInst(newRval, oldNewBlockMap.at(oldReturnInst->getParent()), oldReturnInst->getName());
oldNewValueMap.emplace(oldReturnInst, newReturnInst);
break;
}
case Instruction::kAlloca: {
assert(false);
}
case Instruction::kLoad: {
auto oldLoadInst = dynamic_cast<LoadInst *>(inst);
auto oldPointer = oldLoadInst->getPointer();
Value *newPointer;
newPointer = oldNewValueMap.at(oldPointer);
std::vector<Value *> newIndices;
// for (const auto &index : oldLoadInst->getIndices()) {
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
// }
ss << oldLoadInst->getName() << suffix;
// TODO : 这里的newLoadInst的类型需要根据oldLoadInst的类型来推断
auto newLoadInst = new LoadInst(newPointer, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
break;
}
case Instruction::kStore: {
auto oldStoreInst = dynamic_cast<StoreInst *>(inst);
auto oldPointer = oldStoreInst->getPointer();
auto oldValue = oldStoreInst->getValue();
Value *newPointer;
Value *newValue;
std::vector<Value *> newIndices;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
// TODO: 这里的newIndices需要根据oldStoreInst的类型来推断
// for (const auto &index : oldStoreInst->getIndices()) {
// newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
// }
auto newStoreInst = new StoreInst(newValue, newPointer,
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
break;
}
// TODO复制GEP指令
case Instruction::kMemset: {
auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst);
auto oldPointer = oldMemsetInst->getPointer();
auto oldValue = oldMemsetInst->getValue();
Value *newPointer;
Value *newValue;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
auto newMemsetInst = new MemsetInst(newPointer, oldMemsetInst->getBegin(), oldMemsetInst->getSize(), newValue,
oldNewBlockMap.at(oldMemsetInst->getParent()), oldMemsetInst->getName());
oldNewValueMap.emplace(oldMemsetInst, newMemsetInst);
break;
}
case Instruction::kInvalid:
case Instruction::kPhi: {
break;
}
default:
assert(false);
}
for (const auto &userUse : inst->getUses()) {
auto user = userUse->getUser();
if (!isAddedToCreate.at(user)) {
toCreate.push(user);
isAddedToCreate.at(user) = true;
}
}
}
for (const auto &oldBlock : blocks) {
auto newBlock = oldNewBlockMap.at(oldBlock.get());
builder.setPosition(newBlock, newBlock->end());
for (const auto &inst : oldBlock->getInstructions()) {
builder.insertInst(dynamic_cast<Instruction *>(oldNewValueMap.at(inst.get())));
}
}
// for (const auto &param : blocks.front()->getArguments()) {
// newFunction->getEntryBlock()->insertArgument(dynamic_cast<AllocaInst *>(oldNewValueMap.at(param)));
// }
for (const auto &arg : arguments) {
auto newArg = dynamic_cast<Argument *>(oldNewValueMap.at(arg));
if (newArg != nullptr) {
newFunction->insertArgument(newArg);
}
}
return newFunction;
} }
/** /**
* 设置操作数 * 设置操作数
*/ */
void User::setOperand(unsigned index, Value *value) { void User::setOperand(unsigned index, Value *newvalue) {
assert(index < getNumOperands()); if (index >= operands.size()) {
operands[index]->setValue(value); std::cerr << "index=" << index << ", but mOperands max size=" << operands.size() << std::endl;
value->addUse(operands[index]); assert(index < operands.size());
}
std::shared_ptr<Use> olduse = operands[index];
Value *oldValue = olduse->getValue();
if (oldValue != newvalue) {
// 如果新值和旧值不同,先移除旧值的使用关系
oldValue->removeUse(olduse);
// 设置新的操作数
operands[index] = std::make_shared<Use>(index, this, newvalue);
newvalue->addUse(operands[index]);
}
else {
// 如果新值和旧值相同直接更新use的索引
operands[index]->setValue(newvalue);
}
} }
/** /**
* 替换操作数 * 替换操作数
@@ -565,29 +265,50 @@ void User::replaceOperand(unsigned index, Value *value) {
value->addUse(use); value->addUse(use);
} }
/**
* 移除操作数
*/
void User::removeOperand(unsigned index) {
assert(index < getNumOperands() && "Index out of range in removeOperand");
std::shared_ptr<Use> useToRemove = operands.at(index);
Value *valueToRemove = useToRemove->getValue();
if(valueToRemove) {
if(valueToRemove == this) {
std::cerr << "Cannot remove operand that is the same as the User itself." << std::endl;
}
valueToRemove->removeUse(useToRemove);
}
operands.erase(operands.begin() + index);
unsigned newIndex = 0;
for(auto it = operands.begin(); it != operands.end(); ++it, ++newIndex) {
(*it)->setIndex(newIndex); // 更新剩余操作数的索引
}
}
/** /**
* phi相关函数 * phi相关函数
*/ */
Value* PhiInst::getvalfromBlk(BasicBlock* blk) const { Value* PhiInst::getValfromBlk(BasicBlock* blk) {
// refreshB2VMap(); refreshMap();
if( blk2val.find(blk) != blk2val.end()) { if( blk2val.find(blk) != blk2val.end()) {
return blk2val.at(blk); return blk2val.at(blk);
} }
return nullptr; return nullptr;
} }
BasicBlock* PhiInst::getBlkfromVal(Value* val) const { BasicBlock* PhiInst::getBlkfromVal(Value* val) {
// 返回第一个值对应的基本块 // 返回第一个值对应的基本块
for(unsigned i = 0; i < vsize; i++) { for(unsigned i = 0; i < vsize; i++) {
if(getValue(i) == val) { if(getIncomingValue(i) == val) {
return getBlock(i); return getIncomingBlock(i);
} }
} }
return nullptr; return nullptr;
} }
void PhiInst::delValue(Value* val){ void PhiInst::removeIncomingValue(Value* val){
//根据value删除对应的基本块和值 //根据value删除对应的基本块和值
unsigned i = 0; unsigned i = 0;
BasicBlock* blk = getBlkfromVal(val); BasicBlock* blk = getBlkfromVal(val);
@@ -595,62 +316,77 @@ void PhiInst::delValue(Value* val){
return; // 如果val没有对应的基本块直接返回 return; // 如果val没有对应的基本块直接返回
} }
for(i = 0; i < vsize; i++) { for(i = 0; i < vsize; i++) {
if(getValue(i) == val) { if(getIncomingValue(i) == val) {
break; break;
} }
} }
removeOperand(2 * i + 1); // 删除blk removeIncoming(i);
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
} }
void PhiInst::delBlk(BasicBlock* blk){ void PhiInst::removeIncomingBlock(BasicBlock* blk){
//根据Blk删除对应的基本块和值 //根据Blk删除对应的基本块和值
unsigned i = 0; unsigned i = 0;
Value* val = getvalfromBlk(blk); Value* val = getValfromBlk(blk);
if(val == nullptr) { if(val == nullptr) {
return; // 如果blk没有对应的值直接返回 return; // 如果blk没有对应的值直接返回
} }
for(i = 0; i < vsize; i++) { for(i = 0; i < vsize; i++) {
if(getBlock(i) == blk) { if(getIncomingBlock(i) == blk) {
break; break;
} }
} }
removeOperand(2 * i + 1); // 删除blk removeIncoming(i);
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
} }
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){ void PhiInst::setIncomingValue(unsigned k, Value* val) {
// refreshB2VMap(); assert(k < vsize && "PhiInst: index out of range");
BasicBlock* oldBlk = getBlock(k); assert(val != nullptr && "PhiInst: value cannot be null");
Value* val = blk2val.at(oldBlk); refreshMap();
if(newBlk == oldBlk || oldBlk == nullptr) { blk2val.erase(getIncomingBlock(k));
return; // 如果新旧基本块相同,直接返回 setOperand(2 * k, val);
} blk2val[getIncomingBlock(k)] = val;
// Value* val = blk2val.at(getBlock(k));
// 替换基本块
setOperand(2 * k + 1, newBlk);
// 替换blk2val映射
blk2val.erase(oldBlk);
blk2val.emplace(newBlk, val);
} }
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){ void PhiInst::setIncomingBlock(unsigned k, BasicBlock* blk) {
// refreshB2VMap(); assert(k < vsize && "PhiInst: index out of range");
Value* val = blk2val.at(oldBlk); assert(blk != nullptr && "PhiInst: block cannot be null");
// 替换基本块 refreshMap();
delBlk(oldBlk); auto oldVal = getIncomingValue(k);
blk2val.erase(getIncomingBlock(k));
setOperand(2 * k + 1, blk);
blk2val[blk] = oldVal;
}
void PhiInst::replaceIncomingValue(Value* newVal, Value* oldVal) {
refreshMap();
assert(blk2val.find(getBlkfromVal(oldVal)) != blk2val.end() && "PhiInst: oldVal not found in blk2val");
auto blk = getBlkfromVal(oldVal);
removeIncomingValue(oldVal);
addIncoming(newVal, blk);
}
void PhiInst::replaceIncomingBlock(BasicBlock* newBlk, BasicBlock* oldBlk) {
refreshMap();
assert(blk2val.find(oldBlk) != blk2val.end() && "PhiInst: oldBlk not found in blk2val");
auto val = blk2val[oldBlk];
removeIncomingBlock(oldBlk);
addIncoming(val, newBlk); addIncoming(val, newBlk);
} }
void PhiInst::refreshB2VMap(){ void PhiInst::replaceIncomingValue(Value *oldValue, Value *newValue, BasicBlock *newBlock) {
blk2val.clear(); refreshMap();
for(unsigned i = 0; i < vsize; i++) { assert(blk2val.find(getBlkfromVal(oldValue)) != blk2val.end() && "PhiInst: oldValue not found in blk2val");
blk2val.emplace(getBlock(i), getValue(i)); auto oldBlock = getBlkfromVal(oldValue);
} removeIncomingValue(oldValue);
addIncoming(newValue, newBlock);
}
void PhiInst::replaceIncomingBlock(BasicBlock *oldBlock, BasicBlock *newBlock, Value *newValue) {
refreshMap();
assert(blk2val.find(oldBlock) != blk2val.end() && "PhiInst: oldBlock not found in blk2val");
auto oldValue = blk2val[oldBlock];
removeIncomingBlock(oldBlock);
addIncoming(newValue, newBlock);
} }
CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name) CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)

View File

@@ -1,21 +1,30 @@
#include "Dom.h" #include "Dom.h"
#include <algorithm> // for std::set_intersection, std::set_difference, std::set_union #include <algorithm> // for std::set_intersection, std::reverse
#include <iostream> // for debug output #include <iostream> // for debug output
#include <limits> // for std::numeric_limits #include <limits> // for std::numeric_limits
#include <queue> #include <queue>
#include <functional> // for std::function
#include <map>
#include <vector>
#include <set>
namespace sysy { namespace sysy {
// 初始化 支配树静态 ID // ==============================================================
// DominatorTreeAnalysisPass 的静态ID
// ==============================================================
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID; void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
// ============================================================== // ==============================================================
// DominatorTree 结果类的实现 // DominatorTree 结果类的实现
// ============================================================== // ==============================================================
// 构造函数:初始化关联函数,但不进行计算
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) { DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
// 构造时可以不计算,在分析遍运行里计算并填充 // 构造时不需要计算,在分析遍运行里计算并填充
} }
// Getter 方法 (保持不变)
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const { const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
auto it = Dominators.find(BB); auto it = Dominators.find(BB);
if (it != Dominators.end()) { if (it != Dominators.end()) {
@@ -48,7 +57,7 @@ const std::set<BasicBlock *> *DominatorTree::getDominatorTreeChildren(BasicBlock
return nullptr; return nullptr;
} }
// 辅助函数:打印 BasicBlock 集合 // 辅助函数:打印 BasicBlock 集合 (保持不变)
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) { void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
if (!DEBUG) if (!DEBUG)
return; return;
@@ -63,24 +72,52 @@ void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) {
std::cout << "}" << std::endl; std::cout << "}" << std::endl;
} }
// 辅助函数:计算逆后序遍历 (RPO) - 保持不变
std::vector<BasicBlock*> DominatorTree::computeReversePostOrder(Function* F) {
std::vector<BasicBlock*> postOrder;
std::set<BasicBlock*> visited;
std::function<void(BasicBlock*)> dfs_rpo =
[&](BasicBlock* bb) {
visited.insert(bb);
for (BasicBlock* succ : bb->getSuccessors()) {
if (visited.find(succ) == visited.end()) {
dfs_rpo(succ);
}
}
postOrder.push_back(bb);
};
dfs_rpo(F->getEntryBlock());
std::reverse(postOrder.begin(), postOrder.end());
if (DEBUG) {
std::cout << "--- Computed RPO: ";
for (BasicBlock* bb : postOrder) {
std::cout << bb->getName() << " ";
}
std::cout << "---" << std::endl;
}
return postOrder;
}
// computeDominators 方法 (保持不变因为它它是独立于IDom算法的)
void DominatorTree::computeDominators(Function *F) { void DominatorTree::computeDominators(Function *F) {
if (DEBUG) if (DEBUG)
std::cout << "--- Computing Dominators ---" << std::endl; std::cout << "--- Computing Dominators ---" << std::endl;
BasicBlock *entryBlock = F->getEntryBlock(); BasicBlock *entryBlock = F->getEntryBlock();
std::vector<BasicBlock *> bbs_in_order; // 用于确定遍历顺序,如果需要的话 std::vector<BasicBlock*> bbs_rpo = computeReversePostOrder(F);
// 初始化:入口块只被自己支配,其他块被所有块支配 for (BasicBlock *bb : bbs_rpo) {
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
bbs_in_order.push_back(bb); // 收集所有块
if (bb == entryBlock) { if (bb == entryBlock) {
Dominators[bb].clear();
Dominators[bb].insert(bb); Dominators[bb].insert(bb);
if (DEBUG) if (DEBUG) std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
std::cout << "Init Dominators[" << bb->getName() << "]: {" << bb->getName() << "}" << std::endl;
} else { } else {
for (const auto &all_bb_ptr : F->getBasicBlocks()) { Dominators[bb].clear();
Dominators[bb].insert(all_bb_ptr.get()); for (BasicBlock *all_bb : bbs_rpo) {
Dominators[bb].insert(all_bb);
} }
if (DEBUG) { if (DEBUG) {
std::cout << "Init Dominators[" << bb->getName() << "]: "; std::cout << "Init Dominators[" << bb->getName() << "]: ";
@@ -94,35 +131,29 @@ void DominatorTree::computeDominators(Function *F) {
while (changed) { while (changed) {
changed = false; changed = false;
iteration++; iteration++;
if (DEBUG) if (DEBUG) std::cout << "Iteration " << iteration << std::endl;
std::cout << "Iteration " << iteration << std::endl;
// 确保遍历顺序一致性例如可以按照DFS或BFS顺序或者简单的迭代器顺序 for (BasicBlock *bb : bbs_rpo) {
// 如果Function::getBasicBlocks()返回的迭代器顺序稳定则无需bbs_in_order if (bb == entryBlock) continue;
for (const auto &bb_ptr : F->getBasicBlocks()) { // 假设这个迭代器顺序稳定
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
// 计算所有前驱的支配者集合的交集
std::set<BasicBlock *> newDom; std::set<BasicBlock *> newDom;
bool firstPredProcessed = false; bool firstPredProcessed = false;
for (BasicBlock *pred : bb->getPredecessors()) { for (BasicBlock *pred : bb->getPredecessors()) {
// 确保前驱的支配者集合已经计算过 if(DEBUG){
if (Dominators.count(pred)) { std::cout << " Processing predecessor: " << pred->getName() << std::endl;
if (!firstPredProcessed) {
newDom = Dominators[pred];
firstPredProcessed = true;
} else {
std::set<BasicBlock *> intersection;
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
std::inserter(intersection, intersection.begin()));
newDom = intersection;
}
} }
if (!firstPredProcessed) {
newDom = Dominators[pred];
firstPredProcessed = true;
} else {
std::set<BasicBlock *> intersection;
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
std::inserter(intersection, intersection.begin()));
newDom = intersection;
}
} }
newDom.insert(bb); // BB 永远支配自己 newDom.insert(bb);
if (newDom != Dominators[bb]) { if (newDom != Dominators[bb]) {
if (DEBUG) { if (DEBUG) {
@@ -140,78 +171,242 @@ void DominatorTree::computeDominators(Function *F) {
std::cout << "--- Dominators Computation Finished ---" << std::endl; std::cout << "--- Dominators Computation Finished ---" << std::endl;
} }
void DominatorTree::computeIDoms(Function *F) { // ==============================================================
if (DEBUG) // Lengauer-Tarjan 算法辅助数据结构和函数 (私有成员)
std::cout << "--- Computing Immediate Dominators (IDoms) ---" << std::endl; // ==============================================================
BasicBlock *entryBlock = F->getEntryBlock(); // DFS 遍历,填充 dfnum_map, vertex_vec, parent_map
IDoms[entryBlock] = nullptr; // 入口块没有即时支配者 // 对应用户代码的 dfs 函数
void DominatorTree::dfs_lt_helper(BasicBlock* u) {
// 遍历所有非入口块 dfnum_map[u] = df_counter;
for (const auto &bb_ptr : F->getBasicBlocks()) { if (df_counter >= vertex_vec.size()) { // 动态调整大小
BasicBlock *bb = bb_ptr.get(); vertex_vec.resize(df_counter + 1);
if (bb == entryBlock)
continue;
BasicBlock *currentIDom = nullptr;
const std::set<BasicBlock *> *domsOfBB = getDominators(bb);
if (!domsOfBB) {
if (DEBUG)
std::cerr << "Warning: Dominators for " << bb->getName() << " not found!" << std::endl;
continue;
} }
vertex_vec[df_counter] = u;
if (DEBUG) std::cout << " DFS: Visiting " << u->getName() << ", dfnum = " << df_counter << std::endl;
df_counter++;
// 遍历bb的所有严格支配者 D (即 bb 的支配者中除了 bb 自身) for (BasicBlock* v : u->getSuccessors()) {
for (BasicBlock *D_candidate : *domsOfBB) { if (dfnum_map.find(v) == dfnum_map.end()) { // 如果 v 未访问过
if (D_candidate == bb) parent_map[v] = u;
continue; // 跳过bb自身 if (DEBUG) std::cout << " DFS: Setting parent[" << v->getName() << "] = " << u->getName() << std::endl;
dfs_lt_helper(v);
bool D_candidate_is_IDom = true;
// 检查是否存在另一个块 X使得 D_candidate 严格支配 X 且 X 严格支配 bb
// 或者更直接的,检查 D_candidate 是否被 bb 的所有其他严格支配者所支配
for (BasicBlock *X_other_dom : *domsOfBB) {
if (X_other_dom == bb || X_other_dom == D_candidate)
continue; // 跳过bb自身和D_candidate
// 如果 X_other_dom 严格支配 bb (它在 domsOfBB 中且不是bb自身)
// 并且 X_other_dom 不被 D_candidate 支配,那么 D_candidate 就不是 IDom
const std::set<BasicBlock *> *domsOfX_other_dom = getDominators(X_other_dom);
if (domsOfX_other_dom && domsOfX_other_dom->count(D_candidate)) { // X_other_dom 支配 D_candidate
// D_candidate 被另一个支配者 X_other_dom 支配
// 这说明 D_candidate 位于 X_other_dom 的“下方”X_other_dom 更接近 bb
// 因此 D_candidate 不是 IDom
D_candidate_is_IDom = false;
break;
} }
}
if (D_candidate_is_IDom) {
currentIDom = D_candidate;
break; // 找到即时支配者,可以退出循环,因为它是唯一的
}
} }
IDoms[bb] = currentIDom;
if (DEBUG) {
std::cout << " IDom[" << bb->getName() << "] = " << (currentIDom ? currentIDom->getName() : "nullptr")
<< std::endl;
}
}
if (DEBUG)
std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl;
} }
/* // 并查集:找到集合的代表,并进行路径压缩
for each node n in a postorder traversal of the dominator tree: // 同时更新 label确保 label[i] 总是指向其祖先链中 sdom_map 最小的节点
df[n] = empty set // 对应用户代码的 find 函数,也包含了 eval 的逻辑
// compute DF_local(n) BasicBlock* DominatorTree::evalAndCompress_lt_helper(BasicBlock* i) {
for each child y of n in the CFG: if (DEBUG) std::cout << " Eval: Processing " << i->getName() << std::endl;
if idom[y] != n: // 如果 i 是根 (ancestor_map[i] == nullptr)
df[n] = df[n] U {y} if (ancestor_map.find(i) == ancestor_map.end() || ancestor_map[i] == nullptr) {
// compute DF_up(n) if (DEBUG) std::cout << " Eval: " << i->getName() << " is root, returning itself." << std::endl;
for each child c of n in the dominator tree: return i; // 根节点自身就是路径上sdom最小的因为它没有祖先
for each element w in df[c]: }
if idom[w] != n:
df[n] = df[n] U {w} // 如果 i 的祖先不是根,则递归查找并进行路径压缩
*/ BasicBlock* root_ancestor = evalAndCompress_lt_helper(ancestor_map[i]);
// 路径压缩时,根据 sdom_map 比较并更新 label_map
// 确保 label_map[i] 存储的是 i 到 root_ancestor 路径上 sdom_map 最小的节点
// 注意:这里的 ancestor_map[i] 已经被递归调用压缩过一次了所以是root_ancestor的旧路径
// 应该比较的是 label_map[ancestor_map[i]] 和 label_map[i]
if (sdom_map.count(label_map[ancestor_map[i]]) && // 确保 label_map[ancestor_map[i]] 存在 sdom
sdom_map.count(label_map[i]) && // 确保 label_map[i] 存在 sdom
dfnum_map[sdom_map[label_map[ancestor_map[i]]]] < dfnum_map[sdom_map[label_map[i]]]) {
if (DEBUG) std::cout << " Eval: Updating label for " << i->getName() << " from "
<< label_map[i]->getName() << " to " << label_map[ancestor_map[i]]->getName() << std::endl;
label_map[i] = label_map[ancestor_map[i]];
}
ancestor_map[i] = root_ancestor; // 执行路径压缩:将 i 直接指向其所属集合的根
if (DEBUG) std::cout << " Eval: Path compression for " << i->getName() << ", new ancestor = "
<< (root_ancestor ? root_ancestor->getName() : "nullptr") << std::endl;
return label_map[i]; // <-- **将这里改为返回 label_map[i]**
}
// Link 函数:将 v 加入 u 的 DFS 树子树中 (实际上是并查集操作)
// 对应用户代码的 fa[u] = fth[u];
void DominatorTree::link_lt_helper(BasicBlock* u_parent, BasicBlock* v_child) {
ancestor_map[v_child] = u_parent; // 设置并查集父节点
label_map[v_child] = v_child; // 初始化 label 为自身
if (DEBUG) std::cout << " Link: " << v_child->getName() << " linked to " << u_parent->getName() << std::endl;
}
// ==============================================================
// Lengauer-Tarjan 算法实现 computeIDoms
// ==============================================================
void DominatorTree::computeIDoms(Function *F) {
if (DEBUG) std::cout << "--- Computing Immediate Dominators (IDoms) using Lengauer-Tarjan ---" << std::endl;
BasicBlock *entryBlock = F->getEntryBlock();
// 1. 初始化所有 LT 相关的数据结构
dfnum_map.clear();
vertex_vec.clear();
parent_map.clear();
sdom_map.clear();
idom_map.clear();
bucket_map.clear();
ancestor_map.clear();
label_map.clear();
df_counter = 0; // DFS 计数器从 0 开始
// 预分配 vertex_vec 的大小避免频繁resize
vertex_vec.resize(F->getBasicBlocks().size() + 1);
// 在 DFS 遍历之前,先为所有基本块初始化 sdom 和 label
// 这是 Lengauer-Tarjan 算法的要求,确保所有节点在 Phase 2 开始前都在 map 中
for (auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock* bb = bb_ptr.get();
sdom_map[bb] = bb; // sdom(bb) 初始化为 bb 自身
label_map[bb] = bb; // label(bb) 初始化为 bb 自身 (用于 Union-Find 的路径压缩)
}
// 确保入口块也被正确初始化(如果它不在 F->getBasicBlocks() 的正常迭代中)
sdom_map[entryBlock] = entryBlock;
label_map[entryBlock] = entryBlock;
// Phase 1: DFS 遍历并预处理
// 对应用户代码的 dfs(st)
dfs_lt_helper(entryBlock);
idom_map[entryBlock] = nullptr; // 入口块没有即时支配者
if (DEBUG) std::cout << " IDom[" << entryBlock->getName() << "] = nullptr" << std::endl;
if (DEBUG) std::cout << " Sdom[" << entryBlock->getName() << "] = " << entryBlock->getName() << std::endl;
// 初始化并查集的祖先和 label
for (auto const& [bb_key, dfn_val] : dfnum_map) {
ancestor_map[bb_key] = nullptr; // 初始为独立集合的根
label_map[bb_key] = bb_key; // 初始 label 为自身
}
if (DEBUG) {
std::cout << " --- DFS Phase Complete ---" << std::endl;
std::cout << " dfnum_map:" << std::endl;
for (auto const& [bb, dfn] : dfnum_map) {
std::cout << " " << bb->getName() << " -> " << dfn << std::endl;
}
std::cout << " vertex_vec (by dfnum):" << std::endl;
for (size_t k = 0; k < df_counter; ++k) {
if (vertex_vec[k]) std::cout << " [" << k << "] -> " << vertex_vec[k]->getName() << std::endl;
}
std::cout << " parent_map:" << std::endl;
for (auto const& [child, parent] : parent_map) {
std::cout << " " << child->getName() << " -> " << (parent ? parent->getName() : "nullptr") << std::endl;
}
std::cout << " ------------------------" << std::endl;
}
// Phase 2: 计算半支配者 (sdom)
// 对应用户代码的 for (int i = dfc; i >= 2; --i) 循环的上半部分
// 按照 DFS 编号递减的顺序遍历所有节点 (除了 entryBlock它的 DFS 编号是 0)
if (DEBUG) std::cout << "--- Phase 2: Computing Semi-Dominators (sdom) ---" << std::endl;
for (int i = df_counter - 1; i >= 1; --i) { // 从 DFS 编号最大的节点开始,到 1
BasicBlock* w = vertex_vec[i]; // 当前处理的节点
if (DEBUG) std::cout << " Processing node w: " << w->getName() << " (dfnum=" << i << ")" << std::endl;
// 对于 w 的每个前驱 v
for (BasicBlock* v : w->getPredecessors()) {
if (DEBUG) std::cout << " Considering predecessor v: " << v->getName() << std::endl;
// 如果前驱 v 未被 DFS 访问过 (即不在 dfnum_map 中),则跳过
if (dfnum_map.find(v) == dfnum_map.end()) {
if (DEBUG) std::cout << " Predecessor " << v->getName() << " not in DFS tree, skipping." << std::endl;
continue;
}
// 调用 evalAndCompress 来找到 v 在其 DFS 树祖先链上具有最小 sdom 的节点
BasicBlock* u_with_min_sdom_on_path = evalAndCompress_lt_helper(v);
if (DEBUG) std::cout << " Eval(" << v->getName() << ") returned "
<< u_with_min_sdom_on_path->getName() << std::endl;
if (DEBUG && sdom_map.count(u_with_min_sdom_on_path) && sdom_map.count(w)) {
std::cout << " Comparing sdom: dfnum[" << sdom_map[u_with_min_sdom_on_path]->getName() << "] (" << dfnum_map[sdom_map[u_with_min_sdom_on_path]]
<< ") vs dfnum[" << sdom_map[w]->getName() << "] (" << dfnum_map[sdom_map[w]] << ")" << std::endl;
}
// 比较 sdom(u) 和 sdom(w)
if (sdom_map.count(u_with_min_sdom_on_path) && sdom_map.count(w) &&
dfnum_map[sdom_map[u_with_min_sdom_on_path]] < dfnum_map[sdom_map[w]]) {
if (DEBUG) std::cout << " Updating sdom[" << w->getName() << "] from "
<< sdom_map[w]->getName() << " to "
<< sdom_map[u_with_min_sdom_on_path]->getName() << std::endl;
sdom_map[w] = sdom_map[u_with_min_sdom_on_path]; // 更新 sdom(w)
if (DEBUG) std::cout << " Sdom update applied. New sdom[" << w->getName() << "] = " << sdom_map[w]->getName() << std::endl;
}
}
// 将 w 加入 sdom(w) 对应的桶中
bucket_map[sdom_map[w]].push_back(w);
if (DEBUG) std::cout << " Adding " << w->getName() << " to bucket of sdom(" << w->getName() << "): "
<< sdom_map[w]->getName() << std::endl;
// 将 w 的父节点加入并查集 (link 操作)
if (parent_map.count(w) && parent_map[w] != nullptr) {
link_lt_helper(parent_map[w], w);
}
// Phase 3-part 1: 处理 parent[w] 的桶中所有节点,确定部分 idom
if (parent_map.count(w) && parent_map[w] != nullptr) {
BasicBlock* p = parent_map[w]; // p 是 w 的父节点
if (DEBUG) std::cout << " Processing bucket for parent " << p->getName() << std::endl;
// 注意这里需要复制桶的内容因为原始桶在循环中会被clear
std::vector<BasicBlock*> nodes_in_p_bucket_copy = bucket_map[p];
for (BasicBlock* y : nodes_in_p_bucket_copy) {
if (DEBUG) std::cout << " Processing node y from bucket: " << y->getName() << std::endl;
// 找到 y 在其 DFS 树祖先链上具有最小 sdom 的节点
BasicBlock* u = evalAndCompress_lt_helper(y);
if (DEBUG) std::cout << " Eval(" << y->getName() << ") returned " << u->getName() << std::endl;
// 确定 idom(y)
// if sdom(eval(y)) == sdom(parent(w)), then idom(y) = parent(w)
// else idom(y) = eval(y)
if (sdom_map.count(u) && sdom_map.count(p) &&
dfnum_map[sdom_map[u]] < dfnum_map[sdom_map[p]]) {
idom_map[y] = u; // 确定的 idom
if (DEBUG) std::cout << " IDom[" << y->getName() << "] set to " << u->getName() << std::endl;
} else {
idom_map[y] = p; // p 是 y 的 idom
if (DEBUG) std::cout << " IDom[" << y->getName() << "] set to " << p->getName() << std::endl;
}
}
bucket_map[p].clear(); // 清空桶,防止重复处理
if (DEBUG) std::cout << " Cleared bucket for parent " << p->getName() << std::endl;
}
}
// Phase 3-part 2: 最终确定 idom (处理那些 idom != sdom 的节点)
if (DEBUG) std::cout << "--- Phase 3: Finalizing Immediate Dominators (idom) ---" << std::endl;
for (int i = 1; i < df_counter; ++i) { // 从 DFS 编号最小的节点 (除了 entryBlock) 开始
BasicBlock* w = vertex_vec[i];
if (DEBUG) std::cout << " Finalizing node w: " << w->getName() << std::endl;
if (idom_map.count(w) && sdom_map.count(w) && idom_map[w] != sdom_map[w]) {
// idom[w] 的 idom 是其真正的 idom
if (DEBUG) std::cout << " idom[" << w->getName() << "] (" << idom_map[w]->getName()
<< ") != sdom[" << w->getName() << "] (" << sdom_map[w]->getName() << ")" << std::endl;
if (idom_map.count(idom_map[w])) {
idom_map[w] = idom_map[idom_map[w]];
if (DEBUG) std::cout << " Updating idom[" << w->getName() << "] to idom(idom(w)): "
<< idom_map[w]->getName() << std::endl;
} else {
if (DEBUG) std::cout << " Warning: idom(idom(" << w->getName() << ")) not found, leaving idom[" << w->getName() << "] as is." << std::endl;
}
}
if (DEBUG) {
std::cout << " Final IDom[" << w->getName() << "] = " << (idom_map[w] ? idom_map[w]->getName() : "nullptr") << std::endl;
}
}
// 将计算结果从 idom_map 存储到 DominatorTree 的成员变量 IDoms 中
IDoms = idom_map;
if (DEBUG) std::cout << "--- Immediate Dominators Computation Finished ---" << std::endl;
}
// ==============================================================
// computeDominanceFrontiers 和 computeDominatorTreeChildren (保持不变)
// ==============================================================
void DominatorTree::computeDominanceFrontiers(Function *F) { void DominatorTree::computeDominanceFrontiers(Function *F) {
if (DEBUG) if (DEBUG)
@@ -221,21 +416,17 @@ void DominatorTree::computeDominanceFrontiers(Function *F) {
BasicBlock *X = bb_ptr_X.get(); BasicBlock *X = bb_ptr_X.get();
DominanceFrontiers[X].clear(); DominanceFrontiers[X].clear();
// 遍历所有可能的 Z (X支配Z或者Z就是X)
for (const auto &bb_ptr_Z : F->getBasicBlocks()) { for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
BasicBlock *Z = bb_ptr_Z.get(); BasicBlock *Z = bb_ptr_Z.get();
const std::set<BasicBlock *> *domsOfZ = getDominators(Z); const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
// 如果 X 不支配 Z则 Z 与 DF(X) 无关 if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) { // Z 不被 X 支配
if (!domsOfZ || domsOfZ->find(X) == domsOfZ->end()) {
continue; continue;
} }
// 遍历 Z 的所有后继 Y
for (BasicBlock *Y : Z->getSuccessors()) { for (BasicBlock *Y : Z->getSuccessors()) {
// 如果 Y 不被 X 严格支配,则 Y 在 DF(X) 中
// Y 不被 X 严格支配意味着 (Y不被X支配) 或 (Y就是X)
const std::set<BasicBlock *> *domsOfY = getDominators(Y); const std::set<BasicBlock *> *domsOfY = getDominators(Y);
// 如果 Y == X或者 Y 不被 X 严格支配 (即 Y 不被 X 支配)
if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) { if (Y == X || (domsOfY && domsOfY->find(X) == domsOfY->end())) {
DominanceFrontiers[X].insert(Y); DominanceFrontiers[X].insert(Y);
} }
@@ -274,23 +465,21 @@ void DominatorTree::computeDominatorTreeChildren(Function *F) {
} }
// ============================================================== // ==============================================================
// DominatorTreeAnalysisPass 的实现 // DominatorTreeAnalysisPass 的实现 (保持不变)
// ============================================================== // ==============================================================
bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) { bool DominatorTreeAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 每次运行时清空旧数据,确保重新计算 // 每次运行时清空旧数据,确保重新计算
CurrentDominatorTree = std::make_unique<DominatorTree>(F); CurrentDominatorTree = std::make_unique<DominatorTree>(F);
// 不需要手动清空mapunique_ptr会创建新的DominatorTree对象其map是空的
CurrentDominatorTree->computeDominators(F); CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F); // 修正后的IDoms算法 CurrentDominatorTree->computeIDoms(F); // 修正后的LT算法
CurrentDominatorTree->computeDominanceFrontiers(F); CurrentDominatorTree->computeDominanceFrontiers(F);
CurrentDominatorTree->computeDominatorTreeChildren(F); CurrentDominatorTree->computeDominatorTreeChildren(F);
return false; // 分析遍通常返回 false表示不修改 IR return false;
} }
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() { std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
// 返回计算好的 DominatorTree 实例,所有权转移给 AnalysisManager
return std::move(CurrentDominatorTree); return std::move(CurrentDominatorTree);
} }

View File

@@ -0,0 +1,79 @@
#include "BuildCFG.h"
#include "Dom.h"
#include "Liveness.h"
#include <iostream>
#include <queue>
#include <set>
namespace sysy {
void *BuildCFG::ID = (void *)&BuildCFG::ID; // 定义唯一的 Pass ID
// 声明Pass的分析使用
void BuildCFG::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// BuildCFG不依赖其他分析
// analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 错误的例子
// BuildCFG会使所有依赖于CFG的分析结果失效所以它必须声明这些失效
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
analysisInvalidations.insert(&LivenessAnalysisPass::ID);
}
bool BuildCFG::runOnFunction(Function *F, AnalysisManager &AM) {
if (DEBUG) {
std::cout << "Running BuildCFG pass on function: " << F->getName() << std::endl;
}
bool changed = false;
// 1. 清空所有基本块的前驱和后继列表
for (auto &bb : F->getBasicBlocks()) {
bb->clearPredecessors();
bb->clearSuccessors();
}
// 2. 遍历每个基本块重建CFG
for (auto &bb : F->getBasicBlocks()) {
// 获取基本块的最后一条指令
auto &inst = *bb->terminator();
Instruction *termInst = inst.get();
// 确保基本块有终结指令
if (!termInst) {
continue;
}
// 根据终结指令类型,建立前驱后继关系
if (termInst->isBranch()) {
// 无条件跳转
if (termInst->isUnconditional()) {
auto brInst = dynamic_cast<UncondBrInst *>(termInst);
BasicBlock *succ = dynamic_cast<BasicBlock *>(brInst->getBlock());
assert(succ && "Branch instruction's target must be a BasicBlock");
bb->addSuccessor(succ);
succ->addPredecessor(bb.get());
changed = true;
// 条件跳转
} else if (termInst->isConditional()) {
auto brInst = dynamic_cast<CondBrInst *>(termInst);
BasicBlock *trueSucc = dynamic_cast<BasicBlock *>(brInst->getThenBlock());
BasicBlock *falseSucc = dynamic_cast<BasicBlock *>(brInst->getElseBlock());
assert(trueSucc && falseSucc && "Branch instruction's targets must be BasicBlocks");
bb->addSuccessor(trueSucc);
trueSucc->addPredecessor(bb.get());
bb->addSuccessor(falseSucc);
falseSucc->addPredecessor(bb.get());
changed = true;
}
} else if (auto retInst = dynamic_cast<ReturnInst *>(termInst)) {
// RetInst没有后继无需处理
// ...
}
}
return changed;
}
} // namespace sysy

View File

@@ -0,0 +1,143 @@
#include "../../include/midend/Pass/Optimize/LargeArrayToGlobal.h"
#include "../../IR.h"
#include <unordered_map>
#include <sstream>
#include <string>
namespace sysy {
// Helper function to convert type to string
static std::string typeToString(Type *type) {
if (!type) return "null";
switch (type->getKind()) {
case Type::kInt:
return "int";
case Type::kFloat:
return "float";
case Type::kPointer:
return "ptr";
case Type::kArray: {
auto *arrayType = type->as<ArrayType>();
return "[" + std::to_string(arrayType->getNumElements()) + " x " +
typeToString(arrayType->getElementType()) + "]";
}
default:
return "unknown";
}
}
void *LargeArrayToGlobalPass::ID = &LargeArrayToGlobalPass::ID;
bool LargeArrayToGlobalPass::runOnModule(Module *M, AnalysisManager &AM) {
bool changed = false;
if (!M) {
return false;
}
// Collect all alloca instructions from all functions
std::vector<std::pair<AllocaInst*, Function*>> allocasToConvert;
for (auto &funcPair : M->getFunctions()) {
Function *F = funcPair.second.get();
if (!F || F->getBasicBlocks().begin() == F->getBasicBlocks().end()) {
continue;
}
for (auto &BB : F->getBasicBlocks()) {
for (auto &inst : BB->getInstructions()) {
if (auto *alloca = dynamic_cast<AllocaInst*>(inst.get())) {
Type *allocatedType = alloca->getAllocatedType();
// Calculate the size of the allocated type
unsigned size = calculateTypeSize(allocatedType);
// Debug: print size information
std::cout << "LargeArrayToGlobalPass: Found alloca with size " << size
<< " for type " << typeToString(allocatedType) << std::endl;
// Convert arrays of 1KB (1024 bytes) or larger to global variables
if (size >= 1024) {
std::cout << "LargeArrayToGlobalPass: Converting array of size " << size << " to global" << std::endl;
allocasToConvert.emplace_back(alloca, F);
}
}
}
}
}
// Convert the collected alloca instructions to global variables
for (auto [alloca, F] : allocasToConvert) {
convertAllocaToGlobal(alloca, F, M);
changed = true;
}
return changed;
}
unsigned LargeArrayToGlobalPass::calculateTypeSize(Type *type) {
if (!type) return 0;
switch (type->getKind()) {
case Type::kInt:
case Type::kFloat:
return 4;
case Type::kPointer:
return 8;
case Type::kArray: {
auto *arrayType = type->as<ArrayType>();
return arrayType->getNumElements() * calculateTypeSize(arrayType->getElementType());
}
default:
return 0;
}
}
void LargeArrayToGlobalPass::convertAllocaToGlobal(AllocaInst *alloca, Function *F, Module *M) {
Type *allocatedType = alloca->getAllocatedType();
// Create a unique name for the global variable
std::string globalName = generateUniqueGlobalName(alloca, F);
// Create the global variable - GlobalValue expects pointer type
Type *pointerType = Type::getPointerType(allocatedType);
GlobalValue *globalVar = M->createGlobalValue(globalName, pointerType);
if (!globalVar) {
return;
}
// Replace all uses of the alloca with the global variable
alloca->replaceAllUsesWith(globalVar);
// Remove the alloca instruction from its basic block
for (auto &BB : F->getBasicBlocks()) {
auto &instructions = BB->getInstructions();
for (auto it = instructions.begin(); it != instructions.end(); ++it) {
if (it->get() == alloca) {
instructions.erase(it);
break;
}
}
}
}
std::string LargeArrayToGlobalPass::generateUniqueGlobalName(AllocaInst *alloca, Function *F) {
std::string baseName = alloca->getName();
if (baseName.empty()) {
baseName = "array";
}
// Ensure uniqueness by appending function name and counter
static std::unordered_map<std::string, int> nameCounter;
std::string key = F->getName() + "." + baseName;
int counter = nameCounter[key]++;
std::ostringstream oss;
oss << key << "." << counter;
return oss.str();
}
} // namespace sysy

View File

@@ -148,8 +148,8 @@ void Reg2MemContext::rewritePhis(Function *func) {
// 1. 为 Phi 指令的每个入边,在前驱块的末尾插入 Store 指令 // 1. 为 Phi 指令的每个入边,在前驱块的末尾插入 Store 指令
// PhiInst 假设有 getIncomingValues() 和 getIncomingBlocks() // PhiInst 假设有 getIncomingValues() 和 getIncomingBlocks()
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 假设 PhiInst 是通过操作数来管理入边的 for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 假设 PhiInst 是通过操作数来管理入边的
Value *incomingValue = phiInst->getValue(i); // 获取入值 Value *incomingValue = phiInst->getIncomingValue(i); // 获取入值
BasicBlock *incomingBlock = phiInst->getBlock(i); // 获取对应的入块 BasicBlock *incomingBlock = phiInst->getIncomingBlock(i); // 获取对应的入块
// 在入块的跳转指令之前插入 StoreInst // 在入块的跳转指令之前插入 StoreInst
// 需要找到 incomingBlock 的终结指令 (Terminator Instruction) // 需要找到 incomingBlock 的终结指令 (Terminator Instruction)

View File

@@ -845,7 +845,7 @@ void SCCPContext::RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removed
for (Instruction *inst : insts_to_check) { for (Instruction *inst : insts_to_check) {
if (auto phi = dynamic_cast<PhiInst *>(inst)) { if (auto phi = dynamic_cast<PhiInst *>(inst)) {
phi->delBlk(removedPred); phi->removeIncomingBlock(removedPred);
} }
} }
} }

View File

@@ -189,7 +189,7 @@ bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
break; break;
} }
// 将这个 Phi 节点中来自不可达前驱unreachableBlock的输入参数删除 // 将这个 Phi 节点中来自不可达前驱unreachableBlock的输入参数删除
dynamic_cast<PhiInst *>(phiInstPtr.get())->delBlk(unreachableBlock); dynamic_cast<PhiInst *>(phiInstPtr.get())->removeIncomingBlock(unreachableBlock);
} }
} }
} }
@@ -311,7 +311,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 找到在空块链中导致 currentDefBlock 的那个前驱块 // 找到在空块链中导致 currentDefBlock 的那个前驱块
if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) { if (emptyBlockRedirectMap.count(incomingBlock) || incomingBlock == currentBlock) {
// 递归追溯该传入值 // 递归追溯该传入值
return getUltimateSourceValue(phi->getIncomingValue(incomingBlock), incomingBlock); return getUltimateSourceValue(phi->getValfromBlk(incomingBlock), incomingBlock);
} }
} }
} }
@@ -354,7 +354,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) { if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值 // 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS); Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源 // 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P // currentBlock 是 P
@@ -364,12 +364,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值 // 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源 if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue); // phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else { } else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction"); assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况 // 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值 // 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->removeIncoming(actualEmptyPredecessorOfS); phiInst->getValfromBlk(actualEmptyPredecessorOfS);
} }
} }
} else { } else {
@@ -421,7 +422,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) { if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值 // 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS); Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源 // 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P // currentBlock 是 P
@@ -431,12 +432,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值 // 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源 if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue); // phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else { } else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction"); assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况 // 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值 // 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->removeIncoming(actualEmptyPredecessorOfS); phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
} }
} }
} else { } else {
@@ -481,7 +483,7 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
if (actualEmptyPredecessorOfS) { if (actualEmptyPredecessorOfS) {
// 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值 // 获取 Phi 节点原本从 actualEmptyPredecessorOfS 接收的值
Value *valueFromEmptyPredecessor = phiInst->getIncomingValue(actualEmptyPredecessorOfS); Value *valueFromEmptyPredecessor = phiInst->getValfromBlk(actualEmptyPredecessorOfS);
// 追溯这个值,找到它在非空块中的最终来源 // 追溯这个值,找到它在非空块中的最终来源
// currentBlock 是 P // currentBlock 是 P
@@ -491,12 +493,13 @@ bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder *pBuilder) {
// 替换 Phi 节点的传入块和传入值 // 替换 Phi 节点的传入块和传入值
if (ultimateSourceValue) { // 确保成功追溯到有效来源 if (ultimateSourceValue) { // 确保成功追溯到有效来源
phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue); // phiInst->replaceIncoming(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
phiInst->replaceIncomingBlock(actualEmptyPredecessorOfS, currentBlock, ultimateSourceValue);
} else { } else {
assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction"); assert(false && "[DelEmptyBlock] Unable to trace a valid source for Phi instruction");
// 无法追溯到有效来源,这可能是个错误或特殊情况 // 无法追溯到有效来源,这可能是个错误或特殊情况
// 此时可能需要移除该 Phi 项,或者插入一个 undef 值 // 此时可能需要移除该 Phi 项,或者插入一个 undef 值
phiInst->removeIncoming(actualEmptyPredecessorOfS); phiInst->removeIncomingBlock(actualEmptyPredecessorOfS);
} }
} }
} else { } else {
@@ -647,7 +650,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
break; break;
} }
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值 // 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get()); dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
} }
} else { // cond为false或0 } else { // cond为false或0
@@ -665,7 +668,7 @@ bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder *pBuilder) {
break; break;
} }
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值 // 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->removeIncoming(basicblock.get()); dynamic_cast<PhiInst *>(phiinst.get())->removeIncomingBlock(basicblock.get());
} }
} }
} }

View File

@@ -6,6 +6,8 @@
#include "Mem2Reg.h" #include "Mem2Reg.h"
#include "Reg2Mem.h" #include "Reg2Mem.h"
#include "SCCP.h" #include "SCCP.h"
#include "BuildCFG.h"
#include "LargeArrayToGlobal.h"
#include "Pass.h" #include "Pass.h"
#include <iostream> #include <iostream>
#include <queue> #include <queue>
@@ -35,10 +37,13 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
3. 添加优化passid 3. 添加优化passid
*/ */
// 注册分析遍 // 注册分析遍
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>(); registerAnalysisPass<DominatorTreeAnalysisPass>();
registerAnalysisPass<sysy::LivenessAnalysisPass>(); registerAnalysisPass<LivenessAnalysisPass>();
// 注册优化遍 // 注册优化遍
registerOptimizationPass<BuildCFG>();
registerOptimizationPass<LargeArrayToGlobalPass>();
registerOptimizationPass<SysYDelInstAfterBrPass>(); registerOptimizationPass<SysYDelInstAfterBrPass>();
registerOptimizationPass<SysYDelNoPreBLockPass>(); registerOptimizationPass<SysYDelNoPreBLockPass>();
registerOptimizationPass<SysYBlockMergePass>(); registerOptimizationPass<SysYBlockMergePass>();
@@ -58,6 +63,16 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
if (DEBUG) std::cout << "Applying -O1 optimizations.\n"; if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n"; if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n";
if(DEBUG) {
std::cout << "=== IR Before CFGOpt Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->addPass(&LargeArrayToGlobalPass::ID);
this->run();
this->clearPasses(); this->clearPasses();
this->addPass(&SysYDelInstAfterBrPass::ID); this->addPass(&SysYDelInstAfterBrPass::ID);
this->addPass(&SysYDelNoPreBLockPass::ID); this->addPass(&SysYDelNoPreBLockPass::ID);
@@ -67,6 +82,10 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
this->addPass(&SysYAddReturnPass::ID); this->addPass(&SysYAddReturnPass::ID);
this->run(); this->run();
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->run();
if(DEBUG) { if(DEBUG) {
std::cout << "=== IR After CFGOpt Optimizations ===\n"; std::cout << "=== IR After CFGOpt Optimizations ===\n";
printPasses(); printPasses();
@@ -107,7 +126,9 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
std::cout << "=== IR After Reg2Mem Optimizations ===\n"; std::cout << "=== IR After Reg2Mem Optimizations ===\n";
printPasses(); printPasses();
} }
this->clearPasses();
this->addPass(&BuildCFG::ID);
this->run();
if (DEBUG) std::cout << "--- Custom optimization sequence finished ---\n"; if (DEBUG) std::cout << "--- Custom optimization sequence finished ---\n";
} }
@@ -122,6 +143,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
SysYPrinter printer(moduleIR); SysYPrinter printer(moduleIR);
printer.printIR(); printer.printIR();
} }
} }
void PassManager::clearPasses() { void PassManager::clearPasses() {

View File

@@ -15,6 +15,139 @@
using namespace std; using namespace std;
namespace sysy { namespace sysy {
std::pair<long long, int> calculate_signed_magic(int d) {
if (d == 0) throw std::runtime_error("Division by zero");
if (d == 1 || d == -1) return {0, 0}; // Not used by strength reduction
int k = 0;
unsigned int ad = (d > 0) ? d : -d;
unsigned int temp = ad;
while (temp > 0) {
temp >>= 1;
k++;
}
if ((ad & (ad - 1)) == 0) { // if power of 2
k--;
}
unsigned __int128 m_val = 1;
m_val <<= (32 + k - 1);
unsigned __int128 m_prime = m_val / ad;
long long m = m_prime + 1;
return {m, k};
}
// 清除因函数调用而失效的表达式缓存(保守策略)
void SysYIRGenerator::invalidateExpressionsOnCall() {
availableBinaryExpressions.clear();
availableUnaryExpressions.clear();
availableLoads.clear();
availableGEPs.clear();
}
// 在进入新的基本块时清空所有表达式缓存
void SysYIRGenerator::enterNewBasicBlock() {
availableBinaryExpressions.clear();
availableUnaryExpressions.clear();
availableLoads.clear();
availableGEPs.clear();
}
// 清除因变量赋值而失效的表达式缓存
// @param storedAddress: store 指令的目标地址 (例如 AllocaInst* 或 GEPInst*)
void SysYIRGenerator::invalidateExpressionsOnStore(Value *storedAddress) {
// 遍历二元表达式缓存,移除受影响的条目
// 创建一个临时列表来存储要移除的键,避免在迭代时修改容器
std::vector<ExpKey> binaryKeysToRemove;
for (const auto &pair : availableBinaryExpressions) {
// 检查左操作数
// 如果左操作数是 LoadInst并且它从 storedAddress 加载
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.left)) {
if (loadInst->getPointer() == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue; // 这个表达式已标记为移除,跳到下一个
}
}
// 如果左操作数本身就是被存储的地址 (例如,将一个地址值直接作为操作数,虽然不常见)
if (pair.first.left == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
// 检查右操作数,逻辑同左操作数
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.right)) {
if (loadInst->getPointer() == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
}
if (pair.first.right == storedAddress) {
binaryKeysToRemove.push_back(pair.first);
continue;
}
}
// 实际移除条目
for (const auto &key : binaryKeysToRemove) {
availableBinaryExpressions.erase(key);
}
// 遍历一元表达式缓存,移除受影响的条目
std::vector<UnExpKey> unaryKeysToRemove;
for (const auto &pair : availableUnaryExpressions) {
// 检查操作数
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.operand)) {
if (loadInst->getPointer() == storedAddress) {
unaryKeysToRemove.push_back(pair.first);
continue;
}
}
if (pair.first.operand == storedAddress) {
unaryKeysToRemove.push_back(pair.first);
continue;
}
}
// 实际移除条目
for (const auto &key : unaryKeysToRemove) {
availableUnaryExpressions.erase(key);
}
availableLoads.erase(storedAddress);
std::vector<GEPKey> gepKeysToRemove;
for (const auto &pair : availableGEPs) {
// 检查 GEP 的基指针是否受存储影响
if (auto loadInst = dynamic_cast<LoadInst *>(pair.first.basePointer)) {
if (loadInst->getPointer() == storedAddress) {
gepKeysToRemove.push_back(pair.first);
continue; // 标记此GEP为移除跳过后续检查
}
}
// 如果基指针本身就是存储的目标地址 (不常见,但可能)
if (pair.first.basePointer == storedAddress) {
gepKeysToRemove.push_back(pair.first);
continue;
}
// 检查 GEP 的每个索引是否受存储影响
for (const auto &indexVal : pair.first.indices) {
if (auto loadInst = dynamic_cast<LoadInst *>(indexVal)) {
if (loadInst->getPointer() == storedAddress) {
gepKeysToRemove.push_back(pair.first);
break; // 标记此GEP为移除并跳出内部循环
}
}
// 如果索引本身就是存储的目标地址
if (indexVal == storedAddress) {
gepKeysToRemove.push_back(pair.first);
break;
}
}
}
// 实际移除条目
for (const auto &key : gepKeysToRemove) {
availableGEPs.erase(key);
}
}
// std::vector<Value*> BinaryValueStack; ///< 用于存储value的栈 // std::vector<Value*> BinaryValueStack; ///< 用于存储value的栈
// std::vector<int> BinaryOpStack; ///< 用于存储二元表达式的操作符栈 // std::vector<int> BinaryOpStack; ///< 用于存储二元表达式的操作符栈
@@ -244,27 +377,56 @@ void SysYIRGenerator::compute() {
} }
} else { } else {
// 否则创建相应的IR指令 // 否则创建相应的IR指令
if (commonType == Type::getIntType()) { ExpKey currentExpKey(static_cast<BinaryOp>(op), lhs, rhs);
switch (op) { auto it = availableBinaryExpressions.find(currentExpKey);
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break; if (it != availableBinaryExpressions.end()) {
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break; // 在缓存中找到,重用结果
case BinaryOp::DIV: resultValue = builder.createDivInst(lhs, rhs); break; resultValue = it->second;
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break; } else {
} if (commonType == Type::getIntType()) {
} else if (commonType == Type::getFloatType()) { switch (op) {
switch (op) { case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break; case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break; case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break; case BinaryOp::DIV: {
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break; ConstantInteger *rhsConst = dynamic_cast<ConstantInteger *>(rhs);
case BinaryOp::MOD: if (rhsConst) {
std::cerr << "Error: Modulo operator not supported for float types." << std::endl; int divisor = rhsConst->getInt();
if (divisor > 0 && (divisor & (divisor - 1)) == 0) {
int shift = 0;
int temp = divisor;
while (temp > 1) {
temp >>= 1;
shift++;
}
resultValue = builder.createSRAInst(lhs, ConstantInteger::get(shift));
} else {
resultValue = builder.createDivInst(lhs, rhs);
}
} else {
resultValue = builder.createDivInst(lhs, rhs);
}
break;
}
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
}
} else if (commonType == Type::getFloatType()) {
switch (op) {
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break;
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break;
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break;
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break;
case BinaryOp::MOD:
std::cerr << "Error: Modulo operator not supported for float types." << std::endl;
return;
}
} else {
std::cerr << "Error: Unsupported type for binary instruction." << std::endl;
return; return;
} }
} else { // 将新创建的指令结果添加到缓存
std::cerr << "Error: Unsupported type for binary instruction." << std::endl; availableBinaryExpressions[currentExpKey] = resultValue;
return;
} }
} }
break; break;
@@ -316,36 +478,45 @@ void SysYIRGenerator::compute() {
return; return;
} }
} else { } else {
// 否则创建相应的IR指令 // 否则创建相应的IR指令 (在这里应用CSE)
switch (op) { UnExpKey currentUnExpKey(static_cast<BinaryOp>(op), operand);
case BinaryOp::PLUS: auto it = availableUnaryExpressions.find(currentUnExpKey);
resultValue = operand; // 一元加指令通常直接返回操作数 if (it != availableUnaryExpressions.end()) {
break; // 在缓存中找到,重用结果
case BinaryOp::NEG: { resultValue = it->second;
if (commonType == sysy::Type::getIntType()) { } else {
resultValue = builder.createNegInst(operand); switch (op) {
} else if (commonType == sysy::Type::getFloatType()) { case BinaryOp::PLUS:
resultValue = builder.createFNegInst(operand); resultValue = operand; // 一元加指令通常直接返回操作数
} else { break;
std::cerr << "Error: Negation not supported for operand type." << std::endl; case BinaryOp::NEG: {
return; if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNegInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNegInst(operand);
} else {
std::cerr << "Error: Negation not supported for operand type." << std::endl;
return;
}
break;
}
case BinaryOp::NOT:
// 逻辑非
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNotInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNotInst(operand);
} else {
std::cerr << "Error: Logical NOT not supported for operand type." << std::endl;
return;
}
break;
default:
std::cerr << "Error: Unknown unary operator for instructions: " << op << std::endl;
return;
} }
break; // 将新创建的指令结果添加到缓存
} availableUnaryExpressions[currentUnExpKey] = resultValue;
case BinaryOp::NOT:
// 逻辑非
if (commonType == sysy::Type::getIntType()) {
resultValue = builder.createNotInst(operand);
} else if (commonType == sysy::Type::getFloatType()) {
resultValue = builder.createFNotInst(operand);
} else {
std::cerr << "Error: Logical NOT not supported for operand type." << std::endl;
return;
}
break;
default:
std::cerr << "Error: Unknown unary operator for instructions: " << op << std::endl;
return;
} }
} }
break; break;
@@ -487,7 +658,19 @@ Value* SysYIRGenerator::getGEPAddressInst(Value* basePointer, const std::vector<
// `indices` 向量现在由调用方(如 visitLValue, visitVarDecl, visitAssignStmt负责完整准备 // `indices` 向量现在由调用方(如 visitLValue, visitVarDecl, visitAssignStmt负责完整准备
// 包括是否需要添加初始的 `0` 索引。 // 包括是否需要添加初始的 `0` 索引。
// 所以这里直接将其传递给 `builder.createGetElementPtrInst`。 // 所以这里直接将其传递给 `builder.createGetElementPtrInst`。
return builder.createGetElementPtrInst(basePointer, indices); GEPKey key = {basePointer, indices};
// 尝试从缓存中查找
auto it = availableGEPs.find(key);
if (it != availableGEPs.end()) {
return it->second; // 缓存命中,返回已有的 GEPInst*
}
// 缓存未命中,创建新的 GEPInst
Value* gepInst = builder.createGetElementPtrInst(basePointer, indices); // 假设 builder 提供了 createGEPInst 方法
availableGEPs[key] = gepInst; // 将新的 GEPInst* 加入缓存
return gepInst;
} }
/* /*
@@ -586,7 +769,13 @@ std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
// 显式地为局部常量在栈上分配空间 // 显式地为局部常量在栈上分配空间
// alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*` // alloca 的类型将是指针指向常量类型,例如 `int*` 或 `int[2][3]*`
// 将alloca全部集中到entry中
auto entry = builder.getBasicBlock()->getParent()->getEntryBlock();
auto it = builder.getPosition();
auto nowblk = builder.getBasicBlock();
builder.setPosition(entry, entry->terminator());
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name); AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name);
builder.setPosition(nowblk, it);
ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this)); ArrayValueTree *root = std::any_cast<ArrayValueTree *>(constDef->constInitVal()->accept(this));
ValueCounter values; ValueCounter values;
@@ -743,8 +932,12 @@ std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx) {
// 对于数组alloca 的类型将是指针指向数组类型,例如 `int[2][3]*` // 对于数组alloca 的类型将是指针指向数组类型,例如 `int[2][3]*`
// 对于标量alloca 的类型将是指针指向标量类型,例如 `int*` // 对于标量alloca 的类型将是指针指向标量类型,例如 `int*`
AllocaInst* alloca = auto entry = builder.getBasicBlock()->getParent()->getEntryBlock();
builder.createAllocaInst(Type::getPointerType(variableType), name); auto it = builder.getPosition();
auto nowblk = builder.getBasicBlock();
builder.setPosition(entry, entry->terminator());
AllocaInst *alloca = builder.createAllocaInst(Type::getPointerType(variableType), name);
builder.setPosition(nowblk, it);
if (varDef->initVal() != nullptr) { if (varDef->initVal() != nullptr) {
ValueCounter values; ValueCounter values;
@@ -946,6 +1139,8 @@ std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext *ctx) {
std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
// 更新作用域 // 更新作用域
module->enterNewScope(); module->enterNewScope();
// 清除CSE缓存
enterNewBasicBlock();
auto name = ctx->Ident()->getText(); auto name = ctx->Ident()->getText();
std::vector<Type *> paramActualTypes; std::vector<Type *> paramActualTypes;
@@ -1037,6 +1232,7 @@ std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext *ctx){
// 从 entryBB 无条件跳转到 funcBodyEntry // 从 entryBB 无条件跳转到 funcBodyEntry
builder.createUncondBrInst(funcBodyEntry); builder.createUncondBrInst(funcBodyEntry);
BasicBlock::conectBlocks(entry, funcBodyEntry); // 连接 entryBB 和 funcBodyEntry
builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry builder.setPosition(funcBodyEntry,funcBodyEntry->end()); // 将插入点设置到 funcBodyEntry
for (auto item : ctx->blockStmt()->blockItem()) { for (auto item : ctx->blockStmt()->blockItem()) {
@@ -1100,7 +1296,16 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) { if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) {
Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType(); Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType();
if (allocatedType->isPointer()) { if (allocatedType->isPointer()) {
gepBasePointer = builder.createLoadInst(alloc); // 尝试从缓存中获取 builder.createLoadInst(alloc) 的结果
auto it = availableLoads.find(alloc);
if (it != availableLoads.end()) {
gepBasePointer = it->second; // 缓存命中,重用
} else {
gepBasePointer = builder.createLoadInst(alloc); // 缓存未命中,创建新的 LoadInst
availableLoads[alloc] = gepBasePointer; // 将结果加入缓存
}
// --- CSE 结束 ---
// gepBasePointer = builder.createLoadInst(alloc);
gepIndices = indices; gepIndices = indices;
} else { } else {
gepBasePointer = alloc; gepBasePointer = alloc;
@@ -1162,9 +1367,9 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
} }
} }
} }
builder.createStoreInst(RValue, LValue); builder.createStoreInst(RValue, LValue);
invalidateExpressionsOnStore(LValue);
return std::any(); return std::any();
} }
@@ -1201,7 +1406,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(thenBlock); function->addBasicBlock(thenBlock);
builder.setPosition(thenBlock, thenBlock->end()); builder.setPosition(thenBlock, thenBlock->end());
// CSE清除缓存
enterNewBasicBlock();
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0)); auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
// 如果是块语句,直接访问 // 如果是块语句,直接访问
// 否则访问语句 // 否则访问语句
@@ -1220,7 +1427,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(elseBlock); function->addBasicBlock(elseBlock);
builder.setPosition(elseBlock, elseBlock->end()); builder.setPosition(elseBlock, elseBlock->end());
// CSE清除缓存
enterNewBasicBlock();
block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(1)); block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(1));
if (block != nullptr) { if (block != nullptr) {
visitBlockStmt(block); visitBlockStmt(block);
@@ -1237,7 +1446,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(exitBlock); function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end()); builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
} else { } else {
builder.pushTrueBlock(thenBlock); builder.pushTrueBlock(thenBlock);
builder.pushFalseBlock(exitBlock); builder.pushFalseBlock(exitBlock);
@@ -1250,7 +1461,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(thenBlock); function->addBasicBlock(thenBlock);
builder.setPosition(thenBlock, thenBlock->end()); builder.setPosition(thenBlock, thenBlock->end());
// CSE清除缓存
enterNewBasicBlock();
auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0)); auto block = dynamic_cast<SysYParser::BlockStmtContext *>(ctx->stmt(0));
if (block != nullptr) { if (block != nullptr) {
visitBlockStmt(block); visitBlockStmt(block);
@@ -1267,6 +1480,9 @@ std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(exitBlock); function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end()); builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
} }
return std::any(); return std::any();
} }
@@ -1284,7 +1500,9 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
builder.createUncondBrInst(headBlock); builder.createUncondBrInst(headBlock);
BasicBlock::conectBlocks(curBlock, headBlock); BasicBlock::conectBlocks(curBlock, headBlock);
builder.setPosition(headBlock, headBlock->end()); builder.setPosition(headBlock, headBlock->end());
// CSE清除缓存
enterNewBasicBlock();
BasicBlock* bodyBlock = new BasicBlock(function); BasicBlock* bodyBlock = new BasicBlock(function);
BasicBlock* exitBlock = new BasicBlock(function); BasicBlock* exitBlock = new BasicBlock(function);
@@ -1300,6 +1518,8 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(bodyBlock); function->addBasicBlock(bodyBlock);
builder.setPosition(bodyBlock, bodyBlock->end()); builder.setPosition(bodyBlock, bodyBlock->end());
// CSE清除缓存
enterNewBasicBlock();
builder.pushBreakBlock(exitBlock); builder.pushBreakBlock(exitBlock);
builder.pushContinueBlock(headBlock); builder.pushContinueBlock(headBlock);
@@ -1324,7 +1544,9 @@ std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext *ctx) {
labelstring.str(""); labelstring.str("");
function->addBasicBlock(exitBlock); function->addBasicBlock(exitBlock);
builder.setPosition(exitBlock, exitBlock->end()); builder.setPosition(exitBlock, exitBlock->end());
// CSE清除缓存
enterNewBasicBlock();
return std::any(); return std::any();
} }
@@ -1439,62 +1661,34 @@ std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
// 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量 // 3. 处理可变变量 (AllocaInst/GlobalValue) 或带非常量索引的常量变量
// 这里区分标量访问和数组元素/子数组访问 // 这里区分标量访问和数组元素/子数组访问
Value *targetAddress = nullptr;
// 检查是否是访问标量变量本身没有索引且声明维度为0 // 检查是否是访问标量变量本身没有索引且声明维度为0
if (dims.empty() && declaredNumDims == 0) { if (dims.empty() && declaredNumDims == 0) {
// 对于标量变量,直接加载其值。
// variable 本身就是指向标量的指针 (e.g., int* %a)
if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) { if (dynamic_cast<AllocaInst*>(variable) || dynamic_cast<GlobalValue*>(variable)) {
value = builder.createLoadInst(variable); targetAddress = variable;
} else { } else {
// 如果走到这里且不是AllocaInst/GlobalValue但dims为空且declaredNumDims为0
// 且又不是ConstantVariable (前面已处理),则可能是错误情况。
assert(false && "Unhandled scalar variable type in LValue access."); assert(false && "Unhandled scalar variable type in LValue access.");
return static_cast<Value*>(nullptr); return static_cast<Value*>(nullptr);
} }
} else { } else {
// 访问数组元素或子数组(有索引,或变量本身是数组/多维指针)
Value* gepBasePointer = nullptr; Value* gepBasePointer = nullptr;
std::vector<Value*> gepIndices; // 准备传递给 getGEPAddressInst 的索引列表 std::vector<Value*> gepIndices;
// GEP 的基指针就是变量本身(它是一个指向内存的指针)
if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) { if (AllocaInst *alloc = dynamic_cast<AllocaInst *>(variable)) {
// 情况 A: 局部变量 (AllocaInst)
// 获取 AllocaInst 分配的内存的实际类型。
// 例如:对于 `int b[10][20];``allocatedType` 是 `[10 x [20 x i32]]`。
// 对于 `int b[][20]` 的函数参数,其 AllocaInst 存储的是一个指针,
// 此时 `allocatedType` 是 `[20 x i32]*`。
Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType(); Type* allocatedType = alloc->getType()->as<PointerType>()->getBaseType();
if (allocatedType->isPointer()) { if (allocatedType->isPointer()) {
// 如果 AllocaInst 分配的是一个指针类型 (例如,用于存储函数参数的指针,如 int b[][20] 中的 b) gepBasePointer = builder.createLoadInst(alloc);
// 即 `allocatedType` 是一个指向数组指针的指针 (e.g., [20 x i32]**)
// 那么 GEP 的基指针是加载这个指针变量的值。
gepBasePointer = builder.createLoadInst(alloc); // 加载出实际的指针值 (e.g., [20 x i32]*)
// 对于这种参数指针,用户提供的索引直接作用于它。不需要额外的 0。
gepIndices = dims; gepIndices = dims;
} else { } else {
// 如果 AllocaInst 分配的是实际的数组数据 (例如int b[10][20] 中的 b) gepBasePointer = alloc;
// 那么 AllocaInst 本身就是 GEP 的基指针。
// 这里的 `alloc` 是指向数组的指针 (e.g., [10 x [20 x i32]]*)
gepBasePointer = alloc; // 类型是 [10 x [20 x i32]]*
// 对于这种完整的数组分配GEP 的第一个索引必须是 0用于“步过”整个数组。
gepIndices.push_back(ConstantInteger::get(0)); gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end()); gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
} }
} else if (GlobalValue *glob = dynamic_cast<GlobalValue *>(variable)) { } else if (GlobalValue *glob = dynamic_cast<GlobalValue *>(variable)) {
// 情况 B: 全局变量 (GlobalValue) gepBasePointer = glob;
// GlobalValue 总是指向全局数据的指针。
gepBasePointer = glob; // 类型是 [61 x [67 x i32]]*
// 对于全局数组GEP 的第一个索引必须是 0用于“步过”整个数组。
gepIndices.push_back(ConstantInteger::get(0)); gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end()); gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
} else if (ConstantVariable *constV = dynamic_cast<ConstantVariable *>(variable)) { } else if (ConstantVariable *constV = dynamic_cast<ConstantVariable *>(variable)) {
// 情况 C: 常量变量 (ConstantVariable),如果它代表全局数组常量
// 假设 ConstantVariable 可以直接作为 GEP 的基指针。
gepBasePointer = constV; gepBasePointer = constV;
// 对于常量数组,也需要 0 索引来“步过”整个数组。
// 这里可以进一步检查 constV->getType()->as<PointerType>()->getBaseType()->isArray()
// 但为了简洁,假设所有 ConstantVariable 作为 GEP 基指针时都需要此 0。
gepIndices.push_back(ConstantInteger::get(0)); gepIndices.push_back(ConstantInteger::get(0));
gepIndices.insert(gepIndices.end(), dims.begin(), dims.end()); gepIndices.insert(gepIndices.end(), dims.begin(), dims.end());
} else { } else {
@@ -1502,18 +1696,25 @@ std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext *ctx) {
return static_cast<Value *>(nullptr); return static_cast<Value *>(nullptr);
} }
// 现在调用 getGEPAddressInst传入正确准备的基指针和索引列表 targetAddress = getGEPAddressInst(gepBasePointer, gepIndices);
Value *targetAddress = getGEPAddressInst(gepBasePointer, gepIndices);
// 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址 }
if (dims.size() < declaredNumDims) {
value = targetAddress; // 如果提供的索引数量少于声明的维度数量,则表示访问的是子数组,返回其地址 (无需加载)
if (dims.size() < declaredNumDims) {
value = targetAddress;
} else {
// value = builder.createLoadInst(targetAddress);
auto it = availableLoads.find(targetAddress);
if (it != availableLoads.end()) {
value = it->second; // 缓存命中,重用已有的 LoadInst 结果
} else { } else {
// 否则,表示访问的是最终的标量元素,加载其值 // 缓存未命中,创建新的 LoadInst
// 假设 createLoadInst 接受 Value* pointer value = builder.createLoadInst(targetAddress);
value = builder.createLoadInst(targetAddress); availableLoads[targetAddress] = value; // 将新的 LoadInst 结果加入缓存
} }
} }
return value; return value;
} }
@@ -1633,6 +1834,7 @@ std::any SysYIRGenerator::visitUnaryExp(SysYParser::UnaryExpContext *ctx) {
visitPrimaryExp(ctx->primaryExp()); visitPrimaryExp(ctx->primaryExp());
} else if (ctx->call() != nullptr) { } else if (ctx->call() != nullptr) {
BinaryExpStack.push_back(std::any_cast<Value *>(visitCall(ctx->call())));BinaryExpLenStack.back()++; BinaryExpStack.push_back(std::any_cast<Value *>(visitCall(ctx->call())));BinaryExpLenStack.back()++;
invalidateExpressionsOnCall();
} else if (ctx->unaryOp() != nullptr) { } else if (ctx->unaryOp() != nullptr) {
// 遇到一元操作符,将其压入 BinaryExpStack // 遇到一元操作符,将其压入 BinaryExpStack
auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->unaryOp()->children[0]); auto opNode = dynamic_cast<antlr4::tree::TerminalNode*>(ctx->unaryOp()->children[0]);

View File

@@ -240,6 +240,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kMul: case Kind::kMul:
case Kind::kDiv: case Kind::kDiv:
case Kind::kRem: case Kind::kRem:
case Kind::kSRA:
case Kind::kMulh:
case Kind::kFAdd: case Kind::kFAdd:
case Kind::kFSub: case Kind::kFSub:
case Kind::kFMul: case Kind::kFMul:
@@ -272,6 +274,8 @@ void SysYPrinter::printInst(Instruction *pInst) {
case Kind::kMul: std::cout << "mul"; break; case Kind::kMul: std::cout << "mul"; break;
case Kind::kDiv: std::cout << "sdiv"; break; case Kind::kDiv: std::cout << "sdiv"; break;
case Kind::kRem: std::cout << "srem"; break; case Kind::kRem: std::cout << "srem"; break;
case Kind::kSRA: std::cout << "ashr"; break;
case Kind::kMulh: std::cout << "mulh"; break;
case Kind::kFAdd: std::cout << "fadd"; break; case Kind::kFAdd: std::cout << "fadd"; break;
case Kind::kFSub: std::cout << "fsub"; break; case Kind::kFSub: std::cout << "fsub"; break;
case Kind::kFMul: std::cout << "fmul"; break; case Kind::kFMul: std::cout << "fmul"; break;
@@ -295,7 +299,12 @@ void SysYPrinter::printInst(Instruction *pInst) {
// Types and operands // Types and operands
std::cout << " "; std::cout << " ";
printType(binInst->getType()); // For comparison operations, print operand types instead of result type
if (pInst->getKind() >= Kind::kICmpEQ && pInst->getKind() <= Kind::kFCmpGE) {
printType(binInst->getLhs()->getType());
} else {
printType(binInst->getType());
}
std::cout << " "; std::cout << " ";
printValue(binInst->getLhs()); printValue(binInst->getLhs());
std::cout << ", "; std::cout << ", ";
@@ -508,9 +517,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
if (!firstPair) std::cout << ", "; if (!firstPair) std::cout << ", ";
firstPair = false; firstPair = false;
std::cout << "[ "; std::cout << "[ ";
printValue(phiInst->getValue(i)); printValue(phiInst->getIncomingValue(i));
std::cout << ", %"; std::cout << ", %";
printBlock(phiInst->getBlock(i)); printBlock(phiInst->getIncomingBlock(i));
std::cout << " ]"; std::cout << " ]";
} }
std::cout << std::endl; std::cout << std::endl;

View File

@@ -1 +0,0 @@
3

View File

@@ -1,3 +0,0 @@
int main(){
return 3;
}

View File

@@ -1 +0,0 @@
10

View File

@@ -1,8 +0,0 @@
//test domain of global var define and local define
int a = 3;
int b = 5;
int main(){
int a = 5;
return a + b;
}

View File

@@ -1 +0,0 @@
5

View File

@@ -1,8 +0,0 @@
//test local var define
int main(){
int a, b0, _c;
a = 1;
b0 = 2;
_c = 3;
return b0 + _c;
}

View File

@@ -1 +0,0 @@
0

View File

@@ -1,4 +0,0 @@
int a[10][10];
int main(){
return 0;
}

View File

@@ -1 +0,0 @@
14

View File

@@ -1,9 +0,0 @@
//test array define
int main(){
int a[4][2] = {};
int b[4][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int c[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
int d[4][2] = {1, 2, {3}, {5}, 7 , 8};
int e[4][2] = {{d[2][1], c[2][1]}, {3, 4}, {5, 6}, {7, 8}};
return e[3][1] + e[0][0] + e[0][1] + a[2][0];
}

View File

@@ -1 +0,0 @@
21

View File

@@ -1,9 +0,0 @@
int main(){
const int a[4][2] = {{1, 2}, {3, 4}, {}, 7};
int b[4][2] = {};
int c[4][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int d[3 + 1][2] = {1, 2, {3}, {5}, a[3][0], 8};
int e[4][2][1] = {{d[2][1], {c[2][1]}}, {3, 4}, {5, 6}, {7, 8}};
return e[3][1][0] + e[0][0][0] + e[0][1][0] + d[3][0];
}

View File

@@ -1 +0,0 @@
5

View File

@@ -1,6 +0,0 @@
//test const gloal var define
const int a = 10, b = 5;
int main(){
return b;
}

View File

@@ -1 +0,0 @@
5

View File

@@ -1,5 +0,0 @@
//test const local var define
int main(){
const int a = 10, b = 5;
return b;
}

View File

@@ -1 +0,0 @@
4

View File

@@ -1,5 +0,0 @@
const int a[5]={0,1,2,3,4};
int main(){
return a[4];
}

View File

@@ -1 +0,0 @@
9

View File

@@ -1,11 +0,0 @@
int a;
int func(int p){
p = p - 1;
return p;
}
int main(){
int b;
a = 10;
b = func(a);
return b;
}

View File

@@ -1 +0,0 @@
4

View File

@@ -1,8 +0,0 @@
int defn(){
return 4;
}
int main(){
int a=defn();
return a;
}

View File

@@ -1 +0,0 @@
9

View File

@@ -1,7 +0,0 @@
//test add
int main(){
int a, b;
a = 10;
b = -1;
return a + b;
}

View File

@@ -1 +0,0 @@
15

View File

@@ -1,5 +0,0 @@
//test addc
const int a = 10;
int main(){
return a + 5;
}

View File

@@ -1 +0,0 @@
248

View File

@@ -1,7 +0,0 @@
//test sub
const int a = 10;
int main(){
int b;
b = 2;
return b - a;
}

View File

@@ -1 +0,0 @@
8

View File

@@ -1,6 +0,0 @@
//test subc
int main(){
int a;
a = 10;
return a - 2;
}

View File

@@ -1 +0,0 @@
50

View File

@@ -1,7 +0,0 @@
//test mul
int main(){
int a, b;
a = 10;
b = 5;
return a * b;
}

View File

@@ -1 +0,0 @@
25

View File

@@ -1,5 +0,0 @@
//test mulc
const int a = 5;
int main(){
return a * 5;
}

View File

@@ -1 +0,0 @@
2

View File

@@ -1,7 +0,0 @@
//test div
int main(){
int a, b;
a = 10;
b = 5;
return a / b;
}

View File

@@ -1 +0,0 @@
2

Some files were not shown because too many files have changed in this diff Show More