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();
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* $r23 - $r31 $s0 - $s8 static * $r23 - $r31 $s0 - $s8 static
* *
* Floating-point Register Convention * Floating-point Register Convention
* Name Alias Meaning * Name Alias Meaning
* $f0-$f1 $fa0-$fa1 argument/return value * $f0-$f1 $fa0-$fa1 argument/return value
* $f2-$f7 $fa2-$fa7 argument * $f2-$f7 $fa2-$fa7 argument
* $f8-$f23 $ft0-$ft15 temporary * $f8-$f23 $ft0-$ft15 temporary
......
...@@ -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;
......
...@@ -15,7 +15,7 @@ class FuncInfo; ...@@ -15,7 +15,7 @@ class FuncInfo;
class DeadCode : public TransformPass { class DeadCode : public TransformPass {
public: public:
/** /**
* *
* @param m 所属 Module * @param m 所属 Module
* @param remove_unreachable_bb 是否需要删除不可达的 BasicBlocks * @param remove_unreachable_bb 是否需要删除不可达的 BasicBlocks
......
...@@ -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,13 +81,20 @@ int main(int argc, char **argv) { ...@@ -79,13 +81,20 @@ 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();
} }
delete m; delete m;
} }
return 0; return 0;
...@@ -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,24 +161,25 @@ void Config::check() { ...@@ -143,24 +161,25 @@ void Config::check() {
} }
if (output_file.empty()) { if (output_file.empty()) {
output_file = input_file.stem(); output_file = input_file.stem();
if (emitllvm) { }
output_file.replace_extension(".ll"); if (emitllvm) {
} else if (emitasm) { output_file.replace_extension(".ll");
output_file.replace_extension(".s"); }
} else if (emitasm) {
output_file.replace_extension(".s");
} }
} }
void Config::print_help() const { void Config::print_help() const {
std::cout << "Usage: " << exe_name std::cout << "Usage: " << exe_name
<< " [-h|--help] [-o <target-file>] [-emit-llvm] [-S] [-dump-json]" << " [-h|--help] [-o <target-file>] [-emit-llvm] [-S] [-dump-json]"
"[-mem2reg] [-licm]" "[-mem2reg] [-licm]"
"<input-file>" "<input-file>"
<< std::endl; << std::endl;
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
...@@ -11,14 +11,14 @@ ...@@ -11,14 +11,14 @@
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_;
} }
......
...@@ -42,6 +42,6 @@ void User::remove_operand(unsigned idx) { ...@@ -42,6 +42,6 @@ void User::remove_operand(unsigned idx) {
} }
// remove the designated operand // remove the designated operand
if (operands_[idx]) if (operands_[idx])
operands_[idx]->remove_use(this, idx); operands_[idx]->remove_use(this, idx);
operands_.erase(operands_.begin() + idx); operands_.erase(operands_.begin() + idx);
} }
...@@ -10,11 +10,12 @@ ...@@ -10,11 +10,12 @@
// 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令 // 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令
void DeadCode::run() { void DeadCode::run() {
bool changed; bool changed;
func_info = new FuncInfo(m_); func_info = new FuncInfo(m_);
func_info->run(); func_info->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);
...@@ -133,7 +134,7 @@ bool DeadCode::sweep(Function *func) { ...@@ -133,7 +134,7 @@ bool DeadCode::sweep(Function *func) {
for (auto bb : func->get_basic_blocks()) { for (auto bb : func->get_basic_blocks()) {
for (auto inst : bb->get_instructions()) { for (auto inst : bb->get_instructions()) {
if (marked[inst]) continue; if (marked[inst]) continue;
wait_del.emplace(inst); wait_del.emplace(inst);
} }
bb->get_instructions().remove_if([&wait_del](Instruction* i) -> bool {return wait_del.count(i); }); bb->get_instructions().remove_if([&wait_del](Instruction* i) -> bool {return wait_del.count(i); });
if (!wait_del.empty()) rm = true; if (!wait_del.empty()) rm = true;
...@@ -172,12 +173,12 @@ void DeadCode::sweep_globally() const { ...@@ -172,12 +173,12 @@ void DeadCode::sweep_globally() const {
// changed |= unused_funcs.size() or unused_globals.size(); // changed |= unused_funcs.size() or unused_globals.size();
for (auto func : unused_funcs) for (auto func : unused_funcs)
{ {
m_->get_functions().remove(func); m_->get_functions().remove(func);
delete func; delete func;
} }
for (auto glob : unused_globals) for (auto glob : unused_globals)
{ {
m_->get_global_variable().remove(glob); m_->get_global_variable().remove(glob);
delete glob; delete glob;
} }
} }
...@@ -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需要完成!");
} }
} }
...@@ -178,12 +174,13 @@ void Dominators::create_dominance_frontier() { ...@@ -178,12 +174,13 @@ void Dominators::create_dominance_frontier() {
*/ */
void Dominators::create_dom_tree_succ() { void Dominators::create_dom_tree_succ() {
// 可能有用的数据结构 // 可能有用的数据结构
// idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent // idom_ map<BasicBlock *, BasicBlock *> 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent
// 需要填写 // 需要填写
// 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需要完成!");
} }
/** /**
......
This diff is collapsed.
...@@ -14,23 +14,23 @@ ...@@ -14,23 +14,23 @@
*/ */
void LoopInvariantCodeMotion::run() void LoopInvariantCodeMotion::run()
{ {
func_info_ = new FuncInfo(m_); func_info_ = new FuncInfo(m_);
func_info_->run(); func_info_->run();
for (auto func : m_->get_functions()) for (auto func : m_->get_functions())
{ {
if (func->is_declaration()) continue; if (func->is_declaration()) continue;
loop_detection_ = new LoopDetection(func); loop_detection_ = new LoopDetection(func);
loop_detection_->run(); loop_detection_->run();
for (auto loop : loop_detection_->get_loops()) for (auto loop : loop_detection_->get_loops())
{ {
// 遍历处理顶层循环 // 遍历处理顶层循环
if (loop->get_parent() == nullptr) traverse_loop(loop); if (loop->get_parent() == nullptr) traverse_loop(loop);
} }
delete loop_detection_; delete loop_detection_;
loop_detection_ = nullptr; loop_detection_ = nullptr;
} }
delete func_info_; delete func_info_;
func_info_ = nullptr; func_info_ = nullptr;
} }
/** /**
...@@ -40,12 +40,12 @@ void LoopInvariantCodeMotion::run() ...@@ -40,12 +40,12 @@ void LoopInvariantCodeMotion::run()
*/ */
void LoopInvariantCodeMotion::traverse_loop(Loop* loop) void LoopInvariantCodeMotion::traverse_loop(Loop* loop)
{ {
// 先外层再内层,这样不用在插入 preheader 后更改循环 // 先外层再内层,这样不用在插入 preheader 后更改循环
run_on_loop(loop); run_on_loop(loop);
for (auto sub_loop : loop->get_sub_loops()) for (auto sub_loop : loop->get_sub_loops())
{ {
traverse_loop(sub_loop); traverse_loop(sub_loop);
} }
} }
// TODO: 收集并返回循环 store 过的变量 // TODO: 收集并返回循环 store 过的变量
...@@ -56,35 +56,20 @@ void LoopInvariantCodeMotion::traverse_loop(Loop* loop) ...@@ -56,35 +56,20 @@ void LoopInvariantCodeMotion::traverse_loop(Loop* loop)
// 则你应该返回 %a 而非 %b // 则你应该返回 %a 而非 %b
std::unordered_set<Value*> LoopInvariantCodeMotion::collect_loop_store_vars(Loop* loop) std::unordered_set<Value*> LoopInvariantCodeMotion::collect_loop_store_vars(Loop* loop)
{ {
// 可能用到 // 可能用到
// FuncInfo::store_ptr, FuncInfo::get_stores // FuncInfo::store_ptr, FuncInfo::get_stores
throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} }
// TODO: 收集并返回循环中的所有指令 // TODO: 收集并返回循环中的所有指令
std::vector<Instruction*> LoopInvariantCodeMotion::collect_insts(Loop* loop) 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
}; };
/** /**
...@@ -94,91 +79,95 @@ enum InstructionType: std::uint8_t ...@@ -94,91 +79,95 @@ enum InstructionType: std::uint8_t
*/ */
void LoopInvariantCodeMotion::run_on_loop(Loop* loop) void LoopInvariantCodeMotion::run_on_loop(Loop* loop)
{ {
// 循环 store 过的变量 // 循环 store 过的变量
std::unordered_set<Value*> loop_stores_var = collect_loop_store_vars(loop); std::unordered_set<Value*> loop_stores_var = collect_loop_store_vars(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 // 遍历后是不是还有指令不知道 InstructionType
{ bool have_inst_can_not_decide;
auto inst = dynamic_cast<Instruction*>(val); // 是否存在 invariant
if (inst == nullptr) return true; bool have_invariant = false;
return bbs.count(inst->get_parent()); do
}; {
// inst_type[i] 代表 instructions[i] 是循环变量(每次循环都会变)/ 循环不变量 还是 不知道 have_inst_can_not_decide = false;
std::vector<InstructionType> inst_type; for (int i = 0; i < insts_count; i++)
inst_type.resize(insts_count); {
Instruction* inst = instructions[i];
// 遍历后是不是还有指令不知道 InstructionType InstructionType type = inst_type[inst];
bool have_inst_can_not_decide; if (type != UNKNOWN) continue;
// 是否存在 invariant // 可能有用的函数
bool have_invariant = false; // FuncInfo::load_ptr, FuncInfo::get_stores, FuncInfo::use_io
do
{ // TODO: 识别循环不变式指令
have_inst_can_not_decide = false; // - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT
for (int i = 0; i < insts_count; i++) // - 如果 load 指令加载的变量是循环 store 过的变量,标记为 VARIANT
{ // - 如果指令有 VARIANT 操作数,标记为 VARIANT
Instruction* inst = instructions[i]; // - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant
InstructionType type = inst_type[i]; // - 否则设置 have_inst_can_not_decide
if (type != UNKNOWN) continue;
// 可能有用的函数 // TODO: 外提循环不变的非纯函数调用
// FuncInfo::load_ptr // 注意: 你不应该外提使用了 io 的函数调用
// TODO: 识别循环不变式指令 throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
// - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT }
// - 如果 load 指令加载的变量是循环 store 过的变量,标记为 VARIANT }
// - 如果指令有 VARIANT 操作数,标记为 VARIANT while (have_inst_can_not_decide);
// - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant
// - 否则设置 have_inst_can_not_decide if (!have_invariant) return;
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
} auto header = loop->get_header();
}
while (have_inst_can_not_decide); if (header->get_pre_basic_blocks().size() > 1 || header->get_pre_basic_blocks().front()->get_succ_basic_blocks().size() > 1)
{
if (!have_invariant) return; // 插入 preheader
auto bb = BasicBlock::create(m_, "", loop->get_header()->get_parent());
auto header = loop->get_header(); loop->set_preheader(bb);
if (header->get_pre_basic_blocks().size() > 1 || header->get_pre_basic_blocks().front()->get_succ_basic_blocks().size() > 1) for (auto phi : loop->get_header()->get_instructions())
{ {
// 插入 preheader if (phi->get_instr_type() != Instruction::phi) break;
auto bb = BasicBlock::create(m_, "", loop->get_header()->get_parent()); // 可能有用的函数
loop->set_preheader(bb); // PhiInst::create_phi
for (auto phi : loop->get_header()->get_instructions()) // TODO: 分裂 phi 指令
{ throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
if (phi->get_instr_type() != Instruction::phi) break; }
// TODO: 分裂 phi 指令
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();
// } // }
} }
else loop->set_preheader(header->get_pre_basic_blocks().front()); else loop->set_preheader(header->get_pre_basic_blocks().front());
// insert preheader // insert preheader
auto preheader = loop->get_preheader(); auto preheader = loop->get_preheader();
auto terminator = preheader->get_instructions().back(); auto terminator = preheader->get_instructions().back();
preheader->get_instructions().pop_back(); preheader->get_instructions().pop_back();
// TODO: 外提循环不变指令 // 可以使用 Function::check_for_block_relation_error 检查基本块间的关系是否正确维护
throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
// TODO: 外提循环不变指令
preheader->add_instruction(terminator); throw std::runtime_error("Lab4: 你有一个TODO需要完成!");
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()) {
...@@ -85,7 +102,7 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set<BasicBl ...@@ -85,7 +102,7 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set<BasicBl
} }
// TODO-2: 处理已属于其他循环的节点 // TODO-2: 处理已属于其他循环的节点
if (bb_to_loop_[bb2] != loop) { if (bb_to_loop_[bb2] != loop) {
/* 在此添加代码: /* 在此添加代码:
* 1. 获取bb当前所属的循环sub_loop * 1. 获取bb当前所属的循环sub_loop
* 2. 找到sub_loop的最顶层父循环 * 2. 找到sub_loop的最顶层父循环
......
...@@ -4,16 +4,17 @@ ...@@ -4,16 +4,17 @@
#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;
} }
/** /**
* @brief Mem2Reg Pass的主入口函数 * @brief Mem2Reg Pass的主入口函数
* *
* 该函数执行内存到寄存器的提升过程,将栈上的局部变量提升到SSA格式。 * 该函数执行内存到寄存器的提升过程,将栈上的局部变量提升到SSA格式。
* 主要步骤: * 主要步骤:
* 1. 创建并运行支配树分析 * 1. 创建并运行支配树分析
...@@ -21,7 +22,7 @@ static bool is_not_array_alloca(Value* l_val) ...@@ -21,7 +22,7 @@ static bool is_not_array_alloca(Value* l_val)
* - 清空相关数据结构 * - 清空相关数据结构
* - 插入必要的phi指令 * - 插入必要的phi指令
* - 执行变量重命名 * - 执行变量重命名
* *
* 注意:函数执行后,冗余的局部变量分配指令将由后续的死代码删除Pass处理 * 注意:函数执行后,冗余的局部变量分配指令将由后续的死代码删除Pass处理
*/ */
void Mem2Reg::run() { void Mem2Reg::run() {
...@@ -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());
} }
...@@ -55,17 +56,17 @@ void Mem2Reg::run() { ...@@ -55,17 +56,17 @@ void Mem2Reg::run() {
/** /**
* @brief 在必要的位置插入phi指令 * @brief 在必要的位置插入phi指令
* *
* 该函数实现了经典的phi节点插入算法: * 该函数实现了经典的phi节点插入算法:
* 1. 收集全局活跃变量: * 1. 收集全局活跃变量:
* - 扫描所有store指令 * - 扫描所有store指令
* - 识别在多个基本块中被赋值的变量 * - 识别在多个基本块中被赋值的变量
* *
* 2. 插入phi指令: * 2. 插入phi指令:
* - 对每个全局活跃变量 * - 对每个全局活跃变量
* - 在其定值点的支配边界处插入phi指令 * - 在其定值点的支配边界处插入phi指令
* - 使用工作表法处理迭代式的phi插入 * - 使用工作表法处理迭代式的phi插入
* *
* phi指令的插入遵循最小化原则,只在必要的位置插入phi节点 * phi指令的插入遵循最小化原则,只在必要的位置插入phi节点
*/ */
void Mem2Reg::generate_phi() { void Mem2Reg::generate_phi() {
...@@ -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); {
allocas_.emplace_back(lalloca); not_array_allocas.insert(lalloca);
allocas_.emplace_back(lalloca);
}
allocas_stored_bbs[lalloca].emplace_back(bb); allocas_stored_bbs[lalloca].emplace_back(bb);
} }
} }
...@@ -105,7 +108,7 @@ void Mem2Reg::generate_phi() { ...@@ -105,7 +108,7 @@ void Mem2Reg::generate_phi() {
if (already_handled.count(bb)) continue; if (already_handled.count(bb)) continue;
already_handled.emplace(bb); already_handled.emplace(bb);
for (auto bb_dominance_frontier_bb : for (auto bb_dominance_frontier_bb :
dominators_->get_dominance_frontier(bb)) { dominators_->get_dominance_frontier(bb)) {
if (bb_has_var_phi.find({bb_dominance_frontier_bb, var}) == if (bb_has_var_phi.find({bb_dominance_frontier_bb, var}) ==
bb_has_var_phi.end()) { bb_has_var_phi.end()) {
// generate phi for bb_dominance_frontier_bb & add // generate phi for bb_dominance_frontier_bb & add
...@@ -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