Commit e555b9cc authored by 李晓奇's avatar 李晓奇

Merge branch 'master' of 202.38.79.174:compiler_staff/2022fall-compiler_cminus

parents 7cc5d18a 2f5d0fa7
......@@ -48,6 +48,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_BINARY_DIR})
include_directories(include/lightir)
include_directories(include/optimization)
add_subdirectory(src)
add_subdirectory(tests)
......@@ -33,6 +33,7 @@ Lab3 实验建立在 Lab2 的基础上,带领大家进一步理解源代码到
2. 助教们在 `cminusf_builder.cpp` 提供的部分函数是不完整的,无法通过所有测试用例。需要你补充代码的地方已经用 `TODO` 标出。我们提供的`cminusf_builder.cpp` 只可以满足测试用例 `lv0_1` 中的 `return.cminus`。虽然`eval.py`会显示其他一些测试用例也是`success`,但它对应的`.ll`文件是不正确的,不要因其显示 `success` 忽略了对应的代码补充,那会影响你后面较复杂样例的正确性。
3. 简要阅读 `cminusf_builder.hpp` 和其他头文件中定义的函数和变量,理解项目框架也会为你的实验提供很大的帮助。
4. 请独立完成实验,不要抄袭他人代码。
5. 为方便同学们更好完成实验,补充提示文档,参见[Lab3 More Tips](./more-tips.md)
## 1. 实验框架
......@@ -64,6 +65,7 @@ bool in_global();
```sh
mkdir build && cd build
cmake ..
make clean
make -j
# 安装库 libcminus_io.a 至系统目录
......@@ -179,8 +181,8 @@ cminusfc test.cminus
* 禁止执行恶意代码,违者本次实验0分处理
* 迟交规定
* `Soft Deadline` : 2022/11/07 23:59:59 (北京标准时间,UTC+8)
* `Hard Deadline` : 2022/11/14 23:59:59 (北京标准时间,UTC+8)
* `Soft Deadline` : 2022/11/13 23:59:59 (北京标准时间,UTC+8)
* `Hard Deadline` : 2022/11/20 23:59:59 (北京标准时间,UTC+8)
* 迟交需要邮件通知TA:
* 邮箱: `lq_2019@mail.ustc.edu.cn` 抄送 `edwardzcn@mail.ustc.edu.cn`
* 邮件主题: lab3迟交-学号-姓名
......
# Lab3 补充说明
## 重要提醒
希望同学们仔细阅读实验文档`cminusf.md``LightIR.md`,在lab3编写的过程中也结合自己在lab2所做的工作。
如果在编写过程中不知道具体用哪些函数,可以去查看给出代码中的函数所在的头文件,里面包含部分其他需要用的函数。
## 部分函数的注释
```c++
//存储当前value
Value *tmp_val = nullptr;
// 当前函数
Function *cur_fun = nullptr;
// 表示是否在之前已经进入scope,用于CompoundStmt
// 进入CompoundStmt不仅包括通过Fundeclaration进入,也包括selection-stmt等。
// pre_enter_scope用于控制是否在CompoundStmt中添加scope.enter,scope.exit
bool pre_enter_scope = false;
// types
Type *VOID_T;
Type *INT1_T;
Type *INT32_T;
Type *INT32PTR_T;
Type *FLOAT_T;
Type *FLOATPTR_T;
/*
* use CMinusfBuilder::Scope to construct scopes
* scope.enter: enter a new scope
* scope.exit: exit current scope
* scope.push: add a new binding to current scope
* scope.find: find and return the value bound to the name
*/
void CminusfBuilder::visit(ASTProgram &node) {
VOID_T = Type::get_void_type(module.get());
INT1_T = Type::get_int1_type(module.get());
INT32_T = Type::get_int32_type(module.get());
INT32PTR_T = Type::get_int32_ptr_type(module.get());
FLOAT_T = Type::get_float_type(module.get());
FLOATPTR_T = Type::get_float_ptr_type(module.get());
for (auto decl: node.declarations) { // program -> declaration-list
decl->accept(*this);//进入下一层函数
}
}
void CminusfBuilder::visit(ASTFunDeclaration &node) {
FunctionType *fun_type;
Type *ret_type;
std::vector<Type *> param_types;
if (node.type == TYPE_INT)//函数返回值类型
ret_type = INT32_T;
else if (node.type == TYPE_FLOAT)
ret_type = FLOAT_T;
else
ret_type = VOID_T;
for (auto& param: node.params) { //补全param_types
//TODO:
//根据param的类型分类
//需要考虑int型数组,int型,float型数组,float型
//对于不同的类型,向param_types中添加不同的Type
//param_types.push_back
}
fun_type = FunctionType::get(ret_type, param_types);
auto fun =
Function::create(
fun_type,
node.id,
module.get());//定义函数变量
scope.push(node.id, fun);
cur_fun = fun;
auto funBB = BasicBlock::create(module.get(), "entry", fun);//创建基本块
builder->set_insert_point(funBB);
scope.enter();
pre_enter_scope = true;
std::vector<Value*> args;
for (auto arg = fun->arg_begin();arg != fun->arg_end();arg++) {
args.push_back(*arg);
}
for (int i = 0;i < node.params.size();++i) {
//TODO:
//需要考虑int型数组,int型,float型数组,float型
//builder->create_alloca创建alloca语句
//builder->create_store创建store语句
//scope.push
}
node.compound_stmt->accept(*this);//fun-declaration -> type-specifier ID ( params ) compound-stmt
if (builder->get_insert_block()->get_terminator() == nullptr){//创建ret语句
if (cur_fun->get_return_type()->is_void_type())
builder->create_void_ret();
else if (cur_fun->get_return_type()->is_float_type())
builder->create_ret(CONST_FP(0.));
else
builder->create_ret(CONST_INT(0));
}
scope.exit();
}
void CminusfBuilder::visit(ASTParam &node) { }
void CminusfBuilder::visit(ASTCompoundStmt &node) {
//TODO:此函数为完整实现
bool need_exit_scope = !pre_enter_scope;//添加need_exit_scope变量
if (pre_enter_scope) {
pre_enter_scope = false;
} else {
scope.enter();
}
for (auto& decl: node.local_declarations) {//compound-stmt -> { local-declarations statement-list }
decl->accept(*this);
}
for (auto& stmt: node.statement_list) {
stmt->accept(*this);
if (builder->get_insert_block()->get_terminator() != nullptr)
break;
}
if (need_exit_scope) {
scope.exit();
}
}
void CminusfBuilder::visit(ASTReturnStmt &node) {//return-stmt -> return ; | return expression ;
if (node.expression == nullptr) {
builder->create_void_ret();
} else {
//TODO:
//需要考虑类型转换
//函数返回值和表达式值类型不同时,转换成函数返回值的类型
//用cur_fun获取当前函数返回值类型
//类型转换:builder->create_fptosi
//ret语句
}
}
```
This diff is collapsed.
......@@ -13,9 +13,16 @@
- [report](./Reports/2-ir-gen-warmup/report.md)
* [lab3](./Documentations/3-ir-gen/)
<<<<<<< HEAD
+ DDL:2022-11-07 23:59:59 (UTC+8)
- [report](./Reports/3-ir-gen/report.md)
=======
+ DDL:2022-11-13 23:59:59 (UTC+8)
* [lab4.1](./Documentations/4.1-ssa/)
+ DDL:2022-11-27 23:59:59 (UTC+8)
>>>>>>> 2f5d0fa70297542b1032ca4614f0f426fa7a4e33
## FAQ: How to merge upstream remote branches
......
# Lab4.1 实验报告
## 实验要求
请按照自己的理解,写明本次实验需要干什么
## 思考题
### Mem2reg
1. ...
2. ...
3. ...
### 代码阅读总结
此次实验有什么收获
### 实验反馈 (可选 不会评分)
对本次实验的建议
......@@ -49,7 +49,7 @@ class BasicBlock : public Value, public llvm::ilist_node<BasicBlock> {
void add_instr_begin(Instruction *instr);
void delete_instr(Instruction *instr);
void erase_instr(Instruction *instr);
bool empty() { return instr_list_.empty(); }
int get_num_of_instr() { return instr_list_.size(); }
......@@ -60,6 +60,7 @@ class BasicBlock : public Value, public llvm::ilist_node<BasicBlock> {
virtual std::string print() override;
private:
BasicBlock(const BasicBlock &) = delete;
explicit BasicBlock(Module *m, const std::string &name, Function *parent);
std::list<BasicBlock *> pre_bbs_;
std::list<BasicBlock *> succ_bbs_;
......
......@@ -21,6 +21,7 @@ class FunctionType;
class Function : public Value, public llvm::ilist_node<Function>
{
public:
Function(const Function &) = delete;
Function(FunctionType *ty, const std::string &name, Module *parent);
virtual ~Function();
static Function *create(FunctionType *ty, const std::string &name,
......
......@@ -17,6 +17,7 @@ class GlobalVariable : public User, public llvm::ilist_node<GlobalVariable> {
GlobalVariable(std::string name, Module *m, Type *ty, bool is_const, Constant *init = nullptr);
public:
GlobalVariable(const GlobalVariable &) = delete;
static GlobalVariable *create(std::string name, Module *m, Type *ty, bool is_const, Constant *init);
virtual ~GlobalVariable() = default;
Constant *get_init() { return init_val_; }
......
......@@ -46,6 +46,7 @@ class Instruction : public User, public llvm::ilist_node<Instruction>
// ty here is result type
Instruction(Type *ty, OpID id, unsigned num_ops, BasicBlock *parent);
Instruction(Type *ty, OpID id, unsigned num_ops);
Instruction(const Instruction &) = delete;
virtual ~Instruction() = default;
inline const BasicBlock *get_parent() const { return parent_; }
inline BasicBlock *get_parent() { return parent_; }
......
#ifndef SYSYC_DOMINATORS_HPP
#define SYSYC_DOMINATORS_HPP
#include "BasicBlock.h"
#include "PassManager.hpp"
#include <list>
#include <map>
#include <set>
class Dominators : public Pass {
public:
explicit Dominators(Module *m) : Pass(m) {}
~Dominators() = default;
void run() override;
void create_doms(Function *f);
void create_reverse_post_order(Function *f);
void create_idom(Function *f);
void create_dominance_frontier(Function *f);
void create_dom_tree_succ(Function *f);
// for debug
void print_idom(Function *f);
void print_dominance_frontier(Function *f);
/****************api about Dominator****************/
void add_dom(BasicBlock *bb, BasicBlock *dom_bb) { doms_[bb].insert(dom_bb); }
std::set<BasicBlock *> &get_doms(BasicBlock *bb) { return doms_[bb]; }
void set_doms(BasicBlock *bb, std::set<BasicBlock *> &doms) {
doms_[bb].clear();
doms_[bb].insert(doms.begin(), doms.end());
}
BasicBlock *get_idom(BasicBlock *bb) { return idom_[bb]; }
void set_idom(BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; }
void add_dominance_frontier(BasicBlock *bb, BasicBlock *dom_frontier_bb) {
dom_frontier_[bb].insert(dom_frontier_bb);
}
std::set<BasicBlock *> &get_dominance_frontier(BasicBlock *bb) { return dom_frontier_[bb]; }
void set_dominance_frontier(BasicBlock *bb, std::set<BasicBlock *> &df) {
dom_frontier_[bb].clear();
dom_frontier_[bb].insert(df.begin(), df.end());
}
// successor blocks of this node in dominance tree
std::set<BasicBlock *> get_dom_tree_succ_blocks(BasicBlock *bb) { return dom_tree_succ_blocks_[bb]; }
void add_dom_tree_succ_block(BasicBlock *bb, BasicBlock *dom_tree_succ_bb) {
dom_tree_succ_blocks_[bb].insert(dom_tree_succ_bb);
}
/****************api about Dominator****************/
private:
void post_order_visit(BasicBlock *bb, std::set<BasicBlock *> &visited);
BasicBlock *intersect(BasicBlock *b1, BasicBlock *b2);
std::list<BasicBlock *> reverse_post_order_{};
std::map<BasicBlock *, int> post_order_id_{}; // the root has highest ID
std::map<BasicBlock *, std::set<BasicBlock *>> doms_{}; // dominance set
std::map<BasicBlock *, BasicBlock *> idom_{}; // immediate dominance
std::map<BasicBlock *, std::set<BasicBlock *>> dom_frontier_{}; // dominance frontier set
std::map<BasicBlock *, std::set<BasicBlock *>> dom_tree_succ_blocks_{};
};
#endif
#ifndef SYSYC_MEM2REG_HPP
#define SYSYC_MEM2REG_HPP
#include "BasicBlock.h"
#include "Dominators.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Instruction.h"
#include "Module.h"
#include "PassManager.hpp"
#include <memory>
class Mem2Reg : public Pass {
private:
Function *func_;
std::unique_ptr<Dominators> dominators_;
public:
Mem2Reg(Module *m) : Pass(m) {}
~Mem2Reg(){};
void run() override;
void generate_phi();
void re_name(BasicBlock *bb);
void remove_alloca();
};
#endif
\ No newline at end of file
#ifndef PASSMANAGER_HPP
#define PASSMANAGER_HPP
#include "Module.h"
#include <memory>
#include <vector>
class Pass {
public:
Pass(Module *m) : m_(m) {}
virtual ~Pass() = default;
virtual void run() = 0;
protected:
Module *m_;
};
class PassManager {
public:
PassManager(Module *m) : m_(m) {}
template <typename PassType, typename... Args>
void add_pass(bool print_ir, Args &&...args) {
passes_.push_back(
std::pair<std::unique_ptr<Pass>, bool>(new PassType(m_, std::forward<Args>(args)...), print_ir));
}
void run() {
for (auto &pass : passes_) {
pass.first->run();
if (pass.second) {
m_->set_print_name();
std::cout << m_->print();
}
}
}
private:
std::vector<std::pair<std::unique_ptr<Pass>, bool>> passes_;
Module *m_;
};
#endif
\ No newline at end of file
......@@ -2,4 +2,5 @@ add_subdirectory(parser)
add_subdirectory(common)
add_subdirectory(io)
add_subdirectory(lightir)
add_subdirectory(cminusfc)
\ No newline at end of file
add_subdirectory(cminusfc)
add_subdirectory(optimization)
\ No newline at end of file
......@@ -9,6 +9,7 @@ target_link_libraries(
IR_lib
common
syntax
OP_lib
)
install(
......
#include "Dominators.h"
#include "Mem2Reg.hpp"
#include "PassManager.hpp"
#include "cminusf_builder.hpp"
#include "logging.hpp"
......@@ -8,7 +11,11 @@
using namespace std::literals::string_literals;
void print_help(std::string exe_name) {
<<<<<<< HEAD
std::cout << "Usage: " << exe_name << " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] <input-file>"
=======
std::cout << "Usage: " << exe_name << " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] [-mem2reg] <input-file>"
>>>>>>> 2f5d0fa70297542b1032ca4614f0f426fa7a4e33
<< std::endl;
}
......@@ -17,10 +24,6 @@ int main(int argc, char **argv) {
std::string input_path;
bool mem2reg = false;
bool const_propagation = false;
bool activevars = false;
bool loop_inv_hoist = false;
bool loop_search = false;
bool emit = false;
for (int i = 1; i < argc; ++i) {
......@@ -39,14 +42,6 @@ int main(int argc, char **argv) {
emit = true;
} else if (argv[i] == "-mem2reg"s) {
mem2reg = true;
} else if (argv[i] == "-loop-search"s) {
loop_search = true;
} else if (argv[i] == "-loop-inv-hoist"s) {
loop_inv_hoist = true;
} else if (argv[i] == "-const-propagation"s) {
const_propagation = true;
} else if (argv[i] == "-active-vars"s) {
activevars = true;
} else {
if (input_path.empty()) {
input_path = argv[i];
......@@ -93,6 +88,14 @@ int main(int argc, char **argv) {
auto m = builder.getModule();
m->set_print_name();
PassManager PM(m.get());
if (mem2reg) {
PM.add_pass<Mem2Reg>(emit);
}
PM.run();
auto IR = m->print();
std::ofstream output_stream;
......
......@@ -22,6 +22,10 @@ void BasicBlock::delete_instr(Instruction *instr) {
instr_list_.remove(instr);
instr->remove_use_of_ops();
}
void BasicBlock::erase_instr(Instruction *instr) {
instr->remove_use_of_ops();
instr_list_.erase(instr);
}
const Instruction *BasicBlock::get_terminator() const {
if (instr_list_.empty()) {
......
......@@ -114,7 +114,8 @@ IntegerType *IntegerType::get(unsigned num_bits, Module *m) {
} else if (num_bits == 32) {
return m->get_int32_type();
} else {
assert("IntegerType::get has error num_bits");
assert(false and "IntegerType::get has error num_bits");
return nullptr;
}
}
......
......@@ -17,6 +17,7 @@ void Value::replace_all_use_with(Value *new_val) {
assert(val && "new_val is not a user");
val->set_operand(use.arg_no_, new_val);
}
use_list_.clear();
}
void Value::remove_use(Value *val) {
......
add_library(
OP_lib STATIC
Dominators.cpp
Mem2Reg.cpp
)
#include "Dominators.h"
#include <algorithm>
#include <string>
void Dominators::run() {
for (auto &f1 : m_->get_functions()) {
auto f = &f1;
if (f->get_basic_blocks().size() == 0)
continue;
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
doms_.insert({bb, {}});
idom_.insert({bb, {}});
dom_frontier_.insert({bb, {}});
dom_tree_succ_blocks_.insert({bb, {}});
}
create_reverse_post_order(f);
create_idom(f);
create_dominance_frontier(f);
create_dom_tree_succ(f);
// for debug
// print_idom(f);
// print_dominance_frontier(f);
}
}
void Dominators::create_doms(Function *f) {
// init
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
add_dom(bb, bb);
}
// iterate
bool changed = true;
std::vector<BasicBlock *> ret(f->get_num_basic_blocks());
std::vector<BasicBlock *> pre(f->get_num_basic_blocks());
while (changed) {
changed = false;
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
auto &bbs = bb->get_pre_basic_blocks();
auto &first = get_doms((*bbs.begin()));
pre.insert(pre.begin(), first.begin(), first.end());
pre.resize(first.size());
ret.resize(f->get_num_basic_blocks());
for (auto iter = ++bbs.begin(); iter != bbs.end(); ++iter) {
auto &now = get_doms((*iter));
auto it = std::set_intersection(pre.begin(), pre.end(), now.begin(), now.end(), ret.begin());
ret.resize(it - ret.begin());
pre.resize(ret.size());
pre.insert(pre.begin(), ret.begin(), ret.end());
}
std::set<BasicBlock *> doms;
doms.insert(bb);
doms.insert(pre.begin(), pre.end());
if (get_doms(bb) != doms) {
set_doms(bb, doms);
changed = true;
}
}
}
}
void Dominators::create_reverse_post_order(Function *f) {
reverse_post_order_.clear();
post_order_id_.clear();
std::set<BasicBlock *> visited;
post_order_visit(f->get_entry_block(), visited);
reverse_post_order_.reverse();
}
void Dominators::post_order_visit(BasicBlock *bb, std::set<BasicBlock *> &visited) {
visited.insert(bb);
for (auto b : bb->get_succ_basic_blocks()) {
if (visited.find(b) == visited.end())
post_order_visit(b, visited);
}
post_order_id_[bb] = reverse_post_order_.size();
reverse_post_order_.push_back(bb);
}
void Dominators::create_idom(Function *f) {
// init
for (auto &bb : f->get_basic_blocks())
set_idom(&bb, nullptr);
auto root = f->get_entry_block();
set_idom(root, root);
// iterate
bool changed = true;
while (changed) {
changed = false;
for (auto bb : this->reverse_post_order_) {
if (bb == root) {
continue;
}
// find one pred which has idom
BasicBlock *pred = nullptr;
for (auto p : bb->get_pre_basic_blocks()) {
if (get_idom(p)) {
pred = p;
break;
}
}
assert(pred);
BasicBlock *new_idom = pred;
for (auto p : bb->get_pre_basic_blocks()) {
if (p == pred)
continue;
if (get_idom(p)) {
new_idom = intersect(p, new_idom);
}
}
if (get_idom(bb) != new_idom) {
set_idom(bb, new_idom);
changed = true;
}
}
}
}
// find closest parent of b1 and b2
BasicBlock *Dominators::intersect(BasicBlock *b1, BasicBlock *b2) {
while (b1 != b2) {
while (post_order_id_[b1] < post_order_id_[b2]) {
assert(get_idom(b1));
b1 = get_idom(b1);
}
while (post_order_id_[b2] < post_order_id_[b1]) {
assert(get_idom(b2));
b2 = get_idom(b2);
}
}
return b1;
}
void Dominators::create_dominance_frontier(Function *f) {
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
if (bb->get_pre_basic_blocks().size() >= 2) {
for (auto p : bb->get_pre_basic_blocks()) {
auto runner = p;
while (runner != get_idom(bb)) {
add_dominance_frontier(runner, bb);
runner = get_idom(runner);
}
}
}
}
}
void Dominators::create_dom_tree_succ(Function *f) {
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
auto idom = get_idom(bb);
// e.g, entry bb
if (idom != bb) {
add_dom_tree_succ_block(idom, bb);
}
}
}
void Dominators::print_idom(Function *f) {
int counter = 0;
std::map<BasicBlock *, std::string> bb_id;
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
if (bb->get_name().empty())
bb_id[bb] = "bb" + std::to_string(counter);
else
bb_id[bb] = bb->get_name();
counter++;
}
printf("Immediate dominance of function %s:\n", f->get_name().c_str());
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
std::string output;
output = bb_id[bb] + ": ";
if (get_idom(bb)) {
output += bb_id[get_idom(bb)];
} else {
output += "null";
}
printf("%s\n", output.c_str());
}
}
void Dominators::print_dominance_frontier(Function *f) {
int counter = 0;
std::map<BasicBlock *, std::string> bb_id;
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
if (bb->get_name().empty())
bb_id[bb] = "bb" + std::to_string(counter);
else
bb_id[bb] = bb->get_name();
counter++;
}
printf("Dominance Frontier of function %s:\n", f->get_name().c_str());
for (auto &bb1 : f->get_basic_blocks()) {
auto bb = &bb1;
std::string output;
output = bb_id[bb] + ": ";
if (get_dominance_frontier(bb).empty()) {
output += "null";
} else {
bool first = true;
for (auto df : get_dominance_frontier(bb)) {
if (first) {
first = false;
} else {
output += ", ";
}
output += bb_id[df];
}
}
printf("%s\n", output.c_str());
}
}
#include "Mem2Reg.hpp"
#include "IRBuilder.h"
#include <memory>
// 判断是否是全局变量地址
#define IS_GLOBAL_VARIABLE(l_val) dynamic_cast<GlobalVariable *>(l_val)
// 判断是否是 getelementptr 指令
#define IS_GEP_INSTR(l_val) dynamic_cast<GetElementPtrInst *>(l_val)
std::map<Value *, std::vector<Value *>> var_val_stack; // 全局变量初值提前存入栈中
void Mem2Reg::run() {
// 创建支配树分析 Pass 的实例
dominators_ = std::make_unique<Dominators>(m_);
// 建立支配树
dominators_->run();
// 以函数为单元遍历实现 Mem2Reg 算法
for (auto &f : m_->get_functions()) {
func_ = &f;
if (func_->get_basic_blocks().size() >= 1) {
// 对应伪代码中 phi 指令插入的阶段
generate_phi();
// 对应伪代码中重命名阶段
re_name(func_->get_entry_block());
}
// 移除冗余的局部变量的分配空间
remove_alloca();
}
}
void Mem2Reg::generate_phi() {
// global_live_var_name 是全局名字集合,以 alloca 出的局部变量来统计。
// 步骤一:找到活跃在多个 block 的全局名字集合,以及它们所属的 bb 块
std::set<Value *> global_live_var_name;
std::map<Value *, std::set<BasicBlock *>> live_var_2blocks;
for (auto &bb1 : func_->get_basic_blocks()) {
auto bb = &bb1;
std::set<Value *> var_is_killed;
for (auto &instr1 : bb->get_instructions()) {
auto instr = &instr1;
if (instr->is_store()) {
// store i32 a, i32 *b
// a is r_val, b is l_val
auto r_val = static_cast<StoreInst *>(instr)->get_rval();
auto l_val = static_cast<StoreInst *>(instr)->get_lval();
if (!IS_GLOBAL_VARIABLE(l_val) && !IS_GEP_INSTR(l_val)) {
global_live_var_name.insert(l_val);
live_var_2blocks[l_val].insert(bb);
}
}
}
}
// 步骤二:从支配树获取支配边界信息,并在对应位置插入 phi 指令
std::map<std::pair<BasicBlock *, Value *>, bool> bb_has_var_phi; // bb has phi for var
for (auto var : global_live_var_name) {
std::vector<BasicBlock *> work_list;
work_list.assign(live_var_2blocks[var].begin(), live_var_2blocks[var].end());
for (int i = 0; i < work_list.size(); i++) {
auto bb = work_list[i];
for (auto bb_dominance_frontier_bb : dominators_->get_dominance_frontier(bb)) {
if (bb_has_var_phi.find({bb_dominance_frontier_bb, var}) == bb_has_var_phi.end()) {
// generate phi for bb_dominance_frontier_bb & add bb_dominance_frontier_bb to work list
auto phi =
PhiInst::create_phi(var->get_type()->get_pointer_element_type(), bb_dominance_frontier_bb);
phi->set_lval(var);
bb_dominance_frontier_bb->add_instr_begin(phi);
work_list.push_back(bb_dominance_frontier_bb);
bb_has_var_phi[{bb_dominance_frontier_bb, var}] = true;
}
}
}
}
}
void Mem2Reg::re_name(BasicBlock *bb) {
std::vector<Instruction *> wait_delete;
// 步骤三:将 phi 指令作为 lval 的最新定值,lval 即是为局部变量 alloca 出的地址空间
for (auto &instr1 : bb->get_instructions()) {
auto instr = &instr1;
if (instr->is_phi()) {
auto l_val = static_cast<PhiInst *>(instr)->get_lval();
var_val_stack[l_val].push_back(instr);
}
}
for (auto &instr1 : bb->get_instructions()) {
auto instr = &instr1;
// 步骤四:用 lval 最新的定值替代对应的load指令
if (instr->is_load()) {
auto l_val = static_cast<LoadInst *>(instr)->get_lval();
if (!IS_GLOBAL_VARIABLE(l_val) && !IS_GEP_INSTR(l_val)) {
if (var_val_stack.find(l_val) != var_val_stack.end()) {
// 此处指令替换会维护 UD 链与 DU 链
instr->replace_all_use_with(var_val_stack[l_val].back());
wait_delete.push_back(instr);
}
}
}
// 步骤五:将 store 指令的 rval,也即被存入内存的值,作为 lval 的最新定值
if (instr->is_store()) {
auto l_val = static_cast<StoreInst *>(instr)->get_lval();
auto r_val = static_cast<StoreInst *>(instr)->get_rval();
if (!IS_GLOBAL_VARIABLE(l_val) && !IS_GEP_INSTR(l_val)) {
var_val_stack[l_val].push_back(r_val);
wait_delete.push_back(instr);
}
}
}
// 步骤六:为 lval 对应的 phi 指令参数补充完整
for (auto succ_bb : bb->get_succ_basic_blocks()) {
for (auto &instr1 : succ_bb->get_instructions()) {
auto instr = &instr1;
if (instr->is_phi()) {
auto l_val = static_cast<PhiInst *>(instr)->get_lval();
if (var_val_stack.find(l_val) != var_val_stack.end()) {
assert(var_val_stack[l_val].size() != 0);
static_cast<PhiInst *>(instr)->add_phi_pair_operand(var_val_stack[l_val].back(), bb);
}
// 对于 phi 参数只有一个前驱定值的情况,将会输出 [ undef, bb ] 的参数格式
}
}
}
// 步骤七:对 bb 在支配树上的所有后继节点,递归执行 re_name 操作
for (auto dom_succ_bb : dominators_->get_dom_tree_succ_blocks(bb)) {
re_name(dom_succ_bb);
}
// 步骤八:pop出 lval 的最新定值
for (auto &instr1 : bb->get_instructions()) {
auto instr = &instr1;
if (instr->is_store()) {
auto l_val = static_cast<StoreInst *>(instr)->get_lval();
if (!IS_GLOBAL_VARIABLE(l_val) && !IS_GEP_INSTR(l_val)) {
var_val_stack[l_val].pop_back();
}
} else if (instr->is_phi()) {
auto l_val = static_cast<PhiInst *>(instr)->get_lval();
if (var_val_stack.find(l_val) != var_val_stack.end()) {
var_val_stack[l_val].pop_back();
}
}
}
// 清除冗余的指令
for (auto instr : wait_delete) {
bb->erase_instr(instr);
}
}
void Mem2Reg::remove_alloca() {
for (auto &bb1 : func_->get_basic_blocks()) {
auto bb = &bb1;
std::vector<Instruction *> wait_delete;
for (auto &instr1 : bb->get_instructions()) {
auto instr = &instr1;
auto is_alloca = dynamic_cast<AllocaInst *>(instr);
if (is_alloca) {
bool is_int = is_alloca->get_type()->get_pointer_element_type()->is_integer_type();
bool is_float = is_alloca->get_type()->get_pointer_element_type()->is_float_type();
if (is_int || is_float) {
wait_delete.push_back(instr);
}
}
}
for (auto instr : wait_delete) {
bb->erase_instr(instr);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment