Compare commits
14 Commits
Mem2Reg
...
backend-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2b88ee511 | ||
|
|
395e6e4003 | ||
|
|
20cc08708a | ||
|
|
942cb32976 | ||
|
|
ac7569d890 | ||
|
|
11cd32e6df | ||
|
|
617244fae7 | ||
|
|
3c3f48ee87 | ||
|
|
ab3eb253f9 | ||
|
|
7d37bd7528 | ||
|
|
af00612376 | ||
|
|
10e1476ba1 | ||
|
|
b94e87637a | ||
|
|
88a561177d |
@@ -18,9 +18,6 @@ add_executable(sysyc
|
||||
# Backend.cpp
|
||||
SysYIRPrinter.cpp
|
||||
SysYIROptPre.cpp
|
||||
SysYIRAnalyser.cpp
|
||||
Mem2Reg.cpp
|
||||
Reg2Mem.cpp
|
||||
RISCv32Backend.cpp
|
||||
)
|
||||
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
40
src/IR.cpp
40
src/IR.cpp
@@ -598,11 +598,11 @@ auto SymbolTable::addVariable(const std::string &name, User *variable) -> User *
|
||||
std::stringstream ss;
|
||||
auto iter = variableIndex.find(name);
|
||||
if (iter != variableIndex.end()) {
|
||||
ss << name << iter->second ;
|
||||
ss << name << "(" << iter->second << ")";
|
||||
iter->second += 1;
|
||||
} else {
|
||||
variableIndex.emplace(name, 1);
|
||||
ss << name << 0 ;
|
||||
ss << name << "(" << 0 << ")";
|
||||
}
|
||||
|
||||
variable->setName(ss.str());
|
||||
@@ -665,6 +665,42 @@ void SymbolTable::leaveScope() { curNode = curNode->pNode; }
|
||||
*/
|
||||
auto SymbolTable::isInGlobalScope() const -> bool { return curNode->pNode == nullptr; }
|
||||
|
||||
/**
|
||||
* @brief 判断是否为循环不变量
|
||||
* @param value: 要判断的value
|
||||
* @return true: 是不变量
|
||||
* @return false: 不是
|
||||
*/
|
||||
auto Loop::isSimpleLoopInvariant(Value *value) -> bool {
|
||||
// auto constValue = dynamic_cast<ConstantValue *>(value);
|
||||
// if (constValue != nullptr) {
|
||||
// return false;
|
||||
// }
|
||||
if (auto instr = dynamic_cast<Instruction *>(value)) {
|
||||
if (instr->isLoad()) {
|
||||
auto loadinst = dynamic_cast<LoadInst *>(instr);
|
||||
|
||||
auto loadvalue = dynamic_cast<AllocaInst *>(loadinst->getOperand(0));
|
||||
if (loadvalue != nullptr) {
|
||||
if (loadvalue->getParent() != nullptr) {
|
||||
auto basicblock = loadvalue->getParent();
|
||||
return !this->isLoopContainsBasicBlock(basicblock);
|
||||
}
|
||||
}
|
||||
auto globalvalue = dynamic_cast<GlobalValue *>(loadinst->getOperand(0));
|
||||
if (globalvalue != nullptr) {
|
||||
return true;
|
||||
}
|
||||
auto basicblock = instr->getParent();
|
||||
|
||||
return !this->isLoopContainsBasicBlock(basicblock);
|
||||
}
|
||||
auto basicblock = instr->getParent();
|
||||
return !this->isLoopContainsBasicBlock(basicblock);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移动指令
|
||||
*
|
||||
|
||||
823
src/Mem2Reg.cpp
823
src/Mem2Reg.cpp
@@ -1,823 +0,0 @@
|
||||
#include "Mem2Reg.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include "IR.h"
|
||||
#include "SysYIRAnalyser.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 计算给定变量的定义块集合的迭代支配边界
|
||||
// TODO:优化Semi-Naive IDF
|
||||
std::unordered_set<BasicBlock *> Mem2Reg::computeIterDf(const std::unordered_set<BasicBlock *> &blocks) {
|
||||
std::unordered_set<BasicBlock *> workList;
|
||||
std::unordered_set<BasicBlock *> ret_list;
|
||||
workList.insert(blocks.begin(), blocks.end());
|
||||
|
||||
while (!workList.empty()) {
|
||||
auto n = workList.begin();
|
||||
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(*n);
|
||||
auto DFs = blockInfo->getDomFrontiers();
|
||||
for (auto c : DFs) {
|
||||
// 如果c不在ret_list中,则将其加入ret_list和workList
|
||||
// 这里的c是n的支配边界
|
||||
// 也就是n的支配边界中的块
|
||||
// 需要注意的是,支配边界是一个集合,所以可能会有重复
|
||||
if (ret_list.count(c) == 0U) {
|
||||
ret_list.emplace(c);
|
||||
workList.emplace(c);
|
||||
}
|
||||
}
|
||||
workList.erase(n);
|
||||
}
|
||||
return ret_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算value2Blocks的映射,包括value2AllocBlocks、value2DefBlocks以及value2UseBlocks
|
||||
* 其中value2DefBlocks可用于计算迭代支配边界来插入相应变量的phi结点
|
||||
* 这里的value2AllocBlocks、value2DefBlocks和value2UseBlocks改变了函数级别的分析信息
|
||||
*/
|
||||
auto Mem2Reg::computeValue2Blocks() -> void {
|
||||
SysYPrinter printer(pModule); // 初始化打印机
|
||||
std::cout << "===== Start computeValue2Blocks =====" << std::endl;
|
||||
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
std::cout << "\nProcessing function: " << func->getName() << std::endl;
|
||||
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
if (!funcInfo) {
|
||||
std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
std::cout << "BasicBlocks count: " << basicBlocks.size() << std::endl;
|
||||
|
||||
for (auto &it : basicBlocks) {
|
||||
auto basicBlock = it.get();
|
||||
std::cout << "\nProcessing BB: " << basicBlock->getName() << std::endl;
|
||||
// printer.printBlock(basicBlock); // 打印基本块内容
|
||||
|
||||
auto &instrs = basicBlock->getInstructions();
|
||||
for (auto &instr : instrs) {
|
||||
std::cout << " Analyzing instruction: ";
|
||||
printer.printInst(instr.get());
|
||||
std::cout << std::endl;
|
||||
|
||||
if (instr->isAlloca()) {
|
||||
if (!(isArr(instr.get()) || isGlobal(instr.get()))) {
|
||||
std::cout << " Found alloca: ";
|
||||
printer.printInst(instr.get());
|
||||
std::cout << " -> Adding to allocBlocks" << std::endl;
|
||||
|
||||
funcInfo->addValue2AllocBlocks(instr.get(), basicBlock);
|
||||
} else {
|
||||
std::cout << " Skip array/global alloca: ";
|
||||
printer.printInst(instr.get());
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
else if (instr->isStore()) {
|
||||
auto val = instr->getOperand(1);
|
||||
std::cout << " Store target: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
std::cout << " Adding store to defBlocks for value: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(instr.get()));
|
||||
std::cout << std::endl;
|
||||
// 将store的目标值添加到defBlocks中
|
||||
funcInfo->addValue2DefBlocks(val, basicBlock);
|
||||
} else {
|
||||
std::cout << " Skip array/global store" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (instr->isLoad()) {
|
||||
auto val = instr->getOperand(0);
|
||||
std::cout << " Load source: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
std::cout << " Adding load to useBlocks for value: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
funcInfo->addValue2UseBlocks(val, basicBlock);
|
||||
} else {
|
||||
std::cout << " Skip array/global load" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 打印分析结果
|
||||
std::cout << "\nAnalysis results for function " << func->getName() << ":" << std::endl;
|
||||
|
||||
auto &allocMap = funcInfo->getValue2AllocBlocks();
|
||||
std::cout << "AllocBlocks (" << allocMap.size() << "):" << std::endl;
|
||||
for (auto &[val, bb] : allocMap) {
|
||||
std::cout << " ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << " in BB: " << bb->getName() << std::endl;
|
||||
}
|
||||
|
||||
auto &defMap = funcInfo->getValue2DefBlocks();
|
||||
std::cout << "DefBlocks (" << defMap.size() << "):" << std::endl;
|
||||
for (auto &[val, bbs] : defMap) {
|
||||
std::cout << " ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
for (const auto &[bb, count] : bbs) {
|
||||
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")";
|
||||
}
|
||||
}
|
||||
|
||||
auto &useMap = funcInfo->getValue2UseBlocks();
|
||||
std::cout << "UseBlocks (" << useMap.size() << "):" << std::endl;
|
||||
for (auto &[val, bbs] : useMap) {
|
||||
std::cout << " ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
for (const auto &[bb, count] : bbs) {
|
||||
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "===== End computeValue2Blocks =====" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 级联关系的顺带消除,用于llvm mem2reg类预优化1
|
||||
*
|
||||
* 采用队列进行模拟,从某种程度上来看其实可以看作是UD链的反向操作;
|
||||
*
|
||||
* @param [in] instr store指令使用的指令
|
||||
* @param [in] changed 不动点法的判断标准,地址传递
|
||||
* @param [in] func 指令所在函数
|
||||
* @param [in] block 指令所在基本块
|
||||
* @param [in] instrs 基本块所在指令集合,地址传递
|
||||
* @return 无返回值,但满足条件的情况下会对指令进行删除
|
||||
*/
|
||||
auto Mem2Reg::cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block,
|
||||
std::list<std::unique_ptr<Instruction>> &instrs) -> void {
|
||||
if (instr != nullptr) {
|
||||
if (instr->isUnary() || instr->isBinary() || instr->isLoad()) {
|
||||
std::queue<Instruction *> toRemove;
|
||||
toRemove.push(instr);
|
||||
while (!toRemove.empty()) {
|
||||
auto top = toRemove.front();
|
||||
toRemove.pop();
|
||||
auto operands = top->getOperands();
|
||||
for (const auto &operand : operands) {
|
||||
auto elem = dynamic_cast<Instruction *>(operand->getValue());
|
||||
if (elem != nullptr) {
|
||||
if ((elem->isUnary() || elem->isBinary() || elem->isLoad()) && elem->getUses().size() == 1 &&
|
||||
elem->getUses().front()->getUser() == top) {
|
||||
toRemove.push(elem);
|
||||
} else if (elem->isAlloca()) {
|
||||
// value2UseBlock中该block对应次数-1,如果该变量的该useblock中count减为0了,则意味着
|
||||
// 该block其他地方也没用到该alloc了,故从value2UseBlock中删除
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
auto res = funcInfo->removeValue2UseBlock(elem, block);
|
||||
// 只要有一次返回了true,就说明有变化
|
||||
if (res) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto tofind =
|
||||
std::find_if(instrs.begin(), instrs.end(), [&top](const auto &instr) { return instr.get() == top; });
|
||||
assert(tofind != instrs.end());
|
||||
usedelete(tofind->get());
|
||||
instrs.erase(tofind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief llvm mem2reg预优化1: 删除不含load的alloc和store
|
||||
*
|
||||
* 1. 删除不含load的alloc和store;
|
||||
* 2. 删除store指令,之前的用于作store指令第0个操作数的那些级联指令就冗余了,也要删除;
|
||||
* 3. 删除之后,可能有些变量的load使用恰好又没有了,因此再次从第一步开始循环,这里使用不动点法
|
||||
*
|
||||
* @note 额外说明:由于删除了级联关系,所以这里的方法有点儿激进;
|
||||
* 同时也考虑了级联关系时如果调用了函数,可能会有side effect,所以没有删除调用函数的级联关系;
|
||||
* 而且关于函数参数的alloca不会在指令中删除,也不会在value2Alloca中删除;
|
||||
* 同样地,我们不考虑数组和global,不过这里的代码是基于value2blocks的,在value2blocks中已经考虑了,所以不用显式指明
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值,但满足条件的情况下会对指令进行删除
|
||||
*/
|
||||
auto Mem2Reg::preOptimize1() -> void {
|
||||
SysYPrinter printer(pModule); // 初始化打印机
|
||||
|
||||
auto &functions = pModule->getFunctions();
|
||||
std::cout << "===== Start preOptimize1 =====" << std::endl;
|
||||
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
std::cout << "\nProcessing function: " << func->getName() << std::endl;
|
||||
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
if (!funcInfo) {
|
||||
std::cerr << "ERROR: No analysis info for function " << func->getName() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &vToDefB = funcInfo->getValue2DefBlocks();
|
||||
auto &vToUseB = funcInfo->getValue2UseBlocks();
|
||||
auto &vToAllocB = funcInfo->getValue2AllocBlocks();
|
||||
|
||||
// 打印初始状态
|
||||
std::cout << "Initial allocas: " << vToAllocB.size() << std::endl;
|
||||
for (auto &[val, bb] : vToAllocB) {
|
||||
std::cout << " Alloca: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << " in BB: " << bb->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 阶段1:删除无store的alloca
|
||||
std::cout << "\nPhase 1: Remove unused allocas" << std::endl;
|
||||
for (auto iter = vToAllocB.begin(); iter != vToAllocB.end();) {
|
||||
auto val = iter->first;
|
||||
auto bb = iter->second;
|
||||
|
||||
std::cout << "Checking alloca: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << " in BB: " << bb->getName() << std::endl;
|
||||
|
||||
// 如果该alloca没有对应的store指令,且不在函数参数中
|
||||
// 这里的vToDefB是value2DefBlocks,vToUseB是value2UseBlocks
|
||||
|
||||
// 打印vToDefB
|
||||
std::cout << "DefBlocks (" << vToDefB.size() << "):" << std::endl;
|
||||
for (auto &[val, bbs] : vToDefB) {
|
||||
std::cout << " ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
for (const auto &[bb, count] : bbs) {
|
||||
std::cout << " in BB: " << bb->getName() << " (count: " << count << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << vToDefB.count(val) << std::endl;
|
||||
bool hasStore = false;
|
||||
|
||||
|
||||
|
||||
if (vToDefB.count(val) == 0U &&
|
||||
std::find(func->getEntryBlock()->getArguments().begin(),
|
||||
func->getEntryBlock()->getArguments().end(),
|
||||
val) == func->getEntryBlock()->getArguments().end()) {
|
||||
|
||||
std::cout << " Removing unused alloca: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
auto tofind = std::find_if(bb->getInstructions().begin(),
|
||||
bb->getInstructions().end(),
|
||||
[val](const auto &instr) {
|
||||
return instr.get() == val;
|
||||
});
|
||||
if (tofind == bb->getInstructions().end()) {
|
||||
std::cerr << "ERROR: Alloca not found in BB!" << std::endl;
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
usedelete(tofind->get());
|
||||
bb->getInstructions().erase(tofind);
|
||||
iter = vToAllocB.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
// 阶段2:删除无load的store
|
||||
std::cout << "\nPhase 2: Remove dead stores" << std::endl;
|
||||
bool changed = true;
|
||||
int iteration = 0;
|
||||
|
||||
while (changed) {
|
||||
changed = false;
|
||||
iteration++;
|
||||
std::cout << "\nIteration " << iteration << std::endl;
|
||||
|
||||
for (auto iter = vToDefB.begin(); iter != vToDefB.end();) {
|
||||
auto val = iter->first;
|
||||
|
||||
std::cout << "Checking value: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
if (vToUseB.count(val) == 0U) {
|
||||
std::cout << " Found dead store for value: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << std::endl;
|
||||
|
||||
auto blocks = funcInfo->getDefBlocksByValue(val);
|
||||
for (auto block : blocks) {
|
||||
std::cout << " Processing BB: " << block->getName() << std::endl;
|
||||
// printer.printBlock(block); // 打印基本块内容
|
||||
|
||||
auto &instrs = block->getInstructions();
|
||||
for (auto it = instrs.begin(); it != instrs.end();) {
|
||||
if ((*it)->isStore() && (*it)->getOperand(1) == val) {
|
||||
std::cout << " Removing store: ";
|
||||
printer.printInst(it->get());
|
||||
std::cout << std::endl;
|
||||
|
||||
auto valUsedByStore = dynamic_cast<Instruction *>((*it)->getOperand(0));
|
||||
usedelete(it->get());
|
||||
|
||||
if (valUsedByStore != nullptr &&
|
||||
valUsedByStore->getUses().size() == 1 &&
|
||||
valUsedByStore->getUses().front()->getUser() == (*it).get()) {
|
||||
std::cout << " Cascade deleting: ";
|
||||
printer.printInst(valUsedByStore);
|
||||
std::cout << std::endl;
|
||||
|
||||
cascade(valUsedByStore, changed, func, block, instrs);
|
||||
}
|
||||
it = instrs.erase(it);
|
||||
changed = true;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除对应的alloca
|
||||
if (std::find(func->getEntryBlock()->getArguments().begin(),
|
||||
func->getEntryBlock()->getArguments().end(),
|
||||
val) == func->getEntryBlock()->getArguments().end()) {
|
||||
auto bb = funcInfo->getAllocBlockByValue(val);
|
||||
if (bb != nullptr) {
|
||||
std::cout << " Removing alloca: ";
|
||||
printer.printInst(dynamic_cast<Instruction *>(val));
|
||||
std::cout << " in BB: " << bb->getName() << std::endl;
|
||||
|
||||
funcInfo->removeValue2AllocBlock(val);
|
||||
auto tofind = std::find_if(bb->getInstructions().begin(),
|
||||
bb->getInstructions().end(),
|
||||
[val](const auto &instr) {
|
||||
return instr.get() == val;
|
||||
});
|
||||
if (tofind != bb->getInstructions().end()) {
|
||||
usedelete(tofind->get());
|
||||
bb->getInstructions().erase(tofind);
|
||||
} else {
|
||||
std::cerr << "ERROR: Alloca not found in BB!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
iter = vToDefB.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "===== End preOptimize1 =====" << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief llvm mem2reg预优化2: 针对某个变量的Defblocks只有一个块的情况
|
||||
*
|
||||
* 1. 该基本块最后一次对该变量的store指令后的所有对该变量的load指令都可以替换为该基本块最后一次store指令的第0个操作数;
|
||||
* 2. 以该基本块为必经结点的结点集合中的对该变量的load指令都可以替换为该基本块最后一次对该变量的store指令的第0个操作数;
|
||||
* 3.
|
||||
* 如果对该变量的所有load均替换掉了,删除该基本块中最后一次store指令,如果这个store指令是唯一的define,那么再删除alloca指令(不删除参数的alloca);
|
||||
* 4.
|
||||
* 如果对该value的所有load都替换掉了,对于该变量剩下还有store的话,就转换成了preOptimize1的情况,再调用preOptimize1进行删除;
|
||||
*
|
||||
* @note 额外说明:同样有点儿激进;
|
||||
* 同样不考虑数组和全局变量,因为这些变量不会被mem2reg优化,在value2blocks中已经考虑了,所以不用显式指明;
|
||||
* 替换的操作采用了UD链进行简化和效率的提升
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除
|
||||
*/
|
||||
auto Mem2Reg::preOptimize2() -> void {
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
auto values = funcInfo->getValuesOfDefBlock();
|
||||
for (auto val : values) {
|
||||
auto blocks = funcInfo->getDefBlocksByValue(val);
|
||||
// 该val只有一个defining block
|
||||
if (blocks.size() == 1) {
|
||||
auto block = *blocks.begin();
|
||||
auto &instrs = block->getInstructions();
|
||||
auto rit = std::find_if(instrs.rbegin(), instrs.rend(),
|
||||
[val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; });
|
||||
// 注意reverse_iterator求base后是指向下一个指令,因此要减一才是原来的指令
|
||||
assert(rit != instrs.rend());
|
||||
auto it = --rit.base();
|
||||
auto propogationVal = (*it)->getOperand(0);
|
||||
// 其实该块中it后对该val的load指令也可以替换掉了
|
||||
for (auto curit = std::next(it); curit != instrs.end();) {
|
||||
if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) {
|
||||
curit->get()->replaceAllUsesWith(propogationVal);
|
||||
usedelete(curit->get());
|
||||
curit = instrs.erase(curit);
|
||||
funcInfo->removeValue2UseBlock(val, block);
|
||||
} else {
|
||||
++curit;
|
||||
}
|
||||
}
|
||||
// 在支配树后继结点中替换load指令的操作数
|
||||
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
|
||||
std::vector<BasicBlock *> blkchildren;
|
||||
// 获取该块的支配树后继结点
|
||||
std::queue<BasicBlock *> q;
|
||||
auto sdoms = blockInfo->getSdoms();
|
||||
for (auto sdom : sdoms) {
|
||||
q.push(sdom);
|
||||
blkchildren.push_back(sdom);
|
||||
}
|
||||
while (!q.empty()) {
|
||||
auto blk = q.front();
|
||||
q.pop();
|
||||
BlockAnalysisInfo* blkInfo = controlFlowAnalysis->getBlockAnalysisInfo(blk);
|
||||
for (auto sdom : blkInfo->getSdoms()) {
|
||||
q.push(sdom);
|
||||
blkchildren.push_back(sdom);
|
||||
}
|
||||
}
|
||||
for (auto child : blkchildren) {
|
||||
auto &childInstrs = child->getInstructions();
|
||||
for (auto childIter = childInstrs.begin(); childIter != childInstrs.end();) {
|
||||
if ((*childIter)->isLoad() && (*childIter)->getOperand(0) == val) {
|
||||
childIter->get()->replaceAllUsesWith(propogationVal);
|
||||
usedelete(childIter->get());
|
||||
childIter = childInstrs.erase(childIter);
|
||||
funcInfo->removeValue2UseBlock(val, child);
|
||||
} else {
|
||||
++childIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果对该val的所有load均替换掉了,那么对于该val的defining block中的最后一个define也可以删除了
|
||||
// 同时该块中前面对于该val的define也变成死代码了,可调用preOptimize1进行删除
|
||||
if (funcInfo->getUseBlocksByValue(val).empty()) {
|
||||
usedelete(it->get());
|
||||
instrs.erase(it);
|
||||
auto change = funcInfo->removeValue2DefBlock(val, block);
|
||||
if (change) {
|
||||
// 如果define是唯一的,且不是函数参数的alloca,直接删alloca
|
||||
if (std::find(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(),
|
||||
val) == func->getEntryBlock()->getArguments().end()) {
|
||||
auto bb = funcInfo->getAllocBlockByValue(val);
|
||||
assert(bb != nullptr);
|
||||
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
|
||||
[val](const auto &instr) { return instr.get() == val; });
|
||||
usedelete(tofind->get());
|
||||
bb->getInstructions().erase(tofind);
|
||||
funcInfo->removeValue2AllocBlock(val);
|
||||
}
|
||||
} else {
|
||||
// 如果该变量还有其他的define,那么前面的define也变成死代码了
|
||||
assert(!funcInfo->getDefBlocksByValue(val).empty());
|
||||
assert(funcInfo->getUseBlocksByValue(val).empty());
|
||||
preOptimize1();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief llvm mem2reg类预优化3:针对某个变量的所有读写都在同一个块中的情况
|
||||
*
|
||||
* 1. 将每一个load替换成前一个store的值,并删除该load;
|
||||
* 2. 如果在load前没有对该变量的store,则不删除该load;
|
||||
* 3. 如果一个store后没有任何对改变量的load,则删除该store;
|
||||
*
|
||||
* @note 额外说明:第二点不用显式处理,因为我们的方法是从找到第一个store开始;
|
||||
* 第三点其实可以更激进一步地理解,即每次替换了load之后,它对应地那个store也可以删除了,同时注意这里不要使用preoptimize1进行处理,因为他们的级联关系是有用的:即用来求load的替换值;
|
||||
* 同样地,我们这里不考虑数组和全局变量,因为这些变量不会被mem2reg优化,不过这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了;
|
||||
* 替换的操作采用了UD链进行简化和效率的提升
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值,但满足条件的情况下会对指令的操作数进行替换以及对指令进行删除
|
||||
*/
|
||||
auto Mem2Reg::preOptimize3() -> void {
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
auto values = funcInfo->getValuesOfDefBlock();
|
||||
for (auto val : values) {
|
||||
auto sblocks = funcInfo->getDefBlocksByValue(val);
|
||||
auto lblocks = funcInfo->getUseBlocksByValue(val);
|
||||
if (sblocks.size() == 1 && lblocks.size() == 1 && *sblocks.begin() == *lblocks.begin()) {
|
||||
auto block = *sblocks.begin();
|
||||
auto &instrs = block->getInstructions();
|
||||
auto it = std::find_if(instrs.begin(), instrs.end(),
|
||||
[val](const auto &instr) { return instr->isStore() && instr->getOperand(1) == val; });
|
||||
while (it != instrs.end()) {
|
||||
auto propogationVal = (*it)->getOperand(0);
|
||||
auto last = std::find_if(std::next(it), instrs.end(), [val](const auto &instr) {
|
||||
return instr->isStore() && instr->getOperand(1) == val;
|
||||
});
|
||||
for (auto curit = std::next(it); curit != last;) {
|
||||
if ((*curit)->isLoad() && (*curit)->getOperand(0) == val) {
|
||||
curit->get()->replaceAllUsesWith(propogationVal);
|
||||
usedelete(curit->get());
|
||||
curit = instrs.erase(curit);
|
||||
funcInfo->removeValue2UseBlock(val, block);
|
||||
} else {
|
||||
++curit;
|
||||
}
|
||||
}
|
||||
// 替换了load之后,它对应地那个store也可以删除了
|
||||
if (!(std::find_if(func->getEntryBlock()->getArguments().begin(), func->getEntryBlock()->getArguments().end(),
|
||||
[val](const auto &instr) { return instr == val; }) !=
|
||||
func->getEntryBlock()->getArguments().end()) &&
|
||||
last == instrs.end()) {
|
||||
usedelete(it->get());
|
||||
it = instrs.erase(it);
|
||||
if (funcInfo->removeValue2DefBlock(val, block)) {
|
||||
auto bb = funcInfo->getAllocBlockByValue(val);
|
||||
if (bb != nullptr) {
|
||||
auto tofind = std::find_if(bb->getInstructions().begin(), bb->getInstructions().end(),
|
||||
[val](const auto &instr) { return instr.get() == val; });
|
||||
usedelete(tofind->get());
|
||||
bb->getInstructions().erase(tofind);
|
||||
funcInfo->removeValue2AllocBlock(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
it = last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 为所有变量的定义块集合的迭代支配边界插入phi结点
|
||||
*
|
||||
* insertPhi是mem2reg的核心之一,这里是对所有变量的迭代支配边界的phi结点插入,无参数也无返回值;
|
||||
* 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化,刚好这里在计算value2DefBlocks时已经跳过了,所以不需要再显式处理了;
|
||||
* 同时我们进行了剪枝处理,只有在基本块入口活跃的变量,才插入phi函数
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值,但是会在每个变量的迭代支配边界上插入phi结点
|
||||
*/
|
||||
auto Mem2Reg::insertPhi() -> void {
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
const auto &vToDefB = funcInfo->getValue2DefBlocks();
|
||||
for (const auto &map_pair : vToDefB) {
|
||||
// 首先为每个变量找到迭代支配边界
|
||||
auto val = map_pair.first;
|
||||
auto blocks = funcInfo->getDefBlocksByValue(val);
|
||||
auto itDFs = computeIterDf(blocks);
|
||||
// 然后在每个变量相应的迭代支配边界上插入phi结点
|
||||
for (auto basicBlock : itDFs) {
|
||||
const auto &actiTable = activeVarAnalysis->getActiveTable();
|
||||
auto dval = dynamic_cast<User *>(val);
|
||||
// 只有在基本块入口活跃的变量,才插入phi函数
|
||||
if (actiTable.at(basicBlock).front().count(dval) != 0U) {
|
||||
pBuilder->createPhiInst(val->getType(), val, basicBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重命名
|
||||
*
|
||||
* 重命名是mem2reg的核心之二,这里是对单个块的重命名,递归实现
|
||||
* 同样跳过对数组和全局变量的处理,因为这些变量不会被mem2reg优化
|
||||
*
|
||||
* @param [in] block 一个基本块
|
||||
* @param [in] count 计数器,用于给变量重命名,地址传递
|
||||
* @param [in] stacks 用于存储变量的栈,地址传递
|
||||
* @return 无返回值
|
||||
*/
|
||||
auto Mem2Reg::rename(BasicBlock *block, std::unordered_map<Value *, int> &count,
|
||||
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void {
|
||||
auto &instrs = block->getInstructions();
|
||||
std::unordered_map<Value *, int> valPop;
|
||||
// 第一大步:对块中的所有指令遍历处理
|
||||
for (auto iter = instrs.begin(); iter != instrs.end();) {
|
||||
auto instr = iter->get();
|
||||
// 对于load指令,变量用最新的那个
|
||||
if (instr->isLoad()) {
|
||||
auto val = instr->getOperand(0);
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
if (!stacks[val].empty()) {
|
||||
instr->replaceOperand(0, stacks[val].top());
|
||||
}
|
||||
}
|
||||
}
|
||||
// 然后对于define的情况,看alloca、store和phi指令
|
||||
if (instr->isDefine()) {
|
||||
if (instr->isAlloca()) {
|
||||
// alloca指令名字不改了,命名就按x,x_1,x_2...来就行
|
||||
auto val = instr;
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
++valPop[val];
|
||||
stacks[val].push(val);
|
||||
++count[val];
|
||||
}
|
||||
} else if (instr->isPhi()) {
|
||||
// Phi指令也是一条特殊的define指令
|
||||
auto val = dynamic_cast<PhiInst *>(instr)->getMapVal();
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
auto i = count[val];
|
||||
if (i == 0) {
|
||||
// 对还未alloca就有phi的指令的处理,直接删除
|
||||
usedelete(iter->get());
|
||||
iter = instrs.erase(iter);
|
||||
continue;
|
||||
}
|
||||
auto newname = dynamic_cast<Instruction *>(val)->getName() + "_" + std::to_string(i);
|
||||
auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname);
|
||||
FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent());
|
||||
ParentfuncInfo->addIndirectAlloca(newalloca);
|
||||
instr->replaceOperand(0, newalloca);
|
||||
++valPop[val];
|
||||
stacks[val].push(newalloca);
|
||||
++count[val];
|
||||
}
|
||||
} else {
|
||||
// store指令看operand的名字,我们的实现是规定变量在operand的第二位,用一个新的alloca x_i代替
|
||||
auto val = instr->getOperand(1);
|
||||
if (!(isArr(val) || isGlobal(val))) {
|
||||
auto i = count[val];
|
||||
auto newname = dynamic_cast<Instruction *>(val)->getName() + "_" + std::to_string(i);
|
||||
auto newalloca = pBuilder->createAllocaInstWithoutInsert(val->getType(), {}, block, newname);
|
||||
FunctionAnalysisInfo* ParentfuncInfo = controlFlowAnalysis->getFunctionAnalysisInfo(block->getParent());
|
||||
ParentfuncInfo->addIndirectAlloca(newalloca);
|
||||
// block->getParent()->addIndirectAlloca(newalloca);
|
||||
instr->replaceOperand(1, newalloca);
|
||||
++valPop[val];
|
||||
stacks[val].push(newalloca);
|
||||
++count[val];
|
||||
}
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
// 第二大步:把所有CFG中的该块的successor的phi指令的相应operand确定
|
||||
for (auto succ : block->getSuccessors()) {
|
||||
auto position = getPredIndex(block, succ);
|
||||
for (auto &instr : succ->getInstructions()) {
|
||||
if (instr->isPhi()) {
|
||||
auto val = dynamic_cast<PhiInst *>(instr.get())->getMapVal();
|
||||
if (!stacks[val].empty()) {
|
||||
instr->replaceOperand(position + 1, stacks[val].top());
|
||||
}
|
||||
} else {
|
||||
// phi指令是添加在块的最前面的,因此过了之后就不会有phi了,直接break
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 第三大步:递归支配树的后继,支配树才能表示define-use关系
|
||||
BlockAnalysisInfo* blockInfo = controlFlowAnalysis->getBlockAnalysisInfo(block);
|
||||
for (auto sdom : blockInfo->getSdoms()) {
|
||||
rename(sdom, count, stacks);
|
||||
}
|
||||
// 第四大步:遍历块中的所有指令,如果涉及到define,就弹栈,这一步是必要的,可以从递归的整体性来思考原因
|
||||
// 注意这里count没清理,因为平级之间计数仍然是一直增加的,但是stack要清理,因为define-use关系来自直接
|
||||
// 支配结点而不是平级之间,不清理栈会被污染
|
||||
// 提前优化:知道变量对应的要弹栈的次数就可以了,没必要遍历所有instr.
|
||||
for (auto val_pair : valPop) {
|
||||
auto val = val_pair.first;
|
||||
for (int i = 0; i < val_pair.second; ++i) {
|
||||
stacks[val].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重命名所有块
|
||||
*
|
||||
* 调用rename,自上而下实现所有rename
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值
|
||||
*/
|
||||
auto Mem2Reg::renameAll() -> void {
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
// 对于每个function都要SSA化,所以count和stacks定义在这并初始化
|
||||
std::unordered_map<Value *, int> count;
|
||||
std::unordered_map<Value *, std::stack<Instruction *>> stacks;
|
||||
FunctionAnalysisInfo* funcInfo = controlFlowAnalysis->getFunctionAnalysisInfo(func);
|
||||
for (const auto &map_pair : funcInfo->getValue2DefBlocks()) {
|
||||
auto val = map_pair.first;
|
||||
count[val] = 0;
|
||||
}
|
||||
rename(func->getEntryBlock(), count, stacks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mem2reg,对外的接口
|
||||
*
|
||||
* 静态单一赋值 + mem2reg等pass的逻辑组合
|
||||
*
|
||||
* @param [in] void
|
||||
* @return 无返回值
|
||||
*/
|
||||
auto Mem2Reg::mem2regPipeline() -> void {
|
||||
// 首先进行mem2reg的前置分析
|
||||
controlFlowAnalysis = new ControlFlowAnalysis(pModule);
|
||||
activeVarAnalysis = new ActiveVarAnalysis();
|
||||
// 控制流分析
|
||||
controlFlowAnalysis->runControlFlowAnalysis();
|
||||
// 活跃变量分析
|
||||
dataFlowAnalysisUtils.addBackwardAnalyzer(activeVarAnalysis);
|
||||
dataFlowAnalysisUtils.backwardAnalyze(pModule);
|
||||
|
||||
// 计算所有valueToBlocks的定义映射
|
||||
computeValue2Blocks();
|
||||
// SysYPrinter printer(pModule);
|
||||
// 参考llvm的mem2reg遍,在插入phi结点之前,先做些优化
|
||||
preOptimize1();
|
||||
// printer.printIR();
|
||||
preOptimize2();
|
||||
// printer.printIR();
|
||||
// 优化三 可能会针对局部变量优化而删除整个块的alloca/store
|
||||
preOptimize3();
|
||||
//再进行活跃变量分析
|
||||
// 报错?
|
||||
|
||||
// printer.printIR();
|
||||
dataFlowAnalysisUtils.backwardAnalyze(pModule);
|
||||
// 为所有变量插入phi结点
|
||||
insertPhi();
|
||||
// 重命名
|
||||
renameAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算块n是块s的第几个前驱
|
||||
*
|
||||
* helperfunction,没有返回值,但是会将dom和other的交集赋值给dom
|
||||
*
|
||||
* @param [in] n 基本块,n是s的前驱之一
|
||||
* @param [in] s 基本块,s是n的后继之一
|
||||
* @return 返回n是s的第几个前驱
|
||||
*/
|
||||
auto Mem2Reg::getPredIndex(BasicBlock *n, BasicBlock *s) -> int {
|
||||
int index = 0;
|
||||
for (auto elem : s->getPredecessors()) {
|
||||
if (elem == n) {
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
assert(index < static_cast<int>(s->getPredecessors().size()) && "n is not a predecessor of s.");
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个value是不是全局变量
|
||||
*/
|
||||
auto Mem2Reg::isGlobal(Value *val) -> bool {
|
||||
auto gval = dynamic_cast<GlobalValue *>(val);
|
||||
return gval != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一个value是不是数组
|
||||
*/
|
||||
auto Mem2Reg::isArr(Value *val) -> bool {
|
||||
auto aval = dynamic_cast<AllocaInst *>(val);
|
||||
return aval != nullptr && aval->getNumDims() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个指令的operand对应的value的该条use
|
||||
*/
|
||||
auto Mem2Reg::usedelete(Instruction *instr) -> void {
|
||||
for (auto &use : instr->getOperands()) {
|
||||
auto val = use->getValue();
|
||||
val->removeUse(use);
|
||||
}
|
||||
}
|
||||
} // namespace sysy
|
||||
|
||||
@@ -1,30 +1,10 @@
|
||||
#include "RISCv32Backend.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
const std::vector<RISCv32CodeGen::PhysicalReg> RISCv32CodeGen::allocable_regs = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3,
|
||||
PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
|
||||
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3,
|
||||
PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
|
||||
};
|
||||
|
||||
std::string RISCv32CodeGen::reg_to_string(PhysicalReg reg) {
|
||||
switch (reg) {
|
||||
case PhysicalReg::T0: return "t0"; case PhysicalReg::T1: return "t1";
|
||||
case PhysicalReg::T2: return "t2"; case PhysicalReg::T3: return "t3";
|
||||
case PhysicalReg::T4: return "t4"; case PhysicalReg::T5: return "t5";
|
||||
case PhysicalReg::T6: return "t6"; case PhysicalReg::A0: return "a0";
|
||||
case PhysicalReg::A1: return "a1"; case PhysicalReg::A2: return "a2";
|
||||
case PhysicalReg::A3: return "a3"; case PhysicalReg::A4: return "a4";
|
||||
case PhysicalReg::A5: return "a5"; case PhysicalReg::A6: return "a6";
|
||||
case PhysicalReg::A7: return "a7";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::code_gen() {
|
||||
std::stringstream ss;
|
||||
ss << ".text\n";
|
||||
@@ -34,16 +14,22 @@ std::string RISCv32CodeGen::code_gen() {
|
||||
|
||||
std::string RISCv32CodeGen::module_gen() {
|
||||
std::stringstream ss;
|
||||
// 生成全局变量(数据段)
|
||||
for (const auto& global : module->getGlobals()) {
|
||||
ss << ".data\n";
|
||||
ss << ".globl " << global->getName() << "\n";
|
||||
for (auto& global : module->getGlobals()) {
|
||||
ss << ".global " << global->getName() << "\n";
|
||||
ss << ".section .data\n";
|
||||
ss << ".align 2\n";
|
||||
ss << global->getName() << ":\n";
|
||||
ss << " .word 0\n"; // 假设初始化为0
|
||||
for (auto value : global->getInitValues().getValues()) {
|
||||
auto const_val = dynamic_cast<ConstantValue*>(value);
|
||||
if (const_val->isInt()) {
|
||||
ss << ".word " << const_val->getInt() << "\n";
|
||||
} else {
|
||||
ss << ".float " << const_val->getFloat() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// 生成函数(文本段)
|
||||
ss << ".text\n";
|
||||
for (const auto& func : module->getFunctions()) {
|
||||
ss << ".section .text\n";
|
||||
for (auto& func : module->getFunctions()) {
|
||||
ss << function_gen(func.second.get());
|
||||
}
|
||||
return ss.str();
|
||||
@@ -51,107 +37,582 @@ std::string RISCv32CodeGen::module_gen() {
|
||||
|
||||
std::string RISCv32CodeGen::function_gen(Function* func) {
|
||||
std::stringstream ss;
|
||||
// 函数标签
|
||||
ss << ".globl " << func->getName() << "\n";
|
||||
ss << ".global " << func->getName() << "\n";
|
||||
ss << ".type " << func->getName() << ", @function\n";
|
||||
ss << func->getName() << ":\n";
|
||||
// 序言:保存 ra,分配堆栈
|
||||
bool is_leaf = true; // 简化假设
|
||||
ss << " addi sp, sp, -16\n";
|
||||
ss << " sw ra, 12(sp)\n";
|
||||
// 寄存器分配
|
||||
auto alloc = register_allocation(func);
|
||||
// 生成基本块代码
|
||||
for (const auto& bb : func->getBasicBlocks()) {
|
||||
ss << basicBlock_gen(bb.get(), alloc);
|
||||
|
||||
// Perform register allocation
|
||||
auto live_sets = liveness_analysis(func);
|
||||
auto interference_graph = build_interference_graph(live_sets);
|
||||
auto alloc = color_graph(func, interference_graph);
|
||||
|
||||
// Prologue: Adjust stack and save callee-saved registers
|
||||
if (alloc.stack_size > 0) {
|
||||
ss << " addi sp, sp, -" << alloc.stack_size << "\n";
|
||||
ss << " sw ra, " << (alloc.stack_size - 4) << "(sp)\n";
|
||||
}
|
||||
for (auto preg : callee_saved) {
|
||||
if (std::find_if(alloc.vreg_to_preg.begin(), alloc.vreg_to_preg.end(),
|
||||
[preg](const auto& pair) { return pair.second == preg; }) != alloc.vreg_to_preg.end()) {
|
||||
ss << " sw " << get_preg_str(preg) << ", " << (alloc.stack_size - 8) << "(sp)\n";
|
||||
}
|
||||
}
|
||||
|
||||
int block_idx = 0;
|
||||
for (auto& bb : func->getBasicBlocks()) {
|
||||
ss << basicBlock_gen(bb.get(), alloc, block_idx++);
|
||||
}
|
||||
|
||||
// Epilogue: Restore callee-saved registers and stack
|
||||
for (auto preg : callee_saved) {
|
||||
if (std::find_if(alloc.vreg_to_preg.begin(), alloc.vreg_to_preg.end(),
|
||||
[preg](const auto& pair) { return pair.second == preg; }) != alloc.vreg_to_preg.end()) {
|
||||
ss << " lw " << get_preg_str(preg) << ", " << (alloc.stack_size - 8) << "(sp)\n";
|
||||
}
|
||||
}
|
||||
if (alloc.stack_size > 0) {
|
||||
ss << " lw ra, " << (alloc.stack_size - 4) << "(sp)\n";
|
||||
ss << " addi sp, sp, " << alloc.stack_size << "\n";
|
||||
}
|
||||
// 结尾:恢复 ra,释放堆栈
|
||||
ss << " lw ra, 12(sp)\n";
|
||||
ss << " addi sp, sp, 16\n";
|
||||
ss << " ret\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string RISCv32CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc) {
|
||||
std::string RISCv32CodeGen::basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx) {
|
||||
std::stringstream ss;
|
||||
ss << bb->getName() << ":\n";
|
||||
for (const auto& inst : bb->getInstructions()) {
|
||||
auto riscv_insts = instruction_gen(inst.get());
|
||||
for (const auto& riscv_inst : riscv_insts) {
|
||||
ss << " " << riscv_inst.opcode;
|
||||
for (size_t i = 0; i < riscv_inst.operands.size(); ++i) {
|
||||
if (i > 0) ss << ", ";
|
||||
if (riscv_inst.operands[i].kind == Operand::Kind::Reg) {
|
||||
auto it = alloc.reg_map.find(riscv_inst.operands[i].value);
|
||||
if (it != alloc.reg_map.end()) {
|
||||
ss << reg_to_string(it->second);
|
||||
} else {
|
||||
auto stack_it = alloc.stack_map.find(riscv_inst.operands[i].value);
|
||||
if (stack_it != alloc.stack_map.end()) {
|
||||
ss << stack_it->second << "(sp)";
|
||||
} else {
|
||||
ss << "%" << riscv_inst.operands[i].value->getName();
|
||||
}
|
||||
}
|
||||
} else if (riscv_inst.operands[i].kind == Operand::Kind::Imm) {
|
||||
ss << riscv_inst.operands[i].label;
|
||||
} else {
|
||||
ss << riscv_inst.operands[i].label;
|
||||
}
|
||||
}
|
||||
ss << "\n";
|
||||
}
|
||||
ss << ".L" << block_idx << ":\n";
|
||||
auto dag_nodes = build_dag(bb);
|
||||
for (auto& node : dag_nodes) {
|
||||
select_instructions(node.get(), alloc);
|
||||
}
|
||||
std::set<DAGNode*> emitted_nodes;
|
||||
for (auto& node : dag_nodes) {
|
||||
emit_instructions(node.get(), ss, alloc, emitted_nodes);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<RISCv32CodeGen::RISCv32Inst> RISCv32CodeGen::instruction_gen(Instruction* inst) {
|
||||
std::vector<RISCv32Inst> insts;
|
||||
if (auto bin = dynamic_cast<BinaryInst*>(inst)) {
|
||||
std::string opcode;
|
||||
if (bin->getKind() == BinaryInst::kAdd) opcode = "add";
|
||||
else if (bin->getKind() == BinaryInst::kSub) opcode = "sub";
|
||||
else if (bin->getKind() == BinaryInst::kMul) opcode = "mul";
|
||||
else return insts; // 其他操作未实现
|
||||
insts.emplace_back(opcode, std::vector<Operand>{
|
||||
{Operand::Kind::Reg, bin},
|
||||
{Operand::Kind::Reg, bin->getLhs()},
|
||||
{Operand::Kind::Reg, bin->getRhs()}
|
||||
});
|
||||
} else if (auto load = dynamic_cast<LoadInst*>(inst)) {
|
||||
insts.emplace_back("lw", std::vector<Operand>{
|
||||
{Operand::Kind::Reg, load},
|
||||
{Operand::Kind::Label, load->getPointer()->getName()}
|
||||
});
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst)) {
|
||||
insts.emplace_back("sw", std::vector<Operand>{
|
||||
{Operand::Kind::Reg, store->getValue()},
|
||||
{Operand::Kind::Label, store->getPointer()->getName()}
|
||||
});
|
||||
std::vector<std::unique_ptr<RISCv32CodeGen::DAGNode>> RISCv32CodeGen::build_dag(BasicBlock* bb) {
|
||||
std::vector<std::unique_ptr<DAGNode>> nodes;
|
||||
std::map<Value*, DAGNode*> value_to_node;
|
||||
int vreg_counter = 0;
|
||||
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::ALLOCA_ADDR);
|
||||
node->value = alloca;
|
||||
node->result_vreg = "%" + inst->getName(); // Use IR name (%a(0), %b(0))
|
||||
value_to_node[alloca] = node.get();
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto load = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::LOAD);
|
||||
node->value = load;
|
||||
node->result_vreg = "%" + inst->getName(); // Use IR name (%0, %1)
|
||||
auto pointer = load->getPointer();
|
||||
if (value_to_node.count(pointer)) {
|
||||
node->operands.push_back(value_to_node[pointer]);
|
||||
value_to_node[pointer]->users.push_back(node.get());
|
||||
}
|
||||
value_to_node[load] = node.get();
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto store = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::STORE);
|
||||
node->value = store;
|
||||
auto value_operand = store->getValue();
|
||||
auto pointer = store->getPointer();
|
||||
if (value_to_node.count(value_operand)) {
|
||||
node->operands.push_back(value_to_node[value_operand]);
|
||||
value_to_node[value_operand]->users.push_back(node.get());
|
||||
} else if (auto const_val = dynamic_cast<ConstantValue*>(value_operand)) {
|
||||
auto const_node = std::make_unique<DAGNode>(DAGNode::CONSTANT);
|
||||
const_node->value = const_val;
|
||||
const_node->result_vreg = "%" + std::to_string(vreg_counter++); // Use simple %N for constants
|
||||
value_to_node[value_operand] = const_node.get();
|
||||
node->operands.push_back(const_node.get());
|
||||
const_node->users.push_back(node.get());
|
||||
nodes.push_back(std::move(const_node));
|
||||
}
|
||||
if (value_to_node.count(pointer)) {
|
||||
node->operands.push_back(value_to_node[pointer]);
|
||||
value_to_node[pointer]->users.push_back(node.get());
|
||||
}
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto binary = dynamic_cast<BinaryInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::BINARY);
|
||||
node->value = binary;
|
||||
node->result_vreg = "%" + inst->getName(); // Use IR name (%2)
|
||||
for (auto operand : binary->getOperands()) {
|
||||
auto op_value = operand->getValue();
|
||||
if (value_to_node.count(op_value)) {
|
||||
node->operands.push_back(value_to_node[op_value]);
|
||||
value_to_node[op_value]->users.push_back(node.get());
|
||||
} else if (auto const_val = dynamic_cast<ConstantValue*>(op_value)) {
|
||||
auto const_node = std::make_unique<DAGNode>(DAGNode::CONSTANT);
|
||||
const_node->value = const_val;
|
||||
const_node->result_vreg = "%" + std::to_string(vreg_counter++);
|
||||
value_to_node[op_value] = const_node.get();
|
||||
node->operands.push_back(const_node.get());
|
||||
const_node->users.push_back(node.get());
|
||||
nodes.push_back(std::move(const_node));
|
||||
}
|
||||
}
|
||||
value_to_node[binary] = node.get();
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto ret = dynamic_cast<ReturnInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::RETURN);
|
||||
node->value = ret;
|
||||
if (ret->hasReturnValue()) {
|
||||
auto value_operand = ret->getReturnValue();
|
||||
if (value_to_node.count(value_operand)) {
|
||||
node->operands.push_back(value_to_node[value_operand]);
|
||||
value_to_node[value_operand]->users.push_back(node.get());
|
||||
} else if (auto const_val = dynamic_cast<ConstantValue*>(value_operand)) {
|
||||
auto const_node = std::make_unique<DAGNode>(DAGNode::CONSTANT);
|
||||
const_node->value = const_val;
|
||||
const_node->result_vreg = "%" + std::to_string(vreg_counter++);
|
||||
value_to_node[value_operand] = const_node.get();
|
||||
node->operands.push_back(const_node.get());
|
||||
const_node->users.push_back(node.get());
|
||||
nodes.push_back(std::move(const_node));
|
||||
}
|
||||
}
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto cond_br = dynamic_cast<CondBrInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::BRANCH);
|
||||
node->value = cond_br;
|
||||
auto condition = cond_br->getCondition();
|
||||
if (value_to_node.count(condition)) {
|
||||
node->operands.push_back(value_to_node[condition]);
|
||||
value_to_node[condition]->users.push_back(node.get());
|
||||
} else if (auto const_val = dynamic_cast<ConstantValue*>(condition)) {
|
||||
auto const_node = std::make_unique<DAGNode>(DAGNode::CONSTANT);
|
||||
const_node->value = const_val;
|
||||
const_node->result_vreg = "%" + std::to_string(vreg_counter++);
|
||||
value_to_node[condition] = const_node.get();
|
||||
node->operands.push_back(const_node.get());
|
||||
const_node->users.push_back(node.get());
|
||||
nodes.push_back(std::move(const_node));
|
||||
}
|
||||
nodes.push_back(std::move(node));
|
||||
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(inst.get())) {
|
||||
auto node = std::make_unique<DAGNode>(DAGNode::BRANCH);
|
||||
node->value = uncond_br;
|
||||
nodes.push_back(std::move(node));
|
||||
}
|
||||
}
|
||||
return insts;
|
||||
return nodes;
|
||||
}
|
||||
|
||||
void RISCv32CodeGen::eliminate_phi(Function* func) {
|
||||
// TODO: 实现 phi 指令消除
|
||||
void RISCv32CodeGen::select_instructions(DAGNode* node, const RegAllocResult& alloc) {
|
||||
if (node->inst.empty()) {
|
||||
switch (node->kind) {
|
||||
case DAGNode::CONSTANT: {
|
||||
auto const_val = dynamic_cast<ConstantValue*>(node->value);
|
||||
if (const_val->isInt()) {
|
||||
node->inst = "li " + node->result_vreg + ", " + std::to_string(const_val->getInt());
|
||||
} else {
|
||||
node->inst = "# float constant not implemented";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DAGNode::LOAD: {
|
||||
auto load = dynamic_cast<LoadInst*>(node->value);
|
||||
auto pointer = load->getPointer();
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(pointer)) {
|
||||
if (alloc.stack_map.count(alloca)) {
|
||||
node->inst = "lw " + node->result_vreg + ", " + std::to_string(alloc.stack_map.at(alloca)) + "(sp)";
|
||||
}
|
||||
} else if (auto global = dynamic_cast<GlobalValue*>(pointer)) {
|
||||
node->inst = "lw " + node->result_vreg + ", " + global->getName() + "(gp)";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DAGNode::STORE: {
|
||||
auto store = dynamic_cast<StoreInst*>(node->value);
|
||||
auto pointer = store->getPointer();
|
||||
auto value_vreg = node->operands[0]->result_vreg;
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(pointer)) {
|
||||
if (alloc.stack_map.count(alloca)) {
|
||||
node->inst = "sw " + value_vreg + ", " + std::to_string(alloc.stack_map.at(alloca)) + "(sp)";
|
||||
}
|
||||
} else if (auto global = dynamic_cast<GlobalValue*>(pointer)) {
|
||||
node->inst = "sw " + value_vreg + ", " + global->getName() + "(gp)";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DAGNode::BINARY: {
|
||||
auto binary = dynamic_cast<BinaryInst*>(node->value);
|
||||
auto lhs_vreg = node->operands[0]->result_vreg;
|
||||
auto rhs_vreg = node->operands[1]->result_vreg;
|
||||
std::string op;
|
||||
switch (binary->getKind()) {
|
||||
case Instruction::kAdd: op = "add"; break;
|
||||
case Instruction::kSub: op = "sub"; break;
|
||||
case Instruction::kMul: op = "mul"; break;
|
||||
case Instruction::kDiv: op = "div"; break;
|
||||
case Instruction::kICmpEQ: op = "seq"; break;
|
||||
case Instruction::kICmpNE: op = "sne"; break;
|
||||
case Instruction::kICmpLT: op = "slt"; break;
|
||||
case Instruction::kICmpGT: op = "sgt"; break;
|
||||
case Instruction::kICmpLE: op = "sle"; break;
|
||||
case Instruction::kICmpGE: op = "sge"; break;
|
||||
default: op = "# unknown"; break;
|
||||
}
|
||||
node->inst = op + " " + node->result_vreg + ", " + lhs_vreg + ", " + rhs_vreg;
|
||||
break;
|
||||
}
|
||||
case DAGNode::RETURN: {
|
||||
auto ret = dynamic_cast<ReturnInst*>(node->value);
|
||||
if (ret->hasReturnValue()) {
|
||||
auto value_vreg = node->operands[0]->result_vreg;
|
||||
node->inst = "mv a0, " + value_vreg;
|
||||
} else {
|
||||
node->inst = "ret";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DAGNode::BRANCH: {
|
||||
if (auto cond_br = dynamic_cast<CondBrInst*>(node->value)) {
|
||||
auto condition_vreg = node->operands[0]->result_vreg;
|
||||
auto then_block = cond_br->getThenBlock();
|
||||
auto else_block = cond_br->getElseBlock();
|
||||
int then_idx = 0, else_idx = 0;
|
||||
int idx = 0;
|
||||
for (auto& bb : cond_br->getFunction()->getBasicBlocks()) {
|
||||
if (bb.get() == then_block) then_idx = idx;
|
||||
if (bb.get() == else_block) else_idx = idx;
|
||||
idx++;
|
||||
}
|
||||
node->inst = "bne " + condition_vreg + ", zero, .L" + std::to_string(then_idx) + "\n j .L" + std::to_string(else_idx);
|
||||
} else if (auto uncond_br = dynamic_cast<UncondBrInst*>(node->value)) {
|
||||
auto target_block = uncond_br->getBlock();
|
||||
int target_idx = 0;
|
||||
int idx = 0;
|
||||
for (auto& bb : uncond_br->getFunction()->getBasicBlocks()) {
|
||||
if (bb.get() == target_block) target_idx = idx;
|
||||
idx++;
|
||||
}
|
||||
node->inst = "j .L" + std::to_string(target_idx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
node->inst = "# unimplemented";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<Instruction*, std::set<Value*>> RISCv32CodeGen::liveness_analysis(Function* func) {
|
||||
std::map<Instruction*, std::set<Value*>> live_sets;
|
||||
// TODO: 实现活跃性分析
|
||||
return live_sets;
|
||||
void RISCv32CodeGen::emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set<DAGNode*>& emitted_nodes) {
|
||||
if (emitted_nodes.count(node)) return;
|
||||
for (auto operand : node->operands) {
|
||||
emit_instructions(operand, ss, alloc, emitted_nodes);
|
||||
}
|
||||
if (!node->inst.empty() && node->inst != "# unimplemented" && node->inst.find("# alloca") == std::string::npos) {
|
||||
std::string inst = node->inst;
|
||||
std::vector<std::pair<std::string, std::string>> replacements;
|
||||
|
||||
// Collect replacements for result and operand virtual registers
|
||||
if (node->result_vreg != "" && node->kind != DAGNode::ALLOCA_ADDR) {
|
||||
if (alloc.vreg_to_preg.count(node->result_vreg)) {
|
||||
replacements.emplace_back(node->result_vreg, get_preg_str(alloc.vreg_to_preg.at(node->result_vreg)));
|
||||
} else if (alloc.spill_map.count(node->result_vreg)) {
|
||||
auto temp_reg = PhysicalReg::T0;
|
||||
replacements.emplace_back(node->result_vreg, get_preg_str(temp_reg));
|
||||
inst = inst.substr(0, inst.find('\n')); // Handle multi-line instructions
|
||||
ss << " " << inst << "\n";
|
||||
ss << " sw " << get_preg_str(temp_reg) << ", " << alloc.spill_map.at(node->result_vreg) << "(sp)\n";
|
||||
emitted_nodes.insert(node);
|
||||
return;
|
||||
} else {
|
||||
ss << "# Error: Virtual register " << node->result_vreg << " not allocated (kind: " << node->getNodeKindString() << ")\n";
|
||||
}
|
||||
}
|
||||
for (auto operand : node->operands) {
|
||||
if (operand->result_vreg != "" && operand->kind != DAGNode::ALLOCA_ADDR) {
|
||||
if (alloc.vreg_to_preg.count(operand->result_vreg)) {
|
||||
replacements.emplace_back(operand->result_vreg, get_preg_str(alloc.vreg_to_preg.at(operand->result_vreg)));
|
||||
} else if (alloc.spill_map.count(operand->result_vreg)) {
|
||||
auto temp_reg = PhysicalReg::T1;
|
||||
ss << " lw " << get_preg_str(temp_reg) << ", " << alloc.spill_map.at(operand->result_vreg) << "(sp)\n";
|
||||
replacements.emplace_back(operand->result_vreg, get_preg_str(temp_reg));
|
||||
} else {
|
||||
ss << "# Error: Operand virtual register " << operand->result_vreg << " not allocated (kind: " << operand->getNodeKindString() << ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform all replacements only if vreg exists in inst
|
||||
for (const auto& [vreg, preg] : replacements) {
|
||||
size_t pos = inst.find(vreg);
|
||||
while (pos != std::string::npos) {
|
||||
inst.replace(pos, vreg.length(), preg);
|
||||
pos = inst.find(vreg, pos + preg.length());
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the instruction
|
||||
if (node->kind == DAGNode::BRANCH || inst.find('\n') != std::string::npos) {
|
||||
ss << inst << "\n";
|
||||
} else if (inst != "ret") {
|
||||
ss << " " << inst << "\n";
|
||||
}
|
||||
}
|
||||
emitted_nodes.insert(node);
|
||||
}
|
||||
|
||||
std::map<Value*, std::set<Value*>> RISCv32CodeGen::build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets) {
|
||||
std::map<Value*, std::set<Value*>> graph;
|
||||
// TODO: 实现干扰图构建
|
||||
return graph;
|
||||
std::map<Instruction*, std::set<std::string>> RISCv32CodeGen::liveness_analysis(Function* func) {
|
||||
std::map<Instruction*, std::set<std::string>> live_in, live_out;
|
||||
bool changed;
|
||||
|
||||
// Build DAG for all basic blocks
|
||||
std::map<BasicBlock*, std::vector<std::unique_ptr<DAGNode>>> bb_dags;
|
||||
for (auto& bb : func->getBasicBlocks()) {
|
||||
bb_dags[bb.get()] = build_dag(bb.get());
|
||||
}
|
||||
|
||||
// Initialize live_in and live_out
|
||||
for (auto& bb : func->getBasicBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
live_in[inst.get()];
|
||||
live_out[inst.get()];
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
changed = false;
|
||||
for (auto& bb : func->getBasicBlocks()) {
|
||||
// Reverse iterate for backward analysis
|
||||
for (auto it = bb->getInstructions().rbegin(); it != bb->getInstructions().rend(); ++it) {
|
||||
auto inst = it->get();
|
||||
std::set<std::string> new_live_in, new_live_out;
|
||||
|
||||
// live_out = union of live_in of successors
|
||||
for (auto succ : bb->getSuccessors()) {
|
||||
if (!succ->getInstructions().empty()) {
|
||||
auto succ_inst = succ->getInstructions().front().get();
|
||||
new_live_out.insert(live_in[succ_inst].begin(), live_in[succ_inst].end());
|
||||
}
|
||||
}
|
||||
|
||||
// Collect def and use
|
||||
std::set<std::string> def, use;
|
||||
// IR instruction def
|
||||
if (inst->getName() != "" && !dynamic_cast<AllocaInst*>(inst)) {
|
||||
def.insert("%" + inst->getName());
|
||||
}
|
||||
// IR instruction use
|
||||
for (auto operand : inst->getOperands()) {
|
||||
auto value = operand->getValue();
|
||||
if (auto op_inst = dynamic_cast<Instruction*>(value)) {
|
||||
if (op_inst->getName() != "" && !dynamic_cast<AllocaInst*>(op_inst)) {
|
||||
use.insert("%" + op_inst->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DAG node def and use
|
||||
for (auto& node : bb_dags[bb.get()]) {
|
||||
if (node->value == inst && node->kind != DAGNode::ALLOCA_ADDR) {
|
||||
if (node->result_vreg != "") {
|
||||
def.insert(node->result_vreg);
|
||||
}
|
||||
for (auto operand : node->operands) {
|
||||
if (operand->result_vreg != "" && operand->kind != DAGNode::ALLOCA_ADDR) {
|
||||
use.insert(operand->result_vreg);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Constants
|
||||
if (node->kind == DAGNode::CONSTANT) {
|
||||
for (auto user : node->users) {
|
||||
if (user->value == inst) {
|
||||
use.insert(node->result_vreg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// live_in = use U (live_out - def)
|
||||
std::set<std::string> live_out_minus_def;
|
||||
std::set_difference(new_live_out.begin(), new_live_out.end(),
|
||||
def.begin(), def.end(),
|
||||
std::inserter(live_out_minus_def, live_out_minus_def.begin()));
|
||||
new_live_in.insert(use.begin(), use.end());
|
||||
new_live_in.insert(live_out_minus_def.begin(), live_out_minus_def.end());
|
||||
|
||||
// Debug
|
||||
std::cerr << "Instruction: " << (inst->getName() != "" ? "%" + inst->getName() : "none") << "\n";
|
||||
std::cerr << " def: "; for (const auto& d : def) std::cerr << d << " "; std::cerr << "\n";
|
||||
std::cerr << " use: "; for (const auto& u : use) std::cerr << u << " "; std::cerr << "\n";
|
||||
std::cerr << " live_in: "; for (const auto& v : new_live_in) std::cerr << v << " "; std::cerr << "\n";
|
||||
std::cerr << " live_out: "; for (const auto& v : new_live_out) std::cerr << v << " "; std::cerr << "\n";
|
||||
|
||||
if (live_in[inst] != new_live_in || live_out[inst] != new_live_out) {
|
||||
live_in[inst] = new_live_in;
|
||||
live_out[inst] = new_live_out;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
|
||||
// Debug live_out
|
||||
for (const auto& [inst, live_vars] : live_out) {
|
||||
std::cerr << "Instruction: " << (inst->getName() != "" ? "%" + inst->getName() : "none") << " live_out: ";
|
||||
for (const auto& var : live_vars) {
|
||||
std::cerr << var << " ";
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
return live_out;
|
||||
}
|
||||
|
||||
RISCv32CodeGen::RegAllocResult RISCv32CodeGen::register_allocation(Function* func) {
|
||||
RegAllocResult result;
|
||||
// TODO: 实现寄存器分配
|
||||
return result;
|
||||
std::map<std::string, std::set<std::string>> RISCv32CodeGen::build_interference_graph(
|
||||
const std::map<Instruction*, std::set<std::string>>& live_sets) {
|
||||
std::map<std::string, std::set<std::string>> interference_graph;
|
||||
for (const auto& [inst, live_vars] : live_sets) {
|
||||
std::string def_var = inst->getName() != "" && !dynamic_cast<AllocaInst*>(inst) ? "%" + inst->getName() : "";
|
||||
if (def_var != "") {
|
||||
interference_graph[def_var]; // Initialize
|
||||
for (const auto& live_var : live_vars) {
|
||||
if (live_var != def_var && live_var.find("%a(") != 0 && live_var.find("%b(") != 0) {
|
||||
interference_graph[def_var].insert(live_var);
|
||||
interference_graph[live_var].insert(def_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Initialize all live variables
|
||||
for (const auto& live_var : live_vars) {
|
||||
if (live_var.find("%a(") != 0 && live_var.find("%b(") != 0) {
|
||||
interference_graph[live_var];
|
||||
}
|
||||
}
|
||||
// Live variables interfere with each other
|
||||
for (auto it1 = live_vars.begin(); it1 != live_vars.end(); ++it1) {
|
||||
if (it1->find("%a(") == 0 || it1->find("%b(") == 0) continue;
|
||||
for (auto it2 = std::next(it1); it2 != live_vars.end(); ++it2) {
|
||||
if (it2->find("%a(") == 0 || it2->find("%b(") == 0) continue;
|
||||
interference_graph[*it1].insert(*it2);
|
||||
interference_graph[*it2].insert(*it1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug
|
||||
for (const auto& [vreg, neighbors] : interference_graph) {
|
||||
std::cerr << "Vreg " << vreg << " interferes with: ";
|
||||
for (const auto& neighbor : neighbors) {
|
||||
std::cerr << neighbor << " ";
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
return interference_graph;
|
||||
}
|
||||
|
||||
RISCv32CodeGen::RegAllocResult RISCv32CodeGen::color_graph(Function* func, const std::map<std::string, std::set<std::string>>& interference_graph) {
|
||||
RegAllocResult alloc;
|
||||
std::map<std::string, std::set<std::string>> ig = interference_graph;
|
||||
std::stack<std::string> stack;
|
||||
std::set<std::string> spilled;
|
||||
|
||||
// Available physical registers
|
||||
std::vector<PhysicalReg> available_regs = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
|
||||
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5,
|
||||
PhysicalReg::S6, PhysicalReg::S7, PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11
|
||||
};
|
||||
|
||||
// Simplify: Push nodes with degree < number of registers
|
||||
while (!ig.empty()) {
|
||||
bool simplified = false;
|
||||
for (auto it = ig.begin(); it != ig.end();) {
|
||||
if (it->second.size() < available_regs.size()) {
|
||||
stack.push(it->first);
|
||||
for (auto& [vreg, neighbors] : ig) {
|
||||
neighbors.erase(it->first);
|
||||
}
|
||||
it = ig.erase(it);
|
||||
simplified = true;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!simplified) {
|
||||
// Spill the node with the highest degree
|
||||
auto max_it = ig.begin();
|
||||
for (auto it = ig.begin(); it != ig.end(); ++it) {
|
||||
if (it->second.size() > max_it->second.size()) {
|
||||
max_it = it;
|
||||
}
|
||||
}
|
||||
spilled.insert(max_it->first);
|
||||
for (auto& [vreg, neighbors] : ig) {
|
||||
neighbors.erase(max_it->first);
|
||||
}
|
||||
ig.erase(max_it);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign colors (physical registers)
|
||||
while (!stack.empty()) {
|
||||
auto vreg = stack.top();
|
||||
stack.pop();
|
||||
std::set<PhysicalReg> used_colors;
|
||||
if (interference_graph.count(vreg)) {
|
||||
for (const auto& neighbor : interference_graph.at(vreg)) {
|
||||
if (alloc.vreg_to_preg.count(neighbor)) {
|
||||
used_colors.insert(alloc.vreg_to_preg.at(neighbor));
|
||||
}
|
||||
}
|
||||
}
|
||||
bool assigned = false;
|
||||
for (auto preg : available_regs) {
|
||||
if (!used_colors.count(preg)) {
|
||||
alloc.vreg_to_preg[vreg] = preg;
|
||||
assigned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!assigned) {
|
||||
spilled.insert(vreg);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate stack space for AllocaInst and spilled virtual registers
|
||||
int stack_offset = 0;
|
||||
for (auto& bb : func->getBasicBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
|
||||
alloc.stack_map[alloca] = stack_offset;
|
||||
stack_offset += 4; // 4 bytes per variable
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& vreg : spilled) {
|
||||
alloc.spill_map[vreg] = stack_offset;
|
||||
stack_offset += 4;
|
||||
}
|
||||
alloc.stack_size = stack_offset + 8; // Extra space for ra and callee-saved
|
||||
|
||||
// Debug output to verify register allocation
|
||||
for (const auto& [vreg, preg] : alloc.vreg_to_preg) {
|
||||
std::cerr << "Vreg " << vreg << " assigned to " << get_preg_str(preg) << "\n";
|
||||
}
|
||||
for (const auto& vreg : spilled) {
|
||||
std::cerr << "Vreg " << vreg << " spilled to stack offset " << alloc.spill_map.at(vreg) << "\n";
|
||||
}
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
||||
RISCv32CodeGen::PhysicalReg RISCv32CodeGen::get_preg_or_temp(const std::string& vreg, const RegAllocResult& alloc) const {
|
||||
if (alloc.vreg_to_preg.count(vreg)) {
|
||||
return alloc.vreg_to_preg.at(vreg);
|
||||
}
|
||||
return PhysicalReg::T0; // Fallback for spilled registers, handled in emit_instructions
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -6,60 +6,96 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class RISCv32CodeGen {
|
||||
public:
|
||||
explicit RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
std::string code_gen(); // 生成模块的汇编代码
|
||||
enum class PhysicalReg {
|
||||
ZERO, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
|
||||
};
|
||||
|
||||
struct DAGNode {
|
||||
enum NodeKind { CONSTANT, LOAD, STORE, BINARY, CALL, RETURN, BRANCH, ALLOCA_ADDR };
|
||||
NodeKind kind;
|
||||
Value* value = nullptr;
|
||||
std::string inst;
|
||||
std::string result_vreg;
|
||||
std::vector<DAGNode*> operands;
|
||||
std::vector<DAGNode*> users;
|
||||
DAGNode(NodeKind k) : kind(k) {}
|
||||
|
||||
std::string getNodeKindString() const {
|
||||
switch (kind) {
|
||||
case CONSTANT: return "CONSTANT";
|
||||
case LOAD: return "LOAD";
|
||||
case STORE: return "STORE";
|
||||
case BINARY: return "BINARY";
|
||||
case CALL: return "CALL";
|
||||
case RETURN: return "RETURN";
|
||||
case BRANCH: return "BRANCH";
|
||||
case ALLOCA_ADDR: return "ALLOCA_ADDR";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct RegAllocResult {
|
||||
std::map<std::string, PhysicalReg> vreg_to_preg; // 虚拟寄存器到物理寄存器的映射
|
||||
std::map<Value*, int> stack_map; // AllocaInst到栈偏移的映射
|
||||
std::map<std::string, int> spill_map; // 溢出的虚拟寄存器到栈偏移的映射
|
||||
int stack_size = 0; // 总栈帧大小
|
||||
};
|
||||
|
||||
RISCv32CodeGen(Module* mod) : module(mod) {}
|
||||
|
||||
std::string code_gen();
|
||||
std::string module_gen();
|
||||
std::string function_gen(Function* func);
|
||||
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc, int block_idx);
|
||||
std::vector<std::unique_ptr<DAGNode>> build_dag(BasicBlock* bb);
|
||||
void select_instructions(DAGNode* node, const RegAllocResult& alloc);
|
||||
void emit_instructions(DAGNode* node, std::stringstream& ss, const RegAllocResult& alloc, std::set<DAGNode*>& emitted_nodes);
|
||||
std::map<Instruction*, std::set<std::string>> liveness_analysis(Function* func);
|
||||
std::map<std::string, std::set<std::string>> build_interference_graph(
|
||||
const std::map<Instruction*, std::set<std::string>>& live_sets);
|
||||
RegAllocResult color_graph(Function* func, const std::map<std::string, std::set<std::string>>& interference_graph);
|
||||
|
||||
private:
|
||||
Module* module;
|
||||
|
||||
// 物理寄存器
|
||||
enum class PhysicalReg {
|
||||
T0, T1, T2, T3, T4, T5, T6, // x5-x7, x28-x31
|
||||
A0, A1, A2, A3, A4, A5, A6, A7 // x10-x17
|
||||
};
|
||||
static const std::vector<PhysicalReg> allocable_regs;
|
||||
|
||||
// 操作数
|
||||
struct Operand {
|
||||
enum class Kind { Reg, Imm, Label };
|
||||
Kind kind;
|
||||
Value* value; // 用于寄存器
|
||||
std::string label; // 用于标签或立即数
|
||||
Operand(Kind k, Value* v) : kind(k), value(v), label("") {}
|
||||
Operand(Kind k, const std::string& l) : kind(k), value(nullptr), label(l) {}
|
||||
std::map<PhysicalReg, std::string> preg_to_str = {
|
||||
{PhysicalReg::ZERO, "zero"}, {PhysicalReg::RA, "ra"}, {PhysicalReg::SP, "sp"},
|
||||
{PhysicalReg::GP, "gp"}, {PhysicalReg::TP, "tp"}, {PhysicalReg::T0, "t0"},
|
||||
{PhysicalReg::T1, "t1"}, {PhysicalReg::T2, "t2"}, {PhysicalReg::S0, "s0"},
|
||||
{PhysicalReg::S1, "s1"}, {PhysicalReg::A0, "a0"}, {PhysicalReg::A1, "a1"},
|
||||
{PhysicalReg::A2, "a2"}, {PhysicalReg::A3, "a3"}, {PhysicalReg::A4, "a4"},
|
||||
{PhysicalReg::A5, "a5"}, {PhysicalReg::A6, "a6"}, {PhysicalReg::A7, "a7"},
|
||||
{PhysicalReg::S2, "s2"}, {PhysicalReg::S3, "s3"}, {PhysicalReg::S4, "s4"},
|
||||
{PhysicalReg::S5, "s5"}, {PhysicalReg::S6, "s6"}, {PhysicalReg::S7, "s7"},
|
||||
{PhysicalReg::S8, "s8"}, {PhysicalReg::S9, "s9"}, {PhysicalReg::S10, "s10"},
|
||||
{PhysicalReg::S11, "s11"}, {PhysicalReg::T3, "t3"}, {PhysicalReg::T4, "t4"},
|
||||
{PhysicalReg::T5, "t5"}, {PhysicalReg::T6, "t6"}
|
||||
};
|
||||
|
||||
// RISC-V 指令
|
||||
struct RISCv32Inst {
|
||||
std::string opcode;
|
||||
std::vector<Operand> operands;
|
||||
RISCv32Inst(const std::string& op, const std::vector<Operand>& ops)
|
||||
: opcode(op), operands(ops) {}
|
||||
std::vector<PhysicalReg> caller_saved = {
|
||||
PhysicalReg::T0, PhysicalReg::T1, PhysicalReg::T2, PhysicalReg::T3, PhysicalReg::T4, PhysicalReg::T5, PhysicalReg::T6,
|
||||
PhysicalReg::A0, PhysicalReg::A1, PhysicalReg::A2, PhysicalReg::A3, PhysicalReg::A4, PhysicalReg::A5, PhysicalReg::A6, PhysicalReg::A7
|
||||
};
|
||||
|
||||
// 寄存器分配结果
|
||||
struct RegAllocResult {
|
||||
std::map<Value*, PhysicalReg> reg_map; // 虚拟寄存器到物理寄存器的映射
|
||||
std::map<Value*, int> stack_map; // 虚拟寄存器到堆栈槽的映射
|
||||
int stack_size; // 堆栈帧大小
|
||||
std::vector<PhysicalReg> callee_saved = {
|
||||
PhysicalReg::S0, PhysicalReg::S1, PhysicalReg::S2, PhysicalReg::S3, PhysicalReg::S4, PhysicalReg::S5,
|
||||
PhysicalReg::S6, PhysicalReg::S7, PhysicalReg::S8, PhysicalReg::S9, PhysicalReg::S10, PhysicalReg::S11
|
||||
};
|
||||
|
||||
// 后端方法
|
||||
std::string module_gen();
|
||||
std::string function_gen(Function* func);
|
||||
std::string basicBlock_gen(BasicBlock* bb, const RegAllocResult& alloc);
|
||||
std::vector<RISCv32Inst> instruction_gen(Instruction* inst);
|
||||
RegAllocResult register_allocation(Function* func);
|
||||
void eliminate_phi(Function* func);
|
||||
std::map<Instruction*, std::set<Value*>> liveness_analysis(Function* func);
|
||||
std::map<Value*, std::set<Value*>> build_interference_graph(
|
||||
const std::map<Instruction*, std::set<Value*>>& live_sets);
|
||||
std::string reg_to_string(PhysicalReg reg);
|
||||
std::string get_preg_str(PhysicalReg preg) const {
|
||||
return preg_to_str.at(preg);
|
||||
}
|
||||
|
||||
PhysicalReg get_preg_or_temp(const std::string& vreg, const RegAllocResult& alloc) const;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
129
src/Reg2Mem.cpp
129
src/Reg2Mem.cpp
@@ -1,129 +0,0 @@
|
||||
#include "Reg2Mem.h"
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/**
|
||||
* 删除phi节点
|
||||
* 删除phi节点后可能会生成冗余存储代码
|
||||
*/
|
||||
void Reg2Mem::DeletePhiInst(){
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (auto &function : functions) {
|
||||
auto basicBlocks = function.second->getBasicBlocks();
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
|
||||
for (auto iter = basicBlock->begin(); iter != basicBlock->end();) {
|
||||
auto &instruction = *iter;
|
||||
if (instruction->isPhi()) {
|
||||
auto predBlocks = basicBlock->getPredecessors();
|
||||
// 寻找源和目的
|
||||
// 目的就是phi指令的第一个操作数
|
||||
// 源就是phi指令的后续操作数
|
||||
auto destination = instruction->getOperand(0);
|
||||
int predBlockindex = 0;
|
||||
for (auto &predBlock : predBlocks) {
|
||||
++predBlockindex;
|
||||
// 判断前驱块儿只有一个后继还是多个后继
|
||||
// 如果有多个
|
||||
auto source = instruction->getOperand(predBlockindex);
|
||||
if (source == destination) {
|
||||
continue;
|
||||
}
|
||||
// std::cout << predBlock->getNumSuccessors() << std::endl;
|
||||
if (predBlock->getNumSuccessors() > 1) {
|
||||
// 创建一个basicblock
|
||||
auto newbasicBlock = function.second->addBasicBlock();
|
||||
std::stringstream ss;
|
||||
ss << " phidel.L" << pBuilder->getLabelIndex();
|
||||
newbasicBlock->setName(ss.str());
|
||||
ss.str("");
|
||||
// // 修改前驱后继关系
|
||||
basicBlock->replacePredecessor(predBlock, newbasicBlock);
|
||||
// predBlock = newbasicBlock;
|
||||
newbasicBlock->addPredecessor(predBlock);
|
||||
newbasicBlock->addSuccessor(basicBlock.get());
|
||||
predBlock->removeSuccessor(basicBlock.get());
|
||||
predBlock->addSuccessor(newbasicBlock);
|
||||
// std::cout << "the block name is " << basicBlock->getName() << std::endl;
|
||||
// for (auto pb : basicBlock->getPredecessors()) {
|
||||
// // newbasicBlock->addPredecessor(pb);
|
||||
// std::cout << pb->getName() << std::endl;
|
||||
// }
|
||||
// sysy::BasicBlock::conectBlocks(newbasicBlock, static_cast<BasicBlock *>(basicBlock.get()));
|
||||
// 若后为跳转指令,应该修改跳转指令所到达的位置
|
||||
auto thelastinst = predBlock->end();
|
||||
(--thelastinst);
|
||||
|
||||
if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) { // 如果是跳转指令
|
||||
auto opnum = thelastinst->get()->getNumOperands();
|
||||
for (size_t i = 0; i < opnum; i++) {
|
||||
if (thelastinst->get()->getOperand(i) == basicBlock.get()) {
|
||||
thelastinst->get()->replaceOperand(i, newbasicBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 在新块中插入store指令
|
||||
pBuilder->setPosition(newbasicBlock, newbasicBlock->end());
|
||||
// pBuilder->createStoreInst(source, destination);
|
||||
if (source->isInt() || source->isFloat()) {
|
||||
pBuilder->createStoreInst(source, destination);
|
||||
} else {
|
||||
auto loadInst = pBuilder->createLoadInst(source);
|
||||
pBuilder->createStoreInst(loadInst, destination);
|
||||
}
|
||||
// pBuilder->createMoveInst(Instruction::kMove, destination->getType(), destination, source,
|
||||
// newbasicBlock);
|
||||
pBuilder->setPosition(newbasicBlock, newbasicBlock->end());
|
||||
pBuilder->createUncondBrInst(basicBlock.get(), {});
|
||||
} else {
|
||||
// 如果前驱块只有一个后继
|
||||
auto thelastinst = predBlock->end();
|
||||
(--thelastinst);
|
||||
// std::cout << predBlock->getName() << std::endl;
|
||||
// std::cout << thelastinst->get() << std::endl;
|
||||
// std::cout << "First point 11 " << std::endl;
|
||||
if (thelastinst->get()->isConditional() || thelastinst->get()->isUnconditional()) {
|
||||
// 在跳转语句前insert st指令
|
||||
pBuilder->setPosition(predBlock, thelastinst);
|
||||
} else {
|
||||
pBuilder->setPosition(predBlock, predBlock->end());
|
||||
}
|
||||
|
||||
if (source->isInt() || source->isFloat()) {
|
||||
pBuilder->createStoreInst(source, destination);
|
||||
} else {
|
||||
auto loadInst = pBuilder->createLoadInst(source);
|
||||
pBuilder->createStoreInst(loadInst, destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除phi指令
|
||||
auto &instructions = basicBlock->getInstructions();
|
||||
usedelete(iter->get());
|
||||
iter = instructions.erase(iter);
|
||||
if (basicBlock->getNumInstructions() == 0) {
|
||||
if (basicBlock->getNumSuccessors() == 1) {
|
||||
pBuilder->setPosition(basicBlock.get(), basicBlock->end());
|
||||
pBuilder->createUncondBrInst(basicBlock->getSuccessors()[0], {});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reg2Mem::usedelete(Instruction *instr) {
|
||||
for (auto &use : instr->getOperands()) {
|
||||
auto val = use->getValue();
|
||||
val->removeUse(use);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@@ -1,532 +0,0 @@
|
||||
#include "SysYIRAnalyser.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace sysy {
|
||||
|
||||
|
||||
void ControlFlowAnalysis::init() {
|
||||
// 初始化分析器
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
blockAnalysisInfo[basicBlock.get()] = new BlockAnalysisInfo();
|
||||
blockAnalysisInfo[basicBlock.get()]->clear();
|
||||
}
|
||||
functionAnalysisInfo[func] = new FunctionAnalysisInfo();
|
||||
functionAnalysisInfo[func]->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::runControlFlowAnalysis() {
|
||||
// 运行控制流分析
|
||||
clear(); // 清空之前的分析结果
|
||||
init(); // 初始化分析器
|
||||
computeDomNode();
|
||||
computeDomTree();
|
||||
computeDomFrontierAllBlk();
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other) {
|
||||
// 计算交集
|
||||
for (auto it = dom.begin(); it != dom.end();) {
|
||||
if (other.find(*it) == other.end()) {
|
||||
// 如果other中没有这个基本块,则从dom中删除
|
||||
it = dom.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto ControlFlowAnalysis::findCommonDominator(BasicBlock *a, BasicBlock *b) -> BasicBlock * {
|
||||
// 查找两个基本块的共同支配结点
|
||||
while (a != b) {
|
||||
BlockAnalysisInfo* infoA = blockAnalysisInfo[a];
|
||||
BlockAnalysisInfo* infoB = blockAnalysisInfo[b];
|
||||
// 如果深度不同,则向上移动到直接支配结点
|
||||
// TODO:空间换时间倍增优化,优先级较低
|
||||
while (infoA->getDomDepth() > infoB->getDomDepth()) {
|
||||
a = const_cast<BasicBlock*>(infoA->getIdom());
|
||||
infoA = blockAnalysisInfo[a];
|
||||
}
|
||||
while (infoB->getDomDepth() > infoA->getDomDepth()) {
|
||||
b = const_cast<BasicBlock*>(infoB->getIdom());
|
||||
infoB = blockAnalysisInfo[b];
|
||||
}
|
||||
if (a == b) break;
|
||||
a = const_cast<BasicBlock*>(infoA->getIdom());
|
||||
b = const_cast<BasicBlock*>(infoB->getIdom());
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void ControlFlowAnalysis::computeDomNode(){
|
||||
auto &functions = pModule->getFunctions();
|
||||
// 分析每个函数内的基本块
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
std::unordered_set<BasicBlock *> domSetTmp;
|
||||
// 一开始把domSetTmp置为所有block
|
||||
auto entry_block = func->getEntryBlock();
|
||||
entry_block->setName("Entry");
|
||||
blockAnalysisInfo[entry_block]->addDominants(entry_block);
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
domSetTmp.emplace(basicBlock.get());
|
||||
}
|
||||
// 初始化
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
if (basicBlock.get() != entry_block) {
|
||||
blockAnalysisInfo[basicBlock.get()]->setDominants(domSetTmp);
|
||||
// 先把所有block的必经结点都设为N
|
||||
}
|
||||
}
|
||||
|
||||
// 支配节点计算公式
|
||||
//DOM[B]={B}∪ {⋂P∈pred(B) DOM[P]}
|
||||
// 其中pred(B)是B的所有前驱结点
|
||||
// 迭代计算支配结点,直到不再变化
|
||||
// 这里使用迭代法,直到支配结点不再变化
|
||||
// TODO:Lengauer-Tarjan 算法可以更高效地计算支配结点
|
||||
// 或者按照CFG拓扑序遍历效率更高
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
// 循环非start结点
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
if (basicBlock.get() != entry_block) {
|
||||
auto olddom =
|
||||
blockAnalysisInfo[basicBlock.get()]->getDominants();
|
||||
|
||||
std::unordered_set<BasicBlock *> dom =
|
||||
blockAnalysisInfo[basicBlock->getPredecessors().front()]->getDominants();
|
||||
|
||||
// 对于每个基本块,计算其支配结点
|
||||
// 取其前驱结点的支配结点的交集和自己
|
||||
for (auto pred : basicBlock->getPredecessors()) {
|
||||
intersectOP4Dom(dom, blockAnalysisInfo[pred]->getDominants());
|
||||
}
|
||||
dom.emplace(basicBlock.get());
|
||||
blockAnalysisInfo[basicBlock.get()]->setDominants(dom);
|
||||
|
||||
if (dom != olddom) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: SEMI-NCA算法改进
|
||||
void ControlFlowAnalysis::computeDomTree() {
|
||||
// 构造支配树
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
auto entry_block = func->getEntryBlock();
|
||||
|
||||
blockAnalysisInfo[entry_block]->setIdom(entry_block);
|
||||
blockAnalysisInfo[entry_block]->setDomDepth(0); // 入口块深度为0
|
||||
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
if (basicBlock.get() == entry_block) continue;
|
||||
|
||||
BasicBlock *new_idom = nullptr;
|
||||
for (auto pred : basicBlock->getPredecessors()) {
|
||||
// 跳过未处理的前驱
|
||||
if (blockAnalysisInfo[pred]->getIdom() == nullptr) continue;
|
||||
// new_idom = (new_idom == nullptr) ? pred : findCommonDominator(new_idom, pred);
|
||||
if (new_idom == nullptr)
|
||||
new_idom = pred;
|
||||
else
|
||||
new_idom = findCommonDominator(new_idom, pred);
|
||||
}
|
||||
// 更新直接支配节点
|
||||
if (new_idom && new_idom != blockAnalysisInfo[basicBlock.get()]->getIdom()) {
|
||||
// 移除旧的支配关系
|
||||
if (blockAnalysisInfo[basicBlock.get()]->getIdom()) {
|
||||
blockAnalysisInfo[const_cast<BasicBlock*>(blockAnalysisInfo[basicBlock.get()]->getIdom())]->removeSdoms(basicBlock.get());
|
||||
}
|
||||
// 设置新的支配关系
|
||||
|
||||
// std::cout << "Block: " << basicBlock->getName()
|
||||
// << " New Idom: " << new_idom->getName() << std::endl;
|
||||
|
||||
blockAnalysisInfo[basicBlock.get()]->setIdom(new_idom);
|
||||
blockAnalysisInfo[new_idom]->addSdoms(basicBlock.get());
|
||||
// 更新深度 = 直接支配节点深度 + 1
|
||||
blockAnalysisInfo[basicBlock.get()]->setDomDepth(
|
||||
blockAnalysisInfo[new_idom]->getDomDepth() + 1);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (auto &basicBlock : basicBlocks) {
|
||||
// if (basicBlock.get() != func->getEntryBlock()) {
|
||||
// auto dominats =
|
||||
// blockAnalysisInfo[basicBlock.get()]->getDominants();
|
||||
// bool found = false;
|
||||
// // 从前驱结点开始寻找直接支配结点
|
||||
// std::queue<BasicBlock *> q;
|
||||
// for (auto pred : basicBlock->getPredecessors()) {
|
||||
// q.push(pred);
|
||||
// }
|
||||
// // BFS遍历前驱结点,直到找到直接支配结点
|
||||
// while (!found && !q.empty()) {
|
||||
// auto curr = q.front();
|
||||
// q.pop();
|
||||
// if (curr == basicBlock.get())
|
||||
// continue;
|
||||
// if (dominats.count(curr) != 0U) {
|
||||
// blockAnalysisInfo[basicBlock.get()]->setIdom(curr);
|
||||
// blockAnalysisInfo[curr]->addSdoms(basicBlock.get());
|
||||
// found = true;
|
||||
// } else {
|
||||
// for (auto pred : curr->getPredecessors()) {
|
||||
// q.push(pred);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// std::unordered_set<BasicBlock *> ControlFlowAnalysis::computeDomFrontier(BasicBlock *block) {
|
||||
// std::unordered_set<BasicBlock *> ret_list;
|
||||
// // 计算 localDF
|
||||
// for (auto local_successor : block->getSuccessors()) {
|
||||
// if (local_successor->getIdom() != block) {
|
||||
// ret_list.emplace(local_successor);
|
||||
// }
|
||||
// }
|
||||
// // 计算 upDF
|
||||
// for (auto up_successor : block->getSdoms()) {
|
||||
// auto childrenDF = computeDF(up_successor);
|
||||
// for (auto w : childrenDF) {
|
||||
// if (block != w->getIdom() || block == w) {
|
||||
// ret_list.emplace(w);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return ret_list;
|
||||
// }
|
||||
|
||||
void ControlFlowAnalysis::computeDomFrontierAllBlk() {
|
||||
auto &functions = pModule->getFunctions();
|
||||
for (const auto &function : functions) {
|
||||
auto func = function.second.get();
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
|
||||
// 按支配树深度排序(从深到浅)
|
||||
std::vector<BasicBlock *> orderedBlocks;
|
||||
for (auto &bb : basicBlocks) {
|
||||
orderedBlocks.push_back(bb.get());
|
||||
}
|
||||
std::sort(orderedBlocks.begin(), orderedBlocks.end(),
|
||||
[this](BasicBlock *a, BasicBlock *b) {
|
||||
return blockAnalysisInfo[a]->getDomDepth() > blockAnalysisInfo[b]->getDomDepth();
|
||||
});
|
||||
|
||||
// 计算支配边界
|
||||
for (auto block : orderedBlocks) {
|
||||
std::unordered_set<BasicBlock *> df;
|
||||
|
||||
// Local DF: 直接后继中不被当前块支配的
|
||||
for (auto succ : block->getSuccessors()) {
|
||||
// 当前块不支配该后继(即不是其直接支配节点)
|
||||
if (blockAnalysisInfo[succ]->getIdom() != block) {
|
||||
df.insert(succ);
|
||||
}
|
||||
}
|
||||
|
||||
// Up DF: 从支配子树中继承
|
||||
for (auto child : blockAnalysisInfo[block]->getSdoms()) {
|
||||
for (auto w : blockAnalysisInfo[child]->getDomFrontiers()) {
|
||||
// 如果w不被当前块支配
|
||||
if (block != blockAnalysisInfo[w]->getIdom()) {
|
||||
df.insert(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockAnalysisInfo[block]->setDomFrontiers(df);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// dataflow analysis utils
|
||||
// ==========================
|
||||
|
||||
// 先引用学长的代码
|
||||
// TODO: Worklist 增加逆后序遍历机制
|
||||
void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){
|
||||
std::map<DataFlowAnalysis *, bool> workAnalysis;
|
||||
for (auto &dataflow : forwardAnalysisList) {
|
||||
dataflow->init(pModule);
|
||||
}
|
||||
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (auto &dataflow : forwardAnalysisList) {
|
||||
workAnalysis.emplace(dataflow, false);
|
||||
}
|
||||
while (!workAnalysis.empty()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
for (auto &elem : workAnalysis) {
|
||||
if (elem.first->analyze(pModule, block.get())) {
|
||||
elem.second = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<DataFlowAnalysis *, bool> tmp;
|
||||
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
|
||||
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
|
||||
workAnalysis.swap(tmp);
|
||||
|
||||
for (auto &elem : workAnalysis) {
|
||||
elem.second = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) {
|
||||
std::map<DataFlowAnalysis *, bool> workAnalysis;
|
||||
for (auto &dataflow : backwardAnalysisList) {
|
||||
dataflow->init(pModule);
|
||||
}
|
||||
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (auto &dataflow : backwardAnalysisList) {
|
||||
workAnalysis.emplace(dataflow, false);
|
||||
}
|
||||
while (!workAnalysis.empty()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
for (auto &elem : workAnalysis) {
|
||||
if (elem.first->analyze(pModule, block.get())) {
|
||||
elem.second = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<DataFlowAnalysis *, bool> tmp;
|
||||
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
|
||||
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
|
||||
workAnalysis.swap(tmp);
|
||||
|
||||
for (auto &elem : workAnalysis) {
|
||||
elem.second = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::set<User *> ActiveVarAnalysis::getUsedSet(Instruction *inst) {
|
||||
using Kind = Instruction::Kind;
|
||||
std::vector<User *> operands;
|
||||
for (const auto &operand : inst->getOperands()) {
|
||||
operands.emplace_back(dynamic_cast<User *>(operand->getValue()));
|
||||
}
|
||||
std::set<User *> result;
|
||||
switch (inst->getKind()) {
|
||||
// phi op
|
||||
case Kind::kPhi:
|
||||
case Kind::kCall:
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
case Kind::kCondBr:
|
||||
result.insert(operands[0]);
|
||||
break;
|
||||
case Kind::kBr:
|
||||
case Kind::kAlloca:
|
||||
break;
|
||||
// mem op
|
||||
case Kind::kStore:
|
||||
// StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量
|
||||
// 后续的是可能的数组维度
|
||||
result.insert(operands[0]);
|
||||
result.insert(operands.begin() + 2, operands.end());
|
||||
break;
|
||||
case Kind::kLoad:
|
||||
case Kind::kLa: {
|
||||
auto variable = dynamic_cast<AllocaInst *>(operands[0]);
|
||||
auto global = dynamic_cast<GlobalValue *>(operands[0]);
|
||||
auto constArray = dynamic_cast<ConstantVariable *>(operands[0]);
|
||||
if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) ||
|
||||
(constArray != nullptr && constArray->getNumDims() == 0)) {
|
||||
result.insert(operands[0]);
|
||||
}
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
}
|
||||
case Kind::kGetSubArray: {
|
||||
for (unsigned i = 2; i < operands.size(); i++) {
|
||||
// 数组的维度信息
|
||||
result.insert(operands[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Kind::kMemset: {
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
}
|
||||
case Kind::kInvalid:
|
||||
// Binary
|
||||
case Kind::kAdd:
|
||||
case Kind::kSub:
|
||||
case Kind::kMul:
|
||||
case Kind::kDiv:
|
||||
case Kind::kRem:
|
||||
case Kind::kICmpEQ:
|
||||
case Kind::kICmpNE:
|
||||
case Kind::kICmpLT:
|
||||
case Kind::kICmpLE:
|
||||
case Kind::kICmpGT:
|
||||
case Kind::kICmpGE:
|
||||
case Kind::kFAdd:
|
||||
case Kind::kFSub:
|
||||
case Kind::kFMul:
|
||||
case Kind::kFDiv:
|
||||
case Kind::kFCmpEQ:
|
||||
case Kind::kFCmpNE:
|
||||
case Kind::kFCmpLT:
|
||||
case Kind::kFCmpLE:
|
||||
case Kind::kFCmpGT:
|
||||
case Kind::kFCmpGE:
|
||||
case Kind::kAnd:
|
||||
case Kind::kOr:
|
||||
// Unary
|
||||
case Kind::kNeg:
|
||||
case Kind::kNot:
|
||||
case Kind::kFNot:
|
||||
case Kind::kFNeg:
|
||||
case Kind::kFtoI:
|
||||
case Kind::kItoF:
|
||||
// terminator
|
||||
case Kind::kReturn:
|
||||
result.insert(operands.begin(), operands.end());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
result.erase(nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
User * ActiveVarAnalysis::getDefine(Instruction *inst) {
|
||||
User *result = nullptr;
|
||||
if (inst->isStore()) {
|
||||
StoreInst* store = dynamic_cast<StoreInst *>(inst);
|
||||
auto operand = store->getPointer();
|
||||
AllocaInst* variable = dynamic_cast<AllocaInst *>(operand);
|
||||
GlobalValue* global = dynamic_cast<GlobalValue *>(operand);
|
||||
if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) {
|
||||
// 如果是数组变量或者全局变量,则不返回定义
|
||||
// TODO:兼容数组变量
|
||||
result = nullptr;
|
||||
} else {
|
||||
result = dynamic_cast<User *>(operand);
|
||||
}
|
||||
} else if (inst->isPhi()) {
|
||||
result = dynamic_cast<User *>(inst->getOperand(0));
|
||||
} else if (inst->isBinary() || inst->isUnary() || inst->isCall() ||
|
||||
inst->isLoad() || inst->isLa()) {
|
||||
result = dynamic_cast<User *>(inst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActiveVarAnalysis::init(Module *pModule) {
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
activeTable.emplace(block.get(), std::vector<std::set<User *>>{});
|
||||
for (unsigned i = 0; i < block->getNumInstructions() + 1; i++)
|
||||
activeTable.at(block.get()).emplace_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 活跃变量分析公式 每个块内的分析动作供分析器调用
|
||||
bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) {
|
||||
bool changed = false; // 标记数据流结果是否有变化
|
||||
std::set<User *> activeSet{}; // 当前计算的活跃变量集合
|
||||
|
||||
// 步骤1: 计算基本块出口的活跃变量集 (OUT[B])
|
||||
// 公式: OUT[B] = ∪_{S ∈ succ(B)} IN[S]
|
||||
for (const auto &succ : block->getSuccessors()) {
|
||||
// 获取后继块入口的活跃变量集 (IN[S])
|
||||
auto succActiveSet = activeTable.at(succ).front();
|
||||
// 合并所有后继块的入口活跃变量
|
||||
activeSet.insert(succActiveSet.begin(), succActiveSet.end());
|
||||
}
|
||||
|
||||
// 步骤2: 处理基本块出口处的活跃变量集
|
||||
const auto &instructions = block->getInstructions();
|
||||
const auto numInstructions = instructions.size();
|
||||
|
||||
// 获取旧的出口活跃变量集 (block出口对应索引numInstructions)
|
||||
const auto &oldEndActiveSet = activeTable.at(block)[numInstructions];
|
||||
|
||||
// 检查出口活跃变量集是否有变化
|
||||
if (!std::equal(activeSet.begin(), activeSet.end(),
|
||||
oldEndActiveSet.begin(), oldEndActiveSet.end()))
|
||||
{
|
||||
changed = true; // 标记变化
|
||||
activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集
|
||||
}
|
||||
|
||||
// 步骤3: 逆序遍历基本块中的指令
|
||||
// 从最后一条指令开始向前计算每个程序点的活跃变量
|
||||
auto instructionIter = instructions.end();
|
||||
instructionIter--; // 指向最后一条指令
|
||||
|
||||
// 从出口向入口遍历 (索引从numInstructions递减到1)
|
||||
for (unsigned i = numInstructions; i > 0; i--) {
|
||||
auto inst = instructionIter->get(); // 当前指令
|
||||
|
||||
auto used = getUsedSet(inst);
|
||||
User *defined = getDefine(inst);
|
||||
|
||||
// 步骤3.3: 计算指令入口的活跃变量 (IN[i])
|
||||
// 公式: IN[i] = use_i ∪ (OUT[i] - def_i)
|
||||
activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i)
|
||||
activeSet.insert(used.begin(), used.end()); // 添加使用的变量
|
||||
|
||||
// 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口)
|
||||
const auto &oldActiveSet = activeTable.at(block)[i - 1];
|
||||
|
||||
// 检查活跃变量集是否有变化
|
||||
if (!std::equal(activeSet.begin(), activeSet.end(),
|
||||
oldActiveSet.begin(), oldActiveSet.end()))
|
||||
{
|
||||
changed = true; // 标记变化
|
||||
activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集
|
||||
}
|
||||
|
||||
instructionIter--; // 移动到前一条指令
|
||||
}
|
||||
|
||||
return changed; // 返回数据流结果是否变化
|
||||
}
|
||||
|
||||
|
||||
auto ActiveVarAnalysis::getActiveTable() const -> const std::map<BasicBlock *, std::vector<std::set<User *>>> & {
|
||||
return activeTable;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext *ctx) {
|
||||
dims.push_back(std::any_cast<Value *>(visitExp(exp)));
|
||||
}
|
||||
|
||||
auto variable = module->getVariable(name);
|
||||
User* variable = module->getVariable(name);
|
||||
Value* value = std::any_cast<Value *>(visitExp(ctx->exp()));
|
||||
Type* variableType = dynamic_cast<PointerType *>(variable->getType())->getBaseType();
|
||||
|
||||
|
||||
@@ -128,15 +128,12 @@ void SysYPrinter::printFunction(Function *function) {
|
||||
std::cout << " @" << function->getName() << "(";
|
||||
|
||||
auto entryBlock = function->getEntryBlock();
|
||||
const auto &args_types = function->getParamTypes();
|
||||
auto &args = entryBlock->getArguments();
|
||||
|
||||
int i = 0;
|
||||
for (const auto &args_type : args_types) {
|
||||
for (size_t i = 0; i < args.size(); i++) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
printType(args_type);
|
||||
printType(args[i]->getType());
|
||||
std::cout << " %" << args[i]->getName();
|
||||
i++;
|
||||
}
|
||||
|
||||
std::cout << ") {" << std::endl;
|
||||
@@ -438,15 +435,14 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
|
||||
case Kind::kPhi: {
|
||||
auto phiInst = dynamic_cast<PhiInst *>(pInst);
|
||||
printValue(phiInst->getOperand(0));
|
||||
std::cout << " = phi ";
|
||||
std::cout << "%" << phiInst->getName() << " = phi ";
|
||||
printType(phiInst->getType());
|
||||
|
||||
for (unsigned i = 1; i < phiInst->getNumOperands(); i++) {
|
||||
for (unsigned i = 0; i < phiInst->getNumOperands(); i += 2) {
|
||||
if (i > 0) std::cout << ", ";
|
||||
std::cout << "[ ";
|
||||
printValue(phiInst->getOperand(i));
|
||||
std::cout << " ]";
|
||||
std::cout << ", %" << dynamic_cast<BasicBlock*>(phiInst->getOperand(i+1))->getName() << " ]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} break;
|
||||
|
||||
372
src/include/IR.h
372
src/include/IR.h
@@ -317,6 +317,7 @@ class ConstantValue : public Value {
|
||||
|
||||
class Instruction;
|
||||
class Function;
|
||||
class Loop;
|
||||
class BasicBlock;
|
||||
|
||||
/*!
|
||||
@@ -326,73 +327,104 @@ class BasicBlock;
|
||||
* a terminator (branch or return). Besides, `BasicBlock` stores its arguments
|
||||
* and records its predecessor and successor `BasicBlock`s.
|
||||
*/
|
||||
class BasicBlock : public Value {
|
||||
|
||||
class BasicBlock : public Value {
|
||||
friend class Function;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
using inst_list = std::list<std::unique_ptr<Instruction>>;
|
||||
using iterator = inst_list::iterator;
|
||||
using arg_list = std::vector<AllocaInst *>;
|
||||
using block_list = std::vector<BasicBlock *>;
|
||||
using block_set = std::unordered_set<BasicBlock *>;
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
Function *parent; ///< 从属的函数
|
||||
inst_list instructions; ///< 拥有的指令序列
|
||||
arg_list arguments; ///< 分配空间后的形式参数列表
|
||||
block_list successors; ///< 前驱列表
|
||||
block_list predecessors; ///< 后继列表
|
||||
bool reachable = false;
|
||||
BasicBlock *idom = nullptr; ///< 直接支配结点,即支配树前驱,唯一,默认nullptr
|
||||
block_list sdoms; ///< 支配树后继,可以有多个
|
||||
block_set dominants; ///< 必经结点集合
|
||||
block_set dominant_frontiers; ///< 支配边界
|
||||
bool reachable = false; ///< 用于表示该节点是否可达,默认不可达
|
||||
Loop *loopbelong = nullptr; ///< 用来表示该块属于哪个循环,唯一,默认nullptr
|
||||
int loopdepth = 0; /// < 用来表示其归属循环的深度,默认0
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit BasicBlock(Function *parent, const std::string &name = "")
|
||||
: Value(Type::getLabelType(), name), parent(parent) {}
|
||||
|
||||
~BasicBlock() override {
|
||||
for (auto pre : predecessors) {
|
||||
pre->removeSuccessor(this);
|
||||
}
|
||||
|
||||
for (auto suc : successors) {
|
||||
suc->removePredecessor(this);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
} ///< 基本块的析构函数,同时删除其前驱后继关系
|
||||
|
||||
unsigned getNumInstructions() const { return instructions.size(); }
|
||||
unsigned getNumArguments() const { return arguments.size(); }
|
||||
unsigned getNumPredecessors() const { return predecessors.size(); }
|
||||
unsigned getNumSuccessors() const { return successors.size(); }
|
||||
Function* getParent() const { return parent; }
|
||||
void setParent(Function *func) { parent = func; }
|
||||
inst_list& getInstructions() { return instructions; }
|
||||
arg_list& getArguments() { return arguments; }
|
||||
const block_list& getPredecessors() const { return predecessors; }
|
||||
block_list& getSuccessors() { return successors; }
|
||||
iterator begin() { return instructions.begin(); }
|
||||
iterator end() { return instructions.end(); }
|
||||
iterator terminator() { return std::prev(end()); }
|
||||
void insertArgument(AllocaInst *inst) { arguments.push_back(inst); }
|
||||
public:
|
||||
unsigned getNumInstructions() const { return instructions.size(); } ///< 获取指令数量
|
||||
unsigned getNumArguments() const { return arguments.size(); } ///< 获取形式参数数量
|
||||
unsigned getNumPredecessors() const { return predecessors.size(); } ///< 获取前驱数量
|
||||
unsigned getNumSuccessors() const { return successors.size(); } ///< 获取后继数量
|
||||
Function* getParent() const { return parent; } ///< 获取父函数
|
||||
void setParent(Function *func) { parent = func; } ///< 设置父函数
|
||||
inst_list& getInstructions() { return instructions; } ///< 获取指令列表
|
||||
arg_list& getArguments() { return arguments; } ///< 获取分配空间后的形式参数列表
|
||||
const block_list& getPredecessors() const { return predecessors; } ///< 获取前驱列表
|
||||
block_list& getSuccessors() { return successors; } ///< 获取后继列表
|
||||
block_set& getDominants() { return dominants; }
|
||||
BasicBlock* getIdom() { return idom; }
|
||||
block_list& getSdoms() { return sdoms; }
|
||||
block_set& getDFs() { return dominant_frontiers; }
|
||||
iterator begin() { return instructions.begin(); } ///< 返回指向指令列表开头的迭代器
|
||||
iterator end() { return instructions.end(); } ///< 返回指向指令列表末尾的迭代器
|
||||
iterator terminator() { return std::prev(end()); } ///< 基本块最后的IR
|
||||
void insertArgument(AllocaInst *inst) { arguments.push_back(inst); } ///< 插入分配空间后的形式参数
|
||||
void addPredecessor(BasicBlock *block) {
|
||||
if (std::find(predecessors.begin(), predecessors.end(), block) == predecessors.end()) {
|
||||
predecessors.push_back(block);
|
||||
}
|
||||
}
|
||||
} ///< 添加前驱
|
||||
void addSuccessor(BasicBlock *block) {
|
||||
if (std::find(successors.begin(), successors.end(), block) == successors.end()) {
|
||||
successors.push_back(block);
|
||||
}
|
||||
}
|
||||
} ///< 添加后继
|
||||
void addPredecessor(const block_list &blocks) {
|
||||
for (auto block : blocks) {
|
||||
addPredecessor(block);
|
||||
}
|
||||
}
|
||||
} ///< 添加多个前驱
|
||||
void addSuccessor(const block_list &blocks) {
|
||||
for (auto block : blocks) {
|
||||
addSuccessor(block);
|
||||
}
|
||||
} ///< 添加多个后继
|
||||
void setIdom(BasicBlock *block) { idom = block; }
|
||||
void addSdoms(BasicBlock *block) { sdoms.push_back(block); }
|
||||
void clearSdoms() { sdoms.clear(); }
|
||||
// 重载1,参数为 BasicBlock*
|
||||
void addDominants(BasicBlock *block) { dominants.emplace(block); }
|
||||
// 重载2,参数为 block_set
|
||||
void addDominants(const block_set &blocks) { dominants.insert(blocks.begin(), blocks.end()); }
|
||||
void setDominants(BasicBlock *block) {
|
||||
dominants.clear();
|
||||
addDominants(block);
|
||||
}
|
||||
void setDominants(const block_set &doms) {
|
||||
dominants.clear();
|
||||
addDominants(doms);
|
||||
}
|
||||
void setDFs(const block_set &df) {
|
||||
dominant_frontiers.clear();
|
||||
for (auto elem : df) {
|
||||
dominant_frontiers.emplace(elem);
|
||||
}
|
||||
}
|
||||
void removePredecessor(BasicBlock *block) {
|
||||
auto iter = std::find(predecessors.begin(), predecessors.end(), block);
|
||||
@@ -401,7 +433,7 @@ public:
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
} ///< 删除前驱
|
||||
void removeSuccessor(BasicBlock *block) {
|
||||
auto iter = std::find(successors.begin(), successors.end(), block);
|
||||
if (iter != successors.end()) {
|
||||
@@ -409,7 +441,7 @@ public:
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
} ///< 删除后继
|
||||
void replacePredecessor(BasicBlock *oldBlock, BasicBlock *newBlock) {
|
||||
for (auto &predecessor : predecessors) {
|
||||
if (predecessor == oldBlock) {
|
||||
@@ -417,16 +449,41 @@ public:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} ///< 替换前驱
|
||||
// 获取支配树中该块的所有子节点,包括子节点的子节点等,迭代实现
|
||||
block_list getChildren() {
|
||||
std::queue<BasicBlock *> q;
|
||||
block_list children;
|
||||
for (auto sdom : sdoms) {
|
||||
q.push(sdom);
|
||||
children.push_back(sdom);
|
||||
}
|
||||
while (!q.empty()) {
|
||||
auto block = q.front();
|
||||
q.pop();
|
||||
for (auto sdom : block->sdoms) {
|
||||
q.push(sdom);
|
||||
children.push_back(sdom);
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
void setreachableTrue() { reachable = true; } ///< 设置可达
|
||||
void setreachableFalse() { reachable = false; } ///< 设置不可达
|
||||
bool getreachable() { return reachable; } ///< 返回可达状态
|
||||
|
||||
static void conectBlocks(BasicBlock *prev, BasicBlock *next) {
|
||||
prev->addSuccessor(next);
|
||||
next->addPredecessor(prev);
|
||||
}
|
||||
void removeInst(iterator pos) { instructions.erase(pos); }
|
||||
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block);
|
||||
} ///< 连接两个块,即设置两个基本块的前驱后继关系
|
||||
void setLoop(Loop *loop2set) { loopbelong = loop2set; } ///< 设置所属循环
|
||||
Loop* getLoop() { return loopbelong; } ///< 获得所属循环
|
||||
void setLoopDepth(int loopdepth2set) { loopdepth = loopdepth2set; } ///< 设置循环深度
|
||||
int getLoopDepth() { return loopdepth; } ///< 获得其在循环的深度
|
||||
void removeInst(iterator pos) { instructions.erase(pos); } ///< 删除指令
|
||||
iterator moveInst(iterator sourcePos, iterator targetPos, BasicBlock *block); ///< 移动指令
|
||||
};
|
||||
|
||||
//! User is the abstract base type of `Value` types which use other `Value` as
|
||||
@@ -1141,11 +1198,109 @@ public:
|
||||
|
||||
class GlobalValue;
|
||||
|
||||
// 循环类
|
||||
class Loop {
|
||||
public:
|
||||
using block_list = std::vector<BasicBlock *>;
|
||||
using block_set = std::unordered_set<BasicBlock *>;
|
||||
using Loop_list = std::vector<Loop *>;
|
||||
|
||||
protected:
|
||||
Function *parent; // 所属函数
|
||||
block_list blocksInLoop; // 循环内的基本块
|
||||
BasicBlock *preheaderBlock = nullptr; // 前驱块
|
||||
BasicBlock *headerBlock = nullptr; // 循环头
|
||||
block_list latchBlock; // 回边块
|
||||
block_set exitingBlocks; // 退出块
|
||||
block_set exitBlocks; // 退出目标块
|
||||
Loop *parentloop = nullptr; // 父循环
|
||||
Loop_list subLoops; // 子循环
|
||||
size_t loopID; // 循环ID
|
||||
unsigned loopDepth; // 循环深度
|
||||
|
||||
Instruction *indCondVar = nullptr; // 循环条件变量
|
||||
Instruction::Kind IcmpKind; // 比较类型
|
||||
Value *indEnd = nullptr; // 循环结束值
|
||||
AllocaInst *IndPhi = nullptr; // 循环变量
|
||||
|
||||
ConstantValue *indBegin = nullptr; // 循环起始值
|
||||
ConstantValue *indStep = nullptr; // 循环步长
|
||||
|
||||
std::set<GlobalValue *> GlobalValuechange; // 循环内改变的全局变量
|
||||
|
||||
int StepType = 0; // 循环步长类型
|
||||
bool parallelable = false; // 是否可并行
|
||||
|
||||
public:
|
||||
explicit Loop(BasicBlock *header, const std::string &name = "")
|
||||
: headerBlock(header) {
|
||||
blocksInLoop.push_back(header);
|
||||
}
|
||||
|
||||
void setloopID() {
|
||||
static unsigned loopCount = 0;
|
||||
loopCount = loopCount + 1;
|
||||
loopID = loopCount;
|
||||
}
|
||||
ConstantValue* getindBegin() { return indBegin; } ///< 获得循环开始值
|
||||
ConstantValue* getindStep() { return indStep; } ///< 获得循环步长
|
||||
void setindBegin(ConstantValue *indBegin2set) { indBegin = indBegin2set; } ///< 设置循环开始值
|
||||
void setindStep(ConstantValue *indStep2set) { indStep = indStep2set; } ///< 设置循环步长
|
||||
void setStepType(int StepType2Set) { StepType = StepType2Set; } ///< 设置循环变量规则
|
||||
int getStepType() { return StepType; } ///< 获得循环变量规则
|
||||
size_t getLoopID() { return loopID; }
|
||||
|
||||
BasicBlock* getHeader() const { return headerBlock; }
|
||||
BasicBlock* getPreheaderBlock() const { return preheaderBlock; }
|
||||
block_list& getLatchBlocks() { return latchBlock; }
|
||||
block_set& getExitingBlocks() { return exitingBlocks; }
|
||||
block_set& getExitBlocks() { return exitBlocks; }
|
||||
Loop* getParentLoop() const { return parentloop; }
|
||||
void setParentLoop(Loop *parent) { parentloop = parent; }
|
||||
void addBasicBlock(BasicBlock *bb) { blocksInLoop.push_back(bb); }
|
||||
void addSubLoop(Loop *loop) { subLoops.push_back(loop); }
|
||||
void setLoopDepth(unsigned depth) { loopDepth = depth; }
|
||||
block_list& getBasicBlocks() { return blocksInLoop; }
|
||||
Loop_list& getSubLoops() { return subLoops; }
|
||||
unsigned getLoopDepth() const { return loopDepth; }
|
||||
|
||||
bool isLoopContainsBasicBlock(BasicBlock *bb) const {
|
||||
return std::find(blocksInLoop.begin(), blocksInLoop.end(), bb) != blocksInLoop.end();
|
||||
} ///< 判断输入块是否在该循环内
|
||||
|
||||
void addExitingBlock(BasicBlock *bb) { exitingBlocks.insert(bb); }
|
||||
void addExitBlock(BasicBlock *bb) { exitBlocks.insert(bb); }
|
||||
void addLatchBlock(BasicBlock *bb) { latchBlock.push_back(bb); }
|
||||
void setPreheaderBlock(BasicBlock *bb) { preheaderBlock = bb; }
|
||||
|
||||
void setIndexCondInstr(Instruction *instr) { indCondVar = instr; }
|
||||
void setIcmpKind(Instruction::Kind kind) { IcmpKind = kind; }
|
||||
Instruction::Kind getIcmpKind() const { return IcmpKind; }
|
||||
|
||||
bool isSimpleLoopInvariant(Value *value) ; ///< 判断是否为简单循环不变量,若其在loop中,则不是。
|
||||
|
||||
void setIndEnd(Value *value) { indEnd = value; }
|
||||
void setIndPhi(AllocaInst *phi) { IndPhi = phi; }
|
||||
Value* getIndEnd() const { return indEnd; }
|
||||
AllocaInst* getIndPhi() const { return IndPhi; }
|
||||
Instruction* getIndCondVar() const { return indCondVar; }
|
||||
|
||||
void addGlobalValuechange(GlobalValue *globalvaluechange2add) {
|
||||
GlobalValuechange.insert(globalvaluechange2add);
|
||||
} ///<添加在循环中改变的全局变量
|
||||
std::set<GlobalValue *>& getGlobalValuechange() {
|
||||
return GlobalValuechange;
|
||||
} ///<获得在循环中改变的所有全局变量
|
||||
|
||||
void setParallelable(bool flag) { parallelable = flag; }
|
||||
bool isParallelable() const { return parallelable; }
|
||||
};
|
||||
|
||||
class Module;
|
||||
//! Function definitionclass
|
||||
//! Function definition
|
||||
class Function : public Value {
|
||||
friend class Module;
|
||||
|
||||
protected:
|
||||
Function(Module *parent, Type *type, const std::string &name) : Value(type, name), parent(parent) {
|
||||
blocks.emplace_back(new BasicBlock(this));
|
||||
@@ -1153,6 +1308,9 @@ protected:
|
||||
|
||||
public:
|
||||
using block_list = std::list<std::unique_ptr<BasicBlock>>;
|
||||
using Loop_list = std::list<std::unique_ptr<Loop>>;
|
||||
|
||||
// 函数优化属性标识符
|
||||
enum FunctionAttribute : uint64_t {
|
||||
PlaceHolder = 0x0UL,
|
||||
Pure = 0x1UL << 0,
|
||||
@@ -1164,47 +1322,167 @@ public:
|
||||
protected:
|
||||
Module *parent; ///< 函数的父模块
|
||||
block_list blocks; ///< 函数包含的基本块列表
|
||||
Loop_list loops; ///< 函数包含的循环列表
|
||||
Loop_list topLoops; ///< 函数所包含的顶层循环;
|
||||
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 函数中mem2reg引入的间接分配的内存
|
||||
|
||||
FunctionAttribute attribute = PlaceHolder; ///< 函数属性
|
||||
std::set<Function *> callees; ///< 函数调用的函数集合
|
||||
public:
|
||||
|
||||
std::unordered_map<BasicBlock *, Loop *> basicblock2Loop;
|
||||
std::unordered_map<Value *, BasicBlock *> value2AllocBlocks; ///< value -- alloc block mapping
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>
|
||||
value2DefBlocks; //< value -- define blocks mapping
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>> value2UseBlocks; //< value -- use blocks mapping
|
||||
|
||||
public:
|
||||
static unsigned getcloneIndex() {
|
||||
static unsigned cloneIndex = 0;
|
||||
cloneIndex += 1;
|
||||
return cloneIndex - 1;
|
||||
}
|
||||
Function* clone(const std::string &suffix = "_" + std::to_string(getcloneIndex()) + "@") const;
|
||||
Function* clone(const std::string &suffix = "_" + std::to_string(getcloneIndex()) + "@") const; ///< 复制函数
|
||||
const std::set<Function *>& getCallees() { return callees; }
|
||||
void addCallee(Function *callee) { callees.insert(callee); }
|
||||
void removeCallee(Function *callee) { callees.erase(callee); }
|
||||
void clearCallees() { callees.clear(); }
|
||||
std::set<Function *> getCalleesWithNoExternalAndSelf();
|
||||
FunctionAttribute getAttribute() const { return attribute; }
|
||||
FunctionAttribute getAttribute() const { return attribute; } ///< 获取函数属性
|
||||
void setAttribute(FunctionAttribute attr) {
|
||||
attribute = static_cast<FunctionAttribute>(attribute | attr);
|
||||
}
|
||||
void clearAttribute() { attribute = PlaceHolder; }
|
||||
Type* getReturnType() const { return getType()->as<FunctionType>()->getReturnType(); }
|
||||
auto getParamTypes() const { return getType()->as<FunctionType>()->getParamTypes(); }
|
||||
auto getBasicBlocks() { return make_range(blocks); }
|
||||
} ///< 设置函数属性
|
||||
void clearAttribute() { attribute = PlaceHolder; } ///< 清楚所有函数属性,只保留PlaceHolder
|
||||
Loop* getLoopOfBasicBlock(BasicBlock *bb) {
|
||||
return basicblock2Loop.count(bb) != 0 ? basicblock2Loop[bb] : nullptr;
|
||||
} ///< 获得块所在循环
|
||||
unsigned getLoopDepthByBlock(BasicBlock *basicblock2Check) {
|
||||
if (getLoopOfBasicBlock(basicblock2Check) != nullptr) {
|
||||
auto loop = getLoopOfBasicBlock(basicblock2Check);
|
||||
return loop->getLoopDepth();
|
||||
}
|
||||
return static_cast<unsigned>(0);
|
||||
} ///< 通过块,获得其所在循环深度
|
||||
void addBBToLoop(BasicBlock *bb, Loop *LoopToadd) { basicblock2Loop[bb] = LoopToadd; } ///< 添加块与循环的映射
|
||||
std::unordered_map<BasicBlock *, Loop *>& getBBToLoopRef() {
|
||||
return basicblock2Loop;
|
||||
} ///< 获得块-循环映射表
|
||||
// auto getNewLoopPtr(BasicBlock *header) -> Loop * { return new Loop(header); }
|
||||
Type* getReturnType() const { return getType()->as<FunctionType>()->getReturnType(); } ///< 获取返回值类型
|
||||
auto getParamTypes() const { return getType()->as<FunctionType>()->getParamTypes(); } ///< 获取形式参数类型列表
|
||||
auto getBasicBlocks() { return make_range(blocks); } ///< 获取基本块列表
|
||||
block_list& getBasicBlocks_NoRange() { return blocks; }
|
||||
BasicBlock* getEntryBlock() { return blocks.front().get(); }
|
||||
BasicBlock* getEntryBlock() { return blocks.front().get(); } ///< 获取入口块
|
||||
void removeBasicBlock(BasicBlock *blockToRemove) {
|
||||
auto is_same_ptr = [blockToRemove](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == blockToRemove; };
|
||||
blocks.remove_if(is_same_ptr);
|
||||
}
|
||||
// blocks.erase(std::remove_if(blocks.begin(), blocks.end(), is_same_ptr), blocks.end());
|
||||
} ///< 将该块从function的blocks中删除
|
||||
// auto getBasicBlocks_NoRange() -> block_list & { return blocks; }
|
||||
BasicBlock* addBasicBlock(const std::string &name = "") {
|
||||
blocks.emplace_back(new BasicBlock(this, name));
|
||||
return blocks.back().get();
|
||||
}
|
||||
} ///< 添加新的基本块
|
||||
BasicBlock* addBasicBlock(BasicBlock *block) {
|
||||
blocks.emplace_back(block);
|
||||
return block;
|
||||
}
|
||||
} ///< 添加基本块到blocks中
|
||||
BasicBlock* addBasicBlockFront(BasicBlock *block) {
|
||||
blocks.emplace_front(block);
|
||||
return block;
|
||||
}
|
||||
};
|
||||
} // 从前端插入新的基本块
|
||||
/** value -- alloc blocks mapping */
|
||||
void addValue2AllocBlocks(Value *value, BasicBlock *block) {
|
||||
value2AllocBlocks[value] = block;
|
||||
} ///< 添加value -- alloc block mapping
|
||||
BasicBlock* getAllocBlockByValue(Value *value) {
|
||||
if (value2AllocBlocks.count(value) > 0) {
|
||||
return value2AllocBlocks[value];
|
||||
}
|
||||
return nullptr;
|
||||
} ///< 通过value获取alloc block
|
||||
std::unordered_map<Value *, BasicBlock *>& getValue2AllocBlocks() {
|
||||
return value2AllocBlocks;
|
||||
} ///< 获取所有value -- alloc block mappings
|
||||
void removeValue2AllocBlock(Value *value) {
|
||||
value2AllocBlocks.erase(value);
|
||||
} ///< 删除value -- alloc block mapping
|
||||
/** value -- define blocks mapping */
|
||||
void addValue2DefBlocks(Value *value, BasicBlock *block) {
|
||||
++value2DefBlocks[value][block];
|
||||
} ///< 添加value -- define block mapping
|
||||
// keep in mind that the return is not a reference.
|
||||
std::unordered_set<BasicBlock *> getDefBlocksByValue(Value *value) {
|
||||
std::unordered_set<BasicBlock *> blocks;
|
||||
if (value2DefBlocks.count(value) > 0) {
|
||||
for (const auto &pair : value2DefBlocks[value]) {
|
||||
blocks.insert(pair.first);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
} ///< 通过value获取define blocks
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2DefBlocks() {
|
||||
return value2DefBlocks;
|
||||
} ///< 获取所有value -- define blocks mappings
|
||||
bool removeValue2DefBlock(Value *value, BasicBlock *block) {
|
||||
bool changed = false;
|
||||
if (--value2DefBlocks[value][block] == 0) {
|
||||
value2DefBlocks[value].erase(block);
|
||||
if (value2DefBlocks[value].empty()) {
|
||||
value2DefBlocks.erase(value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
} ///< 删除value -- define block mapping
|
||||
std::unordered_set<Value *> getValuesOfDefBlock() {
|
||||
std::unordered_set<Value *> values;
|
||||
for (const auto &pair : value2DefBlocks) {
|
||||
values.insert(pair.first);
|
||||
}
|
||||
return values;
|
||||
} ///< 获取所有定义过的value
|
||||
/** value -- use blocks mapping */
|
||||
void addValue2UseBlocks(Value *value, BasicBlock *block) {
|
||||
++value2UseBlocks[value][block];
|
||||
} ///< 添加value -- use block mapping
|
||||
// keep in mind that the return is not a reference.
|
||||
std::unordered_set<BasicBlock *> getUseBlocksByValue(Value *value) {
|
||||
std::unordered_set<BasicBlock *> blocks;
|
||||
if (value2UseBlocks.count(value) > 0) {
|
||||
for (const auto &pair : value2UseBlocks[value]) {
|
||||
blocks.insert(pair.first);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
} ///< 通过value获取use blocks
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2UseBlocks() {
|
||||
return value2UseBlocks;
|
||||
} ///< 获取所有value -- use blocks mappings
|
||||
bool removeValue2UseBlock(Value *value, BasicBlock *block) {
|
||||
bool changed = false;
|
||||
if (--value2UseBlocks[value][block] == 0) {
|
||||
value2UseBlocks[value].erase(block);
|
||||
if (value2UseBlocks[value].empty()) {
|
||||
value2UseBlocks.erase(value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
} ///< 删除value -- use block mapping
|
||||
void addIndirectAlloca(AllocaInst *alloca) { indirectAllocas.emplace_back(alloca); } ///< 添加间接分配
|
||||
std::list<std::unique_ptr<AllocaInst>>& getIndirectAllocas() {
|
||||
return indirectAllocas;
|
||||
} ///< 获取间接分配列表
|
||||
|
||||
/** loop -- begin */
|
||||
|
||||
void addLoop(Loop *loop) { loops.emplace_back(loop); } ///< 添加循环(非顶层)
|
||||
void addTopLoop(Loop *loop) { topLoops.emplace_back(loop); } ///< 添加顶层循环
|
||||
Loop_list& getLoops() { return loops; } ///< 获得循环(非顶层)
|
||||
Loop_list& getTopLoops() { return topLoops; } ///< 获得顶层循环
|
||||
/** loop -- end */
|
||||
|
||||
}; // class Function
|
||||
|
||||
//! Global value declared at file scope
|
||||
class GlobalValue : public User, public LVal {
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include "SysYIRAnalyser.h"
|
||||
|
||||
namespace sysy {
|
||||
/**
|
||||
* 实现静态单变量赋值核心类 mem2reg
|
||||
*/
|
||||
class Mem2Reg {
|
||||
private:
|
||||
Module *pModule;
|
||||
IRBuilder *pBuilder;
|
||||
ActiveVarAnalysis *activeVarAnalysis; // 活跃变量分析
|
||||
ControlFlowAnalysis *controlFlowAnalysis; // 控制流分析
|
||||
DataFlowAnalysisUtils dataFlowAnalysisUtils;
|
||||
|
||||
public:
|
||||
Mem2Reg(Module *pMoudle, IRBuilder *pBuilder) :
|
||||
pModule(pMoudle), pBuilder(pBuilder), activeVarAnalysis(nullptr), controlFlowAnalysis(nullptr), dataFlowAnalysisUtils()
|
||||
{} // 初始化函数
|
||||
|
||||
void mem2regPipeline(); ///< mem2reg
|
||||
|
||||
private:
|
||||
|
||||
// phi节点的插入需要计算IDF
|
||||
std::unordered_set<BasicBlock *> computeIterDf(const std::unordered_set<BasicBlock *> &blocks); ///< 计算定义块集合的迭代支配边界
|
||||
|
||||
auto computeValue2Blocks() -> void; ///< 计算value2block的映射(不包括数组和global)
|
||||
|
||||
auto preOptimize1() -> void; ///< llvm memtoreg预优化1: 删除不含load的alloc和store
|
||||
auto preOptimize2() -> void; ///< llvm memtoreg预优化2: 针对某个变量的Defblocks只有一个块的情况
|
||||
auto preOptimize3() -> void; ///< llvm memtoreg预优化3: 针对某个变量的所有读写都在同一个块中的情况
|
||||
|
||||
auto insertPhi() -> void; ///< 为所有变量的迭代支配边界插入phi结点
|
||||
|
||||
auto rename(BasicBlock *block, std::unordered_map<Value *, int> &count,
|
||||
std::unordered_map<Value *, std::stack<Instruction *>> &stacks) -> void; ///< 单个块的重命名
|
||||
auto renameAll() -> void; ///< 重命名所有块
|
||||
|
||||
// private helper function.
|
||||
private:
|
||||
auto getPredIndex(BasicBlock *n, BasicBlock *s) -> int; ///< 获取前驱索引
|
||||
auto cascade(Instruction *instr, bool &changed, Function *func, BasicBlock *block,
|
||||
std::list<std::unique_ptr<Instruction>> &instrs) -> void; ///< 消除级联关系
|
||||
auto isGlobal(Value *val) -> bool; ///< 判断是否是全局变量
|
||||
auto isArr(Value *val) -> bool; ///< 判断是否是数组
|
||||
auto usedelete(Instruction *instr) -> void; ///< 删除指令相关的value-use-user关系
|
||||
|
||||
};
|
||||
} // namespace sysy
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
|
||||
namespace sysy {
|
||||
/**
|
||||
* Reg2Mem(后端未做phi指令翻译)
|
||||
*/
|
||||
class Reg2Mem {
|
||||
private:
|
||||
Module *pModule;
|
||||
IRBuilder *pBuilder;
|
||||
|
||||
public:
|
||||
Reg2Mem(Module *pMoudle, IRBuilder *pBuilder) : pModule(pMoudle), pBuilder(pBuilder) {}
|
||||
|
||||
void DeletePhiInst();
|
||||
// 删除UD关系, 因为删除了phi指令会修改ud关系
|
||||
void usedelete(Instruction *instr);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@@ -1,465 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
|
||||
class Loop;
|
||||
// 基本块分析信息类
|
||||
class BlockAnalysisInfo {
|
||||
|
||||
public:
|
||||
using block_list = std::vector<BasicBlock*>;
|
||||
using block_set = std::unordered_set<BasicBlock*>;
|
||||
|
||||
protected:
|
||||
// 支配树相关
|
||||
int domdepth = 0; ///< 支配节点所在深度
|
||||
BasicBlock* idom = nullptr; ///< 直接支配结点
|
||||
block_list sdoms; ///< 支配树后继
|
||||
block_set dominants; ///< 必经结点集合
|
||||
block_set dominant_frontiers; ///< 支配边界
|
||||
|
||||
// 后续添加循环分析相关
|
||||
// Loop* loopbelong = nullptr; ///< 所属循环
|
||||
// int loopdepth = 0; ///< 循环深度
|
||||
|
||||
public:
|
||||
// getterface
|
||||
const int getDomDepth() const { return domdepth; }
|
||||
const BasicBlock* getIdom() const { return idom; }
|
||||
const block_list& getSdoms() const { return sdoms; }
|
||||
const block_set& getDominants() const { return dominants; }
|
||||
const block_set& getDomFrontiers() const { return dominant_frontiers; }
|
||||
|
||||
// 支配树操作
|
||||
void setDomDepth(int depth) { domdepth = depth; }
|
||||
void setIdom(BasicBlock* block) { idom = block; }
|
||||
void addSdoms(BasicBlock* block) { sdoms.push_back(block); }
|
||||
void clearSdoms() { sdoms.clear(); }
|
||||
void removeSdoms(BasicBlock* block) {
|
||||
sdoms.erase(std::remove(sdoms.begin(), sdoms.end(), block), sdoms.end());
|
||||
}
|
||||
void addDominants(BasicBlock* block) { dominants.emplace(block); }
|
||||
void addDominants(const block_set& blocks) { dominants.insert(blocks.begin(), blocks.end()); }
|
||||
void setDominants(BasicBlock* block) {
|
||||
dominants.clear();
|
||||
addDominants(block);
|
||||
}
|
||||
void setDominants(const block_set& doms) {
|
||||
dominants = doms;
|
||||
}
|
||||
void setDomFrontiers(const block_set& df) {
|
||||
dominant_frontiers = df;
|
||||
}
|
||||
|
||||
// TODO:循环分析操作方法
|
||||
|
||||
// 清空所有分析信息
|
||||
void clear() {
|
||||
domdepth = -1;
|
||||
idom = nullptr;
|
||||
sdoms.clear();
|
||||
dominants.clear();
|
||||
dominant_frontiers.clear();
|
||||
// loopbelong = nullptr;
|
||||
// loopdepth = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// 函数分析信息类
|
||||
class FunctionAnalysisInfo {
|
||||
|
||||
|
||||
public:
|
||||
// 函数属性
|
||||
enum FunctionAttribute : uint64_t {
|
||||
PlaceHolder = 0x0UL,
|
||||
Pure = 0x1UL << 0,
|
||||
SelfRecursive = 0x1UL << 1,
|
||||
SideEffect = 0x1UL << 2,
|
||||
NoPureCauseMemRead = 0x1UL << 3
|
||||
};
|
||||
|
||||
// 数据结构
|
||||
using Loop_list = std::list<std::unique_ptr<Loop>>;
|
||||
using block_loop_map = std::unordered_map<BasicBlock*, Loop*>;
|
||||
using value_block_map = std::unordered_map<Value*, BasicBlock*>;
|
||||
using value_block_count_map = std::unordered_map<Value*, std::unordered_map<BasicBlock*, int>>;
|
||||
|
||||
// 分析数据
|
||||
FunctionAttribute attribute = PlaceHolder; ///< 函数属性
|
||||
std::set<Function*> callees; ///< 函数调用集合
|
||||
Loop_list loops; ///< 所有循环
|
||||
Loop_list topLoops; ///< 顶层循环
|
||||
// block_loop_map basicblock2Loop; ///< 基本块到循环映射
|
||||
std::list<std::unique_ptr<AllocaInst>> indirectAllocas; ///< 间接分配内存
|
||||
|
||||
// 值定义/使用信息
|
||||
value_block_map value2AllocBlocks; ///< 值分配位置映射
|
||||
value_block_count_map value2DefBlocks; ///< 值定义位置映射
|
||||
value_block_count_map value2UseBlocks; ///< 值使用位置映射
|
||||
|
||||
// 函数属性操作
|
||||
FunctionAttribute getAttribute() const { return attribute; }
|
||||
void setAttribute(FunctionAttribute attr) { attribute = static_cast<FunctionAttribute>(attribute | attr); }
|
||||
void clearAttribute() { attribute = PlaceHolder; }
|
||||
|
||||
// 调用关系操作
|
||||
void addCallee(Function* callee) { callees.insert(callee); }
|
||||
void removeCallee(Function* callee) { callees.erase(callee); }
|
||||
void clearCallees() { callees.clear(); }
|
||||
|
||||
|
||||
// 值-块映射操作
|
||||
BasicBlock* getAllocBlockByValue(Value* value) {
|
||||
auto it = value2AllocBlocks.find(value);
|
||||
return it != value2AllocBlocks.end() ? it->second : nullptr;
|
||||
}
|
||||
std::unordered_set<BasicBlock *> getDefBlocksByValue(Value *value) {
|
||||
std::unordered_set<BasicBlock *> blocks;
|
||||
if (value2DefBlocks.count(value) > 0) {
|
||||
for (const auto &pair : value2DefBlocks[value]) {
|
||||
blocks.insert(pair.first);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
std::unordered_set<BasicBlock *> getUseBlocksByValue(Value *value) {
|
||||
std::unordered_set<BasicBlock *> blocks;
|
||||
if (value2UseBlocks.count(value) > 0) {
|
||||
for (const auto &pair : value2UseBlocks[value]) {
|
||||
blocks.insert(pair.first);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
// 值定义/使用操作
|
||||
void addValue2AllocBlocks(Value* value, BasicBlock* block) { value2AllocBlocks[value] = block; }
|
||||
void addValue2DefBlocks(Value* value, BasicBlock* block) { ++value2DefBlocks[value][block]; }
|
||||
void addValue2UseBlocks(Value* value, BasicBlock* block) { ++value2UseBlocks[value][block]; }
|
||||
|
||||
|
||||
// 获取值定义/使用信息
|
||||
std::unordered_map<Value *, BasicBlock *>& getValue2AllocBlocks() {
|
||||
return value2AllocBlocks;
|
||||
}
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2DefBlocks() {
|
||||
return value2DefBlocks;
|
||||
}
|
||||
std::unordered_map<Value *, std::unordered_map<BasicBlock *, int>>& getValue2UseBlocks() {
|
||||
return value2UseBlocks;
|
||||
}
|
||||
std::unordered_set<Value *> getValuesOfDefBlock() {
|
||||
std::unordered_set<Value *> values;
|
||||
for (const auto &pair : value2DefBlocks) {
|
||||
values.insert(pair.first);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// 删除信息操作
|
||||
void removeValue2AllocBlock(Value *value) { value2AllocBlocks.erase(value); }
|
||||
bool removeValue2DefBlock(Value *value, BasicBlock *block) {
|
||||
bool changed = false;
|
||||
if (--value2DefBlocks[value][block] == 0) {
|
||||
value2DefBlocks[value].erase(block);
|
||||
if (value2DefBlocks[value].empty()) {
|
||||
value2DefBlocks.erase(value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
bool removeValue2UseBlock(Value *value, BasicBlock *block) {
|
||||
bool changed = false;
|
||||
if (--value2UseBlocks[value][block] == 0) {
|
||||
value2UseBlocks[value].erase(block);
|
||||
if (value2UseBlocks[value].empty()) {
|
||||
value2UseBlocks.erase(value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 间接分配操作
|
||||
void addIndirectAlloca(AllocaInst* alloca) { indirectAllocas.emplace_back(alloca); }
|
||||
std::list<std::unique_ptr<AllocaInst>>& getIndirectAllocas() { return indirectAllocas; }
|
||||
|
||||
// TODO:循环分析操作
|
||||
|
||||
// 清空所有分析信息
|
||||
void clear() {
|
||||
attribute = PlaceHolder;
|
||||
callees.clear();
|
||||
loops.clear();
|
||||
topLoops.clear();
|
||||
// basicblock2Loop.clear();
|
||||
indirectAllocas.clear();
|
||||
value2AllocBlocks.clear();
|
||||
value2DefBlocks.clear();
|
||||
value2UseBlocks.clear();
|
||||
}
|
||||
};
|
||||
// 循环类 - 未实现优化
|
||||
class Loop {
|
||||
public:
|
||||
using block_list = std::vector<BasicBlock *>;
|
||||
using block_set = std::unordered_set<BasicBlock *>;
|
||||
using Loop_list = std::vector<Loop *>;
|
||||
|
||||
protected:
|
||||
Function *parent; // 所属函数
|
||||
block_list blocksInLoop; // 循环内的基本块
|
||||
BasicBlock *preheaderBlock = nullptr; // 前驱块
|
||||
BasicBlock *headerBlock = nullptr; // 循环头
|
||||
block_list latchBlock; // 回边块
|
||||
block_set exitingBlocks; // 退出块
|
||||
block_set exitBlocks; // 退出目标块
|
||||
Loop *parentloop = nullptr; // 父循环
|
||||
Loop_list subLoops; // 子循环
|
||||
size_t loopID; // 循环ID
|
||||
unsigned loopDepth; // 循环深度
|
||||
|
||||
Instruction *indCondVar = nullptr; // 循环条件变量
|
||||
Instruction::Kind IcmpKind; // 比较类型
|
||||
Value *indEnd = nullptr; // 循环结束值
|
||||
AllocaInst *IndPhi = nullptr; // 循环变量
|
||||
|
||||
ConstantValue *indBegin = nullptr; // 循环起始值
|
||||
ConstantValue *indStep = nullptr; // 循环步长
|
||||
|
||||
std::set<GlobalValue *> GlobalValuechange; // 循环内改变的全局变量
|
||||
|
||||
int StepType = 0; // 循环步长类型
|
||||
bool parallelable = false; // 是否可并行
|
||||
|
||||
public:
|
||||
explicit Loop(BasicBlock *header, const std::string &name = "")
|
||||
: headerBlock(header) {
|
||||
blocksInLoop.push_back(header);
|
||||
}
|
||||
|
||||
void setloopID() {
|
||||
static unsigned loopCount = 0;
|
||||
loopCount = loopCount + 1;
|
||||
loopID = loopCount;
|
||||
}
|
||||
ConstantValue* getindBegin() { return indBegin; }
|
||||
ConstantValue* getindStep() { return indStep; }
|
||||
void setindBegin(ConstantValue *indBegin2set) { indBegin = indBegin2set; }
|
||||
void setindStep(ConstantValue *indStep2set) { indStep = indStep2set; }
|
||||
void setStepType(int StepType2Set) { StepType = StepType2Set; }
|
||||
int getStepType() { return StepType; }
|
||||
size_t getLoopID() { return loopID; }
|
||||
|
||||
BasicBlock* getHeader() const { return headerBlock; }
|
||||
BasicBlock* getPreheaderBlock() const { return preheaderBlock; }
|
||||
block_list& getLatchBlocks() { return latchBlock; }
|
||||
block_set& getExitingBlocks() { return exitingBlocks; }
|
||||
block_set& getExitBlocks() { return exitBlocks; }
|
||||
Loop* getParentLoop() const { return parentloop; }
|
||||
void setParentLoop(Loop *parent) { parentloop = parent; }
|
||||
void addBasicBlock(BasicBlock *bb) { blocksInLoop.push_back(bb); }
|
||||
void addSubLoop(Loop *loop) { subLoops.push_back(loop); }
|
||||
void setLoopDepth(unsigned depth) { loopDepth = depth; }
|
||||
block_list& getBasicBlocks() { return blocksInLoop; }
|
||||
Loop_list& getSubLoops() { return subLoops; }
|
||||
unsigned getLoopDepth() const { return loopDepth; }
|
||||
|
||||
bool isLoopContainsBasicBlock(BasicBlock *bb) const {
|
||||
return std::find(blocksInLoop.begin(), blocksInLoop.end(), bb) != blocksInLoop.end();
|
||||
}
|
||||
|
||||
void addExitingBlock(BasicBlock *bb) { exitingBlocks.insert(bb); }
|
||||
void addExitBlock(BasicBlock *bb) { exitBlocks.insert(bb); }
|
||||
void addLatchBlock(BasicBlock *bb) { latchBlock.push_back(bb); }
|
||||
void setPreheaderBlock(BasicBlock *bb) { preheaderBlock = bb; }
|
||||
|
||||
void setIndexCondInstr(Instruction *instr) { indCondVar = instr; }
|
||||
void setIcmpKind(Instruction::Kind kind) { IcmpKind = kind; }
|
||||
Instruction::Kind getIcmpKind() const { return IcmpKind; }
|
||||
|
||||
bool isSimpleLoopInvariant(Value *value) ;
|
||||
|
||||
void setIndEnd(Value *value) { indEnd = value; }
|
||||
void setIndPhi(AllocaInst *phi) { IndPhi = phi; }
|
||||
Value* getIndEnd() const { return indEnd; }
|
||||
AllocaInst* getIndPhi() const { return IndPhi; }
|
||||
Instruction* getIndCondVar() const { return indCondVar; }
|
||||
|
||||
void addGlobalValuechange(GlobalValue *globalvaluechange2add) {
|
||||
GlobalValuechange.insert(globalvaluechange2add);
|
||||
}
|
||||
std::set<GlobalValue *>& getGlobalValuechange() {
|
||||
return GlobalValuechange;
|
||||
}
|
||||
|
||||
void setParallelable(bool flag) { parallelable = flag; }
|
||||
bool isParallelable() const { return parallelable; }
|
||||
};
|
||||
|
||||
// 控制流分析类
|
||||
class ControlFlowAnalysis {
|
||||
private:
|
||||
Module *pModule; ///< 模块
|
||||
std::unordered_map<BasicBlock*, BlockAnalysisInfo*> blockAnalysisInfo; // 基本块分析信息表
|
||||
std::unordered_map<Function*, FunctionAnalysisInfo*> functionAnalysisInfo; // 函数分析信息
|
||||
|
||||
public:
|
||||
explicit ControlFlowAnalysis(Module *pMoudle) : pModule(pMoudle) {}
|
||||
|
||||
// 获取基本块分析信息
|
||||
BlockAnalysisInfo* getBlockAnalysisInfo(BasicBlock *block) {
|
||||
auto it = blockAnalysisInfo.find(block);
|
||||
if (it != blockAnalysisInfo.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr; // 如果未找到,返回nullptr
|
||||
}
|
||||
FunctionAnalysisInfo* getFunctionAnalysisInfo(Function *func) {
|
||||
auto it = functionAnalysisInfo.find(func);
|
||||
if (it != functionAnalysisInfo.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr; // 如果未找到,返回nullptr
|
||||
}
|
||||
|
||||
void init(); // 初始化分析器
|
||||
void computeDomNode(); // 计算必经结点
|
||||
void computeDomTree(); // 构造支配树
|
||||
// std::unordered_set<BasicBlock *> computeDomFrontier(BasicBlock *block) ; // 计算单个块的支配边界(弃用)
|
||||
void computeDomFrontierAllBlk(); // 计算所有块的支配边界
|
||||
void runControlFlowAnalysis(); // 运行控制流分析(主要是支配树和支配边界)
|
||||
void clear(){
|
||||
for (auto &pair : blockAnalysisInfo) {
|
||||
delete pair.second; // 清理基本块分析信息
|
||||
}
|
||||
blockAnalysisInfo.clear();
|
||||
|
||||
for (auto &pair : functionAnalysisInfo) {
|
||||
delete pair.second; // 清理函数分析信息
|
||||
}
|
||||
functionAnalysisInfo.clear();
|
||||
} // 清空分析结果
|
||||
~ControlFlowAnalysis() {
|
||||
clear(); // 析构时清理所有分析信息
|
||||
}
|
||||
|
||||
private:
|
||||
void intersectOP4Dom(std::unordered_set<BasicBlock *> &dom, const std::unordered_set<BasicBlock *> &other); // 交集运算,
|
||||
BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点
|
||||
};
|
||||
|
||||
// 数据流分析类
|
||||
// 该类为抽象类,具体的数据流分析器需要继承此类
|
||||
// 因为每个数据流分析器的分析动作都不一样,所以需要继承并实现analyze方法
|
||||
class DataFlowAnalysis {
|
||||
public:
|
||||
virtual ~DataFlowAnalysis() = default;
|
||||
|
||||
public:
|
||||
virtual void init(Module *pModule) {} ///< 分析器初始化
|
||||
virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作,若完成则返回true;
|
||||
virtual void clear() {} ///< 清空
|
||||
};
|
||||
|
||||
// 数据流分析工具类
|
||||
// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口
|
||||
class DataFlowAnalysisUtils {
|
||||
private:
|
||||
std::vector<DataFlowAnalysis *> forwardAnalysisList; ///< 前向分析器列表
|
||||
std::vector<DataFlowAnalysis *> backwardAnalysisList; ///< 后向分析器列表
|
||||
|
||||
public:
|
||||
DataFlowAnalysisUtils() = default;
|
||||
~DataFlowAnalysisUtils() {
|
||||
clear(); // 析构时清理所有分析器
|
||||
}
|
||||
// 统一添加接口
|
||||
void addAnalyzers(
|
||||
std::vector<DataFlowAnalysis *> forwardList,
|
||||
std::vector<DataFlowAnalysis *> backwardList = {})
|
||||
{
|
||||
forwardAnalysisList.insert(
|
||||
forwardAnalysisList.end(),
|
||||
forwardList.begin(),
|
||||
forwardList.end());
|
||||
|
||||
backwardAnalysisList.insert(
|
||||
backwardAnalysisList.end(),
|
||||
backwardList.begin(),
|
||||
backwardList.end());
|
||||
}
|
||||
|
||||
// 单独添加接口
|
||||
void addForwardAnalyzer(DataFlowAnalysis *analyzer) {
|
||||
forwardAnalysisList.push_back(analyzer);
|
||||
}
|
||||
|
||||
void addBackwardAnalyzer(DataFlowAnalysis *analyzer) {
|
||||
backwardAnalysisList.push_back(analyzer);
|
||||
}
|
||||
|
||||
// 设置分析器列表
|
||||
void setAnalyzers(
|
||||
std::vector<DataFlowAnalysis *> forwardList,
|
||||
std::vector<DataFlowAnalysis *> backwardList)
|
||||
{
|
||||
forwardAnalysisList = std::move(forwardList);
|
||||
backwardAnalysisList = std::move(backwardList);
|
||||
}
|
||||
|
||||
// 清空列表
|
||||
void clear() {
|
||||
forwardAnalysisList.clear();
|
||||
backwardAnalysisList.clear();
|
||||
}
|
||||
|
||||
// 访问器
|
||||
const auto& getForwardAnalyzers() const { return forwardAnalysisList; }
|
||||
const auto& getBackwardAnalyzers() const { return backwardAnalysisList; }
|
||||
|
||||
public:
|
||||
void forwardAnalyze(Module *pModule); ///< 执行前向分析
|
||||
void backwardAnalyze(Module *pModule); ///< 执行后向分析
|
||||
};
|
||||
|
||||
// 活跃变量分析类
|
||||
// 提供def - use分析
|
||||
// 未兼容数组变量但是考虑了维度的use信息
|
||||
class ActiveVarAnalysis : public DataFlowAnalysis {
|
||||
private:
|
||||
std::map<BasicBlock *, std::vector<std::set<User *>>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息
|
||||
|
||||
public:
|
||||
ActiveVarAnalysis() = default;
|
||||
~ActiveVarAnalysis() override = default;
|
||||
|
||||
public:
|
||||
static std::set<User*> getUsedSet(Instruction *inst);
|
||||
static User* getDefine(Instruction *inst);
|
||||
|
||||
public:
|
||||
void init(Module *pModule) override;
|
||||
bool analyze(Module *pModule, BasicBlock *block) override;
|
||||
// 外部活跃信息表访问器
|
||||
const std::map<BasicBlock *, std::vector<std::set<User *>>> &getActiveTable() const;
|
||||
void clear() override {
|
||||
activeTable.clear(); // 清空活跃信息表
|
||||
}
|
||||
};
|
||||
|
||||
// 分析管理器 后续实现
|
||||
// class AnalysisManager {
|
||||
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
@@ -10,9 +10,7 @@ using namespace antlr4;
|
||||
#include "SysYIRGenerator.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include "SysYIROptPre.h"
|
||||
#include "SysYIRAnalyser.h"
|
||||
#include "Mem2Reg.h"
|
||||
#include "Reg2Mem.h"
|
||||
#include "RISCv32Backend.h"
|
||||
// #include "LLVMIRGenerator.h"
|
||||
using namespace sysy;
|
||||
|
||||
@@ -76,23 +74,26 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
// visit AST to generate IR
|
||||
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
if (argStopAfter == "ir") {
|
||||
SysYIRGenerator generator;
|
||||
generator.visitCompUnit(moduleAST);
|
||||
auto moduleIR = generator.get();
|
||||
SysYPrinter printer(moduleIR);
|
||||
printer.printIR();
|
||||
auto builder = generator.getBuilder();
|
||||
SysYOptPre optPre(moduleIR, builder);
|
||||
optPre.SysYOptimizateAfterIR();
|
||||
Mem2Reg mem2reg(moduleIR, builder);
|
||||
mem2reg.mem2regPipeline();
|
||||
printer.printIR();
|
||||
Reg2Mem reg2mem(moduleIR, builder);
|
||||
reg2mem.DeletePhiInst();
|
||||
printer.printIR();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// generate assembly
|
||||
auto module = generator.get();
|
||||
sysy::RISCv32CodeGen codegen(module);
|
||||
string asmCode = codegen.code_gen();
|
||||
if (argStopAfter == "asm") {
|
||||
cout << asmCode << endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
//test add
|
||||
|
||||
|
||||
int main(){
|
||||
int a, b;
|
||||
float d;
|
||||
a = 10;
|
||||
b = 2;
|
||||
int c = a;
|
||||
d = 1.1 ;
|
||||
return a + b + c;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ int main() {
|
||||
const int b = 2;
|
||||
int c;
|
||||
|
||||
if (a == b)
|
||||
c = a + b;
|
||||
if (a != b)
|
||||
c = b - a + 20; // 21 <- this
|
||||
else
|
||||
c = a * b;
|
||||
c = a * b + b + b + 10; // 16
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ int mul(int x, int y) {
|
||||
int main(){
|
||||
int a, b;
|
||||
a = 10;
|
||||
b = 0;
|
||||
a = mul(a, b);
|
||||
return a + b;
|
||||
b = 3;
|
||||
a = mul(a, b); //60
|
||||
return a + b; //66
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user