diff --git a/src/AddressCalculationExpansion.cpp b/src/AddressCalculationExpansion.cpp index 0f03003..f4e9a14 100644 --- a/src/AddressCalculationExpansion.cpp +++ b/src/AddressCalculationExpansion.cpp @@ -1,43 +1,34 @@ #include "AddressCalculationExpansion.h" #include #include -#include // 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 dims; // 存储数组的维度大小(整数) - - // 统一获取维度的方式,不再使用 ArrayType + std::vector dims; if (AllocaInst* allocaInst = dynamic_cast(basePointer)) { - // MODIFICATION: 将 getValue() 替换为 getValue() for (const auto& use_ptr : allocaInst->getDims()) { Value* dimValue = use_ptr->getValue(); if (ConstantValue* constVal = dynamic_cast(dimValue)) { - dims.push_back(constVal->getValue()); // MODIFICATION: 明确指定模板参数为 int + dims.push_back(constVal->getValue()); } 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(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 indexOperands; for (size_t i = firstIndexOperandIdx; i < inst->getNumOperands(); ++i) { indexOperands.push_back(inst->getOperand(i)); } - // 检查索引数量是否与维度匹配 (一个简单的健全性检查) - // 只有当 basePointer 是 AllocaInst 或 GlobalValue 且有明确维度时才进行此检查 if (AllocaInst* allocaInst = dynamic_cast(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 newIndices = {totalOffset}; // 将 totalOffset 作为索引 + // 计算有效地址:effective_address = basePointer + totalOffset + Value* effective_address = pBuilder->createBinaryInst(Instruction::kAdd, basePointer->getType(), basePointer, totalOffset); + // 创建新的 LoadInst 或 StoreInst,indices 为空 + 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(totalOffset)) { - SysYPrinter::printInst(offsetInst); - } else { - SysYPrinter::printValue(totalOffset); // 如果是常量,打印Value - } + std::cerr << "ACE: Computed effective address:\n"; + SysYPrinter::printInst(dynamic_cast(effective_address)); std::cerr << "ACE: New Load/Store instruction:\n"; SysYPrinter::printInst(newInst); std::cerr << "--------------------------------\n"; } - // 迭代器it已经提前移动,无需再次++it } } }