[midend]重构了src目录

This commit is contained in:
Lixuanwang
2025-07-29 21:30:30 +08:00
parent f5922d0178
commit 09ae47924e
84 changed files with 85 additions and 1715 deletions

23
src/midend/CMakeLists.txt Normal file
View File

@@ -0,0 +1,23 @@
# src/midend/CMakeLists.txt
add_library(midend_lib STATIC
IR.cpp
SysYIRGenerator.cpp
SysYIRPrinter.cpp
Pass/Pass.cpp
Pass/Analysis/Dom.cpp
Pass/Analysis/Liveness.cpp
Pass/Optimize/DCE.cpp
Pass/Optimize/Mem2Reg.cpp
Pass/Optimize/Reg2Mem.cpp
Pass/Optimize/SysYIRCFGOpt.cpp
)
# 包含中端模块所需的头文件路径
target_include_directories(midend_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend # 中端顶层头文件
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass # 增加 Pass 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass/Analysis # 增加 Pass/Analysis 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/midend/Pass/Optimize # 增加 Pass/Optimize 头文件路径
${CMAKE_CURRENT_SOURCE_DIR}/../include/frontend # 增加 frontend 头文件路径 (已存在)
${ANTLR_RUNTIME}/runtime/src # ANTLR运行时库头文件
)

742
src/midend/IR.cpp Normal file
View File

