[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