Merge branch 'backend' into deploy-20250804
This commit is contained in:
@@ -46,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);
|
||||||
|
|||||||
@@ -47,12 +47,22 @@ void PrologueEpilogueInsertionPass::runOnMachineFunction(MachineFunction* mfunc)
|
|||||||
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;
|
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;
|
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;
|
int aligned_stack_size = (total_stack_size + 15) & ~15;
|
||||||
frame_info.total_size = aligned_stack_size;
|
frame_info.total_size = aligned_stack_size;
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
|
// 检查是否为内存加载/存储指令,以处理特殊的打印格式
|
||||||
@@ -236,4 +237,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
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "RISCv64ISel.h"
|
#include "RISCv64ISel.h"
|
||||||
|
#include "IR.h" // For GlobalValue
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -1361,14 +1339,19 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
|||||||
if (stride != 0) {
|
if (stride != 0) {
|
||||||
// --- 为当前索引和步长生成偏移计算指令 ---
|
// --- 为当前索引和步长生成偏移计算指令 ---
|
||||||
auto offset_vreg = getNewVReg();
|
auto offset_vreg = getNewVReg();
|
||||||
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();
|
||||||
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)作为偏移量,无需乘法
|
||||||
@@ -1726,4 +1709,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
|
||||||
@@ -55,12 +55,41 @@ void RISCv64RegAlloc::run() {
|
|||||||
|
|
||||||
if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n";
|
if (DEBUG) std::cerr << "===== Running Graph Coloring Register Allocation for function: " << MFunc->getName() << " =====\n";
|
||||||
|
|
||||||
while (true) {
|
const int MAX_ITERATIONS = 50;
|
||||||
|
int iteration = 0;
|
||||||
|
|
||||||
|
while (iteration++ < MAX_ITERATIONS) {
|
||||||
if (doAllocation()) {
|
if (doAllocation()) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
rewriteProgram();
|
rewriteProgram();
|
||||||
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation ---\n";
|
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n";
|
||||||
|
|
||||||
|
if (iteration >= MAX_ITERATIONS) {
|
||||||
|
std::cerr << "ERROR: Register allocation failed to converge after " << MAX_ITERATIONS << " iterations\n";
|
||||||
|
std::cerr << " Spill worklist size: " << spillWorklist.size() << "\n";
|
||||||
|
std::cerr << " Total nodes: " << (initial.size() + coloredNodes.size()) << "\n";
|
||||||
|
|
||||||
|
// Emergency spill remaining nodes to break the loop
|
||||||
|
std::cerr << " Emergency spilling remaining spill worklist nodes...\n";
|
||||||
|
for (unsigned node : spillWorklist) {
|
||||||
|
spilledNodes.insert(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also spill any nodes that didn't get colors
|
||||||
|
std::set<unsigned> uncolored;
|
||||||
|
for (unsigned node : initial) {
|
||||||
|
if (color_map.find(node) == color_map.end()) {
|
||||||
|
uncolored.insert(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned node : uncolored) {
|
||||||
|
spilledNodes.insert(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force completion
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,30 +151,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);
|
||||||
@@ -402,14 +407,32 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1357,9 +1380,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1371,7 +1394,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -17,7 +23,8 @@ public:
|
|||||||
// 公开接口,以便后续模块(如RegAlloc)可以查询或创建vreg
|
// 公开接口,以便后续模块(如RegAlloc)可以查询或创建vreg
|
||||||
unsigned getVReg(Value* val);
|
unsigned getVReg(Value* val);
|
||||||
unsigned getNewVReg() { return vreg_counter++; }
|
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; }
|
||||||
|
|||||||
24
src/include/midend/Pass/Optimize/LargeArrayToGlobal.h
Normal file
24
src/include/midend/Pass/Optimize/LargeArrayToGlobal.h
Normal 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
|
||||||
@@ -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) {}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ add_library(midend_lib STATIC
|
|||||||
Pass/Optimize/SysYIRCFGOpt.cpp
|
Pass/Optimize/SysYIRCFGOpt.cpp
|
||||||
Pass/Optimize/SCCP.cpp
|
Pass/Optimize/SCCP.cpp
|
||||||
Pass/Optimize/BuildCFG.cpp
|
Pass/Optimize/BuildCFG.cpp
|
||||||
|
Pass/Optimize/LargeArrayToGlobal.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# 包含中端模块所需的头文件路径
|
# 包含中端模块所需的头文件路径
|
||||||
|
|||||||
143
src/midend/Pass/Optimize/LargeArrayToGlobal.cpp
Normal file
143
src/midend/Pass/Optimize/LargeArrayToGlobal.cpp
Normal 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
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Reg2Mem.h"
|
#include "Reg2Mem.h"
|
||||||
#include "SCCP.h"
|
#include "SCCP.h"
|
||||||
#include "BuildCFG.h"
|
#include "BuildCFG.h"
|
||||||
|
#include "LargeArrayToGlobal.h"
|
||||||
#include "Pass.h"
|
#include "Pass.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -41,6 +42,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
|
|
||||||
// 注册优化遍
|
// 注册优化遍
|
||||||
registerOptimizationPass<BuildCFG>();
|
registerOptimizationPass<BuildCFG>();
|
||||||
|
registerOptimizationPass<LargeArrayToGlobalPass>();
|
||||||
|
|
||||||
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
||||||
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
registerOptimizationPass<SysYDelNoPreBLockPass>();
|
||||||
@@ -68,6 +70,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
|
|
||||||
this->clearPasses();
|
this->clearPasses();
|
||||||
this->addPass(&BuildCFG::ID);
|
this->addPass(&BuildCFG::ID);
|
||||||
|
this->addPass(&LargeArrayToGlobalPass::ID);
|
||||||
this->run();
|
this->run();
|
||||||
|
|
||||||
this->clearPasses();
|
this->clearPasses();
|
||||||
|
|||||||
@@ -38,6 +38,116 @@ std::pair<long long, int> calculate_signed_magic(int d) {
|
|||||||
return {m, k};
|
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; ///< 用于存储二元表达式的操作符栈
|
||||||
@@ -267,46 +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 = it->second;
|
||||||
ConstantInteger *rhsConst = dynamic_cast<ConstantInteger *>(rhs);
|
} else {
|
||||||
if (rhsConst) {
|
if (commonType == Type::getIntType()) {
|
||||||
int divisor = rhsConst->getInt();
|
switch (op) {
|
||||||
if (divisor > 0 && (divisor & (divisor - 1)) == 0) {
|
case BinaryOp::ADD: resultValue = builder.createAddInst(lhs, rhs); break;
|
||||||
int shift = 0;
|
case BinaryOp::SUB: resultValue = builder.createSubInst(lhs, rhs); break;
|
||||||
int temp = divisor;
|
case BinaryOp::MUL: resultValue = builder.createMulInst(lhs, rhs); break;
|
||||||
while (temp > 1) {
|
case BinaryOp::DIV: {
|
||||||
temp >>= 1;
|
ConstantInteger *rhsConst = dynamic_cast<ConstantInteger *>(rhs);
|
||||||
shift++;
|
if (rhsConst) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
resultValue = builder.createSRAInst(lhs, ConstantInteger::get(shift));
|
|
||||||
} else {
|
} else {
|
||||||
resultValue = builder.createDivInst(lhs, rhs);
|
resultValue = builder.createDivInst(lhs, rhs);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
resultValue = builder.createDivInst(lhs, rhs);
|
|
||||||
}
|
}
|
||||||
break;
|
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
|
||||||
}
|
}
|
||||||
case BinaryOp::MOD: resultValue = builder.createRemInst(lhs, rhs); break;
|
} else if (commonType == Type::getFloatType()) {
|
||||||
}
|
switch (op) {
|
||||||
} else if (commonType == Type::getFloatType()) {
|
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break;
|
||||||
switch (op) {
|
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break;
|
||||||
case BinaryOp::ADD: resultValue = builder.createFAddInst(lhs, rhs); break;
|
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break;
|
||||||
case BinaryOp::SUB: resultValue = builder.createFSubInst(lhs, rhs); break;
|
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break;
|
||||||
case BinaryOp::MUL: resultValue = builder.createFMulInst(lhs, rhs); break;
|
case BinaryOp::MOD:
|
||||||
case BinaryOp::DIV: resultValue = builder.createFDivInst(lhs, rhs); break;
|
std::cerr << "Error: Modulo operator not supported for float types." << std::endl;
|
||||||
case BinaryOp::MOD:
|
return;
|
||||||
std::cerr << "Error: Modulo operator not supported for float types." << std::endl;
|
}
|
||||||
|
} 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;
|
||||||
@@ -358,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;
|
||||||
@@ -529,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -628,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;
|
||||||
@@ -785,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;
|
||||||
@@ -988,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;
|
||||||
@@ -1143,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;
|
||||||
@@ -1205,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1244,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));
|
||||||
// 如果是块语句,直接访问
|
// 如果是块语句,直接访问
|
||||||
// 否则访问语句
|
// 否则访问语句
|
||||||
@@ -1263,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);
|
||||||
@@ -1280,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);
|
||||||
@@ -1293,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);
|
||||||
@@ -1310,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();
|
||||||
}
|
}
|
||||||
@@ -1327,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);
|
||||||
|
|
||||||
@@ -1343,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);
|
||||||
@@ -1367,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1482,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 {
|
||||||
@@ -1545,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1676,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]);
|
||||||
|
|||||||
Reference in New Issue
Block a user