@@ -0,0 +1,742 @@
#include "IR.h"
#include <algorithm>
#include <cassert>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#include "IRBuilder.h"
/**
* @file IR.cpp
*
* @brief 定义IR相关类型与操作的源文件
*/
namespace sysy {
//===----------------------------------------------------------------------===//
// Types
//===----------------------------------------------------------------------===//
auto Type::getIntType() -> Type * {
static Type intType(kInt);
return &intType;
}
auto Type::getFloatType() -> Type * {
static Type floatType(kFloat);
return &floatType;
}
auto Type::getVoidType() -> Type * {
static Type voidType(kVoid);
return &voidType;
}
auto Type::getLabelType() -> Type * {
static Type labelType(kLabel);
return &labelType;
}
auto Type::getPointerType(Type *baseType) -> Type * {
// forward to PointerType
return PointerType::get(baseType);
}
auto Type::getFunctionType(Type *returnType, const std::vector<Type *> &paramTypes) -> Type * {
// forward to FunctionType
return FunctionType::get(returnType, paramTypes);
}
auto Type::getArrayType(Type *elementType, unsigned numElements) -> Type * {
// forward to ArrayType
return ArrayType::get(elementType, numElements);
}
auto Type::getSize() const -> unsigned {
switch (kind) {
case kInt:
case kFloat:
return 4;
case kLabel:
case kPointer:
case kFunction:
return 8;
case Kind::kArray: {
const ArrayType* arrType = static_cast<const ArrayType*>(this);
return arrType->getElementType()->getSize() * arrType->getNumElements();
}
case kVoid:
return 0;
}
return 0;
}
PointerType* PointerType::get(Type *baseType) {
static std::map<Type *, std::unique_ptr<PointerType>> pointerTypes;
auto iter = pointerTypes.find(baseType);
if (iter != pointerTypes.end()) {
return iter->second.get();
}
auto type = new PointerType(baseType);
assert(type);
auto result = pointerTypes.emplace(baseType, type);
return result.first->second.get();
}
FunctionType*FunctionType::get(Type *returnType, const std::vector<Type *> &paramTypes) {
static std::set<std::unique_ptr<FunctionType>> functionTypes;
auto iter =
std::find_if(functionTypes.begin(), functionTypes.end(), [&](const std::unique_ptr<FunctionType> &type) -> bool {
if (returnType != type->getReturnType() ||
paramTypes.size() != static_cast<size_t>(type->getParamTypes().size())) {
return false;
}
return std::equal(paramTypes.begin(), paramTypes.end(), type->getParamTypes().begin());
});
if (iter != functionTypes.end()) {
return iter->get();
}
auto type = new FunctionType(returnType, paramTypes);
assert(type);
auto result = functionTypes.emplace(type);
return result.first->get();
}
ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
static std::set<std::unique_ptr<ArrayType>> arrayTypes;
auto iter = std::find_if(arrayTypes.begin(), arrayTypes.end(), [&](const std::unique_ptr<ArrayType> &type) -> bool {
return elementType == type->getElementType() && numElements == type->getNumElements();
});
if (iter != arrayTypes.end()) {
return iter->get();
}
auto type = new ArrayType(elementType, numElements);
assert(type);
auto result = arrayTypes.emplace(type);
return result.first->get();
}
void Value::replaceAllUsesWith(Value *value) {
for (auto &use : uses) {
use->getUser()->setOperand(use->getIndex(), value);
}
uses.clear();
}
// Implementations for static members
std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> ConstantValue::mConstantPool;
std::unordered_map<Type*, UndefinedValue*> UndefinedValue::UndefValues;
ConstantValue* ConstantValue::get(Type* type, ConstantValVariant val) {
ConstantValueKey key = {type, val};
auto it = mConstantPool.find(key);
if (it != mConstantPool.end()) {
return it->second;
}
ConstantValue* newConstant = nullptr;
if (std::holds_alternative<int>(val)) {
newConstant = new ConstantInteger(type, std::get<int>(val));
} else if (std::holds_alternative<float>(val)) {
newConstant = new ConstantFloating(type, std::get<float>(val));
} else {
assert(false && "Unsupported ConstantValVariant type");
}
mConstantPool[key] = newConstant;
return newConstant;
}
ConstantInteger* ConstantInteger::get(Type* type, int val) {
return dynamic_cast<ConstantInteger*>(ConstantValue::get(type, val));
}
ConstantFloating* ConstantFloating::get(Type* type, float val) {
return dynamic_cast<ConstantFloating*>(ConstantValue::get(type, val));
}
UndefinedValue* UndefinedValue::get(Type* type) {
assert(!type->isVoid() && "Cannot get UndefinedValue of void type!");
auto it = UndefValues.find(type);
if (it != UndefValues.end()) {
return it->second;
}
UndefinedValue* newUndef = new UndefinedValue(type);
UndefValues[type] = newUndef;
return newUndef;
}
auto Function::getCalleesWithNoExternalAndSelf() -> std::set<Function *> {
std::set<Function *> result;
for (auto callee : callees) {
if (parent->getExternalFunctions().count(callee->getName()) == 0U && callee != this) {
result.insert(callee);
}
}
return result;
}
// 函数克隆,后续函数级优化(内联等)需要用到
Function * Function::clone(const std::string &suffix) const {
std::stringstream ss;
std::map<BasicBlock *, BasicBlock *> oldNewBlockMap;
IRBuilder builder;
auto newFunction = new Function(parent, type, name);
newFunction->getEntryBlock()->setName(blocks.front()->getName());
oldNewBlockMap.emplace(blocks.front().get(), newFunction->getEntryBlock());
auto oldBlockListIter = std::next(blocks.begin());
while (oldBlockListIter != blocks.end()) {
auto newBlock = newFunction->addBasicBlock(oldBlockListIter->get()->getName());
oldNewBlockMap.emplace(oldBlockListIter->get(), newBlock);
oldBlockListIter++;
}
for (const auto &oldNewBlockItem : oldNewBlockMap) {
auto oldBlock = oldNewBlockItem.first;
auto newBlock = oldNewBlockItem.second;
for (const auto &oldPred : oldBlock->getPredecessors()) {
newBlock->addPredecessor(oldNewBlockMap.at(oldPred));
}
for (const auto &oldSucc : oldBlock->getSuccessors()) {
newBlock->addSuccessor(oldNewBlockMap.at(oldSucc));
}
}
std::map<Value *, Value *> oldNewValueMap;
std::map<Value *, bool> isAddedToCreate;
std::map<Value *, bool> isCreated;
std::queue<Value *> toCreate;
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
isAddedToCreate.emplace(inst.get(), false);
isCreated.emplace(inst.get(), false);
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(value);
if (oldAllocInst != nullptr) {
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
if (inst->getKind() == Instruction::kAlloca) {
if (oldNewValueMap.find(inst.get()) == oldNewValueMap.end()) {
auto oldAllocInst = dynamic_cast<AllocaInst *>(inst.get());
std::vector<Value *> dims;
for (const auto &dim : oldAllocInst->getDims()) {
dims.emplace_back(dim->getValue());
}
ss << oldAllocInst->getName() << suffix;
auto newAllocInst =
new AllocaInst(oldAllocInst->getType(), dims, oldNewBlockMap.at(oldAllocInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldAllocInst, newAllocInst);
if (isAddedToCreate.find(oldAllocInst) == isAddedToCreate.end()) {
isAddedToCreate.emplace(oldAllocInst, true);
} else {
isAddedToCreate.at(oldAllocInst) = true;
}
if (isCreated.find(oldAllocInst) == isCreated.end()) {
isCreated.emplace(oldAllocInst, true);
} else {
isCreated.at(oldAllocInst) = true;
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
for (const auto &valueUse : inst->getOperands()) {
auto value = valueUse->getValue();
if (oldNewValueMap.find(value) == oldNewValueMap.end()) {
auto globalValue = dynamic_cast<GlobalValue *>(value);
auto constVariable = dynamic_cast<ConstantVariable *>(value);
auto constantValue = dynamic_cast<ConstantValue *>(value);
auto functionValue = dynamic_cast<Function *>(value);
if (globalValue != nullptr || constantValue != nullptr || constVariable != nullptr ||
functionValue != nullptr) {
if (functionValue == this) {
oldNewValueMap.emplace(value, newFunction);
} else {
oldNewValueMap.emplace(value, value);
}
isCreated.emplace(value, true);
isAddedToCreate.emplace(value, true);
}
}
}
}
}
for (const auto &oldBlock : blocks) {
for (const auto &inst : oldBlock->getInstructions()) {
if (inst->getKind() != Instruction::kAlloca) {
bool isReady = true;
for (const auto &use : inst->getOperands()) {
auto value = use->getValue();
if (dynamic_cast<BasicBlock *>(value) == nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (isReady) {
toCreate.push(inst.get());
isAddedToCreate.at(inst.get()) = true;
}
}
}
}
while (!toCreate.empty()) {
auto inst = dynamic_cast<Instruction *>(toCreate.front());
toCreate.pop();
bool isReady = true;
for (const auto &valueUse : inst->getOperands()) {
auto value = dynamic_cast<Instruction *>(valueUse->getValue());
if (value != nullptr && !isCreated.at(value)) {
isReady = false;
break;
}
}
if (!isReady) {
toCreate.push(inst);
continue;
}
isCreated.at(inst) = true;
switch (inst->getKind()) {
case Instruction::kAdd:
case Instruction::kSub:
case Instruction::kMul:
case Instruction::kDiv:
case Instruction::kRem:
case Instruction::kICmpEQ:
case Instruction::kICmpNE:
case Instruction::kICmpLT:
case Instruction::kICmpGT:
case Instruction::kICmpLE:
case Instruction::kICmpGE:
case Instruction::kAnd:
case Instruction::kOr:
case Instruction::kFAdd:
case Instruction::kFSub:
case Instruction::kFMul:
case Instruction::kFDiv:
case Instruction::kFCmpEQ:
case Instruction::kFCmpNE:
case Instruction::kFCmpLT:
case Instruction::kFCmpGT:
case Instruction::kFCmpLE:
case Instruction::kFCmpGE: {
auto oldBinaryInst = dynamic_cast<BinaryInst *>(inst);
auto lhs = oldBinaryInst->getLhs();
auto rhs = oldBinaryInst->getRhs();
Value *newLhs;
Value *newRhs;
newLhs = oldNewValueMap[lhs];
newRhs = oldNewValueMap[rhs];
ss << oldBinaryInst->getName() << suffix;
auto newBinaryInst = new BinaryInst(oldBinaryInst->getKind(), oldBinaryInst->getType(), newLhs, newRhs,
oldNewBlockMap.at(oldBinaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldBinaryInst, newBinaryInst);
break;
}
case Instruction::kNeg:
case Instruction::kNot:
case Instruction::kFNeg:
case Instruction::kFNot:
case Instruction::kItoF:
case Instruction::kFtoI: {
auto oldUnaryInst = dynamic_cast<UnaryInst *>(inst);
auto hs = oldUnaryInst->getOperand();
Value *newHs;
newHs = oldNewValueMap.at(hs);
ss << oldUnaryInst->getName() << suffix;
auto newUnaryInst = new UnaryInst(oldUnaryInst->getKind(), oldUnaryInst->getType(), newHs,
oldNewBlockMap.at(oldUnaryInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldUnaryInst, newUnaryInst);
break;
}
case Instruction::kCall: {
auto oldCallInst = dynamic_cast<CallInst *>(inst);
std::vector<Value *> newArgumnts;
for (const auto &arg : oldCallInst->getArguments()) {
newArgumnts.emplace_back(oldNewValueMap.at(arg->getValue()));
}
ss << oldCallInst->getName() << suffix;
CallInst *newCallInst;
newCallInst =
new CallInst(oldCallInst->getCallee(), newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()), ss.str());
ss.str("");
// if (oldCallInst->getCallee() != this) {
// newCallInst = new CallInst(oldCallInst->getCallee(), newArgumnts,
// oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// } else {
// newCallInst = new CallInst(newFunction, newArgumnts, oldNewBlockMap.at(oldCallInst->getParent()),
// oldCallInst->getName());
// }
oldNewValueMap.emplace(oldCallInst, newCallInst);
break;
}
case Instruction::kCondBr: {
auto oldCondBrInst = dynamic_cast<CondBrInst *>(inst);
auto oldCond = oldCondBrInst->getCondition();
Value *newCond;
newCond = oldNewValueMap.at(oldCond);
auto newCondBrInst = new CondBrInst(newCond, oldNewBlockMap.at(oldCondBrInst->getThenBlock()),
oldNewBlockMap.at(oldCondBrInst->getElseBlock()), {}, {},
oldNewBlockMap.at(oldCondBrInst->getParent()));
oldNewValueMap.emplace(oldCondBrInst, newCondBrInst);
break;
}
case Instruction::kBr: {
auto oldBrInst = dynamic_cast<UncondBrInst *>(inst);
auto newBrInst =
new UncondBrInst(oldNewBlockMap.at(oldBrInst->getBlock()), {}, oldNewBlockMap.at(oldBrInst->getParent()));
oldNewValueMap.emplace(oldBrInst, newBrInst);
break;
}
case Instruction::kReturn: {
auto oldReturnInst = dynamic_cast<ReturnInst *>(inst);
auto oldRval = oldReturnInst->getReturnValue();
Value *newRval = nullptr;
if (oldRval != nullptr) {
newRval = oldNewValueMap.at(oldRval);
}
auto newReturnInst =
new ReturnInst(newRval, oldNewBlockMap.at(oldReturnInst->getParent()), oldReturnInst->getName());
oldNewValueMap.emplace(oldReturnInst, newReturnInst);
break;
}
case Instruction::kAlloca: {
assert(false);
}
case Instruction::kLoad: {
auto oldLoadInst = dynamic_cast<LoadInst *>(inst);
auto oldPointer = oldLoadInst->getPointer();
Value *newPointer;
newPointer = oldNewValueMap.at(oldPointer);
std::vector<Value *> newIndices;
for (const auto &index : oldLoadInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
ss << oldLoadInst->getName() << suffix;
auto newLoadInst = new LoadInst(newPointer, newIndices, oldNewBlockMap.at(oldLoadInst->getParent()), ss.str());
ss.str("");
oldNewValueMap.emplace(oldLoadInst, newLoadInst);
break;
}
case Instruction::kStore: {
auto oldStoreInst = dynamic_cast<StoreInst *>(inst);
auto oldPointer = oldStoreInst->getPointer();
auto oldValue = oldStoreInst->getValue();
Value *newPointer;
Value *newValue;
std::vector<Value *> newIndices;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
for (const auto &index : oldStoreInst->getIndices()) {
newIndices.emplace_back(oldNewValueMap.at(index->getValue()));
}
auto newStoreInst = new StoreInst(newValue, newPointer, newIndices,
oldNewBlockMap.at(oldStoreInst->getParent()), oldStoreInst->getName());
oldNewValueMap.emplace(oldStoreInst, newStoreInst);
break;
}
// TODO复制GEP指令
case Instruction::kMemset: {
auto oldMemsetInst = dynamic_cast<MemsetInst *>(inst);
auto oldPointer = oldMemsetInst->getPointer();
auto oldValue = oldMemsetInst->getValue();
Value *newPointer;
Value *newValue;
newPointer = oldNewValueMap.at(oldPointer);
newValue = oldNewValueMap.at(oldValue);
auto newMemsetInst = new MemsetInst(newPointer, oldMemsetInst->getBegin(), oldMemsetInst->getSize(), newValue,
oldNewBlockMap.at(oldMemsetInst->getParent()), oldMemsetInst->getName());
oldNewValueMap.emplace(oldMemsetInst, newMemsetInst);
break;
}
case Instruction::kInvalid:
case Instruction::kPhi: {
break;
}
default:
assert(false);
}
for (const auto &userUse : inst->getUses()) {
auto user = userUse->getUser();
if (!isAddedToCreate.at(user)) {
toCreate.push(user);
isAddedToCreate.at(user) = true;
}
}
}
for (const auto &oldBlock : blocks) {
auto newBlock = oldNewBlockMap.at(oldBlock.get());
builder.setPosition(newBlock, newBlock->end());
for (const auto &inst : oldBlock->getInstructions()) {
builder.insertInst(dynamic_cast<Instruction *>(oldNewValueMap.at(inst.get())));
}
}
// for (const auto &param : blocks.front()->getArguments()) {
// newFunction->getEntryBlock()->insertArgument(dynamic_cast<AllocaInst *>(oldNewValueMap.at(param)));
// }
for (const auto &arg : arguments) {
auto newArg = dynamic_cast<Argument *>(oldNewValueMap.at(arg));
if (newArg != nullptr) {
newFunction->insertArgument(newArg);
}
}
return newFunction;
}
/**
* 设置操作数
*/
void User::setOperand(unsigned index, Value *value) {
assert(index < getNumOperands());
operands[index]->setValue(value);
value->addUse(operands[index]);
}
/**
* 替换操作数
*/
void User::replaceOperand(unsigned index, Value *value) {
assert(index < getNumOperands());
auto &use = operands[index];
use->getValue()->removeUse(use);
use->setValue(value);
value->addUse(use);
}
/**
* phi相关函数
*/
Value* PhiInst::getvalfromBlk(BasicBlock* blk){
refreshB2VMap();
if( blk2val.find(blk) != blk2val.end()) {
return blk2val.at(blk);
}
return nullptr;
}
BasicBlock* PhiInst::getBlkfromVal(Value* val){
// 返回第一个值对应的基本块
for(unsigned i = 0; i < vsize; i++) {
if(getValue(i) == val) {
return getBlock(i);
}
}
return nullptr;
}
void PhiInst::delValue(Value* val){
//根据value删除对应的基本块和值
unsigned i = 0;
BasicBlock* blk = getBlkfromVal(val);
for(i = 0; i < vsize; i++) {
if(getValue(i) == val) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::delBlk(BasicBlock* blk){
//根据Blk删除对应的基本块和值
unsigned i = 0;
Value* val = getvalfromBlk(blk);
for(i = 0; i < vsize; i++) {
if(getBlock(i) == blk) {
break;
}
}
removeOperand(2 * i + 1); // 删除blk
removeOperand(2 * i); // 删除val
vsize--;
blk2val.erase(blk); // 删除blk2val映射
}
void PhiInst::replaceBlk(BasicBlock* newBlk, unsigned k){
refreshB2VMap();
Value* val = blk2val.at(getBlock(k));
// 替换基本块
setOperand(2 * k + 1, newBlk);
// 替换blk2val映射
blk2val.erase(getBlock(k));
blk2val.emplace(newBlk, val);
}
void PhiInst::replaceold2new(BasicBlock* oldBlk, BasicBlock* newBlk){
refreshB2VMap();
Value* val = blk2val.at(oldBlk);
// 替换基本块
delBlk(oldBlk);
addIncoming(val, newBlk);
}
void PhiInst::refreshB2VMap(){
blk2val.clear();
for(unsigned i = 0; i < vsize; i++) {
blk2val.emplace(getBlock(i), getValue(i));
}
}
CallInst::CallInst(Function *callee, const std::vector<Value *> &args, BasicBlock *parent, const std::string &name)
: Instruction(kCall, callee->getReturnType(), parent, name) {
addOperand(callee);
for (auto arg : args) {
addOperand(arg);
}
}
/**
* 获取被调用函数的指针
*/
Function * CallInst::getCallee() const { return dynamic_cast<Function *>(getOperand(0)); }
/**
* 获取变量指针
*/
auto SymbolTable::getVariable(const std::string &name) const -> Value * {
auto node = curNode;
while (node != nullptr) {
auto iter = node->varList.find(name);
if (iter != node->varList.end()) {
return iter->second;
}
node = node->pNode;
}
return nullptr;
}
/**
* 添加变量到符号表
*/
auto SymbolTable::addVariable(const std::string &name, Value *variable) -> Value * {
Value *result = nullptr;
if (curNode != nullptr) {
std::stringstream ss;
auto iter = variableIndex.find(name);
if (iter != variableIndex.end()) {
ss << name << iter->second ;
iter->second += 1;
} else {
variableIndex.emplace(name, 1);
ss << name << 0 ;
}
variable->setName(ss.str());
curNode->varList.emplace(name, variable);
auto global = dynamic_cast<GlobalValue *>(variable);
auto constvar = dynamic_cast<ConstantVariable *>(variable);
if (global != nullptr) {
globals.emplace_back(global);
} else if (constvar != nullptr) {
consts.emplace_back(constvar);
}
result = variable;
}
return result;
}
/**
* 获取全局变量
*/
auto SymbolTable::getGlobals() -> std::vector<std::unique_ptr<GlobalValue>> & { return globals; }
/**
* 获取常量
*/
auto SymbolTable::getConsts() const -> const std::vector<std::unique_ptr<ConstantVariable>> & { return consts; }
/**
* 进入新的作用域
*/
void SymbolTable::enterNewScope() {
auto newNode = new SymbolTableNode;
nodeList.emplace_back(newNode);
if (curNode != nullptr) {
curNode->children.emplace_back(newNode);
}
newNode->pNode = curNode;
curNode = newNode;
}
/**
* 进入全局作用域
*/
void SymbolTable::enterGlobalScope() { curNode = nodeList.front().get(); }
/**
* 离开作用域
*/
void SymbolTable::leaveScope() { curNode = curNode->pNode; }
/**
* 是否位于全局作用域
*/
auto SymbolTable::isInGlobalScope() const -> bool { return curNode->pNode == nullptr; }
/**
*移动指令
*/
auto BasicBlock::moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block) -> iterator {
auto inst = sourcePos->release();
inst->setParent(block);
block->instructions.emplace(targetPos, inst);
return instructions.erase(sourcePos);
}
} // namespace sysy

View File

@@ -0,0 +1,202 @@
#include "Dom.h"
#include <limits> // for std::numeric_limits
#include <queue>
namespace sysy {
// 初始化 支配树静态 ID
void *DominatorTreeAnalysisPass::ID = (void *)&DominatorTreeAnalysisPass::ID;
// ==============================================================
// DominatorTree 结果类的实现
// ==============================================================
DominatorTree::DominatorTree(Function *F) : AssociatedFunction(F) {
// 构造时可以不计算,在分析遍运行里计算并填充
}
const std::set<BasicBlock *> *DominatorTree::getDominators(BasicBlock *BB) const {
auto it = Dominators.find(BB);
if (it != Dominators.end()) {
return &(it->second);
}
return nullptr;
}
BasicBlock *DominatorTree::getImmediateDominator(BasicBlock *BB) const {
auto it = IDoms.find(BB);
if (it != IDoms.end()) {
return it->second;
}
return nullptr;
}
const std::set<BasicBlock *> *DominatorTree::getDominanceFrontier(BasicBlock *BB) const {
auto it = DominanceFrontiers.find(BB);
if (it != DominanceFrontiers.end()) {
return &(it->second);
}
return nullptr;
}
const std::set<BasicBlock*>* DominatorTree::getDominatorTreeChildren(BasicBlock* BB) const {
auto it = DominatorTreeChildren.find(BB);
if (it != DominatorTreeChildren.end()) {
return &(it->second);
}
return nullptr;
}
void DominatorTree::computeDominators(Function *F) {
// 经典的迭代算法计算支配者集合
// TODO: 可以替换为更高效的算法,如 Lengauer-Tarjan 算法
BasicBlock *entryBlock = F->getEntryBlock();
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock) {
Dominators[bb].insert(bb);
} else {
for (const auto &all_bb_ptr : F->getBasicBlocks()) {
Dominators[bb].insert(all_bb_ptr.get());
}
}
}
bool changed = true;
while (changed) {
changed = false;
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
std::set<BasicBlock *> newDom;
bool firstPred = true;
for (BasicBlock *pred : bb->getPredecessors()) {
if (Dominators.count(pred)) {
if (firstPred) {
newDom = Dominators[pred];
firstPred = false;
} else {
std::set<BasicBlock *> intersection;
std::set_intersection(newDom.begin(), newDom.end(), Dominators[pred].begin(), Dominators[pred].end(),
std::inserter(intersection, intersection.begin()));
newDom = intersection;
}
}
}
newDom.insert(bb);
if (newDom != Dominators[bb]) {
Dominators[bb] = newDom;
changed = true;
}
}
}
}
void DominatorTree::computeIDoms(Function *F) {
// 采用与之前类似的简化实现。TODO:Lengauer-Tarjan等算法。
BasicBlock *entryBlock = F->getEntryBlock();
IDoms[entryBlock] = nullptr;
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
if (bb == entryBlock)
continue;
BasicBlock *currentIDom = nullptr;
const std::set<BasicBlock *> *domsOfBB = getDominators(bb);
if (!domsOfBB)
continue;
for (BasicBlock *D : *domsOfBB) {
if (D == bb)
continue;
bool isCandidateIDom = true;
for (BasicBlock *candidate : *domsOfBB) {
if (candidate == bb || candidate == D)
continue;
const std::set<BasicBlock *> *domsOfCandidate = getDominators(candidate);
if (domsOfCandidate && domsOfCandidate->count(D) == 0 && domsOfBB->count(candidate)) {
isCandidateIDom = false;
break;
}
}
if (isCandidateIDom) {
currentIDom = D;
break;
}
}
IDoms[bb] = currentIDom;
}
}
void DominatorTree::computeDominanceFrontiers(Function *F) {
// 经典的支配边界计算算法
for (const auto &bb_ptr_X : F->getBasicBlocks()) {
BasicBlock *X = bb_ptr_X.get();
DominanceFrontiers[X].clear();
for (BasicBlock *Y : X->getSuccessors()) {
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
DominanceFrontiers[X].insert(Y);
}
}
const std::set<BasicBlock *> *domsOfX = getDominators(X);
if (!domsOfX)
continue;
for (const auto &bb_ptr_Z : F->getBasicBlocks()) {
BasicBlock *Z = bb_ptr_Z.get();
if (Z == X)
continue;
const std::set<BasicBlock *> *domsOfZ = getDominators(Z);
if (domsOfZ && domsOfZ->count(X) && Z != X) {
for (BasicBlock *Y : Z->getSuccessors()) {
const std::set<BasicBlock *> *domsOfY = getDominators(Y);
if (domsOfY && domsOfY->find(X) == domsOfY->end()) {
DominanceFrontiers[X].insert(Y);
}
}
}
}
}
}
void DominatorTree::computeDominatorTreeChildren(Function *F) {
for (auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *B = bb_ptr.get();
auto it = getImmediateDominator(B);
if (it != nullptr) {
BasicBlock *A = it;
if (A) {
DominatorTreeChildren[A].insert(B);
}
}
}
}
// ==============================================================
// DominatorTreeAnalysisPass 的实现
// ==============================================================
bool DominatorTreeAnalysisPass::runOnFunction(Function* F, AnalysisManager &AM) {
CurrentDominatorTree = std::make_unique<DominatorTree>(F);
CurrentDominatorTree->computeDominators(F);
CurrentDominatorTree->computeIDoms(F);
CurrentDominatorTree->computeDominanceFrontiers(F);
CurrentDominatorTree->computeDominatorTreeChildren(F);
return false;
}
std::unique_ptr<AnalysisResultBase> DominatorTreeAnalysisPass::getResult() {
// 返回计算好的 DominatorTree 实例,所有权转移给 AnalysisManager
return std::move(CurrentDominatorTree);
}
} // namespace sysy

View File

@@ -0,0 +1,160 @@
#include "Liveness.h"
#include <algorithm> // For std::set_union, std::set_difference
#include <iostream>
#include <queue> // Potentially for worklist, though not strictly needed for the iterative approach below
#include <set> // For std::set
namespace sysy {
// 初始化静态 ID
void *LivenessAnalysisPass::ID = (void *)&LivenessAnalysisPass::ID;
// ==============================================================
// LivenessAnalysisResult 结果类的实现
// ==============================================================
const std::set<Value *> *LivenessAnalysisResult::getLiveIn(BasicBlock *BB) const {
auto it = liveInSets.find(BB);
if (it != liveInSets.end()) {
return &(it->second);
}
// 返回一个空集合,表示未找到或不存在
static const std::set<Value *> emptySet;
return &emptySet;
}
const std::set<Value *> *LivenessAnalysisResult::getLiveOut(BasicBlock *BB) const {
auto it = liveOutSets.find(BB);
if (it != liveOutSets.end()) {
return &(it->second);
}
static const std::set<Value *> emptySet;
return &emptySet;
}
void LivenessAnalysisResult::computeDefUse(BasicBlock *BB, std::set<Value *> &def, std::set<Value *> &use) {
def.clear(); // 将持有在 BB 中定义的值
use.clear(); // 将持有在 BB 中使用但在其定义之前的值
// 临时集合,用于跟踪当前基本块中已经定义过的变量
std::set<Value *> defined_in_block_so_far;
// 按照指令在块中的顺序遍历
for (const auto &inst_ptr : BB->getInstructions()) {
Instruction *inst = inst_ptr.get();
// 1. 处理指令的操作数 (Use) - 在定义之前的使用
for (const auto &use_ptr : inst->getOperands()) { // 修正迭代器类型
Value *operand = use_ptr->getValue(); // 从 shared_ptr<Use> 获取 Value*
// 过滤掉常量和全局变量,因为它们通常不被视为活跃变量
ConstantValue *constValue = dynamic_cast<ConstantValue *>(operand);
GlobalValue *globalValue = dynamic_cast<GlobalValue *>(operand);
if (constValue || globalValue) {
continue; // 跳过常量和全局变量
}
// 如果操作数是一个变量Instruction 或 Argument并且它在此基本块的当前点之前尚未被定义
if (defined_in_block_so_far.find(operand) == defined_in_block_so_far.end()) {
use.insert(operand);
}
}
// 2. 处理指令自身产生的定义 (Def)
if (inst->isDefine()) { // 使用 isDefine() 方法
// 指令自身定义了一个值。将其添加到块的 def 集合,
// 并添加到当前块中已定义的值的临时集合。
def.insert(inst); // inst 本身就是被定义的值(例如,虚拟寄存器)
defined_in_block_so_far.insert(inst);
}
}
}
void LivenessAnalysisResult::computeLiveness(Function *F) {
// 每次计算前清空旧结果
liveInSets.clear(); // 直接清空 map不再使用 F 作为键
liveOutSets.clear(); // 直接清空 map
// 初始化所有基本块的 LiveIn 和 LiveOut 集合为空
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
liveInSets[bb] = {}; // 直接以 bb 为键
liveOutSets[bb] = {}; // 直接以 bb 为键
}
bool changed = true;
while (changed) {
changed = false;
// TODO : 目前为逆序遍历基本块,考虑反向拓扑序遍历基本块
// 逆序遍历基本块
// std::list<std::unique_ptr<BasicBlock>> basicBlocks(F->getBasicBlocks().begin(), F->getBasicBlocks().end());
// std::reverse(basicBlocks.begin(), basicBlocks.end());
// 然后遍历 basicBlocks
// 创建一个 BasicBlock* 的列表来存储指针,避免拷贝 unique_ptr
// Option 1: Using std::vector<BasicBlock*> (preferred for performance with reverse)
std::vector<BasicBlock*> basicBlocksPointers;
for (const auto& bb_ptr : F->getBasicBlocks()) {
basicBlocksPointers.push_back(bb_ptr.get());
}
std::reverse(basicBlocksPointers.begin(), basicBlocksPointers.end());
for (auto bb_iter = basicBlocksPointers.begin(); bb_iter != basicBlocksPointers.end(); ++bb_iter) {
BasicBlock *bb = *bb_iter; // 获取 BasicBlock 指针
if (!bb)
continue; // 避免空指针
std::set<Value *> oldLiveIn = liveInSets[bb];
std::set<Value *> oldLiveOut = liveOutSets[bb];
// 1. 计算 LiveOut(BB) = Union(LiveIn(Succ) for Succ in Successors(BB))
std::set<Value *> newLiveOut;
for (BasicBlock *succ : bb->getSuccessors()) {
const std::set<Value *> *succLiveIn = getLiveIn(succ); // 获取后继的 LiveIn
if (succLiveIn) {
newLiveOut.insert(succLiveIn->begin(), succLiveIn->end());
}
}
liveOutSets[bb] = newLiveOut;
// 2. 计算 LiveIn(BB) = Use(BB) Union (LiveOut(BB) - Def(BB))
std::set<Value *> defSet, useSet;
computeDefUse(bb, defSet, useSet); // 计算当前块的 Def 和 Use
std::set<Value *> liveOutMinusDef;
std::set_difference(newLiveOut.begin(), newLiveOut.end(), defSet.begin(), defSet.end(),
std::inserter(liveOutMinusDef, liveOutMinusDef.begin()));
std::set<Value *> newLiveIn = useSet;
newLiveIn.insert(liveOutMinusDef.begin(), liveOutMinusDef.end());
liveInSets[bb] = newLiveIn;
// 检查是否发生变化
if (oldLiveIn != newLiveIn || oldLiveOut != newLiveOut) {
changed = true;
}
}
}
}
// ==============================================================
// LivenessAnalysisPass 的实现
// ==============================================================
bool LivenessAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 每次运行创建一个新的 LivenessAnalysisResult 对象来存储结果
CurrentLivenessResult = std::make_unique<LivenessAnalysisResult>(F);
// 调用 LivenessAnalysisResult 内部的方法来计算分析结果
CurrentLivenessResult->computeLiveness(F);
// 分析遍通常不修改 IR所以返回 false
return false;
}
std::unique_ptr<AnalysisResultBase> LivenessAnalysisPass::getResult() {
// 返回计算好的 LivenessAnalysisResult 实例,所有权转移给 AnalysisManager
return std::move(CurrentLivenessResult);
}
} // namespace sysy

