[llvm] [DSE] Handle variable offsets with sized dead_on_return (PR #180364)

Aiden Grossman via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 7 11:03:32 PST 2026


https://github.com/boomanaiden154 created https://github.com/llvm/llvm-project/pull/180364

With a sized dead_on_return, we need to not eliminate stores if there are to a pointer with a variable offset from the underlying object marked dead_on_return. This manifested as an assertion failure as BaseValue/V ended up not being equal. It's possible we could do a range analysis to try and prove the variable offset stays within bounds, but this case seems to come up relatively rarely (only reproducible with a UBSan build of LLVM) and is probably not worth the compile time.

Fixes #180361.

>From 7549e38fdb6ab5074cbcad6a4276d477ea8a6813 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Sat, 7 Feb 2026 18:57:54 +0000
Subject: [PATCH] [DSE] Handle variable offsets with sized dead_on_return

With a sized dead_on_return, we need to not eliminate stores if there
are to a pointer with a variable offset from the underlying object
marked dead_on_return. This manifested as an assertion failure as
BaseValue/V ended up not being equal. It's possible we could do a range
analysis to try and prove the variable offset stays within bounds, but
this case seems to come up relatively rarely (only reproducible with a
UBSan build of LLVM) and is probably not worth the compile time.

Fixes #180361.
---
 llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp |  6 +++++-
 llvm/test/Transforms/DeadStoreElimination/simple.ll | 11 +++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 582ec1dbcec98..e056f0c1f6390 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1227,7 +1227,11 @@ struct DSEState {
       int64_t ValueOffset;
       [[maybe_unused]] const Value *BaseValue =
           GetPointerBaseWithConstantOffset(Ptr, ValueOffset, DL);
-      assert(BaseValue == V);
+      // If we are not able to find a constant offset from the UO, we have to
+      // pessimistically assume that the store writes to memory out of the
+      // dead_on_return bounds.
+      if (BaseValue != V)
+        return false;
       // This store is only invisible after return if we are in bounds of the
       // range marked dead.
       if (StoreSize.hasValue() &&
diff --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll b/llvm/test/Transforms/DeadStoreElimination/simple.ll
index 4467afb43f3b6..60a6602f030f7 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -955,5 +955,16 @@ define void @test_dead_on_return_variable_memset(ptr dead_on_return(8) %p, i64 %
   ret void
 }
 
+define void @test_dead_on_return_variable_offset(ptr dead_on_return(4) %p, i64 %offset) {
+; CHECK-LABEL: @test_dead_on_return_variable_offset(
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFFSET:%.*]]
+; CHECK-NEXT:    store i32 0, ptr [[P1]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p1 = getelementptr i8, ptr %p, i64 %offset
+  store i32 0, ptr %p1
+  ret void
+}
+
 declare void @opaque(ptr)
 declare void @maythrow() memory(none)



More information about the llvm-commits mailing list