[llvm] [LV] Compute SCEV for memcheck before unlinking (PR #160326)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 23 08:36:43 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-vectorizers
Author: Igor Kirillov (igogo-x86)
<details>
<summary>Changes</summary>
When generating runtime memory checks for outer loops, we split blocks and later unlink them, making the memcheck block unreachable. For instructions in unreachable blocks, ScalarEvolution returns an unknown/poison SCEV, which is treated as a constant and thus loop-invariant. The cost model then assumes the check can be hoisted and underestimates its cost. See this code in `GeneratedRTChecks::getCost`:
```
const SCEV *Cond = SE->getSCEV(MemRuntimeCheckCond);
if (SE->isLoopInvariant(Cond, OuterLoop)) {
```
Set OuterLoop early in GeneratedRTChecks::create and compute the SCEV for MemRuntimeCheckCond before unlinking, so getCost() sees the cached expression rather than a poison constant.
---
Full diff: https://github.com/llvm/llvm-project/pull/160326.diff
1 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+9-2)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index ca092dcfcb492..575f45b051cf6 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -1807,6 +1807,10 @@ class GeneratedRTChecks {
BasicBlock *LoopHeader = L->getHeader();
BasicBlock *Preheader = L->getLoopPreheader();
+ // Outer loop is used as part of later cost calculations (e.g. to
+ // determine if runtime checks are loop-invariant and can be hoisted).
+ OuterLoop = L->getParentLoop();
+
// Use SplitBlock to create blocks for SCEV & memory runtime checks to
// ensure the blocks are properly added to LoopInfo & DominatorTree. Those
// may be used by SCEVExpander. The blocks will be un-linked from their
@@ -1850,6 +1854,11 @@ class GeneratedRTChecks {
assert(MemRuntimeCheckCond &&
"no RT checks generated although RtPtrChecking "
"claimed checks are required");
+ // Compute SCEV while the block is reachable.
+ // After unlinking, SCEV returns unknown/poison (constant -> invariant),
+ // which makes getCost() wrongly discount hoisted checks.
+ if (OuterLoop)
+ PSE.getSE()->getSCEV(MemRuntimeCheckCond);
}
SCEVExp.eraseDeadInstructions(SCEVCheckCond);
@@ -1889,8 +1898,6 @@ class GeneratedRTChecks {
LI->removeBlock(SCEVCheckBlock);
}
- // Outer loop is used as part of the later cost calculations.
- OuterLoop = L->getParentLoop();
}
InstructionCost getCost() {
``````````
</details>
https://github.com/llvm/llvm-project/pull/160326
More information about the llvm-commits
mailing list