[midend]重构了src目录
This commit is contained in:
1554
src/include/midend/IR.h
Normal file
1554
src/include/midend/IR.h
Normal file
File diff suppressed because it is too large
Load Diff
404
src/include/midend/IRBuilder.h
Normal file
404
src/include/midend/IRBuilder.h
Normal file
@@ -0,0 +1,404 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "IR.h"
|
||||
|
||||
/**
|
||||
* @file IRBuilder.h
|
||||
*
|
||||
* @brief 定义IR构建器的头文件
|
||||
*/
|
||||
namespace sysy {
|
||||
|
||||
/**
|
||||
* @brief 中间IR的构建器
|
||||
*
|
||||
*/
|
||||
class IRBuilder {
|
||||
private:
|
||||
unsigned labelIndex; ///< 基本块标签编号
|
||||
unsigned tmpIndex; ///< 临时变量编号
|
||||
|
||||
BasicBlock *block; ///< 当前基本块
|
||||
BasicBlock::iterator position; ///< 当前基本块指令列表位置的迭代器
|
||||
|
||||
std::vector<BasicBlock *> trueBlocks; ///< true分支基本块列表
|
||||
std::vector<BasicBlock *> falseBlocks; ///< false分支基本块列表
|
||||
|
||||
std::vector<BasicBlock *> breakBlocks; ///< break目标块列表
|
||||
std::vector<BasicBlock *> continueBlocks; ///< continue目标块列表
|
||||
|
||||
public:
|
||||
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||
explicit IRBuilder(BasicBlock *block) : labelIndex(0), tmpIndex(0), block(block), position(block->end()) {}
|
||||
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
||||
: labelIndex(0), tmpIndex(0), block(block), position(position) {}
|
||||
|
||||
public:
|
||||
unsigned getLabelIndex() {
|
||||
labelIndex += 1;
|
||||
return labelIndex - 1;
|
||||
} ///< 获取基本块标签编号
|
||||
unsigned getTmpIndex() {
|
||||
tmpIndex += 1;
|
||||
return tmpIndex - 1;
|
||||
} ///< 获取临时变量编号
|
||||
BasicBlock * getBasicBlock() const { return block; } ///< 获取当前基本块
|
||||
BasicBlock * getBreakBlock() const { return breakBlocks.back(); } ///< 获取break目标块
|
||||
BasicBlock * popBreakBlock() {
|
||||
auto result = breakBlocks.back();
|
||||
breakBlocks.pop_back();
|
||||
return result;
|
||||
} ///< 弹出break目标块
|
||||
BasicBlock * getContinueBlock() const { return continueBlocks.back(); } ///< 获取continue目标块
|
||||
BasicBlock * popContinueBlock() {
|
||||
auto result = continueBlocks.back();
|
||||
continueBlocks.pop_back();
|
||||
return result;
|
||||
} ///< 弹出continue目标块
|
||||
|
||||
BasicBlock * getTrueBlock() const { return trueBlocks.back(); } ///< 获取true分支基本块
|
||||
BasicBlock * getFalseBlock() const { return falseBlocks.back(); } ///< 获取false分支基本块
|
||||
BasicBlock * popTrueBlock() {
|
||||
auto result = trueBlocks.back();
|
||||
trueBlocks.pop_back();
|
||||
return result;
|
||||
} ///< 弹出true分支基本块
|
||||
BasicBlock * popFalseBlock() {
|
||||
auto result = falseBlocks.back();
|
||||
falseBlocks.pop_back();
|
||||
return result;
|
||||
} ///< 弹出false分支基本块
|
||||
BasicBlock::iterator getPosition() const { return position; } ///< 获取当前基本块指令列表位置的迭代器
|
||||
void setPosition(BasicBlock *block, BasicBlock::iterator position) {
|
||||
this->block = block;
|
||||
this->position = position;
|
||||
} ///< 设置基本块和基本块指令列表位置的迭代器
|
||||
void setPosition(BasicBlock::iterator position) {
|
||||
this->position = position;
|
||||
} ///< 设置当前基本块指令列表位置的迭代器
|
||||
void pushBreakBlock(BasicBlock *block) { breakBlocks.push_back(block); } ///< 压入break目标基本块
|
||||
void pushContinueBlock(BasicBlock *block) { continueBlocks.push_back(block); } ///< 压入continue目标基本块
|
||||
void pushTrueBlock(BasicBlock *block) { trueBlocks.push_back(block); } ///< 压入true分支基本块
|
||||
void pushFalseBlock(BasicBlock *block) { falseBlocks.push_back(block); } ///< 压入false分支基本块
|
||||
|
||||
public:
|
||||
Instruction * insertInst(Instruction *inst) {
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 插入指令
|
||||
UnaryInst * createUnaryInst(Instruction::Kind kind, Type *type, Value *operand, const std::string &name = "") {
|
||||
std::string newName;
|
||||
if (name.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
auto inst = new UnaryInst(kind, type, operand, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建一元指令
|
||||
UnaryInst * createNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNeg, Type::getIntType(), operand, name);
|
||||
} ///< 创建取反指令
|
||||
UnaryInst * createNotInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNot, Type::getIntType(), operand, name);
|
||||
} ///< 创建取非指令
|
||||
UnaryInst * createFtoIInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFtoI, Type::getIntType(), operand, name);
|
||||
} ///< 创建浮点转整型指令
|
||||
UnaryInst * createBitFtoIInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kBitFtoI, Type::getIntType(), operand, name);
|
||||
} ///< 创建按位浮点转整型指令
|
||||
UnaryInst * createFNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFNeg, Type::getFloatType(), operand, name);
|
||||
} ///< 创建浮点取反指令
|
||||
UnaryInst * createFNotInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFNot, Type::getIntType(), operand, name);
|
||||
} ///< 创建浮点取非指令
|
||||
UnaryInst * createIToFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand, name);
|
||||
} ///< 创建整型转浮点指令
|
||||
UnaryInst * createBitItoFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kBitItoF, Type::getFloatType(), operand, name);
|
||||
} ///< 创建按位整型转浮点指令
|
||||
BinaryInst * createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
std::string newName;
|
||||
if (name.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
auto inst = new BinaryInst(kind, type, lhs, rhs, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建二元指令
|
||||
BinaryInst * createAddInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kAdd, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建加法指令
|
||||
BinaryInst * createSubInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSub, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建减法指令
|
||||
BinaryInst * createMulInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kMul, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建乘法指令
|
||||
BinaryInst * createDivInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kDiv, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建除法指令
|
||||
BinaryInst * createRemInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kRem, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建取余指令
|
||||
BinaryInst * createICmpEQInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpEQ, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建相等设置指令
|
||||
BinaryInst * createICmpNEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpNE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建不相等设置指令
|
||||
BinaryInst * createICmpLTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLT, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建小于设置指令
|
||||
BinaryInst * createICmpLEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建小于等于设置指令
|
||||
BinaryInst * createICmpGTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGT, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建大于设置指令
|
||||
BinaryInst * createICmpGEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建大于等于设置指令
|
||||
BinaryInst * createFAddInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFAdd, Type::getFloatType(), lhs, rhs, name);
|
||||
} ///< 创建浮点加法指令
|
||||
BinaryInst * createFSubInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFSub, Type::getFloatType(), lhs, rhs, name);
|
||||
} ///< 创建浮点减法指令
|
||||
BinaryInst * createFMulInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFMul, Type::getFloatType(), lhs, rhs, name);
|
||||
} ///< 创建浮点乘法指令
|
||||
BinaryInst * createFDivInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFDiv, Type::getFloatType(), lhs, rhs, name);
|
||||
} ///< 创建浮点除法指令
|
||||
BinaryInst * createFCmpEQInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpEQ, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点相等设置指令
|
||||
BinaryInst * createFCmpNEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpNE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点不相等设置指令
|
||||
BinaryInst * createFCmpLTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLT, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点小于设置指令
|
||||
BinaryInst * createFCmpLEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点小于等于设置指令
|
||||
BinaryInst * createFCmpGTInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGT, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点大于设置指令
|
||||
BinaryInst * createFCmpGEInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGE, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建浮点相大于等于设置指令
|
||||
BinaryInst * createAndInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kAnd, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建按位且指令
|
||||
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建按位或指令
|
||||
CallInst * createCallInst(Function *callee, const std::vector<Value *> &args, const std::string &name = "") {
|
||||
std::string newName;
|
||||
if (name.empty() && callee->getReturnType() != Type::getVoidType()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
auto inst = new CallInst(callee, args, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建Call指令
|
||||
ReturnInst * createReturnInst(Value *value = nullptr, const std::string &name = "") {
|
||||
auto inst = new ReturnInst(value, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建return指令
|
||||
UncondBrInst * createUncondBrInst(BasicBlock *thenBlock, const std::vector<Value *> &args) {
|
||||
auto inst = new UncondBrInst(thenBlock, args, block);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建无条件指令
|
||||
CondBrInst * createCondBrInst(Value *condition, BasicBlock *thenBlock, BasicBlock *elseBlock,
|
||||
const std::vector<Value *> &thenArgs, const std::vector<Value *> &elseArgs) {
|
||||
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, elseArgs, block);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建条件跳转指令
|
||||
AllocaInst * createAllocaInst(Type *type, const std::vector<Value *> &dims = {}, const std::string &name = "") {
|
||||
auto inst = new AllocaInst(type, dims, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建分配指令
|
||||
AllocaInst * createAllocaInstWithoutInsert(Type *type, const std::vector<Value *> &dims = {}, BasicBlock *parent = nullptr,
|
||||
const std::string &name = "") {
|
||||
auto inst = new AllocaInst(type, dims, parent, name);
|
||||
assert(inst);
|
||||
return inst;
|
||||
} ///< 创建不插入指令列表的分配指令[仅用于phi指令]
|
||||
LoadInst * createLoadInst(Value *pointer, const std::vector<Value *> &indices = {}, const std::string &name = "") {
|
||||
std::string newName;
|
||||
if (name.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
auto inst = new LoadInst(pointer, indices, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建load指令
|
||||
MemsetInst * createMemsetInst(Value *pointer, Value *begin, Value *size, Value *value, const std::string &name = "") {
|
||||
auto inst = new MemsetInst(pointer, begin, size, value, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建memset指令
|
||||
StoreInst * createStoreInst(Value *value, Value *pointer, const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new StoreInst(value, pointer, indices, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
} ///< 创建store指令
|
||||
PhiInst * createPhiInst(Type *type, const std::vector<Value*> &vals = {}, const std::vector<BasicBlock*> &blks = {}, const std::string &name = "") {
|
||||
std::string newName;
|
||||
if (name.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
auto inst = new PhiInst(type, vals, blks, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(block->begin(), inst);
|
||||
return inst;
|
||||
} ///< 创建Phi指令
|
||||
// GetElementPtrInst* createGetElementPtrInst(Value *basePointer,
|
||||
// const std::vector<Value *> &indices = {},
|
||||
// const std::string &name = "") {
|
||||
// std::string newName;
|
||||
// if (name.empty()) {
|
||||
// std::stringstream ss;
|
||||
// ss << tmpIndex;
|
||||
// newName = ss.str();
|
||||
// tmpIndex++;
|
||||
// } else {
|
||||
// newName = name;
|
||||
// }
|
||||
|
||||
// auto inst = new GetElementPtrInst(basePointer, indices, block, newName);
|
||||
// assert(inst);
|
||||
// block->getInstructions().emplace(position, inst);
|
||||
// return inst;
|
||||
// }
|
||||
/**
|
||||
* @brief 根据 LLVM 设计模式创建 GEP 指令。
|
||||
* 它会自动推断返回类型,无需手动指定。
|
||||
*/
|
||||
GetElementPtrInst *createGetElementPtrInst(Value *basePointer, const std::vector<Value *> &indices,
|
||||
const std::string &name = "") {
|
||||
Type *ResultElementType = getIndexedType(basePointer->getType(), indices);
|
||||
if (!ResultElementType) {
|
||||
assert(false && "Invalid GEP indexing!");
|
||||
return nullptr;
|
||||
}
|
||||
Type *ResultType = PointerType::get(ResultElementType);
|
||||
std::string newName;
|
||||
if (name.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << tmpIndex;
|
||||
newName = ss.str();
|
||||
tmpIndex++;
|
||||
} else {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
auto inst = new GetElementPtrInst(ResultType, basePointer, indices, block, newName);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
static Type *getIndexedType(Type *pointerType, const std::vector<Value *> &indices) {
|
||||
assert(pointerType->isPointer() && "base must be a pointer type!");
|
||||
// GEP 的类型推断从基指针所指向的类型开始。
|
||||
// 例如:
|
||||
// - 如果 pointerType 是 `[20 x [10 x i32]]*`,`currentWalkType` 初始为 `[20 x [10 x i32]]`。
|
||||
// - 如果 pointerType 是 `i32*`,`currentWalkType` 初始为 `i32`。
|
||||
// - 如果 pointerType 是 `i32**`,`currentWalkType` 初始为 `i32*`。
|
||||
Type *currentWalkType = pointerType->as<PointerType>()->getBaseType();
|
||||
|
||||
// 遍历所有索引来深入类型层次结构。
|
||||
// `indices` 向量包含了所有 GEP 索引,包括由 `visitLValue` 等函数添加的初始 `0` 索引。
|
||||
for (int i = 0; i < indices.size(); ++i) {
|
||||
if (currentWalkType->isArray()) {
|
||||
// 情况一:当前遍历类型是 `ArrayType`。
|
||||
// 索引用于选择数组元素,`currentWalkType` 更新为数组的元素类型。
|
||||
currentWalkType = currentWalkType->as<ArrayType>()->getElementType();
|
||||
} else if (currentWalkType->isPointer()) {
|
||||
// 情况二:当前遍历类型是 `PointerType`。
|
||||
// 这意味着我们正在通过一个指针来访问其指向的内存。
|
||||
// 索引用于选择该指针所指向的“数组”的元素。
|
||||
// `currentWalkType` 更新为该指针所指向的基础类型。
|
||||
// 例如:如果 `currentWalkType` 是 `i32*`,它将变为 `i32`。
|
||||
// 如果 `currentWalkType` 是 `[10 x i32]*`,它将变为 `[10 x i32]`。
|
||||
currentWalkType = currentWalkType->as<PointerType>()->getBaseType();
|
||||
} else {
|
||||
// 情况三:当前遍历类型是标量类型 (例如 `i32`, `float` 等非聚合、非指针类型)。
|
||||
//
|
||||
// 如果 `currentWalkType` 是标量,并且当前索引 `i` **不是** `indices` 向量中的最后一个索引,
|
||||
// 这意味着尝试对一个标量类型进行进一步的结构性索引,这是**无效的**。
|
||||
// 例如:`int x; x[0];` 对应的 GEP 链中,`x` 的类型是 `i32`,再加 `[0]` 索引就是错误。
|
||||
//
|
||||
// 如果 `currentWalkType` 是标量,且这是**最后一个索引** (`i == indices.size() - 1`),
|
||||
// 那么 GEP 是合法的,它只是计算一个偏移地址,最终的类型就是这个标量类型。
|
||||
// 此时 `currentWalkType` 保持不变,循环结束。
|
||||
if (i < indices.size() - 1) {
|
||||
assert(false && "Invalid GEP indexing: attempting to index into a non-aggregate/non-pointer type with further indices.");
|
||||
return nullptr; // 返回空指针表示类型推断失败
|
||||
}
|
||||
// 如果是最后一个索引,且当前类型是标量,则类型保持不变,这是合法的。
|
||||
// 循环会自然结束,返回正确的 `currentWalkType`。
|
||||
}
|
||||
}
|
||||
// 所有索引处理完毕后,`currentWalkType` 就是 GEP 指令最终计算出的地址所指向的元素的类型。
|
||||
return currentWalkType;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
55
src/include/midend/Pass/Analysis/Dom.h
Normal file
55
src/include/midend/Pass/Analysis/Dom.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h" // 包含 Pass 框架
|
||||
#include "IR.h" // 包含 IR 定义
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 支配树分析结果类 (保持不变)
|
||||
class DominatorTree : public AnalysisResultBase {
|
||||
public:
|
||||
DominatorTree(Function* F);
|
||||
const std::set<BasicBlock*>* getDominators(BasicBlock* BB) const;
|
||||
BasicBlock* getImmediateDominator(BasicBlock* BB) const;
|
||||
const std::set<BasicBlock*>* getDominanceFrontier(BasicBlock* BB) const;
|
||||
const std::set<BasicBlock*>* getDominatorTreeChildren(BasicBlock* BB) const;
|
||||
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominatorsMap() const { return Dominators; }
|
||||
const std::map<BasicBlock*, BasicBlock*>& getIDomsMap() const { return IDoms; }
|
||||
const std::map<BasicBlock*, std::set<BasicBlock*>>& getDominanceFrontiersMap() const { return DominanceFrontiers; }
|
||||
void computeDominators(Function* F);
|
||||
void computeIDoms(Function* F);
|
||||
void computeDominanceFrontiers(Function* F);
|
||||
void computeDominatorTreeChildren(Function* F);
|
||||
private:
|
||||
Function* AssociatedFunction;
|
||||
std::map<BasicBlock*, std::set<BasicBlock*>> Dominators;
|
||||
std::map<BasicBlock*, BasicBlock*> IDoms;
|
||||
std::map<BasicBlock*, std::set<BasicBlock*>> DominanceFrontiers;
|
||||
std::map<BasicBlock*, std::set<BasicBlock*>> DominatorTreeChildren;
|
||||
};
|
||||
|
||||
|
||||
// 支配树分析遍
|
||||
class DominatorTreeAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
DominatorTreeAnalysisPass() : AnalysisPass("DominatorTreeAnalysis", Pass::Granularity::Function) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
bool runOnFunction(Function* F, AnalysisManager &AM) override;
|
||||
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<DominatorTree> CurrentDominatorTree;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
72
src/include/midend/Pass/Analysis/Liveness.h
Normal file
72
src/include/midend/Pass/Analysis/Liveness.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h" // 包含 IR 定义
|
||||
#include "Pass.h" // 包含 Pass 框架
|
||||
#include <algorithm> // for std::set_union, std::set_difference
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
class Value;
|
||||
class Instruction;
|
||||
|
||||
// 活跃变量分析结果类
|
||||
// 它将包含 LiveIn 和 LiveOut 集合
|
||||
class LivenessAnalysisResult : public AnalysisResultBase {
|
||||
public:
|
||||
LivenessAnalysisResult(Function *F) : AssociatedFunction(F) {}
|
||||
|
||||
// 获取给定基本块的 LiveIn 集合
|
||||
const std::set<Value *> *getLiveIn(BasicBlock *BB) const;
|
||||
|
||||
// 获取给定基本块的 LiveOut 集合
|
||||
const std::set<Value *> *getLiveOut(BasicBlock *BB) const;
|
||||
|
||||
// 暴露内部数据结构,如果需要更直接的访问
|
||||
const std::map<BasicBlock *, std::set<Value *>> &getLiveInSets() const { return liveInSets; }
|
||||
const std::map<BasicBlock *, std::set<Value *>> &getLiveOutSets() const { return liveOutSets; }
|
||||
|
||||
// 核心计算方法,由 LivenessAnalysisPass 调用
|
||||
void computeLiveness(Function *F);
|
||||
|
||||
private:
|
||||
Function *AssociatedFunction; // 这个活跃变量分析是为哪个函数计算的
|
||||
std::map<BasicBlock *, std::set<Value *>> liveInSets;
|
||||
std::map<BasicBlock *, std::set<Value *>> liveOutSets;
|
||||
|
||||
// 辅助函数:计算基本块的 Def 和 Use 集合
|
||||
// Def: 块内定义,且定义在所有使用之前的值
|
||||
// Use: 块内使用,且使用在所有定义之前的值
|
||||
void computeDefUse(BasicBlock *BB, std::set<Value *> &def, std::set<Value *> &use);
|
||||
};
|
||||
|
||||
// 活跃变量分析遍
|
||||
class LivenessAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID; // LLVM 风格的唯一 ID
|
||||
|
||||
LivenessAnalysisPass() : AnalysisPass("LivenessAnalysis", Pass::Granularity::Function) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
// 运行分析并返回结果。现在接受 AnalysisManager& AM 参数
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
|
||||
// 获取分析结果的指针。
|
||||
// 注意:AnalysisManager 将会调用此方法来获取结果并进行缓存。
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override;
|
||||
|
||||
private:
|
||||
// 存储当前分析计算出的 LivenessAnalysisResult 实例
|
||||
// runOnFunction 每次调用都会创建新的 LivenessAnalysisResult 对象
|
||||
std::unique_ptr<LivenessAnalysisResult> CurrentLivenessResult;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
63
src/include/midend/Pass/Optimize/DCE.h
Normal file
63
src/include/midend/Pass/Optimize/DCE.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include "Dom.h"
|
||||
#include <unordered_set>
|
||||
#include <queue>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明分析结果类,确保在需要时可以引用
|
||||
// class DominatorTreeAnalysisResult; // Pass.h 中已包含,这里不再需要
|
||||
class SideEffectInfoAnalysisResult; // 假设有副作用分析结果类
|
||||
|
||||
// DCEContext 类,用于封装DCE的内部逻辑和状态
|
||||
// 这样可以避免静态变量在多线程或多次运行时的冲突,并保持代码的模块化
|
||||
class DCEContext {
|
||||
public:
|
||||
// 运行DCE的主要方法
|
||||
// func: 当前要优化的函数
|
||||
// tp: 分析管理器,用于获取其他分析结果(如果需要)
|
||||
void run(Function* func, AnalysisManager* AM, bool &changed);
|
||||
|
||||
private:
|
||||
// 存储活跃指令的集合
|
||||
std::unordered_set<Instruction*> alive_insts;
|
||||
|
||||
// 判断指令是否是“天然活跃”的(即总是保留的)
|
||||
// inst: 要检查的指令
|
||||
// 返回值: 如果指令是天然活跃的,则为true,否则为false
|
||||
bool isAlive(Instruction* inst);
|
||||
|
||||
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
|
||||
// inst: 要标记为活跃的指令
|
||||
void addAlive(Instruction* inst);
|
||||
};
|
||||
|
||||
// DCE 优化遍类,继承自 OptimizationPass
|
||||
class DCE : public OptimizationPass {
|
||||
public:
|
||||
// 构造函数
|
||||
DCE() : OptimizationPass("DCE", Granularity::Function) {}
|
||||
|
||||
// 静态成员,作为该遍的唯一ID
|
||||
static void *ID;
|
||||
|
||||
// 运行在函数上的优化逻辑
|
||||
// F: 当前要优化的函数
|
||||
// AM: 分析管理器,用于获取或使分析结果失效
|
||||
// 返回值: 如果IR被修改,则为true,否则为false
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
|
||||
// 声明该遍的分析依赖和失效信息
|
||||
// analysisDependencies: 该遍运行前需要哪些分析结果
|
||||
// analysisInvalidations: 该遍运行后会使哪些分析结果失效
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||
|
||||
// Pass 基类中的纯虚函数,必须实现
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
118
src/include/midend/Pass/Optimize/Mem2Reg.h
Normal file
118
src/include/midend/Pass/Optimize/Mem2Reg.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h" // 包含Pass的基类定义
|
||||
#include "IR.h" // 包含IR相关的定义,如Instruction, Function, BasicBlock, AllocaInst, LoadInst, StoreInst, PhiInst等
|
||||
#include "Dom.h" // 假设支配树分析的头文件,提供 DominatorTreeAnalysisResult
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <queue>
|
||||
#include <stack> // 用于变量重命名阶段的SSA值栈
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明分析结果类,确保在需要时可以引用
|
||||
class DominatorTree;
|
||||
|
||||
// Mem2RegContext 类,封装 mem2reg 遍的核心逻辑和状态
|
||||
// 这样可以避免静态变量在多线程或多次运行时的冲突,并保持代码的模块化
|
||||
class Mem2RegContext {
|
||||
public:
|
||||
|
||||
Mem2RegContext(IRBuilder *builder) : builder(builder) {}
|
||||
// 运行 mem2reg 优化的主要方法
|
||||
// func: 当前要优化的函数
|
||||
// tp: 分析管理器,用于获取支配树等分析结果
|
||||
void run(Function* func, AnalysisManager* tp);
|
||||
|
||||
private:
|
||||
IRBuilder *builder; // IR 构建器,用于插入指令
|
||||
// 存储所有需要被提升的 AllocaInst
|
||||
std::vector<AllocaInst*> promotableAllocas;
|
||||
|
||||
// 存储每个 AllocaInst 对应的 Phi 指令列表
|
||||
// 键是 AllocaInst,值是该 AllocaInst 在各个基本块中插入的 Phi 指令的列表
|
||||
// (实际上,一个 AllocaInst 在一个基本块中只会有一个 Phi)
|
||||
std::unordered_map<AllocaInst*, std::unordered_map<BasicBlock*, PhiInst*>> allocaToPhiMap;
|
||||
|
||||
// 存储每个 AllocaInst 对应的当前活跃 SSA 值栈
|
||||
// 用于在变量重命名阶段追踪每个 AllocaInst 在不同控制流路径上的最新值
|
||||
std::unordered_map<AllocaInst*, std::stack<Value*>> allocaToValueStackMap;
|
||||
|
||||
// 辅助映射,存储每个 AllocaInst 的所有 store 指令
|
||||
std::unordered_map<AllocaInst*, std::unordered_set<StoreInst*>> allocaToStoresMap;
|
||||
|
||||
// 辅助映射,存储每个 AllocaInst 对应的定义基本块(包含 store 指令的块)
|
||||
std::unordered_map<AllocaInst*, std::unordered_set<BasicBlock*>> allocaToDefBlocksMap;
|
||||
|
||||
// 支配树分析结果,用于 Phi 插入和变量重命名
|
||||
DominatorTree* dt;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段1: 识别可提升的 AllocaInst
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 判断一个 AllocaInst 是否可以被提升到寄存器
|
||||
// alloca: 要检查的 AllocaInst
|
||||
// 返回值: 如果可以提升,则为 true,否则为 false
|
||||
bool isPromotableAlloca(AllocaInst* alloca);
|
||||
|
||||
// 收集所有对给定 AllocaInst 进行存储的 StoreInst
|
||||
// alloca: 目标 AllocaInst
|
||||
void collectStores(AllocaInst* alloca);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段2: 插入 Phi 指令 (Phi Insertion)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 为给定的 AllocaInst 插入必要的 Phi 指令
|
||||
// alloca: 目标 AllocaInst
|
||||
// defBlocks: 包含对该 AllocaInst 进行 store 操作的基本块集合
|
||||
void insertPhis(AllocaInst* alloca, const std::unordered_set<BasicBlock*>& defBlocks);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段3: 变量重命名 (Variable Renaming)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 对支配树进行深度优先遍历,重命名变量并替换 load/store 指令
|
||||
// alloca: 当前正在处理的 AllocaInst
|
||||
// currentBB: 当前正在遍历的基本块
|
||||
// dt: 支配树分析结果
|
||||
// valueStack: 存储当前 AllocaInst 在当前路径上可见的 SSA 值栈
|
||||
void renameVariables(AllocaInst* alloca, BasicBlock* currentBB);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// 阶段4: 清理
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// 删除所有原始的 AllocaInst、LoadInst 和 StoreInst
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
// Mem2Reg 优化遍类,继承自 OptimizationPass
|
||||
// 粒度为 Function,表示它在每个函数上独立运行
|
||||
class Mem2Reg : public OptimizationPass {
|
||||
private:
|
||||
IRBuilder *builder;
|
||||
|
||||
public:
|
||||
// 构造函数
|
||||
Mem2Reg(IRBuilder *builder) : OptimizationPass("Mem2Reg", Granularity::Function), builder(builder) {}
|
||||
|
||||
// 静态成员,作为该遍的唯一ID
|
||||
static void *ID;
|
||||
|
||||
// 运行在函数上的优化逻辑
|
||||
// F: 当前要优化的函数
|
||||
// AM: 分析管理器,用于获取支配树等分析结果,或使分析结果失效
|
||||
// 返回值: 如果IR被修改,则为true,否则为false
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
|
||||
// 声明该遍的分析依赖和失效信息
|
||||
// analysisDependencies: 该遍运行前需要哪些分析结果
|
||||
// analysisInvalidations: 该遍运行后会使哪些分析结果失效
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
59
src/include/midend/Pass/Optimize/Reg2Mem.h
Normal file
59
src/include/midend/Pass/Optimize/Reg2Mem.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h" // 你的 IR Builder
|
||||
#include "Liveness.h"
|
||||
#include "Dom.h"
|
||||
#include "Pass.h" // 你的 Pass 框架基类
|
||||
#include <iostream> // 调试用
|
||||
#include <map> // 用于 Value 到 AllocaInst 的映射
|
||||
#include <set> // 可能用于其他辅助集合
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class Reg2MemContext {
|
||||
public:
|
||||
Reg2MemContext(IRBuilder *b) : builder(b) {}
|
||||
|
||||
// 运行 Reg2Mem 优化
|
||||
void run(Function *func);
|
||||
|
||||
private:
|
||||
IRBuilder *builder; // IR 构建器
|
||||
|
||||
// 存储 SSA Value 到对应的 AllocaInst 的映射
|
||||
// 只有那些需要被"溢出"到内存的 SSA 值才会被记录在这里
|
||||
std::map<Value *, AllocaInst *> valueToAllocaMap;
|
||||
|
||||
// 辅助函数:
|
||||
// 1. 识别并为 SSA Value 分配 AllocaInst
|
||||
void allocateMemoryForSSAValues(Function *func);
|
||||
|
||||
// 2. 将 SSA 值的使用替换为 Load/Store
|
||||
void insertLoadsAndStores(Function *func);
|
||||
|
||||
// 3. 处理 Phi 指令,将其转换为 Load/Store
|
||||
void rewritePhis(Function *func);
|
||||
|
||||
// 4. 清理 (例如,可能删除不再需要的 Phi 指令)
|
||||
void cleanup(Function *func);
|
||||
|
||||
// 判断一个 Value 是否是 AllocaInst 可以为其分配内存的目标
|
||||
// 通常指非指针类型的Instruction结果和Argument
|
||||
bool isPromotableToMemory(Value *val);
|
||||
};
|
||||
|
||||
class Reg2Mem : public OptimizationPass {
|
||||
private:
|
||||
IRBuilder *builder; ///< IR构建器,用于插入指令
|
||||
public:
|
||||
static void *ID; ///< Pass的唯一标识符
|
||||
Reg2Mem(IRBuilder* builder) : OptimizationPass("Reg2Mem", Pass::Granularity::Function), builder(builder) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||
void *getPassID() const override { return &ID; } ///< 获取 Pass ID
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
196
src/include/midend/Pass/Optimize/SCCP.h
Normal file
196
src/include/midend/Pass/Optimize/SCCP.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 稀疏条件常量传播类
|
||||
// Sparse Conditional Constant Propagation
|
||||
/*
|
||||
伪代码
|
||||
function SCCP_Optimization(Module):
|
||||
for each Function in Module:
|
||||
changed = true
|
||||
while changed:
|
||||
changed = false
|
||||
// 阶段1: 常量传播与折叠
|
||||
changed |= PropagateConstants(Function)
|
||||
// 阶段2: 控制流简化
|
||||
changed |= SimplifyControlFlow(Function)
|
||||
end while
|
||||
end for
|
||||
|
||||
function PropagateConstants(Function):
|
||||
// 初始化
|
||||
executableBlocks = {entryBlock}
|
||||
valueState = map<Value, State> // 值->状态映射
|
||||
instWorkList = Queue()
|
||||
edgeWorkList = Queue()
|
||||
|
||||
// 初始化工作列表
|
||||
for each inst in entryBlock:
|
||||
instWorkList.push(inst)
|
||||
|
||||
// 迭代处理
|
||||
while !instWorkList.empty() || !edgeWorkList.empty():
|
||||
// 处理指令工作列表
|
||||
while !instWorkList.empty():
|
||||
inst = instWorkList.pop()
|
||||
// 如果指令是可执行基本块中的
|
||||
if executableBlocks.contains(inst.parent):
|
||||
ProcessInstruction(inst)
|
||||
|
||||
// 处理边工作列表
|
||||
while !edgeWorkList.empty():
|
||||
edge = edgeWorkList.pop()
|
||||
ProcessEdge(edge)
|
||||
|
||||
// 应用常量替换
|
||||
for each inst in Function:
|
||||
if valueState[inst] == CONSTANT:
|
||||
ReplaceWithConstant(inst, valueState[inst].constant)
|
||||
changed = true
|
||||
|
||||
return changed
|
||||
|
||||
function ProcessInstruction(Instruction inst):
|
||||
switch inst.type:
|
||||
//二元操作
|
||||
case BINARY_OP:
|
||||
lhs = GetValueState(inst.operands[0])
|
||||
rhs = GetValueState(inst.operands[1])
|
||||
if lhs == CONSTANT && rhs == CONSTANT:
|
||||
newState = ComputeConstant(inst.op, lhs.value, rhs.value)
|
||||
UpdateState(inst, newState)
|
||||
else if lhs == BOTTOM || rhs == BOTTOM:
|
||||
UpdateState(inst, BOTTOM)
|
||||
//phi
|
||||
case PHI:
|
||||
mergedState = ⊤
|
||||
for each incoming in inst.incomings:
|
||||
// 检查每个输入的状态
|
||||
if executableBlocks.contains(incoming.block):
|
||||
incomingState = GetValueState(incoming.value)
|
||||
mergedState = Meet(mergedState, incomingState)
|
||||
UpdateState(inst, mergedState)
|
||||
// 条件分支
|
||||
case COND_BRANCH:
|
||||
cond = GetValueState(inst.condition)
|
||||
if cond == CONSTANT:
|
||||
// 判断条件分支
|
||||
if cond.value == true:
|
||||
AddEdgeToWorkList(inst.parent, inst.trueTarget)
|
||||
else:
|
||||
AddEdgeToWorkList(inst.parent, inst.falseTarget)
|
||||
else if cond == BOTTOM:
|
||||
AddEdgeToWorkList(inst.parent, inst.trueTarget)
|
||||
AddEdgeToWorkList(inst.parent, inst.falseTarget)
|
||||
|
||||
case UNCOND_BRANCH:
|
||||
AddEdgeToWorkList(inst.parent, inst.target)
|
||||
|
||||
// 其他指令处理...
|
||||
|
||||
function ProcessEdge(Edge edge):
|
||||
fromBB, toBB = edge
|
||||
if !executableBlocks.contains(toBB):
|
||||
executableBlocks.add(toBB)
|
||||
for each inst in toBB:
|
||||
if inst is PHI:
|
||||
instWorkList.push(inst)
|
||||
else:
|
||||
instWorkList.push(inst) // 非PHI指令
|
||||
|
||||
// 更新PHI节点的输入
|
||||
for each phi in toBB.phis:
|
||||
instWorkList.push(phi)
|
||||
|
||||
function SimplifyControlFlow(Function):
|
||||
changed = false
|
||||
// 标记可达基本块
|
||||
ReachableBBs = FindReachableBlocks(Function.entry)
|
||||
|
||||
// 删除不可达块
|
||||
for each bb in Function.blocks:
|
||||
if !ReachableBBs.contains(bb):
|
||||
RemoveDeadBlock(bb)
|
||||
changed = true
|
||||
|
||||
// 简化条件分支
|
||||
for each bb in Function.blocks:
|
||||
terminator = bb.terminator
|
||||
if terminator is COND_BRANCH:
|
||||
cond = GetValueState(terminator.condition)
|
||||
if cond == CONSTANT:
|
||||
SimplifyBranch(terminator, cond.value)
|
||||
changed = true
|
||||
|
||||
return changed
|
||||
|
||||
function RemoveDeadBlock(BasicBlock bb):
|
||||
// 1. 更新前驱块的分支指令
|
||||
for each pred in bb.predecessors:
|
||||
UpdateTerminator(pred, bb)
|
||||
|
||||
// 2. 更新后继块的PHI节点
|
||||
for each succ in bb.successors:
|
||||
RemovePhiIncoming(succ, bb)
|
||||
|
||||
// 3. 删除块内所有指令
|
||||
for each inst in bb.instructions:
|
||||
inst.remove()
|
||||
|
||||
// 4. 从函数中移除基本块
|
||||
Function.removeBlock(bb)
|
||||
|
||||
function Meet(State a, State b):
|
||||
if a == ⊤: return b
|
||||
if b == ⊤: return a
|
||||
if a == ⊥ || b == ⊥: return ⊥
|
||||
if a.value == b.value: return a
|
||||
return ⊥
|
||||
|
||||
function UpdateState(Value v, State newState):
|
||||
oldState = valueState.get(v, ⊤)
|
||||
if newState != oldState:
|
||||
valueState[v] = newState
|
||||
for each user in v.users:
|
||||
if user is Instruction:
|
||||
instWorkList.push(user)
|
||||
|
||||
*/
|
||||
|
||||
enum class LatticeValue {
|
||||
Top, // ⊤ (Unknown)
|
||||
Constant, // c (Constant)
|
||||
Bottom // ⊥ (Undefined / Varying)
|
||||
};
|
||||
// LatticeValue: 用于表示值的状态,Top表示未知,Constant表示常量,Bottom表示未定义或变化的值。
|
||||
// 这里的LatticeValue用于跟踪每个SSA值(变量、指令结果)的状态,
|
||||
// 以便在SCCP过程中进行常量传播和控制流简化。
|
||||
|
||||
//TODO: 下列数据结构考虑集成到类中,避免重命名问题
|
||||
static std::set<Instruction *> Worklist;
|
||||
static std::unordered_set<BasicBlock*> Executable_Blocks;
|
||||
static std::queue<std::pair<BasicBlock *, BasicBlock *> > Executable_Edges;
|
||||
static std::map<Value*, LatticeValue> valueState;
|
||||
|
||||
class SCCP {
|
||||
private:
|
||||
Module *pModule;
|
||||
|
||||
public:
|
||||
SCCP(Module *pMoudle) : pModule(pMoudle) {}
|
||||
|
||||
void run();
|
||||
bool PropagateConstants(Function *function);
|
||||
bool SimplifyControlFlow(Function *function);
|
||||
void ProcessInstruction(Instruction *inst);
|
||||
void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
|
||||
void RemoveDeadBlock(BasicBlock *bb);
|
||||
void UpdateState(Value *v, LatticeValue newState);
|
||||
LatticeValue Meet(LatticeValue a, LatticeValue b);
|
||||
LatticeValue GetValueState(Value *v);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
101
src/include/midend/Pass/Optimize/SysYIRCFGOpt.h
Normal file
101
src/include/midend/Pass/Optimize/SysYIRCFGOpt.h
Normal file
@@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include "Pass.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 优化前对SysY IR的预处理,也可以视作部分CFG优化
|
||||
// 主要包括删除无用指令、合并基本块、删除空块等
|
||||
// 这些操作可以在SysY IR生成时就完成,但为了简化IR生成过程,
|
||||
// 这里将其放在SysY IR生成后进行预处理
|
||||
// 同时兼容phi节点的处理,可以再mem2reg后再次调用优化
|
||||
|
||||
//TODO: 可增加的CFG优化和方法
|
||||
// - 检查基本块跳转关系正确性
|
||||
// - 简化条件分支(Branch Simplification),如条件恒真/恒假转为直接跳转
|
||||
// - 合并连续的跳转指令(Jump Threading)在合并不可达块中似乎已经实现了
|
||||
// - 基本块重排序(Block Reordering),提升局部性
|
||||
|
||||
// 辅助工具类,包含实际的CFG优化逻辑
|
||||
// 这些方法可以被独立的Pass调用
|
||||
class SysYCFGOptUtils {
|
||||
public:
|
||||
static bool SysYDelInstAfterBr(Function *func); // 删除br后面的指令
|
||||
static bool SysYDelEmptyBlock(Function *func, IRBuilder* pBuilder); // 空块删除
|
||||
static bool SysYDelNoPreBLock(Function *func); // 删除无前驱块(不可达块)
|
||||
static bool SysYBlockMerge(Function *func); // 合并基本块
|
||||
static bool SysYAddReturn(Function *func, IRBuilder* pBuilder); // 添加return指令
|
||||
static bool SysYCondBr2Br(Function *func, IRBuilder* pBuilder); // 条件分支转换为无条件分支
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// 独立的CFG优化遍
|
||||
// ======================================================================
|
||||
|
||||
class SysYDelInstAfterBrPass : public OptimizationPass {
|
||||
public:
|
||||
static void *ID; // 唯一ID
|
||||
SysYDelInstAfterBrPass() : OptimizationPass("SysYDelInstAfterBrPass", Granularity::Function) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {
|
||||
// 这个优化可能改变CFG结构,使一些CFG相关的分析失效
|
||||
// 可以在这里指定哪些分析会失效,例如支配树、活跃变量等
|
||||
// analysisInvalidations.insert(DominatorTreeAnalysisPass::ID); // 示例
|
||||
}
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
class SysYDelEmptyBlockPass : public OptimizationPass {
|
||||
private:
|
||||
IRBuilder *pBuilder;
|
||||
public:
|
||||
static void *ID;
|
||||
SysYDelEmptyBlockPass(IRBuilder *builder) : OptimizationPass("SysYDelEmptyBlockPass", Granularity::Function), pBuilder(builder) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {};
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
class SysYDelNoPreBLockPass : public OptimizationPass {
|
||||
public:
|
||||
static void *ID;
|
||||
SysYDelNoPreBLockPass() : OptimizationPass("SysYDelNoPreBLockPass", Granularity::Function) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {};
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
class SysYBlockMergePass : public OptimizationPass {
|
||||
public:
|
||||
static void *ID;
|
||||
SysYBlockMergePass() : OptimizationPass("SysYBlockMergePass", Granularity::Function) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {};
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
class SysYAddReturnPass : public OptimizationPass {
|
||||
private:
|
||||
IRBuilder *pBuilder;
|
||||
public:
|
||||
static void *ID;
|
||||
SysYAddReturnPass(IRBuilder *builder) : OptimizationPass("SysYAddReturnPass", Granularity::Function), pBuilder(builder) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {};
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
class SysYCondBr2BrPass : public OptimizationPass {
|
||||
private:
|
||||
IRBuilder *pBuilder;
|
||||
public:
|
||||
static void *ID;
|
||||
SysYCondBr2BrPass(IRBuilder *builder) : OptimizationPass("SysYCondBr2BrPass", Granularity::Function), pBuilder(builder) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager& AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override {};
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
33
src/include/midend/Pass/Optimize/SysYIROptUtils.h
Normal file
33
src/include/midend/Pass/Optimize/SysYIROptUtils.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 优化工具类,包含一些通用的优化方法
|
||||
// 这些方法可以在不同的优化 pass 中复用
|
||||
// 例如:删除use关系,判断是否是全局变量等
|
||||
class SysYIROptUtils{
|
||||
|
||||
public:
|
||||
// 仅仅删除use关系
|
||||
static void usedelete(Instruction *instr) {
|
||||
for (auto &use : instr->getOperands()) {
|
||||
Value* val = use->getValue();
|
||||
val->removeUse(use);
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否是全局变量
|
||||
static bool isGlobal(Value *val) {
|
||||
auto gval = dynamic_cast<GlobalValue *>(val);
|
||||
return gval != nullptr;
|
||||
}
|
||||
// 判断是否是数组
|
||||
static bool isArr(Value *val) {
|
||||
auto aval = dynamic_cast<AllocaInst *>(val);
|
||||
return aval != nullptr && aval->getNumDims() != 0;
|
||||
}
|
||||
};
|
||||
|
||||
}// namespace sysy
|
||||
324
src/include/midend/Pass/Pass.h
Normal file
324
src/include/midend/Pass/Pass.h
Normal file
@@ -0,0 +1,324 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional> // For std::function
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <typeindex> // For std::type_index (although void* ID is more common in LLVM)
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
|
||||
extern int DEBUG; // 全局调试标志
|
||||
|
||||
namespace sysy {
|
||||
|
||||
//前向声明
|
||||
class PassManager;
|
||||
class AnalysisManager;
|
||||
|
||||
// 抽象基类:分析结果
|
||||
class AnalysisResultBase {
|
||||
public:
|
||||
virtual ~AnalysisResultBase() = default;
|
||||
};
|
||||
|
||||
// 抽象基类:Pass
|
||||
class Pass {
|
||||
public:
|
||||
enum class Granularity { Module, Function, BasicBlock };
|
||||
|
||||
enum class PassKind { Analysis, Optimization };
|
||||
|
||||
Pass(const std::string &name, Granularity g, PassKind k) : Name(name), G(g), K(k) {}
|
||||
virtual ~Pass() = default;
|
||||
|
||||
const std::string &getName() const { return Name; }
|
||||
Granularity getGranularity() const { return G; }
|
||||
PassKind getPassKind() const { return K; }
|
||||
|
||||
virtual bool runOnModule(Module *M, AnalysisManager& AM) { return false; }
|
||||
virtual bool runOnFunction(Function *F, AnalysisManager& AM) { return false; }
|
||||
virtual bool runOnBasicBlock(BasicBlock *BB, AnalysisManager& AM) { return false; }
|
||||
|
||||
// 所有 Pass 都必须提供一个唯一的 ID
|
||||
// 这通常是一个静态成员,并在 Pass 类外部定义
|
||||
virtual void *getPassID() const = 0;
|
||||
|
||||
protected:
|
||||
std::string Name;
|
||||
Granularity G;
|
||||
PassKind K;
|
||||
};
|
||||
|
||||
// 抽象基类:分析遍
|
||||
class AnalysisPass : public Pass {
|
||||
public:
|
||||
AnalysisPass(const std::string &name, Granularity g) : Pass(name, g, PassKind::Analysis) {}
|
||||
|
||||
virtual std::unique_ptr<AnalysisResultBase> getResult() = 0;
|
||||
};
|
||||
|
||||
// 抽象基类:优化遍
|
||||
class OptimizationPass : public Pass {
|
||||
public:
|
||||
OptimizationPass(const std::string &name, Granularity g) : Pass(name, g, PassKind::Optimization) {}
|
||||
|
||||
virtual void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||
// 默认不依赖也不修改任何分析
|
||||
}
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// PassRegistry: 全局 Pass 注册表 (单例)
|
||||
// ======================================================================
|
||||
class PassRegistry {
|
||||
public:
|
||||
// Pass 工厂函数类型:返回 Pass 的唯一指针
|
||||
using PassFactory = std::function<std::unique_ptr<Pass>()>;
|
||||
|
||||
// 获取 PassRegistry 实例 (单例模式)
|
||||
static PassRegistry &getPassRegistry() {
|
||||
static PassRegistry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 注册一个 Pass
|
||||
// passID 是 Pass 类的唯一静态 ID (例如 MyPass::ID 的地址)
|
||||
// factory 是一个 lambda 或函数指针,用于创建该 Pass 的实例
|
||||
void registerPass(void *passID, PassFactory factory) {
|
||||
if (factories.count(passID)) {
|
||||
// Error: Pass with this ID already registered
|
||||
// You might want to throw an exception or log an error
|
||||
return;
|
||||
}
|
||||
factories[passID] = std::move(factory);
|
||||
}
|
||||
|
||||
// 通过 Pass ID 创建一个 Pass 实例
|
||||
std::unique_ptr<Pass> createPass(void *passID) {
|
||||
auto it = factories.find(passID);
|
||||
if (it == factories.end()) {
|
||||
// Error: Pass with this ID not registered
|
||||
return nullptr;
|
||||
}
|
||||
return it->second(); // 调用工厂函数创建实例
|
||||
}
|
||||
|
||||
private:
|
||||
PassRegistry() = default; // 私有构造函数,实现单例
|
||||
~PassRegistry() = default;
|
||||
PassRegistry(const PassRegistry &) = delete; // 禁用拷贝构造
|
||||
PassRegistry &operator=(const PassRegistry &) = delete; // 禁用赋值操作
|
||||
|
||||
std::map<void *, PassFactory> factories;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// AnalysisManager: 负责管理和提供分析结果
|
||||
// ======================================================================
|
||||
class AnalysisManager {
|
||||
private:
|
||||
Module *pModuleRef; // 指向被分析的Module
|
||||
|
||||
// 缓存不同粒度的分析结果
|
||||
std::map<void *, std::unique_ptr<AnalysisResultBase>> moduleCachedResults;
|
||||
std::map<std::pair<Function *, void *>, std::unique_ptr<AnalysisResultBase>> functionCachedResults;
|
||||
std::map<std::pair<BasicBlock *, void *>, std::unique_ptr<AnalysisResultBase>> basicBlockCachedResults;
|
||||
|
||||
|
||||
public:
|
||||
// 构造函数接收 Module 指针
|
||||
AnalysisManager(Module *M) : pModuleRef(M) {}
|
||||
AnalysisManager() = delete; // 禁止无参构造
|
||||
|
||||
~AnalysisManager() = default;
|
||||
|
||||
// 获取分析结果的通用模板函数
|
||||
// T 是 AnalysisResult 的具体类型,E 是 AnalysisPass 的具体类型
|
||||
// F 和 BB 参数用于提供上下文,根据分析遍的粒度来使用
|
||||
template <typename T, typename E> T *getAnalysisResult(Function *F = nullptr, BasicBlock *BB = nullptr) {
|
||||
void *analysisID = E::ID; // 获取分析遍的唯一 ID
|
||||
|
||||
// 尝试从注册表创建分析遍实例
|
||||
std::unique_ptr<Pass> basePass = PassRegistry::getPassRegistry().createPass(analysisID);
|
||||
if (!basePass) {
|
||||
// Error: Analysis pass not registered
|
||||
std::cerr << "Error: Analysis pass with ID " << analysisID << " not registered.\n";
|
||||
return nullptr;
|
||||
}
|
||||
AnalysisPass *analysisPass = static_cast<AnalysisPass *>(basePass.get());
|
||||
|
||||
if(DEBUG){
|
||||
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
}
|
||||
// 根据分析遍的粒度处理
|
||||
switch (analysisPass->getGranularity()) {
|
||||
case Pass::Granularity::Module: {
|
||||
// 检查是否已存在有效结果
|
||||
auto it = moduleCachedResults.find(analysisID);
|
||||
if (it != moduleCachedResults.end()) {
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 运行模块级分析遍
|
||||
if (!pModuleRef) {
|
||||
std::cerr << "Error: Module reference not set for AnalysisManager to run Module Pass.\n";
|
||||
return nullptr;
|
||||
}
|
||||
analysisPass->runOnModule(pModuleRef, *this);
|
||||
// 获取结果并缓存
|
||||
std::unique_ptr<AnalysisResultBase> result = analysisPass->getResult();
|
||||
T *specificResult = static_cast<T *>(result.get());
|
||||
moduleCachedResults[analysisID] = std::move(result); // 缓存结果
|
||||
return specificResult;
|
||||
}
|
||||
case Pass::Granularity::Function: {
|
||||
// 检查请求的上下文是否正确
|
||||
if (!F) {
|
||||
std::cerr << "Error: Function context required for Function-level Analysis Pass.\n";
|
||||
return nullptr;
|
||||
}
|
||||
// 检查是否已存在有效结果
|
||||
auto it = functionCachedResults.find({F, analysisID});
|
||||
if (it != functionCachedResults.end()) {
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 运行函数级分析遍
|
||||
analysisPass->runOnFunction(F, *this);
|
||||
// 获取结果并缓存
|
||||
std::unique_ptr<AnalysisResultBase> result = analysisPass->getResult();
|
||||
T *specificResult = static_cast<T *>(result.get());
|
||||
functionCachedResults[{F, analysisID}] = std::move(result); // 缓存结果
|
||||
return specificResult;
|
||||
}
|
||||
case Pass::Granularity::BasicBlock: {
|
||||
// 检查请求的上下文是否正确
|
||||
if (!BB) {
|
||||
std::cerr << "Error: BasicBlock context required for BasicBlock-level Analysis Pass.\n";
|
||||
return nullptr;
|
||||
}
|
||||
// 检查是否已存在有效结果
|
||||
auto it = basicBlockCachedResults.find({BB, analysisID});
|
||||
if (it != basicBlockCachedResults.end()) {
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 运行基本块级分析遍
|
||||
analysisPass->runOnBasicBlock(BB, *this);
|
||||
// 获取结果并缓存
|
||||
std::unique_ptr<AnalysisResultBase> result = analysisPass->getResult();
|
||||
T *specificResult = static_cast<T *>(result.get());
|
||||
basicBlockCachedResults[{BB, analysisID}] = std::move(result); // 缓存结果
|
||||
return specificResult;
|
||||
}
|
||||
}
|
||||
return nullptr; // 不会到达这里
|
||||
}
|
||||
|
||||
// 使所有分析结果失效 (当 IR 被修改时调用)
|
||||
void invalidateAllAnalyses() {
|
||||
moduleCachedResults.clear();
|
||||
functionCachedResults.clear();
|
||||
basicBlockCachedResults.clear();
|
||||
}
|
||||
|
||||
// 使特定分析结果失效
|
||||
// void *analysisID: 要失效的分析的ID
|
||||
// Function *F: 如果是函数级分析,指定函数;如果是模块级或基本块级,则为nullptr (取决于调用方式)
|
||||
// BasicBlock *BB: 如果是基本块级分析,指定基本块;否则为nullptr
|
||||
void invalidateAnalysis(void *analysisID, Function *F = nullptr, BasicBlock *BB = nullptr) {
|
||||
if (BB) {
|
||||
// 使特定基本块的特定分析结果失效
|
||||
basicBlockCachedResults.erase({BB, analysisID});
|
||||
} else if (F) {
|
||||
// 使特定函数的特定分析结果失效 (也可能包含聚合的BasicBlock结果)
|
||||
functionCachedResults.erase({F, analysisID});
|
||||
// 遍历所有属于F的基本块,使其BasicBlockCache失效 (如果该分析是BasicBlock粒度的)
|
||||
// 这需要遍历F的所有基本块,效率较低,更推荐在BasicBlockPass的invalidateAnalysisUsage中精确指定
|
||||
// 或者在Function级别的invalidate时,清空该Function的所有BasicBlock分析
|
||||
// 这里的实现简单地清空该Function下所有该ID的BasicBlock缓存
|
||||
for (auto it = basicBlockCachedResults.begin(); it != basicBlockCachedResults.end(); ) {
|
||||
// 假设BasicBlock::getParent()方法存在,可以获取所属Function
|
||||
if (it->first.second == analysisID /* && it->first.first->getParent() == F */) { // 需要BasicBlock能获取其父函数
|
||||
it = basicBlockCachedResults.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// 使所有函数的特定分析结果失效 (Module级和所有Function/BasicBlock级)
|
||||
moduleCachedResults.erase(analysisID);
|
||||
for (auto it = functionCachedResults.begin(); it != functionCachedResults.end(); ) {
|
||||
if (it->first.second == analysisID) {
|
||||
it = functionCachedResults.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
for (auto it = basicBlockCachedResults.begin(); it != basicBlockCachedResults.end(); ) {
|
||||
if (it->first.second == analysisID) {
|
||||
it = basicBlockCachedResults.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// PassManager:遍管理器
|
||||
// ======================================================================
|
||||
class PassManager {
|
||||
private:
|
||||
std::vector<std::unique_ptr<Pass>> passes;
|
||||
AnalysisManager analysisManager;
|
||||
Module *pmodule;
|
||||
IRBuilder *pBuilder;
|
||||
|
||||
public:
|
||||
PassManager() = default;
|
||||
~PassManager() = default;
|
||||
|
||||
PassManager(Module *module, IRBuilder *builder) : pmodule(module) ,pBuilder(builder), analysisManager(module) {}
|
||||
|
||||
// 运行所有注册的遍
|
||||
bool run();
|
||||
|
||||
// 运行优化管道主要负责注册和运行优化遍
|
||||
// 这里可以根据 optLevel 和 DEBUG 控制不同的优化遍
|
||||
void runOptimizationPipeline(Module* moduleIR, IRBuilder* builder, int optLevel);
|
||||
|
||||
// 添加遍:现在接受 Pass 的 ID,而不是直接的 unique_ptr
|
||||
void addPass(void *passID);
|
||||
|
||||
AnalysisManager &getAnalysisManager() { return analysisManager; }
|
||||
|
||||
void clearPasses();
|
||||
|
||||
// 输出pass列表并打印IR信息供观察优化遍效果
|
||||
void printPasses() const;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// 辅助宏或函数,用于简化 Pass 的注册
|
||||
// ======================================================================
|
||||
|
||||
// 用于分析遍的注册
|
||||
template <typename AnalysisPassType> void registerAnalysisPass();
|
||||
|
||||
// (1) 针对需要 IRBuilder 参数的优化遍的重载
|
||||
// 这个模板只在 OptimizationPassType 可以通过 IRBuilder* 构造时才有效
|
||||
template <typename OptimizationPassType, typename std::enable_if<
|
||||
std::is_constructible<OptimizationPassType, IRBuilder*>::value, int>::type = 0>
|
||||
void registerOptimizationPass(IRBuilder* builder);
|
||||
|
||||
// (2) 针对不需要 IRBuilder 参数的所有其他优化遍的重载
|
||||
// 这个模板只在 OptimizationPassType 不能通过 IRBuilder* 构造时才有效
|
||||
template <typename OptimizationPassType, typename std::enable_if<
|
||||
!std::is_constructible<OptimizationPassType, IRBuilder*>::value, int>::type = 0>
|
||||
void registerOptimizationPass();
|
||||
|
||||
} // namespace sysy
|
||||
146
src/include/midend/SysYIRGenerator.h
Normal file
146
src/include/midend/SysYIRGenerator.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <forward_list>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
|
||||
// @brief 用于存储数组值的树结构
|
||||
// 多位数组本质上是一维数组的嵌套可以用树来表示。
|
||||
class ArrayValueTree {
|
||||
private:
|
||||
Value *value = nullptr; /// 该节点存储的value
|
||||
std::vector<std::unique_ptr<ArrayValueTree>> children; /// 子节点列表
|
||||
|
||||
public:
|
||||
ArrayValueTree() = default;
|
||||
|
||||
public:
|
||||
auto getValue() const -> Value * { return value; }
|
||||
auto getChildren() const
|
||||
-> const std::vector<std::unique_ptr<ArrayValueTree>> & {
|
||||
return children;
|
||||
}
|
||||
|
||||
void setValue(Value *newValue) { value = newValue; }
|
||||
void addChild(ArrayValueTree *newChild) { children.emplace_back(newChild); }
|
||||
void addChildren(const std::vector<ArrayValueTree *> &newChildren) {
|
||||
for (const auto &child : newChildren) {
|
||||
children.emplace_back(child);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
// transform a tree of ArrayValueTree to a ValueCounter
|
||||
static void tree2Array(Type *type, ArrayValueTree *root,
|
||||
const std::vector<Value *> &dims, unsigned numDims,
|
||||
ValueCounter &result, IRBuilder *builder);
|
||||
static void
|
||||
createExternalFunction(const std::vector<Type *> ¶mTypes,
|
||||
const std::vector<std::string> ¶mNames,
|
||||
const std::vector<std::vector<Value *>> ¶mDims,
|
||||
Type *returnType, const std::string &funcName,
|
||||
Module *pModule, IRBuilder *pBuilder);
|
||||
|
||||
static void initExternalFunction(Module *pModule, IRBuilder *pBuilder);
|
||||
};
|
||||
|
||||
class SysYIRGenerator : public SysYBaseVisitor {
|
||||
|
||||
private:
|
||||
std::unique_ptr<Module> module;
|
||||
IRBuilder builder;
|
||||
|
||||
public:
|
||||
SysYIRGenerator() = default;
|
||||
|
||||
public:
|
||||
Module *get() const { return module.get(); }
|
||||
IRBuilder *getBuilder(){ return &builder; }
|
||||
public:
|
||||
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override;
|
||||
|
||||
std::any visitGlobalConstDecl(SysYParser::GlobalConstDeclContext *ctx) override;
|
||||
std::any visitGlobalVarDecl(SysYParser::GlobalVarDeclContext *ctx) override;
|
||||
|
||||
// std::any visitDecl(SysYParser::DeclContext *ctx) override;
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override;
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override;
|
||||
|
||||
std::any visitBType(SysYParser::BTypeContext *ctx) override;
|
||||
|
||||
// std::any visitConstDef(SysYParser::ConstDefContext *ctx) override;
|
||||
// std::any visitVarDef(SysYParser::VarDefContext *ctx) override;
|
||||
|
||||
std::any visitScalarInitValue(SysYParser::ScalarInitValueContext *ctx) override;
|
||||
std::any visitArrayInitValue(SysYParser::ArrayInitValueContext *ctx) override;
|
||||
|
||||
std::any visitConstScalarInitValue(SysYParser::ConstScalarInitValueContext *ctx) override;
|
||||
std::any visitConstArrayInitValue(SysYParser::ConstArrayInitValueContext *ctx) override;
|
||||
|
||||
// std::any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override;
|
||||
std::any visitFuncType(SysYParser::FuncTypeContext* ctx) override;
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
|
||||
// std::any visitInitVal(SysYParser::InitValContext *ctx) override;
|
||||
// std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override;
|
||||
// std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override;
|
||||
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
|
||||
// std::any visitStmt(SysYParser::StmtContext *ctx) override;
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
|
||||
// std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override;
|
||||
// std::any visitBlkStmt(SysYParser::BlkStmtContext *ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override;
|
||||
|
||||
// std::any visitExp(SysYParser::ExpContext *ctx) override;
|
||||
// std::any visitCond(SysYParser::CondContext *ctx) override;
|
||||
|
||||
std::any visitLValue(SysYParser::LValueContext *ctx) override;
|
||||
|
||||
std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override;
|
||||
|
||||
// std::any visitParenExp(SysYParser::ParenExpContext *ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext *ctx) override;
|
||||
// std::any visitString(SysYParser::StringContext *ctx) override;
|
||||
|
||||
std::any visitCall(SysYParser::CallContext *ctx) override;
|
||||
|
||||
std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override;
|
||||
// std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override;
|
||||
|
||||
// std::any visitUnExp(SysYParser::UnExpContext *ctx) override;
|
||||
|
||||
std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override;
|
||||
std::any visitMulExp(SysYParser::MulExpContext *ctx) override;
|
||||
std::any visitAddExp(SysYParser::AddExpContext *ctx) override;
|
||||
std::any visitRelExp(SysYParser::RelExpContext *ctx) override;
|
||||
std::any visitEqExp(SysYParser::EqExpContext *ctx) override;
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override;
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override;
|
||||
|
||||
// std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
|
||||
|
||||
public:
|
||||
// 获取GEP指令的地址
|
||||
Value* getGEPAddressInst(Value* basePointer, const std::vector<Value*>& indices);
|
||||
// 构建数组类型
|
||||
Type* buildArrayType(Type* baseType, const std::vector<Value*>& dims);
|
||||
|
||||
unsigned countArrayDimensions(Type* type);
|
||||
|
||||
}; // class SysYIRGenerator
|
||||
|
||||
} // namespace sysy
|
||||
32
src/include/midend/SysYIRPrinter.h
Normal file
32
src/include/midend/SysYIRPrinter.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "IR.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class SysYPrinter {
|
||||
private:
|
||||
Module *pModule;
|
||||
|
||||
public:
|
||||
explicit SysYPrinter(Module *pModule) : pModule(pModule) {}
|
||||
|
||||
public:
|
||||
void printIR();
|
||||
void printGlobalVariable();
|
||||
|
||||
|
||||
public:
|
||||
static void printFunction(Function *function);
|
||||
static void printInst(Instruction *pInst);
|
||||
static void printType(Type *type);
|
||||
static void printValue(Value *value);
|
||||
static void printBlock(BasicBlock *block);
|
||||
static std::string getBlockName(BasicBlock *block);
|
||||
static std::string getOperandName(Value *operand);
|
||||
static std::string getTypeString(Type *type);
|
||||
static std::string getValueName(Value *value);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
63
src/include/midend/range.h
Normal file
63
src/include/midend/range.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/*!
|
||||
* \defgroup utility Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief `range` is an simple wrapper of an iterator pair [begin, end)
|
||||
*
|
||||
* Example usage
|
||||
*
|
||||
* ```cpp
|
||||
* vector<int> v = {1,2,3};
|
||||
* auto rg = make_range(v);
|
||||
* for (auto v : rg)
|
||||
* cout << v << '\n';
|
||||
* ```
|
||||
*/
|
||||
template <typename IterT> struct range {
|
||||
using iterator = IterT;
|
||||
using value_type = typename std::iterator_traits<iterator>::value_type;
|
||||
using reference = typename std::iterator_traits<iterator>::reference;
|
||||
|
||||
private:
|
||||
iterator b;
|
||||
iterator e;
|
||||
|
||||
public:
|
||||
explicit range(iterator b, iterator e) : b(b), e(e) {}
|
||||
iterator begin() { return b; }
|
||||
iterator end() { return e; }
|
||||
iterator begin() const { return b; }
|
||||
iterator end() const { return e; }
|
||||
auto size() const { return std::distance(b, e); }
|
||||
auto empty() const { return b == e; }
|
||||
};
|
||||
|
||||
//! create `range` object from iterator pair [begin, end)
|
||||
template <typename IterT> range<IterT> make_range(IterT b, IterT e) {
|
||||
return range(b, e);
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::iterator> make_range(ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::const_iterator> make_range(const ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user