添加数据流分析类,实现前向后向分析的模板动作,实现活跃变量分析,基本借鉴学长代码,后续可优化实现
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
|
} // namespace sysy
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,7 @@ public:
|
|||||||
bool isParallelable() const { return parallelable; }
|
bool isParallelable() const { return parallelable; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 控制流分析类
|
||||||
class ControlFlowAnalysis {
|
class ControlFlowAnalysis {
|
||||||
private:
|
private:
|
||||||
Module *pModule; ///< 模块
|
Module *pModule; ///< 模块
|
||||||
@@ -287,8 +288,111 @@ private:
|
|||||||
BasicBlock* findCommonDominator(BasicBlock *a, BasicBlock *b); // 查找两个基本块的共同支配结点
|
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 {
|
class AnalysisManager {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user