View File

@@ -0,0 +1,140 @@
#include "DCE.h" // 包含DCE遍的头文件
#include "IR.h" // 包含IR相关的定义
#include "SysYIROptUtils.h" // 包含SysY IR优化工具类的定义
#include <cassert> // 用于断言
#include <iostream> // 用于调试输出
#include <set> // 包含set虽然DCEContext内部用unordered_set但这里保留
namespace sysy {
// DCE 遍的静态 ID
void *DCE::ID = (void *)&DCE::ID;
// ======================================================================
// DCEContext 类的实现
// 封装了 DCE 遍的核心逻辑和状态,确保每次函数优化运行时状态独立
// ======================================================================
// DCEContext 的 run 方法实现
void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
// 清空活跃指令集合,确保每次运行都是新的状态
alive_insts.clear();
// 第一次遍历:扫描所有指令,识别“天然活跃”的指令并将其及其依赖标记为活跃
// 使用 func->getBasicBlocks() 获取基本块列表,保留用户风格
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
// 确保基本块有效
if (!basicBlock)
continue;
// 使用 basicBlock->getInstructions() 获取指令列表,保留用户风格
for (auto &inst : basicBlock->getInstructions()) {
// 确保指令有效
if (!inst)
continue;
// 调用 DCEContext 自身的 isAlive 和 addAlive 方法
if (isAlive(inst.get())) {
addAlive(inst.get());
}
}
}
// 第二次遍历:删除所有未被标记为活跃的指令。
for (auto &basicBlock : basicBlocks) {
if (!basicBlock)
continue;
// 使用传统的迭代器循环,并手动管理迭代器,
// 以便在删除元素后正确前进。保留用户风格
for (auto instIter = basicBlock->getInstructions().begin(); instIter != basicBlock->getInstructions().end();) {
auto &inst = *instIter;
Instruction *currentInst = inst.get();
// 如果指令不在活跃集合中,则删除它。
// 分支和返回指令由 isAlive 处理,并会被保留。
if (alive_insts.count(currentInst) == 0) {
// 删除指令,保留用户风格的 SysYIROptUtils::usedelete 和 erase
changed = true; // 标记 IR 已被修改
SysYIROptUtils::usedelete(currentInst);
instIter = basicBlock->getInstructions().erase(instIter); // 删除后返回下一个迭代器
} else {
++instIter; // 指令活跃,移动到下一个
}
}
}
}
// 判断指令是否是“天然活跃”的实现
// 只有具有副作用的指令(如存储、函数调用、原子操作)
// 和控制流指令(如分支、返回)是天然活跃的。
bool DCEContext::isAlive(Instruction *inst) {
// TODO: 后续程序并发考虑原子操作
// 其结果不被其他指令使用的指令(例如 StoreInst, BranchInst, ReturnInst
// dynamic_cast<ir::CallInst>(inst) 检查是否是函数调用指令,
// 函数调用通常有副作用。
// 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程。
// 保留用户提供的 isAlive 逻辑
bool isBranchOrReturn = inst->isBranch() || inst->isReturn();
bool isCall = inst->isCall();
bool isStoreOrMemset = inst->isStore() || inst->isMemset();
return isBranchOrReturn || isCall || isStoreOrMemset;
}
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
void DCEContext::addAlive(Instruction *inst) {
// 如果指令已经存在于活跃集合中,则无需重复处理
if (alive_insts.count(inst) > 0) {
return;
}
// 将当前指令标记为活跃
alive_insts.insert(inst);
// 遍历当前指令的所有操作数
// 保留用户提供的 getOperands() 和 getValue()
for (auto operand : inst->getOperands()) {
// 如果操作数是一个指令(即它是一个值的定义),
// 并且它还没有被标记为活跃
if (auto opInst = dynamic_cast<Instruction *>(operand->getValue())) {
addAlive(opInst); // 递归地将操作数指令标记为活跃
}
}
}
// ======================================================================
// DCE Pass 类的实现
// 主要负责与 PassManager 交互,创建 DCEContext 实例并运行优化
// ======================================================================
// DCE 遍的 runOnFunction 方法实现
bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {
DCEContext ctx;
bool changed = false;
ctx.run(func, &AM, changed); // 运行 DCE 优化
// 如果 IR 被修改,则使相关的分析结果失效
if (changed) {
// DCE 会删除指令,这会影响数据流分析,尤其是活跃性分析。
// 如果删除导致基本块变空,也可能间接影响 CFG 和支配树。
// AM.invalidateAnalysis(&LivenessAnalysisPass::ID, func); // 活跃性分析失效
// AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, func); // 支配树分析可能失效
// 其他所有依赖于数据流或 IR 结构的分析都可能失效。
}
return changed;
}
// 声明DCE遍的分析依赖和失效信息
void DCE::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// DCE不依赖特定的分析结果它通过遍历和副作用判断来工作。
// DCE会删除指令这会影响许多分析结果。
// 至少,它会影响活跃性分析、支配树、控制流图(如果删除导致基本块为空并被合并)。
// 假设存在LivenessAnalysisPass和DominatorTreeAnalysisPass
// analysisInvalidations.insert(&LivenessAnalysisPass::ID);
// analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
// 任何改变IR结构的优化都可能导致通用分析如活跃性、支配树、循环信息失效。
// 最保守的做法是使所有函数粒度的分析失效,或者只声明你明确知道会受影响的分析。
// 考虑到这个DCE仅删除指令如果它不删除基本块CFG可能不变但数据流分析会失效。
// 对于更激进的DCE如ADCECFG也会改变。
// 这里我们假设它主要影响数据流分析并且可能间接影响CFG相关分析。
// 如果有SideEffectInfo它也可能被修改但通常SideEffectInfo是静态的不因DCE而变。
}
} // namespace sysy

View File

