[InstCombine] Remove memset of undef value
authorNikita Popov <npopov@redhat.com>
Thu, 21 Apr 2022 13:57:37 +0000 (15:57 +0200)
committerNikita Popov <npopov@redhat.com>
Fri, 29 Apr 2022 12:51:18 +0000 (14:51 +0200)
This removes memset with undef char. We already do this for stores
of undef value.

This comes with the caveat that this optimization is not, strictly
speaking, legal for undef values, because we might be overwriting
a poison value. However, our entire load/store model currently still
operates on undef values, so we need to support undef here as well
for internal consistency.

Once https://github.com/llvm/llvm-project/issues/52930 is resolved,
these and related folds can be limited to poison -- I've added
FIXMEs to that effect.

Differential Revision: https://reviews.llvm.org/D124173

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
llvm/test/Transforms/InstCombine/memset.ll
llvm/test/Transforms/InstCombine/store.ll

index 1de861ea979bf656b1611c97256aeab82b5e1a03..957b954c2afb82df2c56bbbd1a08601f6be69650 100644 (file)
@@ -258,6 +258,15 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
     return MI;
   }
 
+  // Remove memset with an undef value.
+  // FIXME: This is technically incorrect because it might overwrite a poison
+  // value. Change to PoisonValue once #52930 is resolved.
+  if (isa<UndefValue>(MI->getValue())) {
+    // Set the size of the copy to 0, it will be deleted on the next iteration.
+    MI->setLength(Constant::getNullValue(MI->getLength()->getType()));
+    return MI;
+  }
+
   // Extract the length and alignment and fill if they are constant.
   ConstantInt *LenC = dyn_cast<ConstantInt>(MI->getLength());
   ConstantInt *FillC = dyn_cast<ConstantInt>(MI->getValue());
index 0bfb9beae6fc7f989c2f97b335cb0136465c5878..3351d24a2a9203208583bf9d3271514ee9f08474 100644 (file)
@@ -1435,6 +1435,8 @@ 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))
     return eraseInstFromFunction(SI);
 
index 2cc26803f19bca5eee3a252a9ca34b9ce484cd06..7676ebc0435a2e229802adcf9a1c432d07bf2271 100644 (file)
@@ -33,9 +33,10 @@ define void @memset_to_constant() {
   ret void
 }
 
+; FIXME: This is technically incorrect because it might overwrite a poison
+; value. Stop folding it once #52930 is resolved.
 define void @memset_undef(i8* %p) {
 ; CHECK-LABEL: @memset_undef(
-; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(8) [[P:%.*]], i8 undef, i32 8, i1 false)
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.memset.p0i8.i32(i8* %p, i8 undef, i32 8, i1 false)
@@ -53,7 +54,6 @@ define void @memset_undef_volatile(i8* %p) {
 
 define void @memset_poison(i8* %p) {
 ; CHECK-LABEL: @memset_poison(
-; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(8) [[P:%.*]], i8 poison, i32 8, i1 false)
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.memset.p0i8.i32(i8* %p, i8 poison, i32 8, i1 false)
index 8a29049d5b75c15e46b3847645ee6e990d784095..d4e0e0c4e51403cc7f65cd67077682b964f62883 100644 (file)
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
+; FIXME: This is technically incorrect because it might overwrite a poison
+; value. Stop folding it once #52930 is resolved.
 define void @store_of_undef(i32* %P) {
 ; CHECK-LABEL: @store_of_undef(
 ; CHECK-NEXT:    ret void