diff --git a/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp b/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp index d343fbf..ae4e556 100644 --- a/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp +++ b/src/backend/RISCv64/Handler/EliminateFrameIndices.cpp @@ -46,9 +46,13 @@ void EliminateFrameIndicesPass::runOnMachineFunction(MachineFunction* mfunc) { Type* allocated_type = alloca->getType()->as()->getBaseType(); int size = getTypeSizeInBytes(allocated_type); - // RISC-V要求栈地址8字节对齐 - size = (size + 7) & ~7; - if (size == 0) size = 8; // 至少分配8字节 + // 优化栈帧大小:对于大数组使用4字节对齐,小对象使用8字节对齐 + if (size >= 256) { // 大数组优化 + size = (size + 3) & ~3; // 4字节对齐 + } else { + size = (size + 7) & ~7; // 8字节对齐 + } + if (size == 0) size = 4; // 最小4字节 local_var_offset += size; unsigned alloca_vreg = isel->getVReg(alloca); diff --git a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp index ab91660..4c17e83 100644 --- a/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp +++ b/src/backend/RISCv64/Handler/PrologueEpilogueInsertion.cpp @@ -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()); frame_info.callee_saved_size = frame_info.callee_saved_regs_to_store.size() * 8; - // 3. 计算最终的栈帧总大小 + // 3. 计算最终的栈帧总大小,包含栈溢出保护 int total_stack_size = frame_info.locals_size + frame_info.spill_size + frame_info.callee_saved_size + 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; diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 24a7fd3..dad1bbb 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -1339,14 +1339,19 @@ void RISCv64ISel::selectNode(DAGNode* node) { if (stride != 0) { // --- 为当前索引和步长生成偏移计算指令 --- auto offset_vreg = getNewVReg(); - auto index_vreg = getVReg(indexValue); - - // 如果索引是常量,先用 LI 指令加载到虚拟寄存器 + + // 处理索引 - 区分常量与动态值 + unsigned index_vreg; if (auto const_index = dynamic_cast(indexValue)) { + // 对于常量索引,直接创建新的虚拟寄存器 + index_vreg = getNewVReg(); auto li = std::make_unique(RVOpcodes::LI); li->addOperand(std::make_unique(index_vreg)); li->addOperand(std::make_unique(const_index->getInt())); CurMBB->addInstruction(std::move(li)); + } else { + // 对于动态索引,使用已存在的虚拟寄存器 + index_vreg = getVReg(indexValue); } // 优化:如果步长是1,可以直接移动(MV)作为偏移量,无需乘法 diff --git a/src/include/midend/Pass/Optimize/LargeArrayToGlobal.h b/src/include/midend/Pass/Optimize/LargeArrayToGlobal.h new file mode 100644 index 0000000..39c5a52 --- /dev/null +++ b/src/include/midend/Pass/Optimize/LargeArrayToGlobal.h @@ -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 \ No newline at end of file diff --git a/src/include/midend/Pass/Pass.h b/src/include/midend/Pass/Pass.h index 887ad3f..1dcaa68 100644 --- a/src/include/midend/Pass/Pass.h +++ b/src/include/midend/Pass/Pass.h @@ -279,7 +279,7 @@ private: IRBuilder *pBuilder; public: - PassManager() = default; + PassManager() = delete; ~PassManager() = default; PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {} diff --git a/src/midend/CMakeLists.txt b/src/midend/CMakeLists.txt index f944a3c..db4d13c 100644 --- a/src/midend/CMakeLists.txt +++ b/src/midend/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(midend_lib STATIC Pass/Optimize/SysYIRCFGOpt.cpp Pass/Optimize/SCCP.cpp Pass/Optimize/BuildCFG.cpp + Pass/Optimize/LargeArrayToGlobal.cpp ) # 包含中端模块所需的头文件路径 diff --git a/src/midend/Pass/Optimize/LargeArrayToGlobal.cpp b/src/midend/Pass/Optimize/LargeArrayToGlobal.cpp new file mode 100644 index 0000000..9f63dce --- /dev/null +++ b/src/midend/Pass/Optimize/LargeArrayToGlobal.cpp @@ -0,0 +1,143 @@ +#include "../../include/midend/Pass/Optimize/LargeArrayToGlobal.h" +#include "../../IR.h" +#include +#include +#include + +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(); + 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> 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(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(); + 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 nameCounter; + std::string key = F->getName() + "." + baseName; + + int counter = nameCounter[key]++; + std::ostringstream oss; + oss << key << "." << counter; + + return oss.str(); +} + +} // namespace sysy \ No newline at end of file diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index 73a4573..48e1046 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -7,6 +7,7 @@ #include "Reg2Mem.h" #include "SCCP.h" #include "BuildCFG.h" +#include "LargeArrayToGlobal.h" #include "Pass.h" #include #include @@ -41,6 +42,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR // 注册优化遍 registerOptimizationPass(); + registerOptimizationPass(); registerOptimizationPass(); registerOptimizationPass(); @@ -68,6 +70,7 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR this->clearPasses(); this->addPass(&BuildCFG::ID); + this->addPass(&LargeArrayToGlobalPass::ID); this->run(); this->clearPasses();