Skip to content

Commit 79374fd

Browse files
committed
opt: LoopConstantPromotion 跳过 div/mod 除数常量,恢复取模强度削减
const 全局 mod 被 LoopConstantPromotion 用 shl const,0 物化进 vreg 以省去每轮 lui+addiw 重物化,但这把可强度 削减的 srem x, 998244353(魔数乘法 ~5 周期)反而退化成 remw x, vreg (寄存器除法 ~40 周期)。强度削减收益远大于省一次重物化 第一遍扫描额外收集被用作 DIV_I/MOD_I 除数的常量,第二遍跳过它们 不予提升,保持字面量交给后端已有的 Granlund-Montgomery 魔数除法
1 parent 71f8912 commit 79374fd

1 file changed

Lines changed: 18 additions & 1 deletion

File tree

ir/passes/fixedPointFunctionPass/LoopConstantPromotion.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,26 @@ bool LoopConstantPromotion::run()
162162
continue;
163163
}
164164

165-
// 第一遍扫描:统计循环体内每个可提升常量的出现次数
165+
// 第一遍扫描:统计循环体内每个可提升常量的出现次数,
166+
// 并记录被用作 div/mod 除数的常量——这类常量保持字面量才能让后端
167+
// 把除法/取模强度削减为魔数乘法(远比省一次重物化划算),不予提升
166168
std::unordered_map<Value *, int32_t> useCounts;
169+
std::unordered_set<Value *> divisorConstants;
167170
for (auto * bb : *loopBody) {
168171
for (auto * inst : bb->getInstructions()) {
169172
if (!inst || inst->isDead()) {
170173
continue;
171174
}
172175

176+
if (auto * binary = dynamic_cast<BinaryInst *>(inst)) {
177+
const IRInstOperator op = binary->getOp();
178+
if (op == IRInstOperator::IRINST_OP_DIV_I || op == IRInstOperator::IRINST_OP_MOD_I) {
179+
if (dynamic_cast<ConstInteger *>(binary->getRHS()) != nullptr) {
180+
divisorConstants.insert(binary->getRHS());
181+
}
182+
}
183+
}
184+
173185
for (auto * operand : inst->getOperandsValue()) {
174186
if (shouldPromoteConstant(operand)) {
175187
++useCounts[operand];
@@ -187,6 +199,11 @@ bool LoopConstantPromotion::run()
187199
continue;
188200
}
189201

202+
// 作 div/mod 除数的常量保持字面量,交给后端强度削减
203+
if (divisorConstants.count(constant) > 0) {
204+
continue;
205+
}
206+
190207
// 创建物化指令:将常量"固化"为虚拟寄存器值
191208
// 创建物化指令:将常量"固化"为虚拟寄存器值,插入 preheader
192209
// 整数:shl const, 0 —— 左移零位等价于恒等操作

0 commit comments

Comments
 (0)