[llvm] [InstComb] Handle undef in simplifyMaskedStore (PR #161825)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 3 04:08:20 PDT 2025


https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/161825

None

>From d14b933a552e0c11a79f1ee4bc48aad04b0f1d43 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Fri, 3 Oct 2025 11:42:02 +0100
Subject: [PATCH 1/2] [InstComb] Pre-commit test for masked-ld-st

---
 .../InstCombine/masked_intrinsics.ll          | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/masked_intrinsics.ll b/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
index 8f7683419a82a..e5e90c414a77c 100644
--- a/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
@@ -16,6 +16,14 @@ define <2 x double> @load_zeromask(ptr %ptr, <2 x double> %passthru)  {
   ret <2 x double> %res
 }
 
+define <2 x double> @load_poisonmask(ptr %ptr, <2 x double> %passthru)  {
+; CHECK-LABEL: @load_poisonmask(
+; CHECK-NEXT:    ret <2 x double> [[PASSTHRU:%.*]]
+;
+  %res = call <2 x double> @llvm.masked.load.v2f64.p0(ptr %ptr, i32 1, <2 x i1> splat(i1 poison), <2 x double> %passthru)
+  ret <2 x double> %res
+}
+
 define <2 x double> @load_onemask(ptr %ptr, <2 x double> %passthru)  {
 ; CHECK-LABEL: @load_onemask(
 ; CHECK-NEXT:    [[UNMASKEDLOAD:%.*]] = load <2 x double>, ptr [[PTR:%.*]], align 2
@@ -150,6 +158,15 @@ define void @store_zeromask(ptr %ptr, <2 x double> %val)  {
   ret void
 }
 
+define void @store_poisonmask(ptr %ptr, <2 x double> %val)  {
+; CHECK-LABEL: @store_poisonmask(
+; CHECK-NEXT:    call void @llvm.masked.store.v2f64.p0(<2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], i32 4, <2 x i1> poison)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.masked.store.v2f64.p0(<2 x double> %val, ptr %ptr, i32 4, <2 x i1> splat(i1 poison))
+  ret void
+}
+
 define void @store_onemask(ptr %ptr, <2 x double> %val)  {
 ; CHECK-LABEL: @store_onemask(
 ; CHECK-NEXT:    store <2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], align 4
@@ -159,6 +176,15 @@ define void @store_onemask(ptr %ptr, <2 x double> %val)  {
   ret void
 }
 
+define void @store_one_withpoison_mask(ptr %ptr, <2 x double> %val)  {
+; CHECK-LABEL: @store_one_withpoison_mask(
+; CHECK-NEXT:    call void @llvm.masked.store.v2f64.p0(<2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], i32 4, <2 x i1> <i1 true, i1 poison>)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.masked.store.v2f64.p0(<2 x double> %val, ptr %ptr, i32 4, <2 x i1> <i1 1, i1 poison>)
+  ret void
+}
+
 define void @store_demandedelts(ptr %ptr, double %val)  {
 ; CHECK-LABEL: @store_demandedelts(
 ; CHECK-NEXT:    [[VALVEC1:%.*]] = insertelement <2 x double> poison, double [[VAL:%.*]], i64 0

>From 7d153e3ee416c830f15e54b7f543614df0496619 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Fri, 3 Oct 2025 11:52:32 +0100
Subject: [PATCH 2/2] [InstComb] Handle undef in simplifyMaskedStore

---
 .../InstCombine/InstCombineCalls.cpp          | 34 +++++++++++--------
 .../InstCombine/masked_intrinsics.ll          |  3 +-
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index cf6d0ecab4f69..5b7fa8458c6f4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -292,25 +292,29 @@ Value *InstCombinerImpl::simplifyMaskedLoad(IntrinsicInst &II) {
   const Align Alignment =
       cast<ConstantInt>(II.getArgOperand(1))->getAlignValue();
 
+  // If we can unconditionally load from this address, replace with a
+  // load/select idiom.
+  if (isDereferenceablePointer(LoadPtr, II.getType(), II.getDataLayout(), &II,
+                               &AC, &DT)) {
+    LoadInst *LI = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment,
+                                             "unmaskedload");
+    LI->copyMetadata(II);
+    return Builder.CreateSelect(II.getArgOperand(2), LI, II.getArgOperand(3));
+  }
+
+  auto *ConstMask = dyn_cast<Constant>(II.getArgOperand(2));
+  if (!ConstMask)
+    return nullptr;
+
   // If the mask is all ones or undefs, this is a plain vector load of the 1st
   // argument.
-  if (maskIsAllOneOrUndef(II.getArgOperand(2))) {
+  if (maskIsAllOneOrUndef(ConstMask)) {
     LoadInst *L = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment,
                                             "unmaskedload");
     L->copyMetadata(II);
     return L;
   }
 
-  // If we can unconditionally load from this address, replace with a
-  // load/select idiom. TODO: use DT for context sensitive query
-  if (isDereferenceablePointer(LoadPtr, II.getType(),
-                               II.getDataLayout(), &II, &AC)) {
-    LoadInst *LI = Builder.CreateAlignedLoad(II.getType(), LoadPtr, Alignment,
-                                             "unmaskedload");
-    LI->copyMetadata(II);
-    return Builder.CreateSelect(II.getArgOperand(2), LI, II.getArgOperand(3));
-  }
-
   return nullptr;
 }
 
@@ -318,18 +322,18 @@ Value *InstCombinerImpl::simplifyMaskedLoad(IntrinsicInst &II) {
 // * Single constant active lane -> store
 // * Narrow width by halfs excluding zero/undef lanes
 Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) {
+  Value *StorePtr = II.getArgOperand(1);
+  Align Alignment = cast<ConstantInt>(II.getArgOperand(2))->getAlignValue();
   auto *ConstMask = dyn_cast<Constant>(II.getArgOperand(3));
   if (!ConstMask)
     return nullptr;
 
   // If the mask is all zeros, this instruction does nothing.
-  if (ConstMask->isNullValue())
+  if (maskIsAllZeroOrUndef(ConstMask))
     return eraseInstFromFunction(II);
 
   // If the mask is all ones, this is a plain vector store of the 1st argument.
-  if (ConstMask->isAllOnesValue()) {
-    Value *StorePtr = II.getArgOperand(1);
-    Align Alignment = cast<ConstantInt>(II.getArgOperand(2))->getAlignValue();
+  if (maskIsAllOneOrUndef(ConstMask)) {
     StoreInst *S =
         new StoreInst(II.getArgOperand(0), StorePtr, false, Alignment);
     S->copyMetadata(II);
diff --git a/llvm/test/Transforms/InstCombine/masked_intrinsics.ll b/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
index e5e90c414a77c..55be926230c45 100644
--- a/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/masked_intrinsics.ll
@@ -160,7 +160,6 @@ define void @store_zeromask(ptr %ptr, <2 x double> %val)  {
 
 define void @store_poisonmask(ptr %ptr, <2 x double> %val)  {
 ; CHECK-LABEL: @store_poisonmask(
-; CHECK-NEXT:    call void @llvm.masked.store.v2f64.p0(<2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], i32 4, <2 x i1> poison)
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.masked.store.v2f64.p0(<2 x double> %val, ptr %ptr, i32 4, <2 x i1> splat(i1 poison))
@@ -178,7 +177,7 @@ define void @store_onemask(ptr %ptr, <2 x double> %val)  {
 
 define void @store_one_withpoison_mask(ptr %ptr, <2 x double> %val)  {
 ; CHECK-LABEL: @store_one_withpoison_mask(
-; CHECK-NEXT:    call void @llvm.masked.store.v2f64.p0(<2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], i32 4, <2 x i1> <i1 true, i1 poison>)
+; CHECK-NEXT:    store <2 x double> [[VAL:%.*]], ptr [[PTR:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.masked.store.v2f64.p0(<2 x double> %val, ptr %ptr, i32 4, <2 x i1> <i1 1, i1 poison>)



More information about the llvm-commits mailing list