@@ -0,0 +1,388 @@
#include "Mem2Reg.h" // 包含 Mem2Reg 遍的头文件
#include "Dom.h" // 包含支配树分析的头文件
#include "Liveness.h"
#include "IR.h" // 包含 IR 相关的定义
#include "SysYIROptUtils.h"
#include <cassert> // 用于断言
#include <iostream> // 用于调试输出
namespace sysy {
void *Mem2Reg::ID = (void *)&Mem2Reg::ID;
void Mem2RegContext::run(Function *func, AnalysisManager *AM) {
if (func->getBasicBlocks().empty()) {
return;
}
// 清空所有状态,确保每次运行都是新的状态
promotableAllocas.clear();
allocaToPhiMap.clear();
allocaToValueStackMap.clear();
allocaToStoresMap.clear();
allocaToDefBlocksMap.clear();
// 获取支配树分析结果
dt = AM->getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(func);
assert(dt && "DominatorTreeAnalysisResult not available for Mem2Reg!");
// --------------------------------------------------------------------
// 阶段1: 识别可提升的 AllocaInst 并收集其 Store 指令
// --------------------------------------------------------------------
// 遍历函数入口块?中的所有指令,寻找 AllocaInst
// 必须是要入口块的吗
for (auto &inst : func->getEntryBlock()->getInstructions_Range()) {
Value *allocainst = inst.get();
if (auto alloca = dynamic_cast<AllocaInst *>(allocainst)) {
if (isPromotableAlloca(alloca)) {
promotableAllocas.push_back(alloca);
collectStores(alloca); // 收集所有对该 alloca 的 store
}
}
}
// --------------------------------------------------------------------
// 阶段2: 插入 Phi 指令
// --------------------------------------------------------------------
for (auto alloca : promotableAllocas) {
// 为每个可提升的 alloca 插入 Phi 指令
insertPhis(alloca, allocaToDefBlocksMap[alloca]);
}
// --------------------------------------------------------------------
// 阶段3: 变量重命名
// --------------------------------------------------------------------
// 为每个可提升的 alloca 初始化其值栈
for (auto alloca : promotableAllocas) {
// 初始值通常是 undef 或 null取决于 IR 类型系统
UndefinedValue *undefValue = UndefinedValue::get(alloca->getType()->as<PointerType>()->getBaseType());
allocaToValueStackMap[alloca].push(undefValue); // 压入一个初始的“未定义”值
}
// 从入口基本块开始,对支配树进行 DFS 遍历,进行变量重命名
renameVariables(nullptr, func->getEntryBlock()); // 第一个参数 alloca 在这里不使用,因为是递归入口点
// --------------------------------------------------------------------
// 阶段4: 清理
// --------------------------------------------------------------------
cleanup();
}
// 判断一个 AllocaInst 是否可以被提升到寄存器
bool Mem2RegContext::isPromotableAlloca(AllocaInst *alloca) {
// 1. 必须是标量类型非数组、非结构体sysy不支持结构体
if (alloca->getType()->as<PointerType>()->getBaseType()->isArray()) {
return false;
}
// 2. 其所有用途都必须是 LoadInst 或 StoreInst
// (或 GetElementPtrInst但 GEP 的结果也必须只被 Load/Store 使用)
for (auto use : alloca->getUses()) {
auto user = use->getUser();
if (!user)
return false; // 用户无效
if (dynamic_cast<LoadInst *>(user)) {
// OK
} else if (dynamic_cast<StoreInst *>(user)) {
// OK
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(user)) {
// 如果是 GetElementPtrInst (GEP)
// 需要判断这个 GEP 是否代表了数组元素的访问,而非简单的指针操作
// LLVM 的 mem2reg 通常不提升用于数组元素访问的 alloca。
// 启发式判断:
// 如果 GEP 有多个索引(例如 `getelementptr i32, i32* %ptr, i32 0, i32 %idx`
// 或者第一个索引(对于指针类型)不是常量 0则很可能是数组访问。
// 对于 `alloca i32* %a.param` (对应 `int a[]` 参数),其 `allocatedType()` 是 `i32*`。
// 访问 `a[i]` 会生成类似 `getelementptr i32, i32* %a.param, i32 %i` 的 GEP。
// 这种 GEP 有两个操作数:基指针和索引。
// 检查 GEP 的操作数数量和索引值
// GEP 的操作数通常是:<base_pointer>, <index_1>, <index_2>, ...
// 对于一个 `i32*` 类型的 `alloca`,如果它被 GEP 使用,那么 GEP 的第一个索引通常是 `0`
// (表示解引用指针本身),后续索引才是数组元素的索引。
// 如果 GEP 的操作数数量大于 2 (即 `base_ptr` 和 `index_0` 之外还有其他索引)
// 或者 `index_0` 不是常量 0则它可能是一个复杂的数组访问。
// 假设 `gep->getNumOperands()` 和 `gep->getOperand(idx)->getValue()`
// 假设 `ConstantInt` 类用于表示常量整数值
if (gep->getNumOperands() > 2) { // 如果有超过一个索引(除了基指针的第一个隐式索引)
// std::cerr << "Mem2Reg: Not promotable (GEP with multiple indices): " << alloca->name() << std::endl;
return false; // 复杂 GEP通常表示数组或结构体字段访问
}
if (gep->getNumOperands() == 2) { // 只有基指针和一个索引
Value *firstIndexVal = gep->getOperand(1); // 获取第一个索引值
if (auto constInt = dynamic_cast<ConstantInteger *>(firstIndexVal)) {
if (constInt->getInt() != 0) {
// std::cerr << "Mem2Reg: Not promotable (GEP with non-zero first index): " << alloca->name() << std::endl;
return false; // 索引不是0表示访问数组的非第一个元素
}
} else {
// std::cerr << "Mem2Reg: Not promotable (GEP with non-constant first index): " << alloca->name() <<
// std::endl;
return false; // 索引不是常量,表示动态数组访问
}
}
// 此外GEP 的结果也必须只被 LoadInst 或 StoreInst 使用
for (auto gep_use : gep->getUses()) {
auto gep_user = gep_use->getUser();
if (!gep_user) {
// std::cerr << "Mem2Reg: Not promotable (GEP result null user): " << alloca->name() << std::endl;
return false;
}
if (!dynamic_cast<LoadInst *>(gep_user) && !dynamic_cast<StoreInst *>(gep_user)) {
// std::cerr << "Mem2Reg: Not promotable (GEP result used by non-load/store): " << alloca->name() <<
// std::endl;
return false; // GEP 结果被其他指令使用,地址逃逸或复杂用途
}
}
} else {
// 其他类型的用户,如 CallInst (如果地址逃逸),则不能提升
return false;
}
}
// 3. 不能是 volatile 内存访问 (假设 AllocaInst 有 isVolatile() 方法)
// if (alloca->isVolatile()) return false; // 如果有这样的属性
return true;
}
// 收集所有对给定 AllocaInst 进行存储的 StoreInst
void Mem2RegContext::collectStores(AllocaInst *alloca) {
// 遍历 alloca 的所有用途
for (auto use : alloca->getUses()) {
auto user = use->getUser();
if (!user)
continue;
if (auto storeInst = dynamic_cast<StoreInst *>(user)) {
allocaToStoresMap[alloca].insert(storeInst);
allocaToDefBlocksMap[alloca].insert(storeInst->getParent());
} else if (auto gep = dynamic_cast<GetElementPtrInst *>(user)) {
// 如果是 GEP递归收集其下游的 store
for (auto gep_use : gep->getUses()) {
if (auto gep_store = dynamic_cast<StoreInst *>(gep_use->getUser())) {
allocaToStoresMap[alloca].insert(gep_store);
allocaToDefBlocksMap[alloca].insert(gep_store->getParent());
}
}
}
}
}
// 为给定的 AllocaInst 插入必要的 Phi 指令
void Mem2RegContext::insertPhis(AllocaInst *alloca, const std::unordered_set<BasicBlock *> &defBlocks) {
std::queue<BasicBlock *> workQueue;
std::unordered_set<BasicBlock *> phiHasBeenInserted; // 记录已插入 Phi 的基本块
// 将所有定义块加入工作队列
for (auto bb : defBlocks) {
workQueue.push(bb);
}
while (!workQueue.empty()) {
BasicBlock *currentDefBlock = workQueue.front();
workQueue.pop();
// 遍历当前定义块的支配边界 (Dominance Frontier)
const std::set<BasicBlock *> *frontierBlocks = dt->getDominanceFrontier(currentDefBlock);
for (auto frontierBlock : *frontierBlocks) {
// 如果该支配边界块还没有为当前 alloca 插入 Phi 指令
if (phiHasBeenInserted.find(frontierBlock) == phiHasBeenInserted.end()) {
// 在支配边界块的开头插入一个新的 Phi 指令
// Phi 指令的类型与 alloca 的类型指向的类型相同
builder->setPosition(frontierBlock, frontierBlock->begin()); // 设置插入位置为基本块开头
PhiInst *phiInst = builder->createPhiInst(alloca->getAllocatedType(), {}, {}, "");
allocaToPhiMap[alloca][frontierBlock] = phiInst; // 记录 Phi 指令
phiHasBeenInserted.insert(frontierBlock); // 标记已插入 Phi
// 如果这个支配边界块本身也是一个定义块(即使没有 store但插入了 Phi
// 那么它的支配边界也可能需要插入 Phi
// 例如一个xx型的cfg如果在第一个交叉处插入phi节点那么第二个交叉处可能也需要插入phi
workQueue.push(frontierBlock);
}
}
}
}
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
void Mem2RegContext::renameVariables(AllocaInst *currentAlloca, BasicBlock *currentBB) {
// 维护一个局部栈,用于存储当前基本块中为 Phi 和 Store 创建的 SSA 值,以便在退出时弹出
std::stack<Value *> localStackPushed;
// --------------------------------------------------------------------
// 处理当前基本块的指令
// --------------------------------------------------------------------
for (auto instIter = currentBB->getInstructions().begin(); instIter != currentBB->getInstructions().end();) {
Instruction *inst = instIter->get();
bool instDeleted = false;
// 处理 Phi 指令 (如果是当前 alloca 的 Phi)
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
// 检查这个 Phi 是否是为某个可提升的 alloca 插入的
for (auto alloca : promotableAllocas) {
if (allocaToPhiMap[alloca].count(currentBB) && allocaToPhiMap[alloca][currentBB] == phiInst) {
// 为 Phi 指令的输出创建一个新的 SSA 值,并压入值栈
allocaToValueStackMap[alloca].push(phiInst);
localStackPushed.push(phiInst); // 记录以便弹出
break; // 找到对应的 alloca处理下一个指令
}
}
}
// 处理 LoadInst
else if (auto loadInst = dynamic_cast<LoadInst *>(inst)) {
// 检查这个 LoadInst 是否是为某个可提升的 alloca
for (auto alloca : promotableAllocas) {
if (loadInst->getPointer() == alloca) {
// loadInst->getPointer() 返回 AllocaInst*
// 将 LoadInst 的所有用途替换为当前 alloca 值栈顶部的 SSA 值
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca during load replacement!");
loadInst->replaceAllUsesWith(allocaToValueStackMap[alloca].top());
// instIter = currentBB->force_delete_inst(loadInst); // 删除 LoadInst
SysYIROptUtils::usedelete(loadInst); // 仅删除 use 关系
instIter = currentBB->getInstructions().erase(instIter); // 删除 LoadInst
instDeleted = true;
// std::cerr << "Mem2Reg: Replaced load " << loadInst->name() << " with SSA value." << std::endl;
break;
}
}
}
// 处理 StoreInst
else if (auto storeInst = dynamic_cast<StoreInst *>(inst)) {
// 检查这个 StoreInst 是否是为某个可提升的 alloca
for (auto alloca : promotableAllocas) {
if (storeInst->getPointer() == alloca) {
// 假设 storeInst->getPointer() 返回 AllocaInst*
// 将 StoreInst 存储的值作为新的 SSA 值,压入值栈
allocaToValueStackMap[alloca].push(storeInst->getValue());
localStackPushed.push(storeInst->getValue()); // 记录以便弹出
SysYIROptUtils::usedelete(storeInst);
instIter = currentBB->getInstructions().erase(instIter); // 删除 StoreInst
instDeleted = true;
// std::cerr << "Mem2Reg: Replaced store to " << storeInst->ptr()->name() << " with SSA value." << std::endl;
break;
}
}
}
if (!instDeleted) {
++instIter; // 如果指令没有被删除,移动到下一个
}
}
// --------------------------------------------------------------------
// 处理后继基本块的 Phi 指令参数
// --------------------------------------------------------------------
for (auto successorBB : currentBB->getSuccessors()) {
if (!successorBB)
continue;
for (auto alloca : promotableAllocas) {
// 如果后继基本块包含为当前 alloca 插入的 Phi 指令
if (allocaToPhiMap[alloca].count(successorBB)) {
auto phiInst = allocaToPhiMap[alloca][successorBB];
// 为 Phi 指令添加来自当前基本块的参数
// 参数值是当前 alloca 值栈顶部的 SSA 值
assert(!allocaToValueStackMap[alloca].empty() && "Value stack empty for alloca when setting phi operand!");
phiInst->addIncoming(allocaToValueStackMap[alloca].top(), currentBB);
}
}
}
// --------------------------------------------------------------------
// 递归访问支配树的子节点
// --------------------------------------------------------------------
const std::set<BasicBlock *> *dominatedBlocks = dt->getDominatorTreeChildren(currentBB);
if(dominatedBlocks){
for (auto dominatedBB : *dominatedBlocks) {
if (dominatedBB) {
std::cout << "Mem2Reg: Recursively renaming variables in dominated block: " << dominatedBB->getName() << std::endl;
renameVariables(currentAlloca, dominatedBB);
}
}
}
// --------------------------------------------------------------------
// 退出基本块时,弹出在此块中压入值栈的 SSA 值
// --------------------------------------------------------------------
while (!localStackPushed.empty()) {
Value *val = localStackPushed.top();
localStackPushed.pop();
// 找到是哪个 alloca 对应的栈
for (auto alloca : promotableAllocas) {
if (!allocaToValueStackMap[alloca].empty() && allocaToValueStackMap[alloca].top() == val) {
allocaToValueStackMap[alloca].pop();
break;
}
}
}
}
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
void Mem2RegContext::cleanup() {
for (auto alloca : promotableAllocas) {
if (alloca && alloca->getParent()) {
// 删除 alloca 指令本身
SysYIROptUtils::usedelete(alloca);
alloca->getParent()->removeInst(alloca); // 从基本块中删除 alloca
// std::cerr << "Mem2Reg: Deleted alloca " << alloca->name() << std::endl;
}
}
// LoadInst 和 StoreInst 已经在 renameVariables 阶段被删除了
}
// Mem2Reg 遍的 runOnFunction 方法实现
bool Mem2Reg::runOnFunction(Function *F, AnalysisManager &AM) {
// 记录初始的指令数量,用于判断优化是否发生了改变
size_t initial_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
initial_inst_count += bb->getInstructions().size();
}
Mem2RegContext ctx(builder);
ctx.run(F, &AM); // 运行 Mem2Reg 优化
// 运行优化后,再次计算指令数量
size_t final_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
final_inst_count += bb->getInstructions().size();
}
// 如果指令数量发生变化(通常是减少,因为 load/store 被删除phi 被添加),说明 IR 被修改了
// TODO不保险后续修改为更精确的判断
// 直接在添加和删除指令时维护changed值
bool changed = (initial_inst_count != final_inst_count);
// 如果 IR 被修改,则使相关的分析结果失效
if (changed) {
// Mem2Reg 会显著改变 IR 结构,特别是数据流和控制流(通过 Phi
// 这会使几乎所有数据流分析和部分控制流分析失效。
// AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, F); // 支配树可能间接改变(如果基本块被删除)
// AM.invalidateAnalysis(&LivenessAnalysisPass::ID, F); // 活跃性分析肯定失效
// AM.invalidateAnalysis(&LoopInfoAnalysisPass::ID, F); // 循环信息可能失效
// AM.invalidateAnalysis(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效(如果 Alloca/Load/Store
// 被替换为寄存器)
// ... 其他数据流分析,如到达定义、可用表达式等,也应失效
}
return changed;
}
// 声明Mem2Reg遍的分析依赖和失效信息
void Mem2Reg::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// Mem2Reg 强烈依赖于支配树分析来插入 Phi 指令
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 假设 DominatorTreeAnalysisPass 的 ID
// Mem2Reg 会删除 Alloca/Load/Store 指令,插入 Phi 指令,这会大幅改变 IR 结构。
// 因此,它会使许多分析结果失效。
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析肯定失效
// analysisInvalidations.insert(&LoopInfoAnalysisPass::ID); // 循环信息可能失效
// analysisInvalidations.insert(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效
// 其他所有依赖于数据流或 IR 结构的分析都可能失效。
}
} // namespace sysy

