[llvm] [IndVarSimplify] Allow predicateLoopExit on some loops with local writes (PR #155901)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 29 04:02:32 PDT 2025
================
@@ -1840,6 +1865,34 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
auto *BI = cast<BranchInst>(ExitingBB->getTerminator());
+ if (HasLocalSideEffects) {
+ BasicBlock *Unreachable = nullptr;
+ BasicBlock *InLoop = nullptr;
+ for (BasicBlock *Succ : BI->successors()) {
+ if (isa<UnreachableInst>(Succ->getTerminator()))
+ Unreachable = Succ;
+ else if (L->contains(Succ))
+ InLoop = Succ;
+ }
+ // Exit BB which have one branch back into the loop and another one to
+ // a trap can still be optimized, because local side effects cannot
+ // be observed in the exit case (the trap). We could be smarter about
+ // this, but for now lets pattern match common cases that directly trap.
+ if (Unreachable == nullptr || InLoop == nullptr)
+ return Changed;
+ if (llvm::any_of(*Unreachable, [](Instruction &I) {
+ if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
+ if (II->getIntrinsicID() != Intrinsic::trap &&
----------------
nikic wrote:
I don't really want to introduce trap-specific optimizations in IndVars. The general idea here is useful also for libcxx hardening, rust bounds checks, etc.
The way I would generalize this is that we have an unreachable (or even a return) which is preceded by instructions that do not Ref the allocas. We could do something generic with AA here, or limit this to the cases where either a) the stored allocas do not escape or b) the instruction do not read anything but inaccessible memory. `llvm.trap` is already `memory(inaccessiblemem: readwrite)`. `llvm.ubsantrap` isn't, but should probably be.
https://github.com/llvm/llvm-project/pull/155901
More information about the llvm-commits
mailing list