[llvm] [VectorUtils] Pad concatenateVectors with poison instead of undef (PR #225598)

Le Gia Bao via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 22:42:10 PDT 2026


https://github.com/L3GiaBao created https://github.com/llvm/llvm-project/pull/225598

undef is now depcrecated, so pad with poison instead.

>From 11df9c8fe2e6cae95ae4334a89e55c7e1b9db615 Mon Sep 17 00:00:00 2001
From: Le Gia Bao <legiabao7300 at gmail.com>
Date: Wed, 23 Sep 2026 12:34:53 +0700
Subject: [PATCH] [VectorUtils] Pad concatenateVectors with poison instead of
 undef

---
 llvm/lib/Analysis/VectorUtils.cpp             |  11 +-
 .../interleaved-store-concat-poison-pad.ll    | 127 ++++++++++++++++++
 2 files changed, 134 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopVectorize/X86/interleaved-store-concat-poison-pad.ll

diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 1c105ebb772b3..1b7d11e492dd5 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1203,7 +1203,7 @@ llvm::SmallVector<int, 16> llvm::createUnaryMask(ArrayRef<int> Mask,
 
 /// A helper function for concatenating vectors. This function concatenates two
 /// vectors having the same element type. If the second vector has fewer
-/// elements than the first, it is padded with undefs.
+/// elements than the first, it is padded with poison.
 static Value *concatenateTwoVectors(IRBuilderBase &Builder, Value *V1,
                                     Value *V2) {
   VectorType *VecTy1 = dyn_cast<VectorType>(V1->getType());
@@ -1217,9 +1217,12 @@ static Value *concatenateTwoVectors(IRBuilderBase &Builder, Value *V1,
   assert(NumElts1 >= NumElts2 && "Unexpect the first vector has less elements");
 
   if (NumElts1 > NumElts2) {
-    // Extend with UNDEFs.
-    V2 = Builder.CreateShuffleVector(
-        V2, createSequentialMask(0, NumElts2, NumElts1 - NumElts2));
+    // Extend with poison.
+    if (isa<PoisonValue>(V2))
+      V2 = PoisonValue::get(VecTy1);
+    else
+      V2 = Builder.CreateShuffleVector(
+          V2, createSequentialMask(0, NumElts2, NumElts1 - NumElts2));
   }
 
   return Builder.CreateShuffleVector(
diff --git a/llvm/test/Transforms/LoopVectorize/X86/interleaved-store-concat-poison-pad.ll b/llvm/test/Transforms/LoopVectorize/X86/interleaved-store-concat-poison-pad.ll
new file mode 100644
index 0000000000000..c06f154d8cc52
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/X86/interleaved-store-concat-poison-pad.ll
@@ -0,0 +1,127 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=loop-vectorize -mcpu=skx -enable-interleaved-mem-accesses -enable-masked-interleaved-mem-accesses=1 -force-vector-width=8 -force-vector-interleave=1 -S < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+%triple.i32 = type { i32, i32, i32 }
+
+define void @concat_pad_poison_splat(ptr %a, i64 %n) {
+; CHECK-LABEL: define void @concat_pad_poison_splat(
+; CHECK-SAME: ptr [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8
+; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
+; CHECK:       [[VECTOR_PH]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i64 [[N]], 7
+; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[TMP0]]
+; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
+; CHECK:       [[VECTOR_BODY]]:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[TRIPLE_I32:%.*]], ptr [[A]], i64 [[INDEX]], i32 0
+; CHECK-NEXT:    call void @llvm.masked.store.v24i32.p0(<24 x i32> <i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison, i32 0, i32 1, i32 poison>, ptr align 4 [[TMP1]], <24 x i1> <i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false>)
+; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[TMP2]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
+; CHECK:       [[MIDDLE_BLOCK]]:
+; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]
+; CHECK:       [[SCALAR_PH]]:
+; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    br label %[[FOR_BODY:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[GEP_A0:%.*]] = getelementptr inbounds [[TRIPLE_I32]], ptr [[A]], i64 [[IV]], i32 0
+; CHECK-NEXT:    store i32 0, ptr [[GEP_A0]], align 4
+; CHECK-NEXT:    [[GEP_A1:%.*]] = getelementptr inbounds [[TRIPLE_I32]], ptr [[A]], i64 [[IV]], i32 1
+; CHECK-NEXT:    store i32 1, ptr [[GEP_A1]], align 4
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %for.body
+
+for.body:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
+  %gep.a0 = getelementptr inbounds %triple.i32, ptr %a, i64 %iv, i32 0
+  store i32 0, ptr %gep.a0, align 4
+  %gep.a1 = getelementptr inbounds %triple.i32, ptr %a, i64 %iv, i32 1
+  store i32 1, ptr %gep.a1, align 4
+  %iv.next = add nuw nsw i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, %n
+  br i1 %ec, label %exit, label %for.body
+
+exit:
+  ret void
+}
+
+define void @concat_pad_poison_loaded_value(ptr noalias %a, ptr noalias %b, i64 %n) {
+; CHECK-LABEL: define void @concat_pad_poison_loaded_value(
+; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8
+; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
+; CHECK:       [[VECTOR_PH]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i64 [[N]], 7
+; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[N]], [[TMP0]]
+; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
+; CHECK:       [[VECTOR_BODY]]:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]]
+; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[TRIPLE_I32:%.*]], ptr [[A]], i64 [[INDEX]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <16 x i32> [[TMP3]], <16 x i32> poison, <24 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23>
+; CHECK-NEXT:    [[INTERLEAVED_VEC:%.*]] = shufflevector <24 x i32> [[TMP4]], <24 x i32> poison, <24 x i32> <i32 0, i32 8, i32 16, i32 1, i32 9, i32 17, i32 2, i32 10, i32 18, i32 3, i32 11, i32 19, i32 4, i32 12, i32 20, i32 5, i32 13, i32 21, i32 6, i32 14, i32 22, i32 7, i32 15, i32 23>
+; CHECK-NEXT:    call void @llvm.masked.store.v24i32.p0(<24 x i32> [[INTERLEAVED_VEC]], ptr align 4 [[TMP2]], <24 x i1> <i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false>)
+; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
+; CHECK:       [[MIDDLE_BLOCK]]:
+; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]]
+; CHECK-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]
+; CHECK:       [[SCALAR_PH]]:
+; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    br label %[[FOR_BODY:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[FOR_BODY]] ]
+; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
+; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[GEP_B]], align 4
+; CHECK-NEXT:    [[GEP_A0:%.*]] = getelementptr inbounds [[TRIPLE_I32]], ptr [[A]], i64 [[IV]], i32 0
+; CHECK-NEXT:    store i32 [[L]], ptr [[GEP_A0]], align 4
+; CHECK-NEXT:    [[GEP_A1:%.*]] = getelementptr inbounds [[TRIPLE_I32]], ptr [[A]], i64 [[IV]], i32 1
+; CHECK-NEXT:    store i32 [[L]], ptr [[GEP_A1]], align 4
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[FOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %for.body
+
+for.body:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ]
+  %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
+  %l = load i32, ptr %gep.b, align 4
+  %gep.a0 = getelementptr inbounds %triple.i32, ptr %a, i64 %iv, i32 0
+  store i32 %l, ptr %gep.a0, align 4
+  %gep.a1 = getelementptr inbounds %triple.i32, ptr %a, i64 %iv, i32 1
+  store i32 %l, ptr %gep.a1, align 4
+  %iv.next = add nuw nsw i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, %n
+  br i1 %ec, label %exit, label %for.body
+
+exit:
+  ret void
+}
+;.
+; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
+; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
+; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
+; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]}
+; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
+; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META2]], [[META1]]}
+;.



More information about the llvm-commits mailing list