View File

@@ -0,0 +1,289 @@
#include "Reg2Mem.h"
#include "SysYIROptUtils.h"
#include "SysYIRPrinter.h"
extern int DEBUG; // 全局调试标志
namespace sysy {
void *Reg2Mem::ID = (void *)&Reg2Mem::ID;
void Reg2MemContext::run(Function *func) {
if (func->getBasicBlocks().empty()) {
return;
}
// 清空状态,确保每次运行都是新的
valueToAllocaMap.clear();
// 阶段1: 识别并为 SSA Value 分配 AllocaInst
allocateMemoryForSSAValues(func);
// 阶段2: 将 Phi 指令转换为 Load/Store 逻辑 (此阶段需要先于通用 Load/Store 插入)
// 这样做是因为 Phi 指令的特殊性,它需要在前驱块的末尾插入 Store
// 如果先处理通用 Load/Store可能无法正确处理 Phi 的复杂性
rewritePhis(func); // Phi 指令可能在 rewritePhis 中被删除或标记删除
// 阶段3: 将其他 SSA Value 的使用替换为 Load/Store
insertLoadsAndStores(func);
// 阶段4: 清理(删除不再需要的 Phi 指令)
cleanup(func);
}
bool Reg2MemContext::isPromotableToMemory(Value *val) {
// 参数和指令结果是 SSA 值
if(DEBUG){
// if(val->getName() == ""){
// assert(false && "Value name should not be empty in Reg2MemContext::isPromotableToMemory");
// }
// std::cout << "Checking if value is promotable to memory: " << val->getName() << std::endl;
}
// if (dynamic_cast<Argument *>(val) || dynamic_cast<Instruction *>(val)) {
// // 如果值已经是指针类型,则通常不为其分配额外的内存,因为它已经是一个地址。
// // (除非我们想将其值也存储起来,这通常不用于 Reg2Mem
// // // Reg2Mem 关注的是将非指针值从寄存器语义转换为内存语义。
// if (val->getType()->isPointer()) {
// return false;
// }
// return true;
// }
// 1. 如果是 Argument则可以提升到内存
if (dynamic_cast<Argument *>(val)) {
// 参数类型i32, i32* 等)都可以为其分配内存
// 因为它们在 Mem2Reg 逆操作中,被认为是从寄存器分配到内存
return true;
}
if (dynamic_cast<PhiInst *>(val)) {
// Phi 指令的结果也是一个 SSA 值,需要将其转换为 Load/Store
return true;
}
return false;
}
void Reg2MemContext::allocateMemoryForSSAValues(Function *func) {
// AllocaInst 必须在函数的入口基本块中
BasicBlock *entryBlock = func->getEntryBlock();
if (!entryBlock) {
return; // 函数可能没有入口块 (例如声明)
}
// 1. 为函数参数分配内存
builder->setPosition(entryBlock, entryBlock->begin()); // 确保在入口块的开始位置插入
for (auto arg : func->getArguments()) {
// 默认情况下,将所有参数是提升到内存
if (isPromotableToMemory(arg)) {
// 参数的类型就是 AllocaInst 需要分配的类型
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(arg->getType()), {}, arg->getName() + ".reg2mem");
// 将参数值 store 到 alloca 中 (这是 Mem2Reg 逆转的关键一步)
valueToAllocaMap[arg] = alloca;
// 确保 alloca 位于入口块的顶部,但在所有参数的 store 指令之前
// 通常 alloca 都在 entry block 的最开始
// 这里我们只是创建,并让 builder 决定插入位置 (通常在当前插入点)
// 如果需要严格控制顺序,可能需要手动 insert 到 instruction list
}
}
// 2. 为指令结果分配内存
// 遍历所有基本块和指令,找出所有需要分配 Alloca 的指令结果
for (auto &bb : func->getBasicBlocks()) {
for (auto &inst : bb->getInstructions_Range()) {
// SysYPrinter::printInst(inst.get());
// 只有有结果的指令才可能需要分配内存
// (例如 BinaryInst, CallInst, LoadInst, PhiInst 等)
// StoreInst, BranchInst, ReturnInst 等没有结果的指令不需要
if (dynamic_cast<AllocaInst*>(inst.get()) || inst.get()->getType()->isVoid()) {
continue;
}
if (isPromotableToMemory(inst.get())) {
// 为指令的结果分配内存
// AllocaInst 应该在入口块,而不是当前指令所在块
// 这里我们只是创建,并稍后调整其位置
// 通常的做法是在循环结束后统一将 alloca 放到 entryBlock 的顶部
AllocaInst *alloca = builder->createAllocaInst(Type::getPointerType(inst.get()->getType()), {}, inst.get()->getName() + ".reg2mem");
valueToAllocaMap[inst.get()] = alloca;
}
}
}
Instruction *firstNonAlloca = nullptr;
for (auto instIter = entryBlock->getInstructions().begin(); instIter != entryBlock->getInstructions().end(); instIter++) {
if (!dynamic_cast<AllocaInst*>(instIter->get())) {
firstNonAlloca = instIter->get();
break;
}
}
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());
}
void Reg2MemContext::rewritePhis(Function *func) {
std::vector<PhiInst *> phisToErase; // 收集要删除的 Phi
// 遍历所有基本块和其中的指令,查找 Phi 指令
for (auto &bb : func->getBasicBlocks()) {
// auto insts = bb->getInstructions(); // 复制一份,因为要修改
for (auto instIter = bb->getInstructions().begin(); instIter != bb->getInstructions().end(); instIter++) {
Instruction *inst = instIter->get();
if (auto phiInst = dynamic_cast<PhiInst *>(inst)) {
// 检查 Phi 指令是否是需要处理的 SSA 值
if (valueToAllocaMap.count(phiInst)) {
AllocaInst *alloca = valueToAllocaMap[phiInst];
// 1. 为 Phi 指令的每个入边,在前驱块的末尾插入 Store 指令
// PhiInst 假设有 getIncomingValues() 和 getIncomingBlocks()
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 假设 PhiInst 是通过操作数来管理入边的
Value *incomingValue = phiInst->getValue(i); // 获取入值
BasicBlock *incomingBlock = phiInst->getBlock(i); // 获取对应的入块
// 在入块的跳转指令之前插入 StoreInst
// 需要找到 incomingBlock 的终结指令 (Terminator Instruction)
// 并将 StoreInst 插入到它前面
if (incomingBlock->terminator()->get()->isTerminator()) {
builder->setPosition(incomingBlock, incomingBlock->terminator());
} else {
// 如果没有终结指令,插入到末尾
builder->setPosition(incomingBlock, incomingBlock->end());
}
builder->createStoreInst(incomingValue, alloca);
}
// 2. 在当前 Phi 所在基本块的开头,插入 Load 指令
// 将 Load 指令插入到 Phi 指令之后,因为 Phi 指令即将被删除
builder->setPosition(bb.get(), bb.get()->findInstIterator(phiInst));
LoadInst *newLoad = builder->createLoadInst(alloca);
// 3. 将 Phi 指令的所有用途替换为新的 Load 指令
phiInst->replaceAllUsesWith(newLoad);
// 标记 Phi 指令待删除
phisToErase.push_back(phiInst);
}
}
}
}
// 实际删除 Phi 指令
for (auto phi : phisToErase) {
if (phi && phi->getParent()) {
SysYIROptUtils::usedelete(phi); // 清理 use-def 链
phi->getParent()->removeInst(phi); // 从基本块中删除
}
}
}
void Reg2MemContext::insertLoadsAndStores(Function *func) {
// 收集所有需要替换的 uses避免在迭代时修改 use 链表
std::vector<std::pair<Use *, LoadInst *>> usesToReplace;
std::vector<Instruction *> instsToStore; // 收集需要插入 Store 的指令
// 遍历所有基本块和指令
for (auto &bb : func->getBasicBlocks()) {
for (auto instIter = bb->getInstructions().begin(); instIter != bb->getInstructions().end(); instIter++) {
Instruction *inst = instIter->get();
// 如果指令有结果且我们为其分配了 alloca (Phi 已在 rewritePhis 处理)
// 并且其类型不是 void
if (!inst->getType()->isVoid() && valueToAllocaMap.count(inst)) {
// 在指令之后插入 Store 指令
// StoreInst 应该插入到当前指令之后
builder->setPosition(bb.get(), bb.get()->findInstIterator(inst));
builder->createStoreInst(inst, valueToAllocaMap[inst]);
}
// 处理指令的操作数:如果操作数是一个 SSA 值,且为其分配了 alloca
// (并且这个操作数不是 Phi Inst 的 incoming value因为 Phi 的 incoming value 已经在 rewritePhis 中处理了)
// 注意Phi Inst 的操作数是特殊的,它们表示来自不同前驱块的值。
// 这里的处理主要是针对非 Phi 指令的操作数。
for (auto use = inst->getUses().begin(); use != inst->getUses().end(); ++use) {
// 如果当前 use 的 Value 是一个 Instruction 或 Argument
Value *operand = use->get()->getValue();
if (isPromotableToMemory(operand) && valueToAllocaMap.count(operand)) {
// 确保这个 operand 不是一个即将被删除的 Phi 指令
// (在 rewritePhis 阶段Phi 已经被处理并可能被标记删除)
// 或者检查 use 的 user 不是 PhiInst
if (dynamic_cast<PhiInst *>(inst)) {
continue; // Phi 的操作数已在 rewritePhis 中处理
}
AllocaInst *alloca = valueToAllocaMap[operand];
// 在使用点之前插入 Load 指令
// LoadInst 应该插入到使用它的指令之前
builder->setPosition(bb.get(), bb.get()->findInstIterator(inst));
LoadInst *newLoad = builder->createLoadInst(alloca);
// 记录要替换的 use
usesToReplace.push_back({use->get(), newLoad});
}
}
}
}
// 执行所有替换操作
for (auto &pair : usesToReplace) {
pair.first->setValue(pair.second); // 替换 use 的 Value
}
}
void Reg2MemContext::cleanup(Function *func) {
// 此时,所有原始的 Phi 指令应该已经被删除。
// 如果有其他需要删除的临时指令,可以在这里处理。
// 通常Reg2Mem 的清理比 Mem2Reg 简单,因为主要是在插入指令。
// 这里可以作为一个占位符,以防未来有其他清理需求。
}
bool Reg2Mem::runOnFunction(Function *F, AnalysisManager &AM) {
// 记录初始指令数量
size_t initial_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
initial_inst_count += bb->getInstructions().size();
}
Reg2MemContext ctx(builder); // 假设 builder 是一个全局或可访问的 IRBuilder 实例
ctx.run(F);
// 记录最终指令数量
size_t final_inst_count = 0;
for (auto &bb : F->getBasicBlocks()) {
final_inst_count += bb->getInstructions().size();
}
// TODO: 添加更精确的变化检测逻辑例如在run函数中维护changed状态
bool changed = (initial_inst_count != final_inst_count); // 粗略判断是否改变
if (changed) {
// Reg2Mem 会显著改变 IR 结构,特别是数据流。
// 它会插入大量的 Load/Store 指令,改变 Value 的来源。
// 这会使几乎所有数据流分析失效。
// 例如:
// AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, F); // 如果基本块结构改变,可能失效
// AM.invalidateAnalysis(&LivenessAnalysisPass::ID, F); // 活跃性分析肯定失效
// AM.invalidateAnalysis(&DCEPass::ID, F); // 可能产生新的死代码
// ... 其他所有数据流分析
}
return changed;
}
void Reg2Mem::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
// Reg2Mem 通常不需要特定的分析作为依赖,因为它主要是一个转换。
// 但它会使许多分析失效。
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 例如
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
}
} // namespace sysy

View File

