diff --git a/include/ir/IR.h b/include/ir/IR.h index 8b2ec34..e69de29 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -1,533 +0,0 @@ -// 当前只支撑 i32、i32*、void 以及最小的内存/算术指令,演示用。 -// -// 当前已经实现: -// 1. 基础类型系统:void / i32 / i32* -// 2. Value 体系:Value / ConstantValue / ConstantInt / Function / BasicBlock / User / GlobalValue / Instruction -// 3. 最小指令集:Add / Alloca / Load / Store / Ret -// 4. BasicBlock / Function / Module 三层组织结构 -// 5. IRBuilder:便捷创建常量和最小指令 -// 6. def-use 关系的轻量实现: -// - Instruction 保存 operand 列表 -// - Value 保存 uses -// - 支持 ReplaceAllUsesWith 的简化实现 -// -// 当前尚未实现或只做了最小占位: -// 1. 完整类型系统:数组、函数类型、label 类型等 -// 2. 更完整的指令系统:br / condbr / call / phi / gep 等 -// 3. 更成熟的 Use 管理(例如 LLVM 风格的双向链式结构) -// 4. 更完整的 IR verifier 和优化基础设施 -// -// 当前需要特别说明的两个简化点: -// 1. BasicBlock 虽然已经纳入 Value 体系,但其类型目前仍用 void 作为占位, -// 后续如果补 label type,可以再改成更合理的块标签类型。 -// 2. ConstantValue 体系目前只实现了 ConstantInt,后续可以继续补 ConstantFloat、 -// ConstantArray等更完整的常量种类。 -// -// 建议的扩展顺序: -// 1. 先补更多指令和类型 -// 2. 再补控制流相关 IR -// 3. 最后再考虑把 Value/User/Use 进一步抽象成更完整的框架 - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace ir { - -class Type; -class Value; -class User; -class ConstantValue; -class ConstantInt; -class ConstantFloat; -class GlobalValue; -class Instruction; -class BasicBlock; -class Function; - -// Use 表示一个 Value 的一次使用记录。 -// 当前实现设计: -// - value:被使用的值 -// - user:使用该值的 User -// - operand_index:该值在 user 操作数列表中的位置 - -class Use { - public: - Use() = default; - Use(Value* value, User* user, size_t operand_index) - : value_(value), user_(user), operand_index_(operand_index) {} - - Value* GetValue() const { return value_; } - User* GetUser() const { return user_; } - size_t GetOperandIndex() const { return operand_index_; } - - void SetValue(Value* value) { value_ = value; } - void SetUser(User* user) { user_ = user; } - void SetOperandIndex(size_t operand_index) { operand_index_ = operand_index; } - - private: - Value* value_ = nullptr; - User* user_ = nullptr; - size_t operand_index_ = 0; -}; - -// IR 上下文:集中管理类型、常量等共享资源,便于复用与扩展。 -class Context { - public: - Context() = default; - ~Context(); - // 去重创建 i32 常量。 - ConstantInt* GetConstInt(int v); - // 去重创建 float 常量。 - ConstantFloat* GetConstFloat(float v); - - std::string NextTemp(); - - private: - std::unordered_map> const_ints_; - std::unordered_map> const_floats_; - int temp_index_ = -1; -}; - -class Type { - public: - enum class Kind { Void, Int32, PtrInt32, Float32, PtrFloat32 }; - explicit Type(Kind k); - // 使用静态共享对象获取类型。 - // 同一类型可直接比较返回值是否相等,例如: - // Type::GetInt32Type() == Type::GetInt32Type() - static const std::shared_ptr& GetVoidType(); - static const std::shared_ptr& GetInt32Type(); - static const std::shared_ptr& GetPtrInt32Type(); - static const std::shared_ptr& GetFloat32Type(); - static const std::shared_ptr& GetPtrFloat32Type(); - Kind GetKind() const; - bool IsVoid() const; - bool IsInt32() const; - bool IsPtrInt32() const; - bool IsFloat32() const; - bool IsPtrFloat32() const; - - private: - Kind kind_; -}; - -class Value { - public: - Value(std::shared_ptr ty, std::string name); - virtual ~Value() = default; - const std::shared_ptr& GetType() const; - const std::string& GetName() const; - void SetName(std::string n); - bool IsVoid() const; - bool IsInt32() const; - bool IsPtrInt32() const; - bool IsFloat32() const; - bool IsPtrFloat32() const; - bool IsConstant() const; - bool IsInstruction() const; - bool IsUser() const; - bool IsFunction() const; - void AddUse(User* user, size_t operand_index); - void RemoveUse(User* user, size_t operand_index); - const std::vector& GetUses() const; - void ReplaceAllUsesWith(Value* new_value); - - protected: - std::shared_ptr type_; - std::string name_; - std::vector uses_; -}; - -// ConstantValue 是常量体系的基类。 -// 当前只实现了 ConstantInt,后续可继续扩展更多常量种类。 -class ConstantValue : public Value { - public: - ConstantValue(std::shared_ptr ty, std::string name = ""); -}; - -class ConstantInt : public ConstantValue { - public: - ConstantInt(std::shared_ptr ty, int v); - int GetValue() const { return value_; } - - private: - int value_{}; -}; - -class ConstantFloat : public ConstantValue { - public: - ConstantFloat(std::shared_ptr ty, float v); - float GetValue() const { return value_; } - - private: - float value_{}; -}; - -// Argument 表示函数的形式参数,作为 Value 在函数体内直接被引用。 -class Argument : public Value { - public: - Argument(std::shared_ptr ty, std::string name, size_t index); - size_t GetArgIndex() const { return arg_index_; } - - private: - size_t arg_index_; -}; - -// 第一版 Lab2 需要的指令集合。 -enum class Opcode { - Add, - Sub, - Mul, - Div, - Mod, - Cmp, - Cast, - Br, - CondBr, - Call, - Alloca, - Load, - Store, - Ret, - Gep, // getelementptr:数组元素地址计算 - Phi, // SSA phi 节点 -}; - -enum class CmpOp { Eq, Ne, Lt, Le, Gt, Ge }; -enum class CastOp { IntToFloat, FloatToInt }; - -// User 是所有“会使用其他 Value 作为输入”的 IR 对象的抽象基类。 -// 当前实现中只有 Instruction 继承自 User。 -class User : public Value { - public: - User(std::shared_ptr ty, std::string name); - size_t GetNumOperands() const; - Value* GetOperand(size_t index) const; - void SetOperand(size_t index, Value* value); - - protected: - // 统一的 operand 入口。 - void AddOperand(Value* value); - // 清空所有 operand(不清除 use 关系,调用者需自行处理)。 - void ClearOperands(); - - private: - std::vector operands_; -}; - -// GlobalValue 是全局值/全局变量体系的空壳占位类。 -// 当前只补齐类层次,具体初始化器、打印和链接语义后续再补。 -class GlobalValue : public User { - public: - GlobalValue(std::shared_ptr ty, std::string name); -}; - -// GlobalVariable 代表一个全局整型变量、常量或数组。 -// 标量:打印为 @name = global i32 N。 -// 数组:打印为 @name = global [count x i32] zeroinitializer。 -class GlobalVariable : public GlobalValue { - public: - GlobalVariable(std::string name, std::shared_ptr ptr_ty, - int init_val = 0, int count = 1, - std::vector init_elems = {}); - int GetInitValue() const { return init_val_; } - int GetCount() const { return count_; } - bool IsArray() const { return count_ > 1; } - bool IsFloat() const { return GetType() && GetType()->IsPtrFloat32(); } - const std::vector& GetInitElements() const { return init_elems_; } - - private: - int init_val_; - int count_; - std::vector init_elems_; -}; - -class Instruction : public User { - public: - Instruction(Opcode op, std::shared_ptr ty, std::string name = ""); - Opcode GetOpcode() const; - bool IsTerminator() const; - BasicBlock* GetParent() const; - void SetParent(BasicBlock* parent); - - private: - Opcode opcode_; - BasicBlock* parent_ = nullptr; -}; - -class BinaryInst : public Instruction { - public: - BinaryInst(Opcode op, std::shared_ptr ty, Value* lhs, Value* rhs, - std::string name); - Value* GetLhs() const; - Value* GetRhs() const; -}; - -class CmpInst : public Instruction { - public: - CmpInst(CmpOp op, std::shared_ptr ty, Value* lhs, Value* rhs, - std::string name); - CmpOp GetCmpOp() const; - Value* GetLhs() const; - Value* GetRhs() const; - - private: - CmpOp cmp_op_; -}; - -class CastInst : public Instruction { - public: - CastInst(CastOp op, std::shared_ptr ty, Value* val, std::string name); - CastOp GetCastOp() const; - Value* GetValue() const; - - private: - CastOp cast_op_; -}; - -class ReturnInst : public Instruction { - public: - ReturnInst(std::shared_ptr void_ty, Value* val); - Value* GetValue() const; -}; - -class AllocaInst : public Instruction { - public: - // 标量 alloca(分配 1 个 i32) - AllocaInst(std::shared_ptr ptr_ty, std::string name); - // 数组 alloca(分配 count 个 i32,count 为编译期常量) - AllocaInst(std::shared_ptr ptr_ty, std::string name, int count); - int GetCount() const { return count_; } - bool IsArray() const { return count_ > 1; } - - private: - int count_ = 1; -}; - -class LoadInst : public Instruction { - public: - LoadInst(std::shared_ptr val_ty, Value* ptr, std::string name); - Value* GetPtr() const; -}; - -class StoreInst : public Instruction { - public: - StoreInst(std::shared_ptr void_ty, Value* val, Value* ptr); - Value* GetValue() const; - Value* GetPtr() const; -}; - -class BranchInst : public Instruction { - public: - BranchInst(std::shared_ptr void_ty, BasicBlock* target); - BasicBlock* GetTarget() const; -}; - -class CondBranchInst : public Instruction { - public: - CondBranchInst(std::shared_ptr void_ty, Value* cond, - BasicBlock* true_bb, BasicBlock* false_bb); - Value* GetCond() const; - BasicBlock* GetTrueBlock() const; - BasicBlock* GetFalseBlock() const; -}; - -class CallInst : public Instruction { - public: - CallInst(std::shared_ptr ret_ty, Function* callee, - std::vector args, std::string name); - Function* GetCallee() const; - size_t GetNumArgs() const; - Value* GetArg(size_t index) const; -}; - -// GepInst:getelementptr i32, i32* base, i32 index -// 用于从数组基址 + 线性偏移量计算元素指针。 -class GepInst : public Instruction { - public: - GepInst(std::shared_ptr ptr_ty, Value* base, Value* index, - std::string name); - Value* GetBase() const; - Value* GetIndex() const; -}; - -// PhiInst:SSA phi 节点,用于控制流汇合点合并不同前驱传来的值。 -// 操作数布局:[val_0, bb_0, val_1, bb_1, ...] -class PhiInst : public Instruction { - public: - PhiInst(std::shared_ptr ty, std::string name); - // 添加一组 (value, incoming_block) 入边。 - void AddIncoming(Value* val, BasicBlock* bb); - size_t GetNumIncoming() const; - Value* GetIncomingValue(size_t i) const; - BasicBlock* GetIncomingBlock(size_t i) const; - void SetIncomingValue(size_t i, Value* val); - // 移除来自指定前驱块的入边。 - void RemoveIncomingBlock(BasicBlock* bb); -}; - -// BasicBlock 已纳入 Value 体系,便于后续向更完整 IR 类图靠拢。 -// 当前其类型仍使用 void 作为占位,后续可替换为专门的 label type。 -class BasicBlock : public Value { - public: - explicit BasicBlock(std::string name); - Function* GetParent() const; - void SetParent(Function* parent); - bool HasTerminator() const; - const std::vector>& GetInstructions() const; - std::vector>& MutableInstructions(); - const std::vector& GetPredecessors() const; - const std::vector& GetSuccessors() const; - std::vector& MutablePredecessors(); - std::vector& MutableSuccessors(); - void AddPredecessor(BasicBlock* pred); - void AddSuccessor(BasicBlock* succ); - void RemovePredecessor(BasicBlock* pred); - void RemoveSuccessor(BasicBlock* succ); - // 在块头部(所有 phi 之后)插入指令。 - template - T* Prepend(Args&&... args) { - auto inst = std::make_unique(std::forward(args)...); - auto* ptr = inst.get(); - ptr->SetParent(this); - // 插入到第一条非-phi 指令之前 - auto it = instructions_.begin(); - while (it != instructions_.end() && - (*it)->GetOpcode() == Opcode::Phi) { - ++it; - } - instructions_.insert(it, std::move(inst)); - return ptr; - } - template - T* Append(Args&&... args) { - if (HasTerminator()) { - throw std::runtime_error("BasicBlock 已有 terminator,不能继续追加指令: " + - name_); - } - auto inst = std::make_unique(std::forward(args)...); - auto* ptr = inst.get(); - ptr->SetParent(this); - instructions_.push_back(std::move(inst)); - return ptr; - } - // 在块的最前面插入 phi 节点。 - PhiInst* PrependPhi(std::shared_ptr ty, const std::string& name); - // 删除指定指令(从块中移除 ownership)。 - void RemoveInstruction(Instruction* inst); - // 判断块是否为空(不含任何指令)。 - bool IsEmpty() const { return instructions_.empty(); } - - private: - Function* parent_ = nullptr; - std::vector> instructions_; - std::vector predecessors_; - std::vector successors_; -}; - -// Function 当前也采用了最小实现。 -// 需要特别注意:由于项目里还没有单独的 FunctionType, -// Function 继承自 Value 后,其 type_ 目前只保存”返回类型”, -// 并不能完整表达”返回类型 + 形参列表”这一整套函数签名。 -class Function : public Value { - public: - Function(std::string name, std::shared_ptr ret_type, - std::vector> param_types = {}); - BasicBlock* CreateBlock(const std::string& name); - BasicBlock* GetEntry(); - const BasicBlock* GetEntry() const; - const std::vector>& GetParamTypes() const; - size_t GetNumParams() const; - Argument* GetArgument(size_t index) const; - const std::vector>& GetBlocks() const; - std::vector>& MutableBlocks(); - // 删除指定基本块(从函数中移除 ownership)。 - void RemoveBlock(BasicBlock* bb); - - // 外部函数声明(无函数体,打印为 declare)。 - void SetExternal(bool v) { is_external_ = v; } - bool IsExternal() const { return is_external_; } - - private: - BasicBlock* entry_ = nullptr; - std::vector> param_types_; - std::vector> args_; - std::vector> blocks_; - bool is_external_ = false; -}; - -class Module { - public: - Module() = default; - Context& GetContext(); - const Context& GetContext() const; - Function* CreateFunction(const std::string& name, - std::shared_ptr ret_type, - std::vector> param_types = {}); - Function* FindFunction(const std::string& name) const; - const std::vector>& GetFunctions() const; - - GlobalVariable* CreateGlobalVar(const std::string& name, int init_val = 0, - int count = 1, - std::shared_ptr ptr_ty = Type::GetPtrInt32Type(), - std::vector init_elems = {}); - GlobalVariable* FindGlobalVar(const std::string& name) const; - const std::vector>& GetGlobalVars() const; - - private: - Context context_; - std::vector> global_vars_; - std::vector> functions_; -}; - -class IRBuilder { - public: - IRBuilder(Context& ctx, BasicBlock* bb); - void SetInsertPoint(BasicBlock* bb); - BasicBlock* GetInsertBlock() const; - - // 构造常量、二元运算、返回指令的最小集合。 - ConstantInt* CreateConstInt(int v); - BinaryInst* CreateBinary(Opcode op, Value* lhs, Value* rhs, - const std::string& name); - BinaryInst* CreateAdd(Value* lhs, Value* rhs, const std::string& name); - BinaryInst* CreateSub(Value* lhs, Value* rhs, const std::string& name); - BinaryInst* CreateMul(Value* lhs, Value* rhs, const std::string& name); - BinaryInst* CreateDiv(Value* lhs, Value* rhs, const std::string& name); - BinaryInst* CreateMod(Value* lhs, Value* rhs, const std::string& name); - CmpInst* CreateCmp(CmpOp op, Value* lhs, Value* rhs, const std::string& name); - CastInst* CreateSIToFP(Value* v, const std::string& name); - CastInst* CreateFPToSI(Value* v, const std::string& name); - AllocaInst* CreateAllocaI32(const std::string& name); - AllocaInst* CreateAllocaArray(int count, const std::string& name); - AllocaInst* CreateAllocaF32(const std::string& name); - AllocaInst* CreateAllocaF32Array(int count, const std::string& name); - LoadInst* CreateLoad(Value* ptr, const std::string& name); - StoreInst* CreateStore(Value* val, Value* ptr); - BranchInst* CreateBr(BasicBlock* target); - CondBranchInst* CreateCondBr(Value* cond, BasicBlock* true_bb, - BasicBlock* false_bb); - CallInst* CreateCall(Function* callee, const std::vector& args, - const std::string& name); - GepInst* CreateGep(Value* base, Value* index, const std::string& name); - ReturnInst* CreateRet(Value* v); - ReturnInst* CreateRetVoid(); - - private: - Context& ctx_; - BasicBlock* insert_block_; -}; - -class IRPrinter { - public: - void Print(const Module& module, std::ostream& os); -}; - -} // namespace ir diff --git a/src/ir/analysis/DominatorTree.cpp b/src/ir/analysis/DominatorTree.cpp index 5c5f1b9..7691648 100644 --- a/src/ir/analysis/DominatorTree.cpp +++ b/src/ir/analysis/DominatorTree.cpp @@ -169,3 +169,4 @@ class DominatorTree { } // namespace analysis } // namespace ir + diff --git a/src/ir/passes/DCE.cpp b/src/ir/passes/DCE.cpp index f1d3ef3..e69de29 100644 --- a/src/ir/passes/DCE.cpp +++ b/src/ir/passes/DCE.cpp @@ -1,130 +0,0 @@ -// 死代码删除(DCE): -// - 删除无用指令与无用基本块 -// - 通常与 CFG 简化配合使用 -// -// 算法:标记 + 清扫 -// 1. 标记所有有副作用的指令为"有用"(ret, br, condbr, store, call) -// 2. 沿数据依赖反向传播,将有用指令依赖的定义也标记为有用 -// 3. 删除所有未被标记的非终结指令 - -#include "ir/IR.h" - -#include -#include -#include - -namespace ir { -namespace passes { - -// 判断一条指令是否有副作用(不可随意删除) -static bool HasSideEffect(Instruction* inst) { - Opcode op = inst->GetOpcode(); - // 终结指令、store、call 均有副作用 - if (op == Opcode::Ret || op == Opcode::Br || op == Opcode::CondBr || - op == Opcode::Store || op == Opcode::Call) { - return true; - } - return false; -} - -bool RunDCE(Function& func) { - if (func.IsExternal()) return false; - - bool changed = false; - - // 标记阶段 - std::unordered_set useful; - std::queue worklist; - - // 初始标记:所有有副作用的指令 - for (const auto& bb : func.GetBlocks()) { - if (!bb) continue; - for (const auto& inst_ptr : bb->GetInstructions()) { - auto* inst = inst_ptr.get(); - if (HasSideEffect(inst)) { - useful.insert(inst); - worklist.push(inst); - } - } - } - - // 反向传播:有用指令的操作数定义也标记为有用 - while (!worklist.empty()) { - auto* inst = worklist.front(); - worklist.pop(); - - for (size_t i = 0; i < inst->GetNumOperands(); ++i) { - auto* operand = inst->GetOperand(i); - if (!operand) continue; - auto* def_inst = dynamic_cast(operand); - if (def_inst && !useful.count(def_inst)) { - useful.insert(def_inst); - worklist.push(def_inst); - } - } - } - - // 清扫阶段:删除未标记为有用的指令 - for (const auto& bb : func.GetBlocks()) { - if (!bb) continue; - std::vector to_remove; - for (const auto& inst_ptr : bb->GetInstructions()) { - auto* inst = inst_ptr.get(); - if (!useful.count(inst)) { - to_remove.push_back(inst); - } - } - for (auto* inst : to_remove) { - // 如果还有使用者,不能直接删除(用 undef/0 替换) - // 在标记-清扫正确的前提下,未标记的指令不应有有用的使用者 - // 但安全起见,先检查 - if (!inst->GetUses().empty()) { - // 仍有使用者 —— 跳过(可能是循环引用的 phi) - continue; - } - bb->RemoveInstruction(inst); - changed = true; - } - } - - return changed; -} - -// 简化版 DCE:只删除没有使用者且无副作用的指令(更安全的实现) -bool RunSimpleDCE(Function& func) { - if (func.IsExternal()) return false; - - bool changed = false; - bool local_changed = true; - - while (local_changed) { - local_changed = false; - for (const auto& bb : func.GetBlocks()) { - if (!bb) continue; - std::vector to_remove; - - for (const auto& inst_ptr : bb->GetInstructions()) { - auto* inst = inst_ptr.get(); - // 跳过有副作用的指令 - if (HasSideEffect(inst)) continue; - // 跳过 alloca(可能后续还会用到) - if (inst->GetOpcode() == Opcode::Alloca) continue; - // 如果没有使用者,可以安全删除 - if (inst->GetUses().empty()) { - to_remove.push_back(inst); - } - } - - for (auto* inst : to_remove) { - bb->RemoveInstruction(inst); - local_changed = true; - changed = true; - } - } - } - - return changed; -} - -} // namespace passes -} // namespace ir diff --git a/src/ir/passes/Mem2Reg.cpp b/src/ir/passes/Mem2Reg.cpp index 2851390..e69de29 100644 --- a/src/ir/passes/Mem2Reg.cpp +++ b/src/ir/passes/Mem2Reg.cpp @@ -1,336 +0,0 @@ -// Mem2Reg(SSA 构造): -// - 将局部变量的 alloca/load/store 提升为 SSA 形式 -// - 插入 PHI 并重写使用,依赖支配树等分析 -// -// 算法流程: -// 1. 识别可提升的 alloca(标量,仅通过 load/store 访问) -// 2. 计算支配树与支配边界 -// 3. 在支配边界处插入 phi -// 4. 沿支配树重命名变量 -// 5. 删除冗余 alloca/load/store - -#include "ir/IR.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ir { -namespace passes { - -// ============ 内联支配树(与 analysis 版本相同) ============ - -namespace { - -class DomTree { - public: - explicit DomTree(Function& func) : func_(func) { Compute(); } - - BasicBlock* GetIDom(BasicBlock* bb) const { - auto it = idom_.find(bb); - return it != idom_.end() ? it->second : nullptr; - } - - const std::vector& GetDF(BasicBlock* bb) const { - static const std::vector empty; - auto it = df_.find(bb); - return it != df_.end() ? it->second : empty; - } - - const std::vector& GetChildren(BasicBlock* bb) const { - static const std::vector empty; - auto it = children_.find(bb); - return it != children_.end() ? it->second : empty; - } - - const std::vector& GetRPO() const { return rpo_; } - - private: - void Compute() { - auto* entry = func_.GetEntry(); - if (!entry) return; - ComputeRPO(entry); - if (rpo_.empty()) return; - for (auto* bb : rpo_) { - idom_[bb] = nullptr; - rpo_index_[bb] = 0; - } - for (size_t i = 0; i < rpo_.size(); ++i) { - rpo_index_[rpo_[i]] = i; - } - idom_[entry] = entry; - bool changed = true; - while (changed) { - changed = false; - for (auto* bb : rpo_) { - if (bb == entry) continue; - BasicBlock* new_idom = nullptr; - for (auto* pred : bb->GetPredecessors()) { - if (idom_.count(pred) && idom_[pred] != nullptr) { - if (!new_idom) { - new_idom = pred; - } else { - new_idom = Intersect(new_idom, pred); - } - } - } - if (new_idom && idom_[bb] != new_idom) { - idom_[bb] = new_idom; - changed = true; - } - } - } - for (auto* bb : rpo_) { - auto* p = GetIDom(bb); - if (p && p != bb) { - children_[p].push_back(bb); - } - } - ComputeDF(); - } - - void ComputeRPO(BasicBlock* entry) { - std::unordered_set visited; - std::vector post_order; - std::function dfs = [&](BasicBlock* bb) { - visited.insert(bb); - for (auto* succ : bb->GetSuccessors()) { - if (!visited.count(succ)) { - dfs(succ); - } - } - post_order.push_back(bb); - }; - dfs(entry); - rpo_.assign(post_order.rbegin(), post_order.rend()); - } - - BasicBlock* Intersect(BasicBlock* b1, BasicBlock* b2) { - while (b1 != b2) { - while (rpo_index_[b1] > rpo_index_[b2]) b1 = idom_[b1]; - while (rpo_index_[b2] > rpo_index_[b1]) b2 = idom_[b2]; - } - return b1; - } - - void ComputeDF() { - for (auto* bb : rpo_) { - df_[bb] = {}; - } - for (auto* bb : rpo_) { - if (bb->GetPredecessors().size() < 2) continue; - for (auto* pred : bb->GetPredecessors()) { - auto* runner = pred; - while (runner && runner != idom_[bb]) { - auto& df_set = df_[runner]; - if (std::find(df_set.begin(), df_set.end(), bb) == df_set.end()) { - df_set.push_back(bb); - } - if (runner == idom_[runner]) break; - runner = idom_[runner]; - } - } - } - } - - Function& func_; - std::vector rpo_; - std::unordered_map rpo_index_; - std::unordered_map idom_; - std::unordered_map> children_; - std::unordered_map> df_; -}; - -// 判断一个 alloca 是否可以被提升为寄存器: -// - 必须是标量(count == 1) -// - 只被 load 和 store 使用 -bool IsPromotable(AllocaInst* alloca) { - if (alloca->IsArray()) return false; - for (const auto& use : alloca->GetUses()) { - auto* user = use.GetUser(); - if (!user) return false; - auto* inst = dynamic_cast(user); - if (!inst) return false; - if (inst->GetOpcode() != Opcode::Load && - inst->GetOpcode() != Opcode::Store) { - return false; - } - // store 只能把 alloca 作为 ptr(operand 1),不能作为 val(operand 0) - if (inst->GetOpcode() == Opcode::Store) { - auto* store = static_cast(inst); - if (store->GetPtr() != alloca) return false; - } - } - return true; -} - -} // namespace - -bool RunMem2Reg(Function& func) { - if (func.IsExternal()) return false; - - DomTree dom(func); - - // 1. 收集可提升的 alloca - std::vector promotable; - auto* entry = func.GetEntry(); - if (!entry) return false; - - for (const auto& inst : entry->GetInstructions()) { - if (auto* alloca = dynamic_cast(inst.get())) { - if (IsPromotable(alloca)) { - promotable.push_back(alloca); - } - } - } - - if (promotable.empty()) return false; - - // 对每个可提升的 alloca 分别执行 - for (auto* alloca : promotable) { - // 确定 alloca 值的类型 - std::shared_ptr val_type; - if (alloca->GetType()->IsPtrInt32()) { - val_type = Type::GetInt32Type(); - } else if (alloca->GetType()->IsPtrFloat32()) { - val_type = Type::GetFloat32Type(); - } else { - continue; - } - - // 2. 收集所有 def 块(包含 store 的块)和 use 块(包含 load 的块) - std::unordered_set def_blocks; - std::vector stores; - std::vector loads; - - for (const auto& use : alloca->GetUses()) { - auto* inst = dynamic_cast(use.GetUser()); - if (!inst || !inst->GetParent()) continue; - if (auto* store = dynamic_cast(inst)) { - if (store->GetPtr() == alloca) { - def_blocks.insert(store->GetParent()); - stores.push_back(store); - } - } else if (auto* load = dynamic_cast(inst)) { - loads.push_back(load); - } - } - - // 3. 插入 phi 节点(使用迭代支配边界) - // 用 map 精确记录当前 alloca 在每个块中插入的 phi - std::unordered_map phi_map; - std::unordered_set phi_blocks; - std::queue worklist; - for (auto* bb : def_blocks) { - worklist.push(bb); - } - static int phi_counter = 0; - while (!worklist.empty()) { - auto* bb = worklist.front(); - worklist.pop(); - for (auto* df_bb : dom.GetDF(bb)) { - if (!phi_blocks.count(df_bb)) { - phi_blocks.insert(df_bb); - auto* phi = df_bb->PrependPhi(val_type, - "%phi." + std::to_string(phi_counter++)); - phi_map[df_bb] = phi; - worklist.push(df_bb); - } - } - } - - // 4. 重命名:沿支配树 DFS - std::stack val_stack; - - std::function Rename = [&](BasicBlock* bb) { - size_t stack_size = val_stack.size(); - - // 处理当前块中我们插入的 phi - auto phi_it = phi_map.find(bb); - if (phi_it != phi_map.end()) { - val_stack.push(phi_it->second); - } - - // 遍历块中所有指令 - std::vector to_remove; - for (auto& inst_ptr : bb->GetInstructions()) { - auto* inst = inst_ptr.get(); - if (auto* store = dynamic_cast(inst)) { - if (store->GetPtr() == alloca) { - val_stack.push(store->GetValue()); - to_remove.push_back(store); - } - } else if (auto* load = dynamic_cast(inst)) { - if (load->GetPtr() == alloca) { - Value* cur_val = val_stack.empty() ? nullptr : val_stack.top(); - if (cur_val) { - load->ReplaceAllUsesWith(cur_val); - } - to_remove.push_back(load); - } - } - } - - // 填充后继块中 phi 的入边 - for (auto* succ : bb->GetSuccessors()) { - auto succ_phi_it = phi_map.find(succ); - if (succ_phi_it == phi_map.end()) continue; - Value* cur_val = val_stack.empty() ? nullptr : val_stack.top(); - if (cur_val) { - succ_phi_it->second->AddIncoming(cur_val, bb); - } - } - - // 递归处理支配树的孩子 - for (auto* child : dom.GetChildren(bb)) { - Rename(child); - } - - // 恢复栈 - while (val_stack.size() > stack_size) { - val_stack.pop(); - } - - // 删除已标记的指令 - for (auto* inst : to_remove) { - bb->RemoveInstruction(inst); - } - }; - - Rename(entry); - - // 5. 删除 alloca - entry->RemoveInstruction(alloca); - - // 6. 清理没有入边的 phi - for (auto* bb : dom.GetRPO()) { - std::vector dead_phis; - for (auto& inst_ptr : bb->GetInstructions()) { - auto* phi = dynamic_cast(inst_ptr.get()); - if (!phi) break; - if (phi->GetNumIncoming() == 0) { - dead_phis.push_back(phi); - } - // 如果 phi 只有一个入边,直接替换为该值 - if (phi->GetNumIncoming() == 1) { - phi->ReplaceAllUsesWith(phi->GetIncomingValue(0)); - dead_phis.push_back(phi); - } - } - for (auto* phi : dead_phis) { - bb->RemoveInstruction(phi); - } - } - } - - return true; -} - -} // namespace passes -} // namespace ir