Commit f40efe88 authored by Yang's avatar Yang

publish lab4

parent 93702b62
...@@ -63,4 +63,4 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) ...@@ -63,4 +63,4 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
include_directories(${PROJECT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_BINARY_DIR}) include_directories(${PROJECT_BINARY_DIR})
add_subdirectory(src) add_subdirectory(src)
# add_subdirectory(tests) add_subdirectory(tests)
...@@ -67,15 +67,10 @@ class CminusfBuilder : public ASTVisitor { ...@@ -67,15 +67,10 @@ class CminusfBuilder : public ASTVisitor {
auto *output_float_fun = auto *output_float_fun =
Function::create(output_float_type, "outputFloat", module); Function::create(output_float_type, "outputFloat", module);
auto *neg_idx_except_type = FunctionType::get(TyVoid, {});
auto *neg_idx_except_fun = Function::create(
neg_idx_except_type, "neg_idx_except", module);
scope.enter(); scope.enter();
scope.push("input", input_fun); scope.push("input", input_fun);
scope.push("output", output_fun); scope.push("output", output_fun);
scope.push("outputFloat", output_float_fun); scope.push("outputFloat", output_float_fun);
scope.push("neg_idx_except", neg_idx_except_fun);
} }
Module* getModule() const { return module; } Module* getModule() const { return module; }
......
...@@ -64,18 +64,6 @@ class CodeGen { ...@@ -64,18 +64,6 @@ class CodeGen {
void gen_fptosi(); void gen_fptosi();
void gen_epilogue(); void gen_epilogue();
static std::string label_name(BasicBlock *bb) {
return "." + bb->get_parent()->get_name() + "_" + bb->get_name();
}
static std::string func_exit_label_name(Function *func) {
return func->get_name() + "_exit";
}
static std::string fcmp_label_name(BasicBlock *bb, unsigned cnt) {
return label_name(bb) + "_fcmp_" + std::to_string(cnt);
}
struct { struct {
/* 随着ir遍历设置 */ /* 随着ir遍历设置 */
Function *func{nullptr}; // 当前函数 Function *func{nullptr}; // 当前函数
...@@ -84,14 +72,12 @@ class CodeGen { ...@@ -84,14 +72,12 @@ class CodeGen {
/* 在allocate()中设置 */ /* 在allocate()中设置 */
unsigned frame_size{0}; // 当前函数的栈帧大小 unsigned frame_size{0}; // 当前函数的栈帧大小
std::unordered_map<Value *, int> offset_map{}; // 指针相对 fp 的偏移 std::unordered_map<Value *, int> offset_map{}; // 指针相对 fp 的偏移
unsigned fcmp_cnt{0}; // fcmp 的计数器, 用于创建 fcmp 需要的 label
void clear() { void clear() {
func = nullptr; func = nullptr;
bb = nullptr; bb = nullptr;
inst = nullptr; inst = nullptr;
frame_size = 0; frame_size = 0;
fcmp_cnt = 0;
offset_map.clear(); offset_map.clear();
} }
......
...@@ -20,8 +20,7 @@ class BasicBlock : public Value { ...@@ -20,8 +20,7 @@ class BasicBlock : public Value {
~BasicBlock() override; ~BasicBlock() override;
static BasicBlock *create(Module *m, const std::string &name, static BasicBlock *create(Module *m, const std::string &name,
Function *parent) { Function *parent) {
auto prefix = name.empty() ? "" : "label_"; return new BasicBlock(m, name, parent);
return new BasicBlock(m, prefix + name, parent);
} }
/****************api about cfg****************/ /****************api about cfg****************/
......
...@@ -214,6 +214,8 @@ public: ...@@ -214,6 +214,8 @@ public:
Value *get_condition() const { return get_operand(0); } Value *get_condition() const { return get_operand(0); }
void replace_all_bb_match(BasicBlock* need_replace, BasicBlock* replace_to);
std::string print() override; std::string print() override;
}; };
...@@ -251,8 +253,8 @@ class StoreInst : public Instruction { ...@@ -251,8 +253,8 @@ class StoreInst : public Instruction {
public: public:
static StoreInst *create_store(Value *val, Value *ptr, BasicBlock *bb); static StoreInst *create_store(Value *val, Value *ptr, BasicBlock *bb);
Value *get_rval() const { return this->get_operand(0); } Value *get_val() const { return this->get_operand(0); }
Value *get_lval() const { return this->get_operand(1); } Value *get_ptr() const { return this->get_operand(1); }
std::string print() override; std::string print() override;
}; };
...@@ -264,7 +266,7 @@ class LoadInst : public Instruction { ...@@ -264,7 +266,7 @@ class LoadInst : public Instruction {
public: public:
static LoadInst *create_load(Value *ptr, BasicBlock *bb, const std::string& name = ""); static LoadInst *create_load(Value *ptr, BasicBlock *bb, const std::string& name = "");
Value *get_lval() const { return this->get_operand(0); } Value *get_ptr() const { return this->get_operand(0); }
Type *get_load_type() const { return get_type(); } Type *get_load_type() const { return get_type(); }
std::string print() override; std::string print() override;
......
...@@ -20,11 +20,11 @@ class Dominators : public FunctionAnalysisPass { ...@@ -20,11 +20,11 @@ class Dominators : public FunctionAnalysisPass {
void run() override; void run() override;
// 获取基本块的直接支配节点 // 获取基本块的直接支配节点
BasicBlock *get_idom(const BasicBlock *bb) const { return idom_.at(bb); } BasicBlock *get_idom(BasicBlock *bb) const { return idom_.at(bb); }
const std::set<BasicBlock*> &get_dominance_frontier(const BasicBlock *bb) { const std::set<BasicBlock*> &get_dominance_frontier(BasicBlock *bb) {
return dom_frontier_.at(bb); return dom_frontier_.at(bb);
} }
const std::set<BasicBlock*> &get_dom_tree_succ_blocks(const BasicBlock *bb) { const std::set<BasicBlock*> &get_dom_tree_succ_blocks(BasicBlock *bb) {
return dom_tree_succ_blocks_.at(bb); return dom_tree_succ_blocks_.at(bb);
} }
...@@ -33,7 +33,7 @@ class Dominators : public FunctionAnalysisPass { ...@@ -33,7 +33,7 @@ class Dominators : public FunctionAnalysisPass {
void dump_dominator_tree(); void dump_dominator_tree();
// functions for dominance tree // functions for dominance tree
bool is_dominate(const BasicBlock *bb1, const BasicBlock *bb2) const { bool is_dominate(BasicBlock *bb1, BasicBlock *bb2) const {
return dom_tree_L_.at(bb1) <= dom_tree_L_.at(bb2) && return dom_tree_L_.at(bb1) <= dom_tree_L_.at(bb2) &&
dom_tree_R_.at(bb1) >= dom_tree_L_.at(bb2); dom_tree_R_.at(bb1) >= dom_tree_L_.at(bb2);
} }
...@@ -54,33 +54,33 @@ class Dominators : public FunctionAnalysisPass { ...@@ -54,33 +54,33 @@ class Dominators : public FunctionAnalysisPass {
void create_dom_tree_succ(); void create_dom_tree_succ();
void create_dom_dfs_order(); void create_dom_dfs_order();
BasicBlock * intersect(BasicBlock *b1, const BasicBlock *b2) const; BasicBlock * intersect(BasicBlock *b1, BasicBlock *b2) const;
void create_reverse_post_order(); void create_reverse_post_order();
void set_idom(const BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; } void set_idom(BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; }
void set_dominance_frontier(const BasicBlock *bb, std::set<BasicBlock*>&df) { void set_dominance_frontier(BasicBlock *bb, std::set<BasicBlock*>&df) {
dom_frontier_[bb].clear(); dom_frontier_[bb].clear();
dom_frontier_[bb].insert(df.begin(), df.end()); dom_frontier_[bb].insert(df.begin(), df.end());
} }
void add_dom_tree_succ_block(const BasicBlock *bb, BasicBlock *dom_tree_succ_bb) { void add_dom_tree_succ_block(BasicBlock *bb, BasicBlock *dom_tree_succ_bb) {
dom_tree_succ_blocks_[bb].insert(dom_tree_succ_bb); dom_tree_succ_blocks_[bb].insert(dom_tree_succ_bb);
} }
unsigned int get_post_order(const BasicBlock *bb) const { unsigned int get_reversed_post_order(BasicBlock *bb) const {
return post_order_.at(bb); return reversed_post_order_.at(bb);
} }
// for debug // for debug
void print_idom() const; void print_idom() const;
void print_dominance_frontier(); void print_dominance_frontier();
std::vector<BasicBlock *> post_order_vec_{}; // 逆后序 std::vector<BasicBlock *> reversed_post_order_vec_{}; // 逆后序
std::map<const BasicBlock *, unsigned int> post_order_{}; // 逆后序 std::map<BasicBlock *, unsigned int> reversed_post_order_{}; // 逆后序索引
std::map<const BasicBlock *, BasicBlock *> idom_{}; // 直接支配 std::map<BasicBlock *, BasicBlock *> idom_{}; // 直接支配
std::map<const BasicBlock *, std::set<BasicBlock*>> dom_frontier_{}; // 支配边界集合 std::map<BasicBlock *, std::set<BasicBlock*>> dom_frontier_{}; // 支配边界集合
std::map<const BasicBlock *, std::set<BasicBlock*>> dom_tree_succ_blocks_{}; // 支配树中的后继节点 std::map<BasicBlock *, std::set<BasicBlock*>> dom_tree_succ_blocks_{}; // 支配树中的后继节点
// 支配树上的dfs序L,R // 支配树上的dfs序L,R
std::map<const BasicBlock *, unsigned int> dom_tree_L_; std::map<BasicBlock *, unsigned int> dom_tree_L_;
std::map<const BasicBlock *, unsigned int> dom_tree_R_; std::map<BasicBlock *, unsigned int> dom_tree_R_;
std::vector<BasicBlock *> dom_dfs_order_; std::vector<BasicBlock *> dom_dfs_order_;
std::vector<BasicBlock *> dom_post_order_; std::vector<BasicBlock *> dom_post_order_;
......
...@@ -27,13 +27,17 @@ class FuncInfo : public ModuleAnalysisPass { ...@@ -27,13 +27,17 @@ class FuncInfo : public ModuleAnalysisPass {
void run() override; void run() override;
// 函数是否是纯函数 // 函数是否是纯函数
bool is_pure(Function *func) { return !func->is_declaration() && !use_libs.count(func) && loads[func].empty() && stores[func].empty(); } bool is_pure(Function *func) { return !func->is_declaration() && !use_libs[func] && loads[func].empty() && stores[func].empty(); }
// 函数是否使用了 io
bool use_io(Function* func) { return func->is_declaration() || use_libs[func]; }
// 返回 StoreInst 存入的变量(全局/局部变量或函数参数) // 返回 StoreInst 存入的变量(全局/局部变量或函数参数)
static Value* store_ptr(const StoreInst* st); static Value* store_ptr(const StoreInst* st);
// 返回 LoadInst 加载的变量(全局/局部变量或函数参数) // 返回 LoadInst 加载的变量(全局/局部变量或函数参数)
static Value* load_ptr(const LoadInst* ld); static Value* load_ptr(const LoadInst* ld);
// 返回 CallInst 代表的函数调用间接存入的变量(全局/局部变量或函数参数) // 返回 CallInst 代表的函数调用间接存入的变量(全局/局部变量或函数参数)
std::unordered_set<Value*> get_stores(const CallInst* call); std::unordered_set<Value*> get_stores(const CallInst* call);
// 返回 CallInst 代表的函数调用间接加载的变量(全局/局部变量或函数参数)
std::unordered_set<Value*> get_loads(const CallInst* call);
private: private:
// 函数存储的值 // 函数存储的值
std::unordered_map<Function*, UseMessage> stores; std::unordered_map<Function*, UseMessage> stores;
......
...@@ -18,8 +18,4 @@ class LoopInvariantCodeMotion : public TransformPass { ...@@ -18,8 +18,4 @@ class LoopInvariantCodeMotion : public TransformPass {
std::vector<Instruction*> collect_insts(Loop* loop); std::vector<Instruction*> collect_insts(Loop* loop);
void traverse_loop(Loop* loop); void traverse_loop(Loop* loop);
void run_on_loop(Loop* loop); void run_on_loop(Loop* loop);
void collect_loop_info(Loop* loop,
std::set<Value *> &loop_instructions,
std::set<Value *> &updated_global,
bool &contains_impure_call);
}; };
\ No newline at end of file
...@@ -40,6 +40,7 @@ class Loop { ...@@ -40,6 +40,7 @@ class Loop {
const std::vector<Loop*>& get_sub_loops() { return sub_loops_; } const std::vector<Loop*>& get_sub_loops() { return sub_loops_; }
const std::unordered_set<BasicBlock *>& get_latches() { return latches_; } const std::unordered_set<BasicBlock *>& get_latches() { return latches_; }
void add_latch(BasicBlock *bb) { latches_.insert(bb); } void add_latch(BasicBlock *bb) { latches_.insert(bb); }
std::string safe_print() const;
}; };
class LoopDetection : public FunctionAnalysisPass { class LoopDetection : public FunctionAnalysisPass {
......
...@@ -25,7 +25,8 @@ def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict): ...@@ -25,7 +25,8 @@ def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
, "BasicBlock" , "BasicBlock"
, "GlobalVariable" , "GlobalVariable"
, "Instruction", "IBinaryInst", "FBinaryInst", "ICmpInst", "FCmpInst", "CallInst", "BranchInst", "ReturnInst", "GetElementPtrInst", "StoreInst", "LoadInst", "AllocaInst", "ZextInst", "FpToSiInst", "SiToFpInst", "PhiInst" , "Instruction", "IBinaryInst", "FBinaryInst", "ICmpInst", "FCmpInst", "CallInst", "BranchInst", "ReturnInst", "GetElementPtrInst", "StoreInst", "LoadInst", "AllocaInst", "ZextInst", "FpToSiInst", "SiToFpInst", "PhiInst"
, "ASMInstruction", "Reg", "FReg", "CFReg" ] , "ASMInstruction", "Reg", "FReg", "CFReg"
, "Loop" ]
for i in types: for i in types:
debugger.HandleCommand( debugger.HandleCommand(
f"type summary add -F lldb_formatters.SafePrintSummary {i} -w my" f"type summary add -F lldb_formatters.SafePrintSummary {i} -w my"
......
...@@ -329,27 +329,10 @@ Value* CminusfBuilder::visit(ASTVar &node) { ...@@ -329,27 +329,10 @@ Value* CminusfBuilder::visit(ASTVar &node) {
} }
} else { } else {
auto *val = node.expression->accept(*this); auto *val = node.expression->accept(*this);
auto *exceptBB = BasicBlock::create(module, "", context.func);
auto *contBB = BasicBlock::create(module, "", context.func);
if (val->get_type()->is_float_type()) { if (val->get_type()->is_float_type()) {
val = builder->create_fptosi(val, INT32_T); val = builder->create_fptosi(val, INT32_T);
} }
Value* is_neg = builder->create_icmp_lt(val, CONST_INT(0));
builder->create_cond_br(is_neg, exceptBB, contBB);
builder->set_insert_point(exceptBB);
auto *neg_idx_except_fun = scope.find("neg_idx_except");
builder->create_call(dynamic_cast<Function *>(neg_idx_except_fun), {});
if (context.func->get_return_type()->is_void_type()) {
builder->create_void_ret();
} else if (context.func->get_return_type()->is_float_type()) {
builder->create_ret(CONST_FP(0.));
} else {
builder->create_ret(CONST_INT(0));
}
builder->set_insert_point(contBB);
Value *tmp_ptr; Value *tmp_ptr;
if (is_int || is_float) { if (is_int || is_float) {
tmp_ptr = builder->create_gep(var, {val}); tmp_ptr = builder->create_gep(var, {val});
......
...@@ -23,30 +23,30 @@ struct Config { ...@@ -23,30 +23,30 @@ struct Config {
std::filesystem::path input_file; std::filesystem::path input_file;
std::filesystem::path output_file; std::filesystem::path output_file;
bool emitast{false}; bool emitast{ false };
bool emitasm{false}; bool emitasm{ false };
bool emitllvm{false}; bool emitllvm{ false };
// optization conifg // optization conifg
bool mem2reg{false}; bool mem2reg{ false };
bool licm{false}; bool licm{ false };
Config(int argc, char **argv) : argc(argc), argv(argv) { Config(int argc, char** argv) : argc(argc), argv(argv) {
parse_cmd_line(); parse_cmd_line();
check(); check();
} }
private: private:
int argc{-1}; int argc{ -1 };
char **argv{nullptr}; char** argv{ nullptr };
void parse_cmd_line(); void parse_cmd_line();
void check(); void check();
// print helper infomation and exit // print helper infomation and exit
void print_help() const; void print_help() const;
void print_err(const string &msg) const; void print_err(const string& msg) const;
}; };
int main(int argc, char **argv) { int main(int argc, char** argv) {
Config config(argc, argv); Config config(argc, argv);
auto syntax_tree = parse(config.input_file.c_str()); auto syntax_tree = parse(config.input_file.c_str());
...@@ -55,7 +55,8 @@ int main(int argc, char **argv) { ...@@ -55,7 +55,8 @@ int main(int argc, char **argv) {
if (config.emitast) { // if emit ast (lab1), print ast and return if (config.emitast) { // if emit ast (lab1), print ast and return
ASTPrinter printer; ASTPrinter printer;
ast.run_visitor(printer); ast.run_visitor(printer);
} else { }
else {
Module* m; Module* m;
CminusfBuilder builder; CminusfBuilder builder;
ast.run_visitor(builder); ast.run_visitor(builder);
...@@ -63,11 +64,12 @@ int main(int argc, char **argv) { ...@@ -63,11 +64,12 @@ int main(int argc, char **argv) {
PassManager PM(m); PassManager PM(m);
// optimization // optimization
if(config.mem2reg) { if (config.mem2reg) {
PM.add_pass<DeadCode>(true);
PM.add_pass<Mem2Reg>(); PM.add_pass<Mem2Reg>();
PM.add_pass<DeadCode>(false); PM.add_pass<DeadCode>(false);
} }
if(config.licm) { if (config.licm) {
PM.add_pass<LoopInvariantCodeMotion>(); PM.add_pass<LoopInvariantCodeMotion>();
PM.add_pass<DeadCode>(false); PM.add_pass<DeadCode>(false);
} }
...@@ -79,7 +81,14 @@ int main(int argc, char **argv) { ...@@ -79,7 +81,14 @@ int main(int argc, char **argv) {
output_stream << "; ModuleID = 'cminus'\n"; output_stream << "; ModuleID = 'cminus'\n";
output_stream << "source_filename = " << abs_path << "\n\n"; output_stream << "source_filename = " << abs_path << "\n\n";
output_stream << m->print(); output_stream << m->print();
} else if (config.emitasm) { }
else if (config.emitasm) {
auto abs_path = std::filesystem::canonical(config.input_file);
config.output_file.replace_extension("ll");
std::ofstream output_stream2(config.output_file);
output_stream2 << "; ModuleID = 'cminus'\n";
output_stream2 << "source_filename = " << abs_path << "\n\n";
output_stream2 << m->print();
CodeGen codegen(m); CodeGen codegen(m);
codegen.run(); codegen.run();
output_stream << codegen.print(); output_stream << codegen.print();
...@@ -96,27 +105,36 @@ void Config::parse_cmd_line() { ...@@ -96,27 +105,36 @@ void Config::parse_cmd_line() {
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (argv[i] == "-h"s || argv[i] == "--help"s) { if (argv[i] == "-h"s || argv[i] == "--help"s) {
print_help(); print_help();
} else if (argv[i] == "-o"s) { }
else if (argv[i] == "-o"s) {
if (output_file.empty() && i + 1 < argc) { if (output_file.empty() && i + 1 < argc) {
output_file = argv[i + 1]; output_file = argv[i + 1];
i += 1; i += 1;
} else { }
else {
print_err("bad output file"); print_err("bad output file");
} }
} else if (argv[i] == "-emit-ast"s) { }
else if (argv[i] == "-emit-ast"s) {
emitast = true; emitast = true;
} else if (argv[i] == "-S"s) { }
else if (argv[i] == "-S"s) {
emitasm = true; emitasm = true;
} else if (argv[i] == "-emit-llvm"s) { }
else if (argv[i] == "-emit-llvm"s) {
emitllvm = true; emitllvm = true;
} else if (argv[i] == "-mem2reg"s) { }
else if (argv[i] == "-mem2reg"s) {
mem2reg = true; mem2reg = true;
} else if (argv[i] == "-licm"s) { }
else if (argv[i] == "-licm"s) {
licm = true; licm = true;
}else { }
else {
if (input_file.empty()) { if (input_file.empty()) {
input_file = argv[i]; input_file = argv[i];
} else { }
else {
string err = string err =
"unrecognized command-line option \'"s + argv[i] + "\'"s; "unrecognized command-line option \'"s + argv[i] + "\'"s;
print_err(err); print_err(err);
...@@ -143,11 +161,12 @@ void Config::check() { ...@@ -143,11 +161,12 @@ void Config::check() {
} }
if (output_file.empty()) { if (output_file.empty()) {
output_file = input_file.stem(); output_file = input_file.stem();
}
if (emitllvm) { if (emitllvm) {
output_file.replace_extension(".ll"); output_file.replace_extension(".ll");
} else if (emitasm) {
output_file.replace_extension(".s");
} }
else if (emitasm) {
output_file.replace_extension(".s");
} }
} }
...@@ -160,7 +179,7 @@ void Config::print_help() const { ...@@ -160,7 +179,7 @@ void Config::print_help() const {
exit(0); exit(0);
} }
void Config::print_err(const string &msg) const { void Config::print_err(const string& msg) const {
std::cout << exe_name << ": " << msg << std::endl; std::cout << exe_name << ": " << msg << std::endl;
exit(-1); exit(-1);
} }
This diff is collapsed.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int input() { #include <sys/time.h>
struct timeval time_start, time_end;
int end_set;
int flags[2];
int input(void)
{
int a; int a;
scanf("%d", &a); scanf("%d", &a);
gettimeofday(&time_start, NULL);
end_set = 0;
return a; return a;
} }
void output(int a) { printf("%d\n", a); } void output(int a)
{
if (end_set == 0)
{
gettimeofday(&time_end, NULL);
end_set = 1;
}
printf("%d\n", a);
}
void outputFloat(float a)
{
if (end_set == 0)
{
gettimeofday(&time_end, NULL);
end_set = 1;
}
printf("%f\n", a);
}
void add_lab4_flag(int idx, int val)
{
flags[idx] += val;
}
void outputFloat(float a) { printf("%f\n", a); } __attribute((constructor)) void before_main(void)
{
flags[0] = 0;
flags[1] = 0;
end_set = 0;
gettimeofday(&time_start, NULL);
}
void neg_idx_except() { __attribute((destructor)) void after_main(void)
printf("negative index exception\n"); {
exit(0); long time_us = 0;
fprintf(stderr, "Allocate Size (bytes):\n%d\n", flags[0]);
fprintf(stderr, "Execute Cost:\n%d\n", flags[1]);
if (end_set == 0)
{
gettimeofday(&time_end, NULL);
}
time_us += 1000000L * (time_end.tv_sec - time_start.tv_sec) +
time_end.tv_usec - time_start.tv_usec;
fprintf(stderr, "Take Times (us):\n%ld\n", time_us);
} }
int input(); int input(void);
void output(int a); void output(int a);
void outputFloat(float a); void outputFloat(float a);
void neg_idx_except(); void add_lab4_flag(int idx, int val);
\ No newline at end of file
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
BasicBlock::BasicBlock(const Module* m, const std::string& name = "", BasicBlock::BasicBlock(const Module* m, const std::string& name = "",
Function* parent = nullptr) Function* parent = nullptr)
: Value(m->get_label_type(), : Value(m->get_label_type(),
parent == nullptr ? GLOBAL_BASICBLOCK_NAMES_.get_name(name) : parent->names4blocks_.get_name(name)) parent == nullptr ? GLOBAL_BASICBLOCK_NAMES_.get_name(name) : parent->names4blocks_.get_name(name))
, parent_(parent) { , parent_(parent) {
assert(parent && "currently parent should not be nullptr"); assert(parent && "currently parent should not be nullptr");
parent_->add_basic_block(this); parent_->add_basic_block(this);
} }
Module *BasicBlock::get_module() const { return get_parent()->get_parent(); } Module* BasicBlock::get_module() const { return get_parent()->get_parent(); }
void BasicBlock::erase_from_parent() { this->get_parent()->remove(this); } void BasicBlock::erase_from_parent() { this->get_parent()->remove(this); }
bool BasicBlock::is_terminated() const { bool BasicBlock::is_terminated() const {
...@@ -34,18 +34,18 @@ bool BasicBlock::is_terminated() const { ...@@ -34,18 +34,18 @@ bool BasicBlock::is_terminated() const {
} }
} }
Instruction *BasicBlock::get_terminator() const Instruction* BasicBlock::get_terminator() const
{ {
assert(is_terminated() && assert(is_terminated() &&
"Trying to get terminator from an bb which is not terminated"); "Trying to get terminator from an bb which is not terminated");
return instr_list_.back(); return instr_list_.back();
} }
void BasicBlock::add_instruction(Instruction *instr) { void BasicBlock::add_instruction(Instruction* instr) {
if (instr->is_alloca() || instr->is_phi()) if (instr->is_alloca() || instr->is_phi())
{ {
auto it = instr_list_.begin(); auto it = instr_list_.begin();
for (; it != instr_list_.end() && ((*it)->is_alloca() || (*it)->is_phi()); ++it){} for (; it != instr_list_.end() && ((*it)->is_alloca() || (*it)->is_phi()); ++it) {}
instr_list_.emplace(it, instr); instr_list_.emplace(it, instr);
return; return;
} }
...@@ -146,4 +146,4 @@ BasicBlock* BasicBlock::get_entry_block_of_same_function() const ...@@ -146,4 +146,4 @@ BasicBlock* BasicBlock::get_entry_block_of_same_function() const
return parent_->get_entry_block(); return parent_->get_entry_block();
} }
Names GLOBAL_BASICBLOCK_NAMES_{"label", "_"}; Names GLOBAL_BASICBLOCK_NAMES_{ "label", "_" };
\ No newline at end of file \ No newline at end of file
...@@ -7,17 +7,8 @@ ...@@ -7,17 +7,8 @@
#include <unordered_set> #include <unordered_set>
#include <queue> #include <queue>
namespace
{
std::string chopName(std::string name)
{
if (name.size() > 3) return { name.begin(), name.begin() + 3 };
return name;
}
}
Function::Function(FunctionType* ty, const std::string& name, Module* parent) Function::Function(FunctionType* ty, const std::string& name, Module* parent)
: Value(ty, name), names4blocks_("label", chopName(name) + "_"), names4insts_("op", ""), parent_(parent), seq_cnt_(0) { : Value(ty, name), names4blocks_("", name + "_"), names4insts_("op", ""), parent_(parent), seq_cnt_(0) {
// num_args_ = ty->getNumParams(); // num_args_ = ty->getNumParams();
parent->add_function(this); parent->add_function(this);
// build args // build args
......
...@@ -382,7 +382,7 @@ std::string Instruction::safe_print() const ...@@ -382,7 +382,7 @@ std::string Instruction::safe_print() const
} }
else else
{ {
if (auto fty = dynamic_cast<FunctionType*>(ty)) if (auto fty = dynamic_cast<FunctionType*>(op0->get_type()))
{ {
auto ty3 = fty->get_return_type(); auto ty3 = fty->get_return_type();
if (ty3 == nullptr) if (ty3 == nullptr)
......
...@@ -197,6 +197,23 @@ BranchInst *BranchInst::create_br(BasicBlock *if_true, BasicBlock *bb) { ...@@ -197,6 +197,23 @@ BranchInst *BranchInst::create_br(BasicBlock *if_true, BasicBlock *bb) {
return new BranchInst(nullptr, if_true, nullptr, bb); return new BranchInst(nullptr, if_true, nullptr, bb);
} }
void BranchInst::replace_all_bb_match(BasicBlock* need_replace, BasicBlock* replace_to)
{
if (need_replace == nullptr || replace_to == nullptr || need_replace == replace_to) return;
int size = static_cast<int>(get_operands().size());
for (int i = 0; i < size; i ++)
{
auto op = get_operand(i);
if (op == need_replace) set_operand(i, replace_to);
}
auto parent = get_parent();
if (parent == nullptr) return;
parent->remove_succ_basic_block(need_replace);
need_replace->remove_pre_basic_block(parent);
parent->add_succ_basic_block(replace_to);
replace_to->add_pre_basic_block(parent);
}
ReturnInst::ReturnInst(Value *val, BasicBlock *bb) ReturnInst::ReturnInst(Value *val, BasicBlock *bb)
: Instruction(bb->get_module()->get_void_type(), ret, "", bb) { : Instruction(bb->get_module()->get_void_type(), ret, "", bb) {
if (val == nullptr) { if (val == nullptr) {
...@@ -352,14 +369,13 @@ SiToFpInst *SiToFpInst::create_sitofp(Value *val, BasicBlock *bb, const std::str ...@@ -352,14 +369,13 @@ SiToFpInst *SiToFpInst::create_sitofp(Value *val, BasicBlock *bb, const std::str
PhiInst::PhiInst(Type *ty, const std::vector<Value *>& vals, PhiInst::PhiInst(Type *ty, const std::vector<Value *>& vals,
const std::vector<BasicBlock *>& val_bbs, BasicBlock *bb, const std::string& name) const std::vector<BasicBlock *>& val_bbs, BasicBlock *bb, const std::string& name)
: Instruction(ty, phi, name) { : Instruction(ty, phi, name, bb) {
assert(vals.size() == val_bbs.size() && "Unmatched vals and bbs"); assert(vals.size() == val_bbs.size() && "Unmatched vals and bbs");
for (unsigned i = 0; i < vals.size(); i++) { for (unsigned i = 0; i < vals.size(); i++) {
assert(ty == vals[i]->get_type() && "Bad type for phi"); assert(ty == vals[i]->get_type() && "Bad type for phi");
add_operand(vals[i]); add_operand(vals[i]);
add_operand(val_bbs[i]); add_operand(val_bbs[i]);
} }
this->set_parent(bb);
} }
PhiInst *PhiInst::create_phi(Type *ty, BasicBlock *bb, PhiInst *PhiInst::create_phi(Type *ty, BasicBlock *bb,
......
...@@ -27,48 +27,48 @@ Module::~Module() ...@@ -27,48 +27,48 @@ Module::~Module()
for (auto i : global_list_) delete i; for (auto i : global_list_) delete i;
} }
Type *Module::get_void_type() const { return void_ty_; } Type* Module::get_void_type() const { return void_ty_; }
Type *Module::get_label_type() const { return label_ty_; } Type* Module::get_label_type() const { return label_ty_; }
IntegerType *Module::get_int1_type() const { return int1_ty_; } IntegerType* Module::get_int1_type() const { return int1_ty_; }
IntegerType *Module::get_int32_type() const { return int32_ty_; } IntegerType* Module::get_int32_type() const { return int32_ty_; }
FloatType *Module::get_float_type() const { return float32_ty_; } FloatType* Module::get_float_type() const { return float32_ty_; }
PointerType *Module::get_int32_ptr_type() { PointerType* Module::get_int32_ptr_type() {
return get_pointer_type(int32_ty_); return get_pointer_type(int32_ty_);
} }
PointerType *Module::get_float_ptr_type() { PointerType* Module::get_float_ptr_type() {
return get_pointer_type(float32_ty_); return get_pointer_type(float32_ty_);
} }
PointerType *Module::get_pointer_type(Type *contained) { PointerType* Module::get_pointer_type(Type* contained) {
if (pointer_map_.find(contained) == pointer_map_.end()) { if (pointer_map_.find(contained) == pointer_map_.end()) {
pointer_map_[contained] = new PointerType(contained); pointer_map_[contained] = new PointerType(contained);
} }
return pointer_map_[contained]; return pointer_map_[contained];
} }
ArrayType *Module::get_array_type(Type *contained, unsigned num_elements) { ArrayType* Module::get_array_type(Type* contained, unsigned num_elements) {
if (array_map_.find({contained, num_elements}) == array_map_.end()) { if (array_map_.find({ contained, num_elements }) == array_map_.end()) {
array_map_[{contained, num_elements}] = array_map_[{contained, num_elements}] =
new ArrayType(contained, num_elements); new ArrayType(contained, num_elements);
} }
return array_map_[{contained, num_elements}]; return array_map_[{contained, num_elements}];
} }
FunctionType *Module::get_function_type(Type *retty, FunctionType* Module::get_function_type(Type* retty,
std::vector<Type *> &args) { std::vector<Type*>& args) {
if (not function_map_.count({retty, args})) { if (not function_map_.count({ retty, args })) {
function_map_[{retty, args}] = function_map_[{retty, args}] =
new FunctionType(retty, args); new FunctionType(retty, args);
} }
return function_map_[{retty, args}]; return function_map_[{retty, args}];
} }
void Module::add_function(Function *f) { function_list_.push_back(f); } void Module::add_function(Function* f) { function_list_.push_back(f); }
std::list<Function*> &Module::get_functions() { return function_list_; } std::list<Function*>& Module::get_functions() { return function_list_; }
void Module::add_global_variable(GlobalVariable *g) { void Module::add_global_variable(GlobalVariable* g) {
global_list_.push_back(g); global_list_.push_back(g);
} }
std::list<GlobalVariable*> &Module::get_global_variable() { std::list<GlobalVariable*>& Module::get_global_variable() {
return global_list_; return global_list_;
} }
......
...@@ -15,6 +15,7 @@ void DeadCode::run() { ...@@ -15,6 +15,7 @@ void DeadCode::run() {
do { do {
changed = false; changed = false;
for (auto func : m_->get_functions()) { for (auto func : m_->get_functions()) {
if (func->is_declaration()) continue;
if (remove_bb_) changed |= clear_basic_blocks(func); if (remove_bb_) changed |= clear_basic_blocks(func);
mark(func); mark(func);
changed |= sweep(func); changed |= sweep(func);
......
...@@ -62,13 +62,13 @@ void Dominators::run() { ...@@ -62,13 +62,13 @@ void Dominators::run() {
* 该函数使用后序号来查找两个节点的最近公共支配者。 * 该函数使用后序号来查找两个节点的最近公共支配者。
* 通过在支配树上向上遍历直到找到交点。 * 通过在支配树上向上遍历直到找到交点。
*/ */
BasicBlock *Dominators::intersect(BasicBlock *b1, const BasicBlock *b2) const BasicBlock *Dominators::intersect(BasicBlock *b1, BasicBlock *b2) const
{ {
while (b1 != b2) { while (b1 != b2) {
while (get_post_order(b1) < get_post_order(b2)) { while (get_reversed_post_order(b1) > get_reversed_post_order(b2)) {
b1 = get_idom(b1); b1 = get_idom(b1);
} }
while (get_post_order(b2) < get_post_order(b1)) { while (get_reversed_post_order(b2) > get_reversed_post_order(b1)) {
b2 = get_idom(b2); b2 = get_idom(b2);
} }
} }
...@@ -84,6 +84,12 @@ BasicBlock *Dominators::intersect(BasicBlock *b1, const BasicBlock *b2) const ...@@ -84,6 +84,12 @@ BasicBlock *Dominators::intersect(BasicBlock *b1, const BasicBlock *b2) const
void Dominators::create_reverse_post_order() { void Dominators::create_reverse_post_order() {
std::set<BasicBlock*> visited; std::set<BasicBlock*> visited;
dfs(f_->get_entry_block(), visited); dfs(f_->get_entry_block(), visited);
int size = static_cast<int>(reversed_post_order_vec_.size()) - 1;
for (auto& it : reversed_post_order_)
{
it.second = size - it.second;
reversed_post_order_vec_[it.second] = it.first;
}
} }
/** /**
...@@ -100,8 +106,8 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) { ...@@ -100,8 +106,8 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) {
dfs(succ, visited); dfs(succ, visited);
} }
} }
post_order_vec_.push_back(bb); reversed_post_order_vec_.push_back(bb);
post_order_.insert({bb, post_order_.size()}); reversed_post_order_.insert({bb, reversed_post_order_.size()});
} }
/** /**
...@@ -111,38 +117,28 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) { ...@@ -111,38 +117,28 @@ void Dominators::dfs(BasicBlock *bb, std::set<BasicBlock *> &visited) {
*/ */
void Dominators::create_idom() { void Dominators::create_idom() {
// 可能有用的数据结构 // 可能有用的数据结构
// post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列 // reversed_post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
// post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 post_order_vec_ 中的索引 // reversed_post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 reversed_post_order_vec_ 中的索引
// 可能有用的函数 // 可能有用的函数
// intersect(BasicBlock *, BasicBlock *) 寻找两个基本块在支配树上的最近祖先 // intersect(BasicBlock *, BasicBlock *) 寻找两个基本块在支配树上的最近祖先
// 需要填写 // 需要填写
// idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a (或者 idom_[a] = a 代表 a 没有直接支配者) // idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a (或者 idom_[a] = a 代表 a 没有直接支配者)
// 代表基本块的直接支配者是否已经确定, 不会在迭代中改变 (默认初始化为 false) int bb_count = static_cast<int>(reversed_post_order_vec_.size());
bool* already_determined = new bool[post_order_vec_.size()]{};
int bb_count = static_cast<int>(post_order_vec_.size()); idom_[reversed_post_order_vec_[0]] = reversed_post_order_vec_[0];
for (int i = 0; i < bb_count; i++)
{
auto bb = post_order_vec_[i];
// TODO 填写可以直接确定直接支配者, 无需参与迭代的基本块的 idom_ 和 already_determined
throw "Unimplemented create_idom";
}
bool changed; bool changed;
do do
{ {
changed = false; changed = false;
for (int i = 0; i < bb_count; i++) for (int i = 1; i < bb_count; i++)
{ {
if (already_determined[i]) continue; auto bb = reversed_post_order_vec_[i];
auto bb = post_order_vec_[i];
// TODO 更新基本块 bb 的 idom_, 设置 changed(如果 idom_ 有变化) // TODO 更新基本块 bb 的 idom_, 设置 changed(如果 idom_ 有变化)
throw "Unimplemented create_idom"; throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
} while (changed); } while (changed);
delete[] already_determined;
} }
/** /**
...@@ -154,19 +150,19 @@ void Dominators::create_idom() { ...@@ -154,19 +150,19 @@ void Dominators::create_idom() {
*/ */
void Dominators::create_dominance_frontier() { void Dominators::create_dominance_frontier() {
// 可能有用的数据结构 // 可能有用的数据结构
// post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列 // reversed_post_order_vec_ vector<BasicBlock*>, 其中基本块按照逆后续排列
// post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 post_order_vec_ 中的索引 // reversed_post_order_ map<BasicBlock*, unsigned int>, 每个基本块在 reversed_post_order_vec_ 中的索引
// idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent // idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent
// (或者 idom_[a] = a 代表 a 没有直接支配者) // (或者 idom_[a] = a 代表 a 没有直接支配者)
// 需要填写 // 需要填写
// dom_frontier_ map<BasicBlock*, set<BasicBlock*>> 支配边界 // dom_frontier_ map<BasicBlock*, set<BasicBlock*>> 支配边界
int bb_count = static_cast<int>(post_order_vec_.size()); int bb_count = static_cast<int>(reversed_post_order_vec_.size());
for (int i = 0; i < bb_count; i++) for (int i = 0; i < bb_count; i++)
{ {
auto bb = post_order_vec_[i]; auto bb = reversed_post_order_vec_[i];
// TODO 计算 bb 的支配边界集合, 填入 dom_frontier_ // TODO 计算 bb 的支配边界集合, 填入 dom_frontier_
throw "Unimplemented create_dominance_frontier"; throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
} }
...@@ -183,7 +179,8 @@ void Dominators::create_dom_tree_succ() { ...@@ -183,7 +179,8 @@ void Dominators::create_dom_tree_succ() {
// dom_tree_succ_blocks_ map<BasicBlock*, set<BasicBlock*>> 支配树中后继(孩子)节点 // dom_tree_succ_blocks_ map<BasicBlock*, set<BasicBlock*>> 支配树中后继(孩子)节点
// TODO 分析得到 f_ 中各个基本块的支配树后继 // TODO 分析得到 f_ 中各个基本块的支配树后继
throw "Unimplemented create_dom_tree_succ"; // 注意如果 idom_[n] = n, 这意味着 n 没有直接支配者,因此 n 的后继中没有 n
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
/** /**
......
...@@ -174,6 +174,21 @@ std::unordered_set<Value*> FuncInfo::get_stores(const CallInst* call) ...@@ -174,6 +174,21 @@ std::unordered_set<Value*> FuncInfo::get_stores(const CallInst* call)
return ret; return ret;
} }
std::unordered_set<Value*> FuncInfo::get_loads(const CallInst* call)
{
auto func = call->get_operand(0)->as<Function>();
if (func->is_declaration()) return {};
std::unordered_set<Value*> ret;
for (auto i : loads[func].globals_) ret.emplace(i);
for (auto arg : loads[func].arguments_)
{
int arg_no = static_cast<int>(arg->get_arg_no());
auto in = call->get_operand(arg_no + 1);
ret.emplace(trace_ptr(in));
}
return ret;
}
void FuncInfo::log() const void FuncInfo::log() const
{ {
for (auto it : use_libs) for (auto it : use_libs)
......
...@@ -67,21 +67,6 @@ std::vector<Instruction*> LoopInvariantCodeMotion::collect_insts(Loop* loop) ...@@ -67,21 +67,6 @@ std::vector<Instruction*> LoopInvariantCodeMotion::collect_insts(Loop* loop)
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
// TODO: 实现collect_loop_info函数
// 1. 遍历当前循环及其子循环的所有指令
// 2. 收集所有指令到loop_instructions中
// 3. 检查store指令是否修改了全局变量,如果是则添加到updated_global中
// 4. 检查是否包含非纯函数调用,如果有则设置contains_impure_call为true
void LoopInvariantCodeMotion::collect_loop_info(
Loop* loop,
std::set<Value*>& loop_instructions,
std::set<Value*>& updated_global,
bool& contains_impure_call)
{
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
}
enum InstructionType: std::uint8_t enum InstructionType: std::uint8_t
{ {
UNKNOWN, VARIANT, INVARIANT UNKNOWN, VARIANT, INVARIANT
...@@ -99,19 +84,9 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop) ...@@ -99,19 +84,9 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
// 循环中的所有指令 // 循环中的所有指令
std::vector<Instruction*> instructions = collect_insts(loop); std::vector<Instruction*> instructions = collect_insts(loop);
int insts_count = static_cast<int>(instructions.size()); int insts_count = static_cast<int>(instructions.size());
// 循环的所有基本块 // Value* 在 map 内说明它是循环内的指令,InstructionType 指示它是循环变量(每次循环都会变)/ 循环不变量 还是 不知道
std::unordered_set<BasicBlock*> bbs; std::unordered_map<Value*, InstructionType> inst_type;
for (auto i : loop->get_blocks()) bbs.emplace(i); for (auto i : instructions) inst_type[i] = UNKNOWN;
// val 是否在循环内定义,可以当成函数进行调用
auto is_val_in_loop = [&bbs](Value* val)->bool
{
auto inst = dynamic_cast<Instruction*>(val);
if (inst == nullptr) return true;
return bbs.count(inst->get_parent());
};
// inst_type[i] 代表 instructions[i] 是循环变量(每次循环都会变)/ 循环不变量 还是 不知道
std::vector<InstructionType> inst_type;
inst_type.resize(insts_count);
// 遍历后是不是还有指令不知道 InstructionType // 遍历后是不是还有指令不知道 InstructionType
bool have_inst_can_not_decide; bool have_inst_can_not_decide;
...@@ -123,10 +98,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop) ...@@ -123,10 +98,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
for (int i = 0; i < insts_count; i++) for (int i = 0; i < insts_count; i++)
{ {
Instruction* inst = instructions[i]; Instruction* inst = instructions[i];
InstructionType type = inst_type[i]; InstructionType type = inst_type[inst];
if (type != UNKNOWN) continue; if (type != UNKNOWN) continue;
// 可能有用的函数 // 可能有用的函数
// FuncInfo::load_ptr // FuncInfo::load_ptr, FuncInfo::get_stores, FuncInfo::use_io
// TODO: 识别循环不变式指令 // TODO: 识别循环不变式指令
// - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT // - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT
...@@ -134,6 +109,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop) ...@@ -134,6 +109,10 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
// - 如果指令有 VARIANT 操作数,标记为 VARIANT // - 如果指令有 VARIANT 操作数,标记为 VARIANT
// - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant // - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant
// - 否则设置 have_inst_can_not_decide // - 否则设置 have_inst_can_not_decide
// TODO: 外提循环不变的非纯函数调用
// 注意: 你不应该外提使用了 io 的函数调用
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
} }
...@@ -152,20 +131,26 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop) ...@@ -152,20 +131,26 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
for (auto phi : loop->get_header()->get_instructions()) for (auto phi : loop->get_header()->get_instructions())
{ {
if (phi->get_instr_type() != Instruction::phi) break; if (phi->get_instr_type() != Instruction::phi) break;
// 可能有用的函数
// PhiInst::create_phi
// TODO: 分裂 phi 指令 // TODO: 分裂 phi 指令
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
// 可能有用的函数
// BranchInst::replace_all_bb_match
// TODO: 维护 bb, header, 与 header 前驱块的基本块关系 // TODO: 维护 bb, header, 与 header 前驱块的基本块关系
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
bb->add_instruction(BranchInst::create_br(header, bb)); BranchInst::create_br(header, bb);
// 若你想维护 LoopDetection 在 LICM 后保持正确 // 若你想维护 LoopDetection 在 LICM 后保持正确
// auto loop2 = loop->get_parent(); // auto loop2 = loop->get_parent();
// while (loop2 != nullptr) // while (loop2 != nullptr)
// { // {
// loop2->get_parent()->add_block(bb); // loop2->add_block(bb);
// loop2 = loop2->get_parent(); // loop2 = loop2->get_parent();
// } // }
} }
...@@ -177,8 +162,12 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop) ...@@ -177,8 +162,12 @@ void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
auto terminator = preheader->get_instructions().back(); auto terminator = preheader->get_instructions().back();
preheader->get_instructions().pop_back(); preheader->get_instructions().pop_back();
// 可以使用 Function::check_for_block_relation_error 检查基本块间的关系是否正确维护
// TODO: 外提循环不变指令 // TODO: 外提循环不变指令
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
preheader->add_instruction(terminator); preheader->add_instruction(terminator);
std::cerr << "licm done\n";
} }
...@@ -54,6 +54,21 @@ void LoopDetection::run() { ...@@ -54,6 +54,21 @@ void LoopDetection::run() {
delete dominators_; delete dominators_;
} }
std::string Loop::safe_print() const
{
std::string ret;
if (header_ == nullptr) ret += "b<null>";
else ret += header_->get_name();
ret += " ";
ret += std::to_string(blocks_.size());
ret += "b ";
ret += std::to_string(latches_.size());
ret += "latch ";
ret += std::to_string(sub_loops_.size());
ret += "sub";
return ret;
}
/** /**
* @brief 发现循环及其子循环 * @brief 发现循环及其子循环
* @param bb 循环的header块 * @param bb 循环的header块
...@@ -69,10 +84,12 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set<BasicBl ...@@ -69,10 +84,12 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set<BasicBl
// 5. 建立正确的循环嵌套关系 // 5. 建立正确的循环嵌套关系
std::vector<BasicBlock*> work_list = {latches.begin(), latches.end()}; // 初始化工作表 std::vector<BasicBlock*> work_list = {latches.begin(), latches.end()}; // 初始化工作表
std::unordered_set<BasicBlock*> already_in_work_list = { latches.begin(), latches.end() }; // 已经在工作表,防止重复加入
while (!work_list.empty()) { // 当工作表非空时继续处理 while (!work_list.empty()) { // 当工作表非空时继续处理
auto bb2 = work_list.back(); auto bb2 = work_list.back();
work_list.pop_back(); work_list.pop_back();
already_in_work_list.erase(bb2);
// TODO-1: 处理未分配给任何循环的节点 // TODO-1: 处理未分配给任何循环的节点
if (bb_to_loop_.find(bb2) == bb_to_loop_.end()) { if (bb_to_loop_.find(bb2) == bb_to_loop_.end()) {
......
...@@ -4,11 +4,12 @@ ...@@ -4,11 +4,12 @@
#include "Value.hpp" #include "Value.hpp"
// l_val 是否是非数组 alloca 变量 // ptr 是否是非数组 alloca 变量(是则转换为 AllocaInst)
static bool is_not_array_alloca(Value* l_val) static AllocaInst* is_not_array_alloca(Value* ptr)
{ {
auto alloca = dynamic_cast<AllocaInst*>(l_val); auto alloca = dynamic_cast<AllocaInst*>(ptr);
return alloca != nullptr && !alloca->get_alloca_type()->is_array_type(); if (alloca != nullptr && !alloca->get_alloca_type()->is_array_type()) return alloca;
return nullptr;
} }
/** /**
...@@ -43,7 +44,7 @@ void Mem2Reg::run() { ...@@ -43,7 +44,7 @@ void Mem2Reg::run() {
generate_phi(); generate_phi();
// 确保每个局部变量的栈都有初始值 // 确保每个局部变量的栈都有初始值
for (auto var : allocas_) for (auto var : allocas_)
var_val_stack[var].emplace_back(ConstantZero::get(var->get_alloca_type(), m_)); var_val_stack[var].emplace_back(var->get_alloca_type()->is_float_type() ? static_cast<Value*>(ConstantFP::get(0, m_)) : static_cast<Value*>(ConstantInt::get(0, m_)));
// 对应伪代码中重命名阶段 // 对应伪代码中重命名阶段
rename(func_->get_entry_block()); rename(func_->get_entry_block());
} }
...@@ -80,11 +81,13 @@ void Mem2Reg::generate_phi() { ...@@ -80,11 +81,13 @@ void Mem2Reg::generate_phi() {
if (instr->is_store()) { if (instr->is_store()) {
// store i32 a, i32 *b // store i32 a, i32 *b
// a is r_val, b is l_val // a is r_val, b is l_val
auto l_val = dynamic_cast<StoreInst *>(instr)->get_lval(); auto l_val = dynamic_cast<StoreInst*>(instr)->get_ptr();
if (is_not_array_alloca(l_val)) { if (auto lalloca = is_not_array_alloca(l_val)) {
auto lalloca = dynamic_cast<AllocaInst*>(instr); if (!not_array_allocas.count(lalloca))
{
not_array_allocas.insert(lalloca); not_array_allocas.insert(lalloca);
allocas_.emplace_back(lalloca); allocas_.emplace_back(lalloca);
}
allocas_stored_bbs[lalloca].emplace_back(bb); allocas_stored_bbs[lalloca].emplace_back(bb);
} }
} }
...@@ -115,7 +118,6 @@ void Mem2Reg::generate_phi() { ...@@ -115,7 +118,6 @@ void Mem2Reg::generate_phi() {
bb_dominance_frontier_bb); bb_dominance_frontier_bb);
phi_to_alloca_.emplace(phi, var); phi_to_alloca_.emplace(phi, var);
bb_to_phi_[bb_dominance_frontier_bb].emplace_back(phi); bb_to_phi_[bb_dominance_frontier_bb].emplace_back(phi);
bb_dominance_frontier_bb->add_instr_begin(phi);
work_list.push_back(bb_dominance_frontier_bb); work_list.push_back(bb_dominance_frontier_bb);
bb_has_var_phi.emplace(bb_dominance_frontier_bb, var); bb_has_var_phi.emplace(bb_dominance_frontier_bb, var);
} }
...@@ -128,20 +130,23 @@ void Mem2Reg::rename(BasicBlock *bb) { ...@@ -128,20 +130,23 @@ void Mem2Reg::rename(BasicBlock *bb) {
// 可能用到的数据结构 // 可能用到的数据结构
// list<AllocaInst*> allocas_ 所有 Mem2Reg 需要消除的局部变量,用于遍历 // list<AllocaInst*> allocas_ 所有 Mem2Reg 需要消除的局部变量,用于遍历
// map<AllocaInst*,vector<Value *>> var_val_stack 每个局部变量的存储值栈,还未进行任何操作时已经存进去了 0,不会为空 // map<AllocaInst*,vector<Value *>> var_val_stack 每个局部变量的存储值栈,还未进行任何操作时已经存进去了 0,不会为空
// map<PhiInst *, AllocaInst*>; Phi 对应的局部变量 // map<PhiInst *, AllocaInst*> phi_to_alloca_; Phi 对应的局部变量
// map<BasicBlock*, list<PhiInst*>>; 在某个基本块的 Phi // map<BasicBlock*, list<PhiInst*>> bb_to_phi_; 在某个基本块的 Phi
// 可能用到的函数 // 可能用到的函数
// Value::replace_all_use_with(Value* a) 将所有用到 this 的指令对应 this 的操作数都替换为 a // Value::replace_all_use_with(Value* a) 将所有用到 this 的指令对应 this 的操作数都替换为 a
// BasicBlock::erase_instrs(set<Instruction*>) 移除并 delete 列表中的指令 // BasicBlock::erase_instrs(set<Instruction*>) 移除并 delete 列表中的指令
// StoreInst / LoadInst get_ptr 这些 Inst 所操作的变量
// is_not_array_alloca(Value* ptr) 一个变量是不是 Mem2Reg 所关心的非数组局部变量
// TODO // TODO
// 步骤一:对每个 alloca 非数组变量(局部变量), 在其存储值栈存入其当前的最新值(也就是目前的栈顶值) // 步骤一:对每个 alloca 非数组变量(局部变量), 在其存储值栈存入其当前的最新值(也就是目前的栈顶值)
// 步骤二:遍历基本块所有指令,执行操作并记录需要删除的 load/store/alloca 指令 // 步骤二:遍历基本块所有指令,执行操作并记录需要删除的 load/store/alloca 指令(注意: 并非所有 load/store/alloca 都是 Mem2Reg 需要处理的)
// - 步骤三: 将 store 指令存储的值,作为其对应局部变量的最新值(更新栈顶) // - 步骤三: 将 store 指令存储的值,作为其对应局部变量的最新值(更新栈顶)
// - 步骤四: 将 load 指令的所有使用替换为其读取的局部变量的最新值 // - 步骤四: 将 phi 指令的所有使用替换为其对应的局部变量的最新值
// 步骤五:为所有后继块的 phi 添加参数 // - 步骤五: 将 load 指令的所有使用替换为其读取的局部变量的最新值
// 步骤六:对 bb 在支配树上的所有后继节点,递归执行 rename 操作 // 步骤六:为所有后继块的 phi 添加参数
// 步骤七:pop 出所有局部变量的最新值 // 步骤七:对 bb 在支配树上的所有后继节点,递归执行 rename 操作
// 步骤八:删除需要删除的冗余指令 // 步骤八:pop 出所有局部变量的最新值
// 步骤九:删除需要删除的冗余指令
} }
add_executable(
eval_lab4
eval_lab4.cpp
)
install(
TARGETS eval_lab4
)
\ No newline at end of file
This diff is collapsed.
add_subdirectory("2-ir-gen/warmup") # add_subdirectory("2-ir-gen/warmup")
add_subdirectory("3-codegen/warmup") # add_subdirectory("3-codegen/warmup")
\ No newline at end of file add_subdirectory("4-opt")
\ No newline at end of file
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