@@ -0,0 +1,600 @@
#include "SysYIRCFGOpt.h"
#include "SysYIROptUtils.h"
#include <cassert>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <iostream>
#include <queue> // 引入队列SysYDelNoPreBLock需要
namespace sysy {
// 定义静态ID
void *SysYDelInstAfterBrPass::ID = (void *)&SysYDelInstAfterBrPass::ID;
void *SysYDelEmptyBlockPass::ID = (void *)&SysYDelEmptyBlockPass::ID;
void *SysYDelNoPreBLockPass::ID = (void *)&SysYDelNoPreBLockPass::ID;
void *SysYBlockMergePass::ID = (void *)&SysYBlockMergePass::ID;
void *SysYAddReturnPass::ID = (void *)&SysYAddReturnPass::ID;
void *SysYCondBr2BrPass::ID = (void *)&SysYCondBr2BrPass::ID;
// ======================================================================
// SysYCFGOptUtils: 辅助工具类包含实际的CFG优化逻辑
// ======================================================================
// 删除br后的无用指令
bool SysYCFGOptUtils::SysYDelInstAfterBr(Function *func) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &basicBlock : basicBlocks) {
bool Branch = false;
auto &instructions = basicBlock->getInstructions();
auto Branchiter = instructions.end();
for (auto iter = instructions.begin(); iter != instructions.end(); ++iter) {
if ((*iter)->isTerminator()){
Branch = true;
Branchiter = iter;
break;
}
}
if (Branchiter != instructions.end()) ++Branchiter;
while (Branchiter != instructions.end()) {
changed = true;
Branchiter = instructions.erase(Branchiter);
}
if (Branch) { // 更新前驱后继关系
auto thelastinstinst = basicBlock->getInstructions().end();
--thelastinstinst;
auto &Successors = basicBlock->getSuccessors();
for (auto iterSucc = Successors.begin(); iterSucc != Successors.end();) {
(*iterSucc)->removePredecessor(basicBlock.get());
basicBlock->removeSuccessor(*iterSucc);
}
if (thelastinstinst->get()->isUnconditional()) {
BasicBlock* branchBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(0));
basicBlock->addSuccessor(branchBlock);
branchBlock->addPredecessor(basicBlock.get());
} else if (thelastinstinst->get()->isConditional()) {
BasicBlock* thenBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(1));
BasicBlock* elseBlock = dynamic_cast<BasicBlock *>(thelastinstinst->get()->getOperand(2));
basicBlock->addSuccessor(thenBlock);
basicBlock->addSuccessor(elseBlock);
thenBlock->addPredecessor(basicBlock.get());
elseBlock->addPredecessor(basicBlock.get());
}
}
}
return changed;
}
// 合并基本块
bool SysYCFGOptUtils::SysYBlockMerge(Function *func) {
bool changed = false;
for (auto blockiter = func->getBasicBlocks().begin();
blockiter != func->getBasicBlocks().end();) {
if (blockiter->get()->getNumSuccessors() == 1) {
// 如果当前块只有一个后继块
// 且后继块只有一个前驱块
// 则将当前块和后继块合并
if (((blockiter->get())->getSuccessors()[0])->getNumPredecessors() == 1) {
// std::cout << "merge block: " << blockiter->get()->getName() << std::endl;
BasicBlock* block = blockiter->get();
BasicBlock* nextBlock = blockiter->get()->getSuccessors()[0];
// auto nextarguments = nextBlock->getArguments();
// 删除br指令
if (block->getNumInstructions() != 0) {
auto thelastinstinst = block->end();
(--thelastinstinst);
if (thelastinstinst->get()->isUnconditional()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
} else if (thelastinstinst->get()->isConditional()) {
// 如果是条件分支,判断条件是否相同,主要优化相同布尔表达式
if (thelastinstinst->get()->getOperand(1)->getName() == thelastinstinst->get()->getOperand(1)->getName()) {
SysYIROptUtils::usedelete(thelastinstinst->get());
thelastinstinst = block->getInstructions().erase(thelastinstinst);
}
}
}
// 将后继块的指令移动到当前块
// 并将后继块的父指针改为当前块
for (auto institer = nextBlock->begin(); institer != nextBlock->end();) {
institer->get()->setParent(block);
block->getInstructions().emplace_back(institer->release());
institer = nextBlock->getInstructions().erase(institer);
}
// 更新前驱后继关系,类似树节点操作
block->removeSuccessor(nextBlock);
nextBlock->removePredecessor(block);
std::list<BasicBlock *> succshoulddel;
for (auto &succ : nextBlock->getSuccessors()) {
block->addSuccessor(succ);
succ->replacePredecessor(nextBlock, block);
succshoulddel.push_back(succ);
}
for (auto del : succshoulddel) {
nextBlock->removeSuccessor(del);
}
func->removeBasicBlock(nextBlock);
changed = true;
} else {
blockiter++;
}
} else {
blockiter++;
}
}
return changed;
}
// 删除无前驱块兼容SSA后的处理
bool SysYCFGOptUtils::SysYDelNoPreBLock(Function *func) {
bool changed = false;
for (auto &block : func->getBasicBlocks()) {
block->setreachableFalse();
}
// 对函数基本块做一个拓扑排序,排查不可达基本块
auto entryBlock = func->getEntryBlock();
entryBlock->setreachableTrue();
std::queue<BasicBlock *> blockqueue;
blockqueue.push(entryBlock);
while (!blockqueue.empty()) {
auto block = blockqueue.front();
blockqueue.pop();
for (auto &succ : block->getSuccessors()) {
if (!succ->getreachable()) {
succ->setreachableTrue();
blockqueue.push(succ);
}
}
}
// 删除不可达基本块指令
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end(); blockIter++) {
if (!blockIter->get()->getreachable()) {
for (auto instIter = blockIter->get()->getInstructions().begin();
instIter != blockIter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get());
instIter = blockIter->get()->getInstructions().erase(instIter);
}
}
}
for (auto blockIter = func->getBasicBlocks().begin(); blockIter != func->getBasicBlocks().end();) {
if (!blockIter->get()->getreachable()) {
for (auto succblock : blockIter->get()->getSuccessors()) {
for (auto &phiinst : succblock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法正确地删除对应于被删除基本块的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(blockIter->get());
}
}
// 删除不可达基本块,注意迭代器不可达问题
func->removeBasicBlock((blockIter++)->get());
changed = true;
} else {
blockIter++;
}
}
return changed;
}
// 删除空块
bool SysYCFGOptUtils::SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder) {
bool changed = false;
// 收集不可达基本块
// 这里的不可达基本块是指没有实际指令的基本块
// 当一个基本块没有实际指令例如只有phi指令和一个uncondbr指令时也会被视作不可达
auto basicBlocks = func->getBasicBlocks();
std::map<sysy::BasicBlock *, BasicBlock *> EmptyBlocks;
// 空块儿和后继的基本块的映射
for (auto &basicBlock : basicBlocks) {
if (basicBlock->getNumInstructions() == 0) {
if (basicBlock->getNumSuccessors() == 1) {
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
else{
// 如果只有phi指令和一个uncondbr。(phi)*(uncondbr)?
// 判断除了最后一个指令之外是不是只有phi指令
bool onlyPhi = true;
for (auto &inst : basicBlock->getInstructions()) {
if (!inst->isPhi() && !inst->isUnconditional()) {
onlyPhi = false;
break;
}
}
if(onlyPhi && basicBlock->getNumSuccessors() == 1) // 确保有后继且只有一个
EmptyBlocks[basicBlock.get()] = basicBlock->getSuccessors().front();
}
}
// 更新基本块信息,增加必要指令
for (auto &basicBlock : basicBlocks) {
// 把空块转换成只有跳转指令的不可达块 (这段逻辑在优化遍中可能需要调整,这里是原样保留)
// 通常DelEmptyBlock 应该在BlockMerge之后运行如果存在完全空块它会尝试填充一个Br指令。
// 但是,它主要目的是重定向跳转。
if (distance(basicBlock->begin(), basicBlock->end()) == 0) {
if (basicBlock->getNumSuccessors() == 0) {
continue;
}
if (basicBlock->getNumSuccessors() > 1) {
// 如果一个空块有多个后继说明CFG结构有问题或者需要特殊处理这里简单assert
assert(false && "Empty block with multiple successors found during SysYDelEmptyBlock");
}
// 这里的逻辑有点问题,如果一个块是空的,且只有一个后继,应该直接跳转到后继。
// 如果这个块最终被删除了,那么其前驱也需要重定向。
// 这个循环的目的是重定向现有的跳转指令,而不是创建新的。
// 所以下面的逻辑才是核心。
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
continue;
}
auto thelastinst = basicBlock->getInstructions().end();
--thelastinst;
// 根据br指令传递的后继块信息跳过空块链
if (thelastinst->get()->isUnconditional()) {
BasicBlock* OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
BasicBlock *thelastBlockOld = nullptr;
// 如果空块链表为多个块
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
thelastinst->get()->replaceOperand(0, EmptyBlocks[thelastBlockOld]);
}
// 如果有重定向发生
if (thelastBlockOld != nullptr) {
basicBlock->removeSuccessor(OldBrBlock);
OldBrBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
} else if (thelastinst->get()->getKind() == Instruction::kCondBr) {
auto OldThenBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
auto OldElseBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
bool thenChanged = false;
bool elseChanged = false;
BasicBlock *thelastBlockOld = nullptr;
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
thelastinst->get()->replaceOperand(
1, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))]);
thenChanged = true;
}
if (thenChanged) {
basicBlock->removeSuccessor(OldThenBlock);
OldThenBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
changed = true; // 标记IR被修改
continue;
}
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
thelastBlockOld = nullptr;
while (EmptyBlocks.count(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)))) {
thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2));
thelastinst->get()->replaceOperand(
2, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))]);
elseChanged = true;
}
if (elseChanged) {
basicBlock->removeSuccessor(OldElseBlock);
OldElseBlock->removePredecessor(basicBlock.get());
basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2)));
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->addPredecessor(basicBlock.get());
changed = true; // 标记IR被修改
}
// 处理 then 和 else 分支合并的情况
if (dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1)) ==
dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))) {
auto thebrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(1));
SysYIROptUtils::usedelete(thelastinst->get());
thelastinst = basicBlock->getInstructions().erase(thelastinst);
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
pBuilder->createUncondBrInst(thebrBlock, {});
changed = true; // 标记IR被修改
continue;
}
// 如果有重定向发生
// 需要更新后继块的前驱关系
if (thelastBlockOld != nullptr) {
for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(2))->getInstructions()) {
if (InstInNew->isPhi()) {
// 使用 delBlk 方法删除 oldBlock 对应的传入值
dynamic_cast<PhiInst *>(InstInNew.get())->delBlk(thelastBlockOld);
} else {
break;
}
}
}
} else {
// 如果不是终止指令,但有后继 (例如,末尾没有显式终止指令的块)
// 这段逻辑可能需要更严谨的CFG检查来确保正确性
if (basicBlock->getNumSuccessors() == 1) {
// 这里的逻辑似乎是想为没有terminator的块添加一个但通常这应该在CFG构建阶段完成。
// 如果这里仍然执行,确保它符合预期。
// pBuilder->setPosition(basicBlock.get(), basicBlock->end());
// pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
// auto thelastinst = basicBlock->getInstructions().end();
// (--thelastinst);
// auto OldBrBlock = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
// sysy::BasicBlock *thelastBlockOld = nullptr;
// while (EmptyBlocks.find(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))) !=
// EmptyBlocks.end()) {
// thelastBlockOld = dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0));
// thelastinst->get()->replaceOperand(
// 0, EmptyBlocks[dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))]);
// }
// basicBlock->removeSuccessor(OldBrBlock);
// OldBrBlock->removePredecessor(basicBlock.get());
// basicBlock->addSuccessor(dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0)));
// dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->addPredecessor(basicBlock.get());
// changed = true; // 标记IR被修改
// if (thelastBlockOld != nullptr) {
// int indexphi = 0;
// for (auto &pred : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getPredecessors()) {
// if (pred == thelastBlockOld) {
// break;
// }
// indexphi++;
// }
// for (auto &InstInNew : dynamic_cast<BasicBlock *>(thelastinst->get()->getOperand(0))->getInstructions()) {
// if (InstInNew->isPhi()) {
// dynamic_cast<PhiInst *>(InstInNew.get())->removeOperand(indexphi + 1);
// } else {
// break;
// }
// }
// }
}
}
}
// 真正的删除空块
for (auto iter = func->getBasicBlocks().begin(); iter != func->getBasicBlocks().end();) {
if (EmptyBlocks.count(iter->get())) {
// EntryBlock跳过
if (iter->get() == func->getEntryBlock()) {
++iter;
continue;
}
for (auto instIter = iter->get()->getInstructions().begin();
instIter != iter->get()->getInstructions().end();) {
SysYIROptUtils::usedelete(instIter->get()); // 仅删除 use 关系
// 显式地从基本块中删除指令并更新迭代器
instIter = iter->get()->getInstructions().erase(instIter);
}
// 删除不可达基本块的phi指令的操作数
for (auto &succ : iter->get()->getSuccessors()) {
for (auto &instinsucc : succ->getInstructions()) {
if (instinsucc->isPhi()) {
// iter->get() 就是当前被删除的空基本块它作为前驱连接到这里的Phi指令
dynamic_cast<PhiInst *>(instinsucc.get())->delBlk(iter->get());
} else {
// Phi 指令通常在基本块的开头,如果不是 Phi 指令就停止检查
break;
}
}
}
func->removeBasicBlock((iter++)->get());
changed = true;
} else {
++iter;
}
}
return changed;
}
// 如果函数没有返回指令,则添加一个默认返回指令(主要解决void函数没有返回指令的问题)
bool SysYCFGOptUtils::SysYAddReturn(Function *func, IRBuilder* pBuilder) {
bool changed = false;
auto basicBlocks = func->getBasicBlocks();
for (auto &block : basicBlocks) {
if (block->getNumSuccessors() == 0) {
// 如果基本块没有后继块,则添加一个返回指令
if (block->getNumInstructions() == 0) {
pBuilder->setPosition(block.get(), block->end());
pBuilder->createReturnInst();
changed = true; // 标记IR被修改
} else {
auto thelastinst = block->getInstructions().end();
--thelastinst;
if (thelastinst->get()->getKind() != Instruction::kReturn) {
// std::cout << "Warning: Function " << func->getName() << " has no return instruction, adding default return." << std::endl;
pBuilder->setPosition(block.get(), block->end());
// TODO: 如果int float函数缺少返回值是否需要报错
if (func->getReturnType()->isInt()) {
pBuilder->createReturnInst(ConstantInteger::get(0));
} else if (func->getReturnType()->isFloat()) {
pBuilder->createReturnInst(ConstantFloating::get(0.0F));
} else {
pBuilder->createReturnInst();
}
changed = true; // 标记IR被修改
}
}
}
}
return changed;
}
// 条件分支转换为无条件分支
// 主要针对已知条件值的分支转换为无条件分支
// 例如 if (cond) { ... } else { ... } 中的 cond 已经
// 确定为 true 或 false 的情况
bool SysYCFGOptUtils::SysYCondBr2Br(Function *func, IRBuilder* pBuilder) {
bool changed = false;
for (auto &basicblock : func->getBasicBlocks()) {
if (basicblock->getNumInstructions() == 0)
continue;
auto thelast = basicblock->getInstructions().end();
--thelast;
if (thelast->get()->isConditional()){
ConstantValue *constOperand = dynamic_cast<ConstantValue *>(thelast->get()->getOperand(0));
std::string opname;
int constint = 0;
float constfloat = 0.0F;
bool constint_Use = false;
bool constfloat_Use = false;
if (constOperand != nullptr) {
if (constOperand->isFloat()) {
constfloat = constOperand->getFloat();
constfloat_Use = true;
} else {
constint = constOperand->getInt();
constint_Use = true;
}
}
// 如果可以计算
if (constfloat_Use || constint_Use) {
changed = true;
auto thenBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(1));
auto elseBlock = dynamic_cast<BasicBlock *>(thelast->get()->getOperand(2));
SysYIROptUtils::usedelete(thelast->get());
thelast = basicblock->getInstructions().erase(thelast);
if ((constfloat_Use && constfloat == 1.0F) || (constint_Use && constint == 1)) {
// cond为true或非0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(thenBlock, {});
// 更新CFG关系
basicblock->removeSuccessor(elseBlock);
elseBlock->removePredecessor(basicblock.get());
// 删除elseBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : elseBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
}
} else { // cond为false或0
pBuilder->setPosition(basicblock.get(), basicblock->end());
pBuilder->createUncondBrInst(elseBlock, {});
// 更新CFG关系
basicblock->removeSuccessor(thenBlock);
thenBlock->removePredecessor(basicblock.get());
// 删除thenBlock的phi指令中对应的basicblock.get()的传入值
for (auto &phiinst : thenBlock->getInstructions()) {
if (phiinst->getKind() != Instruction::kPhi) {
break;
}
// 使用 delBlk 方法删除 basicblock.get() 对应的传入值
dynamic_cast<PhiInst *>(phiinst.get())->delBlk(basicblock.get());
}
}
}
}
}
return changed;
}
// ======================================================================
// 独立的CFG优化遍的实现
// ======================================================================
bool SysYDelInstAfterBrPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelInstAfterBr(F);
}
bool SysYDelEmptyBlockPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelEmptyBlock(F, pBuilder);
}
bool SysYDelNoPreBLockPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYDelNoPreBLock(F);
}
bool SysYBlockMergePass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYBlockMerge(F);
}
bool SysYAddReturnPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYAddReturn(F, pBuilder);
}
bool SysYCondBr2BrPass::runOnFunction(Function *F, AnalysisManager& AM) {
return SysYCFGOptUtils::SysYCondBr2Br(F, pBuilder);
}
} // namespace sysy

