diff options
author | chenglin.bi <chenglin.bi@linaro.org> | 2023-02-10 16:49:56 +0800 |
---|---|---|
committer | chenglin.bi <chenglin.bi@linaro.org> | 2023-02-10 16:52:00 +0800 |
commit | 14dedd9cf596d1e6cfd8d24009393e8b8f1a3dc0 (patch) | |
tree | c3f5111c593fe6a850e0c4d9cc721f64ee9febce /llvm/lib | |
parent | d9283e79d826d83ec4d124baede855475e99611b (diff) | |
download | llvm-14dedd9cf596d1e6cfd8d24009393e8b8f1a3dc0.zip llvm-14dedd9cf596d1e6cfd8d24009393e8b8f1a3dc0.tar.gz llvm-14dedd9cf596d1e6cfd8d24009393e8b8f1a3dc0.tar.bz2 |
[Reland][LSR] Hoist IVInc to loop header if its all uses are in the loop header
Original code will cause crash when the load/store memory type is structure because isIndexedLoadLegal/isIndexedStore doesn't support struct type.
So we limit the load/store memory type to integer.
Origin commit message:
When the latch block is different from header block, IVInc will be expanded in the latch loop. We can't generate the post index load/store this case.
But if the IVInc only used in the loop, actually we still can use the post index load/store because when exit loop we don't care the last IVInc value.
So, trying to hoist IVInc to help backend to generate more post index load/store.
Fix #53625
Reviewed By: eopXD
Differential Revision: https://reviews.llvm.org/D138636
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index ed7fc25..b9d67be 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -5643,6 +5643,36 @@ void LSRInstance::Rewrite(const LSRUse &LU, const LSRFixup &LF, DeadInsts.emplace_back(OperandIsInstr); } +// Trying to hoist the IVInc to loop header if all IVInc users are in +// the loop header. It will help backend to generate post index load/store +// when the latch block is different from loop header block. +static bool canHoistIVInc(const TargetTransformInfo &TTI, const LSRFixup &Fixup, + const LSRUse &LU, Instruction *IVIncInsertPos, + Loop *L) { + if (LU.Kind != LSRUse::Address) + return false; + + // For now this code do the conservative optimization, only work for + // the header block. Later we can hoist the IVInc to the block post + // dominate all users. + BasicBlock *LHeader = L->getHeader(); + if (IVIncInsertPos->getParent() == LHeader) + return false; + + if (!Fixup.OperandValToReplace || + any_of(Fixup.OperandValToReplace->users(), [&LHeader](User *U) { + Instruction *UI = cast<Instruction>(U); + return UI->getParent() != LHeader; + })) + return false; + + Instruction *I = Fixup.UserInst; + Type *Ty = I->getType(); + return Ty->isIntegerTy() && + ((isa<LoadInst>(I) && TTI.isIndexedLoadLegal(TTI.MIM_PostInc, Ty)) || + (isa<StoreInst>(I) && TTI.isIndexedStoreLegal(TTI.MIM_PostInc, Ty))); +} + /// Rewrite all the fixup locations with new values, following the chosen /// solution. void LSRInstance::ImplementSolution( @@ -5651,8 +5681,6 @@ void LSRInstance::ImplementSolution( // we can remove them after we are done working. SmallVector<WeakTrackingVH, 16> DeadInsts; - Rewriter.setIVIncInsertPos(L, IVIncInsertPos); - // Mark phi nodes that terminate chains so the expander tries to reuse them. for (const IVChain &Chain : IVChainVec) { if (PHINode *PN = dyn_cast<PHINode>(Chain.tailUserInst())) @@ -5662,6 +5690,11 @@ void LSRInstance::ImplementSolution( // Expand the new value definitions and update the users. for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) for (const LSRFixup &Fixup : Uses[LUIdx].Fixups) { + Instruction *InsertPos = + canHoistIVInc(TTI, Fixup, Uses[LUIdx], IVIncInsertPos, L) + ? L->getHeader()->getTerminator() + : IVIncInsertPos; + Rewriter.setIVIncInsertPos(L, InsertPos); Rewrite(Uses[LUIdx], Fixup, *Solution[LUIdx], DeadInsts); Changed = true; } |