Compare commits
29 Commits
midend-llv
...
midend-Loo
| Author | SHA1 | Date | |
|---|---|---|---|
| 7547d34598 | |||
| 06a368db39 | |||
| 48865fa805 | |||
| 8b5123460b | |||
| cd27f5fda9 | |||
| 60cb8d6e49 | |||
| ea944f6ba0 | |||
| 0c8a156485 | |||
| debda205cc | |||
| baef82677b | |||
| f634273852 | |||
| 70f6a25ebc | |||
| 8cb807c8b9 | |||
| 1fab6a43f9 | |||
| 1e3791a801 | |||
| 6a7355ed28 | |||
| be9ac89584 | |||
| ac3358d7e3 | |||
| bd23f6154d | |||
| 126c38a1d9 | |||
| c4c91412d1 | |||
| f17e44f8d4 | |||
| a406e44df3 | |||
| b1a46b7d58 | |||
| bd02f5f1eb | |||
| f083e38615 | |||
| ef9d7c4d03 | |||
| 1c7c85dd2f | |||
| aa7f2bb0f5 |
167
Pass_ID_List.md
167
Pass_ID_List.md
@ -228,6 +228,173 @@ Branch 和 Return 指令: 这些是终结符指令,不产生一个可用于其
|
||||
|
||||
在提供的代码中,SSAPValue 的 constantVal 是 int 类型。这使得浮点数常量传播变得复杂。对于浮点数相关的指令(kFAdd, kFMul, kFCmp, kFNeg, kFNot, kItoF, kFtoI 等),如果不能将浮点值准确地存储在 int 中,或者不能可靠地执行浮点运算,那么通常会保守地将结果设置为 Bottom。一个更完善的 SCCP 实现会使用 std::variant<int, float> 或独立的浮点常量存储来处理浮点数。
|
||||
|
||||
## LoopSR循环归纳变量强度削弱 关于魔数计算的说明
|
||||
|
||||
魔数除法的核心思想是:将除法转换为乘法和移位
|
||||
|
||||
数学原理:x / d ≈ (x * m) >> (32 + s)
|
||||
|
||||
m 是魔数 (magic number)
|
||||
s 是额外的移位量 (shift)
|
||||
>> 是算术右移
|
||||
|
||||
2^(32+s) / d ≤ m < 2^(32+s) / d + 2^s / d
|
||||
|
||||
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
|
||||
# 真正的迭代原因:精度要求
|
||||
def explain_precision_requirement():
|
||||
d = 10
|
||||
|
||||
print('魔数算法需要找到精确的边界值:')
|
||||
print('目标:2^p > d * (2^31 - r),其中r是余数')
|
||||
print()
|
||||
|
||||
# 模拟我们算法的迭代过程
|
||||
p = 31
|
||||
two_p = 2**p
|
||||
r = two_p % d # 余数
|
||||
m = two_p // d # 商
|
||||
|
||||
print(f'初始状态 (p={p}):')
|
||||
print(f' 2^{p} = {two_p:,}')
|
||||
print(f' 2^{p} / {d} = {m:,} 余 {r}')
|
||||
print(f' 需要检查: 2^{p} > {d} * (2^31 - {r}) = {d * (2**31 - r):,}')
|
||||
print(f' 条件满足: {two_p > d * (2**31 - r)}')
|
||||
print()
|
||||
|
||||
# 继续迭代直到条件满足
|
||||
iteration = 0
|
||||
while r != 0 and m < 2**31:
|
||||
iteration += 1
|
||||
p += 1
|
||||
two_p *= 2
|
||||
m *= 2
|
||||
r *= 2
|
||||
if r >= d:
|
||||
m += 1
|
||||
r -= d
|
||||
|
||||
print(f'迭代 {iteration} (p={p}):')
|
||||
print(f' m = {m:,}, r = {r}')
|
||||
print(f' m < 2^31? {m < 2**31} (2^31 = {2**31:,})')
|
||||
|
||||
if m >= 2**31:
|
||||
print(f' ✗ 魔数 {m:,} 超出32位范围!')
|
||||
break
|
||||
elif r == 0:
|
||||
print(f' ✓ 余数为0,找到精确解')
|
||||
break
|
||||
|
||||
if iteration > 10: # 防止无限循环
|
||||
print(' ... (限制迭代次数)')
|
||||
break
|
||||
|
||||
explain_precision_requirement()
|
||||
"
|
||||
|
||||
问题在于精度要求。理论魔数需要非常精确,不能简单地用 2^32 / d。让我展示真正的迭代原因:
|
||||
|
||||
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
|
||||
# 真正的迭代原因:精度要求
|
||||
def explain_precision_requirement():
|
||||
d = 10
|
||||
|
||||
print('魔数算法需要找到精确的边界值:')
|
||||
print('目标:2^p > d * (2^31 - r),其中r是余数')
|
||||
print()
|
||||
|
||||
# 模拟我们算法的迭代过程
|
||||
p = 31
|
||||
two_p = 2**p
|
||||
r = two_p % d # 余数
|
||||
m = two_p // d # 商
|
||||
|
||||
print(f'初始状态 (p={p}):')
|
||||
print(f' 2^{p} = {two_p:,}')
|
||||
print(f' 2^{p} / {d} = {m:,} 余 {r}')
|
||||
print(f' 需要检查: 2^{p} > {d} * (2^31 - {r}) = {d * (2**31 - r):,}')
|
||||
print(f' 条件满足: {two_p > d * (2**31 - r)}')
|
||||
print()
|
||||
|
||||
# 继续迭代直到条件满足
|
||||
iteration = 0
|
||||
while r != 0 and m < 2**31:
|
||||
iteration += 1
|
||||
p += 1
|
||||
two_p *= 2
|
||||
m *= 2
|
||||
r *= 2
|
||||
if r >= d:
|
||||
m += 1
|
||||
r -= d
|
||||
|
||||
print(f'迭代 {iteration} (p={p}):')
|
||||
print(f' m = {m:,}, r = {r}')
|
||||
print(f' m < 2^31? {m < 2**31} (2^31 = {2**31:,})')
|
||||
|
||||
if m >= 2**31:
|
||||
print(f' ✗ 魔数 {m:,} 超出32位范围!')
|
||||
break
|
||||
elif r == 0:
|
||||
print(f' ✓ 余数为0,找到精确解')
|
||||
break
|
||||
|
||||
if iteration > 10: # 防止无限循环
|
||||
print(' ... (限制迭代次数)')
|
||||
break
|
||||
|
||||
explain_precision_requirement()
|
||||
"
|
||||
|
||||
|
||||
cd /home/downright/Compiler_Opt/mysysy && python3 -c "
|
||||
# 检查初始状态是否会溢出
|
||||
def check_initial_overflow():
|
||||
int32_max = 2**31 - 1
|
||||
|
||||
print('检查不同除数的初始魔数是否会溢出:')
|
||||
print(f'32位有符号整数最大值: {int32_max:,}')
|
||||
print()
|
||||
|
||||
# 检查各种除数
|
||||
divisors = [2, 3, 5, 7, 9, 10, 11, 13, 17, 25, 100, 1000]
|
||||
|
||||
for d in divisors:
|
||||
# 初始魔数 = 2^31 / d
|
||||
initial_magic = (2**31) // d
|
||||
|
||||
overflow = initial_magic > int32_max
|
||||
status = \"溢出\" if overflow else \"安全\"
|
||||
|
||||
print(f'd={d:4d}: 初始魔数 = 2^31/{d} = {initial_magic:10,} [{status}]')
|
||||
|
||||
print()
|
||||
print('结论: 初始状态下魔数不会溢出,溢出发生在迭代过程中')
|
||||
|
||||
check_initial_overflow()
|
||||
"
|
||||
|
||||
总结
|
||||
迭代的必要性:
|
||||
|
||||
不是为了避免初始溢出(初始状态安全)
|
||||
是为了找到最精确的魔数,减少舍入误差
|
||||
每次迭代提高一倍精度,但魔数也翻倍
|
||||
溢出发生时机:
|
||||
|
||||
初始状态:2^31 / d 总是在32位范围内
|
||||
迭代过程:2^32 / d, 2^33 / d, ... 逐渐超出32位范围
|
||||
回退值的正确性:
|
||||
|
||||
回退值是基于数学理论和实践验证的标准值
|
||||
来自LLVM、GCC等成熟编译器的实现
|
||||
通过测试验证,对各种输入都能产生正确结果
|
||||
算法设计哲学:
|
||||
|
||||
先尝试最优解:通过迭代寻找最精确的魔数
|
||||
检测边界条件:当超出32位范围时及时发现
|
||||
智能回退:使用已验证的标准值保证正确性
|
||||
保持通用性:对于没有预设值的除数仍然可以工作
|
||||
|
||||
# 后续优化可能涉及的改动
|
||||
|
||||
|
||||
@ -517,7 +517,7 @@ void RISCv64ISel::selectNode(DAGNode* node) {
|
||||
CurMBB->addInstruction(std::move(instr));
|
||||
break;
|
||||
}
|
||||
case Instruction::kSRA: {
|
||||
case Instruction::kSra: {
|
||||
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
|
||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
|
||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||
|
||||
@ -727,6 +727,7 @@ class Instruction : public User {
|
||||
kFCmpGE = 0x1UL << 20,
|
||||
kAnd = 0x1UL << 21,
|
||||
kOr = 0x1UL << 22,
|
||||
// kXor = 0x1UL << 46,
|
||||
// Unary
|
||||
kNeg = 0x1UL << 23,
|
||||
kNot = 0x1UL << 24,
|
||||
@ -751,8 +752,10 @@ class Instruction : public User {
|
||||
kPhi = 0x1UL << 39,
|
||||
kBitItoF = 0x1UL << 40,
|
||||
kBitFtoI = 0x1UL << 41,
|
||||
kSRA = 0x1UL << 42,
|
||||
kMulh = 0x1UL << 43
|
||||
kSrl = 0x1UL << 42, // 逻辑右移
|
||||
kSll = 0x1UL << 43, // 逻辑左移
|
||||
kSra = 0x1UL << 44, // 算术右移
|
||||
kMulh = 0x1UL << 45
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -855,8 +858,14 @@ public:
|
||||
return "BitItoF";
|
||||
case kBitFtoI:
|
||||
return "BitFtoI";
|
||||
case kSRA:
|
||||
case kSrl:
|
||||
return "lshr";
|
||||
case kSll:
|
||||
return "shl";
|
||||
case kSra:
|
||||
return "ashr";
|
||||
case kMulh:
|
||||
return "mulh";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@ -868,7 +877,7 @@ public:
|
||||
|
||||
bool isBinary() const {
|
||||
static constexpr uint64_t BinaryOpMask =
|
||||
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSRA | kMulh) |
|
||||
(kAdd | kSub | kMul | kDiv | kRem | kAnd | kOr | kSra | kSrl | kSll | kMulh) |
|
||||
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
|
||||
return kind & BinaryOpMask;
|
||||
}
|
||||
@ -962,7 +971,13 @@ class PhiInst : public Instruction {
|
||||
|
||||
Value* getValfromBlk(BasicBlock* block);
|
||||
BasicBlock* getBlkfromVal(Value* value);
|
||||
|
||||
auto getIncomingValues() const {
|
||||
std::vector<std::pair<BasicBlock*, Value*>> result;
|
||||
for (const auto& [block, value] : blk2val) {
|
||||
result.emplace_back(block, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void addIncoming(Value *value, BasicBlock *block) {
|
||||
assert(value && block && "PhiInst: value and block cannot be null");
|
||||
addOperand(value);
|
||||
@ -1420,8 +1435,19 @@ protected:
|
||||
auto is_same_ptr = [blockToRemove](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == blockToRemove; };
|
||||
blocks.remove_if(is_same_ptr);
|
||||
}
|
||||
BasicBlock* addBasicBlock(const std::string &name, BasicBlock *before) {
|
||||
// 在指定的基本块之前添加一个新的基本块
|
||||
auto it = std::find_if(blocks.begin(), blocks.end(),
|
||||
[before](const std::unique_ptr<BasicBlock> &ptr) { return ptr.get() == before; });
|
||||
if (it != blocks.end()) {
|
||||
auto newblk = blocks.emplace(it, std::make_unique<BasicBlock>(this, name));
|
||||
return newblk->get(); // 返回新添加的基本块指针
|
||||
}
|
||||
assert(false && "BasicBlock to insert before not found!");
|
||||
return nullptr; // 如果没有找到指定的基本块,则返回nullptr
|
||||
} ///< 添加一个新的基本块到某个基本块之前
|
||||
BasicBlock* addBasicBlock(const std::string &name = "") {
|
||||
blocks.emplace_back(new BasicBlock(this, name));
|
||||
blocks.emplace_back(std::make_unique<BasicBlock>(this, name));
|
||||
return blocks.back().get();
|
||||
}
|
||||
BasicBlock* addBasicBlock(BasicBlock *block) {
|
||||
|
||||
@ -217,8 +217,14 @@ class IRBuilder {
|
||||
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建按位或指令
|
||||
BinaryInst * createSRAInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSRA, Type::getIntType(), lhs, rhs, name);
|
||||
BinaryInst * createSllInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSll, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建逻辑左移指令
|
||||
BinaryInst * createSrlInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSrl, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建逻辑右移指令
|
||||
BinaryInst * createSraInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSra, Type::getIntType(), lhs, rhs, name);
|
||||
} ///< 创建算术右移指令
|
||||
BinaryInst * createMulhInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
|
||||
|
||||
246
src/include/midend/Pass/Analysis/AliasAnalysis.h
Normal file
246
src/include/midend/Pass/Analysis/AliasAnalysis.h
Normal file
@ -0,0 +1,246 @@
|
||||
#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 printStatics() 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),
|
||||
aggressiveParameterMode(false), parameterOptimizationEnabled(false) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||
|
||||
// ========== 配置接口 ==========
|
||||
|
||||
/**
|
||||
* 启用针对SysY评测的激进优化模式
|
||||
* 在这种模式下,假设不同参数不会传入相同数组
|
||||
*/
|
||||
void enableSysYTestingMode() {
|
||||
aggressiveParameterMode = true;
|
||||
parameterOptimizationEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用保守的默认模式(适合通用场景)
|
||||
*/
|
||||
void useConservativeMode() {
|
||||
aggressiveParameterMode = false;
|
||||
parameterOptimizationEnabled = false;
|
||||
}
|
||||
|
||||
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 compareIndices(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 useAggressiveParameterAnalysis() const { return aggressiveParameterMode; }
|
||||
bool enableParameterOptimization() const { return parameterOptimizationEnabled; }
|
||||
void setAggressiveParameterMode(bool enable) { aggressiveParameterMode = enable; }
|
||||
void setParameterOptimizationEnabled(bool enable) { parameterOptimizationEnabled = enable; }
|
||||
|
||||
// ========== 辅助优化方法 ==========
|
||||
|
||||
void optimizeConstantIndexAccesses(); // 优化常量索引访问
|
||||
void optimizeSequentialAccesses(); // 优化顺序访问
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
bool isConstantValue(Value* val); // 是否为常量
|
||||
bool hasLoopVariableInIndices(const std::vector<Value*>& indices, Function* F);
|
||||
int calculateConstantOffset(const std::vector<Value*>& indices);
|
||||
void printStatistics() const; // 打印统计信息
|
||||
|
||||
private:
|
||||
// ========== 配置选项 ==========
|
||||
bool aggressiveParameterMode = false; // 激进的参数别名分析模式
|
||||
bool parameterOptimizationEnabled = false; // 启用参数优化
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
242
src/include/midend/Pass/Analysis/CallGraphAnalysis.h
Normal file
242
src/include/midend/Pass/Analysis/CallGraphAnalysis.h
Normal file
@ -0,0 +1,242 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class CallGraphAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 调用图节点信息
|
||||
* 存储单个函数在调用图中的信息
|
||||
*/
|
||||
struct CallGraphNode {
|
||||
Function* function; // 关联的函数
|
||||
std::set<Function*> callers; // 调用此函数的函数集合
|
||||
std::set<Function*> callees; // 此函数调用的函数集合
|
||||
|
||||
// 递归信息
|
||||
bool isRecursive; // 是否参与递归调用
|
||||
bool isSelfRecursive; // 是否自递归
|
||||
int recursiveDepth; // 递归深度(-1表示无限递归)
|
||||
|
||||
// 调用统计
|
||||
size_t totalCallers; // 调用者总数
|
||||
size_t totalCallees; // 被调用函数总数
|
||||
size_t callSiteCount; // 调用点总数
|
||||
|
||||
CallGraphNode(Function* f) : function(f), isRecursive(false),
|
||||
isSelfRecursive(false), recursiveDepth(0), totalCallers(0),
|
||||
totalCallees(0), callSiteCount(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 调用图分析结果类
|
||||
* 包含整个模块的调用图信息和查询接口
|
||||
*/
|
||||
class CallGraphAnalysisResult : public AnalysisResultBase {
|
||||
public:
|
||||
CallGraphAnalysisResult(Module* M) : AssociatedModule(M) {}
|
||||
~CallGraphAnalysisResult() override = default;
|
||||
|
||||
// ========== 基础查询接口 ==========
|
||||
|
||||
/**
|
||||
* 获取函数的调用图节点
|
||||
*/
|
||||
const CallGraphNode* getNode(Function* F) const {
|
||||
auto it = nodes.find(F);
|
||||
return (it != nodes.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的调用图节点(非const版本)
|
||||
*/
|
||||
CallGraphNode* getMutableNode(Function* F) {
|
||||
auto it = nodes.find(F);
|
||||
return (it != nodes.end()) ? it->second.get() : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有函数节点
|
||||
*/
|
||||
const std::map<Function*, std::unique_ptr<CallGraphNode>>& getAllNodes() const {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查函数是否存在于调用图中
|
||||
*/
|
||||
bool hasFunction(Function* F) const {
|
||||
return nodes.find(F) != nodes.end();
|
||||
}
|
||||
|
||||
// ========== 调用关系查询 ==========
|
||||
|
||||
/**
|
||||
* 检查是否存在从caller到callee的调用
|
||||
*/
|
||||
bool hasCallEdge(Function* caller, Function* callee) const {
|
||||
auto node = getNode(caller);
|
||||
return node && node->callees.count(callee) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的所有调用者
|
||||
*/
|
||||
std::vector<Function*> getCallers(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
if (!node) return {};
|
||||
return std::vector<Function*>(node->callers.begin(), node->callers.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数的所有被调用函数
|
||||
*/
|
||||
std::vector<Function*> getCallees(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
if (!node) return {};
|
||||
return std::vector<Function*>(node->callees.begin(), node->callees.end());
|
||||
}
|
||||
|
||||
// ========== 递归分析查询 ==========
|
||||
|
||||
/**
|
||||
* 检查函数是否参与递归调用
|
||||
*/
|
||||
bool isRecursive(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node && node->isRecursive;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查函数是否自递归
|
||||
*/
|
||||
bool isSelfRecursive(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node && node->isSelfRecursive;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取递归深度
|
||||
*/
|
||||
int getRecursiveDepth(Function* F) const {
|
||||
auto node = getNode(F);
|
||||
return node ? node->recursiveDepth : 0;
|
||||
}
|
||||
|
||||
// ========== 拓扑排序和SCC ==========
|
||||
|
||||
/**
|
||||
* 获取函数的拓扑排序结果
|
||||
* 保证被调用函数在调用函数之前
|
||||
*/
|
||||
const std::vector<Function*>& getTopologicalOrder() const {
|
||||
return topologicalOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取强连通分量列表
|
||||
* 每个SCC表示一个递归函数群
|
||||
*/
|
||||
const std::vector<std::vector<Function*>>& getStronglyConnectedComponents() const {
|
||||
return sccs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取函数所在的SCC索引
|
||||
*/
|
||||
int getSCCIndex(Function* F) const {
|
||||
auto it = functionToSCC.find(F);
|
||||
return (it != functionToSCC.end()) ? it->second : -1;
|
||||
}
|
||||
|
||||
// ========== 统计信息 ==========
|
||||
|
||||
struct Statistics {
|
||||
size_t totalFunctions;
|
||||
size_t totalCallEdges;
|
||||
size_t recursiveFunctions;
|
||||
size_t selfRecursiveFunctions;
|
||||
size_t stronglyConnectedComponents;
|
||||
size_t maxSCCSize;
|
||||
double avgCallersPerFunction;
|
||||
double avgCalleesPerFunction;
|
||||
};
|
||||
|
||||
Statistics getStatistics() const;
|
||||
|
||||
/**
|
||||
* 打印调用图分析结果
|
||||
*/
|
||||
void print() const;
|
||||
|
||||
// ========== 内部构建接口 ==========
|
||||
|
||||
void addNode(Function* F);
|
||||
void addCallEdge(Function* caller, Function* callee);
|
||||
void computeTopologicalOrder();
|
||||
void computeStronglyConnectedComponents();
|
||||
void analyzeRecursion();
|
||||
|
||||
private:
|
||||
Module* AssociatedModule; // 关联的模块
|
||||
std::map<Function*, std::unique_ptr<CallGraphNode>> nodes; // 调用图节点
|
||||
std::vector<Function*> topologicalOrder; // 拓扑排序结果
|
||||
std::vector<std::vector<Function*>> sccs; // 强连通分量
|
||||
std::map<Function*, int> functionToSCC; // 函数到SCC的映射
|
||||
|
||||
// 内部辅助方法
|
||||
void dfsTopological(Function* F, std::unordered_set<Function*>& visited,
|
||||
std::vector<Function*>& result);
|
||||
void tarjanSCC();
|
||||
void tarjanDFS(Function* F, int& index, std::vector<int>& indices,
|
||||
std::vector<int>& lowlinks, std::vector<Function*>& stack,
|
||||
std::unordered_set<Function*>& onStack);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SysY调用图分析Pass
|
||||
* Module级别的分析Pass,构建整个模块的函数调用图
|
||||
*/
|
||||
class CallGraphAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void* ID;
|
||||
|
||||
CallGraphAnalysisPass() : AnalysisPass("CallGraphAnalysis", Pass::Granularity::Module) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnModule(Module* M, AnalysisManager& AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override { return std::move(CurrentResult); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<CallGraphAnalysisResult> CurrentResult; // 当前模块的分析结果
|
||||
|
||||
// ========== 主要分析流程 ==========
|
||||
|
||||
void buildCallGraph(Module* M); // 构建调用图
|
||||
void scanFunctionCalls(Function* F); // 扫描函数的调用
|
||||
void processCallInstruction(CallInst* call, Function* caller); // 处理调用指令
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
bool isLibraryFunction(Function* F) const; // 判断是否为标准库函数
|
||||
bool isIntrinsicFunction(Function* F) const; // 判断是否为内置函数
|
||||
void printStatistics() const; // 打印统计信息
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
618
src/include/midend/Pass/Analysis/Loop.h
Normal file
618
src/include/midend/Pass/Analysis/Loop.h
Normal file
@ -0,0 +1,618 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dom.h"
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class LoopAnalysisResult;
|
||||
class AliasAnalysisResult;
|
||||
class SideEffectAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 表示一个识别出的循环。
|
||||
*/
|
||||
class Loop {
|
||||
private:
|
||||
static int NextLoopID; // 静态变量用于分配唯一ID
|
||||
int LoopID;
|
||||
public:
|
||||
// 构造函数:指定循环头
|
||||
Loop(BasicBlock *header) : Header(header), LoopID(NextLoopID++) {}
|
||||
|
||||
// 获取循环头
|
||||
BasicBlock *getHeader() const { return Header; }
|
||||
|
||||
// 获取循环的名称 (基于ID)
|
||||
std::string getName() const { return "loop_" + std::to_string(LoopID); }
|
||||
// 获取循环体包含的所有基本块
|
||||
const std::set<BasicBlock *> &getBlocks() const { return LoopBlocks; }
|
||||
|
||||
// 获取循环的出口基本块(即从循环内部跳转到循环外部的基本块)
|
||||
const std::set<BasicBlock *> &getExitBlocks() const { return ExitBlocks; }
|
||||
|
||||
// 获取循环前置块(如果存在),可以为 nullptr
|
||||
BasicBlock *getPreHeader() const { return PreHeader; }
|
||||
|
||||
// 获取直接包含此循环的父循环(如果存在),可以为 nullptr
|
||||
Loop *getParentLoop() const { return ParentLoop; }
|
||||
|
||||
// 获取直接嵌套在此循环内的子循环
|
||||
const std::vector<Loop *> &getNestedLoops() const { return NestedLoops; }
|
||||
|
||||
// 获取循环的层级 (0 表示最外层循环,1 表示嵌套一层,以此类推)
|
||||
int getLoopLevel() const { return Level; }
|
||||
|
||||
// 检查一个基本块是否属于当前循环
|
||||
bool contains(BasicBlock *BB) const { return LoopBlocks.count(BB); }
|
||||
|
||||
// 判断当前循环是否是最内层循环 (没有嵌套子循环)
|
||||
bool isInnermost() const { return NestedLoops.empty(); }
|
||||
|
||||
// 获取循环的深度(从最外层开始计算)
|
||||
int getLoopDepth() const { return Level + 1; }
|
||||
|
||||
// 获取循环体的大小(基本块数量)
|
||||
size_t getLoopSize() const { return LoopBlocks.size(); }
|
||||
|
||||
// 检查循环是否有唯一的外部前驱(即是否有前置块)
|
||||
bool hasUniquePreHeader() const { return PreHeader != nullptr; }
|
||||
|
||||
// 检查循环是否是最外层循环(没有父循环)
|
||||
bool isOutermost() const { return getParentLoop() == nullptr; }
|
||||
|
||||
// 获取循环的所有出口(从循环内到循环外的基本块)
|
||||
std::vector<BasicBlock*> getExitingBlocks() const {
|
||||
std::vector<BasicBlock*> exitingBlocks;
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (BasicBlock* succ : bb->getSuccessors()) {
|
||||
if (!contains(succ)) {
|
||||
exitingBlocks.push_back(bb);
|
||||
break; // 每个基本块只添加一次
|
||||
}
|
||||
}
|
||||
}
|
||||
return exitingBlocks;
|
||||
}
|
||||
|
||||
// 判断循环是否是简单循环(只有一个回边)
|
||||
bool isSimpleLoop() const {
|
||||
int backEdgeCount = 0;
|
||||
for (BasicBlock* pred : Header->getPredecessors()) {
|
||||
if (contains(pred)) {
|
||||
backEdgeCount++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查循环是否可能有副作用(基于副作用分析结果)
|
||||
* 使用场景: 循环优化决策、并行化分析
|
||||
*/
|
||||
bool mayHaveSideEffects(SideEffectAnalysisResult* sideEffectAnalysis) const;
|
||||
|
||||
/**
|
||||
* 检查循环是否访问全局内存(基于别名分析结果)
|
||||
* 使用场景: 并行化分析、缓存优化
|
||||
*/
|
||||
bool accessesGlobalMemory(AliasAnalysisResult* aliasAnalysis) const;
|
||||
|
||||
/**
|
||||
* 检查循环是否有可能的内存别名冲突
|
||||
* 使用场景: 向量化分析、并行化决策
|
||||
*/
|
||||
bool hasMemoryAliasConflicts(AliasAnalysisResult* aliasAnalysis) const;
|
||||
|
||||
/**
|
||||
* 估算循环的"热度" (基于嵌套深度和大小)
|
||||
* 使用场景: 优化优先级、资源分配
|
||||
*/
|
||||
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); }
|
||||
void setPreHeader(BasicBlock *BB) { PreHeader = BB; }
|
||||
void setParentLoop(Loop *loop) { ParentLoop = loop; }
|
||||
void addNestedLoop(Loop *loop) { NestedLoops.push_back(loop); }
|
||||
void setLoopLevel(int level) { Level = level; }
|
||||
void clearNestedLoops() { NestedLoops.clear(); }
|
||||
private:
|
||||
BasicBlock *Header; // 循环头基本块
|
||||
std::set<BasicBlock *> LoopBlocks; // 循环体包含的基本块集合
|
||||
std::set<BasicBlock *> ExitBlocks; // 循环出口基本块集合
|
||||
BasicBlock *PreHeader = nullptr; // 循环前置块 (Optional)
|
||||
Loop *ParentLoop = nullptr; // 父循环 (用于嵌套)
|
||||
std::vector<Loop *> NestedLoops; // 嵌套的子循环
|
||||
int Level = -1; // 循环的层级,-1表示未计算
|
||||
};
|
||||
|
||||
/**
|
||||
* @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));
|
||||
LoopMap[AllLoops.back()->getHeader()] = AllLoops.back().get();
|
||||
}
|
||||
|
||||
// 获取所有识别出的循环(unique_ptr 管理内存)
|
||||
const std::vector<std::unique_ptr<Loop>> &getAllLoops() const { return AllLoops; }
|
||||
|
||||
// ========== 高频查询接口 ==========
|
||||
|
||||
/**
|
||||
* 获取所有最内层循环 - 循环优化的主要目标
|
||||
* 使用场景: 循环展开、向量化、循环不变量外提
|
||||
*/
|
||||
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 *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 {
|
||||
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];
|
||||
}
|
||||
|
||||
// ========== 利用别名和副作用分析的查询接口 ==========
|
||||
|
||||
/**
|
||||
* 获取所有纯循环(无副作用的循环)
|
||||
* 并行化、循环优化
|
||||
*/
|
||||
std::vector<Loop*> getPureLoops(SideEffectAnalysisResult* sideEffectAnalysis) const {
|
||||
std::vector<Loop*> result;
|
||||
if (!sideEffectAnalysis) return result;
|
||||
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (!loop->mayHaveSideEffects(sideEffectAnalysis)) {
|
||||
result.push_back(loop.get());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有只访问局部内存的循环
|
||||
* 缓存优化、局部性分析
|
||||
*/
|
||||
std::vector<Loop*> getLocalMemoryLoops(AliasAnalysisResult* aliasAnalysis) const {
|
||||
std::vector<Loop*> result;
|
||||
if (!aliasAnalysis) return result;
|
||||
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (!loop->accessesGlobalMemory(aliasAnalysis)) {
|
||||
result.push_back(loop.get());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有无内存别名冲突的循环
|
||||
* 向量化、并行化
|
||||
*/
|
||||
std::vector<Loop*> getNoAliasConflictLoops(AliasAnalysisResult* aliasAnalysis) const {
|
||||
std::vector<Loop*> result;
|
||||
if (!aliasAnalysis) return result;
|
||||
|
||||
for (const auto& loop : AllLoops) {
|
||||
if (!loop->hasMemoryAliasConflicts(aliasAnalysis)) {
|
||||
result.push_back(loop.get());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ========== 低频查询接口(不缓存) ==========
|
||||
|
||||
/**
|
||||
* 检查两个循环是否有嵌套关系
|
||||
* 循环间依赖分析
|
||||
*/
|
||||
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 {
|
||||
return getInnermostContainingLoop(BB);
|
||||
}
|
||||
|
||||
// ========== 缓存管理接口 ==========
|
||||
|
||||
/**
|
||||
* 手动失效缓存 (可删除)
|
||||
*/
|
||||
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;
|
||||
void printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const;
|
||||
void printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const;
|
||||
|
||||
private:
|
||||
Function *AssociatedFunction; // 结果关联的函数
|
||||
std::vector<std::unique_ptr<Loop>> AllLoops; // 所有识别出的循环
|
||||
std::map<BasicBlock *, Loop *> LoopMap; // 循环头到 Loop* 的映射,方便查找
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环分析遍。
|
||||
* 识别函数中的所有循环,并生成 LoopAnalysisResult。
|
||||
*/
|
||||
class LoopAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID,需要在 .cpp 文件中定义
|
||||
static void *ID;
|
||||
|
||||
LoopAnalysisPass() : AnalysisPass("LoopAnalysis", 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<LoopAnalysisResult> CurrentResult; // 当前函数的分析结果
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
356
src/include/midend/Pass/Analysis/LoopCharacteristics.h
Normal file
356
src/include/midend/Pass/Analysis/LoopCharacteristics.h
Normal file
@ -0,0 +1,356 @@
|
||||
#pragma once
|
||||
|
||||
#include "Dom.h" // 支配树分析依赖
|
||||
#include "Loop.h" // 循环分析依赖
|
||||
#include "Liveness.h" // 活跃性分析依赖
|
||||
#include "AliasAnalysis.h" // 别名分析依赖
|
||||
#include "SideEffectAnalysis.h" // 副作用分析依赖
|
||||
#include "CallGraphAnalysis.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;
|
||||
|
||||
enum IVKind {
|
||||
kBasic, // 基本归纳变量
|
||||
kLinear, // 线性归纳变量
|
||||
kCmplx // 复杂派生归纳变量
|
||||
} ; // 归纳变量类型
|
||||
|
||||
struct InductionVarInfo {
|
||||
Value* div; // 派生归纳变量的指令
|
||||
Value* base = nullptr; // 其根phi或BIV或DIV
|
||||
std::pair<Value*, Value*> Multibase = {nullptr, nullptr}; // 多个BIV
|
||||
Instruction::Kind Instkind; // 操作类型
|
||||
int factor = 1; // 系数(如i*2+3的2)
|
||||
int offset = 0; // 常量偏移
|
||||
bool valid; // 是否线性可归约
|
||||
IVKind ivkind; // 归纳变量类型
|
||||
|
||||
|
||||
static std::unique_ptr<InductionVarInfo> createBasicBIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
|
||||
return std::make_unique<InductionVarInfo>(
|
||||
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kBasic}
|
||||
);
|
||||
}
|
||||
|
||||
static std::unique_ptr<InductionVarInfo> createSingleDIV(Value* v, Instruction::Kind kind, Value* base = nullptr, int factor = 1, int offset = 0) {
|
||||
return std::make_unique<InductionVarInfo>(
|
||||
InductionVarInfo{v, base, {nullptr, nullptr}, kind, factor, offset, true, IVKind::kLinear}
|
||||
);
|
||||
}
|
||||
|
||||
static std::unique_ptr<InductionVarInfo> createDoubleDIV(Value* v, Instruction::Kind kind, Value* base1 = nullptr, Value* base2 = nullptr, int factor = 1, int offset = 0) {
|
||||
return std::make_unique<InductionVarInfo>(
|
||||
InductionVarInfo{v, nullptr, {base1, base2}, kind, factor, offset, false, IVKind::kCmplx}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环特征信息结构 - 基础循环分析阶段
|
||||
* 存储循环的基本特征信息,为后续精确分析提供基础
|
||||
*/
|
||||
struct LoopCharacteristics {
|
||||
Loop* loop; // 关联的循环对象
|
||||
|
||||
// ========== 基础循环形式分析 ==========
|
||||
bool isCountingLoop; // 是否为计数循环 (for i=0; i<n; i++)
|
||||
bool isSimpleForLoop; // 是否为简单for循环
|
||||
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
||||
bool isInnermost; // 是否为最内层循环
|
||||
|
||||
// ========== 归纳变量分析 ==========
|
||||
|
||||
// ========== 基础循环不变量分析 ==========
|
||||
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
||||
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
||||
|
||||
std::vector<std::unique_ptr<InductionVarInfo>> InductionVars; // 归纳变量
|
||||
|
||||
// ========== 基础边界分析 ==========
|
||||
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
||||
bool hasKnownBounds; // 是否有已知边界
|
||||
|
||||
// ========== 基础纯度和副作用分析 ==========
|
||||
bool isPure; // 是否为纯循环(无副作用)
|
||||
bool accessesOnlyLocalMemory; // 是否只访问局部内存
|
||||
bool hasNoMemoryAliasConflicts; // 是否无内存别名冲突
|
||||
|
||||
// ========== 基础内存访问模式分析 ==========
|
||||
struct MemoryAccessPattern {
|
||||
std::vector<Instruction*> loadInsts; // load指令列表
|
||||
std::vector<Instruction*> storeInsts; // store指令列表
|
||||
bool isArrayParameter; // 是否为数组参数访问
|
||||
bool isGlobalArray; // 是否为全局数组访问
|
||||
bool hasConstantIndices; // 是否使用常量索引
|
||||
};
|
||||
std::map<Value*, MemoryAccessPattern> memoryPatterns; // 内存访问模式
|
||||
|
||||
// ========== 基础性能特征 ==========
|
||||
size_t instructionCount; // 循环体指令数
|
||||
size_t memoryOperationCount; // 内存操作数
|
||||
size_t arithmeticOperationCount; // 算术操作数
|
||||
double computeToMemoryRatio; // 计算与内存操作比率
|
||||
|
||||
// ========== 基础优化提示 ==========
|
||||
bool benefitsFromUnrolling; // 是否适合循环展开
|
||||
int suggestedUnrollFactor; // 建议的展开因子
|
||||
|
||||
// 构造函数 - 简化的基础分析初始化
|
||||
LoopCharacteristics(Loop* l) : loop(l),
|
||||
isCountingLoop(false), isSimpleForLoop(false), hasComplexControlFlow(false),
|
||||
isInnermost(false), hasKnownBounds(false), isPure(false),
|
||||
accessesOnlyLocalMemory(false), hasNoMemoryAliasConflicts(false),
|
||||
benefitsFromUnrolling(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*> getPureLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->isPure) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有只访问局部内存的循环
|
||||
*/
|
||||
std::vector<Loop*> getLocalMemoryOnlyLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->accessesOnlyLocalMemory) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有无内存别名冲突的循环
|
||||
*/
|
||||
std::vector<Loop*> getNoAliasConflictLoops() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->hasNoMemoryAliasConflicts) {
|
||||
result.push_back(loop);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有适合展开的循环
|
||||
*/
|
||||
std::vector<Loop*> getUnrollingCandidates() const {
|
||||
std::vector<Loop*> result;
|
||||
for (const auto& [loop, chars] : CharacteristicsMap) {
|
||||
if (chars->benefitsFromUnrolling) {
|
||||
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 BasicOptimizationStats {
|
||||
size_t totalLoops;
|
||||
size_t countingLoops;
|
||||
size_t unrollingCandidates;
|
||||
size_t pureLoops;
|
||||
size_t localMemoryOnlyLoops;
|
||||
size_t noAliasConflictLoops;
|
||||
double avgInstructionCount;
|
||||
double avgComputeMemoryRatio;
|
||||
};
|
||||
|
||||
BasicOptimizationStats getOptimizationStats() const {
|
||||
BasicOptimizationStats 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->benefitsFromUnrolling) stats.unrollingCandidates++;
|
||||
if (chars->isPure) stats.pureLoops++;
|
||||
if (chars->accessesOnlyLocalMemory) stats.localMemoryOnlyLoops++;
|
||||
if (chars->hasNoMemoryAliasConflicts) stats.noAliasConflictLoops++;
|
||||
|
||||
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;
|
||||
|
||||
// ========== 缓存的分析结果 ==========
|
||||
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
|
||||
AliasAnalysisResult* aliasAnalysis; // 别名分析结果
|
||||
SideEffectAnalysisResult* sideEffectAnalysis; // 副作用分析结果
|
||||
|
||||
// ========== 核心分析方法 ==========
|
||||
void analyzeLoop(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础循环形式分析
|
||||
void analyzeLoopForm(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础性能指标计算
|
||||
void computePerformanceMetrics(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础纯度和副作用分析
|
||||
void analyzePurityAndSideEffects(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础归纳变量识别
|
||||
void identifyBasicInductionVariables(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 循环不变量识别
|
||||
void identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础边界分析
|
||||
void analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础内存访问模式分析
|
||||
void analyzeBasicMemoryAccessPatterns(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// 基础优化评估
|
||||
void evaluateBasicOptimizationOpportunities(Loop* loop, LoopCharacteristics* characteristics);
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants);
|
||||
void findDerivedInductionVars(Value* root,
|
||||
Value* base, // 只传单一BIV base
|
||||
Loop* loop,
|
||||
std::vector<std::unique_ptr<InductionVarInfo>>& ivs,
|
||||
std::set<Value*>& visited
|
||||
);
|
||||
bool isBasicInductionVariable(Value* val, Loop* loop);
|
||||
bool hasSimpleMemoryPattern(Loop* loop); // 简单的内存模式检查
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
250
src/include/midend/Pass/Analysis/LoopVectorization.h
Normal file
250
src/include/midend/Pass/Analysis/LoopVectorization.h
Normal file
@ -0,0 +1,250 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "Loop.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/**
|
||||
* @brief 依赖类型枚举 - 只考虑真正影响并行性的依赖
|
||||
*
|
||||
* 依赖类型分析说明:
|
||||
* - TRUE_DEPENDENCE (RAW): 真依赖,必须保持原始执行顺序,是最关键的依赖
|
||||
* - ANTI_DEPENDENCE (WAR): 反依赖,影响指令重排序,可通过寄存器重命名等技术缓解
|
||||
* - OUTPUT_DEPENDENCE (WAW): 输出依赖,相对较少但需要考虑,可通过变量私有化解决
|
||||
*
|
||||
*/
|
||||
enum class DependenceType {
|
||||
TRUE_DEPENDENCE, // 真依赖 (RAW) - 读后写流依赖,最重要的依赖类型
|
||||
ANTI_DEPENDENCE, // 反依赖 (WAR) - 写后读反向依赖,影响指令重排序
|
||||
OUTPUT_DEPENDENCE // 输出依赖 (WAW) - 写后写,相对较少但需要考虑
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 依赖向量 - 表示两个内存访问之间的迭代距离
|
||||
* 例如:a[i] 和 a[i+1] 之间的依赖向量是 [1]
|
||||
* a[i][j] 和 a[i+1][j-2] 之间的依赖向量是 [1,-2]
|
||||
*/
|
||||
struct DependenceVector {
|
||||
std::vector<int> distances; // 每个循环层次的依赖距离
|
||||
bool isConstant; // 是否为常量距离
|
||||
bool isKnown; // 是否已知距离
|
||||
|
||||
DependenceVector(size_t loopDepth) : distances(loopDepth, 0), isConstant(false), isKnown(false) {}
|
||||
|
||||
// 检查是否为循环无关依赖
|
||||
bool isLoopIndependent() const {
|
||||
for (int dist : distances) {
|
||||
if (dist != 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取词典序方向向量
|
||||
std::vector<int> getDirectionVector() const;
|
||||
|
||||
// 检查是否可以通过向量化处理
|
||||
bool isVectorizationSafe() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 精确依赖关系 - 包含依赖向量的详细依赖信息
|
||||
*/
|
||||
struct PreciseDependence {
|
||||
Instruction* source;
|
||||
Instruction* sink;
|
||||
DependenceType type;
|
||||
DependenceVector dependenceVector;
|
||||
Value* memoryLocation;
|
||||
|
||||
// 并行化相关
|
||||
bool allowsParallelization; // 是否允许并行化
|
||||
bool requiresSynchronization; // 是否需要同步
|
||||
bool isReductionDependence; // 是否为归约依赖
|
||||
|
||||
PreciseDependence(size_t loopDepth) : dependenceVector(loopDepth),
|
||||
allowsParallelization(true), requiresSynchronization(false), isReductionDependence(false) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 向量化分析信息 - 暂时搁置,保留接口
|
||||
*/
|
||||
struct VectorizationAnalysis {
|
||||
bool isVectorizable; // 固定为false,暂不支持
|
||||
int suggestedVectorWidth; // 固定为1
|
||||
std::vector<std::string> preventingFactors; // 阻止向量化的因素
|
||||
|
||||
VectorizationAnalysis() : isVectorizable(false), suggestedVectorWidth(1) {
|
||||
preventingFactors.push_back("Vectorization temporarily disabled");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 并行化分析信息
|
||||
*/
|
||||
struct ParallelizationAnalysis {
|
||||
bool isParallelizable; // 是否可并行化
|
||||
int suggestedThreadCount; // 建议的线程数
|
||||
std::vector<std::string> preventingFactors; // 阻止并行化的因素
|
||||
|
||||
// 并行化模式
|
||||
enum ParallelizationType {
|
||||
NONE, // 不可并行化
|
||||
EMBARRASSINGLY_PARALLEL, // 完全并行
|
||||
REDUCTION_PARALLEL, // 归约并行
|
||||
PIPELINE_PARALLEL, // 流水线并行
|
||||
CONDITIONAL_PARALLEL // 条件并行
|
||||
} parallelType;
|
||||
|
||||
// 负载均衡
|
||||
bool hasLoadBalance; // 是否有良好的负载均衡
|
||||
bool isDynamicLoadBalanced; // 是否需要动态负载均衡
|
||||
double workComplexity; // 工作复杂度估计
|
||||
|
||||
// 同步需求
|
||||
bool requiresReduction; // 是否需要归约操作
|
||||
bool requiresBarrier; // 是否需要屏障同步
|
||||
std::set<Value*> sharedVariables; // 共享变量
|
||||
std::set<Value*> reductionVariables; // 归约变量
|
||||
std::set<Value*> privatizableVariables; // 可私有化变量
|
||||
|
||||
// 内存访问模式
|
||||
bool hasMemoryConflicts; // 是否有内存冲突
|
||||
bool hasReadOnlyAccess; // 是否只有只读访问
|
||||
bool hasIndependentAccess; // 是否有独立的内存访问
|
||||
|
||||
// 并行化收益评估
|
||||
double parallelizationBenefit; // 并行化收益估计 (0-1)
|
||||
size_t communicationCost; // 通信开销估计
|
||||
size_t synchronizationCost; // 同步开销估计
|
||||
|
||||
ParallelizationAnalysis() : isParallelizable(false), suggestedThreadCount(1), parallelType(NONE),
|
||||
hasLoadBalance(true), isDynamicLoadBalanced(false), workComplexity(0.0), requiresReduction(false),
|
||||
requiresBarrier(false), hasMemoryConflicts(false), hasReadOnlyAccess(false), hasIndependentAccess(false),
|
||||
parallelizationBenefit(0.0), communicationCost(0), synchronizationCost(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环向量化/并行化分析结果
|
||||
*/
|
||||
class LoopVectorizationResult : public AnalysisResultBase {
|
||||
private:
|
||||
Function* AssociatedFunction;
|
||||
std::map<Loop*, VectorizationAnalysis> VectorizationMap;
|
||||
std::map<Loop*, ParallelizationAnalysis> ParallelizationMap;
|
||||
std::map<Loop*, std::vector<PreciseDependence>> DependenceMap;
|
||||
|
||||
public:
|
||||
LoopVectorizationResult(Function* F) : AssociatedFunction(F) {}
|
||||
~LoopVectorizationResult() override = default;
|
||||
|
||||
// 基础接口
|
||||
void addVectorizationAnalysis(Loop* loop, VectorizationAnalysis analysis) {
|
||||
VectorizationMap[loop] = std::move(analysis);
|
||||
}
|
||||
|
||||
void addParallelizationAnalysis(Loop* loop, ParallelizationAnalysis analysis) {
|
||||
ParallelizationMap[loop] = std::move(analysis);
|
||||
}
|
||||
|
||||
void addDependenceAnalysis(Loop* loop, std::vector<PreciseDependence> dependences) {
|
||||
DependenceMap[loop] = std::move(dependences);
|
||||
}
|
||||
|
||||
// 查询接口
|
||||
const VectorizationAnalysis* getVectorizationAnalysis(Loop* loop) const {
|
||||
auto it = VectorizationMap.find(loop);
|
||||
return it != VectorizationMap.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
const ParallelizationAnalysis* getParallelizationAnalysis(Loop* loop) const {
|
||||
auto it = ParallelizationMap.find(loop);
|
||||
return it != ParallelizationMap.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
const std::vector<PreciseDependence>* getPreciseDependences(Loop* loop) const {
|
||||
auto it = DependenceMap.find(loop);
|
||||
return it != DependenceMap.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
// 统计接口
|
||||
size_t getVectorizableLoopCount() const;
|
||||
size_t getParallelizableLoopCount() const;
|
||||
|
||||
// 优化建议
|
||||
std::vector<Loop*> getVectorizationCandidates() const;
|
||||
std::vector<Loop*> getParallelizationCandidates() const;
|
||||
|
||||
// 打印分析结果
|
||||
void print() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环向量化/并行化分析遍
|
||||
* 在循环规范化后执行,进行精确的依赖向量分析和向量化/并行化可行性评估
|
||||
* 专注于并行化分析,向量化功能暂时搁置
|
||||
*/
|
||||
class LoopVectorizationPass : public AnalysisPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
LoopVectorizationPass() : AnalysisPass("LoopVectorization", 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<LoopVectorizationResult> CurrentResult;
|
||||
|
||||
// ========== 主要分析方法 ==========
|
||||
void analyzeLoop(Loop* loop, LoopCharacteristics* characteristics,
|
||||
AliasAnalysisResult* aliasAnalysis, SideEffectAnalysisResult* sideEffectAnalysis);
|
||||
|
||||
// ========== 依赖向量分析 ==========
|
||||
std::vector<PreciseDependence> computeDependenceVectors(Loop* loop, AliasAnalysisResult* aliasAnalysis);
|
||||
DependenceVector computeAccessDependence(Instruction* inst1, Instruction* inst2, Loop* loop);
|
||||
bool areAccessesAffinelyRelated(Value* ptr1, Value* ptr2, Loop* loop);
|
||||
|
||||
// ========== 向量化分析 (暂时搁置) ==========
|
||||
VectorizationAnalysis analyzeVectorizability(Loop* loop, const std::vector<PreciseDependence>& dependences,
|
||||
LoopCharacteristics* characteristics);
|
||||
|
||||
// ========== 并行化分析 ==========
|
||||
ParallelizationAnalysis analyzeParallelizability(Loop* loop, const std::vector<PreciseDependence>& dependences,
|
||||
LoopCharacteristics* characteristics);
|
||||
bool checkParallelizationLegality(Loop* loop, const std::vector<PreciseDependence>& dependences);
|
||||
int estimateOptimalThreadCount(Loop* loop, LoopCharacteristics* characteristics);
|
||||
ParallelizationAnalysis::ParallelizationType determineParallelizationType(Loop* loop,
|
||||
const std::vector<PreciseDependence>& dependences);
|
||||
|
||||
// ========== 并行化专用分析方法 ==========
|
||||
void analyzeReductionPatterns(Loop* loop, ParallelizationAnalysis* analysis);
|
||||
void analyzeMemoryAccessPatterns(Loop* loop, ParallelizationAnalysis* analysis, AliasAnalysisResult* aliasAnalysis);
|
||||
void estimateParallelizationBenefit(Loop* loop, ParallelizationAnalysis* analysis, LoopCharacteristics* characteristics);
|
||||
void identifyPrivatizableVariables(Loop* loop, ParallelizationAnalysis* analysis);
|
||||
void analyzeSynchronizationNeeds(Loop* loop, ParallelizationAnalysis* analysis, const std::vector<PreciseDependence>& dependences);
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
std::vector<int> extractInductionCoefficients(Value* ptr, Loop* loop);
|
||||
bool isConstantStride(Value* ptr, Loop* loop, int& stride);
|
||||
bool isIndependentMemoryAccess(Value* ptr1, Value* ptr2, Loop* loop);
|
||||
double estimateWorkComplexity(Loop* loop);
|
||||
bool hasReductionPattern(Value* var, Loop* loop);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
137
src/include/midend/Pass/Analysis/SideEffectAnalysis.h
Normal file
137
src/include/midend/Pass/Analysis/SideEffectAnalysis.h
Normal file
@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "CallGraphAnalysis.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:
|
||||
};
|
||||
|
||||
// 副作用分析遍类 - Module级别分析
|
||||
class SysYSideEffectAnalysisPass : public AnalysisPass {
|
||||
public:
|
||||
// 静态成员,作为该遍的唯一ID
|
||||
static void* ID;
|
||||
|
||||
SysYSideEffectAnalysisPass() : AnalysisPass("SysYSideEffectAnalysis", Granularity::Module) {}
|
||||
|
||||
// 在模块上运行分析
|
||||
bool runOnModule(Module* M, AnalysisManager& AM) override;
|
||||
|
||||
// 获取分析结果
|
||||
std::unique_ptr<AnalysisResultBase> getResult() override;
|
||||
|
||||
// Pass 基类中的纯虚函数,必须实现
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
private:
|
||||
// 分析结果
|
||||
std::unique_ptr<SideEffectAnalysisResult> result;
|
||||
|
||||
// 调用图分析结果
|
||||
CallGraphAnalysisResult* callGraphAnalysis = nullptr;
|
||||
|
||||
// 分析单个函数的副作用(Module级别的内部方法)
|
||||
SideEffectInfo analyzeFunction(Function* func, AnalysisManager& AM);
|
||||
|
||||
// 分析单个指令的副作用
|
||||
SideEffectInfo analyzeInstruction(Instruction* inst, Function* currentFunc, AnalysisManager& AM);
|
||||
|
||||
// 分析函数调用指令的副作用(利用调用图)
|
||||
SideEffectInfo analyzeCallInstruction(CallInst* call, Function* currentFunc, AnalysisManager& AM);
|
||||
|
||||
// 分析存储指令的副作用
|
||||
SideEffectInfo analyzeStoreInstruction(StoreInst* store, Function* currentFunc, AnalysisManager& AM);
|
||||
|
||||
// 分析内存设置指令的副作用
|
||||
SideEffectInfo analyzeMemsetInstruction(MemsetInst* memset, Function* currentFunc, AnalysisManager& AM);
|
||||
|
||||
// 使用不动点算法分析递归函数群
|
||||
void analyzeStronglyConnectedComponent(const std::vector<Function*>& scc, AnalysisManager& AM);
|
||||
|
||||
// 检查函数间副作用传播的收敛性
|
||||
bool hasConverged(const std::unordered_map<Function*, SideEffectInfo>& oldEffects,
|
||||
const std::unordered_map<Function*, SideEffectInfo>& newEffects) const;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@ -4,6 +4,8 @@
|
||||
#include "IR.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include "Dom.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <unordered_set>
|
||||
#include <queue>
|
||||
|
||||
@ -25,8 +27,12 @@ public:
|
||||
private:
|
||||
// 存储活跃指令的集合
|
||||
std::unordered_set<Instruction*> alive_insts;
|
||||
// 别名分析结果
|
||||
AliasAnalysisResult* aliasAnalysis = nullptr;
|
||||
// 副作用分析结果
|
||||
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
|
||||
|
||||
// 判断指令是否是“天然活跃”的(即总是保留的)
|
||||
// 判断指令是否是"天然活跃"的(即总是保留的)
|
||||
// inst: 要检查的指令
|
||||
// 返回值: 如果指令是天然活跃的,则为true,否则为false
|
||||
bool isAlive(Instruction* inst);
|
||||
@ -34,6 +40,9 @@ private:
|
||||
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
|
||||
// inst: 要标记为活跃的指令
|
||||
void addAlive(Instruction* inst);
|
||||
|
||||
// 检查Store指令是否可能有副作用(通过别名分析)
|
||||
bool mayHaveSideEffect(StoreInst* store);
|
||||
};
|
||||
|
||||
// DCE 优化遍类,继承自 OptimizationPass
|
||||
|
||||
157
src/include/midend/Pass/Optimize/InductionVariableElimination.h
Normal file
157
src/include/midend/Pass/Optimize/InductionVariableElimination.h
Normal file
@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Loop.h"
|
||||
#include "Dom.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class LoopCharacteristicsResult;
|
||||
class LoopAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 死归纳变量信息
|
||||
* 记录一个可以被消除的归纳变量
|
||||
*/
|
||||
struct DeadInductionVariable {
|
||||
PhiInst* phiInst; // phi 指令
|
||||
std::vector<Instruction*> relatedInsts; // 相关的递增/递减指令
|
||||
Loop* containingLoop; // 所在循环
|
||||
bool canEliminate; // 是否可以安全消除
|
||||
|
||||
DeadInductionVariable(PhiInst* phi, Loop* loop)
|
||||
: phiInst(phi), containingLoop(loop), canEliminate(false) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 归纳变量消除上下文类
|
||||
* 封装归纳变量消除优化的核心逻辑和状态
|
||||
*/
|
||||
class InductionVariableEliminationContext {
|
||||
public:
|
||||
InductionVariableEliminationContext() {}
|
||||
|
||||
/**
|
||||
* 运行归纳变量消除优化
|
||||
* @param F 目标函数
|
||||
* @param AM 分析管理器
|
||||
* @return 是否修改了IR
|
||||
*/
|
||||
bool run(Function* F, AnalysisManager& AM);
|
||||
|
||||
private:
|
||||
// 分析结果缓存
|
||||
LoopAnalysisResult* loopAnalysis = nullptr;
|
||||
LoopCharacteristicsResult* loopCharacteristics = nullptr;
|
||||
DominatorTree* dominatorTree = nullptr;
|
||||
SideEffectAnalysisResult* sideEffectAnalysis = nullptr;
|
||||
|
||||
// 死归纳变量存储
|
||||
std::vector<std::unique_ptr<DeadInductionVariable>> deadIVs;
|
||||
std::unordered_map<Loop*, std::vector<DeadInductionVariable*>> loopToDeadIVs;
|
||||
|
||||
// ========== 核心分析和优化阶段 ==========
|
||||
|
||||
/**
|
||||
* 阶段1:识别死归纳变量
|
||||
* 找出没有被有效使用的归纳变量
|
||||
*/
|
||||
void identifyDeadInductionVariables(Function* F);
|
||||
|
||||
/**
|
||||
* 阶段2:分析消除的安全性
|
||||
* 确保消除操作不会破坏程序语义
|
||||
*/
|
||||
void analyzeSafetyForElimination();
|
||||
|
||||
/**
|
||||
* 阶段3:执行归纳变量消除
|
||||
* 删除死归纳变量及其相关指令
|
||||
*/
|
||||
bool performInductionVariableElimination();
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 检查归纳变量是否为死归纳变量
|
||||
* @param iv 归纳变量信息
|
||||
* @param loop 所在循环
|
||||
* @return 如果是死归纳变量返回相关信息,否则返回nullptr
|
||||
*/
|
||||
std::unique_ptr<DeadInductionVariable>
|
||||
isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查归纳变量是否只用于自身更新
|
||||
* @param phiInst phi指令
|
||||
* @param loop 所在循环
|
||||
* @return 是否只用于自身更新
|
||||
*/
|
||||
bool isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop);
|
||||
|
||||
/**
|
||||
* 收集与归纳变量相关的所有指令
|
||||
* @param phiInst phi指令
|
||||
* @param loop 所在循环
|
||||
* @return 相关指令列表
|
||||
*/
|
||||
std::vector<Instruction*> collectRelatedInstructions(PhiInst* phiInst, Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查消除归纳变量的安全性
|
||||
* @param deadIV 死归纳变量
|
||||
* @return 是否可以安全消除
|
||||
*/
|
||||
bool isSafeToEliminate(const DeadInductionVariable* deadIV);
|
||||
|
||||
/**
|
||||
* 消除单个死归纳变量
|
||||
* @param deadIV 死归纳变量
|
||||
* @return 是否成功消除
|
||||
*/
|
||||
bool eliminateDeadInductionVariable(DeadInductionVariable* deadIV);
|
||||
|
||||
/**
|
||||
* 打印调试信息
|
||||
*/
|
||||
void printDebugInfo();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 归纳变量消除优化遍
|
||||
* 消除循环中无用的归纳变量,减少寄存器压力
|
||||
*/
|
||||
class InductionVariableElimination : public OptimizationPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
InductionVariableElimination()
|
||||
: OptimizationPass("InductionVariableElimination", Granularity::Function) {}
|
||||
|
||||
/**
|
||||
* 在函数上运行归纳变量消除优化
|
||||
* @param F 目标函数
|
||||
* @param AM 分析管理器
|
||||
* @return 是否修改了IR
|
||||
*/
|
||||
bool runOnFunction(Function* F, AnalysisManager& AM) override;
|
||||
|
||||
/**
|
||||
* 声明分析依赖和失效信息
|
||||
*/
|
||||
void getAnalysisUsage(std::set<void*>& analysisDependencies,
|
||||
std::set<void*>& analysisInvalidations) const override;
|
||||
|
||||
void* getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
40
src/include/midend/Pass/Optimize/LICM.h
Normal file
40
src/include/midend/Pass/Optimize/LICM.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include "Pass.h"
|
||||
#include "Loop.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Dom.h"
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy{
|
||||
|
||||
class LICMContext {
|
||||
public:
|
||||
LICMContext(Function* func, Loop* loop, IRBuilder* builder, const LoopCharacteristics* chars)
|
||||
: func(func), loop(loop), builder(builder), chars(chars) {}
|
||||
// 运行LICM主流程,返回IR是否被修改
|
||||
bool run();
|
||||
|
||||
private:
|
||||
Function* func;
|
||||
Loop* loop;
|
||||
IRBuilder* builder;
|
||||
const LoopCharacteristics* chars; // 特征分析结果
|
||||
|
||||
// 外提所有可提升指令
|
||||
bool hoistInstructions();
|
||||
};
|
||||
|
||||
|
||||
class LICM : public OptimizationPass{
|
||||
private:
|
||||
IRBuilder *builder; ///< IR构建器,用于插入指令
|
||||
public:
|
||||
static void *ID;
|
||||
LICM(IRBuilder *builder = nullptr) : OptimizationPass("LICM", Granularity::Function) , builder(builder) {}
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
void getAnalysisUsage(std::set<void *> &, std::set<void *> &) const override;
|
||||
void *getPassID() const override { return &ID; }
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
155
src/include/midend/Pass/Optimize/LoopNormalization.h
Normal file
155
src/include/midend/Pass/Optimize/LoopNormalization.h
Normal file
@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#include "Loop.h" // 循环分析依赖
|
||||
#include "Dom.h" // 支配树分析依赖
|
||||
#include "IR.h" // IR定义
|
||||
#include "IRBuilder.h" // IR构建器
|
||||
#include "Pass.h" // Pass框架
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/**
|
||||
* @brief 循环规范化转换Pass
|
||||
*
|
||||
* 该Pass在循环不变量提升等优化前运行,主要负责:
|
||||
* 1. 为没有前置块(preheader)的循环创建前置块
|
||||
* 2. 确保循环结构符合后续优化的要求
|
||||
* 3. 规范化循环的控制流结构
|
||||
*
|
||||
* 前置块的作用:
|
||||
* - 为循环不变量提升提供插入位置
|
||||
* - 简化循环分析和优化
|
||||
* - 确保循环有唯一的入口点
|
||||
*/
|
||||
class LoopNormalizationPass : public OptimizationPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
LoopNormalizationPass(IRBuilder* builder) : OptimizationPass("LoopNormalization", Pass::Granularity::Function), builder(builder) {}
|
||||
|
||||
// 实现 getPassID
|
||||
void *getPassID() const override { return &ID; }
|
||||
|
||||
// 核心运行方法
|
||||
bool runOnFunction(Function *F, AnalysisManager &AM) override;
|
||||
|
||||
// 声明分析依赖和失效信息
|
||||
void getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const override;
|
||||
|
||||
private:
|
||||
// ========== IR构建器 ==========
|
||||
IRBuilder* builder; // IR构建器
|
||||
|
||||
// ========== 缓存的分析结果 ==========
|
||||
LoopAnalysisResult* loopAnalysis; // 循环结构分析结果
|
||||
DominatorTree* domTree; // 支配树分析结果
|
||||
|
||||
// ========== 规范化统计 ==========
|
||||
struct NormalizationStats {
|
||||
size_t totalLoops; // 总循环数
|
||||
size_t loopsNeedingPreheader; // 需要前置块的循环数
|
||||
size_t preheadersCreated; // 创建的前置块数
|
||||
size_t loopsNormalized; // 规范化的循环数
|
||||
size_t redundantPhisRemoved; // 删除的冗余PHI节点数
|
||||
|
||||
NormalizationStats() : totalLoops(0), loopsNeedingPreheader(0),
|
||||
preheadersCreated(0), loopsNormalized(0),
|
||||
redundantPhisRemoved(0) {}
|
||||
} stats;
|
||||
|
||||
// ========== 核心规范化方法 ==========
|
||||
|
||||
/**
|
||||
* 规范化单个循环
|
||||
* @param loop 要规范化的循环
|
||||
* @return 是否进行了修改
|
||||
*/
|
||||
bool normalizeLoop(Loop* loop);
|
||||
|
||||
/**
|
||||
* 为循环创建前置块
|
||||
* @param loop 需要前置块的循环
|
||||
* @return 创建的前置块,如果失败则返回nullptr
|
||||
*/
|
||||
BasicBlock* createPreheaderForLoop(Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查循环是否需要前置块(基于结构性需求)
|
||||
* @param loop 要检查的循环
|
||||
* @return true如果需要前置块
|
||||
*/
|
||||
bool needsPreheader(Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查循环是否已有合适的前置块
|
||||
* @param loop 要检查的循环
|
||||
* @return 现有的前置块,如果没有则返回nullptr
|
||||
*/
|
||||
BasicBlock* getExistingPreheader(Loop* loop);
|
||||
|
||||
/**
|
||||
* 更新支配树关系(在创建新块后)
|
||||
* @param newBlock 新创建的基本块
|
||||
* @param loop 相关的循环
|
||||
*/
|
||||
void updateDominatorRelations(BasicBlock* newBlock, Loop* loop);
|
||||
|
||||
/**
|
||||
* 重定向循环外的前驱块到新的前置块
|
||||
* @param loop 目标循环
|
||||
* @param preheader 新创建的前置块
|
||||
* @param header 循环头部
|
||||
*/
|
||||
void redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header, const std::vector<BasicBlock*>& externalPreds);
|
||||
|
||||
/**
|
||||
* 为前置块生成合适的名称
|
||||
* @param loop 相关的循环
|
||||
* @return 生成的前置块名称
|
||||
*/
|
||||
std::string generatePreheaderName(Loop* loop);
|
||||
|
||||
/**
|
||||
* 验证规范化结果的正确性
|
||||
* @param loop 规范化后的循环
|
||||
* @return true如果规范化正确
|
||||
*/
|
||||
bool validateNormalization(Loop* loop);
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 获取循环的外部前驱块(不在循环内的前驱)
|
||||
* @param loop 目标循环
|
||||
* @return 外部前驱块列表
|
||||
*/
|
||||
std::vector<BasicBlock*> getExternalPredecessors(Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查基本块是否适合作为前置块
|
||||
* @param block 候选基本块
|
||||
* @param loop 目标循环
|
||||
* @return true如果适合作为前置块
|
||||
*/
|
||||
bool isSuitableAsPreheader(BasicBlock* block, Loop* loop);
|
||||
|
||||
/**
|
||||
* 更新PHI节点以适应新的前置块
|
||||
* @param header 循环头部
|
||||
* @param preheader 新的前置块
|
||||
* @param oldPreds 原来的外部前驱
|
||||
*/
|
||||
void updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
|
||||
const std::vector<BasicBlock*>& oldPreds);
|
||||
|
||||
/**
|
||||
* 打印规范化统计信息
|
||||
*/
|
||||
void printStats(Function* F);
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
240
src/include/midend/Pass/Optimize/LoopStrengthReduction.h
Normal file
240
src/include/midend/Pass/Optimize/LoopStrengthReduction.h
Normal file
@ -0,0 +1,240 @@
|
||||
#pragma once
|
||||
|
||||
#include "Pass.h"
|
||||
#include "IR.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Loop.h"
|
||||
#include "Dom.h"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 前向声明
|
||||
class LoopCharacteristicsResult;
|
||||
class LoopAnalysisResult;
|
||||
|
||||
/**
|
||||
* @brief 强度削弱候选项信息
|
||||
* 记录一个可以进行强度削弱的表达式信息
|
||||
*/
|
||||
struct StrengthReductionCandidate {
|
||||
enum OpType {
|
||||
MULTIPLY, // 乘法: iv * const
|
||||
DIVIDE, // 除法: iv / 2^n (转换为右移)
|
||||
DIVIDE_CONST, // 除法: iv / const (使用mulh指令优化)
|
||||
REMAINDER // 取模: iv % 2^n (转换为位与)
|
||||
};
|
||||
|
||||
enum DivisionStrategy {
|
||||
SIMPLE_SHIFT, // 简单右移(仅适用于无符号或非负数)
|
||||
SIGNED_CORRECTION, // 有符号除法修正: (x + (x >> 31) & mask) >> k
|
||||
MULH_OPTIMIZATION // 使用mulh指令优化任意常数除法
|
||||
};
|
||||
|
||||
Instruction* originalInst; // 原始指令 (如 i*4, i/8, i%16)
|
||||
Value* inductionVar; // 归纳变量 (如 i)
|
||||
OpType operationType; // 操作类型
|
||||
DivisionStrategy divStrategy; // 除法策略(仅用于除法)
|
||||
int multiplier; // 乘数/除数/模数 (如 4, 8, 16)
|
||||
int shiftAmount; // 位移量 (对于2的幂)
|
||||
int offset; // 偏移量 (如常数项)
|
||||
BasicBlock* containingBlock; // 所在基本块
|
||||
Loop* containingLoop; // 所在循环
|
||||
bool hasNegativeValues; // 归纳变量是否可能为负数
|
||||
|
||||
// 强度削弱后的新变量
|
||||
PhiInst* newPhi = nullptr; // 新的 phi 指令
|
||||
Value* newInductionVar = nullptr; // 新的归纳变量
|
||||
|
||||
StrengthReductionCandidate(Instruction* inst, Value* iv, OpType opType, int value, int off,
|
||||
BasicBlock* bb, Loop* loop)
|
||||
: originalInst(inst), inductionVar(iv), operationType(opType),
|
||||
divStrategy(SIMPLE_SHIFT), multiplier(value), offset(off),
|
||||
containingBlock(bb), containingLoop(loop), hasNegativeValues(false) {
|
||||
|
||||
// 计算位移量(用于除法和取模的强度削弱)
|
||||
if (opType == DIVIDE || opType == REMAINDER) {
|
||||
shiftAmount = 0;
|
||||
int temp = value;
|
||||
while (temp > 1) {
|
||||
temp >>= 1;
|
||||
shiftAmount++;
|
||||
}
|
||||
} else {
|
||||
shiftAmount = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 强度削弱上下文类
|
||||
* 封装强度削弱优化的核心逻辑和状态
|
||||
*/
|
||||
class StrengthReductionContext {
|
||||
public:
|
||||
StrengthReductionContext(IRBuilder* builder) : builder(builder) {}
|
||||
|
||||
/**
|
||||
* 运行强度削弱优化
|
||||
* @param F 目标函数
|
||||
* @param AM 分析管理器
|
||||
* @return 是否修改了IR
|
||||
*/
|
||||
bool run(Function* F, AnalysisManager& AM);
|
||||
|
||||
private:
|
||||
IRBuilder* builder;
|
||||
|
||||
// 分析结果缓存
|
||||
LoopAnalysisResult* loopAnalysis = nullptr;
|
||||
LoopCharacteristicsResult* loopCharacteristics = nullptr;
|
||||
DominatorTree* dominatorTree = nullptr;
|
||||
|
||||
// 候选项存储
|
||||
std::vector<std::unique_ptr<StrengthReductionCandidate>> candidates;
|
||||
std::unordered_map<Loop*, std::vector<StrengthReductionCandidate*>> loopToCandidates;
|
||||
|
||||
// ========== 核心分析和优化阶段 ==========
|
||||
|
||||
/**
|
||||
* 阶段1:识别强度削弱候选项
|
||||
* 扫描所有循环中的乘法指令,找出可以优化的模式
|
||||
*/
|
||||
void identifyStrengthReductionCandidates(Function* F);
|
||||
|
||||
/**
|
||||
* 阶段2:分析候选项的优化潜力
|
||||
* 评估每个候选项的收益,过滤掉不值得优化的情况
|
||||
*/
|
||||
void analyzeOptimizationPotential();
|
||||
|
||||
/**
|
||||
* 阶段3:执行强度削弱变换
|
||||
* 对选中的候选项执行实际的强度削弱优化
|
||||
*/
|
||||
bool performStrengthReduction();
|
||||
|
||||
// ========== 辅助分析函数 ==========
|
||||
|
||||
/**
|
||||
* 分析归纳变量是否可能取负值
|
||||
* @param ivInfo 归纳变量信息
|
||||
* @param loop 所属循环
|
||||
* @return 如果可能为负数返回true
|
||||
*/
|
||||
bool analyzeInductionVariableRange(const InductionVarInfo* ivInfo, Loop* loop) const;
|
||||
|
||||
/**
|
||||
* 计算用于除法优化的魔数和移位量
|
||||
* @param divisor 除数
|
||||
* @return {魔数, 移位量}
|
||||
*/
|
||||
std::pair<int, int> computeMulhMagicNumbers(int divisor) const;
|
||||
|
||||
/**
|
||||
* 生成除法替换代码
|
||||
* @param candidate 优化候选项
|
||||
* @param builder IR构建器
|
||||
* @return 替换值
|
||||
*/
|
||||
Value* generateDivisionReplacement(StrengthReductionCandidate* candidate, IRBuilder* builder) const;
|
||||
|
||||
/**
|
||||
* 生成任意常数除法替换代码
|
||||
* @param candidate 优化候选项
|
||||
* @param builder IR构建器
|
||||
* @return 替换值
|
||||
*/
|
||||
Value* generateConstantDivisionReplacement(StrengthReductionCandidate* candidate, IRBuilder* builder) const;
|
||||
|
||||
/**
|
||||
* 检查指令是否为强度削弱候选项
|
||||
* @param inst 要检查的指令
|
||||
* @param loop 所在循环
|
||||
* @return 如果是候选项返回候选项信息,否则返回nullptr
|
||||
*/
|
||||
std::unique_ptr<StrengthReductionCandidate>
|
||||
isStrengthReductionCandidate(Instruction* inst, Loop* loop);
|
||||
|
||||
/**
|
||||
* 检查值是否为循环的归纳变量
|
||||
* @param val 要检查的值
|
||||
* @param loop 循环
|
||||
* @param characteristics 循环特征信息
|
||||
* @return 如果是归纳变量返回归纳变量信息,否则返回nullptr
|
||||
*/
|
||||
const InductionVarInfo*
|
||||
getInductionVarInfo(Value* val, Loop* loop, const LoopCharacteristics* characteristics);
|
||||
|
||||
/**
|
||||
* 为候选项创建新的归纳变量
|
||||
* @param candidate 候选项
|
||||
* @return 是否成功创建
|
||||
*/
|
||||
bool createNewInductionVariable(StrengthReductionCandidate* candidate);
|
||||
|
||||
/**
|
||||
* 替换原始指令的所有使用
|
||||
* @param candidate 候选项
|
||||
* @return 是否成功替换
|
||||
*/
|
||||
bool replaceOriginalInstruction(StrengthReductionCandidate* candidate);
|
||||
|
||||
/**
|
||||
* 估算优化收益
|
||||
* 计算强度削弱后的性能提升
|
||||
* @param candidate 候选项
|
||||
* @return 估算的收益分数
|
||||
*/
|
||||
double estimateOptimizationBenefit(const StrengthReductionCandidate* candidate);
|
||||
|
||||
/**
|
||||
* 检查优化的合法性
|
||||
* @param candidate 候选项
|
||||
* @return 是否可以安全地进行优化
|
||||
*/
|
||||
bool isOptimizationLegal(const StrengthReductionCandidate* candidate);
|
||||
|
||||
/**
|
||||
* 打印调试信息
|
||||
*/
|
||||
void printDebugInfo();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 循环强度削弱优化遍
|
||||
* 将循环中的乘法运算转换为更高效的加法运算
|
||||
*/
|
||||
class LoopStrengthReduction : public OptimizationPass {
|
||||
public:
|
||||
// 唯一的 Pass ID
|
||||
static void *ID;
|
||||
|
||||
LoopStrengthReduction(IRBuilder* builder)
|
||||
: OptimizationPass("LoopStrengthReduction", Granularity::Function),
|
||||
builder(builder) {}
|
||||
|
||||
/**
|
||||
* 在函数上运行强度削弱优化
|
||||
* @param F 目标函数
|
||||
* @param AM 分析管理器
|
||||
* @return 是否修改了IR
|
||||
*/
|
||||
bool runOnFunction(Function* F, AnalysisManager& AM) override;
|
||||
|
||||
/**
|
||||
* 声明分析依赖和失效信息
|
||||
*/
|
||||
void getAnalysisUsage(std::set<void*>& analysisDependencies,
|
||||
std::set<void*>& analysisInvalidations) const override;
|
||||
|
||||
void* getPassID() const override { return &ID; }
|
||||
|
||||
private:
|
||||
IRBuilder* builder;
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
@ -3,6 +3,8 @@
|
||||
#include "IR.h"
|
||||
#include "Pass.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
@ -63,6 +65,8 @@ struct SSAPValue {
|
||||
class SCCPContext {
|
||||
private:
|
||||
IRBuilder *builder; // IR 构建器,用于插入指令和创建常量
|
||||
AliasAnalysisResult *aliasAnalysis; // 别名分析结果
|
||||
SideEffectAnalysisResult *sideEffectAnalysis; // 副作用分析结果
|
||||
|
||||
// 工作列表
|
||||
// 存储需要重新评估的指令
|
||||
@ -92,6 +96,14 @@ private:
|
||||
SSAPValue ComputeConstant(BinaryInst *binaryinst, SSAPValue lhsVal, SSAPValue rhsVal);
|
||||
// 辅助函数:对一元操作进行常量折叠
|
||||
SSAPValue ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVal);
|
||||
// 辅助函数:检查是否为已知的纯函数
|
||||
bool isKnownPureFunction(const std::string &funcName) const;
|
||||
// 辅助函数:计算纯函数的常量结果
|
||||
SSAPValue computePureFunctionResult(CallInst *call, const std::vector<SSAPValue> &argValues);
|
||||
// 辅助函数:查找存储到指定位置的常量值
|
||||
SSAPValue findStoredConstantValue(Value *ptr, BasicBlock *currentBB);
|
||||
// 辅助函数:动态检查数组访问是否为常量索引(考虑SCCP状态)
|
||||
bool hasRuntimeConstantAccess(Value *ptr);
|
||||
|
||||
// 主要优化阶段
|
||||
// 阶段1: 常量传播与折叠
|
||||
@ -117,7 +129,13 @@ private:
|
||||
void RemovePhiIncoming(BasicBlock *phiParentBB, BasicBlock *removedPred);
|
||||
|
||||
public:
|
||||
SCCPContext(IRBuilder *builder) : builder(builder) {}
|
||||
SCCPContext(IRBuilder *builder) : builder(builder), aliasAnalysis(nullptr), sideEffectAnalysis(nullptr) {}
|
||||
|
||||
// 设置别名分析结果
|
||||
void setAliasAnalysis(AliasAnalysisResult *aa) { aliasAnalysis = aa; }
|
||||
|
||||
// 设置副作用分析结果
|
||||
void setSideEffectAnalysis(SideEffectAnalysisResult *sea) { sideEffectAnalysis = sea; }
|
||||
|
||||
// 运行 SCCP 优化
|
||||
void run(Function *func, AnalysisManager &AM);
|
||||
|
||||
@ -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);
|
||||
// 获取结果并缓存
|
||||
|
||||
@ -6,11 +6,21 @@ add_library(midend_lib STATIC
|
||||
Pass/Pass.cpp
|
||||
Pass/Analysis/Dom.cpp
|
||||
Pass/Analysis/Liveness.cpp
|
||||
Pass/Analysis/Loop.cpp
|
||||
Pass/Analysis/LoopCharacteristics.cpp
|
||||
Pass/Analysis/LoopVectorization.cpp
|
||||
Pass/Analysis/AliasAnalysis.cpp
|
||||
Pass/Analysis/SideEffectAnalysis.cpp
|
||||
Pass/Analysis/CallGraphAnalysis.cpp
|
||||
Pass/Optimize/DCE.cpp
|
||||
Pass/Optimize/Mem2Reg.cpp
|
||||
Pass/Optimize/Reg2Mem.cpp
|
||||
Pass/Optimize/SysYIRCFGOpt.cpp
|
||||
Pass/Optimize/SCCP.cpp
|
||||
Pass/Optimize/LoopNormalization.cpp
|
||||
Pass/Optimize/LICM.cpp
|
||||
Pass/Optimize/LoopStrengthReduction.cpp
|
||||
Pass/Optimize/InductionVariableElimination.cpp
|
||||
Pass/Optimize/BuildCFG.cpp
|
||||
Pass/Optimize/LargeArrayToGlobal.cpp
|
||||
)
|
||||
|
||||
@ -762,7 +762,7 @@ void BinaryInst::print(std::ostream &os) const {
|
||||
printOperand(os, getLhs());
|
||||
os << ", ";
|
||||
printOperand(os, getRhs());
|
||||
os << "\n ";
|
||||
os << "\n ";
|
||||
printVarName(os, this) << " = zext i1 %" << tmpName << " to i32";
|
||||
} else if (kind == kFCmpEQ || kind == kFCmpNE || kind == kFCmpLT ||
|
||||
kind == kFCmpGT || kind == kFCmpLE || kind == kFCmpGE) {
|
||||
@ -777,9 +777,31 @@ void BinaryInst::print(std::ostream &os) const {
|
||||
printOperand(os, getLhs());
|
||||
os << ", ";
|
||||
printOperand(os, getRhs());
|
||||
os << "\n ";
|
||||
os << "\n ";
|
||||
printVarName(os, this) << " = zext i1 %" << tmpName << " to i32";
|
||||
} else {
|
||||
} else if(kind == kMulh){
|
||||
// 模拟高位乘法:先扩展为i64,乘法,右移32位,截断为i32
|
||||
static int mulhCount = 0;
|
||||
mulhCount++;
|
||||
std::string lhsName = getLhs()->getName();
|
||||
std::string rhsName = getRhs()->getName();
|
||||
std::string tmpLhs = "tmp_mulh_lhs_" + std::to_string(mulhCount) + "_" + lhsName;
|
||||
std::string tmpRhs = "tmp_mulh_rhs_" + std::to_string(mulhCount) + rhsName;
|
||||
std::string tmpMul = "tmp_mulh_mul_" + std::to_string(mulhCount) + getName();
|
||||
std::string tmpHigh = "tmp_mulh_high_" + std::to_string(mulhCount) + getName();
|
||||
// printVarName(os, this) << " = "; // 输出最终变量名
|
||||
|
||||
// os << "; mulh emulation\n ";
|
||||
os << "%" << tmpLhs << " = sext i32 ";
|
||||
printOperand(os, getLhs());
|
||||
os << " to i64\n ";
|
||||
os << "%" << tmpRhs << " = sext i32 ";
|
||||
printOperand(os, getRhs());
|
||||
os << " to i64\n ";
|
||||
os << "%" << tmpMul << " = mul i64 %" << tmpLhs << ", %" << tmpRhs << "\n ";
|
||||
os << "%" << tmpHigh << " = ashr i64 %" << tmpMul << ", 32\n ";
|
||||
printVarName(os, this) << " = trunc i64 %" << tmpHigh << " to i32";
|
||||
}else {
|
||||
// 算术和逻辑指令
|
||||
printVarName(os, this) << " = ";
|
||||
os << getKindString() << " " << *getType() << " ";
|
||||
|
||||
559
src/midend/Pass/Analysis/AliasAnalysis.cpp
Normal file
559
src/midend/Pass/Analysis/AliasAnalysis.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
#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::printStatics() 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();
|
||||
CurrentResult->printStatics();
|
||||
}
|
||||
|
||||
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)) {
|
||||
// 初始化为true,如果发现非常量索引则设为false
|
||||
location->hasConstantIndices = true;
|
||||
|
||||
// 收集所有索引
|
||||
for (unsigned i = 0; i < gepInst->getNumIndices(); ++i) {
|
||||
Value* index = gepInst->getIndex(i);
|
||||
location->indices.push_back(index);
|
||||
|
||||
// 检查是否为常量索引
|
||||
if (!isConstantValue(index)) {
|
||||
location->hasConstantIndices = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否包含循环变量
|
||||
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) {
|
||||
// 如果是同一个访问指针,那就是完全相同的内存位置
|
||||
if (loc1->accessPointer == loc2->accessPointer) {
|
||||
return AliasType::SELF_ALIAS;
|
||||
}
|
||||
|
||||
// 相同基指针但不同访问指针,需要比较索引
|
||||
return compareIndices(loc1, loc2);
|
||||
}
|
||||
|
||||
// 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::compareIndices(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 比较相同基指针下的不同索引访问
|
||||
|
||||
// 如果都有常量索引,可以精确比较
|
||||
if (loc1->hasConstantIndices && loc2->hasConstantIndices) {
|
||||
// 比较索引数量
|
||||
if (loc1->indices.size() != loc2->indices.size()) {
|
||||
return AliasType::NO_ALIAS;
|
||||
}
|
||||
|
||||
// 逐个比较索引值
|
||||
for (size_t i = 0; i < loc1->indices.size(); ++i) {
|
||||
Value* idx1 = loc1->indices[i];
|
||||
Value* idx2 = loc2->indices[i];
|
||||
|
||||
// 都是常量,比较值
|
||||
auto* const1 = dynamic_cast<ConstantInteger*>(idx1);
|
||||
auto* const2 = dynamic_cast<ConstantInteger*>(idx2);
|
||||
|
||||
if (const1 && const2) {
|
||||
int val1 = std::get<int>(const1->getVal());
|
||||
int val2 = std::get<int>(const2->getVal());
|
||||
|
||||
if (val1 != val2) {
|
||||
return AliasType::NO_ALIAS; // 不同常量索引,确定无别名
|
||||
}
|
||||
} else {
|
||||
// 不是常量,无法确定
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
}
|
||||
|
||||
// 所有索引都相同
|
||||
return AliasType::SELF_ALIAS;
|
||||
}
|
||||
|
||||
// 如果有非常量索引,保守估计
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareLocalArrays(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 不同局部数组不别名
|
||||
return AliasType::NO_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareParameters(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// SysY特化:可配置的数组参数别名策略
|
||||
//
|
||||
// SysY中数组参数的语法形式:
|
||||
// void func(int a[], int b[]) - 一维数组参数
|
||||
// void func(int a[][10], int b[]) - 多维数组参数
|
||||
//
|
||||
// 默认保守策略:不同数组参数可能别名(因为可能传入相同数组)
|
||||
// func(arr, arr); // 传入同一个数组给两个参数
|
||||
//
|
||||
// 激进策略:假设不同数组参数不会传入相同数组(适用于评测环境)
|
||||
// 在SysY评测中,这种情况很少出现
|
||||
|
||||
if (useAggressiveParameterAnalysis()) {
|
||||
// 激进策略:不同数组参数假设不别名
|
||||
return AliasType::NO_ALIAS;
|
||||
} else {
|
||||
// 保守策略:不同数组参数可能别名
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareWithGlobal(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 涉及全局数组的访问分析
|
||||
// 这里处理所有涉及全局数组的情况
|
||||
|
||||
// SysY特化:局部数组与全局数组不别名
|
||||
if ((loc1->isLocalArray && loc2->isGlobalArray) ||
|
||||
(loc1->isGlobalArray && loc2->isLocalArray)) {
|
||||
// 局部数组在栈上,全局数组在全局区,确定不别名
|
||||
return AliasType::NO_ALIAS;
|
||||
}
|
||||
|
||||
// SysY特化:数组参数与全局数组可能别名(保守处理)
|
||||
if ((loc1->isFunctionParameter && loc2->isGlobalArray) ||
|
||||
(loc1->isGlobalArray && loc2->isFunctionParameter)) {
|
||||
// 数组参数可能指向全局数组,需要保守处理
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
|
||||
// 其他涉及全局数组的情况,采用保守策略
|
||||
return AliasType::POSSIBLE_ALIAS;
|
||||
}
|
||||
|
||||
AliasType SysYAliasAnalysisPass::compareMixedTypes(MemoryLocation* loc1, MemoryLocation* loc2) {
|
||||
// 混合类型访问的别名分析
|
||||
// 处理不同内存类型之间的别名关系
|
||||
|
||||
// SysY特化:局部数组与数组参数通常不别名
|
||||
// 典型场景:
|
||||
// void func(int p[]) { // p 是数组参数
|
||||
// int local[10]; // local 是局部数组
|
||||
// p[0] = local[0]; // 混合类型访问
|
||||
// }
|
||||
// 或多维数组:
|
||||
// void func(int p[][10]) { // p 是多维数组参数
|
||||
// int local[10]; // local 是局部数组
|
||||
// p[i][0] = local[0]; // 混合类型访问
|
||||
// }
|
||||
// 局部数组与数组参数:在SysY中通常不别名
|
||||
if ((loc1->isLocalArray && loc2->isFunctionParameter) ||
|
||||
(loc1->isFunctionParameter && loc2->isLocalArray)) {
|
||||
// 因为局部数组是栈上分配,而数组参数是传入的外部数组
|
||||
return AliasType::NO_ALIAS;
|
||||
}
|
||||
|
||||
// 对于其他混合情况,保守估计
|
||||
return AliasType::UNKNOWN_ALIAS;
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::applySysYConstraints(Function* F) {
|
||||
// SysY语言特定的约束和优化
|
||||
// 1. SysY没有指针运算,简化了别名分析
|
||||
// 2. 数组传参时保持数组语义
|
||||
// 3. 没有动态内存分配,所有数组要么是局部的要么是参数/全局
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeParameterAnalysis(Function* F) {
|
||||
// 数组参数别名分析优化
|
||||
// 为SysY评测环境提供可配置的优化策略
|
||||
|
||||
if (!enableParameterOptimization()) {
|
||||
return; // 保持默认的保守策略
|
||||
}
|
||||
|
||||
// 可选的参数优化:假设不同数组参数不会传入相同数组
|
||||
// 典型的SysY函数调用:
|
||||
// int arr1[10], arr2[20];
|
||||
// func(arr1, arr2); // 传入不同数组
|
||||
// 而不是:
|
||||
// func(arr1, arr1); // 传入相同数组给两个参数
|
||||
// 这在SysY评测中通常是安全的假设
|
||||
auto& locationMap = CurrentResult->LocationMap;
|
||||
|
||||
for (auto it1 = locationMap.begin(); it1 != locationMap.end(); ++it1) {
|
||||
for (auto it2 = std::next(it1); it2 != locationMap.end(); ++it2) {
|
||||
MemoryLocation* loc1 = it1->second.get();
|
||||
MemoryLocation* loc2 = it2->second.get();
|
||||
|
||||
// 如果两个都是数组参数且基指针不同,设为NO_ALIAS
|
||||
if (loc1->isFunctionParameter && loc2->isFunctionParameter &&
|
||||
loc1->basePointer != loc2->basePointer) {
|
||||
CurrentResult->addAliasRelation(it1->first, it2->first, AliasType::NO_ALIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeArrayAccessAnalysis(Function* F) {
|
||||
// 数组访问别名分析优化
|
||||
// 基于SysY语言的特点进行简单优化
|
||||
|
||||
// 优化1:同一数组的不同常量索引访问确定无别名
|
||||
optimizeConstantIndexAccesses();
|
||||
|
||||
// 优化2:识别简单的顺序访问模式
|
||||
optimizeSequentialAccesses();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeConstantIndexAccesses() {
|
||||
// 优化常量索引访问的别名关系
|
||||
// 对于相同基指针的访问,如果索引都是常量且不同,则确定无别名
|
||||
|
||||
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();
|
||||
|
||||
// 相同基指针且都有常量索引
|
||||
if (loc1->basePointer == loc2->basePointer &&
|
||||
loc1->hasConstantIndices && loc2->hasConstantIndices) {
|
||||
|
||||
// 比较常量偏移
|
||||
if (loc1->constantOffset != loc2->constantOffset) {
|
||||
// 不同的常量偏移,确定无别名
|
||||
CurrentResult->addAliasRelation(ptr1, ptr2, AliasType::NO_ALIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SysYAliasAnalysisPass::optimizeSequentialAccesses() {
|
||||
// 识别和优化顺序访问模式
|
||||
// 这是一个简化的实现,主要用于识别数组的顺序遍历
|
||||
|
||||
// 在SysY中,大多数数组访问都是通过循环进行的
|
||||
// 对于非常量索引的访问,我们采用保守策略,不进行过多优化
|
||||
// 这样可以保持分析的简单性和正确性
|
||||
|
||||
// 未来如果需要更精确的分析,可以在这里添加更复杂的逻辑
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
417
src/midend/Pass/Analysis/CallGraphAnalysis.cpp
Normal file
417
src/midend/Pass/Analysis/CallGraphAnalysis.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
#include "CallGraphAnalysis.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
#include <unordered_set>
|
||||
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 静态成员初始化
|
||||
void* CallGraphAnalysisPass::ID = (void*)&CallGraphAnalysisPass::ID;
|
||||
|
||||
// ========== CallGraphAnalysisResult 实现 ==========
|
||||
|
||||
CallGraphAnalysisResult::Statistics CallGraphAnalysisResult::getStatistics() const {
|
||||
Statistics stats = {};
|
||||
stats.totalFunctions = nodes.size();
|
||||
|
||||
size_t totalCallEdges = 0;
|
||||
size_t recursiveFunctions = 0;
|
||||
size_t selfRecursiveFunctions = 0;
|
||||
size_t totalCallers = 0;
|
||||
size_t totalCallees = 0;
|
||||
|
||||
for (const auto& pair : nodes) {
|
||||
const auto& node = pair.second;
|
||||
totalCallEdges += node->callees.size();
|
||||
totalCallers += node->callers.size();
|
||||
totalCallees += node->callees.size();
|
||||
|
||||
if (node->isRecursive) recursiveFunctions++;
|
||||
if (node->isSelfRecursive) selfRecursiveFunctions++;
|
||||
}
|
||||
|
||||
stats.totalCallEdges = totalCallEdges;
|
||||
stats.recursiveFunctions = recursiveFunctions;
|
||||
stats.selfRecursiveFunctions = selfRecursiveFunctions;
|
||||
stats.stronglyConnectedComponents = sccs.size();
|
||||
|
||||
// 计算最大SCC大小
|
||||
size_t maxSCCSize = 0;
|
||||
for (const auto& scc : sccs) {
|
||||
maxSCCSize = std::max(maxSCCSize, scc.size());
|
||||
}
|
||||
stats.maxSCCSize = maxSCCSize;
|
||||
|
||||
// 计算平均值
|
||||
if (stats.totalFunctions > 0) {
|
||||
stats.avgCallersPerFunction = static_cast<double>(totalCallers) / stats.totalFunctions;
|
||||
stats.avgCalleesPerFunction = static_cast<double>(totalCallees) / stats.totalFunctions;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::print() const {
|
||||
std::cout << "---- Call Graph Analysis Results for Module ----\n";
|
||||
|
||||
// 打印基本统计信息
|
||||
auto stats = getStatistics();
|
||||
std::cout << " Statistics:\n";
|
||||
std::cout << " Total Functions: " << stats.totalFunctions << "\n";
|
||||
std::cout << " Total Call Edges: " << stats.totalCallEdges << "\n";
|
||||
std::cout << " Recursive Functions: " << stats.recursiveFunctions << "\n";
|
||||
std::cout << " Self-Recursive Functions: " << stats.selfRecursiveFunctions << "\n";
|
||||
std::cout << " Strongly Connected Components: " << stats.stronglyConnectedComponents << "\n";
|
||||
std::cout << " Max SCC Size: " << stats.maxSCCSize << "\n";
|
||||
std::cout << " Avg Callers per Function: " << stats.avgCallersPerFunction << "\n";
|
||||
std::cout << " Avg Callees per Function: " << stats.avgCalleesPerFunction << "\n";
|
||||
|
||||
// 打印拓扑排序结果
|
||||
std::cout << " Topological Order (" << topologicalOrder.size() << "):\n";
|
||||
for (size_t i = 0; i < topologicalOrder.size(); ++i) {
|
||||
std::cout << " " << i << ": " << topologicalOrder[i]->getName() << "\n";
|
||||
}
|
||||
|
||||
// 打印强连通分量
|
||||
if (!sccs.empty()) {
|
||||
std::cout << " Strongly Connected Components:\n";
|
||||
for (size_t i = 0; i < sccs.size(); ++i) {
|
||||
std::cout << " SCC " << i << " (size " << sccs[i].size() << "): ";
|
||||
for (size_t j = 0; j < sccs[i].size(); ++j) {
|
||||
if (j > 0) std::cout << ", ";
|
||||
std::cout << sccs[i][j]->getName();
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 打印每个函数的详细信息
|
||||
std::cout << " Function Details:\n";
|
||||
for (const auto& pair : nodes) {
|
||||
const auto& node = pair.second;
|
||||
std::cout << " Function: " << node->function->getName();
|
||||
|
||||
if (node->isRecursive) {
|
||||
std::cout << " (Recursive";
|
||||
if (node->isSelfRecursive) std::cout << ", Self";
|
||||
if (node->recursiveDepth >= 0) std::cout << ", Depth=" << node->recursiveDepth;
|
||||
std::cout << ")";
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
if (!node->callers.empty()) {
|
||||
std::cout << " Callers (" << node->callers.size() << "): ";
|
||||
bool first = true;
|
||||
for (Function* caller : node->callers) {
|
||||
if (!first) std::cout << ", ";
|
||||
std::cout << caller->getName();
|
||||
first = false;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
if (!node->callees.empty()) {
|
||||
std::cout << " Callees (" << node->callees.size() << "): ";
|
||||
bool first = true;
|
||||
for (Function* callee : node->callees) {
|
||||
if (!first) std::cout << ", ";
|
||||
std::cout << callee->getName();
|
||||
first = false;
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "--------------------------------------------------\n";
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::addNode(Function* F) {
|
||||
if (nodes.find(F) == nodes.end()) {
|
||||
nodes[F] = std::make_unique<CallGraphNode>(F);
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::addCallEdge(Function* caller, Function* callee) {
|
||||
// 确保两个函数都有对应的节点
|
||||
addNode(caller);
|
||||
addNode(callee);
|
||||
|
||||
// 添加调用边
|
||||
nodes[caller]->callees.insert(callee);
|
||||
nodes[callee]->callers.insert(caller);
|
||||
|
||||
// 更新统计信息
|
||||
nodes[caller]->totalCallees = nodes[caller]->callees.size();
|
||||
nodes[callee]->totalCallers = nodes[callee]->callers.size();
|
||||
|
||||
// 检查自递归
|
||||
if (caller == callee) {
|
||||
nodes[caller]->isSelfRecursive = true;
|
||||
nodes[caller]->isRecursive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::computeTopologicalOrder() {
|
||||
topologicalOrder.clear();
|
||||
std::unordered_set<Function*> visited;
|
||||
|
||||
// 对每个未访问的函数进行DFS
|
||||
for (const auto& pair : nodes) {
|
||||
Function* F = pair.first;
|
||||
if (visited.find(F) == visited.end()) {
|
||||
dfsTopological(F, visited, topologicalOrder);
|
||||
}
|
||||
}
|
||||
|
||||
// 反转结果(因为我们在后序遍历中添加)
|
||||
std::reverse(topologicalOrder.begin(), topologicalOrder.end());
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::dfsTopological(Function* F, std::unordered_set<Function*>& visited,
|
||||
std::vector<Function*>& result) {
|
||||
visited.insert(F);
|
||||
|
||||
auto node = getNode(F);
|
||||
if (node) {
|
||||
// 先访问所有被调用的函数
|
||||
for (Function* callee : node->callees) {
|
||||
if (visited.find(callee) == visited.end()) {
|
||||
dfsTopological(callee, visited, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 后序遍历:访问完所有子节点后添加当前节点
|
||||
result.push_back(F);
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::computeStronglyConnectedComponents() {
|
||||
tarjanSCC();
|
||||
|
||||
// 为每个函数设置其所属的SCC
|
||||
functionToSCC.clear();
|
||||
for (size_t i = 0; i < sccs.size(); ++i) {
|
||||
for (Function* F : sccs[i]) {
|
||||
functionToSCC[F] = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::tarjanSCC() {
|
||||
sccs.clear();
|
||||
|
||||
std::vector<int> indices(nodes.size(), -1);
|
||||
std::vector<int> lowlinks(nodes.size(), -1);
|
||||
std::vector<Function*> stack;
|
||||
std::unordered_set<Function*> onStack;
|
||||
int index = 0;
|
||||
|
||||
// 为函数分配索引
|
||||
std::map<Function*, int> functionIndex;
|
||||
int idx = 0;
|
||||
for (const auto& pair : nodes) {
|
||||
functionIndex[pair.first] = idx++;
|
||||
}
|
||||
|
||||
// 对每个未访问的函数运行Tarjan算法
|
||||
for (const auto& pair : nodes) {
|
||||
Function* F = pair.first;
|
||||
int fIdx = functionIndex[F];
|
||||
if (indices[fIdx] == -1) {
|
||||
tarjanDFS(F, index, indices, lowlinks, stack, onStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::tarjanDFS(Function* F, int& index, std::vector<int>& indices,
|
||||
std::vector<int>& lowlinks, std::vector<Function*>& stack,
|
||||
std::unordered_set<Function*>& onStack) {
|
||||
// 这里需要函数到索引的映射,简化实现
|
||||
// 在实际实现中应该维护一个全局的函数索引映射
|
||||
static std::map<Function*, int> functionIndex;
|
||||
static int nextIndex = 0;
|
||||
|
||||
if (functionIndex.find(F) == functionIndex.end()) {
|
||||
functionIndex[F] = nextIndex++;
|
||||
}
|
||||
|
||||
int fIdx = functionIndex[F];
|
||||
|
||||
// 确保向量足够大
|
||||
if (fIdx >= static_cast<int>(indices.size())) {
|
||||
indices.resize(fIdx + 1, -1);
|
||||
lowlinks.resize(fIdx + 1, -1);
|
||||
}
|
||||
|
||||
indices[fIdx] = index;
|
||||
lowlinks[fIdx] = index;
|
||||
index++;
|
||||
|
||||
stack.push_back(F);
|
||||
onStack.insert(F);
|
||||
|
||||
auto node = getNode(F);
|
||||
if (node) {
|
||||
for (Function* callee : node->callees) {
|
||||
int calleeIdx = functionIndex[callee];
|
||||
|
||||
// 确保向量足够大
|
||||
if (calleeIdx >= static_cast<int>(indices.size())) {
|
||||
indices.resize(calleeIdx + 1, -1);
|
||||
lowlinks.resize(calleeIdx + 1, -1);
|
||||
}
|
||||
|
||||
if (indices[calleeIdx] == -1) {
|
||||
// 递归访问
|
||||
tarjanDFS(callee, index, indices, lowlinks, stack, onStack);
|
||||
lowlinks[fIdx] = std::min(lowlinks[fIdx], lowlinks[calleeIdx]);
|
||||
} else if (onStack.find(callee) != onStack.end()) {
|
||||
// 后向边
|
||||
lowlinks[fIdx] = std::min(lowlinks[fIdx], indices[calleeIdx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果F是SCC的根
|
||||
if (lowlinks[fIdx] == indices[fIdx]) {
|
||||
std::vector<Function*> scc;
|
||||
Function* w;
|
||||
do {
|
||||
w = stack.back();
|
||||
stack.pop_back();
|
||||
onStack.erase(w);
|
||||
scc.push_back(w);
|
||||
} while (w != F);
|
||||
|
||||
sccs.push_back(std::move(scc));
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisResult::analyzeRecursion() {
|
||||
// 基于SCC分析递归
|
||||
for (const auto& scc : sccs) {
|
||||
if (scc.size() > 1) {
|
||||
// 多函数的SCC,标记为相互递归
|
||||
for (Function* F : scc) {
|
||||
auto* node = getMutableNode(F);
|
||||
if (node) {
|
||||
node->isRecursive = true;
|
||||
node->recursiveDepth = -1; // 相互递归,深度未定义
|
||||
}
|
||||
}
|
||||
} else if (scc.size() == 1) {
|
||||
// 单函数SCC,检查是否自递归
|
||||
Function* F = scc[0];
|
||||
auto* node = getMutableNode(F);
|
||||
if (node && node->callees.count(F) > 0) {
|
||||
node->isSelfRecursive = true;
|
||||
node->isRecursive = true;
|
||||
node->recursiveDepth = -1; // 简化:不计算递归深度
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== CallGraphAnalysisPass 实现 ==========
|
||||
|
||||
bool CallGraphAnalysisPass::runOnModule(Module* M, AnalysisManager& AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running Call Graph Analysis on module\n";
|
||||
}
|
||||
|
||||
// 创建分析结果
|
||||
CurrentResult = std::make_unique<CallGraphAnalysisResult>(M);
|
||||
|
||||
// 执行主要分析步骤
|
||||
buildCallGraph(M);
|
||||
CurrentResult->computeTopologicalOrder();
|
||||
CurrentResult->computeStronglyConnectedComponents();
|
||||
CurrentResult->analyzeRecursion();
|
||||
|
||||
if (DEBUG) {
|
||||
CurrentResult->print();
|
||||
}
|
||||
|
||||
return false; // 分析遍不修改IR
|
||||
}
|
||||
|
||||
void CallGraphAnalysisPass::buildCallGraph(Module* M) {
|
||||
// 1. 为所有函数创建节点(包括声明但未定义的函数)
|
||||
for (auto& pair : M->getFunctions()) {
|
||||
Function* F = pair.second.get();
|
||||
if (!isLibraryFunction(F) && !isIntrinsicFunction(F)) {
|
||||
CurrentResult->addNode(F);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 扫描所有函数的调用关系
|
||||
for (auto& pair : M->getFunctions()) {
|
||||
Function* F = pair.second.get();
|
||||
if (!isLibraryFunction(F) && !isIntrinsicFunction(F)) {
|
||||
scanFunctionCalls(F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisPass::scanFunctionCalls(Function* F) {
|
||||
// 遍历函数中的所有基本块和指令
|
||||
for (auto& BB : F->getBasicBlocks_NoRange()) {
|
||||
for (auto& I : BB->getInstructions()) {
|
||||
if (CallInst* call = dynamic_cast<CallInst*>(I.get())) {
|
||||
processCallInstruction(call, F);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraphAnalysisPass::processCallInstruction(CallInst* call, Function* caller) {
|
||||
Function* callee = call->getCallee();
|
||||
|
||||
if (!callee) {
|
||||
// 间接调用,无法静态确定目标函数
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLibraryFunction(callee) || isIntrinsicFunction(callee)) {
|
||||
// 跳过标准库函数和内置函数
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加调用边
|
||||
CurrentResult->addCallEdge(caller, callee);
|
||||
|
||||
// 更新调用点统计
|
||||
auto* node = CurrentResult->getMutableNode(caller);
|
||||
if (node) {
|
||||
node->callSiteCount++;
|
||||
}
|
||||
}
|
||||
|
||||
bool CallGraphAnalysisPass::isLibraryFunction(Function* F) const {
|
||||
std::string name = F->getName();
|
||||
|
||||
// SysY标准库函数
|
||||
return name == "getint" || name == "getch" || name == "getfloat" ||
|
||||
name == "getarray" || name == "getfarray" ||
|
||||
name == "putint" || name == "putch" || name == "putfloat" ||
|
||||
name == "putarray" || name == "putfarray" ||
|
||||
name == "_sysy_starttime" || name == "_sysy_stoptime";
|
||||
}
|
||||
|
||||
bool CallGraphAnalysisPass::isIntrinsicFunction(Function* F) const {
|
||||
std::string name = F->getName();
|
||||
|
||||
// 编译器内置函数(后续可以增加某些内置函数)
|
||||
return name.substr(0, 5) == "llvm." || name.substr(0, 5) == "sysy.";
|
||||
}
|
||||
|
||||
void CallGraphAnalysisPass::printStatistics() const {
|
||||
if (CurrentResult) {
|
||||
CurrentResult->print();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
415
src/midend/Pass/Analysis/Loop.cpp
Normal file
415
src/midend/Pass/Analysis/Loop.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
#include "Dom.h" // 确保包含 DominatorTreeAnalysisPass 的定义
|
||||
#include "Loop.h" //
|
||||
#include "AliasAnalysis.h" // 添加别名分析依赖
|
||||
#include "SideEffectAnalysis.h" // 添加副作用分析依赖
|
||||
#include <iostream>
|
||||
#include <queue> // 用于 BFS 遍历设置循环层级
|
||||
|
||||
// 调试模式开关
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 定义 Pass 的唯一 ID
|
||||
void *LoopAnalysisPass::ID = (void *)&LoopAnalysisPass::ID;
|
||||
|
||||
// 定义 Loop 类的静态变量
|
||||
int Loop::NextLoopID = 0;
|
||||
// **实现 LoopAnalysisResult::print() 方法**
|
||||
|
||||
|
||||
void LoopAnalysisResult::printBBSet(const std::string &prefix, const std::set<BasicBlock *> &s) const{
|
||||
if (!DEBUG) return;
|
||||
std::cout << prefix << "{";
|
||||
bool first = true;
|
||||
for (const auto &bb : s) {
|
||||
if (!first) std::cout << ", ";
|
||||
std::cout << bb->getName();
|
||||
first = false;
|
||||
}
|
||||
std::cout << "}";
|
||||
}
|
||||
|
||||
// **辅助函数:打印 Loop 指针向量**
|
||||
void LoopAnalysisResult::printLoopVector(const std::string &prefix, const std::vector<Loop *> &loops) const {
|
||||
if (!DEBUG) return;
|
||||
std::cout << prefix << "[";
|
||||
bool first = true;
|
||||
for (const auto &loop : loops) {
|
||||
if (!first) std::cout << ", ";
|
||||
std::cout << loop->getName(); // 假设 Loop::getName() 存在
|
||||
first = false;
|
||||
}
|
||||
std::cout << "]";
|
||||
}
|
||||
|
||||
void LoopAnalysisResult::print() const {
|
||||
if (!DEBUG) return; // 只有在 DEBUG 模式下才打印
|
||||
|
||||
std::cout << "\n--- Loop Analysis Results for Function: " << AssociatedFunction->getName() << " ---" << std::endl;
|
||||
|
||||
if (AllLoops.empty()) {
|
||||
std::cout << " No loops found." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Total Loops Found: " << AllLoops.size() << std::endl;
|
||||
|
||||
// 1. 按层级分组循环
|
||||
std::map<int, std::vector<Loop*>> loopsByLevel;
|
||||
int maxLevel = 0;
|
||||
for (const auto& loop_ptr : AllLoops) {
|
||||
if (loop_ptr->getLoopLevel() != -1) { // 确保层级已计算
|
||||
loopsByLevel[loop_ptr->getLoopLevel()].push_back(loop_ptr.get());
|
||||
if (loop_ptr->getLoopLevel() > maxLevel) {
|
||||
maxLevel = loop_ptr->getLoopLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 打印循环层次结构
|
||||
std::cout << "\n--- Loop Hierarchy ---" << std::endl;
|
||||
for (int level = 0; level <= maxLevel; ++level) {
|
||||
if (loopsByLevel.count(level)) {
|
||||
std::cout << "Level " << level << " Loops:" << std::endl;
|
||||
for (Loop* loop : loopsByLevel[level]) {
|
||||
std::string indent(level * 2, ' '); // 根据层级缩进
|
||||
std::cout << indent << "- Loop Header: " << loop->getName() << std::endl;
|
||||
std::cout << indent << " Blocks: ";
|
||||
printBBSet("", loop->getBlocks());
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << indent << " Exit Blocks: ";
|
||||
printBBSet("", loop->getExitBlocks());
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << indent << " Pre-Header: " << (loop->getPreHeader() ? loop->getPreHeader()->getName() : "None") << std::endl;
|
||||
std::cout << indent << " Parent Loop: " << (loop->getParentLoop() ? loop->getParentLoop()->getName() : "None (Outermost)") << std::endl;
|
||||
std::cout << indent << " Nested Loops: ";
|
||||
printLoopVector("", loop->getNestedLoops());
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 打印最外层/最内层循环摘要
|
||||
std::cout << "\n--- Loop Summary ---" << std::endl;
|
||||
std::cout << "Outermost Loops: ";
|
||||
printLoopVector("", getOutermostLoops());
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Innermost Loops: ";
|
||||
printLoopVector("", getInnermostLoops());
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "-----------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
bool LoopAnalysisPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (F->getBasicBlocks().empty()) {
|
||||
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
|
||||
return false; // 空函数,没有循环
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << "Running LoopAnalysisPass on function: " << F->getName() << std::endl;
|
||||
|
||||
// 获取支配树分析结果
|
||||
// 这是循环分析的关键依赖
|
||||
DominatorTree *DT = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
|
||||
if (!DT) {
|
||||
// 无法获取支配树,无法进行循环分析
|
||||
std::cerr << "Error: DominatorTreeAnalysisResult not available for function " << F->getName() << std::endl;
|
||||
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取别名分析结果 - 用于循环内存访问分析
|
||||
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
|
||||
if (DEBUG && aliasAnalysis) {
|
||||
std::cout << "Loop Analysis: Using alias analysis results for enhanced memory pattern detection" << std::endl;
|
||||
}
|
||||
|
||||
// 获取副作用分析结果 - 用于循环纯度分析
|
||||
SideEffectAnalysisResult *sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||||
if (DEBUG && sideEffectAnalysis) {
|
||||
std::cout << "Loop Analysis: Using side effect analysis results for loop purity detection" << std::endl;
|
||||
}
|
||||
|
||||
CurrentResult = std::make_unique<LoopAnalysisResult>(F);
|
||||
bool changed = false; // 循环分析本身不修改IR,所以通常返回false
|
||||
|
||||
// 步骤 1: 识别回边和对应的自然循环
|
||||
// 回边 (N -> D) 定义:D 支配 N
|
||||
std::vector<std::pair<BasicBlock *, BasicBlock *>> backEdges;
|
||||
for (auto &BB : F->getBasicBlocks()) {
|
||||
auto Block = BB.get();
|
||||
for (BasicBlock *Succ : Block->getSuccessors()) {
|
||||
if (DT->getDominators(Block) && DT->getDominators(Block)->count(Succ)) {
|
||||
// Succ 支配 Block,所以 (Block -> Succ) 是一条回边
|
||||
backEdges.push_back({Block, Succ});
|
||||
if (DEBUG)
|
||||
std::cout << "Found back edge: " << Block->getName() << " -> " << Succ->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << "Total back edges found: " << backEdges.size() << std::endl;
|
||||
|
||||
// 步骤 2: 为每条回边构建自然循环
|
||||
std::map<BasicBlock*, std::unique_ptr<Loop>> loopMap; // 按循环头分组
|
||||
|
||||
for (auto &edge : backEdges) {
|
||||
BasicBlock *N = edge.first; // 回边的尾部
|
||||
BasicBlock *D = edge.second; // 回边的头部 (循环头)
|
||||
|
||||
// 检查是否已经为此循环头创建了循环
|
||||
if (loopMap.find(D) == loopMap.end()) {
|
||||
// 创建新的 Loop 对象
|
||||
loopMap[D] = std::make_unique<Loop>(D);
|
||||
}
|
||||
|
||||
Loop* currentLoop = loopMap[D].get();
|
||||
|
||||
// 收集此回边对应的循环体块:从 N 逆向遍历到 D
|
||||
std::set<BasicBlock *> loopBlocks; // 临时存储循环块
|
||||
std::queue<BasicBlock *> q;
|
||||
|
||||
// 循环头总是循环体的一部分
|
||||
loopBlocks.insert(D);
|
||||
|
||||
// 如果回边的尾部不是循环头本身,则将其加入队列进行遍历
|
||||
if (N != D) {
|
||||
q.push(N);
|
||||
loopBlocks.insert(N);
|
||||
}
|
||||
|
||||
while (!q.empty()) {
|
||||
BasicBlock *current = q.front();
|
||||
q.pop();
|
||||
|
||||
for (BasicBlock *pred : current->getPredecessors()) {
|
||||
// 如果前驱还没有被访问过,则将其加入循环体并继续遍历
|
||||
if (loopBlocks.find(pred) == loopBlocks.end()) {
|
||||
loopBlocks.insert(pred);
|
||||
q.push(pred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将收集到的块添加到 Loop 对象中(合并所有回边的结果)
|
||||
for (BasicBlock *loopBB : loopBlocks) {
|
||||
currentLoop->addBlock(loopBB);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理每个合并后的循环
|
||||
for (auto &[header, currentLoop] : loopMap) {
|
||||
const auto &loopBlocks = currentLoop->getBlocks();
|
||||
|
||||
// 步骤 3: 识别循环出口块 (Exit Blocks)
|
||||
for (BasicBlock *loopBB : loopBlocks) {
|
||||
for (BasicBlock *succ : loopBB->getSuccessors()) {
|
||||
if (loopBlocks.find(succ) == loopBlocks.end()) {
|
||||
// 如果后继不在循环体内,则 loopBB 是一个出口块
|
||||
currentLoop->addExitBlock(loopBB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 步骤 4: 识别循环前置块 (Pre-Header)
|
||||
BasicBlock *candidatePreHeader = nullptr;
|
||||
int externalPredecessorCount = 0;
|
||||
for (BasicBlock *predOfHeader : header->getPredecessors()) {
|
||||
// 使用 currentLoop->contains() 来检查前驱是否在循环体内
|
||||
if (!currentLoop->contains(predOfHeader)) {
|
||||
// 如果前驱不在循环体内,则是一个外部前驱
|
||||
externalPredecessorCount++;
|
||||
candidatePreHeader = predOfHeader;
|
||||
}
|
||||
}
|
||||
|
||||
if (externalPredecessorCount == 1) {
|
||||
currentLoop->setPreHeader(candidatePreHeader);
|
||||
}
|
||||
CurrentResult->addLoop(std::move(currentLoop));
|
||||
}
|
||||
|
||||
// 步骤 5: 处理嵌套循环 (确定父子关系和层级)
|
||||
const auto &allLoops = CurrentResult->getAllLoops();
|
||||
|
||||
// 1. 首先,清除所有循环已设置的父子关系和嵌套子循环列表,确保重新计算
|
||||
for (const auto &loop_ptr : allLoops) {
|
||||
loop_ptr->setParentLoop(nullptr); // 清除父指针
|
||||
loop_ptr->clearNestedLoops(); // 清除子循环列表
|
||||
loop_ptr->setLoopLevel(-1); // 重置循环层级
|
||||
}
|
||||
|
||||
// 2. 遍历所有循环,为每个循环找到其直接父循环并建立关系
|
||||
for (const auto &innerLoop_ptr : allLoops) {
|
||||
Loop *innerLoop = innerLoop_ptr.get();
|
||||
Loop *immediateParent = nullptr; // 用于存储当前 innerLoop 的最近父循环
|
||||
|
||||
for (const auto &outerLoop_ptr : allLoops) {
|
||||
Loop *outerLoop = outerLoop_ptr.get();
|
||||
|
||||
// 一个循环不能是它自己的父循环
|
||||
if (outerLoop == innerLoop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查 outerLoop 是否包含 innerLoop 的所有条件:
|
||||
// Condition 1: outerLoop 的头支配 innerLoop 的头
|
||||
if (!(DT->getDominators(innerLoop->getHeader()) &&
|
||||
DT->getDominators(innerLoop->getHeader())->count(outerLoop->getHeader()))) {
|
||||
continue; // outerLoop 不支配 innerLoop 的头,因此不是一个外层循环
|
||||
}
|
||||
|
||||
// Condition 2: innerLoop 的所有基本块都在 outerLoop 的基本块集合中
|
||||
bool allInnerBlocksInOuter = true;
|
||||
for (BasicBlock *innerBB : innerLoop->getBlocks()) {
|
||||
if (!outerLoop->contains(innerBB)) { //
|
||||
allInnerBlocksInOuter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allInnerBlocksInOuter) {
|
||||
continue; // outerLoop 不包含 innerLoop 的所有块
|
||||
}
|
||||
|
||||
// 到此为止,outerLoop 已经被确认为 innerLoop 的一个“候选父循环”(即它包含了 innerLoop)
|
||||
|
||||
if (immediateParent == nullptr) {
|
||||
// 这是找到的第一个候选父循环
|
||||
immediateParent = outerLoop;
|
||||
} else {
|
||||
// 已经有了一个 immediateParent,需要判断哪个是更“紧密”的父循环
|
||||
// 更紧密的父循环是那个包含另一个候选父循环的。
|
||||
// 如果当前的 immediateParent 包含了 outerLoop 的头,那么 outerLoop 是更深的循环(更接近 innerLoop)
|
||||
if (immediateParent->contains(outerLoop->getHeader())) { //
|
||||
immediateParent = outerLoop; // outerLoop 是更紧密的父循环
|
||||
}
|
||||
// 否则(outerLoop 包含了 immediateParent 的头),说明 immediateParent 更紧密,保持不变
|
||||
// 或者它们互不包含(不应该发生,因为它们都包含了 innerLoop),也保持 immediateParent
|
||||
}
|
||||
}
|
||||
|
||||
// 设置 innerLoop 的直接父循环,并添加到父循环的嵌套列表中
|
||||
if (immediateParent) {
|
||||
innerLoop->setParentLoop(immediateParent);
|
||||
immediateParent->addNestedLoop(innerLoop);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 计算循环层级 (Level)
|
||||
std::queue<Loop *> q_level;
|
||||
|
||||
// 查找所有最外层循环(没有父循环的),设置其层级为0,并加入队列
|
||||
for (const auto &loop_ptr : allLoops) {
|
||||
if (loop_ptr->isOutermost()) {
|
||||
loop_ptr->setLoopLevel(0);
|
||||
q_level.push(loop_ptr.get());
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 BFS 遍历循环树,计算所有嵌套循环的层级
|
||||
while (!q_level.empty()) {
|
||||
Loop *current = q_level.front();
|
||||
q_level.pop();
|
||||
|
||||
for (Loop *nestedLoop : current->getNestedLoops()) {
|
||||
nestedLoop->setLoopLevel(current->getLoopLevel() + 1);
|
||||
q_level.push(nestedLoop);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ========== Loop 类的新增方法实现 ==========
|
||||
|
||||
bool Loop::mayHaveSideEffects(SideEffectAnalysisResult* sideEffectAnalysis) const {
|
||||
if (!sideEffectAnalysis) return true; // 保守假设
|
||||
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (sideEffectAnalysis->hasSideEffect(inst.get())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Loop::accessesGlobalMemory(AliasAnalysisResult* aliasAnalysis) const {
|
||||
if (!aliasAnalysis) return true; // 保守假设
|
||||
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
if (!aliasAnalysis->isLocalArray(loadInst->getPointer())) {
|
||||
return true;
|
||||
}
|
||||
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
if (!aliasAnalysis->isLocalArray(storeInst->getPointer())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Loop::hasMemoryAliasConflicts(AliasAnalysisResult* aliasAnalysis) const {
|
||||
if (!aliasAnalysis) return true; // 保守假设
|
||||
|
||||
std::vector<Value*> memoryAccesses;
|
||||
|
||||
// 收集所有内存访问
|
||||
for (BasicBlock* bb : LoopBlocks) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
memoryAccesses.push_back(loadInst->getPointer());
|
||||
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
memoryAccesses.push_back(storeInst->getPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查两两之间是否有别名
|
||||
for (size_t i = 0; i < memoryAccesses.size(); ++i) {
|
||||
for (size_t j = i + 1; j < memoryAccesses.size(); ++j) {
|
||||
auto aliasType = aliasAnalysis->queryAlias(memoryAccesses[i], memoryAccesses[j]);
|
||||
if (aliasType == AliasType::SELF_ALIAS || aliasType == AliasType::POSSIBLE_ALIAS) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
813
src/midend/Pass/Analysis/LoopCharacteristics.cpp
Normal file
813
src/midend/Pass/Analysis/LoopCharacteristics.cpp
Normal file
@ -0,0 +1,813 @@
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Dom.h"
|
||||
#include "Loop.h"
|
||||
#include "Liveness.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.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;
|
||||
|
||||
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=== Basic Loop Characteristics Statistics ===" << std::endl;
|
||||
std::cout << "Total Loops: " << stats.totalLoops << std::endl;
|
||||
std::cout << "Counting Loops: " << stats.countingLoops << std::endl;
|
||||
std::cout << "Unrolling Candidates: " << stats.unrollingCandidates << std::endl;
|
||||
std::cout << "Pure Loops: " << stats.pureLoops << std::endl;
|
||||
std::cout << "Local Memory Only Loops: " << stats.localMemoryOnlyLoops << std::endl;
|
||||
std::cout << "No Alias Conflict Loops: " << stats.noAliasConflictLoops << 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 ";
|
||||
if (chars->isPure) std::cout << "Pure ";
|
||||
if (chars->accessesOnlyLocalMemory) std::cout << "LocalMemOnly ";
|
||||
if (chars->hasNoMemoryAliasConflicts) std::cout << "NoAliasConflicts ";
|
||||
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 << ") ";
|
||||
std::cout << std::endl;
|
||||
|
||||
// 归纳变量
|
||||
if (!chars->InductionVars.empty()) {
|
||||
std::cout << " Induction Vars: " << chars->InductionVars.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;
|
||||
|
||||
// 获取并缓存所有需要的分析结果
|
||||
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
if (!loopAnalysis) {
|
||||
std::cerr << "Error: LoopAnalysisResult not available for function " << F->getName() << std::endl;
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果没有循环,直接返回
|
||||
if (!loopAnalysis->hasLoops()) {
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取别名分析和副作用分析结果并缓存
|
||||
aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
|
||||
sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||||
|
||||
if (DEBUG) {
|
||||
if (aliasAnalysis) std::cout << "LoopCharacteristics: Using alias analysis results" << std::endl;
|
||||
if (sideEffectAnalysis) std::cout << "LoopCharacteristics: Using side effect analysis results" << std::endl;
|
||||
}
|
||||
|
||||
CurrentResult = std::make_unique<LoopCharacteristicsResult>(F);
|
||||
|
||||
// 分析每个循环的特征 - 现在不需要传递分析结果参数
|
||||
for (const auto& loop_ptr : loopAnalysis->getAllLoops()) {
|
||||
Loop* loop = loop_ptr.get();
|
||||
auto characteristics = std::make_unique<LoopCharacteristics>(loop);
|
||||
|
||||
// 执行各种特征分析,使用缓存的分析结果
|
||||
analyzeLoop(loop, characteristics.get());
|
||||
|
||||
// 添加到结果中
|
||||
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.countingLoops << " counting loops, "
|
||||
<< stats.unrollingCandidates << " unroll candidates" << std::endl;
|
||||
}
|
||||
|
||||
return false; // 特征分析不修改IR
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeLoop(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
if (DEBUG)
|
||||
std::cout << " Analyzing basic characteristics of loop: " << loop->getName() << std::endl;
|
||||
|
||||
// 按顺序执行基础分析 - 现在使用缓存的分析结果
|
||||
computePerformanceMetrics(loop, characteristics);
|
||||
analyzeLoopForm(loop, characteristics);
|
||||
analyzePurityAndSideEffects(loop, characteristics);
|
||||
identifyBasicInductionVariables(loop, characteristics);
|
||||
identifyBasicLoopInvariants(loop, characteristics);
|
||||
analyzeBasicLoopBounds(loop, characteristics);
|
||||
analyzeBasicMemoryAccessPatterns(loop, characteristics);
|
||||
evaluateBasicOptimizationOpportunities(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::analyzePurityAndSideEffects(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
if (!sideEffectAnalysis) {
|
||||
// 没有副作用分析结果,保守处理
|
||||
characteristics->isPure = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查循环是否有副作用
|
||||
characteristics->isPure = !loop->mayHaveSideEffects(sideEffectAnalysis);
|
||||
|
||||
if (DEBUG && characteristics->isPure) {
|
||||
std::cout << " Loop " << loop->getName() << " is identified as PURE (no side effects)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeBasicMemoryAccessPatterns(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
if (!aliasAnalysis) {
|
||||
// 没有别名分析结果,保守处理
|
||||
characteristics->accessesOnlyLocalMemory = false;
|
||||
characteristics->hasNoMemoryAliasConflicts = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否只访问局部内存
|
||||
characteristics->accessesOnlyLocalMemory = !loop->accessesGlobalMemory(aliasAnalysis);
|
||||
|
||||
// 检查是否有内存别名冲突
|
||||
characteristics->hasNoMemoryAliasConflicts = !loop->hasMemoryAliasConflicts(aliasAnalysis);
|
||||
|
||||
if (DEBUG) {
|
||||
if (characteristics->accessesOnlyLocalMemory) {
|
||||
std::cout << " Loop " << loop->getName() << " accesses ONLY LOCAL MEMORY" << std::endl;
|
||||
}
|
||||
if (characteristics->hasNoMemoryAliasConflicts) {
|
||||
std::cout << " Loop " << loop->getName() << " has NO MEMORY ALIAS CONFLICTS" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 分析基础的内存访问模式
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* loadInst = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
Value* ptr = loadInst->getPointer();
|
||||
|
||||
auto& pattern = characteristics->memoryPatterns[ptr];
|
||||
pattern.loadInsts.push_back(loadInst);
|
||||
pattern.isArrayParameter = aliasAnalysis->isFunctionParameter(ptr);
|
||||
pattern.isGlobalArray = aliasAnalysis->isGlobalArray(ptr);
|
||||
pattern.hasConstantIndices = aliasAnalysis->hasConstantAccess(ptr);
|
||||
|
||||
} else if (auto* storeInst = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
Value* ptr = storeInst->getPointer();
|
||||
|
||||
auto& pattern = characteristics->memoryPatterns[ptr];
|
||||
pattern.storeInsts.push_back(storeInst);
|
||||
pattern.isArrayParameter = aliasAnalysis->isFunctionParameter(ptr);
|
||||
pattern.isGlobalArray = aliasAnalysis->isGlobalArray(ptr);
|
||||
pattern.hasConstantIndices = aliasAnalysis->hasConstantAccess(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::isBasicInductionVariable(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;
|
||||
}
|
||||
|
||||
|
||||
void LoopCharacteristicsPass::identifyBasicInductionVariables(
|
||||
Loop* loop, LoopCharacteristics* characteristics) {
|
||||
BasicBlock* header = loop->getHeader();
|
||||
std::vector<std::unique_ptr<InductionVarInfo>> ivs;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " === Identifying Induction Variables for Loop: " << loop->getName() << " ===" << std::endl;
|
||||
std::cout << " Loop header: " << header->getName() << std::endl;
|
||||
std::cout << " Loop blocks: ";
|
||||
for (auto* bb : loop->getBlocks()) {
|
||||
std::cout << bb->getName() << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// 1. 识别所有BIV
|
||||
for (auto& inst : header->getInstructions()) {
|
||||
auto* phi = dynamic_cast<PhiInst*>(inst.get());
|
||||
if (!phi) continue;
|
||||
if (isBasicInductionVariable(phi, loop)) {
|
||||
ivs.push_back(InductionVarInfo::createBasicBIV(phi, Instruction::Kind::kPhi, phi));
|
||||
if (DEBUG) {
|
||||
std::cout << " [BIV] Found basic induction variable: " << phi->getName() << std::endl;
|
||||
std::cout << " Incoming values: ";
|
||||
for (auto& [incomingBB, incomingVal] : phi->getIncomingValues()) {
|
||||
std::cout << "{" << incomingBB->getName() << ": " << incomingVal->getName() << "} ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Found " << ivs.size() << " basic induction variables" << std::endl;
|
||||
}
|
||||
|
||||
// 2. 递归识别所有派生DIV
|
||||
std::set<Value*> visited;
|
||||
size_t initialSize = ivs.size();
|
||||
|
||||
// 保存初始的BIV列表,避免在遍历过程中修改向量导致迭代器失效
|
||||
std::vector<InductionVarInfo*> bivList;
|
||||
for (size_t i = 0; i < initialSize; ++i) {
|
||||
if (ivs[i] && ivs[i]->ivkind == IVKind::kBasic) {
|
||||
bivList.push_back(ivs[i].get());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* biv : bivList) {
|
||||
if (DEBUG) {
|
||||
if (biv && biv->div) {
|
||||
std::cout << " Searching for derived IVs from BIV: " << biv->div->getName() << std::endl;
|
||||
} else {
|
||||
std::cout << " ERROR: Invalid BIV pointer or div field is null" << std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
findDerivedInductionVars(biv->div, biv->base, loop, ivs, visited);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
size_t derivedCount = ivs.size() - initialSize;
|
||||
std::cout << " Found " << derivedCount << " derived induction variables" << std::endl;
|
||||
|
||||
// 打印所有归纳变量的详细信息
|
||||
std::cout << " === Final Induction Variables Summary ===" << std::endl;
|
||||
for (size_t i = 0; i < ivs.size(); ++i) {
|
||||
const auto& iv = ivs[i];
|
||||
std::cout << " [" << i << "] " << iv->div->getName()
|
||||
<< " (kind: " << (iv->ivkind == IVKind::kBasic ? "Basic" :
|
||||
iv->ivkind == IVKind::kLinear ? "Linear" : "Complex") << ")" << std::endl;
|
||||
std::cout << " Operation: " << static_cast<int>(iv->Instkind) << std::endl;
|
||||
if (iv->base) {
|
||||
std::cout << " Base: " << iv->base->getName() << std::endl;
|
||||
}
|
||||
if (iv->Multibase.first || iv->Multibase.second) {
|
||||
std::cout << " Multi-base: ";
|
||||
if (iv->Multibase.first) std::cout << iv->Multibase.first->getName() << " ";
|
||||
if (iv->Multibase.second) std::cout << iv->Multibase.second->getName() << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << " Factor: " << iv->factor << ", Offset: " << iv->offset << std::endl;
|
||||
std::cout << " Valid: " << (iv->valid ? "Yes" : "No") << std::endl;
|
||||
}
|
||||
std::cout << " =============================================" << std::endl;
|
||||
}
|
||||
|
||||
characteristics->InductionVars = std::move(ivs);
|
||||
}
|
||||
|
||||
|
||||
struct LinearExpr {
|
||||
// 表达为: a * base1 + b * base2 + offset
|
||||
Value* base1 = nullptr;
|
||||
Value* base2 = nullptr;
|
||||
int factor1 = 0;
|
||||
int factor2 = 0;
|
||||
int offset = 0;
|
||||
bool valid = false;
|
||||
bool isSimple = false; // 仅一个BIV时true
|
||||
};
|
||||
|
||||
static LinearExpr analyzeLinearExpr(Value* val, Loop* loop, std::vector<std::unique_ptr<InductionVarInfo>>& ivs) {
|
||||
// 递归归约val为线性表达式
|
||||
// 只支持单/双BIV线性组合
|
||||
// 见下方详细实现
|
||||
// ----------
|
||||
if (DEBUG >= 2) { // 更详细的调试级别
|
||||
if (auto* inst = dynamic_cast<Instruction*>(val)) {
|
||||
std::cout << " Analyzing linear expression for: " << val->getName()
|
||||
<< " (kind: " << static_cast<int>(inst->getKind()) << ")" << std::endl;
|
||||
} else {
|
||||
std::cout << " Analyzing linear expression for value: " << val->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 基本变量:常数
|
||||
if (auto* cint = dynamic_cast<ConstantInteger*>(val)) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Constant: " << cint->getInt() << std::endl;
|
||||
}
|
||||
return {nullptr, nullptr, 0, 0, cint->getInt(), true, false};
|
||||
}
|
||||
|
||||
// 基本变量:BIV或派生IV
|
||||
for (auto& iv : ivs) {
|
||||
if (iv->div == val) {
|
||||
if (iv->ivkind == IVKind::kBasic ||
|
||||
iv->ivkind == IVKind::kLinear) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Found " << (iv->ivkind == IVKind::kBasic ? "Basic" : "Linear")
|
||||
<< " IV with base: " << (iv->base ? iv->base->getName() : "null")
|
||||
<< ", factor: " << iv->factor << ", offset: " << iv->offset << std::endl;
|
||||
}
|
||||
return {iv->base, nullptr, iv->factor, 0, iv->offset, true, true};
|
||||
}
|
||||
// 复杂归纳变量
|
||||
if (iv->ivkind == IVKind::kCmplx) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Found Complex IV with multi-base" << std::endl;
|
||||
}
|
||||
return {iv->Multibase.first, iv->Multibase.second, 1, 1, 0, true, false};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 一元负号
|
||||
if (auto* inst = dynamic_cast<Instruction*>(val)) {
|
||||
auto kind = inst->getKind();
|
||||
if (kind == Instruction::Kind::kNeg) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Analyzing negation" << std::endl;
|
||||
}
|
||||
auto expr = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||
if (!expr.valid) return expr;
|
||||
expr.factor1 = -expr.factor1;
|
||||
expr.factor2 = -expr.factor2;
|
||||
expr.offset = -expr.offset;
|
||||
expr.isSimple = (expr.base2 == nullptr);
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Negation result: valid=" << expr.valid << ", simple=" << expr.isSimple << std::endl;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
// 二元加减乘
|
||||
if (kind == Instruction::Kind::kAdd || kind == Instruction::Kind::kSub) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Analyzing " << (kind == Instruction::Kind::kAdd ? "addition" : "subtraction") << std::endl;
|
||||
}
|
||||
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||
if (!expr0.valid || !expr1.valid) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Failed: operand not linear (expr0.valid=" << expr0.valid << ", expr1.valid=" << expr1.valid << ")" << std::endl;
|
||||
}
|
||||
return {nullptr, nullptr, 0, 0, 0, false, false};
|
||||
}
|
||||
|
||||
// 合并:若BIV相同或有一个是常数
|
||||
// 单BIV+常数
|
||||
if (expr0.base1 && !expr1.base1 && !expr1.base2) {
|
||||
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Single BIV + constant pattern" << std::endl;
|
||||
}
|
||||
return {expr0.base1, nullptr, expr0.factor1, 0, expr0.offset + sign * expr1.offset, true, expr0.isSimple};
|
||||
}
|
||||
if (!expr0.base1 && !expr0.base2 && expr1.base1) {
|
||||
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||
int f = sign * expr1.factor1;
|
||||
int off = expr0.offset + sign * expr1.offset;
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Constant + single BIV pattern" << std::endl;
|
||||
}
|
||||
return {expr1.base1, nullptr, f, 0, off, true, expr1.isSimple};
|
||||
}
|
||||
|
||||
// 双BIV线性组合
|
||||
if (expr0.base1 && expr1.base1 && expr0.base1 != expr1.base1 && !expr0.base2 && !expr1.base2) {
|
||||
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||
Value* base1 = expr0.base1;
|
||||
Value* base2 = expr1.base1;
|
||||
int f1 = expr0.factor1;
|
||||
int f2 = sign * expr1.factor1;
|
||||
int off = expr0.offset + sign * expr1.offset;
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Double BIV linear combination" << std::endl;
|
||||
}
|
||||
return {base1, base2, f1, f2, off, true, false};
|
||||
}
|
||||
|
||||
// 同BIV合并
|
||||
if (expr0.base1 && expr1.base1 && expr0.base1 == expr1.base1 && !expr0.base2 && !expr1.base2) {
|
||||
int sign = (kind == Instruction::Kind::kAdd ? 1 : -1);
|
||||
int f = expr0.factor1 + sign * expr1.factor1;
|
||||
int off = expr0.offset + sign * expr1.offset;
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Same BIV combination" << std::endl;
|
||||
}
|
||||
return {expr0.base1, nullptr, f, 0, off, true, true};
|
||||
}
|
||||
}
|
||||
|
||||
// 乘法:BIV*const 或 const*BIV
|
||||
if (kind == Instruction::Kind::kMul) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Analyzing multiplication" << std::endl;
|
||||
}
|
||||
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||
|
||||
// 只允许一侧为常数
|
||||
if (expr0.base1 && !expr1.base1 && !expr1.base2 && expr1.offset) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> BIV * constant pattern" << std::endl;
|
||||
}
|
||||
return {expr0.base1, nullptr, expr0.factor1 * expr1.offset, 0, expr0.offset * expr1.offset, true, true};
|
||||
}
|
||||
if (!expr0.base1 && !expr0.base2 && expr0.offset && expr1.base1) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Constant * BIV pattern" << std::endl;
|
||||
}
|
||||
return {expr1.base1, nullptr, expr1.factor1 * expr0.offset, 0, expr1.offset * expr0.offset, true, true};
|
||||
}
|
||||
// 双BIV乘法不支持
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Multiplication pattern not supported" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 除法:BIV/const(仅当const是2的幂时)
|
||||
if (kind == Instruction::Kind::kDiv) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Analyzing division" << std::endl;
|
||||
}
|
||||
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||
|
||||
// 只支持 BIV / 2^n 形式
|
||||
if (expr0.base1 && !expr1.base1 && !expr1.base2 && expr1.offset > 0) {
|
||||
// 检查是否为2的幂
|
||||
int divisor = expr1.offset;
|
||||
if ((divisor & (divisor - 1)) == 0) { // 2的幂检查
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> BIV / power_of_2 pattern (divisor=" << divisor << ")" << std::endl;
|
||||
}
|
||||
// 对于除法,我们记录为特殊的归纳变量模式
|
||||
// factor表示除数(用于后续强度削弱)
|
||||
return {expr0.base1, nullptr, -divisor, 0, expr0.offset / divisor, true, true};
|
||||
}
|
||||
}
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Division pattern not supported (not power of 2)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 取模:BIV % const(仅当const是2的幂时)
|
||||
if (kind == Instruction::Kind::kRem) {
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Analyzing remainder" << std::endl;
|
||||
}
|
||||
auto expr0 = analyzeLinearExpr(inst->getOperand(0), loop, ivs);
|
||||
auto expr1 = analyzeLinearExpr(inst->getOperand(1), loop, ivs);
|
||||
|
||||
// 只支持 BIV % 2^n 形式
|
||||
if (expr0.base1 && !expr1.base1 && !expr1.base2 && expr1.offset > 0) {
|
||||
// 检查是否为2的幂
|
||||
int modulus = expr1.offset;
|
||||
if ((modulus & (modulus - 1)) == 0) { // 2的幂检查
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> BIV % power_of_2 pattern (modulus=" << modulus << ")" << std::endl;
|
||||
}
|
||||
// 对于取模,我们记录为特殊的归纳变量模式
|
||||
// 使用负的模数来区分取模和除法
|
||||
return {expr0.base1, nullptr, -10000 - modulus, 0, 0, true, true}; // 特殊标记
|
||||
}
|
||||
}
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Remainder pattern not supported (not power of 2)" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 其它情况
|
||||
if (DEBUG >= 2) {
|
||||
std::cout << " -> Other case: not linear" << std::endl;
|
||||
}
|
||||
return {nullptr, nullptr, 0, 0, 0, false, false};
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 经典推进法:反复遍历,直到收敛 TODO:优化
|
||||
bool changed;
|
||||
std::unordered_set<Value*> invariants = characteristics->loopInvariants; // 可能为空
|
||||
|
||||
do {
|
||||
changed = false;
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
Instruction* I = inst.get();
|
||||
// 跳过phi和terminator
|
||||
if (dynamic_cast<PhiInst*>(I)) continue;
|
||||
if (I->isTerminator()) continue;
|
||||
if (invariants.count(I)) continue;
|
||||
|
||||
if (isClassicLoopInvariant(I, loop, invariants)) {
|
||||
invariants.insert(I);
|
||||
characteristics->invariantInsts.insert(I);
|
||||
if (DEBUG)
|
||||
std::cout << " Found loop invariant: " << I->getName() << std::endl;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
|
||||
characteristics->loopInvariants = std::move(invariants);
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 简化的基础边界分析
|
||||
// 检查是否有静态可确定的循环次数(简化版本)
|
||||
if (characteristics->isCountingLoop && !characteristics->InductionVars.empty()) {
|
||||
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
||||
if (characteristics->instructionCount < 10) {
|
||||
characteristics->staticTripCount = 100; // 简化估计
|
||||
characteristics->hasKnownBounds = true;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Estimated static trip count: " << *characteristics->staticTripCount << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::evaluateBasicOptimizationOpportunities(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 评估基础循环展开机会
|
||||
characteristics->benefitsFromUnrolling =
|
||||
characteristics->isInnermost &&
|
||||
characteristics->instructionCount > 3 &&
|
||||
characteristics->instructionCount < 50 &&
|
||||
!characteristics->hasComplexControlFlow;
|
||||
|
||||
if (characteristics->benefitsFromUnrolling) {
|
||||
// 基于循环体大小估算展开因子
|
||||
if (characteristics->instructionCount <= 5) characteristics->suggestedUnrollFactor = 8;
|
||||
else if (characteristics->instructionCount <= 10) characteristics->suggestedUnrollFactor = 4;
|
||||
else if (characteristics->instructionCount <= 20) characteristics->suggestedUnrollFactor = 2;
|
||||
else characteristics->suggestedUnrollFactor = 1;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
if (characteristics->benefitsFromUnrolling) {
|
||||
std::cout << " Loop " << loop->getName() << " benefits from UNROLLING (factor="
|
||||
<< characteristics->suggestedUnrollFactor << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 辅助方法实现 ==========
|
||||
|
||||
// 递归识别DIV,支持线性与复杂归纳变量
|
||||
void LoopCharacteristicsPass::findDerivedInductionVars(
|
||||
Value* root,
|
||||
Value* base, // 只传单一BIV base
|
||||
Loop* loop,
|
||||
std::vector<std::unique_ptr<InductionVarInfo>>& ivs,
|
||||
std::set<Value*>& visited)
|
||||
{
|
||||
if (visited.count(root)) return;
|
||||
visited.insert(root);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Analyzing uses of: " << root->getName() << std::endl;
|
||||
}
|
||||
|
||||
for (auto use : root->getUses()) {
|
||||
auto user = use->getUser();
|
||||
Instruction* inst = dynamic_cast<Instruction*>(user);
|
||||
if (!inst) continue;
|
||||
if (!loop->contains(inst->getParent())) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Skipping user outside loop: " << inst->getName() << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Checking instruction: " << inst->getName()
|
||||
<< " (kind: " << static_cast<int>(inst->getKind()) << ")" << std::endl;
|
||||
}
|
||||
|
||||
// 线性归约分析
|
||||
auto expr = analyzeLinearExpr(inst, loop, ivs);
|
||||
|
||||
if (!expr.valid) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Linear expression analysis failed for: " << inst->getName() << std::endl;
|
||||
}
|
||||
// 复杂非线性归纳变量,作为kCmplx记录(假如你想追踪)
|
||||
// 这里假设expr.base1、base2都有效才记录double
|
||||
if (expr.base1 && expr.base2) {
|
||||
if (DEBUG) {
|
||||
std::cout << " [DIV-COMPLEX] Creating complex derived IV: " << inst->getName()
|
||||
<< " with bases: " << expr.base1->getName() << ", " << expr.base2->getName() << std::endl;
|
||||
}
|
||||
ivs.push_back(InductionVarInfo::createDoubleDIV(inst, inst->getKind(), expr.base1, expr.base2, 0, expr.offset));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 单BIV线性
|
||||
if (expr.base1 && !expr.base2) {
|
||||
// 检查这个指令是否已经是一个已知的IV(特别是BIV),避免重复创建
|
||||
bool alreadyExists = false;
|
||||
for (const auto& existingIV : ivs) {
|
||||
if (existingIV->div == inst) {
|
||||
alreadyExists = true;
|
||||
if (DEBUG) {
|
||||
std::cout << " [DIV-SKIP] Instruction " << inst->getName()
|
||||
<< " already exists as IV, skipping creation" << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyExists) {
|
||||
if (DEBUG) {
|
||||
std::cout << " [DIV-LINEAR] Creating single-base derived IV: " << inst->getName()
|
||||
<< " with base: " << expr.base1->getName()
|
||||
<< ", factor: " << expr.factor1
|
||||
<< ", offset: " << expr.offset << std::endl;
|
||||
}
|
||||
ivs.push_back(InductionVarInfo::createSingleDIV(inst, inst->getKind(), expr.base1, expr.factor1, expr.offset));
|
||||
findDerivedInductionVars(inst, expr.base1, loop, ivs, visited);
|
||||
}
|
||||
}
|
||||
// 双BIV线性
|
||||
else if (expr.base1 && expr.base2) {
|
||||
if (DEBUG) {
|
||||
std::cout << " [DIV-COMPLEX] Creating double-base derived IV: " << inst->getName()
|
||||
<< " with bases: " << expr.base1->getName() << ", " << expr.base2->getName()
|
||||
<< ", offset: " << expr.offset << std::endl;
|
||||
}
|
||||
ivs.push_back(InductionVarInfo::createDoubleDIV(inst, inst->getKind(), expr.base1, expr.base2, 0, expr.offset));
|
||||
// 双BIV情形一般不再递归下游
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Finished analyzing uses of: " << root->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归/推进式判定
|
||||
bool LoopCharacteristicsPass::isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants) {
|
||||
// 1. 常量
|
||||
if (auto* constval = dynamic_cast<ConstantValue*>(val)) return true;
|
||||
|
||||
// 2. 参数(函数参数)通常不在任何BasicBlock内,直接判定为不变量
|
||||
if (auto* arg = dynamic_cast<Argument*>(val)) return true;
|
||||
|
||||
// 3. 指令且定义在循环外
|
||||
if (auto* inst = dynamic_cast<Instruction*>(val)) {
|
||||
if (!loop->contains(inst->getParent()))
|
||||
return true;
|
||||
|
||||
// 4. 跳转 phi指令 副作用 不外提
|
||||
if (inst->isTerminator() || inst->isPhi() || sideEffectAnalysis->hasSideEffect(inst))
|
||||
return false;
|
||||
|
||||
// 5. 所有操作数都是不变量
|
||||
for (size_t i = 0; i < inst->getNumOperands(); ++i) {
|
||||
Value* op = inst->getOperand(i);
|
||||
if (!isClassicLoopInvariant(op, loop, invariants) && !invariants.count(op))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 其它情况
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoopCharacteristicsPass::hasSimpleMemoryPattern(Loop* loop) {
|
||||
// 检查是否有简单的内存访问模式
|
||||
return true; // 暂时简化处理
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
803
src/midend/Pass/Analysis/LoopVectorization.cpp
Normal file
803
src/midend/Pass/Analysis/LoopVectorization.cpp
Normal file
@ -0,0 +1,803 @@
|
||||
#include "LoopVectorization.h"
|
||||
#include "Dom.h"
|
||||
#include "Loop.h"
|
||||
#include "Liveness.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 定义 Pass 的唯一 ID
|
||||
void *LoopVectorizationPass::ID = (void *)&LoopVectorizationPass::ID;
|
||||
|
||||
std::vector<int> DependenceVector::getDirectionVector() const {
|
||||
std::vector<int> direction;
|
||||
direction.reserve(distances.size());
|
||||
|
||||
for (int dist : distances) {
|
||||
if (dist > 0) direction.push_back(1); // 前向依赖
|
||||
else if (dist < 0) direction.push_back(-1); // 后向依赖
|
||||
else direction.push_back(0); // 无依赖
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
bool DependenceVector::isVectorizationSafe() const {
|
||||
if (!isKnown) return false; // 未知依赖,不安全
|
||||
|
||||
// 对于向量化,我们主要关心最内层循环的依赖
|
||||
if (distances.empty()) return true;
|
||||
|
||||
int innermostDistance = distances.back(); // 最内层循环的距离
|
||||
|
||||
// 前向依赖 (距离 > 0) 通常是安全的,可以通过调整向量化顺序处理
|
||||
// 后向依赖 (距离 < 0) 通常不安全,会阻止向量化
|
||||
// 距离 = 0 表示同一迭代内的依赖,通常安全
|
||||
|
||||
return innermostDistance >= 0;
|
||||
}
|
||||
|
||||
size_t LoopVectorizationResult::getVectorizableLoopCount() const {
|
||||
size_t count = 0;
|
||||
for (const auto& [loop, analysis] : VectorizationMap) {
|
||||
if (analysis.isVectorizable) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t LoopVectorizationResult::getParallelizableLoopCount() const {
|
||||
size_t count = 0;
|
||||
for (const auto& [loop, analysis] : ParallelizationMap) {
|
||||
if (analysis.isParallelizable) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::vector<Loop*> LoopVectorizationResult::getVectorizationCandidates() const {
|
||||
std::vector<Loop*> candidates;
|
||||
for (const auto& [loop, analysis] : VectorizationMap) {
|
||||
if (analysis.isVectorizable) {
|
||||
candidates.push_back(loop);
|
||||
}
|
||||
}
|
||||
|
||||
// 按建议的向量宽度排序,优先处理收益更大的循环
|
||||
std::sort(candidates.begin(), candidates.end(),
|
||||
[this](Loop* a, Loop* b) {
|
||||
const auto& analysisA = VectorizationMap.at(a);
|
||||
const auto& analysisB = VectorizationMap.at(b);
|
||||
return analysisA.suggestedVectorWidth > analysisB.suggestedVectorWidth;
|
||||
});
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
std::vector<Loop*> LoopVectorizationResult::getParallelizationCandidates() const {
|
||||
std::vector<Loop*> candidates;
|
||||
for (const auto& [loop, analysis] : ParallelizationMap) {
|
||||
if (analysis.isParallelizable) {
|
||||
candidates.push_back(loop);
|
||||
}
|
||||
}
|
||||
|
||||
// 按建议的线程数排序
|
||||
std::sort(candidates.begin(), candidates.end(),
|
||||
[this](Loop* a, Loop* b) {
|
||||
const auto& analysisA = ParallelizationMap.at(a);
|
||||
const auto& analysisB = ParallelizationMap.at(b);
|
||||
return analysisA.suggestedThreadCount > analysisB.suggestedThreadCount;
|
||||
});
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
void LoopVectorizationResult::print() const {
|
||||
if (!DEBUG) return;
|
||||
|
||||
std::cout << "\n--- Loop Vectorization/Parallelization Analysis Results for Function: "
|
||||
<< AssociatedFunction->getName() << " ---" << std::endl;
|
||||
|
||||
if (VectorizationMap.empty() && ParallelizationMap.empty()) {
|
||||
std::cout << " No vectorization/parallelization analysis results." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 统计信息
|
||||
std::cout << "\n=== Summary ===" << std::endl;
|
||||
std::cout << "Total Loops Analyzed: " << VectorizationMap.size() << std::endl;
|
||||
std::cout << "Vectorizable Loops: " << getVectorizableLoopCount() << std::endl;
|
||||
std::cout << "Parallelizable Loops: " << getParallelizableLoopCount() << std::endl;
|
||||
|
||||
// 详细分析结果
|
||||
for (const auto& [loop, vecAnalysis] : VectorizationMap) {
|
||||
std::cout << "\n--- Loop: " << loop->getName() << " ---" << std::endl;
|
||||
|
||||
// 向量化分析 (暂时搁置)
|
||||
std::cout << " Vectorization: " << (vecAnalysis.isVectorizable ? "YES" : "NO") << std::endl;
|
||||
if (!vecAnalysis.preventingFactors.empty()) {
|
||||
std::cout << " Preventing Factors: ";
|
||||
for (const auto& factor : vecAnalysis.preventingFactors) {
|
||||
std::cout << factor << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// 并行化分析
|
||||
auto parallelIt = ParallelizationMap.find(loop);
|
||||
if (parallelIt != ParallelizationMap.end()) {
|
||||
const auto& parAnalysis = parallelIt->second;
|
||||
std::cout << " Parallelization: " << (parAnalysis.isParallelizable ? "YES" : "NO") << std::endl;
|
||||
if (parAnalysis.isParallelizable) {
|
||||
std::cout << " Suggested Thread Count: " << parAnalysis.suggestedThreadCount << std::endl;
|
||||
if (parAnalysis.requiresReduction) {
|
||||
std::cout << " Requires Reduction: Yes" << std::endl;
|
||||
}
|
||||
if (parAnalysis.requiresBarrier) {
|
||||
std::cout << " Requires Barrier: Yes" << std::endl;
|
||||
}
|
||||
} else if (!parAnalysis.preventingFactors.empty()) {
|
||||
std::cout << " Preventing Factors: ";
|
||||
for (const auto& factor : parAnalysis.preventingFactors) {
|
||||
std::cout << factor << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 依赖关系
|
||||
auto depIt = DependenceMap.find(loop);
|
||||
if (depIt != DependenceMap.end()) {
|
||||
const auto& dependences = depIt->second;
|
||||
std::cout << " Dependences: " << dependences.size() << " found" << std::endl;
|
||||
for (const auto& dep : dependences) {
|
||||
if (dep.dependenceVector.isKnown) {
|
||||
std::cout << " " << dep.source->getName() << " -> " << dep.sink->getName();
|
||||
std::cout << " [";
|
||||
for (size_t i = 0; i < dep.dependenceVector.distances.size(); ++i) {
|
||||
if (i > 0) std::cout << ",";
|
||||
std::cout << dep.dependenceVector.distances[i];
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "-----------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
bool LoopVectorizationPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (F->getBasicBlocks().empty()) {
|
||||
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "Running LoopVectorizationPass on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 获取循环分析结果
|
||||
auto* loopAnalysisResult = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
if (!loopAnalysisResult || !loopAnalysisResult->hasLoops()) {
|
||||
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取循环特征分析结果
|
||||
auto* loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
|
||||
if (!loopCharacteristics) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Warning: LoopCharacteristics analysis not available" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取别名分析结果
|
||||
auto* aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F);
|
||||
|
||||
// 获取副作用分析结果
|
||||
auto* sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||||
|
||||
CurrentResult = std::make_unique<LoopVectorizationResult>(F);
|
||||
|
||||
// 分析每个循环的向量化/并行化可行性
|
||||
for (const auto& loop_ptr : loopAnalysisResult->getAllLoops()) {
|
||||
Loop* loop = loop_ptr.get();
|
||||
|
||||
// 获取该循环的特征信息
|
||||
LoopCharacteristics* characteristics = nullptr;
|
||||
if (loopCharacteristics) {
|
||||
characteristics = const_cast<LoopCharacteristics*>(loopCharacteristics->getCharacteristics(loop));
|
||||
}
|
||||
|
||||
analyzeLoop(loop, characteristics, aliasAnalysis, sideEffectAnalysis);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "LoopVectorizationPass completed. Found "
|
||||
<< CurrentResult->getVectorizableLoopCount() << " vectorizable loops, "
|
||||
<< CurrentResult->getParallelizableLoopCount() << " parallelizable loops" << std::endl;
|
||||
}
|
||||
|
||||
return false; // 分析遍不修改IR
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::analyzeLoop(Loop* loop, LoopCharacteristics* characteristics,
|
||||
AliasAnalysisResult* aliasAnalysis, SideEffectAnalysisResult* sideEffectAnalysis) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Analyzing advanced features for loop: " << loop->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 1. 计算精确依赖向量
|
||||
auto dependences = computeDependenceVectors(loop, aliasAnalysis);
|
||||
CurrentResult->addDependenceAnalysis(loop, dependences);
|
||||
|
||||
// 2. 分析向量化可行性 (暂时搁置,总是返回不可向量化)
|
||||
auto vecAnalysis = analyzeVectorizability(loop, dependences, characteristics);
|
||||
CurrentResult->addVectorizationAnalysis(loop, vecAnalysis);
|
||||
|
||||
// 3. 分析并行化可行性
|
||||
auto parAnalysis = analyzeParallelizability(loop, dependences, characteristics);
|
||||
CurrentResult->addParallelizationAnalysis(loop, parAnalysis);
|
||||
}
|
||||
|
||||
// ========== 依赖向量分析实现 ==========
|
||||
|
||||
std::vector<PreciseDependence> LoopVectorizationPass::computeDependenceVectors(Loop* loop,
|
||||
AliasAnalysisResult* aliasAnalysis) {
|
||||
std::vector<PreciseDependence> dependences;
|
||||
std::vector<Instruction*> memoryInsts;
|
||||
|
||||
// 收集所有内存操作指令
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (dynamic_cast<LoadInst*>(inst.get()) || dynamic_cast<StoreInst*>(inst.get())) {
|
||||
memoryInsts.push_back(inst.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分析每对内存操作之间的依赖关系
|
||||
for (size_t i = 0; i < memoryInsts.size(); ++i) {
|
||||
for (size_t j = i + 1; j < memoryInsts.size(); ++j) {
|
||||
Instruction* inst1 = memoryInsts[i];
|
||||
Instruction* inst2 = memoryInsts[j];
|
||||
|
||||
Value* ptr1 = nullptr;
|
||||
Value* ptr2 = nullptr;
|
||||
|
||||
if (auto* load = dynamic_cast<LoadInst*>(inst1)) {
|
||||
ptr1 = load->getPointer();
|
||||
} else if (auto* store = dynamic_cast<StoreInst*>(inst1)) {
|
||||
ptr1 = store->getPointer();
|
||||
}
|
||||
|
||||
if (auto* load = dynamic_cast<LoadInst*>(inst2)) {
|
||||
ptr2 = load->getPointer();
|
||||
} else if (auto* store = dynamic_cast<StoreInst*>(inst2)) {
|
||||
ptr2 = store->getPointer();
|
||||
}
|
||||
|
||||
if (!ptr1 || !ptr2) continue;
|
||||
|
||||
// 检查是否可能存在别名关系
|
||||
bool mayAlias = false;
|
||||
if (aliasAnalysis) {
|
||||
mayAlias = aliasAnalysis->queryAlias(ptr1, ptr2) != AliasType::NO_ALIAS;
|
||||
} else {
|
||||
mayAlias = (ptr1 != ptr2); // 保守估计
|
||||
}
|
||||
|
||||
if (mayAlias) {
|
||||
// 创建依赖关系
|
||||
PreciseDependence dep(loop->getLoopDepth());
|
||||
dep.source = inst1;
|
||||
dep.sink = inst2;
|
||||
dep.memoryLocation = ptr1;
|
||||
|
||||
// 确定依赖类型
|
||||
bool isStore1 = dynamic_cast<StoreInst*>(inst1) != nullptr;
|
||||
bool isStore2 = dynamic_cast<StoreInst*>(inst2) != nullptr;
|
||||
|
||||
if (isStore1 && !isStore2) {
|
||||
dep.type = DependenceType::TRUE_DEPENDENCE; // Write -> Read (RAW)
|
||||
} else if (!isStore1 && isStore2) {
|
||||
dep.type = DependenceType::ANTI_DEPENDENCE; // Read -> Write (WAR)
|
||||
} else if (isStore1 && isStore2) {
|
||||
dep.type = DependenceType::OUTPUT_DEPENDENCE; // Write -> Write (WAW)
|
||||
} else {
|
||||
continue; // Read -> Read (RAR) - 跳过,不是真正的依赖
|
||||
}
|
||||
|
||||
// 计算依赖向量
|
||||
dep.dependenceVector = computeAccessDependence(inst1, inst2, loop);
|
||||
|
||||
// 判断是否允许并行化
|
||||
dep.allowsParallelization = dep.dependenceVector.isLoopIndependent() ||
|
||||
(dep.dependenceVector.isKnown &&
|
||||
std::all_of(dep.dependenceVector.distances.begin(),
|
||||
dep.dependenceVector.distances.end(),
|
||||
[](int d) { return d >= 0; }));
|
||||
|
||||
dependences.push_back(dep);
|
||||
|
||||
if (DEBUG && dep.dependenceVector.isKnown) {
|
||||
std::cout << " Found dependence: " << inst1->getName()
|
||||
<< " -> " << inst2->getName() << " [";
|
||||
for (size_t k = 0; k < dep.dependenceVector.distances.size(); ++k) {
|
||||
if (k > 0) std::cout << ",";
|
||||
std::cout << dep.dependenceVector.distances[k];
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependences;
|
||||
}
|
||||
|
||||
DependenceVector LoopVectorizationPass::computeAccessDependence(Instruction* inst1, Instruction* inst2, Loop* loop) {
|
||||
DependenceVector depVec(loop->getLoopDepth());
|
||||
|
||||
Value* ptr1 = nullptr;
|
||||
Value* ptr2 = nullptr;
|
||||
|
||||
if (auto* load = dynamic_cast<LoadInst*>(inst1)) {
|
||||
ptr1 = load->getPointer();
|
||||
} else if (auto* store = dynamic_cast<StoreInst*>(inst1)) {
|
||||
ptr1 = store->getPointer();
|
||||
}
|
||||
|
||||
if (auto* load = dynamic_cast<LoadInst*>(inst2)) {
|
||||
ptr2 = load->getPointer();
|
||||
} else if (auto* store = dynamic_cast<StoreInst*>(inst2)) {
|
||||
ptr2 = store->getPointer();
|
||||
}
|
||||
|
||||
if (!ptr1 || !ptr2) return depVec;
|
||||
|
||||
// 尝试分析仿射关系
|
||||
if (areAccessesAffinelyRelated(ptr1, ptr2, loop)) {
|
||||
auto coeff1 = extractInductionCoefficients(ptr1, loop);
|
||||
auto coeff2 = extractInductionCoefficients(ptr2, loop);
|
||||
|
||||
if (coeff1.size() == coeff2.size()) {
|
||||
depVec.isKnown = true;
|
||||
depVec.isConstant = true;
|
||||
|
||||
for (size_t i = 0; i < coeff1.size(); ++i) {
|
||||
depVec.distances[i] = coeff2[i] - coeff1[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return depVec;
|
||||
}
|
||||
|
||||
bool LoopVectorizationPass::areAccessesAffinelyRelated(Value* ptr1, Value* ptr2, Loop* loop) {
|
||||
// 简化实现:检查是否都是基于归纳变量的数组访问
|
||||
// 真正的实现需要复杂的仿射关系分析
|
||||
|
||||
// 检查是否为 GEP 指令
|
||||
auto* gep1 = dynamic_cast<GetElementPtrInst*>(ptr1);
|
||||
auto* gep2 = dynamic_cast<GetElementPtrInst*>(ptr2);
|
||||
|
||||
if (!gep1 || !gep2) return false;
|
||||
|
||||
// 检查是否访问同一个数组基址
|
||||
if (gep1->getBasePointer() != gep2->getBasePointer()) return false;
|
||||
|
||||
// 简化:假设都是仿射的
|
||||
return true;
|
||||
}
|
||||
|
||||
// ========== 向量化分析实现 (暂时搁置) ==========
|
||||
|
||||
VectorizationAnalysis LoopVectorizationPass::analyzeVectorizability(Loop* loop,
|
||||
const std::vector<PreciseDependence>& dependences,
|
||||
LoopCharacteristics* characteristics) {
|
||||
VectorizationAnalysis analysis; // 构造函数已设置为不可向量化
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Vectorization analysis: DISABLED (temporarily)" << std::endl;
|
||||
}
|
||||
|
||||
// 向量化功能暂时搁置,总是返回不可向量化
|
||||
// 这里可以添加一些基本的诊断信息用于日志
|
||||
if (!loop->isInnermost()) {
|
||||
analysis.preventingFactors.push_back("Not innermost loop");
|
||||
}
|
||||
if (loop->getBlocks().size() > 1) {
|
||||
analysis.preventingFactors.push_back("Complex control flow");
|
||||
}
|
||||
if (!dependences.empty()) {
|
||||
analysis.preventingFactors.push_back("Has dependences (not analyzed in detail)");
|
||||
}
|
||||
|
||||
return analysis;
|
||||
}
|
||||
|
||||
// ========== 并行化分析实现 ==========
|
||||
|
||||
ParallelizationAnalysis LoopVectorizationPass::analyzeParallelizability(Loop* loop,
|
||||
const std::vector<PreciseDependence>& dependences,
|
||||
LoopCharacteristics* characteristics) {
|
||||
ParallelizationAnalysis analysis;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Analyzing parallelizability for loop: " << loop->getName() << std::endl;
|
||||
std::cout << " Found " << dependences.size() << " dependences" << std::endl;
|
||||
}
|
||||
|
||||
// 按依赖类型分类分析
|
||||
bool hasTrueDependences = false;
|
||||
bool hasAntiDependences = false;
|
||||
bool hasOutputDependences = false;
|
||||
|
||||
for (const auto& dep : dependences) {
|
||||
switch (dep.type) {
|
||||
case DependenceType::TRUE_DEPENDENCE:
|
||||
hasTrueDependences = true;
|
||||
// 真依赖通常是最难处理的,需要检查是否为归约模式
|
||||
if (dep.isReductionDependence) {
|
||||
analysis.requiresReduction = true;
|
||||
analysis.reductionVariables.insert(dep.memoryLocation);
|
||||
} else {
|
||||
analysis.preventingFactors.push_back("Non-reduction true dependence");
|
||||
}
|
||||
break;
|
||||
case DependenceType::ANTI_DEPENDENCE:
|
||||
hasAntiDependences = true;
|
||||
// 反依赖可以通过变量私有化解决
|
||||
analysis.privatizableVariables.insert(dep.memoryLocation);
|
||||
break;
|
||||
case DependenceType::OUTPUT_DEPENDENCE:
|
||||
hasOutputDependences = true;
|
||||
// 输出依赖可以通过变量私有化或原子操作解决
|
||||
analysis.sharedVariables.insert(dep.memoryLocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 确定并行化类型
|
||||
analysis.parallelType = determineParallelizationType(loop, dependences);
|
||||
|
||||
// 基于依赖类型评估可并行性
|
||||
if (!hasTrueDependences && !hasOutputDependences) {
|
||||
// 只有反依赖或无依赖,完全可并行
|
||||
analysis.parallelType = ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
|
||||
analysis.isParallelizable = true;
|
||||
} else if (analysis.requiresReduction) {
|
||||
// 有归约模式,可以并行但需要特殊处理
|
||||
analysis.parallelType = ParallelizationAnalysis::REDUCTION_PARALLEL;
|
||||
analysis.isParallelizable = true;
|
||||
} else if (hasTrueDependences) {
|
||||
// 有非归约的真依赖,通常不能并行化
|
||||
analysis.isParallelizable = false;
|
||||
analysis.preventingFactors.push_back("Non-reduction loop-carried true dependences");
|
||||
}
|
||||
|
||||
if (analysis.isParallelizable) {
|
||||
// 进一步分析并行化收益和成本
|
||||
estimateParallelizationBenefit(loop, &analysis, characteristics);
|
||||
analyzeSynchronizationNeeds(loop, &analysis, dependences);
|
||||
analysis.suggestedThreadCount = estimateOptimalThreadCount(loop, characteristics);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Parallelizable: " << (analysis.isParallelizable ? "YES" : "NO") << std::endl;
|
||||
if (analysis.isParallelizable) {
|
||||
std::cout << " Type: " << (int)analysis.parallelType << ", Threads: " << analysis.suggestedThreadCount << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return analysis;
|
||||
}
|
||||
|
||||
bool LoopVectorizationPass::checkParallelizationLegality(Loop* loop, const std::vector<PreciseDependence>& dependences) {
|
||||
// 检查所有依赖是否允许并行化
|
||||
for (const auto& dep : dependences) {
|
||||
if (!dep.allowsParallelization) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有无法并行化的操作
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
// 检查原子操作、同步操作等
|
||||
if (auto* call = dynamic_cast<CallInst*>(inst.get())) {
|
||||
// 简化:假设函数调用需要特殊处理
|
||||
// 在实际实现中,需要分析函数的副作用
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int LoopVectorizationPass::estimateOptimalThreadCount(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 基于循环特征估计最优线程数
|
||||
if (!characteristics) return 2;
|
||||
|
||||
// 基于循环体大小和计算密度
|
||||
int baseThreads = 2;
|
||||
|
||||
if (characteristics->instructionCount > 50) baseThreads = 4;
|
||||
if (characteristics->instructionCount > 200) baseThreads = 8;
|
||||
|
||||
// 基于计算与内存比率调整
|
||||
if (characteristics->computeToMemoryRatio > 2.0) {
|
||||
baseThreads *= 2; // 计算密集型,可以使用更多线程
|
||||
}
|
||||
|
||||
return std::min(baseThreads, 16); // 限制最大线程数
|
||||
}
|
||||
|
||||
// ========== 辅助方法实现 ==========
|
||||
|
||||
bool LoopVectorizationPass::isConstantStride(Value* ptr, Loop* loop, int& stride) {
|
||||
// 简化实现:检查是否为常量步长访问
|
||||
stride = 1; // 默认步长
|
||||
|
||||
auto* gep = dynamic_cast<GetElementPtrInst*>(ptr);
|
||||
if (!gep) return false;
|
||||
|
||||
// 检查最后一个索引是否为归纳变量 + 常量
|
||||
if (gep->getNumIndices() > 0) {
|
||||
Value* lastIndex = gep->getIndex(gep->getNumIndices() - 1);
|
||||
|
||||
// 简化:假设是 i 或 i+c 的形式
|
||||
if (auto* binInst = dynamic_cast<BinaryInst*>(lastIndex)) {
|
||||
if (binInst->getKind() == Instruction::kAdd) {
|
||||
// 检查是否为 i + constant
|
||||
if (auto* constInt = dynamic_cast<ConstantInteger*>(binInst->getRhs())) {
|
||||
stride = constInt->getInt();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 默认为步长1的连续访问
|
||||
stride = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> LoopVectorizationPass::extractInductionCoefficients(Value* ptr, Loop* loop) {
|
||||
// 简化实现:返回默认的仿射系数
|
||||
std::vector<int> coefficients;
|
||||
|
||||
// 假设是简单的 a[i] 形式,系数为 [0, 1]
|
||||
coefficients.push_back(0); // 常数项
|
||||
coefficients.push_back(1); // 归纳变量系数
|
||||
|
||||
return coefficients;
|
||||
}
|
||||
|
||||
// ========== 缺失的方法实现 ==========
|
||||
|
||||
ParallelizationAnalysis::ParallelizationType LoopVectorizationPass::determineParallelizationType(
|
||||
Loop* loop, const std::vector<PreciseDependence>& dependences) {
|
||||
|
||||
// 检查是否有任何依赖
|
||||
if (dependences.empty()) {
|
||||
return ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
|
||||
}
|
||||
|
||||
// 检查是否只有归约模式
|
||||
bool hasReduction = false;
|
||||
bool hasOtherDependences = false;
|
||||
|
||||
for (const auto& dep : dependences) {
|
||||
if (dep.isReductionDependence) {
|
||||
hasReduction = true;
|
||||
} else if (dep.type == DependenceType::TRUE_DEPENDENCE) {
|
||||
hasOtherDependences = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasReduction && !hasOtherDependences) {
|
||||
return ParallelizationAnalysis::REDUCTION_PARALLEL;
|
||||
} else if (!hasOtherDependences) {
|
||||
return ParallelizationAnalysis::EMBARRASSINGLY_PARALLEL;
|
||||
}
|
||||
|
||||
return ParallelizationAnalysis::NONE;
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::analyzeReductionPatterns(Loop* loop, ParallelizationAnalysis* analysis) {
|
||||
// 简化实现:查找常见的归约模式
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* binInst = dynamic_cast<BinaryInst*>(inst.get())) {
|
||||
if (binInst->getKind() == Instruction::kAdd || binInst->getKind() == Instruction::kMul) {
|
||||
// 检查是否为累加/累乘模式
|
||||
Value* lhs = binInst->getLhs();
|
||||
if (hasReductionPattern(lhs, loop)) {
|
||||
analysis->requiresReduction = true;
|
||||
analysis->reductionVariables.insert(lhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::analyzeMemoryAccessPatterns(Loop* loop, ParallelizationAnalysis* analysis,
|
||||
AliasAnalysisResult* aliasAnalysis) {
|
||||
std::vector<Value*> memoryAccesses;
|
||||
|
||||
// 收集所有内存访问
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (auto* load = dynamic_cast<LoadInst*>(inst.get())) {
|
||||
memoryAccesses.push_back(load->getPointer());
|
||||
} else if (auto* store = dynamic_cast<StoreInst*>(inst.get())) {
|
||||
memoryAccesses.push_back(store->getPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分析内存访问独立性
|
||||
bool hasIndependentAccess = true;
|
||||
for (size_t i = 0; i < memoryAccesses.size(); ++i) {
|
||||
for (size_t j = i + 1; j < memoryAccesses.size(); ++j) {
|
||||
if (!isIndependentMemoryAccess(memoryAccesses[i], memoryAccesses[j], loop)) {
|
||||
hasIndependentAccess = false;
|
||||
analysis->hasMemoryConflicts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analysis->hasIndependentAccess = hasIndependentAccess;
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::estimateParallelizationBenefit(Loop* loop, ParallelizationAnalysis* analysis,
|
||||
LoopCharacteristics* characteristics) {
|
||||
if (!analysis->isParallelizable) {
|
||||
analysis->parallelizationBenefit = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 基于计算复杂度和并行度计算收益
|
||||
double workComplexity = estimateWorkComplexity(loop);
|
||||
double parallelFraction = 1.0; // 假设完全可并行
|
||||
|
||||
// 根据依赖调整并行度
|
||||
if (analysis->requiresReduction) {
|
||||
parallelFraction *= 0.8; // 归约降低并行效率
|
||||
}
|
||||
if (analysis->hasMemoryConflicts) {
|
||||
parallelFraction *= 0.6; // 内存冲突降低效率
|
||||
}
|
||||
|
||||
// Amdahl定律估算
|
||||
double serialFraction = 1.0 - parallelFraction;
|
||||
int threadCount = analysis->suggestedThreadCount;
|
||||
double speedup = 1.0 / (serialFraction + parallelFraction / threadCount);
|
||||
|
||||
analysis->parallelizationBenefit = std::min((speedup - 1.0) / threadCount, 1.0);
|
||||
|
||||
// 估算同步和通信开销
|
||||
analysis->synchronizationCost = analysis->requiresBarrier ? 100 : 0;
|
||||
analysis->communicationCost = analysis->sharedVariables.size() * 50;
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::identifyPrivatizableVariables(Loop* loop, ParallelizationAnalysis* analysis) {
|
||||
// 简化实现:标识循环内定义的变量为可私有化
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
if (!inst->getType()->isVoid()) {
|
||||
// 如果变量只在循环内使用,可能可以私有化
|
||||
bool onlyUsedInLoop = true;
|
||||
for (auto& use : inst->getUses()) {
|
||||
if (auto* userInst = dynamic_cast<Instruction*>(use->getUser())) {
|
||||
if (!loop->contains(userInst->getParent())) {
|
||||
onlyUsedInLoop = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (onlyUsedInLoop) {
|
||||
analysis->privatizableVariables.insert(inst.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoopVectorizationPass::analyzeSynchronizationNeeds(Loop* loop, ParallelizationAnalysis* analysis,
|
||||
const std::vector<PreciseDependence>& dependences) {
|
||||
// 根据依赖类型确定同步需求
|
||||
for (const auto& dep : dependences) {
|
||||
if (dep.type == DependenceType::OUTPUT_DEPENDENCE) {
|
||||
analysis->requiresBarrier = true;
|
||||
analysis->sharedVariables.insert(dep.memoryLocation);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有归约,需要特殊的归约同步
|
||||
if (analysis->requiresReduction) {
|
||||
analysis->requiresBarrier = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool LoopVectorizationPass::isIndependentMemoryAccess(Value* ptr1, Value* ptr2, Loop* loop) {
|
||||
// 简化实现:基本的独立性检查
|
||||
if (ptr1 == ptr2) return false;
|
||||
|
||||
// 如果是不同的基址,认为是独立的
|
||||
auto* gep1 = dynamic_cast<GetElementPtrInst*>(ptr1);
|
||||
auto* gep2 = dynamic_cast<GetElementPtrInst*>(ptr2);
|
||||
|
||||
if (gep1 && gep2) {
|
||||
if (gep1->getBasePointer() != gep2->getBasePointer()) {
|
||||
return true; // 不同的基址
|
||||
}
|
||||
// 相同基址,需要更精细的分析(这里简化为不独立)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // 默认认为独立
|
||||
}
|
||||
|
||||
double LoopVectorizationPass::estimateWorkComplexity(Loop* loop) {
|
||||
double complexity = 0.0;
|
||||
|
||||
for (BasicBlock* bb : loop->getBlocks()) {
|
||||
for (auto& inst : bb->getInstructions()) {
|
||||
// 基于指令类型分配复杂度权重
|
||||
if (auto* binInst = dynamic_cast<BinaryInst*>(inst.get())) {
|
||||
switch (binInst->getKind()) {
|
||||
case Instruction::kAdd:
|
||||
case Instruction::kSub:
|
||||
complexity += 1.0;
|
||||
break;
|
||||
case Instruction::kMul:
|
||||
complexity += 3.0;
|
||||
break;
|
||||
case Instruction::kDiv:
|
||||
complexity += 10.0;
|
||||
break;
|
||||
default:
|
||||
complexity += 2.0;
|
||||
}
|
||||
} else if (dynamic_cast<LoadInst*>(inst.get()) || dynamic_cast<StoreInst*>(inst.get())) {
|
||||
complexity += 2.0; // 内存访问
|
||||
} else {
|
||||
complexity += 1.0; // 其他指令
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return complexity;
|
||||
}
|
||||
|
||||
bool LoopVectorizationPass::hasReductionPattern(Value* var, Loop* loop) {
|
||||
// 简化实现:检查是否为简单的累加/累乘模式
|
||||
for (auto& use : var->getUses()) {
|
||||
if (auto* binInst = dynamic_cast<BinaryInst*>(use->getUser())) {
|
||||
if (binInst->getKind() == Instruction::kAdd || binInst->getKind() == Instruction::kMul) {
|
||||
// 检查是否为 var = var op something 的模式
|
||||
if (binInst->getLhs() == var || binInst->getRhs() == var) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
402
src/midend/Pass/Analysis/SideEffectAnalysis.cpp
Normal file
402
src/midend/Pass/Analysis/SideEffectAnalysis.cpp
Normal file
@ -0,0 +1,402 @@
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "CallGraphAnalysis.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::runOnModule(Module *M, AnalysisManager &AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running SideEffect analysis on module" << std::endl;
|
||||
}
|
||||
|
||||
// 创建分析结果(构造函数中已经调用了initializeKnownFunctions)
|
||||
result = std::make_unique<SideEffectAnalysisResult>();
|
||||
|
||||
// 获取调用图分析结果
|
||||
callGraphAnalysis = AM.getAnalysisResult<CallGraphAnalysisResult, CallGraphAnalysisPass>();
|
||||
if (!callGraphAnalysis) {
|
||||
std::cerr << "Warning: CallGraphAnalysis not available, falling back to conservative analysis" << std::endl;
|
||||
}
|
||||
|
||||
// 按拓扑序分析函数,确保被调用函数先于调用者分析
|
||||
if (callGraphAnalysis) {
|
||||
// 使用调用图的拓扑排序结果
|
||||
const auto &topOrder = callGraphAnalysis->getTopologicalOrder();
|
||||
|
||||
// 处理强连通分量(递归函数群)
|
||||
const auto &sccs = callGraphAnalysis->getStronglyConnectedComponents();
|
||||
for (const auto &scc : sccs) {
|
||||
if (scc.size() > 1) {
|
||||
// 多个函数的强连通分量,使用不动点算法
|
||||
analyzeStronglyConnectedComponent(scc, AM);
|
||||
} else {
|
||||
// 单个函数,检查是否自递归
|
||||
Function *func = scc[0];
|
||||
if (callGraphAnalysis->isSelfRecursive(func)) {
|
||||
// 自递归函数也需要不动点算法
|
||||
analyzeStronglyConnectedComponent(scc, AM);
|
||||
} else {
|
||||
// 非递归函数,直接分析
|
||||
SideEffectInfo funcEffect = analyzeFunction(func, AM);
|
||||
result->setFunctionSideEffect(func, funcEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有调用图,保守地分析每个函数
|
||||
for (auto &pair : M->getFunctions()) {
|
||||
Function *func = pair.second.get();
|
||||
SideEffectInfo funcEffect = analyzeFunction(func, AM);
|
||||
result->setFunctionSideEffect(func, funcEffect);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "---- Side Effect Analysis Results for Module ----\n";
|
||||
for (auto &pair : M->getFunctions()) {
|
||||
Function *func = pair.second.get();
|
||||
const auto &funcInfo = result->getFunctionSideEffect(func);
|
||||
|
||||
std::cout << "Function " << func->getName() << ": ";
|
||||
switch (funcInfo.type) {
|
||||
case SideEffectType::NO_SIDE_EFFECT:
|
||||
std::cout << "No Side Effect";
|
||||
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 << " (Pure: " << (funcInfo.isPure ? "Yes" : "No")
|
||||
<< ", Modifies Global: " << (funcInfo.mayModifyGlobal ? "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::analyzeFunction(Function *func, AnalysisManager &AM) {
|
||||
SideEffectInfo functionSideEffect;
|
||||
|
||||
// 为每个指令分析副作用
|
||||
for (auto &BB : func->getBasicBlocks()) {
|
||||
for (auto &I : BB->getInstructions_Range()) {
|
||||
Instruction *inst = I.get();
|
||||
SideEffectInfo instEffect = analyzeInstruction(inst, func, AM);
|
||||
|
||||
// 记录指令的副作用信息
|
||||
result->setInstructionSideEffect(inst, instEffect);
|
||||
|
||||
// 合并到函数级别的副作用信息中
|
||||
functionSideEffect = functionSideEffect.merge(instEffect);
|
||||
}
|
||||
}
|
||||
|
||||
return functionSideEffect;
|
||||
}
|
||||
|
||||
void SysYSideEffectAnalysisPass::analyzeStronglyConnectedComponent(const std::vector<Function *> &scc,
|
||||
AnalysisManager &AM) {
|
||||
// 使用不动点算法处理递归函数群
|
||||
std::unordered_map<Function *, SideEffectInfo> currentEffects;
|
||||
std::unordered_map<Function *, SideEffectInfo> previousEffects;
|
||||
|
||||
// 初始化:所有函数都假设为纯函数
|
||||
for (Function *func : scc) {
|
||||
SideEffectInfo initialEffect;
|
||||
initialEffect.isPure = true;
|
||||
currentEffects[func] = initialEffect;
|
||||
result->setFunctionSideEffect(func, initialEffect);
|
||||
}
|
||||
|
||||
bool converged = false;
|
||||
int iterations = 0;
|
||||
const int maxIterations = 10; // 防止无限循环
|
||||
|
||||
while (!converged && iterations < maxIterations) {
|
||||
previousEffects = currentEffects;
|
||||
|
||||
// 重新分析每个函数
|
||||
for (Function *func : scc) {
|
||||
SideEffectInfo newEffect = analyzeFunction(func, AM);
|
||||
currentEffects[func] = newEffect;
|
||||
result->setFunctionSideEffect(func, newEffect);
|
||||
}
|
||||
|
||||
// 检查是否收敛
|
||||
converged = hasConverged(previousEffects, currentEffects);
|
||||
iterations++;
|
||||
}
|
||||
|
||||
if (iterations >= maxIterations) {
|
||||
std::cerr << "Warning: SideEffect analysis did not converge for SCC after " << maxIterations << " iterations"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool SysYSideEffectAnalysisPass::hasConverged(const std::unordered_map<Function *, SideEffectInfo> &oldEffects,
|
||||
const std::unordered_map<Function *, SideEffectInfo> &newEffects) const {
|
||||
for (const auto &pair : oldEffects) {
|
||||
Function *func = pair.first;
|
||||
const SideEffectInfo &oldEffect = pair.second;
|
||||
|
||||
auto it = newEffects.find(func);
|
||||
if (it == newEffects.end()) {
|
||||
return false; // 函数不存在于新结果中
|
||||
}
|
||||
|
||||
const SideEffectInfo &newEffect = it->second;
|
||||
|
||||
// 比较关键属性是否相同
|
||||
if (oldEffect.type != newEffect.type || oldEffect.mayModifyGlobal != newEffect.mayModifyGlobal ||
|
||||
oldEffect.mayModifyMemory != newEffect.mayModifyMemory ||
|
||||
oldEffect.mayCallFunction != newEffect.mayCallFunction || oldEffect.isPure != newEffect.isPure) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeInstruction(Instruction *inst, Function *currentFunc,
|
||||
AnalysisManager &AM) {
|
||||
SideEffectInfo info;
|
||||
|
||||
// 根据指令类型进行分析
|
||||
if (inst->isCall()) {
|
||||
return analyzeCallInstruction(static_cast<CallInst *>(inst), currentFunc, AM);
|
||||
} else if (inst->isStore()) {
|
||||
return analyzeStoreInstruction(static_cast<StoreInst *>(inst), currentFunc, AM);
|
||||
} else if (inst->isMemset()) {
|
||||
return analyzeMemsetInstruction(static_cast<MemsetInst *>(inst), currentFunc, 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, Function *currentFunc,
|
||||
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;
|
||||
}
|
||||
|
||||
// 利用调用图分析结果进行精确分析
|
||||
if (callGraphAnalysis) {
|
||||
// 检查被调用函数是否已分析过
|
||||
const SideEffectInfo &funcEffect = result->getFunctionSideEffect(calledFunc);
|
||||
if (funcEffect.type != SideEffectType::NO_SIDE_EFFECT || !funcEffect.isPure) {
|
||||
return funcEffect;
|
||||
}
|
||||
|
||||
// 检查递归调用
|
||||
if (callGraphAnalysis->isRecursive(calledFunc)) {
|
||||
// 递归函数保守处理(在不动点算法中会精确分析)
|
||||
info.type = SideEffectType::FUNCTION_CALL;
|
||||
info.mayModifyGlobal = true;
|
||||
info.mayModifyMemory = true;
|
||||
info.mayCallFunction = true;
|
||||
info.isPure = false;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
// 对于未分析的用户函数,保守处理
|
||||
info.type = SideEffectType::FUNCTION_CALL;
|
||||
info.mayModifyGlobal = true;
|
||||
info.mayModifyMemory = true;
|
||||
info.mayCallFunction = true;
|
||||
info.isPure = false;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeStoreInstruction(StoreInst *store, Function *currentFunc,
|
||||
AnalysisManager &AM) {
|
||||
SideEffectInfo info;
|
||||
info.type = SideEffectType::MEMORY_WRITE;
|
||||
info.mayModifyMemory = true;
|
||||
info.isPure = false;
|
||||
|
||||
// 获取函数的别名分析结果
|
||||
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(currentFunc);
|
||||
if (aliasAnalysis) {
|
||||
Value *storePtr = store->getPointer();
|
||||
|
||||
// 如果存储到全局变量或可能别名的位置,则可能修改全局状态
|
||||
if (!aliasAnalysis->isLocalArray(storePtr)) {
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
} else {
|
||||
// 没有别名分析结果,保守处理
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
SideEffectInfo SysYSideEffectAnalysisPass::analyzeMemsetInstruction(MemsetInst *memset, Function *currentFunc,
|
||||
AnalysisManager &AM) {
|
||||
SideEffectInfo info;
|
||||
info.type = SideEffectType::MEMORY_WRITE;
|
||||
info.mayModifyMemory = true;
|
||||
info.isPure = false;
|
||||
|
||||
// 获取函数的别名分析结果
|
||||
AliasAnalysisResult *aliasAnalysis = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(currentFunc);
|
||||
if (aliasAnalysis) {
|
||||
Value *memsetPtr = memset->getPointer();
|
||||
|
||||
// 如果memset操作全局变量或可能别名的位置,则可能修改全局状态
|
||||
if (!aliasAnalysis->isLocalArray(memsetPtr)) {
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
} else {
|
||||
// 没有别名分析结果,保守处理
|
||||
info.mayModifyGlobal = true;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
@ -1,9 +1,9 @@
|
||||
#include "DCE.h" // 包含DCE遍的头文件
|
||||
#include "IR.h" // 包含IR相关的定义
|
||||
#include "SysYIROptUtils.h" // 包含SysY IR优化工具类的定义
|
||||
#include <cassert> // 用于断言
|
||||
#include <iostream> // 用于调试输出
|
||||
#include <set> // 包含set,虽然DCEContext内部用unordered_set,但这里保留
|
||||
#include "DCE.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@ -17,10 +17,26 @@ void *DCE::ID = (void *)&DCE::ID;
|
||||
|
||||
// DCEContext 的 run 方法实现
|
||||
void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
|
||||
// 获取别名分析结果
|
||||
if (AM) {
|
||||
aliasAnalysis = AM->getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(func);
|
||||
// 获取副作用分析结果(Module级别)
|
||||
sideEffectAnalysis = AM->getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||||
|
||||
if (DEBUG) {
|
||||
if (aliasAnalysis) {
|
||||
std::cout << "DCE: Using alias analysis results" << std::endl;
|
||||
}
|
||||
if (sideEffectAnalysis) {
|
||||
std::cout << "DCE: Using side effect analysis results" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清空活跃指令集合,确保每次运行都是新的状态
|
||||
alive_insts.clear();
|
||||
|
||||
// 第一次遍历:扫描所有指令,识别“天然活跃”的指令并将其及其依赖标记为活跃
|
||||
// 第一次遍历:扫描所有指令,识别"天然活跃"的指令并将其及其依赖标记为活跃
|
||||
// 使用 func->getBasicBlocks() 获取基本块列表,保留用户风格
|
||||
auto basicBlocks = func->getBasicBlocks();
|
||||
for (auto &basicBlock : basicBlocks) {
|
||||
@ -51,7 +67,7 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
|
||||
// 如果指令不在活跃集合中,则删除它。
|
||||
// 分支和返回指令由 isAlive 处理,并会被保留。
|
||||
if (alive_insts.count(currentInst) == 0) {
|
||||
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
|
||||
instIter = SysYIROptUtils::usedelete(instIter); // 删除后返回下一个迭代器
|
||||
changed = true; // 标记 IR 已被修改
|
||||
} else {
|
||||
++instIter; // 指令活跃,移动到下一个
|
||||
@ -60,20 +76,58 @@ void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
|
||||
}
|
||||
}
|
||||
|
||||
// 判断指令是否是“天然活跃”的实现
|
||||
// 判断指令是否是"天然活跃"的实现
|
||||
// 只有具有副作用的指令(如存储、函数调用、原子操作)
|
||||
// 和控制流指令(如分支、返回)是天然活跃的。
|
||||
bool DCEContext::isAlive(Instruction *inst) {
|
||||
// TODO: 后续程序并发考虑原子操作
|
||||
// 其结果不被其他指令使用的指令(例如 StoreInst, BranchInst, ReturnInst)。
|
||||
// dynamic_cast<ir::CallInst>(inst) 检查是否是函数调用指令,
|
||||
// 函数调用通常有副作用。
|
||||
// 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程。
|
||||
// 保留用户提供的 isAlive 逻辑
|
||||
bool isBranchOrReturn = inst->isBranch() || inst->isReturn();
|
||||
bool isCall = inst->isCall();
|
||||
bool isStoreOrMemset = inst->isStore() || inst->isMemset();
|
||||
return isBranchOrReturn || isCall || isStoreOrMemset;
|
||||
// 终止指令 (BranchInst, ReturnInst) 必须是活跃的,因为它控制了程序的执行流程
|
||||
if (inst->isBranch() || inst->isReturn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 使用副作用分析来判断指令是否有副作用
|
||||
if (sideEffectAnalysis && sideEffectAnalysis->hasSideEffect(inst)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 特殊处理Store指令:使用别名分析进行更精确的判断
|
||||
if (inst->isStore()) {
|
||||
auto* storeInst = static_cast<StoreInst*>(inst);
|
||||
return mayHaveSideEffect(storeInst);
|
||||
}
|
||||
|
||||
// 特殊处理Memset指令:总是保留(因为它修改内存)
|
||||
if (inst->isMemset()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 函数调用指令:总是保留(可能有未知副作用)
|
||||
if (inst->isCall()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 其他指令(算术、逻辑、Load等):无副作用,可以删除
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查Store指令是否可能有副作用(通过别名分析)
|
||||
bool DCEContext::mayHaveSideEffect(StoreInst* store) {
|
||||
if (!aliasAnalysis) {
|
||||
// 没有别名分析结果时,保守地认为所有store都有副作用
|
||||
return true;
|
||||
}
|
||||
|
||||
Value* storePtr = store->getPointer();
|
||||
|
||||
// 如果是对本地数组的存储且访问模式是常量,可能可以安全删除
|
||||
if (aliasAnalysis->isLocalArray(storePtr)) {
|
||||
// 检查是否有其他指令可能读取这个位置
|
||||
// 这里需要更复杂的活性分析,暂时保守处理
|
||||
return true; // 保守地保留所有本地数组的存储
|
||||
}
|
||||
|
||||
// 对全局变量、函数参数等的存储总是有副作用
|
||||
return true;
|
||||
}
|
||||
|
||||
// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
|
||||
@ -102,7 +156,6 @@ void DCEContext::addAlive(Instruction *inst) {
|
||||
|
||||
// DCE 遍的 runOnFunction 方法实现
|
||||
bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {
|
||||
|
||||
DCEContext ctx;
|
||||
bool changed = false;
|
||||
ctx.run(func, &AM, changed); // 运行 DCE 优化
|
||||
@ -120,7 +173,11 @@ bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {
|
||||
|
||||
// 声明DCE遍的分析依赖和失效信息
|
||||
void DCE::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||
// DCE不依赖特定的分析结果,它通过遍历和副作用判断来工作。
|
||||
// DCE依赖别名分析来更精确地判断Store指令的副作用
|
||||
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
|
||||
|
||||
// DCE依赖副作用分析来判断指令是否有副作用
|
||||
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
|
||||
|
||||
// DCE会删除指令,这会影响许多分析结果。
|
||||
// 至少,它会影响活跃性分析、支配树、控制流图(如果删除导致基本块为空并被合并)。
|
||||
|
||||
433
src/midend/Pass/Optimize/InductionVariableElimination.cpp
Normal file
433
src/midend/Pass/Optimize/InductionVariableElimination.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
#include "InductionVariableElimination.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "Loop.h"
|
||||
#include "Dom.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
// 使用全局调试开关
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 定义 Pass 的唯一 ID
|
||||
void *InductionVariableElimination::ID = (void *)&InductionVariableElimination::ID;
|
||||
|
||||
bool InductionVariableElimination::runOnFunction(Function* F, AnalysisManager& AM) {
|
||||
if (F->getBasicBlocks().empty()) {
|
||||
return false; // 空函数
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "Running InductionVariableElimination on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 创建优化上下文并运行
|
||||
InductionVariableEliminationContext context;
|
||||
bool modified = context.run(F, AM);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "InductionVariableElimination " << (modified ? "modified" : "did not modify")
|
||||
<< " function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
void InductionVariableElimination::getAnalysisUsage(std::set<void*>& analysisDependencies,
|
||||
std::set<void*>& analysisInvalidations) const {
|
||||
// 依赖的分析
|
||||
analysisDependencies.insert(&LoopAnalysisPass::ID);
|
||||
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
|
||||
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID);
|
||||
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
|
||||
|
||||
// 会使失效的分析(归纳变量消除会修改IR结构)
|
||||
analysisInvalidations.insert(&LoopCharacteristicsPass::ID);
|
||||
// 注意:支配树分析通常不会因为归纳变量消除而失效,因为我们不改变控制流
|
||||
}
|
||||
|
||||
// ========== InductionVariableEliminationContext 实现 ==========
|
||||
|
||||
bool InductionVariableEliminationContext::run(Function* F, AnalysisManager& AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Starting induction variable elimination analysis..." << std::endl;
|
||||
}
|
||||
|
||||
// 获取必要的分析结果
|
||||
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
|
||||
if (DEBUG) {
|
||||
std::cout << " No loops found, skipping induction variable elimination" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
loopCharacteristics = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
|
||||
if (!loopCharacteristics) {
|
||||
if (DEBUG) {
|
||||
std::cout << " LoopCharacteristics analysis not available" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
dominatorTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
|
||||
if (!dominatorTree) {
|
||||
if (DEBUG) {
|
||||
std::cout << " DominatorTree analysis not available" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
sideEffectAnalysis = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>();
|
||||
if (!sideEffectAnalysis) {
|
||||
if (DEBUG) {
|
||||
std::cout << " SideEffectAnalysis not available, using conservative approach" << std::endl;
|
||||
}
|
||||
// 可以继续执行,但会使用更保守的策略
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
std::cout << " Using SideEffectAnalysis for safety checks" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行三个阶段的优化
|
||||
|
||||
// 阶段1:识别死归纳变量
|
||||
identifyDeadInductionVariables(F);
|
||||
|
||||
if (deadIVs.empty()) {
|
||||
if (DEBUG) {
|
||||
std::cout << " No dead induction variables found" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Found " << deadIVs.size() << " potentially dead induction variables" << std::endl;
|
||||
}
|
||||
|
||||
// 阶段2:分析安全性
|
||||
analyzeSafetyForElimination();
|
||||
|
||||
// 阶段3:执行消除
|
||||
bool modified = performInductionVariableElimination();
|
||||
|
||||
if (DEBUG) {
|
||||
printDebugInfo();
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
void InductionVariableEliminationContext::identifyDeadInductionVariables(Function* F) {
|
||||
if (DEBUG) {
|
||||
std::cout << " === Phase 1: Identifying Dead Induction Variables ===" << std::endl;
|
||||
}
|
||||
|
||||
// 遍历所有循环
|
||||
for (const auto& loop_ptr : loopAnalysis->getAllLoops()) {
|
||||
Loop* loop = loop_ptr.get();
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Analyzing loop: " << loop->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 获取循环特征
|
||||
const LoopCharacteristics* characteristics = loopCharacteristics->getCharacteristics(loop);
|
||||
if (!characteristics) {
|
||||
if (DEBUG) {
|
||||
std::cout << " No characteristics available for loop" << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (characteristics->InductionVars.empty()) {
|
||||
if (DEBUG) {
|
||||
std::cout << " No induction variables found in loop" << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查每个归纳变量是否为死归纳变量
|
||||
for (const auto& iv : characteristics->InductionVars) {
|
||||
auto deadIV = isDeadInductionVariable(iv.get(), loop);
|
||||
if (deadIV) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Found potential dead IV: %" << deadIV->phiInst->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 添加到候选项列表
|
||||
loopToDeadIVs[loop].push_back(deadIV.get());
|
||||
deadIVs.push_back(std::move(deadIV));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " === End Phase 1: Found " << deadIVs.size() << " candidates ===" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<DeadInductionVariable>
|
||||
InductionVariableEliminationContext::isDeadInductionVariable(const InductionVarInfo* iv, Loop* loop) {
|
||||
// 获取 phi 指令
|
||||
auto* phiInst = dynamic_cast<PhiInst*>(iv->div);
|
||||
if (!phiInst) {
|
||||
return nullptr; // 不是 phi 指令
|
||||
}
|
||||
|
||||
// 检查是否只用于自身更新
|
||||
if (!isUsedOnlyForSelfUpdate(phiInst, loop)) {
|
||||
return nullptr; // 有其他用途
|
||||
}
|
||||
|
||||
// 创建死归纳变量信息
|
||||
auto deadIV = std::make_unique<DeadInductionVariable>(phiInst, loop);
|
||||
deadIV->relatedInsts = collectRelatedInstructions(phiInst, loop);
|
||||
|
||||
return deadIV;
|
||||
}
|
||||
|
||||
bool InductionVariableEliminationContext::isUsedOnlyForSelfUpdate(PhiInst* phiInst, Loop* loop) {
|
||||
// 检查 phi 指令的所有使用
|
||||
for (auto use : phiInst->getUses()) {
|
||||
auto user = use->getUser();
|
||||
auto* userInst = dynamic_cast<Instruction*>(user);
|
||||
|
||||
if (!userInst) {
|
||||
return false; // 被非指令使用
|
||||
}
|
||||
|
||||
// 检查使用是否在循环内
|
||||
if (!loop->contains(userInst->getParent())) {
|
||||
return false; // 在循环外被使用
|
||||
}
|
||||
|
||||
// 检查是否为自身的更新指令
|
||||
bool isSelfUpdate = false;
|
||||
|
||||
// 检查是否为加法/减法指令(常见的归纳变量更新模式)
|
||||
if (userInst->getKind() == Instruction::Kind::kAdd ||
|
||||
userInst->getKind() == Instruction::Kind::kSub) {
|
||||
auto* binInst = dynamic_cast<BinaryInst*>(userInst);
|
||||
if (binInst && (binInst->getOperand(0) == phiInst || binInst->getOperand(1) == phiInst)) {
|
||||
// 检查这个指令的结果是否流回到 phi
|
||||
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
||||
if (loop->contains(incomingBB) && incomingVal == binInst) {
|
||||
isSelfUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSelfUpdate) {
|
||||
return false; // 有非自更新的使用
|
||||
}
|
||||
}
|
||||
|
||||
return true; // 只用于自身更新
|
||||
}
|
||||
|
||||
std::vector<Instruction*> InductionVariableEliminationContext::collectRelatedInstructions(
|
||||
PhiInst* phiInst, Loop* loop) {
|
||||
std::vector<Instruction*> relatedInsts;
|
||||
|
||||
// 收集所有与该归纳变量相关的指令
|
||||
for (auto use : phiInst->getUses()) {
|
||||
auto user = use->getUser();
|
||||
auto* userInst = dynamic_cast<Instruction*>(user);
|
||||
|
||||
if (userInst && loop->contains(userInst->getParent())) {
|
||||
relatedInsts.push_back(userInst);
|
||||
}
|
||||
}
|
||||
|
||||
return relatedInsts;
|
||||
}
|
||||
|
||||
void InductionVariableEliminationContext::analyzeSafetyForElimination() {
|
||||
if (DEBUG) {
|
||||
std::cout << " === Phase 2: Analyzing Safety for Elimination ===" << std::endl;
|
||||
}
|
||||
|
||||
// 为每个死归纳变量检查消除的安全性
|
||||
for (auto& deadIV : deadIVs) {
|
||||
bool isSafe = isSafeToEliminate(deadIV.get());
|
||||
deadIV->canEliminate = isSafe;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Dead IV " << deadIV->phiInst->getName()
|
||||
<< ": " << (isSafe ? "SAFE" : "UNSAFE") << " to eliminate" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
size_t safeCount = 0;
|
||||
for (const auto& deadIV : deadIVs) {
|
||||
if (deadIV->canEliminate) safeCount++;
|
||||
}
|
||||
std::cout << " === End Phase 2: " << safeCount << " of " << deadIVs.size()
|
||||
<< " variables are safe to eliminate ===" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool InductionVariableEliminationContext::isSafeToEliminate(const DeadInductionVariable* deadIV) {
|
||||
// 1. 确保归纳变量在循环头
|
||||
if (deadIV->phiInst->getParent() != deadIV->containingLoop->getHeader()) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Unsafe: phi not in loop header" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 确保相关指令都在循环内
|
||||
for (auto* inst : deadIV->relatedInsts) {
|
||||
if (!deadIV->containingLoop->contains(inst->getParent())) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Unsafe: related instruction outside loop" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 确保没有副作用
|
||||
for (auto* inst : deadIV->relatedInsts) {
|
||||
if (sideEffectAnalysis) {
|
||||
// 使用副作用分析进行精确检查
|
||||
if (sideEffectAnalysis->hasSideEffect(inst)) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Unsafe: related instruction " << inst->getName()
|
||||
<< " has side effects" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// 没有副作用分析时使用保守策略:只允许基本算术运算
|
||||
auto kind = inst->getKind();
|
||||
if (kind != Instruction::Kind::kAdd &&
|
||||
kind != Instruction::Kind::kSub &&
|
||||
kind != Instruction::Kind::kMul) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Unsafe: related instruction may have side effects (conservative)" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 确保不影响循环的退出条件
|
||||
for (BasicBlock* exitingBB : deadIV->containingLoop->getExitingBlocks()) {
|
||||
auto terminatorIt = exitingBB->terminator();
|
||||
if (terminatorIt != exitingBB->end()) {
|
||||
Instruction* terminator = terminatorIt->get();
|
||||
if (terminator) {
|
||||
for (size_t i = 0; i < terminator->getNumOperands(); ++i) {
|
||||
if (terminator->getOperand(i) == deadIV->phiInst) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Unsafe: phi used in loop exit condition" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InductionVariableEliminationContext::performInductionVariableElimination() {
|
||||
if (DEBUG) {
|
||||
std::cout << " === Phase 3: Performing Induction Variable Elimination ===" << std::endl;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
|
||||
for (auto& deadIV : deadIVs) {
|
||||
if (!deadIV->canEliminate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Eliminating dead IV: " << deadIV->phiInst->getName() << std::endl;
|
||||
}
|
||||
|
||||
if (eliminateDeadInductionVariable(deadIV.get())) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Successfully eliminated: " << deadIV->phiInst->getName() << std::endl;
|
||||
}
|
||||
modified = true;
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
std::cout << " Failed to eliminate: " << deadIV->phiInst->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " === End Phase 3: " << (modified ? "Eliminations performed" : "No eliminations") << " ===" << std::endl;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool InductionVariableEliminationContext::eliminateDeadInductionVariable(DeadInductionVariable* deadIV) {
|
||||
// 1. 删除所有相关指令
|
||||
for (auto* inst : deadIV->relatedInsts) {
|
||||
auto* bb = inst->getParent();
|
||||
auto it = bb->findInstIterator(inst);
|
||||
if (it != bb->end()) {
|
||||
SysYIROptUtils::usedelete(it);
|
||||
// bb->getInstructions().erase(it);
|
||||
if (DEBUG) {
|
||||
std::cout << " Removed related instruction: " << inst->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 删除 phi 指令
|
||||
auto* bb = deadIV->phiInst->getParent();
|
||||
auto it = bb->findInstIterator(deadIV->phiInst);
|
||||
if (it != bb->end()) {
|
||||
SysYIROptUtils::usedelete(it);
|
||||
// bb->getInstructions().erase(it);
|
||||
if (DEBUG) {
|
||||
std::cout << " Removed phi instruction: " << deadIV->phiInst->getName() << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InductionVariableEliminationContext::printDebugInfo() {
|
||||
if (!DEBUG) return;
|
||||
|
||||
std::cout << "\n=== Induction Variable Elimination Summary ===" << std::endl;
|
||||
std::cout << "Total dead IVs found: " << deadIVs.size() << std::endl;
|
||||
|
||||
size_t eliminatedCount = 0;
|
||||
for (auto& [loop, loopDeadIVs] : loopToDeadIVs) {
|
||||
size_t loopEliminatedCount = 0;
|
||||
for (auto* deadIV : loopDeadIVs) {
|
||||
if (deadIV->canEliminate) {
|
||||
loopEliminatedCount++;
|
||||
eliminatedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (loopEliminatedCount > 0) {
|
||||
std::cout << "Loop " << loop->getName() << ": " << loopEliminatedCount
|
||||
<< " of " << loopDeadIVs.size() << " IVs eliminated" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Total eliminated: " << eliminatedCount << " of " << deadIVs.size() << std::endl;
|
||||
std::cout << "=============================================" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
112
src/midend/Pass/Optimize/LICM.cpp
Normal file
112
src/midend/Pass/Optimize/LICM.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "LICM.h"
|
||||
#include "IR.h"
|
||||
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
void *LICM::ID = (void *)&LICM::ID;
|
||||
|
||||
bool LICMContext::run() { return hoistInstructions(); }
|
||||
|
||||
bool LICMContext::hoistInstructions() {
|
||||
bool changed = false;
|
||||
BasicBlock *preheader = loop->getPreHeader();
|
||||
if (!preheader || !chars)
|
||||
return false;
|
||||
|
||||
// 1. 先收集所有可外提指令
|
||||
std::unordered_set<Instruction *> workSet(chars->invariantInsts.begin(), chars->invariantInsts.end());
|
||||
|
||||
// 2. 计算每个指令被依赖的次数(入度)
|
||||
std::unordered_map<Instruction *, int> indegree;
|
||||
for (auto *inst : workSet) {
|
||||
indegree[inst] = 0;
|
||||
}
|
||||
for (auto *inst : workSet) {
|
||||
for (size_t i = 0; i < inst->getNumOperands(); ++i) {
|
||||
if (auto *dep = dynamic_cast<Instruction *>(inst->getOperand(i))) {
|
||||
if (workSet.count(dep)) {
|
||||
indegree[inst]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Kahn拓扑排序
|
||||
std::vector<Instruction *> sorted;
|
||||
std::queue<Instruction *> q;
|
||||
for (auto &[inst, deg] : indegree) {
|
||||
if (deg == 0)
|
||||
q.push(inst);
|
||||
}
|
||||
while (!q.empty()) {
|
||||
auto *inst = q.front();
|
||||
q.pop();
|
||||
sorted.push_back(inst);
|
||||
for (size_t i = 0; i < inst->getNumOperands(); ++i) {
|
||||
if (auto *dep = dynamic_cast<Instruction *>(inst->getOperand(i))) {
|
||||
if (workSet.count(dep)) {
|
||||
indegree[dep]--;
|
||||
if (indegree[dep] == 0)
|
||||
q.push(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否全部排序,若未全部排序,说明有环(理论上不会)
|
||||
if (sorted.size() != workSet.size()) {
|
||||
if (DEBUG)
|
||||
std::cerr << "LICM: Topological sort failed, possible dependency cycle." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 按拓扑序外提
|
||||
for (auto *inst : sorted) {
|
||||
if (!inst)
|
||||
continue;
|
||||
BasicBlock *parent = inst->getParent();
|
||||
if (parent && loop->contains(parent)) {
|
||||
auto sourcePos = parent->findInstIterator(inst);
|
||||
auto targetPos = preheader->terminator();
|
||||
parent->moveInst(sourcePos, targetPos, preheader);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
// ---- LICM Pass Implementation ----
|
||||
|
||||
bool LICM::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
auto *loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
auto *loopCharsResult = AM.getAnalysisResult<LoopCharacteristicsResult, LoopCharacteristicsPass>(F);
|
||||
if (!loopAnalysis || !loopCharsResult)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
// 对每个函数内的所有循环做处理
|
||||
for (const auto &loop_ptr : loopAnalysis->getAllLoops()) {
|
||||
Loop *loop = loop_ptr.get();
|
||||
if (DEBUG) {
|
||||
std::cout << "LICM: Processing loop in function " << F->getName() << ": " << loop->getName() << std::endl;
|
||||
}
|
||||
const LoopCharacteristics *chars = loopCharsResult->getCharacteristics(loop);
|
||||
if (!chars || !loop->getPreHeader())
|
||||
continue; // 没有分析结果或没有前置块则跳过
|
||||
LICMContext ctx(F, loop, builder, chars);
|
||||
changed |= ctx.run();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void LICM::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||
|
||||
analysisDependencies.insert(&LoopAnalysisPass::ID);
|
||||
analysisDependencies.insert(&LoopCharacteristicsPass::ID);
|
||||
|
||||
analysisInvalidations.insert(&LoopCharacteristicsPass::ID);
|
||||
analysisInvalidations.insert(&LivenessAnalysisPass::ID);
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
528
src/midend/Pass/Optimize/LoopNormalization.cpp
Normal file
528
src/midend/Pass/Optimize/LoopNormalization.cpp
Normal file
@ -0,0 +1,528 @@
|
||||
#include "LoopNormalization.h"
|
||||
#include "Dom.h"
|
||||
#include "Loop.h"
|
||||
#include "SysYIROptUtils.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
// 使用全局调试开关
|
||||
extern int DEBUG;
|
||||
|
||||
namespace sysy {
|
||||
|
||||
// 定义 Pass 的唯一 ID
|
||||
void *LoopNormalizationPass::ID = (void *)&LoopNormalizationPass::ID;
|
||||
|
||||
bool LoopNormalizationPass::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (F->getBasicBlocks().empty()) {
|
||||
return false; // 空函数
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << "Running LoopNormalizationPass on function: " << F->getName() << std::endl;
|
||||
|
||||
// 获取并缓存所有需要的分析结果
|
||||
loopAnalysis = AM.getAnalysisResult<LoopAnalysisResult, LoopAnalysisPass>(F);
|
||||
if (!loopAnalysis || !loopAnalysis->hasLoops()) {
|
||||
if (DEBUG)
|
||||
std::cout << "No loops found in function " << F->getName() << ", skipping normalization" << std::endl;
|
||||
return false; // 没有循环需要规范化
|
||||
}
|
||||
|
||||
domTree = AM.getAnalysisResult<DominatorTree, DominatorTreeAnalysisPass>(F);
|
||||
|
||||
if (!domTree) {
|
||||
std::cerr << "Error: DominatorTree not available for function " << F->getName() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 重置统计信息
|
||||
stats = NormalizationStats();
|
||||
|
||||
bool modified = false;
|
||||
const auto& allLoops = loopAnalysis->getAllLoops();
|
||||
stats.totalLoops = allLoops.size();
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "Found " << stats.totalLoops << " loops to analyze for normalization" << std::endl;
|
||||
}
|
||||
|
||||
// 按循环深度从外到内处理,确保外层循环先规范化
|
||||
std::vector<Loop*> sortedLoops;
|
||||
for (const auto& loop_ptr : allLoops) {
|
||||
sortedLoops.push_back(loop_ptr.get());
|
||||
}
|
||||
|
||||
std::sort(sortedLoops.begin(), sortedLoops.end(), [](Loop* a, Loop* b) {
|
||||
return a->getLoopDepth() < b->getLoopDepth(); // 按深度升序排列
|
||||
});
|
||||
|
||||
// 逐个规范化循环
|
||||
for (Loop* loop : sortedLoops) {
|
||||
if (needsPreheader(loop)) {
|
||||
stats.loopsNeedingPreheader++;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Loop " << loop->getName() << " needs preheader (depth="
|
||||
<< loop->getLoopDepth() << ")" << std::endl;
|
||||
}
|
||||
|
||||
if (normalizeLoop(loop)) {
|
||||
modified = true;
|
||||
stats.loopsNormalized++;
|
||||
|
||||
// 验证规范化结果
|
||||
if (!validateNormalization(loop)) {
|
||||
std::cerr << "Warning: Loop normalization validation failed for loop "
|
||||
<< loop->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
auto* preheader = getExistingPreheader(loop);
|
||||
if (preheader) {
|
||||
std::cout << " Loop " << loop->getName() << " already has preheader: "
|
||||
<< preheader->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG && modified) {
|
||||
printStats(F);
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool LoopNormalizationPass::normalizeLoop(Loop* loop) {
|
||||
if (DEBUG)
|
||||
std::cout << " Normalizing loop: " << loop->getName() << std::endl;
|
||||
|
||||
// 创建前置块
|
||||
BasicBlock* preheader = createPreheaderForLoop(loop);
|
||||
if (!preheader) {
|
||||
if (DEBUG)
|
||||
std::cout << " Failed to create preheader for loop " << loop->getName() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
stats.preheadersCreated++;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Successfully created preheader " << preheader->getName()
|
||||
<< " for loop " << loop->getName() << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BasicBlock* LoopNormalizationPass::createPreheaderForLoop(Loop* loop) {
|
||||
BasicBlock* header = loop->getHeader();
|
||||
if (!header) {
|
||||
if (DEBUG)
|
||||
std::cerr << " Error: Loop has no header block" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 获取循环外的前驱块
|
||||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||||
if (externalPreds.empty()) {
|
||||
if (DEBUG)
|
||||
std::cout << " Loop " << loop->getName() << " has no external predecessors" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Found " << externalPreds.size() << " external predecessors for loop "
|
||||
<< loop->getName() << std::endl;
|
||||
for (auto* pred : externalPreds) {
|
||||
std::cout << " External pred: " << pred->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 生成前置块名称
|
||||
std::string preheaderName = generatePreheaderName(loop);
|
||||
|
||||
// 创建新的前置块
|
||||
Function* parentFunction = header->getParent();
|
||||
BasicBlock* preheader = parentFunction->addBasicBlock(preheaderName, header);
|
||||
|
||||
if (!preheader) {
|
||||
if (DEBUG)
|
||||
std::cerr << " Error: Failed to create basic block " << preheaderName << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 在前置块中创建跳转指令到循环头部
|
||||
builder->setPosition(preheader, preheader->end());
|
||||
UncondBrInst* br = builder->createUncondBrInst(header);
|
||||
|
||||
// 更新preheader的CFG关系
|
||||
preheader->addSuccessor(header);
|
||||
header->addPredecessor(preheader);
|
||||
|
||||
if(DEBUG) {
|
||||
std::cout << " Created preheader " << preheader->getName()
|
||||
<< " with unconditional branch to " << header->getName() << std::endl;
|
||||
}
|
||||
// 重定向外部前驱到新的前置块
|
||||
redirectExternalPredecessors(loop, preheader, header, externalPreds);
|
||||
|
||||
// 更新PHI节点
|
||||
updatePhiNodesForPreheader(header, preheader, externalPreds);
|
||||
|
||||
// 更新支配树关系
|
||||
updateDominatorRelations(preheader, loop);
|
||||
|
||||
// 重要:更新循环对象的前置块信息
|
||||
// 这样后续的优化遍可以通过 loop->getPreHeader() 获取到新创建的前置块
|
||||
loop->setPreHeader(preheader);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Updated loop object: preheader set to " << preheader->getName() << std::endl;
|
||||
}
|
||||
|
||||
return preheader;
|
||||
}
|
||||
|
||||
bool LoopNormalizationPass::needsPreheader(Loop* loop) {
|
||||
// 检查是否已有合适的前置块
|
||||
if (getExistingPreheader(loop) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有外部前驱(如果没有外部前驱,不需要前置块)
|
||||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||||
if (externalPreds.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 基于结构性需求判断:
|
||||
// 1. 如果有多个外部前驱,必须创建前置块来合并它们
|
||||
// 2. 如果单个外部前驱不适合作为前置块,需要创建新的前置块
|
||||
return (externalPreds.size() > 1) || !isSuitableAsPreheader(externalPreds[0], loop);
|
||||
}
|
||||
|
||||
BasicBlock* LoopNormalizationPass::getExistingPreheader(Loop* loop) {
|
||||
BasicBlock* header = loop->getHeader();
|
||||
if (!header) return nullptr;
|
||||
|
||||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||||
|
||||
// 如果只有一个外部前驱,且适合作为前置块,则返回它
|
||||
if (externalPreds.size() == 1 && isSuitableAsPreheader(externalPreds[0], loop)) {
|
||||
return externalPreds[0];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void LoopNormalizationPass::updateDominatorRelations(BasicBlock* newBlock, Loop* loop) {
|
||||
// 由于在getAnalysisUsage中声明了DominatorTree会失效,
|
||||
// PassManager会在本遍运行后自动将支配树结果标记为失效,
|
||||
// 后续需要支配树的Pass会触发重新计算,所以这里无需手动更新
|
||||
|
||||
if (DEBUG) {
|
||||
BasicBlock* header = loop->getHeader();
|
||||
std::cout << " DominatorTree marked for invalidation - new preheader "
|
||||
<< newBlock->getName() << " will dominate " << header->getName()
|
||||
<< " after recomputation by PassManager" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void LoopNormalizationPass::redirectExternalPredecessors(Loop* loop, BasicBlock* preheader, BasicBlock* header,
|
||||
const std::vector<BasicBlock*>& externalPreds) {
|
||||
// std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Redirecting " << externalPreds.size() << " external predecessors" << std::endl;
|
||||
}
|
||||
|
||||
for (BasicBlock* pred : externalPreds) {
|
||||
// 获取前驱块的终止指令
|
||||
auto termIt = pred->terminator();
|
||||
if (termIt == pred->end()) continue;
|
||||
|
||||
Instruction* terminator = termIt->get();
|
||||
if (!terminator) continue;
|
||||
|
||||
// 更新跳转目标
|
||||
if (auto* br = dynamic_cast<UncondBrInst*>(terminator)) {
|
||||
// 无条件跳转
|
||||
if (br->getBlock() == header) {
|
||||
if(DEBUG){
|
||||
std::cout << " Updating unconditional branch from " << br->getBlock()->getName()
|
||||
<< " to " << preheader->getName() << std::endl;
|
||||
}
|
||||
// 需要更新操作数
|
||||
br->setOperand(0, preheader);
|
||||
// 更新CFG关系
|
||||
header->removePredecessor(pred);
|
||||
preheader->addPredecessor(pred);
|
||||
pred->removeSuccessor(header);
|
||||
pred->addSuccessor(preheader);
|
||||
|
||||
}
|
||||
} else if (auto* condBr = dynamic_cast<CondBrInst*>(terminator)) {
|
||||
// 条件跳转
|
||||
bool updated = false;
|
||||
if (condBr->getThenBlock() == header) {
|
||||
condBr->setOperand(1, preheader); // 第1个操作数是then分支
|
||||
updated = true;
|
||||
}
|
||||
if (condBr->getElseBlock() == header) {
|
||||
condBr->setOperand(2, preheader); // 第2个操作数是else分支
|
||||
updated = true;
|
||||
}
|
||||
if (updated) {
|
||||
// 更新CFG关系
|
||||
header->removePredecessor(pred);
|
||||
preheader->addPredecessor(pred);
|
||||
pred->removeSuccessor(header);
|
||||
pred->addSuccessor(preheader);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Updated conditional branch from " << pred->getName()
|
||||
<< " to " << preheader->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string LoopNormalizationPass::generatePreheaderName(Loop* loop) {
|
||||
std::ostringstream oss;
|
||||
oss << loop->getName() << "_preheader";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
bool LoopNormalizationPass::validateNormalization(Loop* loop) {
|
||||
BasicBlock* header = loop->getHeader();
|
||||
if (!header) return false;
|
||||
|
||||
// 检查循环是否现在有唯一的外部前驱
|
||||
std::vector<BasicBlock*> externalPreds = getExternalPredecessors(loop);
|
||||
if (externalPreds.size() != 1) {
|
||||
if (DEBUG)
|
||||
std::cout << " Validation failed: Loop " << loop->getName()
|
||||
<< " has " << externalPreds.size() << " external predecessors (expected 1)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查外部前驱是否适合作为前置块
|
||||
BasicBlock* preheader = externalPreds[0];
|
||||
if (!isSuitableAsPreheader(preheader, loop)) {
|
||||
if (DEBUG)
|
||||
std::cout << " Validation failed: External predecessor " << preheader->getName()
|
||||
<< " is not suitable as preheader" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 额外验证:检查CFG连接性
|
||||
if (!preheader->hasSuccessor(header)) {
|
||||
if (DEBUG)
|
||||
std::cout << " Validation failed: Preheader " << preheader->getName()
|
||||
<< " is not connected to header " << header->getName() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!header->hasPredecessor(preheader)) {
|
||||
if (DEBUG)
|
||||
std::cout << " Validation failed: Header " << header->getName()
|
||||
<< " does not have preheader " << preheader->getName() << " as predecessor" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << " Validation passed for loop " << loop->getName() << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<BasicBlock*> LoopNormalizationPass::getExternalPredecessors(Loop* loop) {
|
||||
std::vector<BasicBlock*> externalPreds;
|
||||
BasicBlock* header = loop->getHeader();
|
||||
if (!header) return externalPreds;
|
||||
|
||||
for (BasicBlock* pred : header->getPredecessors()) {
|
||||
if (!loop->contains(pred)) {
|
||||
externalPreds.push_back(pred);
|
||||
}
|
||||
}
|
||||
|
||||
return externalPreds;
|
||||
}
|
||||
|
||||
bool LoopNormalizationPass::isSuitableAsPreheader(BasicBlock* block, Loop* loop) {
|
||||
if (!block) return false;
|
||||
|
||||
// 检查该块是否只有一个后继,且后继是循环头部
|
||||
auto successors = block->getSuccessors();
|
||||
if (successors.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (successors[0] != loop->getHeader()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查该块是否不包含复杂的控制流
|
||||
// 理想的前置块应该只包含简单的跳转指令
|
||||
size_t instCount = 0;
|
||||
for (const auto& inst : block->getInstructions()) {
|
||||
instCount++;
|
||||
// 如果指令过多,可能不适合作为前置块
|
||||
if (instCount > 10) { // 阈值可调整
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoopNormalizationPass::updatePhiNodesForPreheader(BasicBlock* header, BasicBlock* preheader,
|
||||
const std::vector<BasicBlock*>& oldPreds) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Updating PHI nodes in header " << header->getName()
|
||||
<< " for new preheader " << preheader->getName() << std::endl;
|
||||
}
|
||||
|
||||
std::vector<PhiInst*> phisToRemove; // 需要删除的PHI节点
|
||||
|
||||
for (auto& inst : header->getInstructions()) {
|
||||
if (auto* phi = dynamic_cast<PhiInst*>(inst.get())) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Processing PHI node: " << phi->getName() << std::endl;
|
||||
}
|
||||
|
||||
// 收集来自外部前驱的值 - 需要保持原始的映射关系
|
||||
std::map<BasicBlock*, Value*> externalValues;
|
||||
for (BasicBlock* oldPred : oldPreds) {
|
||||
Value* value = phi->getValfromBlk(oldPred);
|
||||
if (value) {
|
||||
externalValues[oldPred] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理PHI节点的更新
|
||||
if (externalValues.size() > 1) {
|
||||
// 多个外部前驱:在前置块中创建新的PHI节点
|
||||
builder->setPosition(preheader, preheader->getInstructions().begin());
|
||||
|
||||
std::vector<Value*> values;
|
||||
std::vector<BasicBlock*> blocks;
|
||||
for (auto& [block, value] : externalValues) {
|
||||
values.push_back(value);
|
||||
blocks.push_back(block);
|
||||
}
|
||||
|
||||
PhiInst* newPhi = builder->createPhiInst(phi->getType(), values, blocks);
|
||||
|
||||
// 移除所有外部前驱的条目
|
||||
for (BasicBlock* oldPred : oldPreds) {
|
||||
phi->removeIncomingBlock(oldPred);
|
||||
}
|
||||
|
||||
// 添加来自新前置块的条目
|
||||
phi->addIncoming(newPhi, preheader);
|
||||
|
||||
} else if (externalValues.size() == 1) {
|
||||
// 单个外部前驱:直接重新映射
|
||||
Value* value = externalValues.begin()->second;
|
||||
|
||||
// 移除旧的外部前驱条目
|
||||
for (BasicBlock* oldPred : oldPreds) {
|
||||
phi->removeIncomingBlock(oldPred);
|
||||
}
|
||||
|
||||
// 添加来自新前置块的条目
|
||||
phi->addIncoming(value, preheader);
|
||||
|
||||
// 检查PHI节点是否只剩下一个条目(只来自前置块)
|
||||
if (phi->getNumIncomingValues() == 1) {
|
||||
if (DEBUG) {
|
||||
std::cout << " PHI node " << phi->getName()
|
||||
<< " now has only one incoming value, scheduling for removal" << std::endl;
|
||||
}
|
||||
// 用单一值替换所有使用
|
||||
Value* singleValue = phi->getIncomingValue(0u);
|
||||
phi->replaceAllUsesWith(singleValue);
|
||||
phisToRemove.push_back(phi);
|
||||
}
|
||||
} else {
|
||||
// 没有外部值的PHI节点:检查是否需要更新
|
||||
// 这种PHI节点只有循环内的边,通常不需要修改
|
||||
// 但我们仍然需要检查是否只有一个条目
|
||||
if (phi->getNumIncomingValues() == 1) {
|
||||
if (DEBUG) {
|
||||
std::cout << " PHI node " << phi->getName()
|
||||
<< " has only one incoming value (no external), scheduling for removal" << std::endl;
|
||||
}
|
||||
// 用单一值替换所有使用
|
||||
Value* singleValue = phi->getIncomingValue(0u);
|
||||
phi->replaceAllUsesWith(singleValue);
|
||||
phisToRemove.push_back(phi);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG && std::find(phisToRemove.begin(), phisToRemove.end(), phi) == phisToRemove.end()) {
|
||||
std::cout << " Updated PHI node with " << externalValues.size()
|
||||
<< " external values, total incoming: " << phi->getNumIncomingValues() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除标记为移除的PHI节点
|
||||
for (PhiInst* phi : phisToRemove) {
|
||||
if (DEBUG) {
|
||||
std::cout << " Removing redundant PHI node: " << phi->getName() << std::endl;
|
||||
}
|
||||
SysYIROptUtils::usedelete(phi);
|
||||
}
|
||||
|
||||
// 更新统计信息
|
||||
stats.redundantPhisRemoved += phisToRemove.size();
|
||||
|
||||
if (DEBUG && !phisToRemove.empty()) {
|
||||
std::cout << " Removed " << phisToRemove.size() << " redundant PHI nodes" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void LoopNormalizationPass::printStats(Function* F) {
|
||||
std::cout << "\n--- Loop Normalization Statistics for Function: " << F->getName() << " ---" << std::endl;
|
||||
std::cout << "Total loops analyzed: " << stats.totalLoops << std::endl;
|
||||
std::cout << "Loops needing preheader: " << stats.loopsNeedingPreheader << std::endl;
|
||||
std::cout << "Preheaders created: " << stats.preheadersCreated << std::endl;
|
||||
std::cout << "Loops successfully normalized: " << stats.loopsNormalized << std::endl;
|
||||
std::cout << "Redundant PHI nodes removed: " << stats.redundantPhisRemoved << std::endl;
|
||||
|
||||
if (stats.totalLoops > 0) {
|
||||
double normalizationRate = (double)stats.loopsNormalized / stats.totalLoops * 100.0;
|
||||
std::cout << "Normalization rate: " << normalizationRate << "%" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "---------------------------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
void LoopNormalizationPass::getAnalysisUsage(std::set<void *> &analysisDependencies,
|
||||
std::set<void *> &analysisInvalidations) const {
|
||||
// LoopNormalization依赖的分析
|
||||
analysisDependencies.insert(&LoopAnalysisPass::ID); // 循环结构分析
|
||||
analysisDependencies.insert(&DominatorTreeAnalysisPass::ID); // 支配树分析
|
||||
|
||||
// LoopNormalization会修改CFG结构,因此会使以下分析失效
|
||||
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树需要重新计算
|
||||
|
||||
// 注意:我们不让循环结构分析失效,原因如下:
|
||||
// 1. 循环规范化只添加前置块,不改变循环的核心结构(头部、体、回边)
|
||||
// 2. 我们会手动更新Loop对象的前置块信息(通过loop->setPreHeader())
|
||||
// 3. 让循环分析失效并重新计算的成本较高且不必要
|
||||
// 4. 后续优化遍可以正确获取到更新后的前置块信息
|
||||
//
|
||||
// 如果未来有更复杂的循环结构修改,可能需要考虑让循环分析失效:
|
||||
// analysisInvalidations.insert(&LoopAnalysisPass::ID);
|
||||
}
|
||||
|
||||
} // namespace sysy
|
||||
1121
src/midend/Pass/Optimize/LoopStrengthReduction.cpp
Normal file
1121
src/midend/Pass/Optimize/LoopStrengthReduction.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
||||
#include "Mem2Reg.h" // 包含 Mem2Reg 遍的头文件
|
||||
#include "Dom.h" // 包含支配树分析的头文件
|
||||
#include "Liveness.h"
|
||||
#include "AliasAnalysis.h" // 包含别名分析
|
||||
#include "SideEffectAnalysis.h" // 包含副作用分析
|
||||
#include "IR.h" // 包含 IR 相关的定义
|
||||
#include "SysYIROptUtils.h"
|
||||
#include <cassert> // 用于断言
|
||||
@ -420,8 +422,9 @@ void Mem2Reg::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<
|
||||
// 因此,它会使许多分析结果失效。
|
||||
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
|
||||
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析肯定失效
|
||||
analysisInvalidations.insert(&SysYAliasAnalysisPass::ID); // 别名分析必须失效,因为Mem2Reg改变了内存访问模式
|
||||
analysisInvalidations.insert(&SysYSideEffectAnalysisPass::ID); // 副作用分析也可能失效
|
||||
// analysisInvalidations.insert(&LoopInfoAnalysisPass::ID); // 循环信息可能失效
|
||||
// analysisInvalidations.insert(&SideEffectInfoAnalysisPass::ID); // 副作用分析可能失效
|
||||
// 其他所有依赖于数据流或 IR 结构的分析都可能失效。
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
#include "SCCP.h"
|
||||
#include "Dom.h"
|
||||
#include "Liveness.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath> // For std::fmod, std::fabs
|
||||
#include <limits> // For std::numeric_limits
|
||||
#include <set> // For std::set in isKnownPureFunction
|
||||
|
||||
namespace sysy {
|
||||
|
||||
@ -263,6 +265,192 @@ SSAPValue SCCPContext::ComputeConstant(UnaryInst *unaryInst, SSAPValue operandVa
|
||||
return SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
// 辅助函数:检查是否为已知的纯函数
|
||||
bool SCCPContext::isKnownPureFunction(const std::string &funcName) const {
|
||||
// SysY中一些已知的纯函数(不修改全局状态,结果只依赖参数)
|
||||
static const std::set<std::string> knownPureFunctions = {
|
||||
// 数学函数(如果有的话)
|
||||
// "abs", "fabs", "sqrt", "sin", "cos"
|
||||
// SysY标准中基本没有纯函数,大多数都有I/O副作用
|
||||
};
|
||||
|
||||
return knownPureFunctions.find(funcName) != knownPureFunctions.end();
|
||||
}
|
||||
|
||||
// 辅助函数:计算纯函数的常量结果
|
||||
SSAPValue SCCPContext::computePureFunctionResult(CallInst *call, const std::vector<SSAPValue> &argValues) {
|
||||
Function *calledFunc = call->getCallee();
|
||||
if (!calledFunc) {
|
||||
return SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
std::string funcName = calledFunc->getName();
|
||||
|
||||
// 目前SysY中没有标准的纯函数,这里预留扩展空间
|
||||
// 未来可以添加数学函数的常量折叠
|
||||
/*
|
||||
if (funcName == "abs" && argValues.size() == 1) {
|
||||
if (argValues[0].constant_type == ValueType::Integer) {
|
||||
int val = std::get<int>(argValues[0].constantVal);
|
||||
return SSAPValue(std::abs(val));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
// 辅助函数:查找存储到指定位置的常量值
|
||||
SSAPValue SCCPContext::findStoredConstantValue(Value *ptr, BasicBlock *currentBB) {
|
||||
if (!aliasAnalysis) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: No alias analysis available" << std::endl;
|
||||
}
|
||||
return SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Searching for stored constant value for ptr" << std::endl;
|
||||
}
|
||||
|
||||
// 从当前块的指令列表末尾向前查找最近的Store
|
||||
std::vector<Instruction*> instructions;
|
||||
for (auto it = currentBB->begin(); it != currentBB->end(); ++it) {
|
||||
instructions.push_back(it->get());
|
||||
}
|
||||
|
||||
for (int i = instructions.size() - 1; i >= 0; --i) {
|
||||
Instruction *prevInst = instructions[i];
|
||||
|
||||
if (prevInst->isStore()) {
|
||||
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
|
||||
Value *storePtr = storeInst->getPointer();
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Checking store instruction" << std::endl;
|
||||
}
|
||||
|
||||
// 使用别名分析检查Store是否针对相同的内存位置
|
||||
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Alias result: " << (int)aliasResult << std::endl;
|
||||
}
|
||||
|
||||
if (aliasResult == AliasType::SELF_ALIAS) {
|
||||
// 找到了对相同位置的Store,获取存储的值
|
||||
Value *storedValue = storeInst->getValue();
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found matching store, checking value type" << std::endl;
|
||||
}
|
||||
|
||||
// 检查存储的值是否为常量
|
||||
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
|
||||
int val = std::get<int>(constInt->getVal());
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found constant integer value: " << val << std::endl;
|
||||
}
|
||||
return SSAPValue(val);
|
||||
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
|
||||
float val = std::get<float>(constFloat->getVal());
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found constant float value: " << val << std::endl;
|
||||
}
|
||||
return SSAPValue(val);
|
||||
} else {
|
||||
// 存储的值不是常量,检查其SCCP状态
|
||||
SSAPValue storedState = GetValueState(storedValue);
|
||||
if (storedState.state == LatticeVal::Constant) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found SCCP constant value" << std::endl;
|
||||
}
|
||||
return storedState;
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Stored value is not constant" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 找到了最近的Store但不是常量,停止查找
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found non-constant store, stopping search" << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: No constant value found" << std::endl;
|
||||
}
|
||||
return SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
// 辅助函数:动态检查数组访问是否为常量索引(考虑SCCP状态)
|
||||
bool SCCPContext::hasRuntimeConstantAccess(Value *ptr) {
|
||||
if (auto gep = dynamic_cast<GetElementPtrInst *>(ptr)) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Checking runtime constant access for GEP instruction" << std::endl;
|
||||
}
|
||||
|
||||
// 检查所有索引是否为常量或SCCP传播的常量
|
||||
bool allConstantIndices = true;
|
||||
for (auto indexUse : gep->getIndices()) {
|
||||
Value* index = indexUse->getValue();
|
||||
|
||||
// 首先检查是否为编译时常量
|
||||
if (auto constInt = dynamic_cast<ConstantInteger *>(index)) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Index is compile-time constant integer: " << std::get<int>(constInt->getVal()) << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (auto constFloat = dynamic_cast<ConstantFloating *>(index)) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Index is compile-time constant float: " << std::get<float>(constFloat->getVal()) << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否为SCCP传播的常量
|
||||
SSAPValue indexState = GetValueState(index);
|
||||
if (indexState.state == LatticeVal::Constant) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Index is SCCP constant: ";
|
||||
if (indexState.constant_type == ValueType::Integer) {
|
||||
std::cout << std::get<int>(indexState.constantVal);
|
||||
} else {
|
||||
std::cout << std::get<float>(indexState.constantVal);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果任何一个索引不是常量,返回false
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Index is not constant, access is not constant" << std::endl;
|
||||
}
|
||||
allConstantIndices = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: hasRuntimeConstantAccess result: " << (allConstantIndices ? "true" : "false") << std::endl;
|
||||
}
|
||||
return allConstantIndices;
|
||||
}
|
||||
|
||||
// 对于非GEP指令,回退到别名分析的静态结果
|
||||
if (aliasAnalysis) {
|
||||
return aliasAnalysis->hasConstantAccess(ptr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 辅助函数:处理单条指令
|
||||
void SCCPContext::ProcessInstruction(Instruction *inst) {
|
||||
SSAPValue oldState = GetValueState(inst);
|
||||
@ -396,28 +584,237 @@ void SCCPContext::ProcessInstruction(Instruction *inst) {
|
||||
break;
|
||||
}
|
||||
case Instruction::kLoad: {
|
||||
// 对于 Load 指令,除非我们有特殊的别名分析,否则假定为 Bottom
|
||||
// 或者如果它加载的是一个已知常量地址的全局常量
|
||||
// 使用别名分析和副作用分析改进Load指令的处理
|
||||
Value *ptr = inst->getOperand(0);
|
||||
|
||||
// 首先检查是否是全局常量
|
||||
if (auto globalVal = dynamic_cast<GlobalValue *>(ptr)) {
|
||||
// 如果 GlobalValue 有初始化器,并且它是常量,我们可以传播
|
||||
// 这需要额外的逻辑来检查 globalVal 的初始化器
|
||||
// 暂时保守地设置为 Bottom
|
||||
// TODO: 检查全局变量的初始化器进行常量传播
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
} else if (aliasAnalysis && sideEffectAnalysis) {
|
||||
// 使用别名分析和副作用分析进行更精确的Load分析
|
||||
if (aliasAnalysis->isLocalArray(ptr) && (aliasAnalysis->hasConstantAccess(ptr) || hasRuntimeConstantAccess(ptr))) {
|
||||
// 对于局部数组的常量索引访问,检查是否有影响该位置的Store
|
||||
bool mayBeModified = false;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Analyzing local array with constant access for modification" << std::endl;
|
||||
}
|
||||
|
||||
// 遍历指令所在块之前的所有指令,查找可能修改该内存位置的Store
|
||||
BasicBlock *currentBB = inst->getParent();
|
||||
auto instPos = currentBB->findInstIterator(inst);
|
||||
|
||||
SSAPValue foundConstantValue = SSAPValue(LatticeVal::Bottom);
|
||||
bool hasFoundDefinitiveStore = false;
|
||||
|
||||
for (auto it = currentBB->begin(); it != instPos; ++it) {
|
||||
Instruction *prevInst = it->get();
|
||||
|
||||
if (prevInst->isStore()) {
|
||||
StoreInst *storeInst = static_cast<StoreInst *>(prevInst);
|
||||
Value *storePtr = storeInst->getPointer();
|
||||
|
||||
// 使用别名分析判断Store是否可能影响当前Load
|
||||
auto aliasResult = aliasAnalysis->queryAlias(ptr, storePtr);
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Checking store with alias result: " << (int)aliasResult << std::endl;
|
||||
}
|
||||
|
||||
if (aliasResult == AliasType::SELF_ALIAS) {
|
||||
// 找到对相同位置的精确Store
|
||||
Value *storedValue = storeInst->getValue();
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found exact store to same location, checking value" << std::endl;
|
||||
}
|
||||
|
||||
// 检查存储的值是否为常量
|
||||
if (auto constInt = dynamic_cast<ConstantInteger *>(storedValue)) {
|
||||
int val = std::get<int>(constInt->getVal());
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Store contains constant integer: " << val << std::endl;
|
||||
}
|
||||
foundConstantValue = SSAPValue(val);
|
||||
hasFoundDefinitiveStore = true;
|
||||
// 继续遍历,查找是否有更后面的Store覆盖这个值
|
||||
} else if (auto constFloat = dynamic_cast<ConstantFloating *>(storedValue)) {
|
||||
float val = std::get<float>(constFloat->getVal());
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Store contains constant float: " << val << std::endl;
|
||||
}
|
||||
foundConstantValue = SSAPValue(val);
|
||||
hasFoundDefinitiveStore = true;
|
||||
} else {
|
||||
// 存储的值不是编译时常量,检查其SCCP状态
|
||||
SSAPValue storedState = GetValueState(storedValue);
|
||||
if (storedState.state == LatticeVal::Constant) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Store contains SCCP constant" << std::endl;
|
||||
}
|
||||
foundConstantValue = storedState;
|
||||
hasFoundDefinitiveStore = true;
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Store contains non-constant value" << std::endl;
|
||||
}
|
||||
// 非常量Store覆盖了之前的常量,无法传播
|
||||
foundConstantValue = SSAPValue(LatticeVal::Bottom);
|
||||
hasFoundDefinitiveStore = true;
|
||||
}
|
||||
}
|
||||
} else if (aliasResult != AliasType::NO_ALIAS) {
|
||||
// 可能有别名,但不确定
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found store with uncertain alias, stopping propagation" << std::endl;
|
||||
}
|
||||
mayBeModified = true;
|
||||
break;
|
||||
}
|
||||
} else if (prevInst->isCall()) {
|
||||
// 检查函数调用是否可能修改该内存位置
|
||||
if (sideEffectAnalysis->mayModifyMemory(prevInst)) {
|
||||
// 进一步检查是否可能影响局部数组
|
||||
if (!aliasAnalysis->isLocalArray(ptr) ||
|
||||
sideEffectAnalysis->mayModifyGlobal(prevInst)) {
|
||||
mayBeModified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (prevInst->isMemset()) {
|
||||
// Memset指令可能影响内存,但只有在它在相关Store之前时才阻止常量传播
|
||||
MemsetInst *memsetInst = static_cast<MemsetInst *>(prevInst);
|
||||
Value *memsetPtr = memsetInst->getOperand(0);
|
||||
|
||||
auto aliasResult = aliasAnalysis->queryAlias(ptr, memsetPtr);
|
||||
if (aliasResult != AliasType::NO_ALIAS) {
|
||||
// Memset可能影响这个位置,但我们继续查找是否有Store覆盖了memset
|
||||
// 不立即设置mayBeModified = true,让后续的Store有机会覆盖
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found memset that may affect location, but continuing to check for overwriting stores" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: mayBeModified = " << (mayBeModified ? "true" : "false") << std::endl;
|
||||
std::cout << "SCCP: hasFoundDefinitiveStore = " << (hasFoundDefinitiveStore ? "true" : "false") << std::endl;
|
||||
}
|
||||
|
||||
if (!mayBeModified) {
|
||||
if (hasFoundDefinitiveStore && foundConstantValue.state == LatticeVal::Constant) {
|
||||
// 直接使用找到的常量值
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Using found constant value from store analysis: ";
|
||||
if (foundConstantValue.constant_type == ValueType::Integer) {
|
||||
std::cout << std::get<int>(foundConstantValue.constantVal);
|
||||
} else {
|
||||
std::cout << std::get<float>(foundConstantValue.constantVal);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
newState = foundConstantValue;
|
||||
} else {
|
||||
// 如果没有发现修改该位置的指令,尝试用旧方法找到对应的Store值
|
||||
SSAPValue constantValue = findStoredConstantValue(ptr, inst->getParent());
|
||||
if (constantValue.state == LatticeVal::Constant) {
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Found constant value for array load using fallback method: ";
|
||||
if (constantValue.constant_type == ValueType::Integer) {
|
||||
std::cout << std::get<int>(constantValue.constantVal);
|
||||
} else {
|
||||
std::cout << std::get<float>(constantValue.constantVal);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
newState = constantValue;
|
||||
} else {
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
} else {
|
||||
// 非局部数组或非常量访问,保守处理
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
} else {
|
||||
// 没有分析信息时保守处理
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
if (DEBUG && aliasAnalysis && sideEffectAnalysis) {
|
||||
std::cout << "SCCP: Load instruction analysis - "
|
||||
<< (aliasAnalysis->isLocalArray(ptr) ? "local array" : "other")
|
||||
<< ", static constant access: "
|
||||
<< (aliasAnalysis->hasConstantAccess(ptr) ? "yes" : "no")
|
||||
<< ", runtime constant access: "
|
||||
<< (hasRuntimeConstantAccess(ptr) ? "yes" : "no") << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::kStore:
|
||||
// Store 指令不产生值,其 SSAPValue 不重要
|
||||
newState = SSAPValue(); // 保持 Top
|
||||
break;
|
||||
case Instruction::kCall:
|
||||
// TODO: 处理 Call 指令根据副作用分析可以推断的常量
|
||||
// 大多数 Call 指令都假定为 Bottom,除非是纯函数且所有参数都是常量
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
case Instruction::kCall: {
|
||||
// 使用副作用分析改进Call指令处理
|
||||
CallInst *callInst = static_cast<CallInst *>(inst);
|
||||
|
||||
if (sideEffectAnalysis) {
|
||||
const auto &sideEffect = sideEffectAnalysis->getInstructionSideEffect(callInst);
|
||||
|
||||
// 检查是否为纯函数且所有参数都是常量
|
||||
if (sideEffect.isPure && sideEffect.type == SideEffectType::NO_SIDE_EFFECT) {
|
||||
// 对于纯函数,检查所有参数是否都是常量
|
||||
bool allArgsConstant = true;
|
||||
std::vector<SSAPValue> argValues;
|
||||
|
||||
for (unsigned i = 0; i < callInst->getNumOperands() - 1; ++i) { // 减1排除函数本身
|
||||
SSAPValue argVal = GetValueState(callInst->getOperand(i));
|
||||
argValues.push_back(argVal);
|
||||
if (argVal.state != LatticeVal::Constant) {
|
||||
allArgsConstant = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allArgsConstant) {
|
||||
// 对于参数全为常量的纯函数,可以尝试常量折叠
|
||||
// 但由于实际执行函数比较复杂,这里先标记为可优化
|
||||
// TODO: 实现具体的纯函数常量折叠
|
||||
Function *calledFunc = callInst->getCallee();
|
||||
if (calledFunc && isKnownPureFunction(calledFunc->getName())) {
|
||||
// 对已知的纯函数进行常量计算
|
||||
newState = computePureFunctionResult(callInst, argValues);
|
||||
} else {
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
} else {
|
||||
// 参数不全是常量,但函数无副作用
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Pure function call with "
|
||||
<< (allArgsConstant ? "constant" : "non-constant") << " arguments" << std::endl;
|
||||
}
|
||||
} else {
|
||||
// 有副作用的函数调用,保守处理
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Function call with side effects" << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有副作用分析时,保守处理所有Call
|
||||
newState = SSAPValue(LatticeVal::Bottom);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instruction::kGetElementPtr: {
|
||||
// GEP 指令计算地址,通常其结果值(地址指向的内容)是 Bottom
|
||||
// 除非所有索引和基指针都是常量,指向一个确定常量值的内存位置
|
||||
@ -970,12 +1367,34 @@ bool SCCP::runOnFunction(Function *F, AnalysisManager &AM) {
|
||||
if (DEBUG) {
|
||||
std::cout << "Running SCCP on function: " << F->getName() << std::endl;
|
||||
}
|
||||
|
||||
SCCPContext context(builder);
|
||||
|
||||
// 获取别名分析结果
|
||||
if (auto *aliasResult = AM.getAnalysisResult<AliasAnalysisResult, SysYAliasAnalysisPass>(F)) {
|
||||
context.setAliasAnalysis(aliasResult);
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Using alias analysis results" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取副作用分析结果(Module级别)
|
||||
if (auto *sideEffectResult = AM.getAnalysisResult<SideEffectAnalysisResult, SysYSideEffectAnalysisPass>()) {
|
||||
context.setSideEffectAnalysis(sideEffectResult);
|
||||
if (DEBUG) {
|
||||
std::cout << "SCCP: Using side effect analysis results" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
context.run(F, AM);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCCP::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
|
||||
// 声明依赖别名分析和副作用分析
|
||||
analysisDependencies.insert(&SysYAliasAnalysisPass::ID);
|
||||
analysisDependencies.insert(&SysYSideEffectAnalysisPass::ID);
|
||||
|
||||
// analysisInvalidations.insert(nullptr); // 表示使所有默认分析失效
|
||||
analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID); // 支配树可能受影响
|
||||
analysisInvalidations.insert(&LivenessAnalysisPass::ID); // 活跃性分析很可能失效
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
#include "Dom.h"
|
||||
#include "Liveness.h"
|
||||
#include "Loop.h"
|
||||
#include "LoopCharacteristics.h"
|
||||
#include "AliasAnalysis.h"
|
||||
#include "CallGraphAnalysis.h"
|
||||
#include "SideEffectAnalysis.h"
|
||||
#include "SysYIRCFGOpt.h"
|
||||
#include "SysYIRPrinter.h"
|
||||
#include "DCE.h"
|
||||
@ -8,6 +13,10 @@
|
||||
#include "SCCP.h"
|
||||
#include "BuildCFG.h"
|
||||
#include "LargeArrayToGlobal.h"
|
||||
#include "LoopNormalization.h"
|
||||
#include "LICM.h"
|
||||
#include "LoopStrengthReduction.h"
|
||||
#include "InductionVariableElimination.h"
|
||||
#include "Pass.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
@ -39,6 +48,13 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
// 注册分析遍
|
||||
registerAnalysisPass<DominatorTreeAnalysisPass>();
|
||||
registerAnalysisPass<LivenessAnalysisPass>();
|
||||
registerAnalysisPass<sysy::DominatorTreeAnalysisPass>();
|
||||
registerAnalysisPass<sysy::LivenessAnalysisPass>();
|
||||
registerAnalysisPass<SysYAliasAnalysisPass>(); // 别名分析 (优先级高)
|
||||
registerAnalysisPass<CallGraphAnalysisPass>(); // 调用图分析 (Module级别,独立分析)
|
||||
registerAnalysisPass<SysYSideEffectAnalysisPass>(); // 副作用分析 (依赖别名分析和调用图)
|
||||
registerAnalysisPass<LoopAnalysisPass>();
|
||||
registerAnalysisPass<LoopCharacteristicsPass>(); // 循环特征分析依赖别名分析
|
||||
|
||||
// 注册优化遍
|
||||
registerOptimizationPass<BuildCFG>();
|
||||
@ -54,6 +70,10 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
|
||||
registerOptimizationPass<DCE>();
|
||||
registerOptimizationPass<Mem2Reg>(builderIR);
|
||||
registerOptimizationPass<LoopNormalizationPass>(builderIR);
|
||||
registerOptimizationPass<LICM>(builderIR);
|
||||
registerOptimizationPass<LoopStrengthReduction>(builderIR);
|
||||
registerOptimizationPass<InductionVariableElimination>();
|
||||
registerOptimizationPass<Reg2Mem>(builderIR);
|
||||
|
||||
registerOptimizationPass<SCCP>(builderIR);
|
||||
@ -119,9 +139,21 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
}
|
||||
|
||||
this->clearPasses();
|
||||
this->addPass(&Reg2Mem::ID);
|
||||
this->addPass(&LoopNormalizationPass::ID);
|
||||
this->addPass(&LICM::ID);
|
||||
this->addPass(&LoopStrengthReduction::ID);
|
||||
this->addPass(&InductionVariableElimination::ID);
|
||||
this->run();
|
||||
|
||||
if(DEBUG) {
|
||||
std::cout << "=== IR After Loop Normalization, LICM, and Strength Reduction Optimizations ===\n";
|
||||
printPasses();
|
||||
}
|
||||
|
||||
// this->clearPasses();
|
||||
// this->addPass(&Reg2Mem::ID);
|
||||
// this->run();
|
||||
|
||||
if(DEBUG) {
|
||||
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
|
||||
printPasses();
|
||||
|
||||
@ -240,7 +240,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kMul:
|
||||
case Kind::kDiv:
|
||||
case Kind::kRem:
|
||||
case Kind::kSRA:
|
||||
case Kind::kSrl:
|
||||
case Kind::kSll:
|
||||
case Kind::kSra:
|
||||
case Kind::kMulh:
|
||||
case Kind::kFAdd:
|
||||
case Kind::kFSub:
|
||||
@ -274,7 +276,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
||||
case Kind::kMul: std::cout << "mul"; break;
|
||||
case Kind::kDiv: std::cout << "sdiv"; break;
|
||||
case Kind::kRem: std::cout << "srem"; break;
|
||||
case Kind::kSRA: std::cout << "ashr"; break;
|
||||
case Kind::kSrl: std::cout << "lshr"; break;
|
||||
case Kind::kSll: std::cout << "shl"; break;
|
||||
case Kind::kSra: std::cout << "ashr"; break;
|
||||
case Kind::kMulh: std::cout << "mulh"; break;
|
||||
case Kind::kFAdd: std::cout << "fadd"; break;
|
||||
case Kind::kFSub: std::cout << "fsub"; break;
|
||||
|
||||
@ -35,7 +35,7 @@ void usage(int code) {
|
||||
"Supported options:\n"
|
||||
" -h \tprint help message and exit\n"
|
||||
" -f \tpretty-format the input file\n"
|
||||
" -s {ast,ir,asm,llvmir,asmd,ird}\tstop after generating AST/IR/Assembly\n"
|
||||
" -s {ast,ir,asm,asmd,ird}\tstop after generating AST/IR/Assembly\n"
|
||||
" -S \tcompile to assembly (.s file)\n"
|
||||
" -o <file>\tplace the output into <file>\n"
|
||||
" -O<level>\tenable optimization at <level> (e.g., -O0, -O1)\n";
|
||||
|
||||
4
testdata/performance/03_sort1.in
vendored
4
testdata/performance/03_sort1.in
vendored
File diff suppressed because one or more lines are too long
4
testdata/performance/fft0.in
vendored
4
testdata/performance/fft0.in
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user