[midend-LoopAnalysis]为项目添加别名分析遍,副作用分析遍,循环分析遍,循环特征分析遍
This commit is contained in:
208
src/include/midend/Pass/Analysis/AliasAnalysis.h
Normal file
208
src/include/midend/Pass/Analysis/AliasAnalysis.h
Normal file
@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class MemoryLocation;
|
||||
class AliasAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 别名关系类型
|
||||
* 按风险等级递增排序
|
||||
*/
|
||||
enum class AliasType {
|
||||
NO_ALIAS = 0, // 确定无别名 (不同的局部数组)
|
||||
SELF_ALIAS = 1, // 自别名 (同一数组的不同索引)
|
||||
POSSIBLE_ALIAS = 2, // 可能有别名 (函数参数数组)
|
||||
UNKNOWN_ALIAS = 3 // 未知 (保守估计)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 内存位置信息
|
||||
* 描述一个内存访问的基础信息
|
||||
*/
|
||||
struct MemoryLocation {
|
||||
Value* basePointer; // 基指针 (剥离GEP后的真实基址)
|
||||
Value* accessPointer; // 访问指针 (包含索引信息)
|
||||
|
||||
// 分类信息
|
||||
bool isLocalArray; // 是否为局部数组
|
||||
bool isFunctionParameter; // 是否为函数参数
|
||||
bool isGlobalArray; // 是否为全局数组
|
||||
|
||||
// 索引信息
|
||||
std::vector<Value*> indices; // GEP索引列表
|
||||
bool hasConstantIndices; // 是否为常量索引
|
||||
bool hasLoopVariableIndex; // 是否包含循环变量
|
||||
int constantOffset; // 常量偏移量 (仅当全部为常量时有效)
|
||||
|
||||
// 访问模式
|
||||
bool hasReads; // 是否有读操作
|
||||
bool hasWrites; // 是否有写操作
|
||||
std::vector<Instruction*> accessInsts; // 所有访问指令
|
||||
|
||||
MemoryLocation(Value* base, Value* access)
|
||||
: basePointer(base), accessPointer(access),
|
||||
isLocalArray(false), isFunctionParameter(false), isGlobalArray(false),
|
||||
hasConstantIndices(false), hasLoopVariableIndex(false), constantOffset(0),
|
||||
hasReads(false), hasWrites(false) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 别名分析结果
|
||||
* 存储一个函数的完整别名分析信息
|
||||
*/
|
||||
class AliasAnalysisResult : public AnalysisResultBase {
|
||||
public:
|
||||
AliasAnalysisResult(Function *F) : AssociatedFunction(F) {}
|
||||
~AliasAnalysisResult() override = default;
|
||||
|
||||
// ========== 基础查询接口 ==========
|
||||
|
||||
/**
|
||||
* 查询两个指针之间的别名关系
|
||||
*/
|
||||
AliasType queryAlias(Value* ptr1, Value* ptr2) const;
|
||||
|
||||
/**
|
||||
* 查询指针的内存位置信息
|
||||
*/
|
||||
const MemoryLocation* getMemoryLocation(Value* ptr) const;
|
||||
|
||||
/**
|
||||
* 获取所有内存位置
|
||||
*/
|
||||
const std::map<Value*, std::unique_ptr<MemoryLocation>>& getAllMemoryLocations() const {
|
||||
return LocationMap;
|
||||
}
|
||||
|
||||
// ========== 高级查询接口 ==========
|
||||
|
||||
/**
|
||||
* 检查指针是否为局部数组
|
||||
*/
|
||||
bool isLocalArray(Value* ptr) const;
|
||||
|
||||
/**
|
||||
* 检查指针是否为函数参数数组
|
||||
*/
|
||||
bool isFunctionParameter(Value* ptr) const;
|
||||
|
||||
/**
|
||||
* 检查指针是否为全局数组
|
||||
*/
|
||||
bool isGlobalArray(Value* ptr) const;
|
||||
|
||||
/**
|
||||
* 检查指针是否使用常量索引
|
||||
*/
|
||||
bool hasConstantAccess(Value* ptr) const;
|
||||
|
||||
// ========== 统计接口 ==========
|
||||
|
||||
/**
|
||||
* 获取各类别名类型的统计信息
|
||||
*/
|
||||
struct Statistics {
|
||||
int totalQueries;
|
||||
int noAlias;
|
||||
int selfAlias;
|
||||
int possibleAlias;
|
||||
int unknownAlias;
|
||||
int localArrays;
|
||||
int functionParameters;
|
||||
int globalArrays;
|
||||
int constantAccesses;
|
||||
};
|
||||
|
||||
Statistics getStatistics() const;
|
||||
|
||||
/**
|
||||
* 打印别名分析结果 (调试用)
|
||||
*/
|
||||
void print() const;
|
||||
|
||||
// ========== 内部方法 ==========
|
||||
|
||||
void addMemoryLocation(std::unique_ptr<MemoryLocation> location);
|
||||
void addAliasRelation(Value* ptr1, Value* ptr2, AliasType type);
|
||||
|
||||
// ========== 公开数据成员 (供Pass使用) ==========
|
||||
std::map<Value*, std::unique_ptr<MemoryLocation>> LocationMap; // 内存位置映射
|
||||
std::map<std::pair<Value*, Value*>, AliasType> AliasMap; // 别名关系缓存
|
||||
|
||||
private:
|
||||
Function *AssociatedFunction; // 关联的函数
|
||||
|
||||
// 分类存储
|
||||
std::vector<Argument*> ArrayParameters; // 数组参数
|
||||
std::vector<AllocaInst*> LocalArrays; // 局部数组
|
||||
std::set<GlobalValue*> AccessedGlobals; // 访问的全局变量
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SysY语言特化的别名分析Pass
|
||||
* 针对SysY语言特性优化的别名分析实现
|
||||
*/
|
||||
class SysYAliasAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
SysYAliasAnalysisPass() : AnalysisPass("SysYAliasAnalysis", Pass::Granularity::Function) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<AliasAnalysisResult> CurrentResult; // 当前函数的分析结果
|
||||
|
||||
// ========== 主要分析流程 ==========
|
||||
|
||||
void collectMemoryAccesses(Function* F); // 收集内存访问
|
||||
void buildAliasRelations(Function* F); // 构建别名关系
|
||||
void optimizeForSysY(Function* F); // SysY特化优化
|
||||
|
||||
// ========== 内存位置分析 ==========
|
||||
|
||||
std::unique_ptr<MemoryLocation> createMemoryLocation(Value* ptr);
|
||||
Value* getBasePointer(Value* ptr); // 获取基指针
|
||||
void analyzeMemoryType(MemoryLocation* location); // 分析内存类型
|
||||
void analyzeIndexPattern(MemoryLocation* location); // 分析索引模式
|
||||
|
||||
// ========== 别名关系推断 ==========
|
||||
|
||||
AliasType analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2);
|
||||
AliasType compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2);
|
||||
AliasType compareParameters(MemoryLocation* loc1, MemoryLocation* loc2);
|
||||
AliasType compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2);
|
||||
AliasType compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2);
|
||||
|
||||
// ========== SysY特化优化 ==========
|
||||
|
||||
void applySysYConstraints(Function* F); // 应用SysY语言约束
|
||||
void optimizeParameterAnalysis(Function* F); // 优化参数分析
|
||||
void optimizeArrayAccessAnalysis(Function* F); // 优化数组访问分析
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
bool isConstantValue(Value* val); // 是否为常量
|
||||
bool hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F);
|
||||
int calculateConstantOffset(const std::vector<Value*>& indices);
|
||||
void printStatistics() const; // 打印统计信息
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@ -4,8 +4,10 @@
|
||||
#include "IR.h" // 包含 IR 定义
|
||||
#include "Pass.h" // 包含 Pass 框架
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <queue> // 用于循环体块的逆向遍历
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@ -92,6 +94,65 @@ public:
|
||||
return backEdgeCount == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有出口目标块 (循环外接收循环出口边的块)
|
||||
* 使用场景: 循环后置处理、phi节点分析
|
||||
*/
|
||||
std::vector<BasicBlock*> getExitTargetBlocks() const {
|
||||
std::set<BasicBlock*> exitTargetSet;
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (BasicBlock* succ : bb->getSuccessors()) {
|
||||
if (!contains(succ)) {
|
||||
exitTargetSet.insert(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<BasicBlock*>(exitTargetSet.begin(), exitTargetSet.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算循环的"深度"相对于指定的祖先循环
|
||||
* 使用场景: 相对深度计算、嵌套分析
|
||||
*/
|
||||
int getRelativeDepth(Loop* ancestor) const {
|
||||
if (this == ancestor) return 0;
|
||||
|
||||
int depth = 0;
|
||||
Loop* current = this->ParentLoop;
|
||||
while (current && current != ancestor) {
|
||||
depth++;
|
||||
current = current->ParentLoop;
|
||||
}
|
||||
|
||||
return current == ancestor ? depth : -1; // -1表示不是祖先关系
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查循环是否包含函数调用
|
||||
* 使用场景: 内联决策、副作用分析
|
||||
*/
|
||||
bool containsFunctionCalls() const {
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (dynamic_cast<CallInst*>(inst.get())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 估算循环的"热度" (基于嵌套深度和大小)
|
||||
* 使用场景: 优化优先级、资源分配
|
||||
*/
|
||||
double getLoopHotness() const {
|
||||
// 简单的热度估算: 深度权重 + 大小惩罚
|
||||
double hotness = std::pow(2.0, Level); // 深度越深越热
|
||||
hotness /= std::sqrt(LoopBlocks.size()); // 大小越大相对热度降低
|
||||
return hotness;
|
||||
}
|
||||
|
||||
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 Loop 对象 ---
|
||||
void addBlock(BasicBlock *BB) { LoopBlocks.insert(BB); }
|
||||
void addExitBlock(BasicBlock *BB) { ExitBlocks.insert(BB); }
|
||||
@ -112,81 +173,345 @@ private:
|
||||
|
||||
/**
|
||||
* @brief 循环分析结果类。
|
||||
* 包含一个函数中所有识别出的循环。
|
||||
* 包含一个函数中所有识别出的循环,并提供高效的查询缓存机制。
|
||||
*/
|
||||
class LoopAnalysisResult : public AnalysisResultBase {
|
||||
public:
|
||||
LoopAnalysisResult(Function *F) : AssociatedFunction(F) {}
|
||||
~LoopAnalysisResult() override = default;
|
||||
|
||||
// ========== 缓存统计结构 ==========
|
||||
struct CacheStats {
|
||||
size_t innermostLoopsCached;
|
||||
size_t outermostLoopsCached;
|
||||
size_t loopsByDepthCached;
|
||||
size_t containingLoopsCached;
|
||||
size_t allNestedLoopsCached;
|
||||
size_t totalCachedQueries;
|
||||
};
|
||||
|
||||
private:
|
||||
// ========== 高频查询缓存 (必须缓存) ==========
|
||||
mutable std::optional<std::vector<Loop*>> cachedInnermostLoops;
|
||||
mutable std::optional<std::vector<Loop*>> cachedOutermostLoops;
|
||||
mutable std::optional<int> cachedMaxDepth;
|
||||
mutable std::optional<size_t> cachedLoopCount;
|
||||
mutable std::map<int, std::vector<Loop*>> cachedLoopsByDepth;
|
||||
|
||||
// ========== 中频查询缓存 (选择性缓存) ==========
|
||||
mutable std::map<BasicBlock*, Loop*> cachedInnermostContainingLoop;
|
||||
mutable std::map<Loop*, std::set<Loop*>> cachedAllNestedLoops; // 递归嵌套
|
||||
mutable std::map<BasicBlock*, std::vector<Loop*>> cachedAllContainingLoops;
|
||||
|
||||
// ========== 缓存状态管理 ==========
|
||||
mutable bool cacheValid = true;
|
||||
|
||||
// 内部辅助方法
|
||||
void invalidateCache() const {
|
||||
cachedInnermostLoops.reset();
|
||||
cachedOutermostLoops.reset();
|
||||
cachedMaxDepth.reset();
|
||||
cachedLoopCount.reset();
|
||||
cachedLoopsByDepth.clear();
|
||||
cachedInnermostContainingLoop.clear();
|
||||
cachedAllNestedLoops.clear();
|
||||
cachedAllContainingLoops.clear();
|
||||
cacheValid = false;
|
||||
}
|
||||
|
||||
void ensureCacheValid() const {
|
||||
if (!cacheValid) {
|
||||
// 重新计算基础缓存
|
||||
computeBasicCache();
|
||||
cacheValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
void computeBasicCache() const {
|
||||
// 计算最内层循环
|
||||
if (!cachedInnermostLoops) {
|
||||
cachedInnermostLoops = std::vector<Loop*>();
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->isInnermost()) {
|
||||
cachedInnermostLoops->push_back(loop.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算最外层循环
|
||||
if (!cachedOutermostLoops) {
|
||||
cachedOutermostLoops = std::vector<Loop*>();
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->isOutermost()) {
|
||||
cachedOutermostLoops->push_back(loop.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算最大深度
|
||||
if (!cachedMaxDepth) {
|
||||
int maxDepth = 0;
|
||||
for (const auto& loop : AllLoops) {
|
||||
maxDepth = std::max(maxDepth, loop->getLoopDepth());
|
||||
}
|
||||
cachedMaxDepth = maxDepth;
|
||||
}
|
||||
|
||||
// 计算循环总数
|
||||
if (!cachedLoopCount) {
|
||||
cachedLoopCount = AllLoops.size();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// ========== 基础接口 (保持向后兼容,但增加缓存失效) ==========
|
||||
|
||||
// 添加一个识别出的循环到结果中
|
||||
void addLoop(std::unique_ptr<Loop> loop) {
|
||||
invalidateCache(); // 添加新循环时失效缓存
|
||||
AllLoops.push_back(std::move(loop));
|
||||
// 也可以选择将 Loop* 存储到 map 中,方便通过 header 查找
|
||||
LoopMap[AllLoops.back()->getHeader()] = AllLoops.back().get();
|
||||
}
|
||||
|
||||
// 获取所有识别出的循环(unique_ptr 管理内存)
|
||||
const std::vector<std::unique_ptr<Loop>> &getAllLoops() const { return AllLoops; }
|
||||
|
||||
// 获取所有最外层循环
|
||||
const std::vector<Loop *> &getOutermostLoops() const { return OutermostLoops; }
|
||||
|
||||
const std::vector<Loop *> &getInnermostLoops() const { return InnermostLoops; }
|
||||
|
||||
// 获取循环总数
|
||||
size_t getLoopCount() const { return AllLoops.size(); }
|
||||
|
||||
// 获取最大循环嵌套深度
|
||||
int getMaxLoopDepth() const {
|
||||
int maxDepth = 0;
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->getLoopDepth() > maxDepth) {
|
||||
maxDepth = loop->getLoopDepth();
|
||||
// ========== 高频查询接口 (缓存优化) ==========
|
||||
|
||||
/**
|
||||
* 获取所有最内层循环 - 循环优化的主要目标
|
||||
* 使用场景: 循环展开、向量化、循环不变量外提
|
||||
*/
|
||||
const std::vector<Loop*>& getInnermostLoops() const {
|
||||
ensureCacheValid();
|
||||
if (!cachedInnermostLoops) {
|
||||
cachedInnermostLoops = std::vector<Loop*>();
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->isInnermost()) {
|
||||
cachedInnermostLoops->push_back(loop.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxDepth;
|
||||
return *cachedInnermostLoops;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有最外层循环
|
||||
* 使用场景: 循环树遍历、整体优化策略
|
||||
*/
|
||||
const std::vector<Loop*>& getOutermostLoops() const {
|
||||
ensureCacheValid();
|
||||
if (!cachedOutermostLoops) {
|
||||
cachedOutermostLoops = std::vector<Loop*>();
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->isOutermost()) {
|
||||
cachedOutermostLoops->push_back(loop.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return *cachedOutermostLoops;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定深度的所有循环
|
||||
* 使用场景: 分层优化、循环展开决策、并行化分析
|
||||
*/
|
||||
const std::vector<Loop*>& getLoopsAtDepth(int depth) const {
|
||||
ensureCacheValid();
|
||||
if (cachedLoopsByDepth.find(depth) == cachedLoopsByDepth.end()) {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->getLoopDepth() == depth) {
|
||||
result.push_back(loop.get());
|
||||
}
|
||||
}
|
||||
cachedLoopsByDepth[depth] = std::move(result);
|
||||
}
|
||||
return cachedLoopsByDepth[depth];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大循环嵌套深度
|
||||
* 使用场景: 优化预算分配、编译时间控制
|
||||
*/
|
||||
int getMaxLoopDepth() const {
|
||||
ensureCacheValid();
|
||||
if (!cachedMaxDepth) {
|
||||
int maxDepth = 0;
|
||||
for (const auto& loop : AllLoops) {
|
||||
maxDepth = std::max(maxDepth, loop->getLoopDepth());
|
||||
}
|
||||
cachedMaxDepth = maxDepth;
|
||||
}
|
||||
return *cachedMaxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取循环总数
|
||||
* 使用场景: 统计信息、优化决策
|
||||
*/
|
||||
size_t getLoopCount() const {
|
||||
ensureCacheValid();
|
||||
if (!cachedLoopCount) {
|
||||
cachedLoopCount = AllLoops.size();
|
||||
}
|
||||
return *cachedLoopCount;
|
||||
}
|
||||
|
||||
// 获取指定深度的循环数量
|
||||
size_t getLoopCountAtDepth(int depth) const {
|
||||
size_t count = 0;
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->getLoopDepth() == depth) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
return getLoopsAtDepth(depth).size();
|
||||
}
|
||||
|
||||
// 检查函数是否包含循环
|
||||
bool hasLoops() const { return !AllLoops.empty(); }
|
||||
|
||||
// ========== 中频查询接口 (选择性缓存) ==========
|
||||
|
||||
/**
|
||||
* 获取包含指定基本块的最内层循环
|
||||
* 使用场景: 活跃性分析、寄存器分配、指令调度
|
||||
*/
|
||||
Loop* getInnermostContainingLoop(BasicBlock* BB) const {
|
||||
ensureCacheValid();
|
||||
if (cachedInnermostContainingLoop.find(BB) == cachedInnermostContainingLoop.end()) {
|
||||
Loop* result = nullptr;
|
||||
int maxDepth = -1;
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->contains(BB) && loop->getLoopDepth() > maxDepth) {
|
||||
result = loop.get();
|
||||
maxDepth = loop->getLoopDepth();
|
||||
}
|
||||
}
|
||||
cachedInnermostContainingLoop[BB] = result;
|
||||
}
|
||||
return cachedInnermostContainingLoop[BB];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包含指定基本块的所有循环 (从外到内排序)
|
||||
* 使用场景: 循环间优化、依赖分析
|
||||
*/
|
||||
const std::vector<Loop*>& getAllContainingLoops(BasicBlock* BB) const {
|
||||
ensureCacheValid();
|
||||
if (cachedAllContainingLoops.find(BB) == cachedAllContainingLoops.end()) {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (loop->contains(BB)) {
|
||||
result.push_back(loop.get());
|
||||
}
|
||||
}
|
||||
// 按深度排序 (外层到内层)
|
||||
std::sort(result.begin(), result.end(),
|
||||
[](Loop* a, Loop* b) { return a->getLoopDepth() < b->getLoopDepth(); });
|
||||
cachedAllContainingLoops[BB] = std::move(result);
|
||||
}
|
||||
return cachedAllContainingLoops[BB];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定循环的所有嵌套子循环 (递归)
|
||||
* 使用场景: 循环树分析、嵌套优化
|
||||
*/
|
||||
const std::set<Loop*>& getAllNestedLoops(Loop* loop) const {
|
||||
ensureCacheValid();
|
||||
if (cachedAllNestedLoops.find(loop) == cachedAllNestedLoops.end()) {
|
||||
std::set<Loop*> result;
|
||||
std::function<void(Loop*)> collectNested = [&](Loop* current) {
|
||||
for (Loop* nested : current->getNestedLoops()) {
|
||||
result.insert(nested);
|
||||
collectNested(nested); // 递归收集
|
||||
}
|
||||
};
|
||||
collectNested(loop);
|
||||
cachedAllNestedLoops[loop] = std::move(result);
|
||||
}
|
||||
return cachedAllNestedLoops[loop];
|
||||
}
|
||||
|
||||
// ========== 低频查询接口 (按需计算,不缓存) ==========
|
||||
|
||||
/**
|
||||
* 检查两个循环是否有嵌套关系
|
||||
* 使用场景: 循环间依赖分析
|
||||
*/
|
||||
bool isNestedLoop(Loop* inner, Loop* outer) const {
|
||||
if (inner == outer) return false;
|
||||
|
||||
Loop* current = inner->getParentLoop();
|
||||
while (current) {
|
||||
if (current == outer) return true;
|
||||
current = current->getParentLoop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个循环的最近公共祖先循环
|
||||
* 使用场景: 循环融合分析、优化范围确定
|
||||
*/
|
||||
Loop* getLowestCommonAncestor(Loop* loop1, Loop* loop2) const {
|
||||
if (!loop1 || !loop2) return nullptr;
|
||||
if (loop1 == loop2) return loop1;
|
||||
|
||||
// 收集loop1的所有祖先
|
||||
std::set<Loop*> ancestors1;
|
||||
Loop* current = loop1;
|
||||
while (current) {
|
||||
ancestors1.insert(current);
|
||||
current = current->getParentLoop();
|
||||
}
|
||||
|
||||
// 查找loop2祖先链中第一个在ancestors1中的循环
|
||||
current = loop2;
|
||||
while (current) {
|
||||
if (ancestors1.count(current)) {
|
||||
return current;
|
||||
}
|
||||
current = current->getParentLoop();
|
||||
}
|
||||
|
||||
return nullptr; // 没有公共祖先
|
||||
}
|
||||
|
||||
// 通过循环头获取 Loop 对象
|
||||
Loop *getLoopForHeader(BasicBlock *header) const {
|
||||
auto it = LoopMap.find(header);
|
||||
return (it != LoopMap.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
// 通过某个基本块获取包含它的最内层循环
|
||||
// 通过某个基本块获取包含它的最内层循环 (向后兼容接口)
|
||||
Loop *getLoopContainingBlock(BasicBlock *BB) const {
|
||||
// 遍历所有循环,找到包含 BB 且层级最深的循环
|
||||
Loop *innermostContainingLoop = nullptr;
|
||||
for (const auto &loop_ptr : AllLoops) {
|
||||
if (loop_ptr->contains(BB)) {
|
||||
if (!innermostContainingLoop || loop_ptr->getLoopLevel() > innermostContainingLoop->getLoopLevel()) {
|
||||
innermostContainingLoop = loop_ptr.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return innermostContainingLoop;
|
||||
return getInnermostContainingLoop(BB);
|
||||
}
|
||||
|
||||
// --- 供 LoopAnalysisPass 内部调用的方法,用于构建 LoopAnalysisResult 对象 ---
|
||||
void addOutermostLoop(Loop *loop) { OutermostLoops.push_back(loop); }
|
||||
void addInnermostLoop(Loop *loop) { InnermostLoops.push_back(loop); }
|
||||
void clearOutermostLoops() { OutermostLoops.clear(); }
|
||||
void clearInnermostLoops() { InnermostLoops.clear(); }
|
||||
// ========== 缓存管理接口 ==========
|
||||
|
||||
/**
|
||||
* 手动失效缓存 (当IR结构改变时调用)
|
||||
*/
|
||||
void invalidateQueryCache() const {
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存统计信息 (用于性能调试)
|
||||
*/
|
||||
CacheStats getCacheStats() const {
|
||||
CacheStats stats = {};
|
||||
stats.innermostLoopsCached = cachedInnermostLoops.has_value() ? 1 : 0;
|
||||
stats.outermostLoopsCached = cachedOutermostLoops.has_value() ? 1 : 0;
|
||||
stats.loopsByDepthCached = cachedLoopsByDepth.size();
|
||||
stats.containingLoopsCached = cachedInnermostContainingLoop.size();
|
||||
stats.allNestedLoopsCached = cachedAllNestedLoops.size();
|
||||
stats.totalCachedQueries = stats.innermostLoopsCached + stats.outermostLoopsCached +
|
||||
stats.loopsByDepthCached + stats.containingLoopsCached +
|
||||
stats.allNestedLoopsCached;
|
||||
return stats;
|
||||
}
|
||||
|
||||
// --- 保留的内部接口 ---
|
||||
// 注意:由于使用了缓存机制,不再需要手动维护最外层和最内层循环列表
|
||||
|
||||
// 打印分析结果
|
||||
void print() const;
|
||||
@ -197,8 +522,7 @@ private:
|
||||
Function *AssociatedFunction; // 结果关联的函数
|
||||
std::vector<std::unique_ptr<Loop>> AllLoops; // 所有识别出的循环
|
||||
std::map<BasicBlock *, Loop *> LoopMap; // 循环头到 Loop* 的映射,方便查找
|
||||
std::vector<Loop *> OutermostLoops; // 最外层循环的列表
|
||||
std::vector<Loop *> InnermostLoops; // 最内层循环的列表
|
||||
// 注意: 最外层和最内层循环列表已移除,现在通过缓存机制动态计算
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
301
src/include/midend/Pass/Analysis/LoopCharacteristics.h
Normal file
301
src/include/midend/Pass/Analysis/LoopCharacteristics.h
Normal file
@ -0,0 +1,301 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dom.h" // 支配树分析依赖
|
||||
#include "Loop.h" // 循环分析依赖
|
||||
#include "Liveness.h" // 活跃性分析依赖
|
||||
#include "AliasAnalysis.h" // 别名分析依赖
|
||||
#include "IR.h" // IR定义
|
||||
#include "Pass.h" // Pass框架
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class LoopCharacteristicsResult;
|
||||
|
||||
/**
|
||||
* @brief 循环特征信息结构
|
||||
* 存储单个循环的各种特征信息
|
||||
*/
|
||||
struct LoopCharacteristics {
|
||||
Loop* loop; // 关联的循环对象
|
||||
|
||||
// ========== 归纳变量分析 ==========
|
||||
std::vector<Value*> basicInductionVars; // 基本归纳变量 (i = phi(init, i+step))
|
||||
std::vector<Value*> derivedInductionVars; // 派生归纳变量 (j = i * scale + offset)
|
||||
std::map<Value*, int> inductionSteps; // 归纳变量的步长
|
||||
std::map<Value*, Value*> inductionInits; // 归纳变量的初始值
|
||||
|
||||
// ========== 循环不变量分析 ==========
|
||||
std::set<Value*> loopInvariants; // 循环不变量 (循环内定义但值不变)
|
||||
std::set<Instruction*> invariantInsts; // 不变指令 (可以外提的指令)
|
||||
|
||||
// ========== 循环边界分析 ==========
|
||||
std::optional<int> staticTripCount; // 静态可确定的循环次数
|
||||
Value* dynamicTripCountExpr; // 动态循环次数表达式
|
||||
bool hasKnownBounds; // 是否有已知边界
|
||||
Value* lowerBound; // 循环下界
|
||||
Value* upperBound; // 循环上界
|
||||
|
||||
// ========== 循环形式分析 ==========
|
||||
bool isCountingLoop; // 是否为计数循环 (for i=0; i<n; i++)
|
||||
bool isSimpleForLoop; // 是否为简单for循环
|
||||
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
||||
bool isInnermost; // 是否为最内层循环
|
||||
bool isParallel; // 是否可并行化
|
||||
|
||||
// ========== 内存访问模式 ==========
|
||||
struct MemoryAccessPattern {
|
||||
bool isSequential; // 是否顺序访问 (a[i], a[i+1], ...)
|
||||
bool isStrided; // 是否跨步访问 (a[2*i], a[3*i], ...)
|
||||
int stride; // 访问步长
|
||||
std::vector<Instruction*> loadInsts; // load指令列表
|
||||
std::vector<Instruction*> storeInsts; // store指令列表
|
||||
|
||||
// 使用外部别名分析结果
|
||||
AliasType aliasType; // 别名类型(来自别名分析)
|
||||
bool isArrayParameter; // 是否为数组参数访问
|
||||
bool isGlobalArray; // 是否为全局数组访问
|
||||
bool hasConstantIndices; // 是否使用常量索引
|
||||
};
|
||||
std::map<Value*, MemoryAccessPattern> memoryPatterns; // 内存访问模式
|
||||
|
||||
// ========== 循环优化提示 ==========
|
||||
bool benefitsFromUnrolling; // 是否适合循环展开
|
||||
bool benefitsFromVectorization; // 是否适合向量化
|
||||
bool benefitsFromTiling; // 是否适合分块
|
||||
int suggestedUnrollFactor; // 建议的展开因子
|
||||
|
||||
// ========== 性能特征 ==========
|
||||
size_t instructionCount; // 循环体指令数
|
||||
size_t memoryOperationCount; // 内存操作数
|
||||
size_t arithmeticOperationCount; // 算术操作数
|
||||
double computeToMemoryRatio; // 计算与内存操作比率
|
||||
|
||||
// 构造函数
|
||||
LoopCharacteristics(Loop* l) : loop(l), dynamicTripCountExpr(nullptr),
|
||||
hasKnownBounds(false), lowerBound(nullptr), upperBound(nullptr),
|
||||
isCountingLoop(false), isSimpleForLoop(false), hasComplexControlFlow(false),
|
||||
isInnermost(false), isParallel(false), benefitsFromUnrolling(false),
|
||||
benefitsFromVectorization(false), benefitsFromTiling(false),
|
||||
suggestedUnrollFactor(1), instructionCount(0), memoryOperationCount(0),
|
||||
arithmeticOperationCount(0), computeToMemoryRatio(0.0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环特征分析结果类
|
||||
* 包含函数中所有循环的特征信息,并提供查询接口
|
||||
*/
|
||||
class LoopCharacteristicsResult : public AnalysisResultBase {
|
||||
public:
|
||||
LoopCharacteristicsResult(Function *F) : AssociatedFunction(F) {}
|
||||
~LoopCharacteristicsResult() override = default;
|
||||
|
||||
// ========== 基础接口 ==========
|
||||
|
||||
/**
|
||||
* 添加循环特征信息
|
||||
*/
|
||||
void addLoopCharacteristics(std::unique_ptr<LoopCharacteristics> characteristics) {
|
||||
auto* loop = characteristics->loop;
|
||||
CharacteristicsMap[loop] = std::move(characteristics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定循环的特征信息
|
||||
*/
|
||||
const LoopCharacteristics* getCharacteristics(Loop* loop) const {
|
||||
auto it = CharacteristicsMap.find(loop);
|
||||
return (it != CharacteristicsMap.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有循环特征信息
|
||||
*/
|
||||
const std::map<Loop*, std::unique_ptr<LoopCharacteristics>>& getAllCharacteristics() const {
|
||||
return CharacteristicsMap;
|
||||
}
|
||||
|
||||
// ========== 查询接口 ==========
|
||||
|
||||
/**
|
||||
* 获取所有计数循环
|
||||
*/
|
||||
std::vector<Loop*> getCountingLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->isCountingLoop) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可向量化循环
|
||||
*/
|
||||
std::vector<Loop*> getVectorizableLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->benefitsFromVectorization) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有适合展开的循环
|
||||
*/
|
||||
std::vector<Loop*> getUnrollCandidateLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->benefitsFromUnrolling) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有可并行化循环
|
||||
*/
|
||||
std::vector<Loop*> getParallelizableLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->isParallel) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有有静态已知循环次数的循环
|
||||
*/
|
||||
std::vector<Loop*> getStaticBoundLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->staticTripCount.has_value()) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据热度排序循环 (用于优化优先级)
|
||||
*/
|
||||
std::vector<Loop*> getLoopsByHotness() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
|
||||
// 按循环热度排序 (嵌套深度 + 循环次数 + 指令数)
|
||||
std::sort(result.begin(), result.end(), [](Loop* a, Loop* b) {
|
||||
double hotnessA = a->getLoopHotness();
|
||||
double hotnessB = b->getLoopHotness();
|
||||
return hotnessA > hotnessB; // 降序排列
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ========== 统计接口 ==========
|
||||
|
||||
/**
|
||||
* 获取优化候选统计
|
||||
*/
|
||||
struct OptimizationStats {
|
||||
size_t totalLoops;
|
||||
size_t countingLoops;
|
||||
size_t vectorizableLoops;
|
||||
size_t unrollCandidates;
|
||||
size_t parallelizableLoops;
|
||||
size_t staticBoundLoops;
|
||||
double avgInstructionCount;
|
||||
double avgComputeMemoryRatio;
|
||||
};
|
||||
|
||||
OptimizationStats getOptimizationStats() const {
|
||||
OptimizationStats stats = {};
|
||||
stats.totalLoops = CharacteristicsMap.size();
|
||||
|
||||
size_t totalInstructions = 0;
|
||||
double totalComputeMemoryRatio = 0.0;
|
||||
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->isCountingLoop) stats.countingLoops++;
|
||||
if (chars->benefitsFromVectorization) stats.vectorizableLoops++;
|
||||
if (chars->benefitsFromUnrolling) stats.unrollCandidates++;
|
||||
if (chars->isParallel) stats.parallelizableLoops++;
|
||||
if (chars->staticTripCount.has_value()) stats.staticBoundLoops++;
|
||||
|
||||
totalInstructions += chars->instructionCount;
|
||||
totalComputeMemoryRatio += chars->computeToMemoryRatio;
|
||||
}
|
||||
|
||||
if (stats.totalLoops > 0) {
|
||||
stats.avgInstructionCount = static_cast<double>(totalInstructions) / stats.totalLoops;
|
||||
stats.avgComputeMemoryRatio = totalComputeMemoryRatio / stats.totalLoops;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
// 打印分析结果
|
||||
void print() const;
|
||||
|
||||
private:
|
||||
Function *AssociatedFunction; // 关联的函数
|
||||
std::map<Loop*, std::unique_ptr<LoopCharacteristics>> CharacteristicsMap; // 循环特征映射
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环特征分析遍
|
||||
* 基于循环分析结果,分析每个循环的特征信息,为优化决策提供依据
|
||||
*/
|
||||
class LoopCharacteristicsPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
LoopCharacteristicsPass() : AnalysisPass("LoopCharacteristics", Pass::Granularity::Function) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<LoopCharacteristicsResult> CurrentResult; // 当前函数的分析结果
|
||||
|
||||
// 内部分析方法
|
||||
void analyzeLoop(Loop* loop, LoopCharacteristics* characteristics, AnalysisManager &AM);
|
||||
void identifyInductionVariables(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void identifyLoopInvariants(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void analyzeLoopBounds(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void analyzeLoopForm(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void analyzeMemoryAccessPatterns(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void evaluateOptimizationOpportunities(Loop* loop, LoopCharacteristics* characteristics);
|
||||
void computePerformanceMetrics(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 辅助方法
|
||||
bool isInductionVariable(Value* val, Loop* loop);
|
||||
bool isLoopInvariant(Value* val, Loop* loop);
|
||||
bool hasLoopCarriedDependence(Loop* loop);
|
||||
int estimateUnrollFactor(Loop* loop);
|
||||
bool benefitsFromVectorization(Loop* loop);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
126
src/include/midend/Pass/Analysis/SideEffectAnalysis.h
Normal file
126
src/include/midend/Pass/Analysis/SideEffectAnalysis.h
Normal file
@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 副作用类型枚举
|
||||
enum class SideEffectType {
|
||||
NO_SIDE_EFFECT, // 无副作用
|
||||
MEMORY_WRITE, // 内存写入(store、memset)
|
||||
FUNCTION_CALL, // 函数调用(可能有任意副作用)
|
||||
IO_OPERATION, // I/O操作(printf、scanf等)
|
||||
UNKNOWN // 未知副作用
|
||||
};
|
||||
|
||||
// 副作用信息结构
|
||||
struct SideEffectInfo {
|
||||
SideEffectType type = SideEffectType::NO_SIDE_EFFECT;
|
||||
bool mayModifyGlobal = false; // 可能修改全局变量
|
||||
bool mayModifyMemory = false; // 可能修改内存
|
||||
bool mayCallFunction = false; // 可能调用函数
|
||||
bool isPure = true; // 是否为纯函数(无副作用且结果只依赖参数)
|
||||
|
||||
// 合并两个副作用信息
|
||||
SideEffectInfo merge(const SideEffectInfo& other) const {
|
||||
SideEffectInfo result;
|
||||
result.type = (type == SideEffectType::NO_SIDE_EFFECT) ? other.type : type;
|
||||
result.mayModifyGlobal = mayModifyGlobal || other.mayModifyGlobal;
|
||||
result.mayModifyMemory = mayModifyMemory || other.mayModifyMemory;
|
||||
result.mayCallFunction = mayCallFunction || other.mayCallFunction;
|
||||
result.isPure = isPure && other.isPure;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// 副作用分析结果类
|
||||
class SideEffectAnalysisResult : public AnalysisResultBase {
|
||||
private:
|
||||
// 指令级别的副作用信息
|
||||
std::unordered_map<Instruction*, SideEffectInfo> instructionSideEffects;
|
||||
|
||||
// 函数级别的副作用信息
|
||||
std::unordered_map<Function*, SideEffectInfo> functionSideEffects;
|
||||
|
||||
// 已知的SysY标准库函数副作用信息
|
||||
std::unordered_map<std::string, SideEffectInfo> knownFunctions;
|
||||
|
||||
public:
|
||||
SideEffectAnalysisResult();
|
||||
virtual ~SideEffectAnalysisResult() noexcept override = default;
|
||||
|
||||
// 获取指令的副作用信息
|
||||
const SideEffectInfo& getInstructionSideEffect(Instruction* inst) const;
|
||||
|
||||
// 获取函数的副作用信息
|
||||
const SideEffectInfo& getFunctionSideEffect(Function* func) const;
|
||||
|
||||
// 设置指令的副作用信息
|
||||
void setInstructionSideEffect(Instruction* inst, const SideEffectInfo& info);
|
||||
|
||||
// 设置函数的副作用信息
|
||||
void setFunctionSideEffect(Function* func, const SideEffectInfo& info);
|
||||
|
||||
// 检查指令是否有副作用
|
||||
bool hasSideEffect(Instruction* inst) const;
|
||||
|
||||
// 检查指令是否可能修改内存
|
||||
bool mayModifyMemory(Instruction* inst) const;
|
||||
|
||||
// 检查指令是否可能修改全局状态
|
||||
bool mayModifyGlobal(Instruction* inst) const;
|
||||
|
||||
// 检查函数是否为纯函数
|
||||
bool isPureFunction(Function* func) const;
|
||||
|
||||
// 获取已知函数的副作用信息
|
||||
const SideEffectInfo* getKnownFunctionSideEffect(const std::string& funcName) const;
|
||||
|
||||
// 初始化已知函数的副作用信息
|
||||
void initializeKnownFunctions();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
// 副作用分析遍类
|
||||
class SysYSideEffectAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 静态成员,作为该遍的唯一ID
|
||||
static void* ID;
|
||||
|
||||
SysYSideEffectAnalysisPass() : AnalysisPass("SysYSideEffectAnalysis", Granularity::Function) {}
|
||||
|
||||
// 在函数上运行分析
|
||||
bool runOnFunction(Function* F, AnalysisManager& AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override;
|
||||
|
||||
// Pass 基类中的纯虚函数,必须实现
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
private:
|
||||
// 分析结果
|
||||
std::unique_ptr<SideEffectAnalysisResult> result;
|
||||
|
||||
// 别名分析结果(在整个函数分析过程中重复使用)
|
||||
AliasAnalysisResult* aliasAnalysis = nullptr;
|
||||
|
||||
// 分析单个指令的副作用
|
||||
SideEffectInfo analyzeInstruction(Instruction* inst, AnalysisManager& AM);
|
||||
|
||||
// 分析函数调用指令的副作用
|
||||
SideEffectInfo analyzeCallInstruction(CallInst* call, AnalysisManager& AM);
|
||||
|
||||
// 分析存储指令的副作用
|
||||
SideEffectInfo analyzeStoreInstruction(StoreInst* store, AnalysisManager& AM);
|
||||
|
||||
// 分析内存设置指令的副作用
|
||||
SideEffectInfo analyzeMemsetInstruction(MemsetInst* memset, AnalysisManager& AM);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@ -151,17 +151,21 @@ public:
|
||||
}
|
||||
AnalysisPass *analysisPass = static_cast<AnalysisPass *>(basePass.get());
|
||||
|
||||
if(DEBUG){
|
||||
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
}
|
||||
// 根据分析遍的粒度处理
|
||||
switch (analysisPass->getGranularity()) {
|
||||
case Pass::Granularity::Module: {
|
||||
// 检查是否已存在有效结果
|
||||
auto it = moduleCachedResults.find(analysisID);
|
||||
if (it != moduleCachedResults.end()) {
|
||||
if(DEBUG) {
|
||||
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
}
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 只有在实际运行时才打印调试信息
|
||||
if(DEBUG){
|
||||
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
}
|
||||
// 运行模块级分析遍
|
||||
if (!pModuleRef) {
|
||||
std::cerr << "Error: Module reference not set for AnalysisManager to run Module Pass.\n";
|
||||
@ -183,8 +187,16 @@ public:
|
||||
// 检查是否已存在有效结果
|
||||
auto it = functionCachedResults.find({F, analysisID});
|
||||
if (it != functionCachedResults.end()) {
|
||||
if(DEBUG) {
|
||||
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << " (Function: " << F->getName() << ")\n";
|
||||
}
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 只有在实际运行时才打印调试信息
|
||||
if(DEBUG){
|
||||
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
std::cout << "Function: " << F->getName() << "\n";
|
||||
}
|
||||
// 运行函数级分析遍
|
||||
analysisPass->runOnFunction(F, *this);
|
||||
// 获取结果并缓存
|
||||
@ -202,8 +214,16 @@ public:
|
||||
// 检查是否已存在有效结果
|
||||
auto it = basicBlockCachedResults.find({BB, analysisID});
|
||||
if (it != basicBlockCachedResults.end()) {
|
||||
if(DEBUG) {
|
||||
std::cout << "Using cached result for Analysis Pass: " << analysisPass->getName() << " (BasicBlock: " << BB->getName() << ")\n";
|
||||
}
|
||||
return static_cast<T *>(it->second.get()); // 返回缓存结果
|
||||
}
|
||||
// 只有在实际运行时才打印调试信息
|
||||
if(DEBUG){
|
||||
std::cout << "Running Analysis Pass: " << analysisPass->getName() << "\n";
|
||||
std::cout << "BasicBlock: " << BB->getName() << "\n";
|
||||
}
|
||||
// 运行基本块级分析遍
|
||||
analysisPass->runOnBasicBlock(BB, *this);
|
||||
// 获取结果并缓存
|
||||
|
||||
@ -7,6 +7,9 @@ add_library(midend_lib STATIC
|
||||
Pass/Analysis/Dom.cpp
|
||||
Pass/Analysis/Liveness.cpp
|
||||
Pass/Analysis/Loop.cpp
|
||||
Pass/Analysis/LoopCharacteristics.cpp
|
||||
Pass/Analysis/AliasAnalysis.cpp
|
||||
Pass/Analysis/SideEffectAnalysis.cpp
|
||||
Pass/Optimize/DCE.cpp
|
||||
Pass/Optimize/Mem2Reg.cpp
|
||||
Pass/Optimize/Reg2Mem.cpp
|
||||
|
||||
380
src/midend/Pass/Analysis/AliasAnalysis.cpp
Normal file
380
src/midend/Pass/Analysis/AliasAnalysis.cpp
Normal file
@ -0,0 +1,380 @@
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include <iostream>
|
||||
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 静态成员初始化
|
||||
void *SysYAliasAnalysisPass::ID = (void *)&SysYAliasAnalysisPass::ID;
|
||||
|
||||
// ========== AliasAnalysisResult 实现 ==========
|
||||
|
||||
void AliasAnalysisResult::print() const {
|
||||
std::cout << "---- Alias Analysis Results for Function: " << AssociatedFunction->getName() << " ----\n";
|
||||
|
||||
// 打印内存位置信息
|
||||
std::cout << " Memory Locations (" << LocationMap.size() << "):\n";
|
||||
for (const auto& pair : LocationMap) {
|
||||
const auto& loc = pair.second;
|
||||
std::cout << " - Base: " << loc->basePointer->getName();
|
||||
std::cout << " (Type: ";
|
||||
if (loc->isLocalArray) std::cout << "Local";
|
||||
else if (loc->isFunctionParameter) std::cout << "Parameter";
|
||||
else if (loc->isGlobalArray) std::cout << "Global";
|
||||
else std::cout << "Unknown";
|
||||
std::cout << ")\n";
|
||||
}
|
||||
|
||||
// 打印别名关系
|
||||
std::cout << " Alias Relations (" << AliasMap.size() << "):\n";
|
||||
for (const auto& pair : AliasMap) {
|
||||
std::cout << " - (" << pair.first.first->getName() << ", " << pair.first.second->getName() << "): ";
|
||||
switch (pair.second) {
|
||||
case AliasType::NO_ALIAS: std::cout << "No Alias"; break;
|
||||
case AliasType::SELF_ALIAS: std::cout << "Self Alias"; break;
|
||||
case AliasType::POSSIBLE_ALIAS: std::cout << "Possible Alias"; break;
|
||||
case AliasType::UNKNOWN_ALIAS: std::cout << "Unknown Alias"; break;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
std::cout << "-----------------------------------------------------------\n";
|
||||
}
|
||||
|
||||
AliasType AliasAnalysisResult::queryAlias(Value* ptr1, Value* ptr2) const {
|
||||
auto key = std::make_pair(ptr1, ptr2);
|
||||
auto it = AliasMap.find(key);
|
||||
if (it != AliasMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// 尝试反向查找
|
||||
key = std::make_pair(ptr2, ptr1);
|
||||
it = AliasMap.find(key);
|
||||
if (it != AliasMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return AliasType::UNKNOWN_ALIAS; // 保守估计
|
||||
}
|
||||
|
||||
const MemoryLocation* AliasAnalysisResult::getMemoryLocation(Value* ptr) const {
|
||||
auto it = LocationMap.find(ptr);
|
||||
return (it != LocationMap.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
bool AliasAnalysisResult::isLocalArray(Value* ptr) const {
|
||||
const MemoryLocation* loc = getMemoryLocation(ptr);
|
||||
return loc && loc->isLocalArray;
|
||||
}
|
||||
|
||||
bool AliasAnalysisResult::isFunctionParameter(Value* ptr) const {
|
||||
const MemoryLocation* loc = getMemoryLocation(ptr);
|
||||
return loc && loc->isFunctionParameter;
|
||||
}
|
||||
|
||||
bool AliasAnalysisResult::isGlobalArray(Value* ptr) const {
|
||||
const MemoryLocation* loc = getMemoryLocation(ptr);
|
||||
return loc && loc->isGlobalArray;
|
||||
}
|
||||
|
||||
bool AliasAnalysisResult::hasConstantAccess(Value* ptr) const {
|
||||
const MemoryLocation* loc = getMemoryLocation(ptr);
|
||||
return loc && loc->hasConstantIndices;
|
||||
}
|
||||
|
||||
AliasAnalysisResult::Statistics AliasAnalysisResult::getStatistics() const {
|
||||
Statistics stats = {0};
|
||||
|
||||
stats.totalQueries = AliasMap.size();
|
||||
|
||||
for (auto& pair : AliasMap) {
|
||||
switch (pair.second) {
|
||||
case AliasType::NO_ALIAS: stats.noAlias++; break;
|
||||
case AliasType::SELF_ALIAS: stats.selfAlias++; break;
|
||||
case AliasType::POSSIBLE_ALIAS: stats.possibleAlias++; break;
|
||||
case AliasType::UNKNOWN_ALIAS: stats.unknownAlias++; break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& loc : LocationMap) {
|
||||
if (loc.second->isLocalArray) stats.localArrays++;
|
||||
if (loc.second->isFunctionParameter) stats.functionParameters++;
|
||||
if (loc.second->isGlobalArray) stats.globalArrays++;
|
||||
if (loc.second->hasConstantIndices) stats.constantAccesses++;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
// void AliasAnalysisResult::print() const {
|
||||
// std::cout << "=== Alias Analysis Results ===" << std::endl;
|
||||
|
||||
// auto stats = getStatistics();
|
||||
// std::cout << "Total queries: " << stats.totalQueries << std::endl;
|
||||
// std::cout << "No alias: " << stats.noAlias << std::endl;
|
||||
// std::cout << "Self alias: " << stats.selfAlias << std::endl;
|
||||
// std::cout << "Possible alias: " << stats.possibleAlias << std::endl;
|
||||
// std::cout << "Unknown alias: " << stats.unknownAlias << std::endl;
|
||||
// std::cout << "Local arrays: " << stats.localArrays << std::endl;
|
||||
// std::cout << "Function parameters: " << stats.functionParameters << std::endl;
|
||||
// std::cout << "Global arrays: " << stats.globalArrays << std::endl;
|
||||
// std::cout << "Constant accesses: " << stats.constantAccesses << std::endl;
|
||||
// }
|
||||
|
||||
void AliasAnalysisResult::addMemoryLocation(std::unique_ptr<MemoryLocation> location) {
|
||||
Value* ptr = location->accessPointer;
|
||||
LocationMap[ptr] = std::move(location);
|
||||
}
|
||||
|
||||
void AliasAnalysisResult::addAliasRelation(Value* ptr1, Value* ptr2, AliasType type) {
|
||||
auto key = std::make_pair(ptr1, ptr2);
|
||||
AliasMap[key] = type;
|
||||
}
|
||||
|
||||
// ========== SysYAliasAnalysisPass 实现 ==========
|
||||
|
||||
bool SysYAliasAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running SysY Alias Analysis on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 创建分析结果
|
||||
CurrentResult = std::make_unique<AliasAnalysisResult>(F);
|
||||
|
||||
// 执行主要分析步骤
|
||||
collectMemoryAccesses(F);
|
||||
buildAliasRelations(F);
|
||||
optimizeForSysY(F);
|
||||
|
||||
if (DEBUG) {
|
||||
CurrentResult->print();
|
||||
}
|
||||
|
||||
return false; // 分析遍不修改IR
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::collectMemoryAccesses(Function* F) {
|
||||
// 收集函数中所有内存访问指令
|
||||
for (auto& bb : F->getBasicBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
Value* ptr = nullptr;
|
||||
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
ptr = loadInst->getPointer();
|
||||
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
ptr = storeInst->getPointer();
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
// 创建内存位置信息
|
||||
auto location = createMemoryLocation(ptr);
|
||||
location->accessInsts.push_back(inst.get());
|
||||
|
||||
// 更新读写标记
|
||||
if (dynamic_cast<LoadInst*>(inst.get())) {
|
||||
location->hasReads = true;
|
||||
} else {
|
||||
location->hasWrites = true;
|
||||
}
|
||||
|
||||
CurrentResult->addMemoryLocation(std::move(location));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::buildAliasRelations(Function *F) {
|
||||
// 构建所有内存访问之间的别名关系
|
||||
auto& locationMap = CurrentResult->LocationMap;
|
||||
|
||||
std::vector<Value*> allPointers;
|
||||
for (auto& pair : locationMap) {
|
||||
allPointers.push_back(pair.first);
|
||||
}
|
||||
|
||||
// 两两比较所有指针
|
||||
for (size_t i = 0; i < allPointers.size(); ++i) {
|
||||
for (size_t j = i + 1; j < allPointers.size(); ++j) {
|
||||
Value* ptr1 = allPointers[i];
|
||||
Value* ptr2 = allPointers[j];
|
||||
|
||||
MemoryLocation* loc1 = locationMap[ptr1].get();
|
||||
MemoryLocation* loc2 = locationMap[ptr2].get();
|
||||
|
||||
AliasType aliasType = analyzeAliasBetween(loc1, loc2);
|
||||
CurrentResult->addAliasRelation(ptr1, ptr2, aliasType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeForSysY(Function* F) {
|
||||
// SysY特化优化
|
||||
applySysYConstraints(F);
|
||||
optimizeParameterAnalysis(F);
|
||||
optimizeArrayAccessAnalysis(F);
|
||||
}
|
||||
|
||||
std::unique_ptr<MemoryLocation> SysYAliasAnalysisPass::createMemoryLocation(Value* ptr) {
|
||||
Value* basePtr = getBasePointer(ptr);
|
||||
auto location = std::make_unique<MemoryLocation>(basePtr, ptr);
|
||||
|
||||
// 分析内存类型和索引模式
|
||||
analyzeMemoryType(location.get());
|
||||
analyzeIndexPattern(location.get());
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
Value* SysYAliasAnalysisPass::getBasePointer(Value* ptr) {
|
||||
// 递归剥离GEP指令,找到真正的基指针
|
||||
if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(ptr)) {
|
||||
return getBasePointer(gepInst->getBasePointer());
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::analyzeMemoryType(MemoryLocation* location) {
|
||||
Value* base = location->basePointer;
|
||||
|
||||
// 检查内存类型
|
||||
if (dynamic_cast<AllocaInst*>(base)) {
|
||||
location->isLocalArray = true;
|
||||
} else if (dynamic_cast<Argument*>(base)) {
|
||||
location->isFunctionParameter = true;
|
||||
} else if (dynamic_cast<GlobalValue*>(base)) {
|
||||
location->isGlobalArray = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::analyzeIndexPattern(MemoryLocation* location) {
|
||||
// 分析GEP指令的索引模式
|
||||
if (auto* gepInst = dynamic_cast<GetElementPtrInst*>(location->accessPointer)) {
|
||||
// 收集所有索引
|
||||
for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) {
|
||||
Value* index = gepInst->getIndex(i);
|
||||
location->indices.push_back(index);
|
||||
|
||||
// 检查是否为常量索引
|
||||
if (!isConstantValue(index)) {
|
||||
location->hasConstantIndices = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有非常量索引,则为常量访问
|
||||
if (location->indices.empty()) {
|
||||
location->hasConstantIndices = true;
|
||||
}
|
||||
|
||||
// 检查是否包含循环变量
|
||||
Function* containingFunc = nullptr;
|
||||
if (auto* inst = dynamic_cast<Instruction*>(location->basePointer)) {
|
||||
containingFunc = inst->getParent()->getParent();
|
||||
} else if (auto* arg = dynamic_cast<Argument*>(location->basePointer)) {
|
||||
containingFunc = arg->getParent();
|
||||
}
|
||||
|
||||
if (containingFunc) {
|
||||
location->hasLoopVariableIndex = hasLoopVariableInIndices(location->indices, containingFunc);
|
||||
}
|
||||
|
||||
// 计算常量偏移
|
||||
if (location->hasConstantIndices) {
|
||||
location->constantOffset = calculateConstantOffset(location->indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::analyzeAliasBetween(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 分析两个内存位置之间的别名关系
|
||||
|
||||
// 1. 相同基指针的自别名
|
||||
if (loc1->basePointer == loc2->basePointer) {
|
||||
return AliasType::SELF_ALIAS;
|
||||
}
|
||||
|
||||
// 2. 不同类型的内存位置
|
||||
if ((loc1->isLocalArray && loc2->isLocalArray)) {
|
||||
return compareLocalArrays(loc1, loc2);
|
||||
}
|
||||
|
||||
if ((loc1->isFunctionParameter && loc2->isFunctionParameter)) {
|
||||
return compareParameters(loc1, loc2);
|
||||
}
|
||||
|
||||
if ((loc1->isGlobalArray || loc2->isGlobalArray)) {
|
||||
return compareWithGlobal(loc1, loc2);
|
||||
}
|
||||
|
||||
return compareMixedTypes(loc1, loc2);
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 不同局部数组不别名
|
||||
return AliasType::NO_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareParameters(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 不同函数参数可能别名
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 涉及全局数组的访问,保守估计
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 混合类型访问,保守估计
|
||||
return AliasType::UNKNOWN_ALIAS;
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::applySysYConstraints(Function* F) {
|
||||
// 应用SysY语言特定的约束
|
||||
// SysY没有指针运算,简化别名分析
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeParameterAnalysis(Function* F) {
|
||||
// 优化参数别名分析
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeArrayAccessAnalysis(Function* F) {
|
||||
// 优化数组访问别名分析
|
||||
}
|
||||
|
||||
bool SysYAliasAnalysisPass::isConstantValue(Value* val) {
|
||||
return dynamic_cast<ConstantInteger*>(val) != nullptr; // 简化,只检查整数常量
|
||||
}
|
||||
|
||||
bool SysYAliasAnalysisPass::hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F) {
|
||||
// 简化版本:检查索引是否包含循环变量
|
||||
for (Value* index : indices) {
|
||||
if (!isConstantValue(index)) {
|
||||
return true; // 保守估计
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int SysYAliasAnalysisPass::calculateConstantOffset(const std::vector<Value*>& indices) {
|
||||
int offset = 0;
|
||||
for (Value* index : indices) {
|
||||
if (auto* constInt = dynamic_cast<ConstantInteger*>(index)) {
|
||||
// ConstantInteger的getVal()返回variant,需要提取int值
|
||||
auto val = constInt->getVal();
|
||||
if (std::holds_alternative<int>(val)) {
|
||||
offset += std::get<int>(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::printStatistics() const {
|
||||
if (CurrentResult) {
|
||||
CurrentResult->print();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
0
src/midend/Pass/Analysis/AliasAnalysis_new.cpp
Normal file
0
src/midend/Pass/Analysis/AliasAnalysis_new.cpp
Normal file
@ -290,16 +290,14 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 计算循环层级 (Level) 并填充最外层/最内层循环列表
|
||||
// 3. 计算循环层级 (Level)
|
||||
std::queue<Loop *> q_level;
|
||||
|
||||
// 查找所有最外层循环(没有父循环的),设置其层级为0,并加入队列
|
||||
CurrentResult->clearOutermostLoops(); // 清空最外层循环列表
|
||||
for (const auto &loop_ptr : allLoops) {
|
||||
if (loop_ptr->isOutermost()) {
|
||||
loop_ptr->setLoopLevel(0);
|
||||
q_level.push(loop_ptr.get());
|
||||
CurrentResult->addOutermostLoop(loop_ptr.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,12 +312,24 @@ bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
}
|
||||
}
|
||||
|
||||
// 填充最内层循环列表
|
||||
CurrentResult->clearInnermostLoops(); // 清空最内层循环列表
|
||||
for (const auto &loop_ptr : allLoops) {
|
||||
if (loop_ptr->isInnermost()) {
|
||||
CurrentResult->addInnermostLoop(loop_ptr.get());
|
||||
if (DEBUG) {
|
||||
std::cout << "Loop Analysis completed for function: " << F->getName() << std::endl;
|
||||
std::cout << "Total loops found: " << CurrentResult->getLoopCount() << std::endl;
|
||||
std::cout << "Max loop depth: " << CurrentResult->getMaxLoopDepth() << std::endl;
|
||||
std::cout << "Innermost loops: " << CurrentResult->getInnermostLoops().size() << std::endl;
|
||||
std::cout << "Outermost loops: " << CurrentResult->getOutermostLoops().size() << std::endl;
|
||||
|
||||
// 打印各深度的循环分布
|
||||
for (int depth = 1; depth <= CurrentResult->getMaxLoopDepth(); ++depth) {
|
||||
int count = CurrentResult->getLoopCountAtDepth(depth);
|
||||
if (count > 0) {
|
||||
std::cout << "Loops at depth " << depth << ": " << count << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 输出缓存统计
|
||||
auto cacheStats = CurrentResult->getCacheStats();
|
||||
std::cout << "Cache statistics - Total cached queries: " << cacheStats.totalCachedQueries << std::endl;
|
||||
}
|
||||
|
||||
return changed;
|
||||
|
||||
454
src/midend/Pass/Analysis/LoopCharacteristics.cpp
Normal file
454
src/midend/Pass/Analysis/LoopCharacteristics.cpp
Normal file
@ -0,0 +1,454 @@
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Dom.h"
|
||||
#include "Loop.h"
|
||||
#include "Liveness.h"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
// 使用全局调试开关
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 定义 Pass 的唯一 ID
|
||||
void *LoopCharacteristicsPass::ID = (void *)&LoopCharacteristicsPass::ID;
|
||||
|
||||
void LoopCharacteristicsResult::print() const {
|
||||
if (!DEBUG) return; // 只有在 DEBUG 模式下才打印
|
||||
|
||||
std::cout << "\n--- Loop Characteristics Analysis Results for Function: "
|
||||
<< AssociatedFunction->getName() << " ---" << std::endl;
|
||||
|
||||
if (CharacteristicsMap.empty()) {
|
||||
std::cout << " No loop characteristics found." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 打印统计信息
|
||||
auto stats = getOptimizationStats();
|
||||
std::cout << "\n=== Optimization Statistics ===" << std::endl;
|
||||
std::cout << "Total Loops: " << stats.totalLoops << std::endl;
|
||||
std::cout << "Counting Loops: " << stats.countingLoops << std::endl;
|
||||
std::cout << "Vectorizable Loops: " << stats.vectorizableLoops << std::endl;
|
||||
std::cout << "Unroll Candidates: " << stats.unrollCandidates << std::endl;
|
||||
std::cout << "Parallelizable Loops: " << stats.parallelizableLoops << std::endl;
|
||||
std::cout << "Static Bound Loops: " << stats.staticBoundLoops << std::endl;
|
||||
std::cout << "Avg Instructions per Loop: " << stats.avgInstructionCount << std::endl;
|
||||
std::cout << "Avg Compute/Memory Ratio: " << stats.avgComputeMemoryRatio << std::endl;
|
||||
|
||||
// 按热度排序并打印循环特征
|
||||
auto loopsByHotness = getLoopsByHotness();
|
||||
std::cout << "\n=== Loop Characteristics (by hotness) ===" << std::endl;
|
||||
|
||||
for (auto* loop : loopsByHotness) {
|
||||
auto* chars = getCharacteristics(loop);
|
||||
if (!chars) continue;
|
||||
|
||||
std::cout << "\n--- Loop: " << loop->getName() << " (Hotness: "
|
||||
<< loop->getLoopHotness() << ") ---" << std::endl;
|
||||
std::cout << " Level: " << loop->getLoopLevel() << std::endl;
|
||||
std::cout << " Blocks: " << loop->getLoopSize() << std::endl;
|
||||
std::cout << " Instructions: " << chars->instructionCount << std::endl;
|
||||
std::cout << " Memory Operations: " << chars->memoryOperationCount << std::endl;
|
||||
std::cout << " Compute/Memory Ratio: " << chars->computeToMemoryRatio << std::endl;
|
||||
|
||||
// 循环形式
|
||||
std::cout << " Form: ";
|
||||
if (chars->isCountingLoop) std::cout << "Counting ";
|
||||
if (chars->isSimpleForLoop) std::cout << "SimpleFor ";
|
||||
if (chars->isInnermost) std::cout << "Innermost ";
|
||||
if (chars->hasComplexControlFlow) std::cout << "Complex ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// 边界信息
|
||||
if (chars->staticTripCount.has_value()) {
|
||||
std::cout << " Static Trip Count: " << *chars->staticTripCount << std::endl;
|
||||
}
|
||||
if (chars->hasKnownBounds) {
|
||||
std::cout << " Has Known Bounds: Yes" << std::endl;
|
||||
}
|
||||
|
||||
// 优化机会
|
||||
std::cout << " Optimization Opportunities: ";
|
||||
if (chars->benefitsFromUnrolling)
|
||||
std::cout << "Unroll(factor=" << chars->suggestedUnrollFactor << ") ";
|
||||
if (chars->benefitsFromVectorization) std::cout << "Vectorize ";
|
||||
if (chars->benefitsFromTiling) std::cout << "Tile ";
|
||||
if (chars->isParallel) std::cout << "Parallelize ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// 归纳变量
|
||||
if (!chars->basicInductionVars.empty()) {
|
||||
std::cout << " Basic Induction Vars: " << chars->basicInductionVars.size() << std::endl;
|
||||
}
|
||||
if (!chars->derivedInductionVars.empty()) {
|
||||
std::cout << " Derived Induction Vars: " << chars->derivedInductionVars.size() << std::endl;
|
||||
}
|
||||
|
||||
// 循环不变量
|
||||
if (!chars->loopInvariants.empty()) {
|
||||
std::cout << " Loop Invariants: " << chars->loopInvariants.size() << std::endl;
|
||||
}
|
||||
if (!chars->invariantInsts.empty()) {
|
||||
std::cout << " Hoistable Instructions: " << chars->invariantInsts.size() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "-----------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (F->getBasicBlocks().empty()) {
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
return false; // 空函数
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << "Running LoopCharacteristicsPass on function: " << F->getName() << std::endl;
|
||||
|
||||
// 获取循环分析结果 - 这是我们的核心依赖
|
||||
auto* loopAnalysisResult = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
if (!loopAnalysisResult) {
|
||||
std::cerr << "Error: LoopAnalysisResult not available for function " << F->getName() << std::endl;
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果没有循环,直接返回
|
||||
if (!loopAnalysisResult->hasLoops()) {
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
|
||||
// 分析每个循环的特征
|
||||
for (const auto& loop_ptr : loopAnalysisResult->getAllLoops()) {
|
||||
Loop* loop = loop_ptr.get();
|
||||
auto characteristics = std::make_unique<LoopCharacteristics>(loop);
|
||||
|
||||
// 执行各种特征分析
|
||||
analyzeLoop(loop, characteristics.get(), AM);
|
||||
|
||||
// 添加到结果中
|
||||
CurrentResult->addLoopCharacteristics(std::move(characteristics));
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "LoopCharacteristicsPass completed for function: " << F->getName() << std::endl;
|
||||
auto stats = CurrentResult->getOptimizationStats();
|
||||
std::cout << "Analyzed " << stats.totalLoops << " loops, found "
|
||||
<< stats.vectorizableLoops << " vectorizable, "
|
||||
<< stats.unrollCandidates << " unrollable" << std::endl;
|
||||
}
|
||||
|
||||
return false; // 特征分析不修改IR
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeLoop(Loop* loop, LoopCharacteristics* characteristics, AnalysisManager &AM) {
|
||||
if (DEBUG)
|
||||
std::cout << " Analyzing characteristics of loop: " << loop->getName() << std::endl;
|
||||
|
||||
// 按顺序执行各种分析
|
||||
computePerformanceMetrics(loop, characteristics);
|
||||
analyzeLoopForm(loop, characteristics);
|
||||
identifyInductionVariables(loop, characteristics);
|
||||
identifyLoopInvariants(loop, characteristics);
|
||||
analyzeLoopBounds(loop, characteristics);
|
||||
analyzeMemoryAccessPatterns(loop, characteristics);
|
||||
evaluateOptimizationOpportunities(loop, characteristics);
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::computePerformanceMetrics(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
size_t totalInsts = 0;
|
||||
size_t memoryOps = 0;
|
||||
size_t arithmeticOps = 0;
|
||||
|
||||
// 遍历循环中的所有指令
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
totalInsts++;
|
||||
|
||||
// 分类指令类型
|
||||
if (dynamic_cast<LoadInst*>(inst.get()) || dynamic_cast<StoreInst*>(inst.get())) {
|
||||
memoryOps++;
|
||||
} else if (dynamic_cast<BinaryInst*>(inst.get())) {
|
||||
// 检查是否为算术运算
|
||||
auto* binInst = dynamic_cast<BinaryInst*>(inst.get());
|
||||
// 简化:假设所有二元运算都是算术运算
|
||||
arithmeticOps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
characteristics->instructionCount = totalInsts;
|
||||
characteristics->memoryOperationCount = memoryOps;
|
||||
characteristics->arithmeticOperationCount = arithmeticOps;
|
||||
|
||||
// 计算计算与内存操作比率
|
||||
if (memoryOps > 0) {
|
||||
characteristics->computeToMemoryRatio = static_cast<double>(arithmeticOps) / memoryOps;
|
||||
} else {
|
||||
characteristics->computeToMemoryRatio = arithmeticOps; // 纯计算循环
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeLoopForm(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 基本形式判断
|
||||
characteristics->isInnermost = loop->isInnermost();
|
||||
|
||||
// 检查是否为简单循环 (只有一个回边)
|
||||
bool isSimple = loop->isSimpleLoop();
|
||||
characteristics->isSimpleForLoop = isSimple;
|
||||
|
||||
// 检查复杂控制流 (多个出口表示可能有break/continue)
|
||||
auto exitingBlocks = loop->getExitingBlocks();
|
||||
characteristics->hasComplexControlFlow = exitingBlocks.size() > 1;
|
||||
|
||||
// 初步判断是否为计数循环 (需要更复杂的分析)
|
||||
// 简化版本:如果是简单循环且是最内层,很可能是计数循环
|
||||
characteristics->isCountingLoop = isSimple && loop->isInnermost() && exitingBlocks.size() == 1;
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::identifyInductionVariables(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 寻找基本归纳变量
|
||||
BasicBlock* header = loop->getHeader();
|
||||
|
||||
// 遍历循环头的phi指令,寻找归纳变量模式
|
||||
for (auto& inst : header->getInstructions()) {
|
||||
auto* phiInst = dynamic_cast<PhiInst*>(inst.get());
|
||||
if (!phiInst) continue;
|
||||
|
||||
// 检查phi指令是否符合归纳变量模式
|
||||
if (isInductionVariable(phiInst, loop)) {
|
||||
characteristics->basicInductionVars.push_back(phiInst);
|
||||
|
||||
// 分析步长 (简化版本)
|
||||
characteristics->inductionSteps[phiInst] = 1; // 默认步长为1
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << " Found basic induction variable: " << phiInst->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 寻找派生归纳变量 (基于基本归纳变量的线性表达式)
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
// 检查是否为基于归纳变量的计算
|
||||
if (auto* binInst = dynamic_cast<BinaryInst*>(inst.get())) {
|
||||
// 简化:检查操作数是否包含基本归纳变量
|
||||
for (Value* basicIV : characteristics->basicInductionVars) {
|
||||
// 这里需要更复杂的分析来确定派生关系
|
||||
// 暂时简化处理
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::identifyLoopInvariants(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 收集循环不变量
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
Value* val = inst.get();
|
||||
|
||||
// 跳过phi指令和终结指令
|
||||
if (dynamic_cast<PhiInst*>(val)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否为终结指令
|
||||
if (auto* instPtr = dynamic_cast<Instruction*>(val)) {
|
||||
if (instPtr->isTerminator()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoopInvariant(val, loop)) {
|
||||
characteristics->loopInvariants.insert(val);
|
||||
characteristics->invariantInsts.insert(static_cast<Instruction*>(val));
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << " Found loop invariant: " << val->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 简化的边界分析
|
||||
// 在实际实现中,需要分析循环的条件表达式来确定边界
|
||||
|
||||
// 检查是否有静态可确定的循环次数
|
||||
if (characteristics->isCountingLoop && !characteristics->basicInductionVars.empty()) {
|
||||
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
||||
// 这里需要更复杂的符号执行或约束求解
|
||||
|
||||
// 暂时设置一个保守估计
|
||||
if (characteristics->instructionCount < 10) {
|
||||
characteristics->staticTripCount = 100; // 假设小循环执行100次
|
||||
characteristics->hasKnownBounds = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeMemoryAccessPatterns(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 使用外部别名分析结果 - 大幅简化版本
|
||||
std::map<Value*, std::vector<Instruction*>> accessMap;
|
||||
|
||||
// 收集所有内存访问
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
Value* ptr = loadInst->getPointer();
|
||||
accessMap[ptr].push_back(loadInst);
|
||||
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
Value* ptr = storeInst->getPointer();
|
||||
accessMap[ptr].push_back(storeInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分析每个内存位置的访问模式
|
||||
for (auto& [ptr, accesses] : accessMap) {
|
||||
LoopCharacteristics::MemoryAccessPattern pattern;
|
||||
|
||||
// 初始化基本字段
|
||||
pattern.isSequential = true; // 简化:假设大部分访问是顺序的
|
||||
pattern.isStrided = false;
|
||||
pattern.stride = 1;
|
||||
|
||||
// 使用别名分析结果 (简化:设置默认值,实际应该查询别名分析)
|
||||
pattern.aliasType = AliasType::UNKNOWN_ALIAS; // 保守默认值
|
||||
pattern.isArrayParameter = false;
|
||||
pattern.isGlobalArray = false;
|
||||
pattern.hasConstantIndices = true;
|
||||
|
||||
// 分类load和store
|
||||
for (Instruction* inst : accesses) {
|
||||
if (dynamic_cast<LoadInst*>(inst)) {
|
||||
pattern.loadInsts.push_back(inst);
|
||||
} else {
|
||||
pattern.storeInsts.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
characteristics->memoryPatterns[ptr] = pattern;
|
||||
|
||||
if (DEBUG && (static_cast<int>(pattern.aliasType) >= 2)) { // POSSIBLE_ALIAS及以上
|
||||
std::cout << " Found potential aliasing for memory access, type: "
|
||||
<< static_cast<int>(pattern.aliasType) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::evaluateOptimizationOpportunities(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 评估循环展开机会
|
||||
characteristics->benefitsFromUnrolling =
|
||||
characteristics->isInnermost &&
|
||||
characteristics->instructionCount > 3 &&
|
||||
characteristics->instructionCount < 50 &&
|
||||
!characteristics->hasComplexControlFlow;
|
||||
|
||||
if (characteristics->benefitsFromUnrolling) {
|
||||
characteristics->suggestedUnrollFactor = estimateUnrollFactor(loop);
|
||||
}
|
||||
|
||||
// 评估向量化机会
|
||||
characteristics->benefitsFromVectorization = benefitsFromVectorization(loop);
|
||||
|
||||
// 评估并行化机会
|
||||
characteristics->isParallel =
|
||||
!hasLoopCarriedDependence(loop) &&
|
||||
characteristics->isCountingLoop;
|
||||
|
||||
// 评估分块机会 (主要针对嵌套循环)
|
||||
characteristics->benefitsFromTiling =
|
||||
!loop->isInnermost() &&
|
||||
characteristics->memoryOperationCount > characteristics->arithmeticOperationCount;
|
||||
}
|
||||
|
||||
// ========== 辅助方法实现 ==========
|
||||
|
||||
bool LoopCharacteristicsPass::isInductionVariable(Value* val, Loop* loop) {
|
||||
// 简化的归纳变量检测
|
||||
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
||||
if (!phiInst) return false;
|
||||
|
||||
// 检查phi指令是否在循环头
|
||||
if (phiInst->getParent() != loop->getHeader()) return false;
|
||||
|
||||
// 检查是否有来自循环内的更新
|
||||
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
||||
if (loop->contains(incomingBB)) {
|
||||
// 简化:如果有来自循环内的值,认为可能是归纳变量
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::isLoopInvariant(Value* val, Loop* loop) {
|
||||
auto* inst = dynamic_cast<Instruction*>(val);
|
||||
if (!inst) return true; // 非指令(如常量)认为是不变的
|
||||
|
||||
// 如果指令不在循环内定义,则是不变的
|
||||
if (!loop->contains(inst->getParent())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查操作数是否都是循环不变的
|
||||
// 简化版本:如果是load指令且指针是不变的,认为可能是不变的
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst)) {
|
||||
Value* ptr = loadInst->getPointer();
|
||||
return isLoopInvariant(ptr, loop);
|
||||
}
|
||||
|
||||
// 简化:对于其他指令,保守地认为是变化的
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::hasLoopCarriedDependence(Loop* loop) {
|
||||
// 简化的依赖分析
|
||||
// 检查是否有写后读或写后写依赖跨越循环迭代
|
||||
|
||||
std::set<Value*> writtenVars;
|
||||
std::set<Value*> readVars;
|
||||
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
writtenVars.insert(storeInst->getPointer());
|
||||
} else if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
readVars.insert(loadInst->getPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 简化:如果有写后读到同一变量,假设存在依赖
|
||||
for (Value* written : writtenVars) {
|
||||
if (readVars.count(written)) {
|
||||
return true; // 可能存在依赖
|
||||
}
|
||||
}
|
||||
|
||||
return false; // 保守估计:没有明显依赖
|
||||
}
|
||||
|
||||
int LoopCharacteristicsPass::estimateUnrollFactor(Loop* loop) {
|
||||
// 基于循环体大小估算展开因子
|
||||
if (loop->getLoopSize() <= 2) return 8; // 很小的循环
|
||||
if (loop->getLoopSize() <= 5) return 4; // 小循环
|
||||
if (loop->getLoopSize() <= 10) return 2; // 中等循环
|
||||
return 1; // 大循环不建议展开
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::benefitsFromVectorization(Loop* loop) {
|
||||
// 简化的向量化收益评估
|
||||
return loop->isInnermost() && // 最内层循环
|
||||
loop->isSimpleLoop() && // 简单循环结构
|
||||
!hasLoopCarriedDependence(loop); // 没有明显的依赖
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
281
src/midend/Pass/Analysis/SideEffectAnalysis.cpp
Normal file
281
src/midend/Pass/Analysis/SideEffectAnalysis.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 副作用分析遍的静态 ID
|
||||
void* SysYSideEffectAnalysisPass::ID = (void*)&SysYSideEffectAnalysisPass::ID;
|
||||
|
||||
// ======================================================================
|
||||
// SideEffectAnalysisResult 类的实现
|
||||
// ======================================================================
|
||||
|
||||
SideEffectAnalysisResult::SideEffectAnalysisResult() {
|
||||
initializeKnownFunctions();
|
||||
}
|
||||
|
||||
const SideEffectInfo& SideEffectAnalysisResult::getInstructionSideEffect(Instruction* inst) const {
|
||||
auto it = instructionSideEffects.find(inst);
|
||||
if (it != instructionSideEffects.end()) {
|
||||
return it->second;
|
||||
}
|
||||
// 返回默认的无副作用信息
|
||||
static SideEffectInfo noEffect;
|
||||
return noEffect;
|
||||
}
|
||||
|
||||
const SideEffectInfo& SideEffectAnalysisResult::getFunctionSideEffect(Function* func) const {
|
||||
auto it = functionSideEffects.find(func);
|
||||
if (it != functionSideEffects.end()) {
|
||||
return it->second;
|
||||
}
|
||||
// 返回默认的无副作用信息
|
||||
static SideEffectInfo noEffect;
|
||||
return noEffect;
|
||||
}
|
||||
|
||||
void SideEffectAnalysisResult::setInstructionSideEffect(Instruction* inst, const SideEffectInfo& info) {
|
||||
instructionSideEffects[inst] = info;
|
||||
}
|
||||
|
||||
void SideEffectAnalysisResult::setFunctionSideEffect(Function* func, const SideEffectInfo& info) {
|
||||
functionSideEffects[func] = info;
|
||||
}
|
||||
|
||||
bool SideEffectAnalysisResult::hasSideEffect(Instruction* inst) const {
|
||||
const auto& info = getInstructionSideEffect(inst);
|
||||
return info.type != SideEffectType::NO_SIDE_EFFECT;
|
||||
}
|
||||
|
||||
bool SideEffectAnalysisResult::mayModifyMemory(Instruction* inst) const {
|
||||
const auto& info = getInstructionSideEffect(inst);
|
||||
return info.mayModifyMemory;
|
||||
}
|
||||
|
||||
bool SideEffectAnalysisResult::mayModifyGlobal(Instruction* inst) const {
|
||||
const auto& info = getInstructionSideEffect(inst);
|
||||
return info.mayModifyGlobal;
|
||||
}
|
||||
|
||||
bool SideEffectAnalysisResult::isPureFunction(Function* func) const {
|
||||
const auto& info = getFunctionSideEffect(func);
|
||||
return info.isPure;
|
||||
}
|
||||
|
||||
void SideEffectAnalysisResult::initializeKnownFunctions() {
|
||||
// SysY标准库函数的副作用信息
|
||||
|
||||
// I/O函数 - 有副作用
|
||||
SideEffectInfo ioEffect;
|
||||
ioEffect.type = SideEffectType::IO_OPERATION;
|
||||
ioEffect.mayModifyGlobal = true;
|
||||
ioEffect.mayModifyMemory = true;
|
||||
ioEffect.mayCallFunction = true;
|
||||
ioEffect.isPure = false;
|
||||
|
||||
// knownFunctions["printf"] = ioEffect;
|
||||
// knownFunctions["scanf"] = ioEffect;
|
||||
knownFunctions["getint"] = ioEffect;
|
||||
knownFunctions["getch"] = ioEffect;
|
||||
knownFunctions["getfloat"] = ioEffect;
|
||||
knownFunctions["getarray"] = ioEffect;
|
||||
knownFunctions["getfarray"] = ioEffect;
|
||||
knownFunctions["putint"] = ioEffect;
|
||||
knownFunctions["putch"] = ioEffect;
|
||||
knownFunctions["putfloat"] = ioEffect;
|
||||
knownFunctions["putarray"] = ioEffect;
|
||||
knownFunctions["putfarray"] = ioEffect;
|
||||
|
||||
// 时间函数 - 有副作用
|
||||
SideEffectInfo timeEffect;
|
||||
timeEffect.type = SideEffectType::FUNCTION_CALL;
|
||||
timeEffect.mayModifyGlobal = true;
|
||||
timeEffect.mayModifyMemory = false;
|
||||
timeEffect.mayCallFunction = true;
|
||||
timeEffect.isPure = false;
|
||||
|
||||
knownFunctions["_sysy_starttime"] = timeEffect;
|
||||
knownFunctions["_sysy_stoptime"] = timeEffect;
|
||||
|
||||
}
|
||||
|
||||
const SideEffectInfo* SideEffectAnalysisResult::getKnownFunctionSideEffect(const std::string& funcName) const {
|
||||
auto it = knownFunctions.find(funcName);
|
||||
return (it != knownFunctions.end()) ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
// SysYSideEffectAnalysisPass 类的实现
|
||||
// ======================================================================
|
||||
|
||||
bool SysYSideEffectAnalysisPass::runOnFunction(Function* F, AnalysisManager& AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running SideEffect analysis on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 创建分析结果(构造函数中已经调用了initializeKnownFunctions)
|
||||
result = std::make_unique<SideEffectAnalysisResult>();
|
||||
|
||||
// 获取别名分析结果,在整个函数分析过程中重复使用
|
||||
aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
|
||||
|
||||
// 分析函数中的每条指令
|
||||
SideEffectInfo functionSideEffect;
|
||||
|
||||
for (auto& BB : F->getBasicBlocks()) {
|
||||
for (auto& I : BB->getInstructions_Range()) {
|
||||
Instruction* inst = I.get();
|
||||
SideEffectInfo instEffect = analyzeInstruction(inst, AM);
|
||||
|
||||
// 记录指令的副作用信息
|
||||
result->setInstructionSideEffect(inst, instEffect);
|
||||
|
||||
// 合并到函数级别的副作用信息中
|
||||
functionSideEffect = functionSideEffect.merge(instEffect);
|
||||
}
|
||||
}
|
||||
|
||||
// 记录函数级别的副作用信息
|
||||
result->setFunctionSideEffect(F, functionSideEffect);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "---- Side Effect Analysis Results for Function: " << F->getName() << " ----\n";
|
||||
|
||||
for (auto& BB : F->getBasicBlocks()) {
|
||||
for (auto& I : BB->getInstructions_Range()) {
|
||||
Instruction* inst = I.get();
|
||||
const auto& info = result->getInstructionSideEffect(inst);
|
||||
|
||||
SysYPrinter::printInst(inst);
|
||||
std::cout << " -> Side Effect: ";
|
||||
switch (info.type) {
|
||||
case SideEffectType::NO_SIDE_EFFECT: std::cout << "None"; break;
|
||||
case SideEffectType::MEMORY_WRITE: std::cout << "Memory Write"; break;
|
||||
case SideEffectType::FUNCTION_CALL: std::cout << "Function Call"; break;
|
||||
case SideEffectType::IO_OPERATION: std::cout << "I/O Operation"; break;
|
||||
case SideEffectType::UNKNOWN: std::cout << "Unknown"; break;
|
||||
}
|
||||
std::cout << " (Modifies Global: " << (info.mayModifyGlobal ? "Yes" : "No")
|
||||
<< ", Modifies Memory: " << (info.mayModifyMemory ? "Yes" : "No")
|
||||
<< ", Is Pure: " << (info.isPure ? "Yes" : "No") << ")\n";
|
||||
}
|
||||
}
|
||||
std::cout << "------------------------------------------------------------------\n";
|
||||
}
|
||||
|
||||
return false; // Analysis passes return false since they don't modify the IR
|
||||
}
|
||||
|
||||
std::unique_ptr<AnalysisResultBase> SysYSideEffectAnalysisPass::getResult() {
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction* inst, AnalysisManager& AM) {
|
||||
SideEffectInfo info;
|
||||
|
||||
// 根据指令类型进行分析
|
||||
if (inst->isCall()) {
|
||||
return analyzeCallInstruction(static_cast<CallInst*>(inst), AM);
|
||||
} else if (inst->isStore()) {
|
||||
return analyzeStoreInstruction(static_cast<StoreInst*>(inst), AM);
|
||||
} else if (inst->isMemset()) {
|
||||
return analyzeMemsetInstruction(static_cast<MemsetInst*>(inst), AM);
|
||||
} else if (inst->isBranch() || inst->isReturn()) {
|
||||
// 控制流指令无副作用,但必须保留
|
||||
info.type = SideEffectType::NO_SIDE_EFFECT;
|
||||
info.isPure = true;
|
||||
} else {
|
||||
// 其他指令(算术、逻辑、比较等)通常无副作用
|
||||
info.type = SideEffectType::NO_SIDE_EFFECT;
|
||||
info.isPure = true;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeCallInstruction(CallInst* call, AnalysisManager& AM) {
|
||||
SideEffectInfo info;
|
||||
|
||||
// 获取被调用的函数
|
||||
Function* calledFunc = call->getCallee();
|
||||
if (!calledFunc) {
|
||||
// 间接调用,保守处理
|
||||
info.type = SideEffectType::UNKNOWN;
|
||||
info.mayModifyGlobal = true;
|
||||
info.mayModifyMemory = true;
|
||||
info.mayCallFunction = true;
|
||||
info.isPure = false;
|
||||
return info;
|
||||
}
|
||||
|
||||
std::string funcName = calledFunc->getName();
|
||||
|
||||
// 检查是否为已知的标准库函数
|
||||
const SideEffectInfo* knownInfo = result->getKnownFunctionSideEffect(funcName);
|
||||
if (knownInfo) {
|
||||
return *knownInfo;
|
||||
}
|
||||
|
||||
// 对于用户定义的函数,检查是否已经分析过
|
||||
const SideEffectInfo& funcEffect = result->getFunctionSideEffect(calledFunc);
|
||||
if (funcEffect.type != SideEffectType::NO_SIDE_EFFECT || !funcEffect.isPure) {
|
||||
return funcEffect;
|
||||
}
|
||||
|
||||
// 对于未分析的用户函数,保守处理
|
||||
info.type = SideEffectType::FUNCTION_CALL;
|
||||
info.mayModifyGlobal = true;
|
||||
info.mayModifyMemory = true;
|
||||
info.mayCallFunction = true;
|
||||
info.isPure = false;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst* store, AnalysisManager& AM) {
|
||||
SideEffectInfo info;
|
||||
info.type = SideEffectType::MEMORY_WRITE;
|
||||
info.mayModifyMemory = true;
|
||||
info.isPure = false;
|
||||
|
||||
// 使用缓存的别名分析结果
|
||||
if (aliasAnalysis) {
|
||||
Value* storePtr = store->getPointer();
|
||||
|
||||
// 如果存储到全局变量或可能别名的位置,则可能修改全局状态
|
||||
if (!aliasAnalysis->isLocalArray(storePtr)) {
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
} else {
|
||||
// 没有别名分析结果,保守处理
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeMemsetInstruction(MemsetInst* memset, AnalysisManager& AM) {
|
||||
SideEffectInfo info;
|
||||
info.type = SideEffectType::MEMORY_WRITE;
|
||||
info.mayModifyMemory = true;
|
||||
info.isPure = false;
|
||||
|
||||
// 使用缓存的别名分析结果
|
||||
if (aliasAnalysis) {
|
||||
Value* memsetPtr = memset->getPointer();
|
||||
|
||||
// 如果memset操作全局变量或可能别名的位置,则可能修改全局状态
|
||||
if (!aliasAnalysis->isLocalArray(memsetPtr)) {
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
} else {
|
||||
// 没有别名分析结果,保守处理
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -1,6 +1,9 @@
|
||||
#include "Dom.h"
|
||||
#include "Liveness.h"
|
||||
#include "Loop.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "SysYIRCFGOpt.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include "DCE.h"
|
||||
@ -38,7 +41,10 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
// 注册分析遍
|
||||
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
|
||||
registerAnalysisPass<sysy::LivenessAnalysisPass>();
|
||||
registerAnalysisPass<SysYAliasAnalysisPass>(); // 别名分析 (优先级高)
|
||||
registerAnalysisPass<SysYSideEffectAnalysisPass>(); // 副作用分析 (依赖别名分析)
|
||||
registerAnalysisPass<LoopAnalysisPass>();
|
||||
registerAnalysisPass<LoopCharacteristicsPass>(); // 循环特征分析依赖别名分析
|
||||
|
||||
// 注册优化遍
|
||||
registerOptimizationPass<SysYDelInstAfterBrPass>();
|
||||
|
||||
Reference in New Issue
Block a user