Compare commits
8 Commits
midend-Loo
...
midend-Loo
| Author | SHA1 | Date | |
|---|---|---|---|
| 7547d34598 | |||
| 06a368db39 | |||
| 48865fa805 | |||
| 8b5123460b | |||
| cd27f5fda9 | |||
| 60cb8d6e49 | |||
| ea944f6ba0 | |||
| 0c8a156485 |
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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -20,6 +20,42 @@ 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 循环特征信息结构 - 基础循环分析阶段
|
||||
* 存储循环的基本特征信息,为后续精确分析提供基础
|
||||
@ -33,13 +69,13 @@ struct LoopCharacteristics {
|
||||
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
||||
bool isInnermost; // 是否为最内层循环
|
||||
|
||||
// ========== 基础归纳变量分析 ==========
|
||||
std::vector<Value*> basicInductionVars; // 基本归纳变量
|
||||
std::map<Value*, int> inductionSteps; // 归纳变量的步长(简化)
|
||||
// ========== 归纳变量分析 ==========
|
||||
|
||||
// ========== 基础循环不变量分析 ==========
|
||||
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
||||
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
||||
|
||||
std::vector<std::unique_ptr<InductionVarInfo>> InductionVars; // 归纳变量
|
||||
|
||||
// ========== 基础边界分析 ==========
|
||||
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
||||
@ -307,6 +343,12 @@ private:
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
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); // 简单的内存模式检查
|
||||
};
|
||||
|
||||
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
|
||||
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
|
||||
@ -19,6 +19,8 @@ add_library(midend_lib STATIC
|
||||
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
|
||||
)
|
||||
|
||||
@ -779,7 +779,29 @@ void BinaryInst::print(std::ostream &os) const {
|
||||
printOperand(os, getRhs());
|
||||
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() << " ";
|
||||
|
||||
@ -80,8 +80,8 @@ void LoopCharacteristicsResult::print() const {
|
||||
std::cout << std::endl;
|
||||
|
||||
// 归纳变量
|
||||
if (!chars->basicInductionVars.empty()) {
|
||||
std::cout << " Basic Induction Vars: " << chars->basicInductionVars.size() << std::endl;
|
||||
if (!chars->InductionVars.empty()) {
|
||||
std::cout << " Induction Vars: " << chars->InductionVars.size() << std::endl;
|
||||
}
|
||||
|
||||
// 循环不变量
|
||||
@ -282,28 +282,338 @@ void LoopCharacteristicsPass::analyzeBasicMemoryAccessPatterns(Loop* loop, LoopC
|
||||
}
|
||||
}
|
||||
|
||||
void LoopCharacteristicsPass::identifyBasicInductionVariables(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 寻找基本归纳变量(简化版本)
|
||||
BasicBlock* header = loop->getHeader();
|
||||
bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) {
|
||||
// 简化的基础归纳变量检测
|
||||
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
||||
if (!phiInst) return false;
|
||||
|
||||
// 遍历循环头的phi指令,寻找基本归纳变量模式
|
||||
for (auto& inst : header->getInstructions()) {
|
||||
auto* phiInst = dynamic_cast<PhiInst*>(inst.get());
|
||||
if (!phiInst) continue;
|
||||
|
||||
// 检查phi指令是否符合基本归纳变量模式
|
||||
if (isBasicInductionVariable(phiInst, loop)) {
|
||||
characteristics->basicInductionVars.push_back(phiInst);
|
||||
characteristics->inductionSteps[phiInst] = 1; // 简化:默认步长为1
|
||||
|
||||
if (DEBUG)
|
||||
std::cout << " Found basic induction variable: " << phiInst->getName() << std::endl;
|
||||
// 检查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; // 可能为空
|
||||
|
||||
@ -334,7 +644,7 @@ void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharac
|
||||
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
||||
// 简化的基础边界分析
|
||||
// 检查是否有静态可确定的循环次数(简化版本)
|
||||
if (characteristics->isCountingLoop && !characteristics->basicInductionVars.empty()) {
|
||||
if (characteristics->isCountingLoop && !characteristics->InductionVars.empty()) {
|
||||
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
||||
if (characteristics->instructionCount < 10) {
|
||||
characteristics->staticTripCount = 100; // 简化估计
|
||||
@ -373,22 +683,97 @@ void LoopCharacteristicsPass::evaluateBasicOptimizationOpportunities(Loop* loop,
|
||||
|
||||
// ========== 辅助方法实现 ==========
|
||||
|
||||
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; // 简化:有来自循环内的值就认为是基础归纳变量
|
||||
// 递归识别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情形一般不再递归下游
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
if (DEBUG) {
|
||||
std::cout << " Finished analyzing uses of: " << root->getName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归/推进式判定
|
||||
|
||||
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
|
||||
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
@ -15,6 +15,8 @@
|
||||
#include "LargeArrayToGlobal.h"
|
||||
#include "LoopNormalization.h"
|
||||
#include "LICM.h"
|
||||
#include "LoopStrengthReduction.h"
|
||||
#include "InductionVariableElimination.h"
|
||||
#include "Pass.h"
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
@ -70,6 +72,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
registerOptimizationPass<Mem2Reg>(builderIR);
|
||||
registerOptimizationPass<LoopNormalizationPass>(builderIR);
|
||||
registerOptimizationPass<LICM>(builderIR);
|
||||
registerOptimizationPass<LoopStrengthReduction>(builderIR);
|
||||
registerOptimizationPass<InductionVariableElimination>();
|
||||
registerOptimizationPass<Reg2Mem>(builderIR);
|
||||
|
||||
registerOptimizationPass<SCCP>(builderIR);
|
||||
@ -137,16 +141,18 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
||||
this->clearPasses();
|
||||
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 and LICM Optimizations ===\n";
|
||||
std::cout << "=== IR After Loop Normalization, LICM, and Strength Reduction Optimizations ===\n";
|
||||
printPasses();
|
||||
}
|
||||
|
||||
this->clearPasses();
|
||||
this->addPass(&Reg2Mem::ID);
|
||||
this->run();
|
||||
// this->clearPasses();
|
||||
// this->addPass(&Reg2Mem::ID);
|
||||
// this->run();
|
||||
|
||||
if(DEBUG) {
|
||||
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
|
||||
|
||||
@ -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";
|
||||
|
||||
Reference in New Issue
Block a user