[backend] 新pass ACE修改完毕

This commit is contained in:
Lixuanwang
2025-07-18 13:04:02 +08:00
parent b90e4faa6a
commit 198c1974e3

View File

@@ -1,43 +1,34 @@
#include "AddressCalculationExpansion.h"
#include <iostream>
#include <vector>
#include <algorithm> // for std::reverse (if needed, although not used in final version)
#include "IR.h" // 确保IR.h包含所有类型和指令的定义特别是ConstantValue, AllocaInst, GlobalValue
#include "IRBuilder.h" // 确保这里也包含 IRBuilder.h
#include "IR.h"
#include "IRBuilder.h"
extern int DEBUG; // 假设有一个全局的DEBUG宏
extern int DEBUG;
namespace sysy {
bool AddressCalculationExpansion::run() {
bool changed = false;
// 遍历所有函数
for (auto& funcPair : pModule->getFunctions()) {
Function* func = funcPair.second.get();
// 遍历函数中的所有基本块
for (auto& bb_ptr : func->getBasicBlocks()) {
BasicBlock* bb = bb_ptr.get();
// 使用list迭代器因为可能会删除元素
for (auto it = bb->getInstructions().begin(); it != bb->getInstructions().end(); ) {
Instruction* inst = it->get();
Value* basePointer = nullptr;
Value* valueToStore = nullptr; // 仅用于 StoreInst
size_t firstIndexOperandIdx = 0; // 第一个索引操作数在指令操作数列表中的位置
size_t numBaseOperands = 0; // Load/Store指令的基础操作数数量
Value* valueToStore = nullptr;
size_t firstIndexOperandIdx = 0;
size_t numBaseOperands = 0;
if (inst->isLoad()) {
// LoadInst: %result = load Type, Type* %ptr, Index1, Index2, ...
// 操作数: pointer(0), index1(1), index2(2), ...
numBaseOperands = 1; // 只有指针操作数
numBaseOperands = 1;
basePointer = inst->getOperand(0);
firstIndexOperandIdx = 1;
} else if (inst->isStore()) {
// StoreInst: store Type %val, Type* %ptr, Index1, Index2, ...
// 操作数: value(0), pointer(1), index1(2), index2(3), ...
numBaseOperands = 2; // value 和 pointer 操作数
numBaseOperands = 2;
valueToStore = inst->getOperand(0);
basePointer = inst->getOperand(1);
firstIndexOperandIdx = 2;
@@ -46,48 +37,32 @@ bool AddressCalculationExpansion::run() {
continue;
}
// 如果操作数数量 <= 基础操作数数量,说明没有索引,跳过
if (inst->getNumOperands() <= numBaseOperands) {
++it;
continue;
}
// 获取数组的维度信息
std::vector<int> dims; // 存储数组的维度大小(整数)
// 统一获取维度的方式,不再使用 ArrayType
std::vector<int> dims;
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
// MODIFICATION: 将 getValue() 替换为 getValue<int>()
for (const auto& use_ptr : allocaInst->getDims()) {
Value* dimValue = use_ptr->getValue();
if (ConstantValue* constVal = dynamic_cast<ConstantValue*>(dimValue)) {
dims.push_back(constVal->getValue<int>()); // MODIFICATION: 明确指定模板参数为 int
dims.push_back(constVal->getValue<int>());
} else {
// 如果维度不是 ConstantValue或者不是整数这里需要根据你的IR定义进行处理
std::cerr << "Warning: AllocaInst dimension is not a constant integer. Skipping GEP expansion for: ";
SysYPrinter::printValue(allocaInst);
std::cerr << "\n";
dims.clear(); // 清空,表示无法获取有效维度
dims.clear();
break;
}
}
} else if (GlobalValue* globalValue = dynamic_cast<GlobalValue*>(basePointer)) {
// 处理 GlobalValue 的维度
// 假设 GlobalValue 也有类似 AllocaInst 的 getNumDims() 和 getDim() 方法
// 这需要根据你的 GlobalValue 实际定义来验证和实现
// 如果 GlobalValue::getType() 是 PointerType其 baseType 可能是另一个 PointerType
// 或者 GlobalValue 自身就存储了维度
// 暂时跳过 GlobalValue 的 GEP 展开,如果无法确定其维度
std::cerr << "Warning: GlobalValue dimension handling needs explicit implementation for GEP expansion. Skipping GEP for: ";
SysYPrinter::printValue(globalValue);
std::cerr << "\n";
++it;
continue;
continue;
} else {
// 基指针不是 AllocaInst 也不是 GlobalValue或者无法处理其维度
// 这可能是函数参数(指针到数组),或者其他复杂指针
std::cerr << "Warning: Base pointer is not AllocaInst/GlobalValue or its array dimensions cannot be determined for GEP expansion. Skipping GEP for: ";
SysYPrinter::printValue(basePointer);
std::cerr << " in instruction ";
@@ -97,8 +72,6 @@ bool AddressCalculationExpansion::run() {
continue;
}
// 如果没有获取到有效的维度信息例如AllocaInst 没有维度但我们预期有,或者解析失败)
// 且不是一个标量 Load/Store即有索引
if (dims.empty() && (inst->getNumOperands() > numBaseOperands)) {
if (DEBUG) {
std::cerr << "ACE Warning: Could not get valid array dimensions for ";
@@ -111,14 +84,11 @@ bool AddressCalculationExpansion::run() {
continue;
}
// 收集所有索引操作数
std::vector<Value*> indexOperands;
for (size_t i = firstIndexOperandIdx; i < inst->getNumOperands(); ++i) {
indexOperands.push_back(inst->getOperand(i));
}
// 检查索引数量是否与维度匹配 (一个简单的健全性检查)
// 只有当 basePointer 是 AllocaInst 或 GlobalValue 且有明确维度时才进行此检查
if (AllocaInst* allocaInst = dynamic_cast<AllocaInst*>(basePointer)) {
if (allocaInst->getNumDims() != indexOperands.size()) {
if (DEBUG) {
@@ -130,88 +100,57 @@ bool AddressCalculationExpansion::run() {
continue;
}
}
// TODO: 对 GlobalValue 也做类似检查
// 最终线性偏移量 (字节数)
// 初始化为0因为所有偏移都是相对于基地址
Value* totalOffset = ConstantValue::get(0);
// 在当前Load/Store指令之前设置插入点
Value* totalOffset = ConstantValue::get(0);
pBuilder->setPosition(bb, it);
// 遍历所有索引来计算地址
// 累加每个维度贡献的偏移量
for (size_t i = 0; i < indexOperands.size(); ++i) {
Value* index = indexOperands[i];
// 计算当前维度索引的步长(字节数)
int stride = calculateStride(dims, i);
Value* strideConst = ConstantValue::get(stride);
// 1. 计算当前索引的偏移量: %current_dim_offset = index * stride
Type* intType = Type::getIntType(); // 假设索引和偏移量都是int类型
BinaryInst* currentDimOffsetInst = pBuilder->createBinaryInst(Instruction::kMul, intType, index, strideConst);
// UD 链管理由 IRBuilder 负责,不需要手动 addUse
// 2. 将当前维度偏移量加到累计总偏移量上: %new_total_offset = total_offset + current_dim_offset
Value* strideConst = ConstantValue::get(stride);
Type* intType = Type::getIntType();
BinaryInst* currentDimOffsetInst = pBuilder->createBinaryInst(Instruction::kMul, intType, index, strideConst);
BinaryInst* newTotalOffsetInst = pBuilder->createBinaryInst(Instruction::kAdd, intType, totalOffset, currentDimOffsetInst);
// UD 链管理由 IRBuilder 负责,不需要手动 addUse
totalOffset = newTotalOffsetInst; // 更新累计总偏移量
totalOffset = newTotalOffsetInst;
}
// 创建新的LoadInst或StoreInst将计算出的总偏移量作为唯一的偏移量参数
Instruction* newInst = nullptr;
// 新 Load/Store 指令的索引列表,只包含计算出的总偏移量
std::vector<Value*> newIndices = {totalOffset}; // 将 totalOffset 作为索引
// 计算有效地址effective_address = basePointer + totalOffset
Value* effective_address = pBuilder->createBinaryInst(Instruction::kAdd, basePointer->getType(), basePointer, totalOffset);
// 创建新的 LoadInst 或 StoreInstindices 为空
Instruction* newInst = nullptr;
if (inst->isLoad()) {
newInst = pBuilder->createLoadInst(basePointer, newIndices);
// 替换所有使用旧LoadInst结果的地方
newInst = pBuilder->createLoadInst(effective_address, {});
inst->replaceAllUsesWith(newInst);
} else { // StoreInst
newInst = pBuilder->createStoreInst(valueToStore, basePointer, newIndices);
newInst = pBuilder->createStoreInst(valueToStore, effective_address, {});
}
// 删除原始的LoadInst或StoreInst
// 注意:这里需要先让迭代器指向下一个指令,再删除当前指令
Instruction* oldInst = it->get();
++it; // 提前移动迭代器
// 清理旧指令的UD链修正 getOperandAsUse 的使用
// Instruction 没有 getOperandAsUse()。我们通过 getOperand(i) 获取 Value*
// 然后从该 Value* 的 uses 列表中找到并移除对应 oldInst 的 Use。
for(size_t i = 0; i < oldInst->getNumOperands(); ++i) {
++it;
for (size_t i = 0; i < oldInst->getNumOperands(); ++i) {
Value* operandValue = oldInst->getOperand(i);
if (operandValue) {
for (auto use_it = operandValue->getUses().begin(); use_it != operandValue->getUses().end(); ++use_it) {
if ((*use_it)->getUser() == oldInst && (*use_it)->getIndex() == i) {
operandValue->removeUse(*use_it);
break; // 找到并移除了,可以跳出内层循环
break;
}
}
}
}
// 从基本块中删除旧指令
// 使用 BasicBlock 的 list 的 erase 方法
bb->getInstructions().erase(std::prev(it)); // it 已经向前移动,所以需要 prev(it) 指向旧指令的位置
bb->getInstructions().erase(std::prev(it));
changed = true;
if (DEBUG) {
std::cerr << "ACE: Expanded array access. New insts leading to final offset:\n";
// 检查 totalOffset 是否是 Instruction 类型才能打印
if (Instruction* offsetInst = dynamic_cast<Instruction*>(totalOffset)) {
SysYPrinter::printInst(offsetInst);
} else {
SysYPrinter::printValue(totalOffset); // 如果是常量打印Value
}
std::cerr << "ACE: Computed effective address:\n";
SysYPrinter::printInst(dynamic_cast<Instruction*>(effective_address));
std::cerr << "ACE: New Load/Store instruction:\n";
SysYPrinter::printInst(newInst);
std::cerr << "--------------------------------\n";
}
// 迭代器it已经提前移动无需再次++it
}
}
}