@@ -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
453456bool 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+
567703bool LoopStrengthReduce::sweepDeadInstructions () const
568704{
569705 if (!func) {
0 commit comments