From 93702b6203f10aa61f2f9fa4ffb286cd4c630dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E9=BE=99=E6=88=90?= Date: Mon, 1 Dec 2025 19:45:15 +0800 Subject: [PATCH] fix lab4 --- include/lightir/BasicBlock.hpp | 5 + include/lightir/Instruction.hpp | 11 +- include/passes/DeadCode.hpp | 45 +++-- include/passes/Dominators.hpp | 72 +++---- include/passes/FuncInfo.hpp | 67 ++++--- include/passes/LICM.hpp | 23 ++- include/passes/LoopDetection.hpp | 52 +++-- include/passes/Mem2Reg.hpp | 38 ++-- include/passes/PassManager.hpp | 44 +++- src/cminusfc/main.cpp | 5 +- src/lightir/BasicBlock.cpp | 21 ++ src/lightir/Function.cpp | 2 +- src/lightir/Instruction.cpp | 11 + src/lightir/User.cpp | 12 +- src/lightir/Value.cpp | 6 +- src/passes/CMakeLists.txt | 2 +- src/passes/DeadCode.cpp | 120 +++++++---- src/passes/Dominators.cpp | 207 +++++++++++-------- src/passes/FuncInfo.cpp | 333 ++++++++++++++++++++++--------- src/passes/LICM.cpp | 254 +++++++++++++---------- src/passes/LoopDetection.cpp | 125 ++++++------ src/passes/Mem2Reg.cpp | 98 +++++---- src/passes/PassManager.cpp | 7 + 23 files changed, 983 insertions(+), 577 deletions(-) create mode 100644 src/passes/PassManager.cpp diff --git a/include/lightir/BasicBlock.hpp b/include/lightir/BasicBlock.hpp index 418de95..e4c1c02 100755 --- a/include/lightir/BasicBlock.hpp +++ b/include/lightir/BasicBlock.hpp @@ -4,6 +4,7 @@ #include "Value.hpp" #include +#include #include class Function; @@ -64,8 +65,12 @@ class BasicBlock : public Value { // 从 BasicBlock 移除 Instruction,并 delete 这个 Instruction void erase_instr(Instruction* instr) { instr_list_.remove(instr); delete instr; } + // 从 BasicBlock 移除集合中的 Instruction,并 delete 这些 Instruction + void erase_instrs(const std::set& instr); // 从 BasicBlock 移除 Instruction,你需要自己 delete 它 void remove_instr(Instruction *instr) { instr_list_.remove(instr); } + // 从 BasicBlock 移除集合中的 Instruction,你需要自己 delete 它们 + void remove_instrs(const std::set& instr); // 移除的 Instruction 需要自己 delete std::list &get_instructions() { return instr_list_; } diff --git a/include/lightir/Instruction.hpp b/include/lightir/Instruction.hpp index f3dffe4..155cf87 100755 --- a/include/lightir/Instruction.hpp +++ b/include/lightir/Instruction.hpp @@ -342,16 +342,7 @@ class PhiInst : public Instruction { this->add_operand(val); this->add_operand(pre_bb); } - std::vector> get_phi_pairs() const - { - std::vector> res; - int ops = static_cast(get_num_operand()); - for (int i = 0; i < ops; i += 2) { - res.emplace_back(this->get_operand(i), - this->get_operand(i + 1)->as()); - } - return res; - } + std::vector> get_phi_pairs() const; std::string print() override; }; diff --git a/include/passes/DeadCode.hpp b/include/passes/DeadCode.hpp index 8a88009..15f2974 100644 --- a/include/passes/DeadCode.hpp +++ b/include/passes/DeadCode.hpp @@ -1,30 +1,45 @@ #pragma once -#include "FuncInfo.hpp" -#include "PassManager.hpp" +#include -#include +#include "PassManager.hpp" +class FuncInfo; /** - * 死代码消除:参见 - *https://www.clear.rice.edu/comp512/Lectures/10Dead-Clean-SCCP.pdf + * 死代码消除:假设所有指令都可以去掉,然后只保留具有副作用的指令和它们所影响的指令。去掉不可达的基本块。 + * + * 在初始化时指定一个 bool 参数 remove_unreachable_bb, 代表是否去除函数不可达基本块 + * + * 参见 https://www.clear.rice.edu/comp512/Lectures/10Dead-Clean-SCCP.pdf **/ -class DeadCode : public Pass { +class DeadCode : public TransformPass { public: - DeadCode(Module *m) : Pass(m), func_info(std::make_shared(m)) {} + + /** + * + * @param m 所属 Module + * @param remove_unreachable_bb 是否需要删除不可达的 BasicBlocks + */ + DeadCode(Module *m, bool remove_unreachable_bb) : TransformPass(m), remove_bb_(remove_unreachable_bb), func_info(nullptr) {} - void run(); + void run() override; private: - std::shared_ptr func_info; - int ins_count{0}; // 用以衡量死代码消除的性能 - std::deque work_list{}; + bool remove_bb_; + FuncInfo* func_info; std::unordered_map marked{}; + std::deque work_list{}; + // 标记函数中不可删除指令 void mark(Function *func); - void mark(Instruction *ins); + // 标记某不可删除的指令依赖的指令 + void mark(const Instruction *ins); + // 删除函数中无用指令 bool sweep(Function *func); - bool clear_basic_blocks(Function *func); - bool is_critical(Instruction *ins); - void sweep_globally(); + // 从 entry 开始对基本块进行搜索,删除不可达基本块 + static bool clear_basic_blocks(Function *func); + // 指令是否有副作用 + bool is_critical(Instruction *ins) const; + // 删除无用函数和全局变量 + void sweep_globally() const; }; diff --git a/include/passes/Dominators.hpp b/include/passes/Dominators.hpp index 398d0e5..b9714ac 100644 --- a/include/passes/Dominators.hpp +++ b/include/passes/Dominators.hpp @@ -1,35 +1,39 @@ #pragma once +#include +#include + #include "BasicBlock.hpp" #include "PassManager.hpp" -#include -#include -class Dominators : public Pass { +/** + * 分析 Pass, 获得某函数的支配树信息 + * + * 由于它是针对某一特定 Function 的分析 Pass, 你无法通过 m_ 获取 Module, 但可以通过 f_ 获取 Function + */ +class Dominators : public FunctionAnalysisPass { public: - using BBSet = std::set; - explicit Dominators(Module *m) : Pass(m) {} - ~Dominators() = default; + explicit Dominators(Function* f) : FunctionAnalysisPass(f) { assert(!f->is_declaration() && "Dominators can not apply to function declaration."); } + ~Dominators() override = default; void run() override; - void run_on_func(Function *f); - // functions for getting information - BasicBlock *get_idom(BasicBlock *bb) { return idom_.at(bb); } - const BBSet &get_dominance_frontier(BasicBlock *bb) { + // 获取基本块的直接支配节点 + BasicBlock *get_idom(const BasicBlock *bb) const { return idom_.at(bb); } + const std::set &get_dominance_frontier(const BasicBlock *bb) { return dom_frontier_.at(bb); } - const BBSet &get_dom_tree_succ_blocks(BasicBlock *bb) { + const std::set &get_dom_tree_succ_blocks(const BasicBlock *bb) { return dom_tree_succ_blocks_.at(bb); } // print cfg or dominance tree - void dump_cfg(Function *f); - void dump_dominator_tree(Function *f); + void dump_cfg() const; + void dump_dominator_tree(); // functions for dominance tree - const bool is_dominate(BasicBlock *bb1, BasicBlock *bb2) { + bool is_dominate(const BasicBlock *bb1, const BasicBlock *bb2) const { return dom_tree_L_.at(bb1) <= dom_tree_L_.at(bb2) && dom_tree_R_.at(bb1) >= dom_tree_L_.at(bb2); } @@ -45,42 +49,38 @@ class Dominators : public Pass { private: void dfs(BasicBlock *bb, std::set &visited); - void create_idom(Function *f); - void create_dominance_frontier(Function *f); - void create_dom_tree_succ(Function *f); - void create_dom_dfs_order(Function *f); + void create_idom(); + void create_dominance_frontier(); + void create_dom_tree_succ(); + void create_dom_dfs_order(); - BasicBlock * intersect(BasicBlock *b1, BasicBlock *b2); + BasicBlock * intersect(BasicBlock *b1, const BasicBlock *b2) const; - void create_reverse_post_order(Function *f); - void set_idom(BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; } - void set_dominance_frontier(BasicBlock *bb, BBSet &df) { + void create_reverse_post_order(); + void set_idom(const BasicBlock *bb, BasicBlock *idom) { idom_[bb] = idom; } + void set_dominance_frontier(const BasicBlock *bb, std::set&df) { dom_frontier_[bb].clear(); dom_frontier_[bb].insert(df.begin(), df.end()); } - void add_dom_tree_succ_block(BasicBlock *bb, BasicBlock *dom_tree_succ_bb) { + void add_dom_tree_succ_block(const BasicBlock *bb, BasicBlock *dom_tree_succ_bb) { dom_tree_succ_blocks_[bb].insert(dom_tree_succ_bb); } - unsigned int get_post_order(BasicBlock *bb) { + unsigned int get_post_order(const BasicBlock *bb) const { return post_order_.at(bb); } // for debug - void print_idom(Function *f); - void print_dominance_frontier(Function *f); - - // TODO 补充需要的函数 - std::list reverse_post_order_{}; - std::map post_order_id_{}; // the root has highest ID + void print_idom() const; + void print_dominance_frontier(); std::vector post_order_vec_{}; // 逆后序 - std::map post_order_{}; // 逆后序 - std::map idom_{}; // 直接支配 - std::map dom_frontier_{}; // 支配边界集合 - std::map dom_tree_succ_blocks_{}; // 支配树中的后继节点 + std::map post_order_{}; // 逆后序 + std::map idom_{}; // 直接支配 + std::map> dom_frontier_{}; // 支配边界集合 + std::map> dom_tree_succ_blocks_{}; // 支配树中的后继节点 // 支配树上的dfs序L,R - std::map dom_tree_L_; - std::map dom_tree_R_; + std::map dom_tree_L_; + std::map dom_tree_R_; std::vector dom_dfs_order_; std::vector dom_post_order_; diff --git a/include/passes/FuncInfo.hpp b/include/passes/FuncInfo.hpp index e8a8c13..80b521f 100644 --- a/include/passes/FuncInfo.hpp +++ b/include/passes/FuncInfo.hpp @@ -1,35 +1,50 @@ #pragma once -#include "PassManager.hpp" -#include "logging.hpp" - -#include #include +#include + +#include "PassManager.hpp" /** - * 计算哪些函数是纯函数 - * WARN: - * 假定所有函数都是纯函数,除非他写入了全局变量、修改了传入的数组、或者直接间接调用了非纯函数 + * 分析函数的信息,包括哪些函数是纯函数,每个函数存储的变量 */ -class FuncInfo : public Pass { +class FuncInfo : public ModuleAnalysisPass { + // 非纯函数的 load / store 信息 + struct UseMessage + { + // 影响的全局变量(注意此处不包含常全局变量,目前的文法也不支持常全局变量)) + std::unordered_set globals_; + // 影响的参数(第一个参数序号为 0) + std::unordered_set arguments_; + + void add(Value* val); + bool have(Value* val) const; + bool empty() const; + }; public: - FuncInfo(Module *m) : Pass(m) {} - - void run(); - - bool is_pure_function(Function *func) const { return is_pure.at(func); } - + FuncInfo(Module *m) : ModuleAnalysisPass(m) {} + + void run() override; + + // 函数是否是纯函数 + bool is_pure(Function *func) { return !func->is_declaration() && !use_libs.count(func) && loads[func].empty() && stores[func].empty(); } + // 返回 StoreInst 存入的变量(全局/局部变量或函数参数) + static Value* store_ptr(const StoreInst* st); + // 返回 LoadInst 加载的变量(全局/局部变量或函数参数) + static Value* load_ptr(const LoadInst* ld); + // 返回 CallInst 代表的函数调用间接存入的变量(全局/局部变量或函数参数) + std::unordered_set get_stores(const CallInst* call); private: - std::deque worklist; - std::unordered_map is_pure; - - void trivial_mark(Function *func); - void process(Function *func); - Value *get_first_addr(Value *val); - - bool is_side_effect_inst(Instruction *inst); - bool is_local_load(LoadInst *inst); - bool is_local_store(StoreInst *inst); - - void log(); + // 函数存储的值 + std::unordered_map stores; + // 函数加载的值 + std::unordered_map loads; + // 函数是否因为调用库函数而变得非纯函数 + std::unordered_map use_libs; + + // 将所有由变量 var 计算出的指针的来源都设置为变量 var, 并记录在函数内直接对 var 的 load/store + void cal_val_2_var(Value* var, std::unordered_map& val_2_var); + static Value* trace_ptr(Value* val); + + void log() const; }; diff --git a/include/passes/LICM.hpp b/include/passes/LICM.hpp index 4ae0efb..f49bdd5 100644 --- a/include/passes/LICM.hpp +++ b/include/passes/LICM.hpp @@ -1,23 +1,24 @@ +#pragma once + #include "FuncInfo.hpp" #include "LoopDetection.hpp" #include "PassManager.hpp" -#include -#include -class LoopInvariantCodeMotion : public Pass { +class LoopInvariantCodeMotion : public TransformPass { public: - LoopInvariantCodeMotion(Module *m) : Pass(m) {} - ~LoopInvariantCodeMotion() = default; + LoopInvariantCodeMotion(Module *m) : TransformPass(m), loop_detection_(nullptr), func_info_(nullptr) {} + ~LoopInvariantCodeMotion() override = default; void run() override; private: - std::unordered_map, bool> is_loop_done_; - std::unique_ptr loop_detection_; - std::unique_ptr func_info_; - void traverse_loop(std::shared_ptr loop); - void run_on_loop(std::shared_ptr loop); - void collect_loop_info(std::shared_ptr loop, + LoopDetection* loop_detection_; + FuncInfo* func_info_; + std::unordered_set collect_loop_store_vars(Loop* loop); + std::vector collect_insts(Loop* loop); + void traverse_loop(Loop* loop); + void run_on_loop(Loop* loop); + void collect_loop_info(Loop* loop, std::set &loop_instructions, std::set &updated_global, bool &contains_impure_call); diff --git a/include/passes/LoopDetection.hpp b/include/passes/LoopDetection.hpp index b55246c..cd11119 100644 --- a/include/passes/LoopDetection.hpp +++ b/include/passes/LoopDetection.hpp @@ -1,18 +1,17 @@ #pragma once -#include "Dominators.hpp" -#include "PassManager.hpp" -#include + #include #include #include +#include "Dominators.hpp" +#include "PassManager.hpp" + class BasicBlock; class Dominators; class Function; class Module; -using BBset = std::set; -using BBvec = std::vector; class Loop { private: // attribute: @@ -20,9 +19,9 @@ class Loop { BasicBlock *preheader_ = nullptr; BasicBlock *header_; - std::shared_ptr parent_ = nullptr; - BBvec blocks_; - std::vector> sub_loops_; + Loop* parent_ = nullptr; + std::vector blocks_; + std::vector sub_loops_; std::unordered_set latches_; public: @@ -31,34 +30,31 @@ class Loop { } ~Loop() = default; void add_block(BasicBlock *bb) { blocks_.push_back(bb); } - BasicBlock *get_header() { return header_; } - BasicBlock *get_preheader() { return preheader_; } - std::shared_ptr get_parent() { return parent_; } - void set_parent(std::shared_ptr parent) { parent_ = parent; } + BasicBlock *get_header() const { return header_; } + BasicBlock *get_preheader() const { return preheader_; } + Loop* get_parent() const { return parent_; } + void set_parent(Loop* parent) { parent_ = parent; } void set_preheader(BasicBlock *bb) { preheader_ = bb; } - void add_sub_loop(std::shared_ptr loop) { sub_loops_.push_back(loop); } - const BBvec& get_blocks() { return blocks_; } - const std::vector>& get_sub_loops() { return sub_loops_; } + void add_sub_loop(Loop* loop) { sub_loops_.push_back(loop); } + const std::vector& get_blocks() { return blocks_; } + const std::vector& get_sub_loops() { return sub_loops_; } const std::unordered_set& get_latches() { return latches_; } void add_latch(BasicBlock *bb) { latches_.insert(bb); } }; -class LoopDetection : public Pass { - private: - Function *func_; - std::unique_ptr dominators_; - std::vector> loops_; +class LoopDetection : public FunctionAnalysisPass { + Dominators* dominators_; + std::vector loops_; // map from header to loop - std::unordered_map> bb_to_loop_; - void discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, - std::shared_ptr loop); + std::unordered_map bb_to_loop_; + void discover_loop_and_sub_loops(BasicBlock *bb, std::set&latches, + Loop* loop); public: - LoopDetection(Module *m) : Pass(m) {} - ~LoopDetection() = default; + LoopDetection(Function *f) : FunctionAnalysisPass(f), dominators_(nullptr) { assert(!f->is_declaration() && "LoopDetection can not apply to function declaration." ); } + ~LoopDetection() override; void run() override; - void run_on_func(Function *f); - void print() ; - std::vector> &get_loops() { return loops_; } + void print() const; + std::vector &get_loops() { return loops_; } }; diff --git a/include/passes/Mem2Reg.hpp b/include/passes/Mem2Reg.hpp index 867810e..ae1e2e7 100644 --- a/include/passes/Mem2Reg.hpp +++ b/include/passes/Mem2Reg.hpp @@ -1,41 +1,33 @@ #pragma once +#include + #include "Dominators.hpp" #include "Instruction.hpp" #include "Value.hpp" -#include -#include - -class Mem2Reg : public Pass { +class Mem2Reg : public TransformPass { private: + // 当前函数 Function *func_; - std::unique_ptr dominators_; - std::map phi_map; + // 当前函数对应的支配树 + Dominators* dominators_; // TODO 添加需要的变量 + // 所有需要处理的变量 + std::list allocas_; // 变量定值栈 - std::map> var_val_stack; - // phi指令对应的左值(地址) - std::map phi_lval; - + std::map> var_val_stack; + // Phi 对应的局部变量 + std::map phi_to_alloca_; + // 在某个基本块的 Phi + std::map> bb_to_phi_; public: - Mem2Reg(Module *m) : Pass(m) {} - ~Mem2Reg() = default; + Mem2Reg(Module *m) : TransformPass(m), func_(nullptr), dominators_(nullptr) {} + ~Mem2Reg() override = default; void run() override; void generate_phi(); void rename(BasicBlock *bb); - - static inline bool is_global_variable(Value *l_val) { - return dynamic_cast(l_val) != nullptr; - } - static inline bool is_gep_instr(Value *l_val) { - return dynamic_cast(l_val) != nullptr; - } - - static inline bool is_valid_ptr(Value *l_val) { - return not is_global_variable(l_val) and not is_gep_instr(l_val); - } }; diff --git a/include/passes/PassManager.hpp b/include/passes/PassManager.hpp index d7cd50b..9200f8f 100644 --- a/include/passes/PassManager.hpp +++ b/include/passes/PassManager.hpp @@ -1,36 +1,64 @@ #pragma once -#include "Module.hpp" - #include #include -class Pass { - public: - Pass(Module *m) : m_(m) {} - virtual ~Pass() = default; +#include "Module.hpp" + +// 转换 Pass, 例如 mem2reg, licm, deadcode +class TransformPass { +public: + TransformPass(Module* m) : m_(m) {} + virtual ~TransformPass(); virtual void run() = 0; +protected: + Module* m_; +}; + +// 依赖于整个 Module 进行分析的分析 Pass, 例如 funcinfo +class ModuleAnalysisPass { + public: + ModuleAnalysisPass(Module *m) : m_(m) {} + virtual ~ModuleAnalysisPass(); + virtual void run() = 0; + protected: Module *m_; }; +// 依赖于单个 Function 进行分析的分析 Pass, 例如 dominators, loopdetection +class FunctionAnalysisPass { +public: + FunctionAnalysisPass(Function* f) : f_(f) {} + virtual ~FunctionAnalysisPass(); + virtual void run() = 0; + +protected: + Function* f_; +}; + class PassManager { public: PassManager(Module *m) : m_(m) {} + // 添加一个 Transform Pass, 添加的 Pass 被顺序运行 template void add_pass(Args &&...args) { + static_assert(std::is_base_of_v, "Pass must derive from TransformPass"); passes_.emplace_back(new PassType(m_, std::forward(args)...)); } void run() { - for (auto &pass : passes_) { + for (auto& pass : passes_) { pass->run(); + delete pass; + pass = nullptr; } } private: - std::vector> passes_; + // 它们会被顺序运行 + std::vector passes_; Module *m_; }; diff --git a/src/cminusfc/main.cpp b/src/cminusfc/main.cpp index 6bb21f6..8bcc785 100755 --- a/src/cminusfc/main.cpp +++ b/src/cminusfc/main.cpp @@ -64,13 +64,12 @@ int main(int argc, char **argv) { PassManager PM(m); // optimization if(config.mem2reg) { - PM.add_pass(); PM.add_pass(); - PM.add_pass(); + PM.add_pass(false); } if(config.licm) { PM.add_pass(); - PM.add_pass(); + PM.add_pass(false); } PM.run(); diff --git a/src/lightir/BasicBlock.cpp b/src/lightir/BasicBlock.cpp index 5bd0a6d..6804d37 100755 --- a/src/lightir/BasicBlock.cpp +++ b/src/lightir/BasicBlock.cpp @@ -77,6 +77,27 @@ void BasicBlock::add_instr_before_terminator(Instruction* instr) { else instr_list_.insert(std::prev(instr_list_.end()), instr); } +void BasicBlock::erase_instrs(const std::set& instr) +{ + std::list ok; + for (auto i : instr_list_) + { + if (!instr.count(i)) ok.emplace_back(i); + } + instr_list_ = std::move(ok); + for (auto i : instr) delete i; +} + +void BasicBlock::remove_instrs(const std::set& instr) +{ + std::list ok; + for (auto i : instr_list_) + { + if (!instr.count(i)) ok.emplace_back(i); + } + instr_list_ = std::move(ok); +} + std::string BasicBlock::print() { std::string bb_ir; bb_ir += this->get_name(); diff --git a/src/lightir/Function.cpp b/src/lightir/Function.cpp index be10832..00ce82e 100755 --- a/src/lightir/Function.cpp +++ b/src/lightir/Function.cpp @@ -121,7 +121,7 @@ std::string Function::print() { } else { for (auto arg : get_args()) { - if (&arg != &*get_args().begin()) + if (arg != get_args().front()) func_ir += ", "; func_ir += arg->print(); } diff --git a/src/lightir/Instruction.cpp b/src/lightir/Instruction.cpp index 9ea2788..22ef75b 100755 --- a/src/lightir/Instruction.cpp +++ b/src/lightir/Instruction.cpp @@ -368,4 +368,15 @@ PhiInst *PhiInst::create_phi(Type *ty, BasicBlock *bb, return new PhiInst(ty, vals, val_bbs, bb, name); } +std::vector> PhiInst::get_phi_pairs() const +{ + std::vector> res; + int ops = static_cast(get_num_operand()); + for (int i = 0; i < ops; i += 2) { + auto bb = dynamic_cast(this->get_operand(i + 1)); + res.emplace_back(this->get_operand(i), bb); + } + return res; +} + Names GLOBAL_INSTRUCTION_NAMES_{"op", "_" }; \ No newline at end of file diff --git a/src/lightir/User.cpp b/src/lightir/User.cpp index c7a2d7f..8c531e2 100755 --- a/src/lightir/User.cpp +++ b/src/lightir/User.cpp @@ -16,7 +16,7 @@ void User::set_operand(unsigned i, Value *v) { } void User::add_operand(Value *v) { - assert(v != nullptr && "bad use: add_operand(nullptr)"); + if (v == nullptr) return; v->add_use(this, static_cast(operands_.size())); operands_.push_back(v); } @@ -34,10 +34,14 @@ void User::remove_operand(unsigned idx) { assert(idx < operands_.size() && "remove_operand out of index"); // influence on other operands for (unsigned i = idx + 1; i < operands_.size(); ++i) { - operands_[i]->remove_use(this, i); - operands_[i]->add_use(this, i - 1); + if (operands_[i]) + { + operands_[i]->remove_use(this, i); + operands_[i]->add_use(this, i - 1); + } } // remove the designated operand - operands_[idx]->remove_use(this, idx); + if (operands_[idx]) + operands_[idx]->remove_use(this, idx); operands_.erase(operands_.begin() + idx); } diff --git a/src/lightir/Value.cpp b/src/lightir/Value.cpp index f41ec7a..99c9490 100755 --- a/src/lightir/Value.cpp +++ b/src/lightir/Value.cpp @@ -14,10 +14,12 @@ bool Value::set_name(const std::string& name) { } void Value::add_use(User *user, unsigned arg_no) { + if (user == nullptr) return; use_list_.emplace_back(user, arg_no); }; void Value::remove_use(User *user, unsigned arg_no) { + if (user == nullptr) return; auto target_use = Use(user, arg_no); use_list_.remove_if([&](const Use &use) { return use == target_use; }); } @@ -28,7 +30,8 @@ void Value::replace_all_use_with(Value *new_val) const return; while (!use_list_.empty()) { auto use = use_list_.begin(); - use->val_->set_operand(use->arg_no_, new_val); + auto val = use->val_; + if (val != nullptr) val->set_operand(use->arg_no_, new_val); } } @@ -38,6 +41,7 @@ void Value::replace_use_with_if(Value *new_val, return; for (auto iter = use_list_.begin(); iter != use_list_.end();) { auto &use = *iter++; + if (use.val_ == nullptr) continue; if (not should_replace(&use)) continue; use.val_->set_operand(use.arg_no_, new_val); diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index b22ccea..7f7f28e 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -6,4 +6,4 @@ add_library( LoopDetection.cpp LICM.cpp Mem2Reg.cpp -) \ No newline at end of file + PassManager.cpp) \ No newline at end of file diff --git a/src/passes/DeadCode.cpp b/src/passes/DeadCode.cpp index e9a224e..ed753df 100644 --- a/src/passes/DeadCode.cpp +++ b/src/passes/DeadCode.cpp @@ -1,36 +1,95 @@ #include "DeadCode.hpp" -#include "logging.hpp" + +#include +#include #include +#include "FuncInfo.hpp" +#include "logging.hpp" + // 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令 void DeadCode::run() { - bool changed{}; + bool changed; + func_info = new FuncInfo(m_); func_info->run(); do { changed = false; for (auto func : m_->get_functions()) { - changed |= clear_basic_blocks(func); + if (remove_bb_) changed |= clear_basic_blocks(func); mark(func); changed |= sweep(func); } } while (changed); - LOG_INFO << "dead code pass erased " << ins_count << " instructions"; + delete func_info; + func_info = nullptr; +} + +static void remove_phi_operand_if_in(PhiInst* inst, const std::unordered_set& in) +{ + int opc = static_cast(inst->get_num_operand()); + for (int i = opc - 1; i >= 0; i -= 2) + { + auto bb = dynamic_cast(inst->get_operand(i)); + if (in.count(bb)) + { + inst->remove_operand(i); + inst->remove_operand(i - 1); + } + } } bool DeadCode::clear_basic_blocks(Function *func) { - bool changed = 0; - std::vector to_erase; - for (auto bb : func->get_basic_blocks()) { - if(bb->get_pre_basic_blocks().empty() && bb != func->get_entry_block()) { - to_erase.push_back(bb); - changed = 1; + // 已经访问的基本块 + std::unordered_set visited; + // 还未访问的基本块 + std::queue toVisit; + toVisit.emplace(func->get_entry_block()); + visited.emplace(func->get_entry_block()); + while (!toVisit.empty()) + { + auto bb = toVisit.front(); + toVisit.pop(); + for (auto suc : bb->get_succ_basic_blocks()) + { + if (!visited.count(suc)) + { + visited.emplace(suc); + toVisit.emplace(suc); + } + } + } + + // 遍历后剩余的基本块不可达 + std::unordered_set erase_set; + std::list erase_list; + for (auto bb : func->get_basic_blocks()) + { + if (!visited.count(bb)) + { + erase_set.emplace(bb); + erase_list.emplace_back(bb); } } - for (auto bb : to_erase) { + + // 删除可达基本块中对不可达基本块中变量的 phi 引用 + // 例如 A -> B, B 中具有 phi [val , A], 则要将这一对删除 + // 当一个 phi 因为这个原因只剩下一对操作数时, 它可以被消除, 不过这里不管它 + for (auto i : func->get_basic_blocks()) + { + if (erase_set.count(i)) continue; + for (auto j : i->get_instructions()) + { + auto phi = dynamic_cast(j); + if (phi == nullptr) break; // 假定所有 phi 都在基本块指令的最前面,见 https://ustc-compiler-2025.github.io/homepage/exp_platform_intro/TA/#%E4%BD%BF%E7%94%A8%E4%B8%A4%E6%AE%B5%E5%8C%96-instruction-list + remove_phi_operand_if_in(phi, erase_set); + } + } + + for (auto bb : erase_list) { bb->erase_from_parent(); delete bb; } - return changed; + return !erase_list.empty(); } void DeadCode::mark(Function *func) { @@ -54,7 +113,7 @@ void DeadCode::mark(Function *func) { } } -void DeadCode::mark(Instruction *ins) { +void DeadCode::mark(const Instruction *ins) { for (auto op : ins->get_operands()) { auto def = dynamic_cast(op); if (def == nullptr) @@ -69,33 +128,26 @@ void DeadCode::mark(Instruction *ins) { } bool DeadCode::sweep(Function *func) { - std::unordered_set wait_del{}; + bool rm = false; // changed + std::unordered_set wait_del; for (auto bb : func->get_basic_blocks()) { - for (auto it = bb->get_instructions().begin(); - it != bb->get_instructions().end();) { - if (marked[*it]) { - ++it; - continue; - } else { - wait_del.insert(*it); - it++; - } + for (auto inst : bb->get_instructions()) { + if (marked[inst]) continue; + wait_del.emplace(inst); } + bb->get_instructions().remove_if([&wait_del](Instruction* i) -> bool {return wait_del.count(i); }); + if (!wait_del.empty()) rm = true; + wait_del.clear(); } - for (auto inst : wait_del) - inst->remove_all_operands(); - for (auto inst : wait_del) - inst->get_parent()->erase_instr(inst); - ins_count += wait_del.size(); - return not wait_del.empty(); // changed + return rm; } -bool DeadCode::is_critical(Instruction *ins) { +bool DeadCode::is_critical(Instruction *ins) const { // 对纯函数的无用调用也可以在删除之列 if (ins->is_call()) { auto call_inst = dynamic_cast(ins); auto callee = dynamic_cast(call_inst->get_operand(0)); - if (func_info->is_pure_function(callee)) + if (func_info->is_pure(callee)) return false; return true; } @@ -106,15 +158,15 @@ bool DeadCode::is_critical(Instruction *ins) { return false; } -void DeadCode::sweep_globally() { +void DeadCode::sweep_globally() const { std::vector unused_funcs; std::vector unused_globals; for (auto f_r : m_->get_functions()) { - if (f_r->get_use_list().size() == 0 and f_r->get_name() != "main") + if (f_r->get_use_list().empty() and f_r->get_name() != "main") unused_funcs.push_back(f_r); } for (auto glob_var_r : m_->get_global_variable()) { - if (glob_var_r->get_use_list().size() == 0) + if (glob_var_r->get_use_list().empty()) unused_globals.push_back(glob_var_r); } // changed |= unused_funcs.size() or unused_globals.size(); diff --git a/src/passes/Dominators.cpp b/src/passes/Dominators.cpp index 22b6375..232f24c 100644 --- a/src/passes/Dominators.cpp +++ b/src/passes/Dominators.cpp @@ -1,26 +1,35 @@ #include "Dominators.hpp" -#include "BasicBlock.hpp" -#include "Function.hpp" + #include #include -/** - * @brief 支配器分析的入口函数 - * - * 遍历模块中的所有函数,对每个非声明的函数执行支配关系分析。 - */ -void Dominators::run() { - for(auto f : m_->get_functions()) { - if(f->is_declaration()) - continue; - run_on_func(f); - } -} +#include "BasicBlock.hpp" +#include "Function.hpp" + +// TODO README + +// 一些注意事项: +// +// 1. Dominators 是针对特定 Function 的分析 Pass +// 因此代码中的所有基本块都属于同一个函数 +// 函数至少有一个入口块,你不用考虑没有基本块的情况 +// +// 2. 入口块不一定支配函数的所有基本块 +// 例如 +// if(xxx) +// return; +// else +// return; +// while(xxx) +// xxx +// 的 while 附近基本块就是不可达基本块 +// 你需要考虑你的支配树算法能不能处理这种情况, +// 如果不能,你可以在用到 Dominators 的 Pass 前面跑一个 DeadCode +// DeadCode 有选项可以去除不可达基本块 /** * @brief 对单个函数执行支配关系分析 - * @param f 要分析的函数 - * + * * 该函数执行完整的支配关系分析流程: * 1. 初始化数据结构 * 2. 创建反向后序遍历序列 @@ -29,19 +38,19 @@ void Dominators::run() { * 5. 构建支配树的后继关系 * 6. 创建支配树的DFS序 */ -void Dominators::run_on_func(Function *f) { +void Dominators::run() { dom_post_order_.clear(); dom_dfs_order_.clear(); - for(auto bb : f->get_basic_blocks()) { - idom_.insert({bb, nullptr}); - dom_frontier_.insert({bb, {}}); - dom_tree_succ_blocks_.insert({bb, {}}); + for (auto bb : f_->get_basic_blocks()) { + idom_.insert({ bb, nullptr }); + dom_frontier_.insert({ bb, {} }); + dom_tree_succ_blocks_.insert({ bb, {} }); } - create_reverse_post_order(f); - create_idom(f); - create_dominance_frontier(f); - create_dom_tree_succ(f); - create_dom_dfs_order(f); + create_reverse_post_order(); + create_idom(); + create_dominance_frontier(); + create_dom_tree_succ(); + create_dom_dfs_order(); } /** @@ -53,7 +62,8 @@ void Dominators::run_on_func(Function *f) { * 该函数使用后序号来查找两个节点的最近公共支配者。 * 通过在支配树上向上遍历直到找到交点。 */ -BasicBlock *Dominators::intersect(BasicBlock *b1, BasicBlock *b2) { +BasicBlock *Dominators::intersect(BasicBlock *b1, const BasicBlock *b2) const +{ while (b1 != b2) { while (get_post_order(b1) < get_post_order(b2)) { b1 = get_idom(b1); @@ -67,14 +77,13 @@ BasicBlock *Dominators::intersect(BasicBlock *b1, BasicBlock *b2) { /** * @brief 创建函数的反向后序遍历序列 - * @param f 要处理的函数 * * 通过DFS遍历CFG来构建基本块的后序遍历序列。 * 这个序列用于后续的支配关系分析。 */ -void Dominators::create_reverse_post_order(Function *f) { - BBSet visited; - dfs(f->get_entry_block(), visited); +void Dominators::create_reverse_post_order() { + std::set visited; + dfs(f_->get_entry_block(), visited); } /** @@ -97,47 +106,88 @@ void Dominators::dfs(BasicBlock *bb, std::set &visited) { /** * @brief 计算所有基本块的直接支配者(immediate dominator) - * @param f 要分析的函数 * - * 使用迭代算法计算每个基本块的直接支配者: - * 1. 将入口块的直接支配者设置为自身 - * 2. 重复遍历所有基本块,更新它们的直接支配者 - * 3. 当没有变化时算法终止 + * 使用迭代算法计算每个基本块的直接支配者, 见课程主页 Dominators 一节 */ -void Dominators::create_idom(Function *f) { - // TODO 分析得到 f 中各个基本块的 idom - throw "Unimplemented create_idom"; +void Dominators::create_idom() { + // 可能有用的数据结构 + // post_order_vec_ vector, 其中基本块按照逆后续排列 + // post_order_ map, 每个基本块在 post_order_vec_ 中的索引 + // 可能有用的函数 + // intersect(BasicBlock *, BasicBlock *) 寻找两个基本块在支配树上的最近祖先 + // 需要填写 + // idom_ map 直接支配者, idom_[a] = b 代表 b 直接支配 a (或者 idom_[a] = a 代表 a 没有直接支配者) + + // 代表基本块的直接支配者是否已经确定, 不会在迭代中改变 (默认初始化为 false) + bool* already_determined = new bool[post_order_vec_.size()]{}; + + int bb_count = static_cast(post_order_vec_.size()); + for (int i = 0; i < bb_count; i++) + { + auto bb = post_order_vec_[i]; + // TODO 填写可以直接确定直接支配者, 无需参与迭代的基本块的 idom_ 和 already_determined + throw "Unimplemented create_idom"; + } + + bool changed; + do + { + changed = false; + for (int i = 0; i < bb_count; i++) + { + if (already_determined[i]) continue; + auto bb = post_order_vec_[i]; + // TODO 更新基本块 bb 的 idom_, 设置 changed(如果 idom_ 有变化) + throw "Unimplemented create_idom"; + } + } while (changed); + + delete[] already_determined; } /** * @brief 计算所有基本块的支配边界(dominance frontier) - * @param f 要分析的函数 * * 对于每个有多个前驱的基本块B: * 从每个前驱P开始,沿着支配树向上遍历直到遇到B的直接支配者, * 将B加入路径上所有节点的支配边界中。 */ -void Dominators::create_dominance_frontier(Function *f) { - // TODO 分析得到 f 中各个基本块的支配边界集合 - throw "Unimplemented create_dominance_frontier"; +void Dominators::create_dominance_frontier() { + // 可能有用的数据结构 + // post_order_vec_ vector, 其中基本块按照逆后续排列 + // post_order_ map, 每个基本块在 post_order_vec_ 中的索引 + // idom_ map 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent + // (或者 idom_[a] = a 代表 a 没有直接支配者) + // 需要填写 + // dom_frontier_ map> 支配边界 + int bb_count = static_cast(post_order_vec_.size()); + for (int i = 0; i < bb_count; i++) + { + auto bb = post_order_vec_[i]; + // TODO 计算 bb 的支配边界集合, 填入 dom_frontier_ + throw "Unimplemented create_dominance_frontier"; + } } /** * @brief 构建支配树的后继关系 - * @param f 要处理的函数 * * 基于已计算的直接支配者关系,构建支配树的子节点关系。 * 如果A是B的直接支配者,则B是A在支配树上的后继。 */ -void Dominators::create_dom_tree_succ(Function *f) { - // TODO 分析得到 f 中各个基本块的支配树后继 +void Dominators::create_dom_tree_succ() { + // 可能有用的数据结构 + // idom_ map 直接支配者, idom_[a] = b 代表 b 直接支配 a, 支配树中 b 是 a 的 parent + // 需要填写 + // dom_tree_succ_blocks_ map> 支配树中后继(孩子)节点 + + // TODO 分析得到 f_ 中各个基本块的支配树后继 throw "Unimplemented create_dom_tree_succ"; } /** * @brief 为支配树创建深度优先搜索序 - * @param f 要处理的函数 * * 该函数通过深度优先搜索遍历支配树,为每个基本块分配两个序号: * 1. dom_tree_L_:记录DFS首次访问该节点的时间戳 @@ -150,8 +200,8 @@ void Dominators::create_dom_tree_succ(Function *f) { * 这些序号和顺序可用于快速判断支配关系: * 如果节点A支配节点B,则A的L值小于B的L值,且A的R值大于B的R值 */ -void Dominators::create_dom_dfs_order(Function *f) { - // 分析得到 f 中各个基本块的支配树上的dfs序L,R +void Dominators::create_dom_dfs_order() { + // 分析得到 f_ 中各个基本块的支配树上的dfs序L,R unsigned int order = 0; std::function dfs = [&](BasicBlock *bb) { dom_tree_L_[bb] = ++ order; @@ -161,33 +211,33 @@ void Dominators::create_dom_dfs_order(Function *f) { } dom_tree_R_[bb] = order; }; - dfs(f->get_entry_block()); + dfs(f_->get_entry_block()); dom_post_order_ = std::vector(dom_dfs_order_.rbegin(), dom_dfs_order_.rend()); } /** * @brief 打印函数的直接支配关系 - * @param f 要打印的函数 * * 该函数以可读格式打印函数中所有基本块的直接支配者(immediate dominator)。 * 输出格式为: * 基本块名: 其直接支配者名 * 如果基本块没有直接支配者(如入口块),则显示"null"。 */ -void Dominators::print_idom(Function *f) { - f->get_parent()->set_print_name(); +void Dominators::print_idom() const +{ + f_->get_parent()->set_print_name(); int counter = 0; std::map bb_id; - for (auto bb : f->get_basic_blocks()) { + for (auto bb : f_->get_basic_blocks()) { if (bb->get_name().empty()) bb_id[bb] = "bb" + std::to_string(counter); else bb_id[bb] = bb->get_name(); counter++; } - printf("Immediate dominance of function %s:\n", f->get_name().c_str()); - for (auto bb : f->get_basic_blocks()) { + printf("Immediate dominance of function %s:\n", f_->get_name().c_str()); + for (auto bb : f_->get_basic_blocks()) { std::string output; output = bb_id[bb] + ": "; if (get_idom(bb)) { @@ -201,26 +251,25 @@ void Dominators::print_idom(Function *f) { /** * @brief 打印函数的支配边界信息 - * @param f 要打印的函数 * * 该函数以可读格式打印函数中所有基本块的支配边界(dominance frontier)。 * 输出格式为: * 基本块名: 支配边界中的基本块列表 * 如果基本块没有支配边界,则显示"null"。 */ -void Dominators::print_dominance_frontier(Function *f) { - f->get_parent()->set_print_name(); +void Dominators::print_dominance_frontier() { + f_->get_parent()->set_print_name(); int counter = 0; std::map bb_id; - for (auto bb : f->get_basic_blocks()) { + for (auto bb : f_->get_basic_blocks()) { if (bb->get_name().empty()) bb_id[bb] = "bb" + std::to_string(counter); else bb_id[bb] = bb->get_name(); counter++; } - printf("Dominance Frontier of function %s:\n", f->get_name().c_str()); - for (auto bb : f->get_basic_blocks()) { + printf("Dominance Frontier of function %s:\n", f_->get_name().c_str()); + for (auto bb : f_->get_basic_blocks()) { std::string output; output = bb_id[bb] + ": "; if (get_dominance_frontier(bb).empty()) { @@ -242,21 +291,18 @@ void Dominators::print_dominance_frontier(Function *f) { /** * @brief 将函数的控制流图(CFG)导出为图形文件 - * @param f 要导出的函数 * * 该函数生成函数的控制流图的DOT格式描述,并使用graphviz将其转换为PNG图像。 * 生成两个文件: * - {函数名}_cfg.dot:DOT格式的图形描述 * - {函数名}_cfg.png:可视化的控制流图 */ -void Dominators::dump_cfg(Function *f) +void Dominators::dump_cfg() const { - f->get_parent()->set_print_name(); - if(f->is_declaration()) - return; + f_->get_parent()->set_print_name(); std::vector edge_set; bool has_edges = false; - for (auto bb : f->get_basic_blocks()) { + for (auto bb : f_->get_basic_blocks()) { auto succ_blocks = bb->get_succ_basic_blocks(); if(!succ_blocks.empty()) has_edges = true; @@ -265,9 +311,9 @@ void Dominators::dump_cfg(Function *f) } } std::string digraph = "digraph G {\n"; - if (!has_edges && !f->get_basic_blocks().empty()) { + if (!has_edges && !f_->get_basic_blocks().empty()) { // 如果没有边且至少有一个基本块,添加一个自环以显示唯一的基本块 - auto bb = f->get_basic_blocks().front(); + auto bb = f_->get_basic_blocks().front(); digraph += '\t' + bb->get_name() + ";\n"; } else { for (auto &edge : edge_set) { @@ -276,32 +322,31 @@ void Dominators::dump_cfg(Function *f) } digraph += "}\n"; std::ofstream file_output; - file_output.open(f->get_name() + "_cfg.dot", std::ios::out); + file_output.open(f_->get_name() + "_cfg.dot", std::ios::out); file_output << digraph; file_output.close(); - std::string dot_cmd = "dot -Tpng " + f->get_name() + "_cfg.dot" + " -o " + f->get_name() + "_cfg.png"; + std::string dot_cmd = "dot -Tpng " + f_->get_name() + "_cfg.dot" + " -o " + f_->get_name() + "_cfg.png"; std::system(dot_cmd.c_str()); } /** * @brief 将函数的支配树导出为图形文件 - * @param f 要导出的函数 * * 该函数生成函数的支配树的DOT格式描述,并使用graphviz将其转换为PNG图像。 * 生成两个文件: * - {函数名}_dom_tree.dot:DOT格式的图形描述 * - {函数名}_dom_tree.png:可视化的支配树 */ -void Dominators::dump_dominator_tree(Function *f) +void Dominators::dump_dominator_tree() { - f->get_parent()->set_print_name(); - if(f->is_declaration()) + f_->get_parent()->set_print_name(); + if(f_->is_declaration()) return; std::vector edge_set; bool has_edges = false; // 用于检查是否有边存在 - for (auto b : f->get_basic_blocks()) { + for (auto b : f_->get_basic_blocks()) { if (idom_.find(b) != idom_.end() && idom_[b] != b) { edge_set.push_back('\t' + idom_[b]->get_name() + "->" + b->get_name() + ";\n"); has_edges = true; // 如果存在支配边,标记为 true @@ -310,9 +355,9 @@ void Dominators::dump_dominator_tree(Function *f) std::string digraph = "digraph G {\n"; - if (!has_edges && !f->get_basic_blocks().empty()) { + if (!has_edges && !f_->get_basic_blocks().empty()) { // 如果没有边且至少有一个基本块,直接添加该块以显示它 - BasicBlock* b = f->get_basic_blocks().front(); + BasicBlock* b = f_->get_basic_blocks().front(); digraph += '\t' + b->get_name() + ";\n"; } else { for (auto &edge : edge_set) { @@ -323,10 +368,10 @@ void Dominators::dump_dominator_tree(Function *f) digraph += "}\n"; std::ofstream file_output; - file_output.open(f->get_name() + "_dom_tree.dot", std::ios::out); + file_output.open(f_->get_name() + "_dom_tree.dot", std::ios::out); file_output << digraph; file_output.close(); - std::string dot_cmd = "dot -Tpng " + f->get_name() + "_dom_tree.dot" + " -o " + f->get_name() + "_dom_tree.png"; + std::string dot_cmd = "dot -Tpng " + f_->get_name() + "_dom_tree.dot" + " -o " + f_->get_name() + "_dom_tree.png"; std::system(dot_cmd.c_str()); } \ No newline at end of file diff --git a/src/passes/FuncInfo.cpp b/src/passes/FuncInfo.cpp index 9eccf59..501526d 100644 --- a/src/passes/FuncInfo.cpp +++ b/src/passes/FuncInfo.cpp @@ -1,109 +1,258 @@ #include "FuncInfo.hpp" + +#include +#include + #include "Function.hpp" +#include "logging.hpp" -void FuncInfo::run() { - for (auto func : m_->get_functions()) { - trivial_mark(func); - if (not is_pure[func]) - worklist.push_back(func); - } - while (worklist.empty() == false) { - auto now = worklist.front(); - worklist.pop_front(); - process(now); - } - log(); +void FuncInfo::UseMessage::add(Value* val) +{ + auto g = dynamic_cast(val); + if (g != nullptr) + { + globals_.emplace(g); + return; + } + auto arg = dynamic_cast(val); + arguments_.emplace(arg); } -void FuncInfo::log() { - for (auto it : is_pure) { - LOG_INFO << it.first->get_name() << " is pure? " << it.second; - } +bool FuncInfo::UseMessage::have(Value* val) const +{ + auto g = dynamic_cast(val); + if (g != nullptr) return globals_.count(g); + return arguments_.count(dynamic_cast(val)); } -// 有 store 操作的函数非纯函数来处理 -void FuncInfo::trivial_mark(Function *func) { - if (func->is_declaration() or func->get_name() == "main") { - is_pure[func] = false; - return; - } - // 只要传入数组,都作为非纯函数处理 - for (auto it = func->get_function_type()->param_begin(); - it != func->get_function_type()->param_end(); ++it) { - auto arg_type = *it; - if (arg_type->is_integer_type() == false and - arg_type->is_float_type() == false) { - is_pure[func] = false; - return; - } - } - for (auto bb : func->get_basic_blocks()) - for (auto inst : bb->get_instructions()) { - if (is_side_effect_inst(inst)) { - is_pure[func] = false; - return; - } - } - is_pure[func] = true; +bool FuncInfo::UseMessage::empty() const +{ + return globals_.empty() && arguments_.empty(); } -void FuncInfo::process(Function *func) { - for (auto &use : func->get_use_list()) { - LOG_INFO << use.val_->print() << " uses func: " << func->get_name(); - if (auto inst = dynamic_cast(use.val_)) { - auto func = (inst->get_parent()->get_parent()); - if (is_pure[func]) { - is_pure[func] = false; - worklist.push_back(func); - } - } else - LOG_WARNING << "Value besides instruction uses a function"; - } +void FuncInfo::run() +{ + std::unordered_map val_to_var; + // 计算对全局变量的 load/store + for (auto glob : m_->get_global_variable()) + cal_val_2_var(glob, val_to_var); + std::queue worklist; + std::unordered_set in_worklist; + // 计算对函数参数的 load/store + // 本质上来说,对局部变量的 load/store 不会在函数外产生副作用,它也不会被用作 func_info 的信息 + for (auto func : m_->get_functions()) + { + if (func->is_declaration()) continue; + use_libs[func] = false; + worklist.emplace(func); + in_worklist.emplace(func); + for (auto arg : func->get_args()) + { + if (arg->get_type()->is_pointer_type()) + { + cal_val_2_var(arg, val_to_var); + } + } + } + + // 处理函数相互调用导致的隐式 load/store + while (!worklist.empty()) + { + // 被调用的函数 + auto calleeF = worklist.front(); + worklist.pop(); + in_worklist.erase(calleeF); + for (auto& use : calleeF->get_use_list()) + { + // 函数调用指令 + auto inst = dynamic_cast(use.val_); + // 调用 f 的函数 + auto callerF = inst->get_parent()->get_parent(); + auto& callerLoads = loads[callerF]; + auto& calleeLoads = loads[calleeF]; + auto& callerStores = stores[callerF]; + auto& calleeStores = stores[calleeF]; + // caller 的 load store 数量 + auto caller_old_load_store_count = callerLoads.globals_.size() + callerLoads.arguments_.size() + + callerStores.globals_.size() + callerStores.arguments_.size(); + // caller 同时 load 了 callee load 的全局变量 + for (auto i : calleeLoads.globals_) callerLoads.globals_.emplace(i); + // caller 同时 store 了 callee store 的全局变量 + for (auto i : calleeStores.globals_) callerStores.globals_.emplace(i); + auto& ops = inst->get_operands(); + // 形式参数 + for (auto calleArg : calleeF->get_args()) + { + if (calleArg->get_type()->is_pointer_type()) + { + // 传入的实参 + auto trueArg = ops[calleArg->get_arg_no() + 1]; + // 实参来自哪个临时变量 + auto trueArgVar = val_to_var.find(trueArg); + // 来自局部变量,跳过,因为对局部变量的 load/store 不会在函数外产生副作用 + if (trueArgVar == val_to_var.end()) continue; + auto trace = trueArgVar->second; + // 添加 load + if (calleeLoads.have(calleArg)) callerLoads.add(trace); + // 添加 store + if (calleeStores.have(calleArg)) callerStores.add(trace); + } + } + // caller f 的 load/store 产生了变化,可能会影响其它调用 f 的函数的 load/store + if (callerLoads.globals_.size() + callerLoads.arguments_.size() + callerStores.globals_.size() + + callerStores.arguments_.size() != caller_old_load_store_count) + { + if (!in_worklist.count(callerF)) + { + in_worklist.emplace(callerF); + worklist.emplace(callerF); + } + } + } + } + + // 没有 load/store,但是调用了库函数的函数是非纯函数(因为库函数是 IO) + for (auto& func : m_->get_functions()) + { + if (func->is_declaration()) + { + for (auto& use : func->get_use_list()) + { + auto call = dynamic_cast(use.val_); + use_libs[call->get_parent()->get_parent()] = true; + } + } + worklist.emplace(func); + in_worklist.emplace(func); + } + while (!worklist.empty()) + { + auto f = worklist.front(); + worklist.pop(); + in_worklist.erase(f); + if (use_libs[f]) + for (auto& use : f->get_use_list()) + { + auto inst = dynamic_cast(use.val_); + auto cf = inst->get_parent()->get_parent(); + if (!use_libs[cf]) + { + use_libs[cf] = true; + if (!in_worklist.count(cf)) + { + in_worklist.emplace(cf); + worklist.emplace(cf); + } + } + } + } + log(); } -// 对局部变量进行 store 没有副作用 -bool FuncInfo::is_side_effect_inst(Instruction *inst) { - if (inst->is_store()) { - if (is_local_store(dynamic_cast(inst))) - return false; - return true; - } - if (inst->is_load()) { - if (is_local_load(dynamic_cast(inst))) - return false; - return true; - } - // call 指令的副作用会在后续 bfs 中计算 - return false; +Value* FuncInfo::store_ptr(const StoreInst* st) +{ + return trace_ptr(st->get_operand(1)); } -bool FuncInfo::is_local_load(LoadInst *inst) { - auto addr = - dynamic_cast(get_first_addr(inst->get_operand(0))); - if (addr and addr->is_alloca()) - return true; - return false; +Value* FuncInfo::load_ptr(const LoadInst* ld) +{ + return trace_ptr(ld->get_operand(0)); } -bool FuncInfo::is_local_store(StoreInst *inst) { - auto addr = dynamic_cast(get_first_addr(inst->get_lval())); - if (addr and addr->is_alloca()) - return true; - return false; +std::unordered_set FuncInfo::get_stores(const CallInst* call) +{ + auto func = call->get_operand(0)->as(); + if (func->is_declaration()) return {}; + std::unordered_set ret; + for (auto i : stores[func].globals_) ret.emplace(i); + for (auto arg : stores[func].arguments_) + { + int arg_no = static_cast(arg->get_arg_no()); + auto in = call->get_operand(arg_no + 1); + ret.emplace(trace_ptr(in)); + } + return ret; } -Value *FuncInfo::get_first_addr(Value *val) { - if (auto inst = dynamic_cast(val)) { - if (inst->is_alloca()) - return inst; - if (inst->is_gep()) - return get_first_addr(inst->get_operand(0)); - if (inst->is_load()) - return val; - LOG_WARNING << "FuncInfo: try to determine addr in operands"; - for (auto op : inst->get_operands()) { - if (op->get_type()->is_pointer_type()) - return get_first_addr(op); - } - } - return val; + +void FuncInfo::log() const +{ + for (auto it : use_libs) + { + LOG_INFO << it.first->get_name() << " is pure? " << it.second; + } +} + +void FuncInfo::cal_val_2_var(Value* var, std::unordered_map& val_2_var) +{ + auto global = dynamic_cast(var); + if (global != nullptr && global->is_const()) return; + std::unordered_set handled; + std::queue wait_to_handle; + handled.emplace(var); + val_2_var[var] = var; + wait_to_handle.emplace(var); + while (!wait_to_handle.empty()) + { + Value* v = wait_to_handle.front(); + wait_to_handle.pop(); + for (auto& use : v->get_use_list()) + { + auto inst = dynamic_cast(use.val_); + auto f = inst->get_parent()->get_parent(); + switch (inst->get_instr_type()) + { + case Instruction::load: + { + loads[f].add(var); + break; + } + case Instruction::store: + { + stores[f].add(var); + break; + } + case Instruction::getelementptr: + case Instruction::phi: + { + if (!handled.count(inst)) + { + handled.emplace(inst); + val_2_var[inst] = var; + wait_to_handle.emplace(inst); + } + break; + } + // case Instruction::call: + // { + // 如果遇到不能确定行为的库函数,需要指定其其对参数同时进行了读写,目前这里遇不到 + // auto callF = dynamic_cast(inst->get_operand(0)); + // if (callF->is_declaration()) + // { + // stores[f].add(var); + // loads[f].add(var); + // } + // break; + // } + default: + break; + } + } + } +} + +Value* FuncInfo::trace_ptr(Value* val) +{ + assert(val != nullptr); + if (dynamic_cast(val) != nullptr + || dynamic_cast(val) != nullptr + || dynamic_cast(val) != nullptr + ) + return val; + auto inst = dynamic_cast(val); + assert(inst != nullptr); + if (inst->is_gep()) return trace_ptr(inst->get_operand(0)); + // 这意味着栈里面存在指针,你需要运行 Mem2Reg;或者你给 trace_ptr 传入了非指针参数 + assert(!inst->is_load()); + assert(inst->is_alloca()); + return inst; } diff --git a/src/passes/LICM.cpp b/src/passes/LICM.cpp index fcf316b..87f0f81 100644 --- a/src/passes/LICM.cpp +++ b/src/passes/LICM.cpp @@ -1,31 +1,36 @@ +#include "LICM.hpp" + +#include +#include + #include "BasicBlock.hpp" -#include "Constant.hpp" #include "Function.hpp" -#include "GlobalVariable.hpp" #include "Instruction.hpp" -#include "LICM.hpp" #include "PassManager.hpp" -#include -#include -#include /** * @brief 循环不变式外提Pass的主入口函数 * */ -void LoopInvariantCodeMotion::run() { - - loop_detection_ = std::make_unique(m_); - loop_detection_->run(); - func_info_ = std::make_unique(m_); - func_info_->run(); - for (auto &loop : loop_detection_->get_loops()) { - is_loop_done_[loop] = false; - } - - for (auto &loop : loop_detection_->get_loops()) { - traverse_loop(loop); - } +void LoopInvariantCodeMotion::run() +{ + func_info_ = new FuncInfo(m_); + func_info_->run(); + for (auto func : m_->get_functions()) + { + if (func->is_declaration()) continue; + loop_detection_ = new LoopDetection(func); + loop_detection_->run(); + for (auto loop : loop_detection_->get_loops()) + { + // 遍历处理顶层循环 + if (loop->get_parent() == nullptr) traverse_loop(loop); + } + delete loop_detection_; + loop_detection_ = nullptr; + } + delete func_info_; + func_info_ = nullptr; } /** @@ -33,102 +38,147 @@ void LoopInvariantCodeMotion::run() { * @param loop 当前要处理的循环 * */ -void LoopInvariantCodeMotion::traverse_loop(std::shared_ptr loop) { - if (is_loop_done_[loop]) { - return; - } - is_loop_done_[loop] = true; - for (auto &sub_loop : loop->get_sub_loops()) { - traverse_loop(sub_loop); - } - run_on_loop(loop); +void LoopInvariantCodeMotion::traverse_loop(Loop* loop) +{ + // 先外层再内层,这样不用在插入 preheader 后更改循环 + run_on_loop(loop); + for (auto sub_loop : loop->get_sub_loops()) + { + traverse_loop(sub_loop); + } } +// TODO: 收集并返回循环 store 过的变量 +// 例如 +// %a = alloca ... +// %b = getelementptr %a ... +// store ... %b +// 则你应该返回 %a 而非 %b +std::unordered_set LoopInvariantCodeMotion::collect_loop_store_vars(Loop* loop) +{ + // 可能用到 + // FuncInfo::store_ptr, FuncInfo::get_stores + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); +} + +// TODO: 收集并返回循环中的所有指令 +std::vector LoopInvariantCodeMotion::collect_insts(Loop* loop) +{ + 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( - std::shared_ptr loop, - std::set &loop_instructions, - std::set &updated_global, - bool &contains_impure_call) { - - throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); + Loop* loop, + std::set& loop_instructions, + std::set& updated_global, + bool& contains_impure_call) +{ + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); } +enum InstructionType: std::uint8_t +{ + UNKNOWN, VARIANT, INVARIANT +}; + /** * @brief 对单个循环执行不变式外提优化 * @param loop 要优化的循环 * */ -void LoopInvariantCodeMotion::run_on_loop(std::shared_ptr loop) { - std::set loop_instructions; - std::set updated_global; - bool contains_impure_call = false; - collect_loop_info(loop, loop_instructions, updated_global, contains_impure_call); - - std::vector loop_invariant; - - - // TODO: 识别循环不变式指令 - // - // - 如果指令已被标记为不变式则跳过 - // - 跳过 store、ret、br、phi 等指令与非纯函数调用 - // - 特殊处理全局变量的 load 指令 - // - 检查指令的所有操作数是否都是循环不变的 - // - 如果有新的不变式被添加则注意更新 changed 标志,继续迭代 - - bool changed; - do { - changed = false; - - throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); - - } while (changed); - - if (loop->get_preheader() == nullptr) { - loop->set_preheader( - BasicBlock::create(m_, "", loop->get_header()->get_parent())); - } - - if (loop_invariant.empty()) - return; - - // insert preheader - auto preheader = loop->get_preheader(); - - // TODO: 更新 phi 指令 - for (auto phi_inst_ : loop->get_header()->get_instructions()) { - if (phi_inst_->get_instr_type() != Instruction::phi) - break; - - throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); - } - - // TODO: 用跳转指令重构控制流图 - // 将所有非 latch 的 header 前驱块的跳转指向 preheader - // 并将 preheader 的跳转指向 header - // 注意这里需要更新前驱块的后继和后继的前驱 - std::vector pred_to_remove; - for (auto pred : loop->get_header()->get_pre_basic_blocks()) { - throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); - } - - for (auto pred : pred_to_remove) { - loop->get_header()->remove_pre_basic_block(pred); - } - - // TODO: 外提循环不变指令 - throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); - - // insert preheader br to header - BranchInst::create_br(loop->get_header(), preheader); - - // insert preheader to parent loop - if (loop->get_parent() != nullptr) { - loop->get_parent()->add_block(preheader); - } +void LoopInvariantCodeMotion::run_on_loop(Loop* loop) +{ + // 循环 store 过的变量 + std::unordered_set loop_stores_var = collect_loop_store_vars(loop); + // 循环中的所有指令 + std::vector instructions = collect_insts(loop); + int insts_count = static_cast(instructions.size()); + // 循环的所有基本块 + std::unordered_set bbs; + for (auto i : loop->get_blocks()) bbs.emplace(i); + // val 是否在循环内定义,可以当成函数进行调用 + auto is_val_in_loop = [&bbs](Value* val)->bool + { + auto inst = dynamic_cast(val); + if (inst == nullptr) return true; + return bbs.count(inst->get_parent()); + }; + // inst_type[i] 代表 instructions[i] 是循环变量(每次循环都会变)/ 循环不变量 还是 不知道 + std::vector inst_type; + inst_type.resize(insts_count); + + // 遍历后是不是还有指令不知道 InstructionType + bool have_inst_can_not_decide; + // 是否存在 invariant + bool have_invariant = false; + do + { + have_inst_can_not_decide = false; + for (int i = 0; i < insts_count; i++) + { + Instruction* inst = instructions[i]; + InstructionType type = inst_type[i]; + if (type != UNKNOWN) continue; + // 可能有用的函数 + // FuncInfo::load_ptr + + // TODO: 识别循环不变式指令 + // - 将 store、ret、br、phi 等指令与非纯函数调用标记为 VARIANT + // - 如果 load 指令加载的变量是循环 store 过的变量,标记为 VARIANT + // - 如果指令有 VARIANT 操作数,标记为 VARIANT + // - 如果指令所有操作数都是 INVARIANT (或者不在循环内),标记为 INVARIANT, 设置 have_invariant + // - 否则设置 have_inst_can_not_decide + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); + } + } + while (have_inst_can_not_decide); + + if (!have_invariant) return; + + auto header = loop->get_header(); + + if (header->get_pre_basic_blocks().size() > 1 || header->get_pre_basic_blocks().front()->get_succ_basic_blocks().size() > 1) + { + // 插入 preheader + auto bb = BasicBlock::create(m_, "", loop->get_header()->get_parent()); + loop->set_preheader(bb); + + for (auto phi : loop->get_header()->get_instructions()) + { + if (phi->get_instr_type() != Instruction::phi) break; + // TODO: 分裂 phi 指令 + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); + } + + // TODO: 维护 bb, header, 与 header 前驱块的基本块关系 + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); + + bb->add_instruction(BranchInst::create_br(header, bb)); + + // 若你想维护 LoopDetection 在 LICM 后保持正确 + // auto loop2 = loop->get_parent(); + // while (loop2 != nullptr) + // { + // loop2->get_parent()->add_block(bb); + // loop2 = loop2->get_parent(); + // } + } + else loop->set_preheader(header->get_pre_basic_blocks().front()); + + // insert preheader + auto preheader = loop->get_preheader(); + + auto terminator = preheader->get_instructions().back(); + preheader->get_instructions().pop_back(); + + // TODO: 外提循环不变指令 + throw std::runtime_error("Lab4: 你有一个TODO需要完成!"); + + preheader->add_instruction(terminator); } - diff --git a/src/passes/LoopDetection.cpp b/src/passes/LoopDetection.cpp index 2a7edae..d9a27ac 100644 --- a/src/passes/LoopDetection.cpp +++ b/src/passes/LoopDetection.cpp @@ -1,25 +1,57 @@ #include "LoopDetection.hpp" + #include "Dominators.hpp" -#include -/** - * @brief 循环检测Pass的主入口函数 - * - * 该函数执行以下步骤: - * 1. 创建支配树分析实例 - * 2. 遍历模块中的所有函数 - * 3. 对每个非声明函数执行循环检测 - * 4. 最后打印检测结果 - */ +using std::set; +using std::vector; +using std::map; + +LoopDetection::~LoopDetection() +{ + for (auto loop : loops_) delete loop; +} + + /** + * @brief 对单个函数执行循环检测 + * + * 该函数通过以下步骤检测循环: + * 1. 创建支配树分析实例 + * 2. 运行支配树分析 + * 3. 按支配树后序遍历所有基本块 + * 4. 对每个块,检查其前驱是否存在回边 + * 5. 如果存在回边,创建新的循环并: + * - 设置循环header + * - 添加latch节点 + * - 发现循环体和子循环 + * 6. 最后打印检测结果 + */ void LoopDetection::run() { - dominators_ = std::make_unique(m_); - for (auto f : m_->get_functions()) { - if (f->is_declaration()) + dominators_ = new Dominators(f_); + dominators_->run(); + for (auto bb : dominators_->get_dom_post_order()) { + std::set latches; + for (auto pred : bb->get_pre_basic_blocks()) { + if (dominators_->is_dominate(bb, pred)) { + // pred is a back edge + // pred -> bb , pred is the latch node + latches.insert(pred); + } + } + if (latches.empty()) { continue; - func_ = f; - run_on_func(f); + } + // create loop + auto loop = new Loop(bb); + bb_to_loop_[bb] = loop; + // add latch nodes + for (auto latch : latches) { + loop->add_latch(latch); + } + loops_.push_back(loop); + discover_loop_and_sub_loops(bb, latches, loop); } print(); + delete dominators_; } /** @@ -28,8 +60,7 @@ void LoopDetection::run() { * @param latches 循环的回边终点(latch)集合 * @param loop 当前正在处理的循环对象 */ -void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, - std::shared_ptr loop) { +void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, std::set&latches, Loop* loop) { // TODO List: // 1. 初始化工作表,将所有latch块加入 // 2. 实现主循环逻辑 @@ -37,14 +68,14 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, // 4. 处理已属于其他循环的节点 // 5. 建立正确的循环嵌套关系 - BBvec work_list = {latches.begin(), latches.end()}; // 初始化工作表 + std::vector work_list = {latches.begin(), latches.end()}; // 初始化工作表 while (!work_list.empty()) { // 当工作表非空时继续处理 - auto bb = work_list.back(); + auto bb2 = work_list.back(); work_list.pop_back(); // TODO-1: 处理未分配给任何循环的节点 - if (bb_to_loop_.find(bb) == bb_to_loop_.end()) { + if (bb_to_loop_.find(bb2) == bb_to_loop_.end()) { /* 在此添加代码: * 1. 使用loop->add_block将bb加入当前循环 * 2. 更新bb_to_loop_映射 @@ -54,7 +85,7 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, } // TODO-2: 处理已属于其他循环的节点 - else if (bb_to_loop_[bb] != loop) { + if (bb_to_loop_[bb2] != loop) { /* 在此添加代码: * 1. 获取bb当前所属的循环sub_loop * 2. 找到sub_loop的最顶层父循环 @@ -62,7 +93,7 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, * 4. 建立循环嵌套关系: * - 设置父循环 * - 添加子循环 - * 5. 将子循环的所有基本快加入到父循环中 + * 5. 将子循环的所有基本块加入到父循环中 * 6. 将子循环header的前驱加入工作表 */ @@ -72,44 +103,6 @@ void LoopDetection::discover_loop_and_sub_loops(BasicBlock *bb, BBset &latches, } } -/** - * @brief 对单个函数执行循环检测 - * @param f 要分析的函数 - * - * 该函数通过以下步骤检测循环: - * 1. 运行支配树分析 - * 2. 按支配树后序遍历所有基本块 - * 3. 对每个块,检查其前驱是否存在回边 - * 4. 如果存在回边,创建新的循环并: - * - 设置循环header - * - 添加latch节点 - * - 发现循环体和子循环 - */ -void LoopDetection::run_on_func(Function *f) { - dominators_->run_on_func(f); - for (auto bb : dominators_->get_dom_post_order()) { - BBset latches; - for (auto pred : bb->get_pre_basic_blocks()) { - if (dominators_->is_dominate(bb, pred)) { - // pred is a back edge - // pred -> bb , pred is the latch node - latches.insert(pred); - } - } - if (latches.empty()) { - continue; - } - // create loop - auto loop = std::make_shared(bb); - bb_to_loop_[bb] = loop; - // add latch nodes - for (auto latch : latches) { - loop->add_latch(latch); - } - loops_.push_back(loop); - discover_loop_and_sub_loops(bb, latches, loop); - } -} /** * @brief 打印循环检测的结果 @@ -119,21 +112,21 @@ void LoopDetection::run_on_func(Function *f) { * 2. 循环包含的所有基本块 * 3. 循环的所有子循环 */ -void LoopDetection::print() { - m_->set_print_name(); - std::cerr << "Loop Detection Result:" << std::endl; +void LoopDetection::print() const { + f_->get_parent()->set_print_name(); + std::cerr << "Loop Detection Result:\n"; for (auto &loop : loops_) { std::cerr << "Loop header: " << loop->get_header()->get_name() - << std::endl; + << '\n'; std::cerr << "Loop blocks: "; for (auto bb : loop->get_blocks()) { std::cerr << bb->get_name() << " "; } - std::cerr << std::endl; + std::cerr << '\n'; std::cerr << "Sub loops: "; for (auto &sub_loop : loop->get_sub_loops()) { std::cerr << sub_loop->get_header()->get_name() << " "; } - std::cerr << std::endl; + std::cerr << '\n'; } } \ No newline at end of file diff --git a/src/passes/Mem2Reg.cpp b/src/passes/Mem2Reg.cpp index 1781f7e..157682c 100644 --- a/src/passes/Mem2Reg.cpp +++ b/src/passes/Mem2Reg.cpp @@ -1,8 +1,15 @@ #include "Mem2Reg.hpp" + #include "IRBuilder.hpp" #include "Value.hpp" -#include + +// l_val 是否是非数组 alloca 变量 +static bool is_not_array_alloca(Value* l_val) +{ + auto alloca = dynamic_cast(l_val); + return alloca != nullptr && !alloca->get_alloca_type()->is_array_type(); +} /** * @brief Mem2Reg Pass的主入口函数 @@ -18,23 +25,30 @@ * 注意:函数执行后,冗余的局部变量分配指令将由后续的死代码删除Pass处理 */ void Mem2Reg::run() { - // 创建支配树分析 Pass 的实例 - dominators_ = std::make_unique(m_); - // 建立支配树 - dominators_->run(); // 以函数为单元遍历实现 Mem2Reg 算法 for (auto f : m_->get_functions()) { if (f->is_declaration()) continue; func_ = f; + // 创建 func_ 支配树 + dominators_ = new Dominators(func_); + // 建立支配树 + dominators_->run(); + allocas_.clear(); var_val_stack.clear(); - phi_lval.clear(); - if (func_->get_basic_blocks().size() >= 1) { + phi_to_alloca_.clear(); + bb_to_phi_.clear(); + if (!func_->get_basic_blocks().empty()) { // 对应伪代码中 phi 指令插入的阶段 generate_phi(); + // 确保每个局部变量的栈都有初始值 + for (auto var : allocas_) + var_val_stack[var].emplace_back(ConstantZero::get(var->get_alloca_type(), m_)); // 对应伪代码中重命名阶段 rename(func_->get_entry_block()); } + delete dominators_; + dominators_ = nullptr; // 后续 DeadCode 将移除冗余的局部变量的分配空间 } } @@ -55,34 +69,41 @@ void Mem2Reg::run() { * phi指令的插入遵循最小化原则,只在必要的位置插入phi节点 */ void Mem2Reg::generate_phi() { - // global_live_var_name 是全局名字集合,以 alloca 出的局部变量来统计。 - // 步骤一:找到活跃在多个 block 的全局名字集合,以及它们所属的 bb 块 - std::set global_live_var_name; - std::map> live_var_2blocks; + // 步骤一:找到活跃在多个 block 的名字集合,以及它们所属的 bb 块 + + // global_live_var_name 包括函数中所有非数组 alloca 变量 + std::set not_array_allocas; + // 每个 alloca 在什么基本块被 store (可能重复) + std::map> allocas_stored_bbs; for (auto bb : func_->get_basic_blocks()) { - std::set var_is_killed; for (auto instr : bb->get_instructions()) { if (instr->is_store()) { // store i32 a, i32 *b // a is r_val, b is l_val - auto l_val = static_cast(instr)->get_lval(); - if (is_valid_ptr(l_val)) { - global_live_var_name.insert(l_val); - live_var_2blocks[l_val].insert(bb); + auto l_val = dynamic_cast(instr)->get_lval(); + if (is_not_array_alloca(l_val)) { + auto lalloca = dynamic_cast(instr); + not_array_allocas.insert(lalloca); + allocas_.emplace_back(lalloca); + allocas_stored_bbs[lalloca].emplace_back(bb); } } } } // 步骤二:从支配树获取支配边界信息,并在对应位置插入 phi 指令 - std::map, bool> - bb_has_var_phi; // bb has phi for var - for (auto var : global_live_var_name) { + + // 基本块是否已经有了对特定 alloca 变量的 phi + std::set> bb_has_var_phi; + for (auto var : not_array_allocas) { std::vector work_list; - work_list.assign(live_var_2blocks[var].begin(), - live_var_2blocks[var].end()); + std::set already_handled; + work_list.assign(allocas_stored_bbs[var].begin(), allocas_stored_bbs[var].end()); for (unsigned i = 0; i < work_list.size(); i++) { auto bb = work_list[i]; + // 防止在同一基本块重复运行 + if (already_handled.count(bb)) continue; + already_handled.emplace(bb); for (auto bb_dominance_frontier_bb : dominators_->get_dominance_frontier(bb)) { if (bb_has_var_phi.find({bb_dominance_frontier_bb, var}) == @@ -92,10 +113,11 @@ void Mem2Reg::generate_phi() { auto phi = PhiInst::create_phi( var->get_type()->get_pointer_element_type(), bb_dominance_frontier_bb); - phi_lval.emplace(phi, var); + phi_to_alloca_.emplace(phi, var); + 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); - bb_has_var_phi[{bb_dominance_frontier_bb, var}] = true; + bb_has_var_phi.emplace(bb_dominance_frontier_bb, var); } } } @@ -103,17 +125,23 @@ void Mem2Reg::generate_phi() { } void Mem2Reg::rename(BasicBlock *bb) { - std::vector wait_delete; + // 可能用到的数据结构 + // list allocas_ 所有 Mem2Reg 需要消除的局部变量,用于遍历 + // map> var_val_stack 每个局部变量的存储值栈,还未进行任何操作时已经存进去了 0,不会为空 + // map; Phi 对应的局部变量 + // map>; 在某个基本块的 Phi + // 可能用到的函数 + // Value::replace_all_use_with(Value* a) 将所有用到 this 的指令对应 this 的操作数都替换为 a + // BasicBlock::erase_instrs(set) 移除并 delete 列表中的指令 + // TODO - // 步骤一:将 phi 指令作为 lval 的最新定值,lval 即是为局部变量 alloca 出的地址空间 - // 步骤二:用 lval 最新的定值替代对应的load指令 - // 步骤三:将 store 指令的 rval,也即被存入内存的值,作为 lval 的最新定值 - // 步骤四:为 lval 对应的 phi 指令参数补充完整 - // 步骤五:对 bb 在支配树上的所有后继节点,递归执行 re_name 操作 - // 步骤六:pop出 lval 的最新定值 - - // 步骤七:清除冗余的指令 - for (auto instr : wait_delete) { - bb->erase_instr(instr); - } + // 步骤一:对每个 alloca 非数组变量(局部变量), 在其存储值栈存入其当前的最新值(也就是目前的栈顶值) + // 步骤二:遍历基本块所有指令,执行操作并记录需要删除的 load/store/alloca 指令 + // - 步骤三: 将 store 指令存储的值,作为其对应局部变量的最新值(更新栈顶) + // - 步骤四: 将 load 指令的所有使用替换为其读取的局部变量的最新值 + // 步骤五:为所有后继块的 phi 添加参数 + // 步骤六:对 bb 在支配树上的所有后继节点,递归执行 rename 操作 + // 步骤七:pop 出所有局部变量的最新值 + // 步骤八:删除需要删除的冗余指令 } + diff --git a/src/passes/PassManager.cpp b/src/passes/PassManager.cpp new file mode 100644 index 0000000..45fabfa --- /dev/null +++ b/src/passes/PassManager.cpp @@ -0,0 +1,7 @@ +#include "PassManager.hpp" + +TransformPass::~TransformPass() = default; + +ModuleAnalysisPass::~ModuleAnalysisPass() = default; + +FunctionAnalysisPass::~FunctionAnalysisPass() = default; -- GitLab