[llvm] [BlockExtractor] Invalidate analyses after splitting landing pads (PR #217853)

Advit Arora via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 06:10:42 PDT 2026


https://github.com/advitrocks9 updated https://github.com/llvm/llvm-project/pull/217853

>From 8d6a1da121106ac04568297a285332596a01aaee Mon Sep 17 00:00:00 2001
From: Advit Arora <advitarora2 at gmail.com>
Date: Fri, 21 Aug 2026 14:20:58 +0530
Subject: [PATCH 1/2] [BlockExtractor] Invalidate analyses after splitting
 landing pads

`-passes=extract-blocks` with no block list still edits the CFG. `splitLandingPadPreds` runs over every function before the block list is consulted and splits any landing pad whose predecessors include a landing pad other than the invoking block, but it never touched `runOnModule`'s `Changed` flag, so the pass returned `PreservedAnalyses::all()` and the DominatorTree cached by an earlier function pass survived a CFG it no longer describes.

Two consumers fall over on the reporter's input.

```
opt -passes='function(sroa),extract-blocks,function(instcombine)' test.ll -S
```

gives `br i1 poison` on a condition that is `icmp eq i32 0, 0`, because `prepareWorklist` asks the stale tree about blocks it has no node for. And

```
opt -passes='function(sroa),extract-blocks,function(jump-threading)' test.ll -disable-output
```

trips `assert(TN)` in `SemiNCAInfo::DeleteUnreachable`. Splicing `function(invalidate<domtree>)` in after `extract-blocks` makes both go away.

Make the split report itself; the existing ternary in `BlockExtractorPass::run` picks `none()` from there. A module the split does not touch still reports `all()`.

The test pins the contract rather than either symptom: `require<domtree>` on both sides of the pass under `-debug-pass-manager`, then `verify<domtree>` after it. Both RUN lines fail on an unpatched tree, the second aborting with the two blocks the split created missing from the cached tree.

Fixes https://github.com/llvm/llvm-project/issues/213833
---
 llvm/lib/Transforms/IPO/BlockExtractor.cpp    |  9 +++--
 .../BlockExtractor/invalidate-analyses.ll     | 33 +++++++++++++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll

diff --git a/llvm/lib/Transforms/IPO/BlockExtractor.cpp b/llvm/lib/Transforms/IPO/BlockExtractor.cpp
index 23991afc511a0..9bede77c8ac89 100644
--- a/llvm/lib/Transforms/IPO/BlockExtractor.cpp
+++ b/llvm/lib/Transforms/IPO/BlockExtractor.cpp
@@ -58,7 +58,7 @@ class BlockExtractor {
       BlocksByName;
 
   void loadFile();
-  void splitLandingPadPreds(Function &F);
+  bool splitLandingPadPreds(Function &F);
 };
 
 } // end anonymous namespace
@@ -94,7 +94,8 @@ void BlockExtractor::loadFile() {
 
 /// Extracts the landing pads to make sure all of them have only one
 /// predecessor.
-void BlockExtractor::splitLandingPadPreds(Function &F) {
+bool BlockExtractor::splitLandingPadPreds(Function &F) {
+  bool Changed = false;
   for (BasicBlock &BB : F) {
     for (Instruction &I : BB) {
       if (!isa<InvokeInst>(&I))
@@ -119,8 +120,10 @@ void BlockExtractor::splitLandingPadPreds(Function &F) {
 
       SmallVector<BasicBlock *, 2> NewBBs;
       SplitLandingPadPredecessors(LPad, Parent, ".1", ".2", NewBBs);
+      Changed = true;
     }
   }
+  return Changed;
 }
 
 bool BlockExtractor::runOnModule(Module &M) {
@@ -129,7 +132,7 @@ bool BlockExtractor::runOnModule(Module &M) {
   // Get all the functions.
   SmallVector<Function *, 4> Functions;
   for (Function &F : M) {
-    splitLandingPadPreds(F);
+    Changed |= splitLandingPadPreds(F);
     Functions.push_back(&F);
   }
 
diff --git a/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll b/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll
new file mode 100644
index 0000000000000..a558c0925f4e0
--- /dev/null
+++ b/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll
@@ -0,0 +1,33 @@
+; RUN: opt -passes='function(require<domtree>),extract-blocks,function(require<domtree>)' -debug-pass-manager -disable-output %s 2>&1 | FileCheck %s
+; RUN: opt -passes='function(require<domtree>),extract-blocks,function(verify<domtree>)' -disable-output %s
+
+; The landing pad split runs even with an empty block list, so the CFG changes.
+
+; CHECK: Running analysis: DominatorTreeAnalysis on foo
+; CHECK: Running pass: BlockExtractorPass
+; CHECK: Running analysis: DominatorTreeAnalysis on foo
+
+define void @foo() personality ptr @__gxx_personality_v0 {
+entry:
+  invoke void @bar()
+          to label %exit unwind label %lpad
+
+lpad:
+  %0 = landingpad { ptr, i32 }
+          catch ptr null
+  invoke void @bar()
+          to label %exit unwind label %lpad2
+
+lpad2:
+  %1 = landingpad { ptr, i32 }
+          cleanup
+  invoke void @bar()
+          to label %exit unwind label %lpad
+
+exit:
+  ret void
+}
+
+declare void @bar()
+
+declare i32 @__gxx_personality_v0(...)

>From 571fff7d3aa94b917a48b9200400f5d4ea6ac6f8 Mon Sep 17 00:00:00 2001
From: Advit Arora <advitarora2 at gmail.com>
Date: Fri, 21 Aug 2026 18:40:25 +0530
Subject: [PATCH 2/2] [BlockExtractor] Simplify invalidate-analyses test

---
 llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll b/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll
index a558c0925f4e0..24c220979a921 100644
--- a/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll
+++ b/llvm/test/Transforms/BlockExtractor/invalidate-analyses.ll
@@ -1,11 +1,7 @@
-; RUN: opt -passes='function(require<domtree>),extract-blocks,function(require<domtree>)' -debug-pass-manager -disable-output %s 2>&1 | FileCheck %s
 ; RUN: opt -passes='function(require<domtree>),extract-blocks,function(verify<domtree>)' -disable-output %s
 
 ; The landing pad split runs even with an empty block list, so the CFG changes.
-
-; CHECK: Running analysis: DominatorTreeAnalysis on foo
-; CHECK: Running pass: BlockExtractorPass
-; CHECK: Running analysis: DominatorTreeAnalysis on foo
+; Ensure that we properly invalidate analyses.
 
 define void @foo() personality ptr @__gxx_personality_v0 {
 entry:



More information about the llvm-commits mailing list