[llvm] [LoopVectorize] Clear stale CycleAnalysis after loop simplification (PR #218563)

Oscar Priego via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 17:52:22 PDT 2026


https://github.com/Opriego created https://github.com/llvm/llvm-project/pull/218563

Fixes #218392.

`LoopVectorizePass::runImpl()` simplifies loops before processing them. That
initial `simplifyLoop()` phase may change the CFG.

If `CycleAnalysis` was already cached by an earlier pass, the cached result
still describes the pre-simplified CFG. Later, `processLoop()` may request
`BlockFrequencyAnalysis` lazily from the cost model. Since BFI now depends on
`CycleAnalysis`, it can consume the stale cycle information and hit:

    Assertion `Resolved >= Pred && "unhandled irreducible control flow"' failed.

Clear a cached `CycleAnalysis` immediately after the initial loop
simplification when the CFG changed, so a later BFI request recomputes cycle
information for the simplified CFG.

This is similar to #215237, which clears stale `CycleAnalysis` after
vectorizing a loop. This change covers the earlier CFG-changing simplification
phase before the first loop is processed.

Added a reduced regression test based on #218392.

Testing:
- `bfi-stale-after-loop-simplify.ll`: PASS
- existing `bfi-stale-crash.ll`: PASS
- exact #218392 reproducer:
  `function(require<cycles>,loop-vectorize,print<block-freq>)`: exit 0


>From 14de72320af44ee3e8c75efb9450ed2b4571055d Mon Sep 17 00:00:00 2001
From: Oscar Priego Verdugo <oscar.priegov at gmail.com>
Date: Mon, 24 Aug 2026 18:28:46 -0600
Subject: [PATCH] [LoopVectorize] Clear stale CycleAnalysis after loop
 simplification

---
 .../Transforms/Vectorize/LoopVectorize.cpp    |  6 +++++
 .../bfi-stale-after-loop-simplify.ll          | 25 +++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 llvm/test/Transforms/LoopVectorize/bfi-stale-after-loop-simplify.ll

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 63f955538a8d7..97fd016a63d2c 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8330,6 +8330,12 @@ LoopVectorizeResult LoopVectorizePass::runImpl(Function &F) {
     Changed |= CFGChanged |=
         simplifyLoop(L, DT, LI, SE, AC, nullptr, false /* PreserveLCSSA */);
 
+  // Loop simplification may change the CFG before processLoop() lazily requests
+  // BlockFrequencyAnalysis. Clear a cached CycleAnalysis so BFI recomputes it
+  // for the simplified CFG.
+  if (CFGChanged && FAM->getCachedResult<CycleAnalysis>(F))
+    FAM->clearAnalysis<CycleAnalysis>(F);
+
   // Build up a worklist of inner-loops to vectorize. This is necessary as
   // the act of vectorizing or partially unrolling a loop creates new loops
   // and can invalidate iterators across the loops.
diff --git a/llvm/test/Transforms/LoopVectorize/bfi-stale-after-loop-simplify.ll b/llvm/test/Transforms/LoopVectorize/bfi-stale-after-loop-simplify.ll
new file mode 100644
index 0000000000000..1dfe4882f9193
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/bfi-stale-after-loop-simplify.ll
@@ -0,0 +1,25 @@
+; RUN: opt < %s -passes='function(require<cycles>,loop-vectorize)' -disable-output
+
+; LoopVectorize simplifies loops before processing them. If CycleAnalysis was
+; cached before the pass, it must not be reused after loop simplification
+; changes the CFG when BlockFrequencyInfo is requested lazily.
+
+define i16 @f(i1 %c) {
+entry:
+  br label %header
+
+latch:
+  %iv.next = add i16 %iv, 1
+  %done = icmp eq i16 %iv.next, 0
+  br i1 %done, label %second, label %header
+
+header:
+  %iv = phi i16 [ 0, %entry ], [ %iv.next, %latch ]
+  br i1 %c, label %trap, label %latch
+
+trap:
+  unreachable
+
+second:
+  br i1 false, label %second, label %second
+}



More information about the llvm-commits mailing list