[llvm] [SROA] Fix assertion failure when promoting self-referential load/store (PR #208826)

Krisitan Erik Olsen via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 18:02:45 PDT 2026


https://github.com/Kristianerik updated https://github.com/llvm/llvm-project/pull/208826

>From 30d47f7d93dc2a38429e48f96971ff81351c331c Mon Sep 17 00:00:00 2001
From: Kristianerik <kristian.erik at outlook.com>
Date: Mon, 13 Jul 2026 00:07:14 -0700
Subject: [PATCH] [SROA] Fix assertion failure when promoting self-referential
 load/store

---
 llvm/lib/Transforms/Utils/SSAUpdater.cpp      |  3 ++
 .../SROA/sroa-self-referential-load.ll        | 45 +++++++++++++++++++
 2 files changed, 48 insertions(+)
 create mode 100644 llvm/test/Transforms/SROA/sroa-self-referential-load.ll

diff --git a/llvm/lib/Transforms/Utils/SSAUpdater.cpp b/llvm/lib/Transforms/Utils/SSAUpdater.cpp
index b6c5c28161fd8..44afd43ec3896 100644
--- a/llvm/lib/Transforms/Utils/SSAUpdater.cpp
+++ b/llvm/lib/Transforms/Utils/SSAUpdater.cpp
@@ -447,6 +447,9 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
         // use the stored value.
         if (StoredValue) {
           replaceLoadWithValue(L, StoredValue);
+          // Avoid assertions in unreachable code.
+          if (StoredValue == L)
+            StoredValue = PoisonValue::get(L->getType());
           L->replaceAllUsesWith(StoredValue);
           ReplacedLoads[L] = StoredValue;
         } else {
diff --git a/llvm/test/Transforms/SROA/sroa-self-referential-load.ll b/llvm/test/Transforms/SROA/sroa-self-referential-load.ll
new file mode 100644
index 0000000000000..39c2cf01455a3
--- /dev/null
+++ b/llvm/test/Transforms/SROA/sroa-self-referential-load.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt --passes=sroa -S < %s | FileCheck %s
+
+; Ensure no crash when a store's value operand is the load being promoted,
+; creating a self-referential cycle in unreachable code.
+
+define i32 @func(i64 %iv) {
+; CHECK-LABEL: define i32 @func(
+; CHECK-SAME: i64 [[IV:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca [2 x i32], align 4
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT:.*]]:
+; CHECK-NEXT:    store i32 poison, ptr [[A]], align 4
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[DEAD:.*]]:
+; CHECK-NEXT:    br label %[[DEAD]]
+; CHECK:       [[USE:.*]]:
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [4 x i8], ptr [[A]], i64 [[IV]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[GEP]], align 4
+; CHECK-NEXT:    br i1 false, label %[[USE]], label %[[DEAD]]
+;
+entry:
+  %a = alloca [2 x i32], align 4
+  br label %loop
+
+loop:
+  br label %loop
+
+exit:
+  store i32 %0, ptr %a, align 4
+  %0 = load i32, ptr %a, align 4
+  br label %exit
+
+dead:
+  br label %dead
+
+use:
+  %gep = getelementptr [4 x i8], ptr %a, i64 %iv
+  %1 = load i32, ptr %gep, align 4
+  br i1 false, label %use, label %dead
+}
+



More information about the llvm-commits mailing list