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> 或独立的浮点常量存储来处理浮点数。
|
在提供的代码中,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));
|
CurMBB->addInstruction(std::move(instr));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Instruction::kSRA: {
|
case Instruction::kSra: {
|
||||||
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
|
auto rhs_const = dynamic_cast<ConstantInteger*>(rhs);
|
||||||
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
|
auto instr = std::make_unique<MachineInstr>(RVOpcodes::SRAIW);
|
||||||
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
instr->addOperand(std::make_unique<RegOperand>(dest_vreg));
|
||||||
|
|||||||
@@ -727,6 +727,7 @@ class Instruction : public User {
|
|||||||
kFCmpGE = 0x1UL << 20,
|
kFCmpGE = 0x1UL << 20,
|
||||||
kAnd = 0x1UL << 21,
|
kAnd = 0x1UL << 21,
|
||||||
kOr = 0x1UL << 22,
|
kOr = 0x1UL << 22,
|
||||||
|
// kXor = 0x1UL << 46,
|
||||||
// Unary
|
// Unary
|
||||||
kNeg = 0x1UL << 23,
|
kNeg = 0x1UL << 23,
|
||||||
kNot = 0x1UL << 24,
|
kNot = 0x1UL << 24,
|
||||||
@@ -751,8 +752,10 @@ class Instruction : public User {
|
|||||||
kPhi = 0x1UL << 39,
|
kPhi = 0x1UL << 39,
|
||||||
kBitItoF = 0x1UL << 40,
|
kBitItoF = 0x1UL << 40,
|
||||||
kBitFtoI = 0x1UL << 41,
|
kBitFtoI = 0x1UL << 41,
|
||||||
kSRA = 0x1UL << 42,
|
kSrl = 0x1UL << 42, // 逻辑右移
|
||||||
kMulh = 0x1UL << 43
|
kSll = 0x1UL << 43, // 逻辑左移
|
||||||
|
kSra = 0x1UL << 44, // 算术右移
|
||||||
|
kMulh = 0x1UL << 45
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -855,8 +858,14 @@ public:
|
|||||||
return "BitItoF";
|
return "BitItoF";
|
||||||
case kBitFtoI:
|
case kBitFtoI:
|
||||||
return "BitFtoI";
|
return "BitFtoI";
|
||||||
case kSRA:
|
case kSrl:
|
||||||
|
return "lshr";
|
||||||
|
case kSll:
|
||||||
|
return "shl";
|
||||||
|
case kSra:
|
||||||
return "ashr";
|
return "ashr";
|
||||||
|
case kMulh:
|
||||||
|
return "mulh";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@@ -868,7 +877,7 @@ public:
|
|||||||
|
|
||||||
bool isBinary() const {
|
bool isBinary() const {
|
||||||
static constexpr uint64_t BinaryOpMask =
|
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);
|
(kICmpEQ | kICmpNE | kICmpLT | kICmpGT | kICmpLE | kICmpGE);
|
||||||
return kind & BinaryOpMask;
|
return kind & BinaryOpMask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,8 +217,14 @@ class IRBuilder {
|
|||||||
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
BinaryInst * createOrInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
return createBinaryInst(Instruction::kOr, Type::getIntType(), lhs, rhs, name);
|
||||||
} ///< 创建按位或指令
|
} ///< 创建按位或指令
|
||||||
BinaryInst * createSRAInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
BinaryInst * createSllInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
return createBinaryInst(Instruction::kSRA, Type::getIntType(), lhs, rhs, 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 = "") {
|
BinaryInst * createMulhInst(Value *lhs, Value *rhs, const std::string &name = "") {
|
||||||
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
|
return createBinaryInst(Instruction::kMulh, Type::getIntType(), lhs, rhs, name);
|
||||||
|
|||||||
@@ -20,6 +20,42 @@ namespace sysy {
|
|||||||
// 前向声明
|
// 前向声明
|
||||||
class LoopCharacteristicsResult;
|
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 循环特征信息结构 - 基础循环分析阶段
|
* @brief 循环特征信息结构 - 基础循环分析阶段
|
||||||
* 存储循环的基本特征信息,为后续精确分析提供基础
|
* 存储循环的基本特征信息,为后续精确分析提供基础
|
||||||
@@ -33,14 +69,14 @@ struct LoopCharacteristics {
|
|||||||
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
bool hasComplexControlFlow; // 是否有复杂控制流 (break, continue)
|
||||||
bool isInnermost; // 是否为最内层循环
|
bool isInnermost; // 是否为最内层循环
|
||||||
|
|
||||||
// ========== 基础归纳变量分析 ==========
|
// ========== 归纳变量分析 ==========
|
||||||
std::vector<Value*> basicInductionVars; // 基本归纳变量
|
|
||||||
std::map<Value*, int> inductionSteps; // 归纳变量的步长(简化)
|
|
||||||
|
|
||||||
// ========== 基础循环不变量分析 ==========
|
// ========== 基础循环不变量分析 ==========
|
||||||
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
std::unordered_set<Value*> loopInvariants; // 循环不变量
|
||||||
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
std::unordered_set<Instruction*> invariantInsts; // 可提升的不变指令
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<InductionVarInfo>> InductionVars; // 归纳变量
|
||||||
|
|
||||||
// ========== 基础边界分析 ==========
|
// ========== 基础边界分析 ==========
|
||||||
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
std::optional<int> staticTripCount; // 静态循环次数(如果可确定)
|
||||||
bool hasKnownBounds; // 是否有已知边界
|
bool hasKnownBounds; // 是否有已知边界
|
||||||
@@ -307,6 +343,12 @@ private:
|
|||||||
|
|
||||||
// ========== 辅助方法 ==========
|
// ========== 辅助方法 ==========
|
||||||
bool isClassicLoopInvariant(Value* val, Loop* loop, const std::unordered_set<Value*>& invariants);
|
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 isBasicInductionVariable(Value* val, Loop* loop);
|
||||||
bool hasSimpleMemoryPattern(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/SCCP.cpp
|
||||||
Pass/Optimize/LoopNormalization.cpp
|
Pass/Optimize/LoopNormalization.cpp
|
||||||
Pass/Optimize/LICM.cpp
|
Pass/Optimize/LICM.cpp
|
||||||
|
Pass/Optimize/LoopStrengthReduction.cpp
|
||||||
|
Pass/Optimize/InductionVariableElimination.cpp
|
||||||
Pass/Optimize/BuildCFG.cpp
|
Pass/Optimize/BuildCFG.cpp
|
||||||
Pass/Optimize/LargeArrayToGlobal.cpp
|
Pass/Optimize/LargeArrayToGlobal.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -779,7 +779,29 @@ void BinaryInst::print(std::ostream &os) const {
|
|||||||
printOperand(os, getRhs());
|
printOperand(os, getRhs());
|
||||||
os << "\n ";
|
os << "\n ";
|
||||||
printVarName(os, this) << " = zext i1 %" << tmpName << " to i32";
|
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) << " = ";
|
printVarName(os, this) << " = ";
|
||||||
os << getKindString() << " " << *getType() << " ";
|
os << getKindString() << " " << *getType() << " ";
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ void LoopCharacteristicsResult::print() const {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
// 归纳变量
|
// 归纳变量
|
||||||
if (!chars->basicInductionVars.empty()) {
|
if (!chars->InductionVars.empty()) {
|
||||||
std::cout << " Basic Induction Vars: " << chars->basicInductionVars.size() << std::endl;
|
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) {
|
bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) {
|
||||||
// 寻找基本归纳变量(简化版本)
|
// 简化的基础归纳变量检测
|
||||||
BasicBlock* header = loop->getHeader();
|
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
||||||
|
if (!phiInst) return false;
|
||||||
|
|
||||||
// 遍历循环头的phi指令,寻找基本归纳变量模式
|
// 检查phi指令是否在循环头
|
||||||
for (auto& inst : header->getInstructions()) {
|
if (phiInst->getParent() != loop->getHeader()) return false;
|
||||||
auto* phiInst = dynamic_cast<PhiInst*>(inst.get());
|
|
||||||
if (!phiInst) continue;
|
|
||||||
|
|
||||||
// 检查phi指令是否符合基本归纳变量模式
|
// 检查是否有来自循环内的更新
|
||||||
if (isBasicInductionVariable(phiInst, loop)) {
|
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
||||||
characteristics->basicInductionVars.push_back(phiInst);
|
if (loop->contains(incomingBB)) {
|
||||||
characteristics->inductionSteps[phiInst] = 1; // 简化:默认步长为1
|
return true; // 简化:有来自循环内的值就认为是基础归纳变量
|
||||||
|
|
||||||
if (DEBUG)
|
|
||||||
std::cout << " Found basic induction variable: " << phiInst->getName() << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharacteristics* characteristics) {
|
||||||
// 经典推进法:反复遍历,直到收敛
|
// 经典推进法:反复遍历,直到收敛 TODO:优化
|
||||||
bool changed;
|
bool changed;
|
||||||
std::unordered_set<Value*> invariants = characteristics->loopInvariants; // 可能为空
|
std::unordered_set<Value*> invariants = characteristics->loopInvariants; // 可能为空
|
||||||
|
|
||||||
@@ -334,7 +644,7 @@ void LoopCharacteristicsPass::identifyBasicLoopInvariants(Loop* loop, LoopCharac
|
|||||||
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
void LoopCharacteristicsPass::analyzeBasicLoopBounds(Loop* loop, LoopCharacteristics* characteristics) {
|
||||||
// 简化的基础边界分析
|
// 简化的基础边界分析
|
||||||
// 检查是否有静态可确定的循环次数(简化版本)
|
// 检查是否有静态可确定的循环次数(简化版本)
|
||||||
if (characteristics->isCountingLoop && !characteristics->basicInductionVars.empty()) {
|
if (characteristics->isCountingLoop && !characteristics->InductionVars.empty()) {
|
||||||
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
// 简化:如果是计数循环且有基本归纳变量,尝试确定循环次数
|
||||||
if (characteristics->instructionCount < 10) {
|
if (characteristics->instructionCount < 10) {
|
||||||
characteristics->staticTripCount = 100; // 简化估计
|
characteristics->staticTripCount = 100; // 简化估计
|
||||||
@@ -373,22 +683,97 @@ void LoopCharacteristicsPass::evaluateBasicOptimizationOpportunities(Loop* loop,
|
|||||||
|
|
||||||
// ========== 辅助方法实现 ==========
|
// ========== 辅助方法实现 ==========
|
||||||
|
|
||||||
bool LoopCharacteristicsPass::isBasicInductionVariable(Value* val, Loop* loop) {
|
// 递归识别DIV,支持线性与复杂归纳变量
|
||||||
// 简化的基础归纳变量检测
|
void LoopCharacteristicsPass::findDerivedInductionVars(
|
||||||
auto* phiInst = dynamic_cast<PhiInst*>(val);
|
Value* root,
|
||||||
if (!phiInst) return false;
|
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);
|
||||||
|
|
||||||
// 检查phi指令是否在循环头
|
if (DEBUG) {
|
||||||
if (phiInst->getParent() != loop->getHeader()) return false;
|
std::cout << " Analyzing uses of: " << root->getName() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否有来自循环内的更新
|
for (auto use : root->getUses()) {
|
||||||
for (auto& [incomingBB, incomingVal] : phiInst->getIncomingValues()) {
|
auto user = use->getUser();
|
||||||
if (loop->contains(incomingBB)) {
|
Instruction* inst = dynamic_cast<Instruction*>(user);
|
||||||
return true; // 简化:有来自循环内的值就认为是基础归纳变量
|
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 "LargeArrayToGlobal.h"
|
||||||
#include "LoopNormalization.h"
|
#include "LoopNormalization.h"
|
||||||
#include "LICM.h"
|
#include "LICM.h"
|
||||||
|
#include "LoopStrengthReduction.h"
|
||||||
|
#include "InductionVariableElimination.h"
|
||||||
#include "Pass.h"
|
#include "Pass.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -70,6 +72,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
registerOptimizationPass<Mem2Reg>(builderIR);
|
registerOptimizationPass<Mem2Reg>(builderIR);
|
||||||
registerOptimizationPass<LoopNormalizationPass>(builderIR);
|
registerOptimizationPass<LoopNormalizationPass>(builderIR);
|
||||||
registerOptimizationPass<LICM>(builderIR);
|
registerOptimizationPass<LICM>(builderIR);
|
||||||
|
registerOptimizationPass<LoopStrengthReduction>(builderIR);
|
||||||
|
registerOptimizationPass<InductionVariableElimination>();
|
||||||
registerOptimizationPass<Reg2Mem>(builderIR);
|
registerOptimizationPass<Reg2Mem>(builderIR);
|
||||||
|
|
||||||
registerOptimizationPass<SCCP>(builderIR);
|
registerOptimizationPass<SCCP>(builderIR);
|
||||||
@@ -137,16 +141,18 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
this->clearPasses();
|
this->clearPasses();
|
||||||
this->addPass(&LoopNormalizationPass::ID);
|
this->addPass(&LoopNormalizationPass::ID);
|
||||||
this->addPass(&LICM::ID);
|
this->addPass(&LICM::ID);
|
||||||
|
this->addPass(&LoopStrengthReduction::ID);
|
||||||
|
this->addPass(&InductionVariableElimination::ID);
|
||||||
this->run();
|
this->run();
|
||||||
|
|
||||||
if(DEBUG) {
|
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();
|
printPasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->clearPasses();
|
// this->clearPasses();
|
||||||
this->addPass(&Reg2Mem::ID);
|
// this->addPass(&Reg2Mem::ID);
|
||||||
this->run();
|
// this->run();
|
||||||
|
|
||||||
if(DEBUG) {
|
if(DEBUG) {
|
||||||
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
|
std::cout << "=== IR After Reg2Mem Optimizations ===\n";
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
case Kind::kMul:
|
case Kind::kMul:
|
||||||
case Kind::kDiv:
|
case Kind::kDiv:
|
||||||
case Kind::kRem:
|
case Kind::kRem:
|
||||||
case Kind::kSRA:
|
case Kind::kSrl:
|
||||||
|
case Kind::kSll:
|
||||||
|
case Kind::kSra:
|
||||||
case Kind::kMulh:
|
case Kind::kMulh:
|
||||||
case Kind::kFAdd:
|
case Kind::kFAdd:
|
||||||
case Kind::kFSub:
|
case Kind::kFSub:
|
||||||
@@ -274,7 +276,9 @@ void SysYPrinter::printInst(Instruction *pInst) {
|
|||||||
case Kind::kMul: std::cout << "mul"; break;
|
case Kind::kMul: std::cout << "mul"; break;
|
||||||
case Kind::kDiv: std::cout << "sdiv"; break;
|
case Kind::kDiv: std::cout << "sdiv"; break;
|
||||||
case Kind::kRem: std::cout << "srem"; 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::kMulh: std::cout << "mulh"; break;
|
||||||
case Kind::kFAdd: std::cout << "fadd"; break;
|
case Kind::kFAdd: std::cout << "fadd"; break;
|
||||||
case Kind::kFSub: std::cout << "fsub"; break;
|
case Kind::kFSub: std::cout << "fsub"; break;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ void usage(int code) {
|
|||||||
"Supported options:\n"
|
"Supported options:\n"
|
||||||
" -h \tprint help message and exit\n"
|
" -h \tprint help message and exit\n"
|
||||||
" -f \tpretty-format the input file\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"
|
" -S \tcompile to assembly (.s file)\n"
|
||||||
" -o <file>\tplace the output into <file>\n"
|
" -o <file>\tplace the output into <file>\n"
|
||||||
" -O<level>\tenable optimization at <level> (e.g., -O0, -O1)\n";
|
" -O<level>\tenable optimization at <level> (e.g., -O0, -O1)\n";
|
||||||
|
|||||||
Reference in New Issue
Block a user