添加数据流分析类,实现前向后向分析的模板动作,实现活跃变量分析,基本借鉴学长代码,后续可优化实现
This commit is contained in:
@ -254,6 +254,267 @@ void ControlFlowAnalysis::computeDomFrontierAllBlk() {
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// dataflow analysis utils
|
||||
// ==========================
|
||||
|
||||
// 先引用学长的代码
|
||||
// TODO: Worklist 增加逆后序遍历机制
|
||||
void DataFlowAnalysisUtils::forwardAnalyze(Module *pModule){
|
||||
std::map<DataFlowAnalysis *, bool> workAnalysis;
|
||||
for (auto &dataflow : forwardAnalysisList) {
|
||||
dataflow->init(pModule);
|
||||
}
|
||||
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (auto &dataflow : forwardAnalysisList) {
|
||||
workAnalysis.emplace(dataflow, false);
|
||||
}
|
||||
while (!workAnalysis.empty()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
for (auto &elem : workAnalysis) {
|
||||
if (elem.first->analyze(pModule, block.get())) {
|
||||
elem.second = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<DataFlowAnalysis *, bool> tmp;
|
||||
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
|
||||
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
|
||||
workAnalysis.swap(tmp);
|
||||
|
||||
for (auto &elem : workAnalysis) {
|
||||
elem.second = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DataFlowAnalysisUtils::backwardAnalyze(Module *pModule) {
|
||||
std::map<DataFlowAnalysis *, bool> workAnalysis;
|
||||
for (auto &dataflow : backwardAnalysisList) {
|
||||
dataflow->init(pModule);
|
||||
}
|
||||
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (auto &dataflow : backwardAnalysisList) {
|
||||
workAnalysis.emplace(dataflow, false);
|
||||
}
|
||||
while (!workAnalysis.empty()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
for (auto &elem : workAnalysis) {
|
||||
if (elem.first->analyze(pModule, block.get())) {
|
||||
elem.second = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<DataFlowAnalysis *, bool> tmp;
|
||||
std::remove_copy_if(workAnalysis.begin(), workAnalysis.end(), std::inserter(tmp, tmp.end()),
|
||||
[](const std::pair<DataFlowAnalysis *, bool> &elem) -> bool { return !elem.second; });
|
||||
workAnalysis.swap(tmp);
|
||||
|
||||
for (auto &elem : workAnalysis) {
|
||||
elem.second = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::set<User *> ActiveVarAnalysis::getUsedSet(Instruction *inst) {
|
||||
using Kind = Instruction::Kind;
|
||||
std::vector<User *> operands;
|
||||
for (const auto &operand : inst->getOperands()) {
|
||||
operands.emplace_back(dynamic_cast<User *>(operand->getValue()));
|
||||
}
|
||||
std::set<User *> result;
|
||||
switch (inst->getKind()) {
|
||||
// phi op
|
||||
case Kind::kPhi:
|
||||
case Kind::kCall:
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
case Kind::kCondBr:
|
||||
result.insert(operands[0]);
|
||||
break;
|
||||
case Kind::kBr:
|
||||
case Kind::kAlloca:
|
||||
break;
|
||||
// mem op
|
||||
case Kind::kStore:
|
||||
// StoreInst 的第一个操作数是被存储的值,第二个操作数是存储的变量
|
||||
// 后续的是可能的数组维度
|
||||
result.insert(operands[0]);
|
||||
result.insert(operands.begin() + 2, operands.end());
|
||||
break;
|
||||
case Kind::kLoad:
|
||||
case Kind::kLa: {
|
||||
auto variable = dynamic_cast<AllocaInst *>(operands[0]);
|
||||
auto global = dynamic_cast<GlobalValue *>(operands[0]);
|
||||
auto constArray = dynamic_cast<ConstantVariable *>(operands[0]);
|
||||
if ((variable != nullptr && variable->getNumDims() == 0) || (global != nullptr && global->getNumDims() == 0) ||
|
||||
(constArray != nullptr && constArray->getNumDims() == 0)) {
|
||||
result.insert(operands[0]);
|
||||
}
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
}
|
||||
case Kind::kGetSubArray: {
|
||||
for (unsigned i = 2; i < operands.size(); i++) {
|
||||
// 数组的维度信息
|
||||
result.insert(operands[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Kind::kMemset: {
|
||||
result.insert(std::next(operands.begin()), operands.end());
|
||||
break;
|
||||
}
|
||||
case Kind::kInvalid:
|
||||
// Binary
|
||||
case Kind::kAdd:
|
||||
case Kind::kSub:
|
||||
case Kind::kMul:
|
||||
case Kind::kDiv:
|
||||
case Kind::kRem:
|
||||
case Kind::kICmpEQ:
|
||||
case Kind::kICmpNE:
|
||||
case Kind::kICmpLT:
|
||||
case Kind::kICmpLE:
|
||||
case Kind::kICmpGT:
|
||||
case Kind::kICmpGE:
|
||||
case Kind::kFAdd:
|
||||
case Kind::kFSub:
|
||||
case Kind::kFMul:
|
||||
case Kind::kFDiv:
|
||||
case Kind::kFCmpEQ:
|
||||
case Kind::kFCmpNE:
|
||||
case Kind::kFCmpLT:
|
||||
case Kind::kFCmpLE:
|
||||
case Kind::kFCmpGT:
|
||||
case Kind::kFCmpGE:
|
||||
case Kind::kAnd:
|
||||
case Kind::kOr:
|
||||
// Unary
|
||||
case Kind::kNeg:
|
||||
case Kind::kNot:
|
||||
case Kind::kFNot:
|
||||
case Kind::kFNeg:
|
||||
case Kind::kFtoI:
|
||||
case Kind::kItoF:
|
||||
// terminator
|
||||
case Kind::kReturn:
|
||||
result.insert(operands.begin(), operands.end());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
result.erase(nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
User * ActiveVarAnalysis::getDefine(Instruction *inst) {
|
||||
User *result = nullptr;
|
||||
if (inst->isStore()) {
|
||||
StoreInst* store = dynamic_cast<StoreInst *>(inst);
|
||||
auto operand = store->getPointer();
|
||||
AllocaInst* variable = dynamic_cast<AllocaInst *>(operand);
|
||||
GlobalValue* global = dynamic_cast<GlobalValue *>(operand);
|
||||
if ((variable != nullptr && variable->getNumDims() != 0) || (global != nullptr && global->getNumDims() != 0)) {
|
||||
// 如果是数组变量或者全局变量,则不返回定义
|
||||
// TODO:兼容数组变量
|
||||
result = nullptr;
|
||||
} else {
|
||||
result = dynamic_cast<User *>(operand);
|
||||
}
|
||||
} else if (inst->isPhi()) {
|
||||
result = dynamic_cast<User *>(inst->getOperand(0));
|
||||
} else if (inst->isBinary() || inst->isUnary() || inst->isCall() ||
|
||||
inst->isLoad() || inst->isLa()) {
|
||||
result = dynamic_cast<User *>(inst);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActiveVarAnalysis::init(Module *pModule) {
|
||||
for (const auto &function : pModule->getFunctions()) {
|
||||
for (const auto &block : function.second->getBasicBlocks()) {
|
||||
activeTable.emplace(block.get(), std::vector<std::set<User *>>{});
|
||||
for (unsigned i = 0; i < block->getNumInstructions() + 1; i++)
|
||||
activeTable.at(block.get()).emplace_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 活跃变量分析公式 每个块内的分析动作供分析器调用
|
||||
bool ActiveVarAnalysis::analyze(Module *pModule, BasicBlock *block) {
|
||||
bool changed = false; // 标记数据流结果是否有变化
|
||||
std::set<User *> activeSet{}; // 当前计算的活跃变量集合
|
||||
|
||||
// 步骤1: 计算基本块出口的活跃变量集 (OUT[B])
|
||||
// 公式: OUT[B] = ∪_{S ∈ succ(B)} IN[S]
|
||||
for (const auto &succ : block->getSuccessors()) {
|
||||
// 获取后继块入口的活跃变量集 (IN[S])
|
||||
auto succActiveSet = activeTable.at(succ).front();
|
||||
// 合并所有后继块的入口活跃变量
|
||||
activeSet.insert(succActiveSet.begin(), succActiveSet.end());
|
||||
}
|
||||
|
||||
// 步骤2: 处理基本块出口处的活跃变量集
|
||||
const auto &instructions = block->getInstructions();
|
||||
const auto numInstructions = instructions.size();
|
||||
|
||||
// 获取旧的出口活跃变量集 (block出口对应索引numInstructions)
|
||||
const auto &oldEndActiveSet = activeTable.at(block)[numInstructions];
|
||||
|
||||
// 检查出口活跃变量集是否有变化
|
||||
if (!std::equal(activeSet.begin(), activeSet.end(),
|
||||
oldEndActiveSet.begin(), oldEndActiveSet.end()))
|
||||
{
|
||||
changed = true; // 标记变化
|
||||
activeTable.at(block)[numInstructions] = activeSet; // 更新出口活跃变量集
|
||||
}
|
||||
|
||||
// 步骤3: 逆序遍历基本块中的指令
|
||||
// 从最后一条指令开始向前计算每个程序点的活跃变量
|
||||
auto instructionIter = instructions.end();
|
||||
instructionIter--; // 指向最后一条指令
|
||||
|
||||
// 从出口向入口遍历 (索引从numInstructions递减到1)
|
||||
for (unsigned i = numInstructions; i > 0; i--) {
|
||||
auto inst = instructionIter->get(); // 当前指令
|
||||
|
||||
auto used = getUsedSet(inst);
|
||||
User *defined = getDefine(inst);
|
||||
|
||||
// 步骤3.3: 计算指令入口的活跃变量 (IN[i])
|
||||
// 公式: IN[i] = use_i ∪ (OUT[i] - def_i)
|
||||
activeSet.erase(defined); // 移除被定义的变量 (OUT[i] - def_i)
|
||||
activeSet.insert(used.begin(), used.end()); // 添加使用的变量
|
||||
|
||||
// 获取旧的入口活跃变量集 (位置i-1对应当前指令的入口)
|
||||
const auto &oldActiveSet = activeTable.at(block)[i - 1];
|
||||
|
||||
// 检查活跃变量集是否有变化
|
||||
if (!std::equal(activeSet.begin(), activeSet.end(),
|
||||
oldActiveSet.begin(), oldActiveSet.end()))
|
||||
{
|
||||
changed = true; // 标记变化
|
||||
activeTable.at(block)[i - 1] = activeSet; // 更新入口活跃变量集
|
||||
}
|
||||
|
||||
instructionIter--; // 移动到前一条指令
|
||||
}
|
||||
|
||||
return changed; // 返回数据流结果是否变化
|
||||
}
|
||||
|
||||
|
||||
auto ActiveVarAnalysis::getActiveTable() const -> const std::map<BasicBlock *, std::vector<std::set<User *>>> & {
|
||||
return activeTable;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
|
||||
|
||||
@ -252,6 +252,7 @@ public:
|
||||
bool isParallelable() const { return parallelable; }
|
||||
};
|
||||
|
||||
// 控制流分析类
|
||||
class ControlFlowAnalysis {
|
||||
private:
|
||||
Module *pModule; ///< 模块
|
||||
@ -287,8 +288,111 @@ private:
|
||||
BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点
|
||||
};
|
||||
|
||||
// 数据流分析类
|
||||
// 该类为抽象类,具体的数据流分析器需要继承此类
|
||||
// 因为每个数据流分析器的分析动作都不一样,所以需要继承并实现analyze方法
|
||||
class DataFlowAnalysis {
|
||||
public:
|
||||
virtual ~DataFlowAnalysis() = default;
|
||||
|
||||
// 分析管理器(整合版)
|
||||
public:
|
||||
virtual void init(Module *pModule) {} ///< 分析器初始化
|
||||
virtual auto analyze(Module *pModule, BasicBlock *block) -> bool { return true; } ///< 分析动作,若完成则返回true;
|
||||
virtual void clear() {} ///< 清空
|
||||
};
|
||||
|
||||
// 数据流分析工具类
|
||||
// 该类用于管理多个数据流分析器,提供统一的前向与后向分析接口
|
||||
class DataFlowAnalysisUtils {
|
||||
private:
|
||||
std::vector<DataFlowAnalysis *> forwardAnalysisList; ///< 前向分析器列表
|
||||
std::vector<DataFlowAnalysis *> backwardAnalysisList; ///< 后向分析器列表
|
||||
|
||||
public:
|
||||
DataFlowAnalysisUtils() = default;
|
||||
|
||||
// 统一构造
|
||||
DataFlowAnalysisUtils(
|
||||
std::vector<DataFlowAnalysis *> forwardList = {},
|
||||
std::vector<DataFlowAnalysis *> backwardList = {})
|
||||
: forwardAnalysisList(std::move(forwardList)),
|
||||
backwardAnalysisList(std::move(backwardList)) {}
|
||||
|
||||
// 统一添加接口
|
||||
void addAnalyzers(
|
||||
std::vector<DataFlowAnalysis *> forwardList,
|
||||
std::vector<DataFlowAnalysis *> backwardList = {})
|
||||
{
|
||||
forwardAnalysisList.insert(
|
||||
forwardAnalysisList.end(),
|
||||
forwardList.begin(),
|
||||
forwardList.end());
|
||||
|
||||
backwardAnalysisList.insert(
|
||||
backwardAnalysisList.end(),
|
||||
backwardList.begin(),
|
||||
backwardList.end());
|
||||
}
|
||||
|
||||
// 单独添加接口
|
||||
void addForwardAnalyzer(DataFlowAnalysis *analyzer) {
|
||||
forwardAnalysisList.push_back(analyzer);
|
||||
}
|
||||
|
||||
void addBackwardAnalyzer(DataFlowAnalysis *analyzer) {
|
||||
backwardAnalysisList.push_back(analyzer);
|
||||
}
|
||||
|
||||
// 设置分析器列表
|
||||
void setAnalyzers(
|
||||
std::vector<DataFlowAnalysis *> forwardList,
|
||||
std::vector<DataFlowAnalysis *> backwardList)
|
||||
{
|
||||
forwardAnalysisList = std::move(forwardList);
|
||||
backwardAnalysisList = std::move(backwardList);
|
||||
}
|
||||
|
||||
// 清空列表
|
||||
void clear() {
|
||||
forwardAnalysisList.clear();
|
||||
backwardAnalysisList.clear();
|
||||
}
|
||||
|
||||
// 访问器
|
||||
const auto& getForwardAnalyzers() const { return forwardAnalysisList; }
|
||||
const auto& getBackwardAnalyzers() const { return backwardAnalysisList; }
|
||||
|
||||
public:
|
||||
void forwardAnalyze(Module *pModule); ///< 执行前向分析
|
||||
void backwardAnalyze(Module *pModule); ///< 执行后向分析
|
||||
};
|
||||
|
||||
// 活跃变量分析类
|
||||
// 提供def - use分析
|
||||
// 未兼容数组变量但是考虑了维度的use信息
|
||||
class ActiveVarAnalysis : public DataFlowAnalysis {
|
||||
private:
|
||||
std::map<BasicBlock *, std::vector<std::set<User *>>> activeTable; ///< 活跃信息表,存储每个基本块内的的活跃变量信息
|
||||
|
||||
public:
|
||||
ActiveVarAnalysis() = default;
|
||||
~ActiveVarAnalysis() override = default;
|
||||
|
||||
public:
|
||||
static std::set<User*> getUsedSet(Instruction *inst);
|
||||
static User* getDefine(Instruction *inst);
|
||||
|
||||
public:
|
||||
void init(Module *pModule) override;
|
||||
bool analyze(Module *pModule, BasicBlock *block) override;
|
||||
// 外部活跃信息表访问器
|
||||
const std::map<BasicBlock *, std::vector<std::set<User *>>> &getActiveTable() const;
|
||||
void clear() override {
|
||||
activeTable.clear(); // 清空活跃信息表
|
||||
}
|
||||
};
|
||||
|
||||
// 分析管理器
|
||||
class AnalysisManager {
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user