Files
mysysy/src/midend/Pass/Analysis/Liveness.cpp
2025-07-29 21:30:30 +08:00

160 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Liveness.h"
#include <algorithm> // For std::set_union, std::set_difference
#include <iostream>
#include <queue> // Potentially for worklist, though not strictly needed for the iterative approach below
#include <set> // For std::set
namespace sysy {
// 初始化静态 ID
void *LivenessAnalysisPass::ID = (void *)&LivenessAnalysisPass::ID;
// ==============================================================
// LivenessAnalysisResult 结果类的实现
// ==============================================================
const std::set<Value *> *LivenessAnalysisResult::getLiveIn(BasicBlock *BB) const {
auto it = liveInSets.find(BB);
if (it != liveInSets.end()) {
return &(it->second);
}
// 返回一个空集合,表示未找到或不存在
static const std::set<Value *> emptySet;
return &emptySet;
}
const std::set<Value *> *LivenessAnalysisResult::getLiveOut(BasicBlock *BB) const {
auto it = liveOutSets.find(BB);
if (it != liveOutSets.end()) {
return &(it->second);
}
static const std::set<Value *> emptySet;
return &emptySet;
}
void LivenessAnalysisResult::computeDefUse(BasicBlock *BB, std::set<Value *> &def, std::set<Value *> &use) {
def.clear(); // 将持有在 BB 中定义的值
use.clear(); // 将持有在 BB 中使用但在其定义之前的值
// 临时集合,用于跟踪当前基本块中已经定义过的变量
std::set<Value *> defined_in_block_so_far;
// 按照指令在块中的顺序遍历
for (const auto &inst_ptr : BB->getInstructions()) {
Instruction *inst = inst_ptr.get();
// 1. 处理指令的操作数 (Use) - 在定义之前的使用
for (const auto &use_ptr : inst->getOperands()) { // 修正迭代器类型
Value *operand = use_ptr->getValue(); // 从 shared_ptr<Use> 获取 Value*
// 过滤掉常量和全局变量,因为它们通常不被视为活跃变量
ConstantValue *constValue = dynamic_cast<ConstantValue *>(operand);
GlobalValue *globalValue = dynamic_cast<GlobalValue *>(operand);
if (constValue || globalValue) {
continue; // 跳过常量和全局变量
}
// 如果操作数是一个变量Instruction 或 Argument并且它在此基本块的当前点之前尚未被定义
if (defined_in_block_so_far.find(operand) == defined_in_block_so_far.end()) {
use.insert(operand);
}
}
// 2. 处理指令自身产生的定义 (Def)
if (inst->isDefine()) { // 使用 isDefine() 方法
// 指令自身定义了一个值。将其添加到块的 def 集合,
// 并添加到当前块中已定义的值的临时集合。
def.insert(inst); // inst 本身就是被定义的值(例如,虚拟寄存器)
defined_in_block_so_far.insert(inst);
}
}
}
void LivenessAnalysisResult::computeLiveness(Function *F) {
// 每次计算前清空旧结果
liveInSets.clear(); // 直接清空 map不再使用 F 作为键
liveOutSets.clear(); // 直接清空 map
// 初始化所有基本块的 LiveIn 和 LiveOut 集合为空
for (const auto &bb_ptr : F->getBasicBlocks()) {
BasicBlock *bb = bb_ptr.get();
liveInSets[bb] = {}; // 直接以 bb 为键
liveOutSets[bb] = {}; // 直接以 bb 为键
}
bool changed = true;
while (changed) {
changed = false;
// TODO : 目前为逆序遍历基本块,考虑反向拓扑序遍历基本块
// 逆序遍历基本块
// std::list<std::unique_ptr<BasicBlock>> basicBlocks(F->getBasicBlocks().begin(), F->getBasicBlocks().end());
// std::reverse(basicBlocks.begin(), basicBlocks.end());
// 然后遍历 basicBlocks
// 创建一个 BasicBlock* 的列表来存储指针,避免拷贝 unique_ptr
// Option 1: Using std::vector<BasicBlock*> (preferred for performance with reverse)
std::vector<BasicBlock*> basicBlocksPointers;
for (const auto& bb_ptr : F->getBasicBlocks()) {
basicBlocksPointers.push_back(bb_ptr.get());
}
std::reverse(basicBlocksPointers.begin(), basicBlocksPointers.end());
for (auto bb_iter = basicBlocksPointers.begin(); bb_iter != basicBlocksPointers.end(); ++bb_iter) {
BasicBlock *bb = *bb_iter; // 获取 BasicBlock 指针
if (!bb)
continue; // 避免空指针
std::set<Value *> oldLiveIn = liveInSets[bb];
std::set<Value *> oldLiveOut = liveOutSets[bb];
// 1. 计算 LiveOut(BB) = Union(LiveIn(Succ) for Succ in Successors(BB))
std::set<Value *> newLiveOut;
for (BasicBlock *succ : bb->getSuccessors()) {
const std::set<Value *> *succLiveIn = getLiveIn(succ); // 获取后继的 LiveIn
if (succLiveIn) {
newLiveOut.insert(succLiveIn->begin(), succLiveIn->end());
}
}
liveOutSets[bb] = newLiveOut;
// 2. 计算 LiveIn(BB) = Use(BB) Union (LiveOut(BB) - Def(BB))
std::set<Value *> defSet, useSet;
computeDefUse(bb, defSet, useSet); // 计算当前块的 Def 和 Use
std::set<Value *> liveOutMinusDef;
std::set_difference(newLiveOut.begin(), newLiveOut.end(), defSet.begin(), defSet.end(),
std::inserter(liveOutMinusDef, liveOutMinusDef.begin()));
std::set<Value *> newLiveIn = useSet;
newLiveIn.insert(liveOutMinusDef.begin(), liveOutMinusDef.end());
liveInSets[bb] = newLiveIn;
// 检查是否发生变化
if (oldLiveIn != newLiveIn || oldLiveOut != newLiveOut) {
changed = true;
}
}
}
}
// ==============================================================
// LivenessAnalysisPass 的实现
// ==============================================================
bool LivenessAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
// 每次运行创建一个新的 LivenessAnalysisResult 对象来存储结果
CurrentLivenessResult = std::make_unique<LivenessAnalysisResult>(F);
// 调用 LivenessAnalysisResult 内部的方法来计算分析结果
CurrentLivenessResult->computeLiveness(F);
// 分析遍通常不修改 IR所以返回 false
return false;
}
std::unique_ptr<AnalysisResultBase> LivenessAnalysisPass::getResult() {
// 返回计算好的 LivenessAnalysisResult 实例,所有权转移给 AnalysisManager
return std::move(CurrentLivenessResult);
}
} // namespace sysy