[llvm] [InstCombine] Don't fold `store undef` at non-byte-sized widths (PR #230955)

Mitch Briles via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 11 05:54:28 PDT 2026


https://github.com/MitchBriles created https://github.com/llvm/llvm-project/pull/230955

It's well known that we can't remove `store i1 undef` unless we can prove the byte is non-`poison`. However, since https://github.com/llvm/llvm-project/pull/180739 it's doubly wrong unless we can prove that bits 1..7 in memory are already zero, since the stored value is zero-extended to the next byte boundary.

>From b1aff54d945e145bdd2e2093b06e7ecc99bab5cd Mon Sep 17 00:00:00 2001
From: Mitch <mitchbriles at gmail.com>
Date: Sun, 11 Oct 2026 06:33:13 -0600
Subject: [PATCH 1/2] Pre-commit test

---
 llvm/test/Transforms/InstCombine/store.ll | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/store.ll b/llvm/test/Transforms/InstCombine/store.ll
index 8b801a4a3c946..4867a652c5181 100644
--- a/llvm/test/Transforms/InstCombine/store.ll
+++ b/llvm/test/Transforms/InstCombine/store.ll
@@ -11,6 +11,16 @@ define void @store_of_undef(ptr %P) {
   ret void
 }
 
+; Wrong to fold for two reasons: possible poison overwrite, and can't guarantee
+; that the high bit of this byte in memory will be zero.
+define void @store_of_nonbyte_undef(ptr %P) {
+; CHECK-LABEL: @store_of_nonbyte_undef(
+; CHECK-NEXT:    ret void
+;
+  store i7 undef, ptr %P
+  ret void
+}
+
 define void @store_of_poison(ptr %P) {
 ; CHECK-LABEL: @store_of_poison(
 ; CHECK-NEXT:    ret void

>From 90186dcab6bec2a965de9f7c52142c130541ac57 Mon Sep 17 00:00:00 2001
From: Mitch <mitchbriles at gmail.com>
Date: Sun, 11 Oct 2026 06:39:15 -0600
Subject: [PATCH 2/2] [InstCombine]  Don't fold `store undef` at non-byte-sized
 widths

---
 .../InstCombine/InstCombineLoadStoreAlloca.cpp           | 9 ++++++---
 llvm/test/Transforms/InstCombine/store.ll                | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 527ba917da3cb..0fa61d56cce20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/VectorUtils.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
@@ -1586,9 +1587,11 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) {
   }
 
   // store undef, Ptr -> noop
-  // FIXME: This is technically incorrect because it might overwrite a poison
-  // value. Change to PoisonValue once #52930 is resolved.
-  if (isa<UndefValue>(Val))
+  // Non-byte-sized stores of undef (e.g. i12) are padded with zeros, so we
+  // can't remove the instruction.
+  // FIXME: It's incorrect to overwrite poison with undef
+  if (isa<PoisonValue>(Val) ||
+      (isa<UndefValue>(Val) && DL.typeSizeEqualsStoreSize(Val->getType())))
     return eraseInstFromFunction(SI);
 
   // Replace byte constants with integer constants in stores.
diff --git a/llvm/test/Transforms/InstCombine/store.ll b/llvm/test/Transforms/InstCombine/store.ll
index 4867a652c5181..43a4e633650ff 100644
--- a/llvm/test/Transforms/InstCombine/store.ll
+++ b/llvm/test/Transforms/InstCombine/store.ll
@@ -15,6 +15,7 @@ define void @store_of_undef(ptr %P) {
 ; that the high bit of this byte in memory will be zero.
 define void @store_of_nonbyte_undef(ptr %P) {
 ; CHECK-LABEL: @store_of_nonbyte_undef(
+; CHECK-NEXT:    store i7 undef, ptr [[P:%.*]], align 1
 ; CHECK-NEXT:    ret void
 ;
   store i7 undef, ptr %P



More information about the llvm-commits mailing list