223
src/midend/Pass/Pass.cpp Normal file
View File

@@ -0,0 +1,223 @@
#include "Dom.h"
#include "Liveness.h"
#include "SysYIRCFGOpt.h"
#include "SysYIRPrinter.h"
#include "DCE.h"
#include "Mem2Reg.h"
#include "Reg2Mem.h"
#include "Pass.h"
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <vector>
extern int DEBUG; // 全局调试标志
namespace sysy {
// ======================================================================
// 封装优化流程的函数包含Pass注册和迭代运行逻辑
// ======================================================================
void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR, int optLevel) {
if (DEBUG) std::cout << "--- Starting Middle-End Optimizations (Level -O" << optLevel << ") ---\n";
/*
中端开发框架基本流程:
1) 分析pass
1. 实现分析pass并引入Pass.cpp
2. 注册分析pass
2) 优化pass
1. 实现优化pass并引入Pass.cpp
2. 注册优化pass
3. 添加优化passid
*/
// 注册分析遍
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
registerAnalysisPass<sysy::LivenessAnalysisPass>();
// 注册优化遍
registerOptimizationPass<SysYDelInstAfterBrPass>();
registerOptimizationPass<SysYDelNoPreBLockPass>();
registerOptimizationPass<SysYBlockMergePass>();
registerOptimizationPass<SysYDelEmptyBlockPass>(builderIR);
registerOptimizationPass<SysYCondBr2BrPass>(builderIR);
registerOptimizationPass<SysYAddReturnPass>(builderIR);
registerOptimizationPass<DCE>();
registerOptimizationPass<Mem2Reg>(builderIR);
registerOptimizationPass<Reg2Mem>(builderIR);
if (optLevel >= 1) {
//经过设计安排优化遍的执行顺序以及执行逻辑
if (DEBUG) std::cout << "Applying -O1 optimizations.\n";
if (DEBUG) std::cout << "--- Running custom optimization sequence ---\n";
this->clearPasses();
this->addPass(&SysYDelInstAfterBrPass::ID);
this->addPass(&SysYDelNoPreBLockPass::ID);
this->addPass(&SysYBlockMergePass::ID);
this->addPass(&SysYDelEmptyBlockPass::ID);
this->addPass(&SysYCondBr2BrPass::ID);
this->addPass(&SysYAddReturnPass::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After CFGOpt Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&DCE::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After DCE Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Mem2Reg::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Mem2Reg Optimizations ===\n";
printPasses();
}
this->clearPasses();
this->addPass(&Reg2Mem::ID);
this->run();
if(DEBUG) {
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
printPasses();
}
if (DEBUG) std::cout << "--- Custom optimization sequence finished ---\n";
}
// 2. 创建遍管理器
// 3. 根据优化级别添加不同的优化遍
// TODO : 根据 optLevel 添加不同的优化遍
// 讨论 是不动点迭代进行优化遍还是手动客制化优化遍的顺序?
if (DEBUG) {
std::cout << "=== Final IR After Middle-End Optimizations (Level -O" << optLevel << ") ===\n";
SysYPrinter printer(moduleIR);
printer.printIR();
}
}
void PassManager::clearPasses() {
passes.clear();
}
void PassManager::addPass(void *passID) {
PassRegistry &registry = PassRegistry::getPassRegistry();
std::unique_ptr<Pass> P = registry.createPass(passID);
if (!P) {
// Error: Pass not found or failed to create
return;
}
passes.push_back(std::move(P));
}
// 运行所有注册的遍
bool PassManager::run() {
bool changed = false;
for (const auto &p : passes) {
bool passChanged = false; // 记录当前遍是否修改了 IR
// 处理优化遍的分析依赖和失效
if (p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
// PassManager 不显式运行分析依赖。
// 而是优化遍在 runOnFunction 内部通过 AnalysisManager.getAnalysisResult 按需请求。
}
if (p->getGranularity() == Pass::Granularity::Module) {
passChanged = p->runOnModule(pmodule, analysisManager);
} else if (p->getGranularity() == Pass::Granularity::Function) {
for (auto &funcPair : pmodule->getFunctions()) {
Function *F = funcPair.second.get();
passChanged = p->runOnFunction(F, analysisManager) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
} else if (p->getGranularity() == Pass::Granularity::BasicBlock) {
for (auto &funcPair : pmodule->getFunctions()) {
Function *F = funcPair.second.get();
for (auto &bbPtr : funcPair.second->getBasicBlocks()) {
passChanged = p->runOnBasicBlock(bbPtr.get(), analysisManager) || passChanged;
if (passChanged && p->getPassKind() == Pass::PassKind::Optimization) {
OptimizationPass *optPass = static_cast<OptimizationPass *>(p.get());
std::set<void *> analysisDependencies;
std::set<void *> analysisInvalidations;
optPass->getAnalysisUsage(analysisDependencies, analysisInvalidations);
for (void *invalidationID : analysisInvalidations) {
analysisManager.invalidateAnalysis(invalidationID, F);
}
}
}
}
}
changed = changed || passChanged;
}
return changed;
}
void PassManager::printPasses() const {
std::cout << "Registered Passes:\n";
for (const auto &p : passes) {
std::cout << " - " << p->getName() << " (Granularity: "
<< static_cast<int>(p->getGranularity())
<< ", Kind: " << static_cast<int>(p->getPassKind()) << ")\n";
}
std::cout << "Total Passes: " << passes.size() << "\n";
if (pmodule) {
SysYPrinter printer(pmodule);
std::cout << "Module IR:\n";
printer.printIR();
}
}
template <typename AnalysisPassType> void registerAnalysisPass() {
PassRegistry::getPassRegistry().registerPass(&AnalysisPassType::ID,
[]() { return std::make_unique<AnalysisPassType>(); });
}
template <typename OptimizationPassType, typename std::enable_if<
std::is_constructible<OptimizationPassType, IRBuilder*>::value, int>::type>
void registerOptimizationPass(IRBuilder* builder) {
PassRegistry::getPassRegistry().registerPass(&OptimizationPassType::ID,
[builder]() { return std::make_unique<OptimizationPassType>(builder); });
}
template <typename OptimizationPassType, typename std::enable_if<
!std::is_constructible<OptimizationPassType, IRBuilder*>::value, int>::type>
void registerOptimizationPass() {
PassRegistry::getPassRegistry().registerPass(&OptimizationPassType::ID,
[]() { return std::make_unique<OptimizationPassType>(); });
}
} // namespace sysy

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,505 @@
#include "SysYIRPrinter.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
#include "IR.h" // 确保IR.h包含了ArrayType、GetElementPtrInst等的定义
namespace sysy {
void SysYPrinter::printIR() {
const auto &functions = pModule->getFunctions();
//TODO: Print target datalayout and triple (minimal required by LLVM)
printGlobalVariable();
for (const auto &iter : functions) {
if (iter.second->getName() == "main") {
printFunction(iter.second.get());
break;
}
}
for (const auto &iter : functions) {
if (iter.second->getName() != "main") {
printFunction(iter.second.get());
}
}
}
std::string SysYPrinter::getTypeString(Type *type) {
if (type->isVoid()) {
return "void";
} else if (type->isInt()) {
return "i32";
} else if (type->isFloat()) {
return "float";
} else if (auto ptrType = dynamic_cast<PointerType*>(type)) {
// 递归打印指针指向的类型,然后加上 '*'
return getTypeString(ptrType->getBaseType()) + "*";
} else if (auto funcType = dynamic_cast<FunctionType*>(type)) {
// 对于函数类型,打印其返回类型
// 注意这里可能需要更完整的函数签名打印取决于你的IR表示方式
// 比如:`retType (paramType1, paramType2, ...)`
// 但为了简化和LLVM IR兼容性通常在定义时完整打印
return getTypeString(funcType->getReturnType());
} else if (auto arrayType = dynamic_cast<ArrayType*>(type)) { // 新增:处理数组类型
// 打印格式为 [num_elements x element_type]
return "[" + std::to_string(arrayType->getNumElements()) + " x " + getTypeString(arrayType->getElementType()) + "]";
}
assert(false && "Unsupported type");
return "";
}
std::string SysYPrinter::getValueName(Value *value) {
if (auto global = dynamic_cast<GlobalValue*>(value)) {
return "@" + global->getName();
} else if (auto inst = dynamic_cast<Instruction*>(value)) {
return "%" + inst->getName();
} else if (auto constInt = dynamic_cast<ConstantInteger*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constInt->getInt());
} else if (auto constFloat = dynamic_cast<ConstantFloating*>(value)) { // 优先匹配具体的常量类型
return std::to_string(constFloat->getFloat());
} else if (auto constUndef = dynamic_cast<UndefinedValue*>(value)) { // 如果有Undef类型
return "undef";
} else if (auto constVal = dynamic_cast<ConstantValue*>(value)) { // fallback for generic ConstantValue
// 这里的逻辑可能需要根据你ConstantValue的实际设计调整
// 确保它能处理所有可能的ConstantValue
if (constVal->getType()->isFloat()) {
return std::to_string(constVal->getFloat());
}
return std::to_string(constVal->getInt());
} else if (auto constVar = dynamic_cast<ConstantVariable*>(value)) {
return constVar->getName(); // 假设ConstantVariable有自己的名字或通过getByIndices获取值
} else if (auto argVar = dynamic_cast<Argument*>(value)) {
return "%" + argVar->getName(); // 假设ArgumentVariable有自己的名字
}
assert(false && "Unknown value type or unable to get value name");
return "";
}
std::string SysYPrinter::getBlockName(BasicBlock *block) {
static int blockId = 0; // 用于生成唯一的基本块ID
if (block->getName().empty()) {
return "bb" + std::to_string(blockId++); // 如果没有名字生成一个唯一的基本块ID
} else {
return block->getName();
}
}
void SysYPrinter::printType(Type *type) {
std::cout << getTypeString(type);
}
void SysYPrinter::printValue(Value *value) {
std::cout << getValueName(value);
}
void SysYPrinter::printGlobalVariable() {
auto &globals = pModule->getGlobals();
for (const auto &global : globals) {
std::cout << "@" << global->getName() << " = global ";
// 全局变量的类型是一个指针,指向其基类型 (可能是 ArrayType 或 Integer/FloatType)
auto globalVarBaseType = dynamic_cast<PointerType *>(global->getType())->getBaseType();
printType(globalVarBaseType); // 打印全局变量的实际类型 (例如 i32 或 [10 x i32])
std::cout << " ";
// 检查是否是数组类型 (通过检查 globalVarBaseType 是否是 ArrayType)
if (globalVarBaseType->isArray()) {
// 数组初始化器
std::cout << "["; // LLVM IR 数组初始化器格式: [type value, type value, ...]
auto values = global->getInitValues(); // 假设 getInitValues() 返回一个 ValueCounter
const std::vector<sysy::Value *> &counterValues = values.getValues(); // 获取所有值
for (size_t i = 0; i < counterValues.size(); i++) {
if (i > 0) std::cout << ", ";
// 打印元素类型,这个元素类型应该是数组的最终元素类型,例如 i32 或 float
// 可以从 globalVarBaseType 逐层剥离得到最终元素类型,但这里简化为直接从值获取
printType(counterValues[i]->getType());
std::cout << " ";
printValue(counterValues[i]);
}
std::cout << "]";
} else {
// 标量初始化器
// 假设标量全局变量的初始化值通过 getByIndex(0) 获取
Value* initVal = global->getByIndex(0);
printType(initVal->getType()); // 打印标量值的类型
std::cout << " ";
printValue(initVal); // 打印标量值
}
std::cout << ", align 4" << std::endl;
}
}
void SysYPrinter::printBlock(BasicBlock *block) {
std::cout << getBlockName(block);
}
void SysYPrinter::printFunction(Function *function) {
// Function signature
std::cout << "define ";
printType(function->getReturnType());
std::cout << " @" << function->getName() << "(";
auto entryBlock = function->getEntryBlock();
const auto &args_types = function->getParamTypes();
auto &args = function->getArguments();
int i = 0;
for (const auto &args_type : args_types) {
if (i > 0) std::cout << ", ";
printType(args_type);
std::cout << " %" << args[i]->getName();
i++;
}
std::cout << ") {" << std::endl;
// Function body
for (const auto &blockIter : function->getBasicBlocks()) {
// Basic block label
BasicBlock* blockPtr = blockIter.get();
if (!blockPtr->getName().empty()) {
std::cout << blockPtr->getName() << ":" << std::endl;
}
// Instructions
for (const auto &instIter : blockIter->getInstructions()) {
auto inst = instIter.get();
std::cout << " ";
printInst(inst);
}
}
std::cout << "}" << std::endl << std::endl;
}
void SysYPrinter::printInst(Instruction *pInst) {
using Kind = Instruction::Kind;
switch (pInst->getKind()) {
case Kind::kAdd:
case Kind::kSub:
case Kind::kMul:
case Kind::kDiv:
case Kind::kRem:
case Kind::kFAdd:
case Kind::kFSub:
case Kind::kFMul:
case Kind::kFDiv:
case Kind::kICmpEQ:
case Kind::kICmpNE:
case Kind::kICmpLT:
case Kind::kICmpGT:
case Kind::kICmpLE:
case Kind::kICmpGE:
case Kind::kFCmpEQ:
case Kind::kFCmpNE:
case Kind::kFCmpLT:
case Kind::kFCmpGT:
case Kind::kFCmpLE:
case Kind::kFCmpGE:
case Kind::kAnd:
case Kind::kOr: {
auto binInst = dynamic_cast<BinaryInst *>(pInst);
// Print result variable if exists
if (!binInst->getName().empty()) {
std::cout << "%" << binInst->getName() << " = ";
}
// Operation name
switch (pInst->getKind()) {
case Kind::kAdd: std::cout << "add"; break;
case Kind::kSub: std::cout << "sub"; break;
case Kind::kMul: std::cout << "mul"; break;
case Kind::kDiv: std::cout << "sdiv"; break;
case Kind::kRem: std::cout << "srem"; break;
case Kind::kFAdd: std::cout << "fadd"; break;
case Kind::kFSub: std::cout << "fsub"; break;
case Kind::kFMul: std::cout << "fmul"; break;
case Kind::kFDiv: std::cout << "fdiv"; break;
case Kind::kICmpEQ: std::cout << "icmp eq"; break;
case Kind::kICmpNE: std::cout << "icmp ne"; break;
case Kind::kICmpLT: std::cout << "icmp slt"; break; // LLVM uses slt/sgt for signed less/greater than
case Kind::kICmpGT: std::cout << "icmp sgt"; break;
case Kind::kICmpLE: std::cout << "icmp sle"; break;
case Kind::kICmpGE: std::cout << "icmp sge"; break;
case Kind::kFCmpEQ: std::cout << "fcmp oeq"; break; // oeq for ordered equal
case Kind::kFCmpNE: std::cout << "fcmp one"; break; // one for ordered not equal
case Kind::kFCmpLT: std::cout << "fcmp olt"; break; // olt for ordered less than
case Kind::kFCmpGT: std::cout << "fcmp ogt"; break; // ogt for ordered greater than
case Kind::kFCmpLE: std::cout << "fcmp ole"; break; // ole for ordered less than or equal
case Kind::kFCmpGE: std::cout << "fcmp oge"; break; // oge for ordered greater than or equal
case Kind::kAnd: std::cout << "and"; break;
case Kind::kOr: std::cout << "or"; break;
default: break; // Should not reach here
}
// Types and operands
std::cout << " ";
printType(binInst->getType());
std::cout << " ";
printValue(binInst->getLhs());
std::cout << ", ";
printValue(binInst->getRhs());
std::cout << std::endl;
} break;
case Kind::kNeg:
case Kind::kNot:
case Kind::kFNeg:
case Kind::kFtoI:
case Kind::kBitFtoI:
case Kind::kItoF:
case Kind::kBitItoF: {
auto unyInst = dynamic_cast<UnaryInst *>(pInst);
if (!unyInst->getName().empty()) {
std::cout << "%" << unyInst->getName() << " = ";
}
switch (pInst->getKind()) {
case Kind::kNeg: std::cout << "sub "; break; // integer negation is `sub i32 0, operand`
case Kind::kNot: std::cout << "xor "; break; // logical/bitwise NOT is `xor i32 -1, operand` or `xor i1 true, operand`
case Kind::kFNeg: std::cout << "fneg "; break; // float negation
case Kind::kFtoI: std::cout << "fptosi "; break; // float to signed integer
case Kind::kBitFtoI: std::cout << "bitcast "; break; // bitcast float to int
case Kind::kItoF: std::cout << "sitofp "; break; // signed integer to float
case Kind::kBitItoF: std::cout << "bitcast "; break; // bitcast int to float
default: break; // Should not reach here
}
printType(unyInst->getOperand()->getType()); // Print operand type
std::cout << " ";
// Special handling for integer negation and logical NOT
if (pInst->getKind() == Kind::kNeg) {
std::cout << "0, "; // for 'sub i32 0, operand'
} else if (pInst->getKind() == Kind::kNot) {
// For logical NOT (i1 -> i1), use 'xor i1 true, operand'
// For bitwise NOT (i32 -> i32), use 'xor i32 -1, operand'
if (unyInst->getOperand()->getType()->isInt()) { // Assuming i32 for bitwise NOT
std::cout << "NOT, "; // or specific bitmask for NOT
} else { // Assuming i1 for logical NOT
std::cout << "true, ";
}
}
printValue(pInst->getOperand(0));
// For type conversions (fptosi, sitofp, bitcast), need to specify destination type
if (pInst->getKind() == Kind::kFtoI || pInst->getKind() == Kind::kItoF ||
pInst->getKind() == Kind::kBitFtoI || pInst->getKind() == Kind::kBitItoF) {
std::cout << " to ";
printType(unyInst->getType()); // Print result type
}
std::cout << std::endl;
} break;
case Kind::kCall: {
auto callInst = dynamic_cast<CallInst *>(pInst);
auto function = callInst->getCallee();
if (!callInst->getName().empty()) {
std::cout << "%" << callInst->getName() << " = ";
}
std::cout << "call ";
printType(callInst->getType()); // Return type of the call
std::cout << " @" << function->getName() << "(";
auto params = callInst->getArguments();
bool first = true;
for (auto &param : params) {
if (!first) std::cout << ", ";
first = false;
printType(param->getValue()->getType()); // Type of argument
std::cout << " ";
printValue(param->getValue()); // Value of argument
}
std::cout << ")" << std::endl;
} break;
case Kind::kCondBr: {
auto condBrInst = dynamic_cast<CondBrInst *>(pInst);
std::cout << "br i1 "; // Condition type should be i1
printValue(condBrInst->getCondition());
std::cout << ", label %" << condBrInst->getThenBlock()->getName();
std::cout << ", label %" << condBrInst->getElseBlock()->getName();
std::cout << std::endl;
} break;
case Kind::kBr: {
auto brInst = dynamic_cast<UncondBrInst *>(pInst);
std::cout << "br label %" << brInst->getBlock()->getName();
std::cout << std::endl;
} break;
case Kind::kReturn: {
auto retInst = dynamic_cast<ReturnInst *>(pInst);
std::cout << "ret ";
if (retInst->getNumOperands() != 0) {
printType(retInst->getOperand(0)->getType());
std::cout << " ";
printValue(retInst->getOperand(0));
} else {
std::cout << "void";
}
std::cout << std::endl;
} break;
case Kind::kAlloca: {
auto allocaInst = dynamic_cast<AllocaInst *>(pInst);
std::cout << "%" << allocaInst->getName() << " = alloca ";
// AllocaInst 的类型现在应该是一个 PointerType指向正确的 ArrayType 或 ScalarType
// 例如alloca i32, align 4 或者 alloca [10 x i32], align 4
// auto allocatedType = dynamic_cast<PointerType *>(allocaInst->getType())->getBaseType();
auto allocatedType = allocaInst->getAllocatedType();
printType(allocatedType);
// 仍然打印维度信息,如果存在的话
if (allocaInst->getNumDims() > 0) {
std::cout << ", ";
for (size_t i = 0; i < allocaInst->getNumDims(); i++) {
if (i > 0) std::cout << ", ";
printType(Type::getIntType()); // 维度大小通常是 i32 类型
std::cout << " ";
printValue(allocaInst->getDim(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
case Kind::kLoad: {
auto loadInst = dynamic_cast<LoadInst *>(pInst);
std::cout << "%" << loadInst->getName() << " = load ";
printType(loadInst->getType()); // 加载的结果类型
std::cout << ", ";
printType(loadInst->getPointer()->getType()); // 指针类型
std::cout << " ";
printValue(loadInst->getPointer()); // 要加载的地址
// 仍然打印索引信息,如果存在的话
if (loadInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符,取决于你期望的格式
for (size_t i = 0; i < loadInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(loadInst->getIndex(i)->getType());
std::cout << " ";
printValue(loadInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
case Kind::kStore: {
auto storeInst = dynamic_cast<StoreInst *>(pInst);
std::cout << "store ";
printType(storeInst->getValue()->getType()); // 要存储的值的类型
std::cout << " ";
printValue(storeInst->getValue()); // 要存储的值
std::cout << ", ";
printType(storeInst->getPointer()->getType()); // 目标指针的类型
std::cout << " ";
printValue(storeInst->getPointer()); // 目标地址
// 仍然打印索引信息,如果存在的话
if (storeInst->getNumIndices() > 0) {
std::cout << ", indices "; // 或者其他分隔符
for (size_t i = 0; i < storeInst->getNumIndices(); i++) {
if (i > 0) std::cout << ", ";
printType(storeInst->getIndex(i)->getType());
std::cout << " ";
printValue(storeInst->getIndex(i));
}
}
std::cout << ", align 4" << std::endl;
} break;
case Kind::kGetElementPtr: { // 新增GetElementPtrInst 打印
auto gepInst = dynamic_cast<GetElementPtrInst*>(pInst);
std::cout << "%" << gepInst->getName() << " = getelementptr inbounds "; // 假设总是 inbounds
// GEP 的第一个操作数是基指针,其类型是一个指向聚合类型的指针
// 第一个参数是基指针所指向的聚合类型的类型 (e.g., [10 x i32])
auto basePtrType = dynamic_cast<PointerType*>(gepInst->getBasePointer()->getType());
printType(basePtrType->getBaseType()); // 打印基指针指向的类型
std::cout << ", ";
printType(gepInst->getBasePointer()->getType()); // 打印基指针自身的类型 (e.g., [10 x i32]*)
std::cout << " ";
printValue(gepInst->getBasePointer()); // 打印基指针
// 打印所有索引
for (auto indexVal : gepInst->getIndices()) { // 使用 getIndices() 迭代器
std::cout << ", ";
printType(indexVal->getValue()->getType()); // 打印索引的类型 (通常是 i32)
std::cout << " ";
printValue(indexVal->getValue()); // 打印索引值
}
std::cout << std::endl;
} break;
case Kind::kMemset: {
auto memsetInst = dynamic_cast<MemsetInst *>(pInst);
std::cout << "call void @llvm.memset.p0.";
printType(memsetInst->getPointer()->getType());
std::cout << "(";
printType(memsetInst->getPointer()->getType());
std::cout << " ";
printValue(memsetInst->getPointer());
std::cout << ", i8 ";
printValue(memsetInst->getValue());
std::cout << ", i32 ";
printValue(memsetInst->getSize());
std::cout << ", i1 false)" << std::endl; // alignment for memset is typically i1
} break;
case Kind::kPhi: {
auto phiInst = dynamic_cast<PhiInst *>(pInst);
// Phi 指令的名称通常是结果变量
std::cout << "%" << phiInst->getName() << " = phi ";
printType(phiInst->getType()); // Phi 结果类型
// Phi 指令的操作数是成对的 [value, basic_block]
// 这里假设 getOperands() 返回的是 (val1, block1, val2, block2...)
// 如果你的 PhiInst 存储方式是 getIncomingValues() 和 getIncomingBlocks(),请相应调整
// LLVM IR 格式: phi type [value1, block1], [value2, block2]
bool firstPair = true;
for (unsigned i = 0; i < phiInst->getNumIncomingValues(); ++i) { // 遍历成对的操作数
if (!firstPair) std::cout << ", ";
firstPair = false;
std::cout << "[ ";
printValue(phiInst->getValue(i));
std::cout << ", %";
printBlock(phiInst->getBlock(i));
std::cout << " ]";
}
std::cout << std::endl;
} break;
// 以下两个 Kind 应该删除或替换为 kGEP
// case Kind::kLa: { /* REMOVED */ } break;
// case Kind::kGetSubArray: { /* REMOVED */ } break;
default:
assert(false && "Unsupported instruction kind in SysYPrinter");
break;
}
}
} // namespace sysy