#include "DeadCode.hpp" #include "logging.hpp" #include // 处理流程:两趟处理,mark 标记有用变量,sweep 删除无用指令 void DeadCode::run() { bool changed{}; func_info->run(); do { changed = false; for (auto func : m_->get_functions()) { changed |= clear_basic_blocks(func); mark(func); changed |= sweep(func); } } while (changed); LOG_INFO << "dead code pass erased " << ins_count << " instructions"; } 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; } } for (auto bb : to_erase) { bb->erase_from_parent(); delete bb; } return changed; } void DeadCode::mark(Function *func) { work_list.clear(); marked.clear(); for (auto bb : func->get_basic_blocks()) { for (auto ins : bb->get_instructions()) { if (is_critical(ins)) { marked[ins] = true; work_list.push_back(ins); } } } while (work_list.empty() == false) { auto now = work_list.front(); work_list.pop_front(); mark(now); } } void DeadCode::mark(Instruction *ins) { for (auto op : ins->get_operands()) { auto def = dynamic_cast(op); if (def == nullptr) continue; if (marked[def]) continue; if (def->get_function() != ins->get_function()) continue; marked[def] = true; work_list.push_back(def); } } bool DeadCode::sweep(Function *func) { 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 : 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 } bool DeadCode::is_critical(Instruction *ins) { // 对纯函数的无用调用也可以在删除之列 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)) return false; return true; } if (ins->is_br() || ins->is_ret()) return true; if (ins->is_store()) return true; return false; } void DeadCode::sweep_globally() { 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") unused_funcs.push_back(f_r); } for (auto glob_var_r : m_->get_global_variable()) { if (glob_var_r->get_use_list().size() == 0) unused_globals.push_back(glob_var_r); } // changed |= unused_funcs.size() or unused_globals.size(); for (auto func : unused_funcs) { m_->get_functions().remove(func); delete func; } for (auto glob : unused_globals) { m_->get_global_variable().remove(glob); delete glob; } }