Skip to content

Commit d3eb90e

Browse files
committed
opt: 新增位模拟循环惯用法识别,逐位 srem/sdiv 循环折叠为原生按位指令
新增 BitwiseLoopIdiom pass(放在 PhiToSelect 之后): 匹配 a、b、len(32,-1)、result(0,+pow)、power(1,*2) 五 phi 规范循环, 对 (bit_a,bit_b) 四种组合做抽象求值得到累加条件真值表,按表判定 对应 and/or/xor。改写时在 preheader 插入 (a0|b0)>=0 守卫:两操作数 均非负时走原生按位指令快速路径(此时逐位模拟与原生指令严格等价), 负数仍走原循环,任意输入语义不变,符合优化合理性认定要求 配套为 IR 新增 IRINST_OP_AND_I/OR_I/XOR_I 三个算子:RISCV64 后端 生成 and/or/xor 及 12 位立即数形式,ConstProp 支持常量折叠, GVN 标记可交换,LICM 允许外提
1 parent bc81ff2 commit d3eb90e

12 files changed

Lines changed: 792 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ set(IR_SRCS
245245
ir/passes/fixedPointFunctionPass/InstCombine.cpp
246246
ir/passes/fixedPointFunctionPass/GVN.h
247247
ir/passes/fixedPointFunctionPass/GVN.cpp
248+
ir/passes/fixedPointFunctionPass/BitwiseLoopIdiom.h
249+
ir/passes/fixedPointFunctionPass/BitwiseLoopIdiom.cpp
248250
ir/passes/fixedPointFunctionPass/LoopTiling.h
249251
ir/passes/fixedPointFunctionPass/LoopTiling.cpp
250252
ir/passes/fixedPointFunctionPass/LoopStrengthReduce.h

backend/riscv64/InstSelectorRiscV64.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,9 @@ InstSelectorRiscV64::InstSelectorRiscV64(
507507
translatorHandlers[IRInstOperator::IRINST_OP_SHL_I] = &InstSelectorRiscV64::translate_shl;
508508
translatorHandlers[IRInstOperator::IRINST_OP_ASHR_I] = &InstSelectorRiscV64::translate_ashr;
509509
translatorHandlers[IRInstOperator::IRINST_OP_LSHR_I] = &InstSelectorRiscV64::translate_lshr;
510+
translatorHandlers[IRInstOperator::IRINST_OP_AND_I] = &InstSelectorRiscV64::translate_and;
511+
translatorHandlers[IRInstOperator::IRINST_OP_OR_I] = &InstSelectorRiscV64::translate_or;
512+
translatorHandlers[IRInstOperator::IRINST_OP_XOR_I] = &InstSelectorRiscV64::translate_xor;
510513
translatorHandlers[IRInstOperator::IRINST_OP_LT_I] = &InstSelectorRiscV64::translate_icmp;
511514
translatorHandlers[IRInstOperator::IRINST_OP_GT_I] = &InstSelectorRiscV64::translate_icmp;
512515
translatorHandlers[IRInstOperator::IRINST_OP_LE_I] = &InstSelectorRiscV64::translate_icmp;
@@ -1469,6 +1472,71 @@ void InstSelectorRiscV64::translate_shift(Instruction * inst,
14691472
storeResult(inst, dstReg, inst);
14701473
}
14711474

1475+
/// @brief 翻译按位与指令(and)
1476+
void InstSelectorRiscV64::translate_and(Instruction * inst)
1477+
{
1478+
translate_bitwise(inst, "and", "andi");
1479+
}
1480+
1481+
/// @brief 翻译按位或指令(or)
1482+
void InstSelectorRiscV64::translate_or(Instruction * inst)
1483+
{
1484+
translate_bitwise(inst, "or", "ori");
1485+
}
1486+
1487+
/// @brief 翻译按位异或指令(xor)
1488+
void InstSelectorRiscV64::translate_xor(Instruction * inst)
1489+
{
1490+
translate_bitwise(inst, "xor", "xori");
1491+
}
1492+
1493+
/// @brief 翻译按位运算指令的通用实现
1494+
///
1495+
/// RV64 的 and/or/xor 无 W 变体,对两个已按 i32 符号扩展的寄存器做按位
1496+
/// 运算结果仍保持符号扩展性质,因此无需额外的 sext.w。
1497+
/// 右操作数为 12 位有符号范围内的常量时使用立即数形式
1498+
void InstSelectorRiscV64::translate_bitwise(Instruction * inst,
1499+
const std::string & regOp,
1500+
const std::string & immOp)
1501+
{
1502+
auto * binary = dynamic_cast<BinaryInst *>(inst);
1503+
if (binary == nullptr) {
1504+
return;
1505+
}
1506+
1507+
int dstReg = getResultReg(inst);
1508+
LocalTempManager::Lease dstLease;
1509+
if (dstReg < 0) {
1510+
dstLease = tempMgr.borrow(inst);
1511+
dstReg = dstLease.reg();
1512+
}
1513+
1514+
OperandReg lhs = loadOperand(binary->getLHS(), inst, dstReg);
1515+
1516+
if (auto * rhsConst = asConstInteger(binary->getRHS())) {
1517+
const int32_t imm = rhsConst->getVal();
1518+
if (imm >= -2048 && imm <= 2047) {
1519+
iloc.inst(immOp,
1520+
PlatformRiscV64::regName[dstReg],
1521+
PlatformRiscV64::regName[lhs.reg],
1522+
std::to_string(imm));
1523+
releaseOperand(lhs);
1524+
storeResult(inst, dstReg, inst);
1525+
return;
1526+
}
1527+
}
1528+
1529+
const int rhsPreferredReg = lhs.reg != dstReg ? dstReg : -1;
1530+
OperandReg rhs = loadOperand(binary->getRHS(), inst, rhsPreferredReg < 0 ? dstReg : -1, rhsPreferredReg);
1531+
iloc.inst(regOp,
1532+
PlatformRiscV64::regName[dstReg],
1533+
PlatformRiscV64::regName[lhs.reg],
1534+
PlatformRiscV64::regName[rhs.reg]);
1535+
releaseOperand(rhs);
1536+
releaseOperand(lhs);
1537+
storeResult(inst, dstReg, inst);
1538+
}
1539+
14721540
/// @brief 翻译浮点二元运算的通用实现
14731541
///
14741542
/// float SSA值优先保存在FPR中,避免在热点浮点运算中反复fmv.w.x/fmv.x.w。

backend/riscv64/InstSelectorRiscV64.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ class InstSelectorRiscV64 {
138138
void translate_lshr(Instruction * inst);
139139
/// @brief 翻译移位指令的通用实现,根据移位量是否为常量选择立即数/寄存器形式
140140
void translate_shift(Instruction * inst, const std::string & regOp, const std::string & immOp);
141+
/// @brief 翻译按位与指令(and)
142+
void translate_and(Instruction * inst);
143+
/// @brief 翻译按位或指令(or)
144+
void translate_or(Instruction * inst);
145+
/// @brief 翻译按位异或指令(xor)
146+
void translate_xor(Instruction * inst);
147+
/// @brief 翻译按位运算指令的通用实现,右操作数为 12 位有符号常量时用立即数形式
148+
void translate_bitwise(Instruction * inst, const std::string & regOp, const std::string & immOp);
141149
/// @brief 翻译icmp指令(整数比较)
142150
void translate_icmp(Instruction * inst);
143151
/// @brief 翻译fcmp指令(浮点比较)

ir/Instruction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ bool Instruction::isSpeculatable() const
126126
case IRInstOperator::IRINST_OP_SHL_I:
127127
case IRInstOperator::IRINST_OP_ASHR_I:
128128
case IRInstOperator::IRINST_OP_LSHR_I:
129+
case IRInstOperator::IRINST_OP_AND_I:
130+
case IRInstOperator::IRINST_OP_OR_I:
131+
case IRInstOperator::IRINST_OP_XOR_I:
129132
case IRInstOperator::IRINST_OP_LT_I:
130133
case IRInstOperator::IRINST_OP_GT_I:
131134
case IRInstOperator::IRINST_OP_LE_I:

ir/Instruction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ enum class IRInstOperator : std::int8_t {
2222
IRINST_OP_SHL_I, ///< 逻辑左移
2323
IRINST_OP_ASHR_I, ///< 算术右移(保留符号位)
2424
IRINST_OP_LSHR_I, ///< 逻辑右移(高位补 0)
25+
IRINST_OP_AND_I, ///< 按位与
26+
IRINST_OP_OR_I, ///< 按位或
27+
IRINST_OP_XOR_I, ///< 按位异或
2528
IRINST_OP_LT_I,
2629
IRINST_OP_GT_I,
2730
IRINST_OP_LE_I,

ir/Instructions/BinaryInst.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ const char * BinaryInst::opToLLVMName(IRInstOperator op)
4343
return "ashr";
4444
case IRInstOperator::IRINST_OP_LSHR_I:
4545
return "lshr";
46+
case IRInstOperator::IRINST_OP_AND_I:
47+
return "and";
48+
case IRInstOperator::IRINST_OP_OR_I:
49+
return "or";
50+
case IRInstOperator::IRINST_OP_XOR_I:
51+
return "xor";
4652
case IRInstOperator::IRINST_OP_ADD_F:
4753
return "fadd";
4854
case IRInstOperator::IRINST_OP_SUB_F:

ir/passes/PassManager.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "Module.h"
1515
#include "fixedPointFunctionPass/CFGSimplify.h"
1616
#include "fixedPointFunctionPass/ConstProp.h"
17+
#include "fixedPointFunctionPass/BitwiseLoopIdiom.h"
1718
#include "fixedPointFunctionPass/CanonicalizeLoop.h"
1819
#include "fixedPointFunctionPass/DeadInstElim.h"
1920
#include "fixedPointFunctionPass/GVN.h"
@@ -287,6 +288,11 @@ void PassManager::registerDefaultOptimizationPipeline(int32_t optLevel, bool ena
287288
PhiToSelect pass(func);
288289
return pass.run();
289290
});
291+
// 位模拟循环惯用法识别:依赖 PhiToSelect 把累加分支规范成 select 形态
292+
registerFixedPointFunctionPass("BitwiseLoopIdiom", [this](Function * func) {
293+
BitwiseLoopIdiom pass(func, module);
294+
return pass.run();
295+
});
290296
registerFixedPointFunctionPass("InstCombine", [this](Function * func) {
291297
InstCombine pass(func, module);
292298
return pass.run();

0 commit comments

Comments
 (0)