[llvm] [MoveAutoInit] Don't move auto-init instructions into EH pad blocks (PR #222100)
Nikhil Ludder via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 11:46:40 PDT 2026
https://github.com/badnikhil created https://github.com/llvm/llvm-project/pull/222100
`BasicBlock::getFirstInsertionPt()` skips a leading EH pad, but the MemorySSA update registers the moved instruction with `InsertionPlace::Beginning`. A `CatchPadInst` is itself a `MemoryDef`, so instruction order and access order disagree and `-verify-memoryssa` asserts. Extend the existing `CatchSwitchInst` guard to all EH pads.
Fixes #221568.
Written with claude-code (Opus 5); reviewed and tested locally.
>From 1545f5780369334df607d8ccda0fd7890ca2ec03 Mon Sep 17 00:00:00 2001
From: badnikhil <nikhilljatt at gmail.com>
Date: Wed, 9 Sep 2026 00:13:50 +0530
Subject: [PATCH] [MoveAutoInit] Don't move auto-init instructions into EH pad
blocks
getFirstInsertionPt() skips a leading EH pad, but the MemorySSA update
places the moved access at the beginning of the block. A CatchPadInst is
itself a MemoryDef, so instruction order and access order disagree and
-verify-memoryssa asserts. Extend the CatchSwitchInst guard to all EH pads.
Fixes #221568.
---
llvm/lib/Transforms/Utils/MoveAutoInit.cpp | 9 ++--
llvm/test/Transforms/MoveAutoInit/catchpad.ll | 48 +++++++++++++++++++
2 files changed, 54 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/Transforms/MoveAutoInit/catchpad.ll
diff --git a/llvm/lib/Transforms/Utils/MoveAutoInit.cpp b/llvm/lib/Transforms/Utils/MoveAutoInit.cpp
index a3e44fb513a3d..aac430ddd7059 100644
--- a/llvm/lib/Transforms/Utils/MoveAutoInit.cpp
+++ b/llvm/lib/Transforms/Utils/MoveAutoInit.cpp
@@ -178,9 +178,12 @@ static bool runMoveAutoInit(Function &F, DominatorTree &DT, MemorySSA &MSSA) {
UsersDominator = DominatingPredecessor;
}
- // CatchSwitchInst blocks can only have one instruction, so they are not
- // good candidates for insertion.
- while (isa<CatchSwitchInst>(UsersDominator->getFirstNonPHIIt())) {
+ // EH pad blocks are not good candidates for insertion: CatchSwitchInst
+ // blocks can only have one instruction, and for the other pads
+ // getFirstInsertionPt() skips the pad instruction, which may itself have a
+ // memory access, while the MemorySSA update below assumes the moved
+ // instruction becomes the first access of the block.
+ while (UsersDominator->isEHPad()) {
for (BasicBlock *Pred : predecessors(UsersDominator))
if (DT.isReachableFromEntry(Pred))
UsersDominator = DT.findNearestCommonDominator(UsersDominator, Pred);
diff --git a/llvm/test/Transforms/MoveAutoInit/catchpad.ll b/llvm/test/Transforms/MoveAutoInit/catchpad.ll
new file mode 100644
index 0000000000000..447d013d42152
--- /dev/null
+++ b/llvm/test/Transforms/MoveAutoInit/catchpad.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -S -passes='move-auto-init' -verify-memoryssa | FileCheck %s
+
+; A CatchPadInst is a MemoryDef, so the auto-init store cannot be moved to the
+; beginning of its block, see #221568.
+
+declare void @dummy()
+
+define void @test() personality ptr @dummy {
+; CHECK-LABEL: define void @test() personality ptr @dummy {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
+; CHECK-NEXT: br label [[MIDDLE:%.*]]
+; CHECK: middle:
+; CHECK-NEXT: store i32 0, ptr [[P]], align 4, !annotation [[META0:![0-9]+]]
+; CHECK-NEXT: invoke void @dummy()
+; CHECK-NEXT: to label [[CLEAN:%.*]] unwind label [[CATCHBB:%.*]]
+; CHECK: clean:
+; CHECK-NEXT: ret void
+; CHECK: catchbb:
+; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[PAD:%.*]]] unwind to caller
+; CHECK: pad:
+; CHECK-NEXT: [[C:%.*]] = catchpad within [[CS]] [i32 0]
+; CHECK-NEXT: ret void
+;
+entry:
+ %p = alloca i32, align 4
+ store i32 0, ptr %p, align 4, !annotation !0
+ br label %middle
+
+middle:
+ invoke void @dummy() to label %clean unwind label %catchbb
+
+clean:
+ ret void
+
+catchbb:
+ %cs = catchswitch within none [label %pad] unwind to caller
+
+pad:
+ %c = catchpad within %cs [i32 0]
+ ret void
+}
+
+!0 = !{!"auto-init"}
+;.
+; CHECK: [[META0]] = !{!"auto-init"}
+;.
More information about the llvm-commits
mailing list