[llvm] [MoveAutoInit] Don't move auto-init instructions into EH pad blocks (PR #222100)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 11:47:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikhil Ludder (badnikhil)
<details>
<summary>Changes</summary>
`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.
---
Full diff: https://github.com/llvm/llvm-project/pull/222100.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Utils/MoveAutoInit.cpp (+6-3)
- (added) llvm/test/Transforms/MoveAutoInit/catchpad.ll (+48)
``````````diff
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"}
+;.
``````````
</details>
https://github.com/llvm/llvm-project/pull/222100
More information about the llvm-commits
mailing list