From 15fe69187a9c3389d8d5dcd528f7ef43d257525f Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Tue, 29 Jul 2025 15:30:28 +0800 Subject: [PATCH] =?UTF-8?q?[midend-mem2reg]=E7=9B=AE=E5=89=8Dreg2mem?= =?UTF-8?q?=E4=BB=85=E5=B0=86=E5=87=BD=E6=95=B0=E5=8F=82=E6=95=B0=E5=92=8C?= =?UTF-8?q?phi=E6=8C=87=E4=BB=A4=E5=8F=8A=E5=85=B6=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E8=BF=9B=E8=A1=8Creg2mem=EF=BC=8C=E6=97=A8?= =?UTF-8?q?=E5=9C=A8=E6=B6=88=E9=99=A4phi=E6=8C=87=E4=BB=A4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Reg2Mem.cpp | 67 ++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/Reg2Mem.cpp b/src/Reg2Mem.cpp index 19e2e91..b2034c0 100644 --- a/src/Reg2Mem.cpp +++ b/src/Reg2Mem.cpp @@ -39,13 +39,23 @@ bool Reg2MemContext::isPromotableToMemory(Value *val) { // } // std::cout << "Checking if value is promotable to memory: " << val->getName() << std::endl; } - if (dynamic_cast(val) || dynamic_cast(val)) { - // 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。 - // (除非我们想将其值也存储起来,这通常不用于 Reg2Mem) - // // Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。 - if (val->getType()->isPointer()) { - return false; - } + // if (dynamic_cast(val) || dynamic_cast(val)) { + // // 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。 + // // (除非我们想将其值也存储起来,这通常不用于 Reg2Mem) + // // // Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。 + // if (val->getType()->isPointer()) { + // return false; + // } + // return true; + // } + // 1. 如果是 Argument,则可以提升到内存 + if (dynamic_cast(val)) { + // 参数类型(i32, i32* 等)都可以为其分配内存 + // 因为它们在 Mem2Reg 逆操作中,被认为是从寄存器分配到内存 + return true; + } + if (dynamic_cast(val)) { + // Phi 指令的结果也是一个 SSA 值,需要将其转换为 Load/Store return true; } return false; @@ -62,18 +72,17 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) { builder->setPosition(entryBlock, entryBlock->begin()); // 确保在入口块的开始位置插入 for (auto arg : func->getArguments()) { // 默认情况下,将所有参数是提升到内存 - // if (isPromotableToMemory(arg)) { + if (isPromotableToMemory(arg)) { // 参数的类型就是 AllocaInst 需要分配的类型 AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(arg->getType()), {}, arg->getName() + ".reg2mem"); // 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步) - builder->createStoreInst(arg, alloca); valueToAllocaMap[arg] = alloca; // 确保 alloca 位于入口块的顶部,但在所有参数的 store 指令之前 // 通常 alloca 都在 entry block 的最开始 // 这里我们只是创建,并让 builder 决定插入位置 (通常在当前插入点) // 如果需要严格控制顺序,可能需要手动 insert 到 instruction list - // } + } } // 2. 为指令结果分配内存 @@ -99,25 +108,27 @@ void Reg2MemContext::allocateMemoryForSSAValues(Function *func) { } } } - - // 统一将所有新创建的 AllocaInst 移到入口块的最前面, - // 在参数的 AllocaInst 和 Store 指令之后。 - // 这部分可能需要根据你的 IR 结构来调整。 - // 假设 builder.createAllocaInst 默认在当前 builder position 插入。 - // 如果 builder 只能在当前位置插入,可能需要收集这些 alloca,然后在最后手动移动。 - // 更简单的方式是:在 builder 创建 alloca 时,将 position 设置到 entryBlock 的开头。 - builder->setPosition(entryBlock, entryBlock->begin()); - // 再次循环 valueToAllocaMap,如果 alloca 是新创建的,确保它在正确位置 - // 对于已经创建的 alloca,这里不需要重新创建 - for (auto const &[val, alloca_inst] : valueToAllocaMap) { - // 假设 alloca_inst 还没有被插入或者需要移动到开头 - // 你的 builder 可能需要一个方法来将指令移动到特定位置 - // 如果 builder.createAllocaInst 总是插入到当前位置,那么需要在循环之前设置好 builder 的位置 + Instruction *firstNonAlloca = nullptr; + for (auto instIter = entryBlock->getInstructions().begin(); instIter != entryBlock->getInstructions().end(); instIter++) { + if (!dynamic_cast(instIter->get())) { + firstNonAlloca = instIter->get(); + break; + } } - // 再次设置 builder 位置到入口块的末尾,以便后续插入 Store 等指令 - // 由于消除了fallthrough所有入口块的末尾一定是一个 terminator - // 所以可以安全地将位置设置到末尾的terminator。 - // 这将确保后续的 Store 指令插入到入口块的末尾。 + + if (firstNonAlloca) { + builder->setPosition(entryBlock, entryBlock->findInstIterator(firstNonAlloca)); + } else { // 如果 entryBlock 只有 AllocaInst 或为空,则设置到 terminator 前 + builder->setPosition(entryBlock, entryBlock->terminator()); + } + + // 插入所有参数的初始 Store 指令 + for (auto arg : func->getArguments()) { + if (valueToAllocaMap.count(arg)) { // 检查是否为其分配了 alloca + builder->createStoreInst(arg, valueToAllocaMap[arg]); + } + } + builder->setPosition(entryBlock, entryBlock->terminator()); }