Skip to content

Commit 71f8912

Browse files
committed
opt: LoopStrengthReduce 支持指针IV基址+循环不变列偏移的强度削减
新增 reducePointerIVOffsetGEP:识别 gep(指针IV, 0, 不变索引) 的下标式 访问,把不变列偏移折入新指针 IV 的起点——init=gep(基址起点, 0, j), step=每轮前进一行(step*N 个元素)。改写后内层循环直接 lw 0(ptr)、 ptr += 行步长,零地址重算。 新增"不变索引支配 preheader"安全门保证可在 preheader 重物化
1 parent d3eb90e commit 71f8912

2 files changed

Lines changed: 143 additions & 1 deletion

File tree

ir/passes/fixedPointFunctionPass/LoopStrengthReduce.cpp

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,10 @@ bool LoopStrengthReduce::tryReduceHeader(BasicBlock * header)
447447
return false;
448448
}
449449

450-
return reduceFirstCandidate(header, preheader, latch, scev, loopBody);
450+
if (reduceFirstCandidate(header, preheader, latch, scev, loopBody)) {
451+
return true;
452+
}
453+
return reducePointerIVOffsetGEP(header, preheader, latch, scev, loopBody);
451454
}
452455

453456
bool LoopStrengthReduce::reduceFirstCandidate(BasicBlock * header,
@@ -564,6 +567,139 @@ bool LoopStrengthReduce::reduceFirstCandidate(BasicBlock * header,
564567
return true;
565568
}
566569

570+
bool LoopStrengthReduce::reducePointerIVOffsetGEP(BasicBlock * header,
571+
BasicBlock * preheader,
572+
BasicBlock * latch,
573+
ScalarEvolution & scev,
574+
const std::unordered_set<BasicBlock *> & loopBody)
575+
{
576+
auto & domTree = func->getAnalysisCache().getOrCompute<DominatorTree>([this] { return DominatorTree(func); });
577+
578+
// 寻找种子:下标式 gep(P, idx),P 为本循环的指针型归纳 phi,idx 循环不变,结果为标量指针
579+
GetElementPtrInst * seed = nullptr;
580+
const ScalarEvolution::AddRecurrenceExpr * baseRec = nullptr;
581+
for (auto * bb : func->getBlocks()) {
582+
if (loopBody.find(bb) == loopBody.end()) {
583+
continue;
584+
}
585+
586+
for (auto * inst : bb->getInstructions()) {
587+
auto * gep = dynamic_cast<GetElementPtrInst *>(inst);
588+
// 种子必须是下标式 gep(decay=true,渲染为 ", i32 0, i32 idx"),
589+
// 即从行数组基址按列索引取标量元素
590+
if (!gep || gep->isDead() || !gep->isArrayDecayGEP()) {
591+
continue;
592+
}
593+
594+
// 列索引必须循环不变,且其定义支配 preheader(保证可在 preheader 重物化)
595+
Value * index = gep->getIndexOperand();
596+
if (!isLoopInvariantValue(index, loopBody) || !allUsesStayInLoop(gep, loopBody)) {
597+
continue;
598+
}
599+
if (auto * indexInst = dynamic_cast<Instruction *>(index)) {
600+
if (!indexInst->getParentBlock() || !domTree.dominates(indexInst->getParentBlock(), preheader)) {
601+
continue;
602+
}
603+
}
604+
605+
// 基址必须是本循环的指针型仿射递推
606+
const auto * rec = scev.getAddRecurrence(gep->getBasePointer());
607+
if (!rec || !rec->isPointerRecurrence() || rec->getLoopHeader() != header ||
608+
rec->getPreheader() != preheader || rec->getLatch() != latch) {
609+
continue;
610+
}
611+
612+
// 结果必须是标量指针(int*/float*),避免多维数组步长换算的复杂性
613+
auto * resultPtrType = dynamic_cast<PointerType *>(gep->getType());
614+
if (!resultPtrType) {
615+
continue;
616+
}
617+
const Type * pointee = resultPtrType->getPointeeType();
618+
if (!pointee || !(pointee->isIntegerType() || pointee->isFloatType())) {
619+
continue;
620+
}
621+
622+
seed = gep;
623+
baseRec = rec;
624+
break;
625+
}
626+
627+
if (seed) {
628+
break;
629+
}
630+
}
631+
632+
if (!seed) {
633+
return false;
634+
}
635+
636+
// 取基址所指行数组的长度 N([N x T]*),新指针 IV 每步前进 step*N 个元素
637+
Value * basePtr = seed->getBasePointer();
638+
auto * basePtrType = dynamic_cast<PointerType *>(basePtr->getType());
639+
if (!basePtrType) {
640+
return false;
641+
}
642+
const auto * rowArrayType = dynamic_cast<const ArrayType *>(basePtrType->getPointeeType());
643+
if (!rowArrayType) {
644+
return false;
645+
}
646+
const int64_t newStep = static_cast<int64_t>(baseRec->getStep()) * rowArrayType->getNumElements();
647+
if (newStep <= 0 || newStep > std::numeric_limits<int32_t>::max()) {
648+
return false;
649+
}
650+
651+
Value * baseInit = baseRec->getStartValue();
652+
if (!baseInit) {
653+
return false;
654+
}
655+
656+
Type * elemPtrType = seed->getType();
657+
Value * invariantIndex = seed->getIndexOperand();
658+
659+
// 收集所有同基址、同不变索引的下标式 gep,可被同一新指针 IV 覆盖
660+
std::vector<GetElementPtrInst *> targets;
661+
for (auto * bb : func->getBlocks()) {
662+
if (loopBody.find(bb) == loopBody.end()) {
663+
continue;
664+
}
665+
666+
for (auto * inst : bb->getInstructions()) {
667+
auto * gep = dynamic_cast<GetElementPtrInst *>(inst);
668+
if (!gep || gep->isDead() || !gep->isArrayDecayGEP()) {
669+
continue;
670+
}
671+
if (gep->getBasePointer() == basePtr && gep->getIndexOperand() == invariantIndex &&
672+
gep->getType() == elemPtrType && allUsesStayInLoop(gep, loopBody)) {
673+
targets.push_back(gep);
674+
}
675+
}
676+
}
677+
if (targets.empty()) {
678+
return false;
679+
}
680+
681+
// 新指针 IV:init = gep(baseInit, 0, idx)(下标式 decay=true,得 T*,把不变列偏移折入起点),
682+
// step = gep(ptrPhi, step*N)(指针式 decay=false,前进一行)
683+
auto * initPtr = new GetElementPtrInst(func, baseInit, invariantIndex, elemPtrType, true);
684+
auto * ptrPhi = new PhiInst(func, elemPtrType);
685+
auto * stepValue = mod->newConstInteger(seed->getIndexOperand()->getType(), static_cast<int32_t>(newStep));
686+
auto * nextPtr = new GetElementPtrInst(func, ptrPhi, stepValue, elemPtrType, false);
687+
688+
insertBeforeTerminator(preheader, initPtr);
689+
insertPhiAtHeader(header, ptrPhi);
690+
insertBeforeTerminator(latch, nextPtr);
691+
ptrPhi->addIncoming(initPtr, preheader);
692+
ptrPhi->addIncoming(nextPtr, latch);
693+
694+
for (auto * gep : targets) {
695+
gep->replaceAllUseWith(ptrPhi);
696+
gep->clearOperands();
697+
gep->setDead(true);
698+
}
699+
700+
return true;
701+
}
702+
567703
bool LoopStrengthReduce::sweepDeadInstructions() const
568704
{
569705
if (!func) {

ir/passes/fixedPointFunctionPass/LoopStrengthReduce.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ class LoopStrengthReduce {
3030
BasicBlock * latch,
3131
class ScalarEvolution & scev,
3232
const std::unordered_set<BasicBlock *> & loopBody);
33+
/// @brief 将 gep(指针IV基址, 0, 循环不变索引) 改写为折入不变列偏移的新指针 recurrence
34+
bool reducePointerIVOffsetGEP(BasicBlock * header,
35+
BasicBlock * preheader,
36+
BasicBlock * latch,
37+
class ScalarEvolution & scev,
38+
const std::unordered_set<BasicBlock *> & loopBody);
3339
bool sweepDeadInstructions() const;
3440

3541
Function * func = nullptr;

0 commit comments

Comments
 (0)