[llvm] [X86] combineSelect - `fold select(c,vtrunc(x),0)` => `X86ISD::MTRUNC(x,c)` (PR #212865)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 05:34:50 PDT 2026


https://github.com/VachanVY updated https://github.com/llvm/llvm-project/pull/212865

>From 7c889acaff65200cb3d9c68610c7b0453ac065f4 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 30 Jul 2026 01:47:11 +0530
Subject: [PATCH 1/3] [X86] Pre-Commit Tests. NFC

---
 llvm/test/CodeGen/X86/trunc-select-fold.ll | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/trunc-select-fold.ll

diff --git a/llvm/test/CodeGen/X86/trunc-select-fold.ll b/llvm/test/CodeGen/X86/trunc-select-fold.ll
new file mode 100644
index 0000000000000..fea533b2e251f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/trunc-select-fold.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=znver5 | FileCheck %s
+
+define <8 x i8> @test_mask_vpmovqb(<8 x i64> %0, <8 x i64> %1) {
+; CHECK-LABEL: test_mask_vpmovqb:
+; CHECK:       # %bb.0: # %Entry
+; CHECK-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
+; CHECK-NEXT:    vpopcntq %zmm0, %zmm0
+; CHECK-NEXT:    vpmovqb %zmm0, %xmm0
+; CHECK-NEXT:    vmovdqu8 %xmm0, %xmm0 {%k1} {z}
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+Entry:
+  %2 = icmp eq <8 x i64> %0, %1
+  %3 = tail call range(i64 0, 65) <8 x i64> @llvm.ctpop.v8i64(<8 x i64> %0)
+  %4 = trunc nuw nsw <8 x i64> %3 to <8 x i8>
+  %5 = select <8 x i1> %2, <8 x i8> %4, <8 x i8> zeroinitializer
+  ret <8 x i8> %5
+}

>From 1be9c42c891164d695b010025efb356dbfde1a89 Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 30 Jul 2026 02:00:41 +0530
Subject: [PATCH 2/3] [X86] Fold vselect(mask, vtrunc(x), 0) to masked vtrunc
 for  vpmovqb

optimization + Check diff

fixes #156883
---
 llvm/lib/Target/X86/X86ISelLowering.cpp    | 14 ++++++++++++++
 llvm/test/CodeGen/X86/avx512-trunc.ll      |  3 +--
 llvm/test/CodeGen/X86/trunc-select-fold.ll |  3 +--
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index bb4b13e4feca4..d11057829525a 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -48680,6 +48680,20 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
     return DAG.getNode(N->getOpcode(), DL, VT, Cond, LHS, RHS);
   }
 
+  // Fold vselect(mask, vtrunc(x), 0) to vtrunc for masked vpmovqb.
+  if (Subtarget.hasAVX512() && CondVT.isVector() &&
+      CondVT.getVectorElementType() == MVT::i1 &&
+      ISD::isBuildVectorAllZeros(RHS.getNode()) && LHS.hasOneUse()) {
+    if (LHS.getOpcode() == X86ISD::VTRUNC) {
+      SDValue TruncSrc = LHS.getOperand(0);
+      EVT TruncSrcVT = TruncSrc.getValueType();
+      if (VT == MVT::v16i8 && TruncSrcVT == MVT::v8i64) {
+        return DAG.getNode(X86ISD::VMTRUNC, DL, VT, TruncSrc, DAG.getUNDEF(VT),
+                           Cond);
+      }
+    }
+  }
+
   // AVX512 - Extend select to merge with target shuffle.
   // select(mask, extract_subvector(shuffle(x)), y) -->
   // extract_subvector(select(widen(mask), shuffle(x), widen(y)))
diff --git a/llvm/test/CodeGen/X86/avx512-trunc.ll b/llvm/test/CodeGen/X86/avx512-trunc.ll
index d438e1b6a75d6..50cf48088e200 100644
--- a/llvm/test/CodeGen/X86/avx512-trunc.ll
+++ b/llvm/test/CodeGen/X86/avx512-trunc.ll
@@ -57,9 +57,8 @@ define <8 x i8> @trunc_qb_512_maskz(<8 x i64> %i, i8 %m) #0 {
 ;
 ; SKX-LABEL: trunc_qb_512_maskz:
 ; SKX:       ## %bb.0:
-; SKX-NEXT:    vpmovqb %zmm0, %xmm0
 ; SKX-NEXT:    kmovd %edi, %k1
-; SKX-NEXT:    vmovdqu8 %xmm0, %xmm0 {%k1} {z}
+; SKX-NEXT:    vpmovqb %zmm0, %xmm0 {%k1}
 ; SKX-NEXT:    vzeroupper
 ; SKX-NEXT:    retq
   %x = trunc <8 x i64> %i to <8 x i8>
diff --git a/llvm/test/CodeGen/X86/trunc-select-fold.ll b/llvm/test/CodeGen/X86/trunc-select-fold.ll
index fea533b2e251f..23a1e3a664941 100644
--- a/llvm/test/CodeGen/X86/trunc-select-fold.ll
+++ b/llvm/test/CodeGen/X86/trunc-select-fold.ll
@@ -6,8 +6,7 @@ define <8 x i8> @test_mask_vpmovqb(<8 x i64> %0, <8 x i64> %1) {
 ; CHECK:       # %bb.0: # %Entry
 ; CHECK-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
 ; CHECK-NEXT:    vpopcntq %zmm0, %zmm0
-; CHECK-NEXT:    vpmovqb %zmm0, %xmm0
-; CHECK-NEXT:    vmovdqu8 %xmm0, %xmm0 {%k1} {z}
+; CHECK-NEXT:    vpmovqb %zmm0, %xmm0 {%k1}
 ; CHECK-NEXT:    vzeroupper
 ; CHECK-NEXT:    retq
 Entry:

>From 0486878d533b415822ef62e888d216c218ba932e Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Fri, 31 Jul 2026 18:04:21 +0530
Subject: [PATCH 3/3] [X86] Add `{z}`. Add to test to `avx512-trunc.ll` itself

---
 llvm/lib/Target/X86/X86ISelLowering.cpp    |  5 +-
 llvm/test/CodeGen/X86/avx512-trunc.ll      | 65 +++++++++++++++++++++-
 llvm/test/CodeGen/X86/trunc-select-fold.ll | 18 ------
 3 files changed, 66 insertions(+), 22 deletions(-)
 delete mode 100644 llvm/test/CodeGen/X86/trunc-select-fold.ll

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d11057829525a..34b2ab8bcc7fa 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -48680,7 +48680,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
     return DAG.getNode(N->getOpcode(), DL, VT, Cond, LHS, RHS);
   }
 
-  // Fold vselect(mask, vtrunc(x), 0) to vtrunc for masked vpmovqb.
+  // Fold vselect(mask, vtrunc(x), 0) to vmtrunc for masked vpmovqb.
   if (Subtarget.hasAVX512() && CondVT.isVector() &&
       CondVT.getVectorElementType() == MVT::i1 &&
       ISD::isBuildVectorAllZeros(RHS.getNode()) && LHS.hasOneUse()) {
@@ -48688,8 +48688,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
       SDValue TruncSrc = LHS.getOperand(0);
       EVT TruncSrcVT = TruncSrc.getValueType();
       if (VT == MVT::v16i8 && TruncSrcVT == MVT::v8i64) {
-        return DAG.getNode(X86ISD::VMTRUNC, DL, VT, TruncSrc, DAG.getUNDEF(VT),
-                           Cond);
+        return DAG.getNode(X86ISD::VMTRUNC, DL, VT, TruncSrc, RHS, Cond);
       }
     }
   }
diff --git a/llvm/test/CodeGen/X86/avx512-trunc.ll b/llvm/test/CodeGen/X86/avx512-trunc.ll
index 50cf48088e200..e6806eee908db 100644
--- a/llvm/test/CodeGen/X86/avx512-trunc.ll
+++ b/llvm/test/CodeGen/X86/avx512-trunc.ll
@@ -58,7 +58,7 @@ define <8 x i8> @trunc_qb_512_maskz(<8 x i64> %i, i8 %m) #0 {
 ; SKX-LABEL: trunc_qb_512_maskz:
 ; SKX:       ## %bb.0:
 ; SKX-NEXT:    kmovd %edi, %k1
-; SKX-NEXT:    vpmovqb %zmm0, %xmm0 {%k1}
+; SKX-NEXT:    vpmovqb %zmm0, %xmm0 {%k1} {z}
 ; SKX-NEXT:    vzeroupper
 ; SKX-NEXT:    retq
   %x = trunc <8 x i64> %i to <8 x i8>
@@ -1463,3 +1463,66 @@ define void @test_trunc_v2i16_v2i8(ptr %dst, ptr %src) {
   store <2 x i8> %2, ptr %dst
   ret void
 }
+
+; Test vselect(mask, vtrunc(x), 0) to vmtrunc for masked vpmovqb. PR212865
+define <8 x i8> @test_mask_vpmovqb(<8 x i64> %0, <8 x i64> %1) {
+; CHECK-LABEL: test_mask_vpmovqb:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
+; CHECK-NEXT:    vpopcntq %zmm0, %zmm0
+; CHECK-NEXT:    vpmovqb %zmm0, %xmm0 {%k1} {z}
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
+; KNL-LABEL: test_mask_vpmovqb:
+; KNL:       ## %bb.0:
+; KNL-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
+; KNL-NEXT:    vextracti64x4 $1, %zmm0, %ymm1
+; KNL-NEXT:    vpbroadcastb {{.*#+}} ymm2 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15]
+; KNL-NEXT:    vpand %ymm2, %ymm1, %ymm3
+; KNL-NEXT:    vbroadcasti128 {{.*#+}} ymm4 = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]
+; KNL-NEXT:    ## ymm4 = mem[0,1,0,1]
+; KNL-NEXT:    vpshufb %ymm3, %ymm4, %ymm3
+; KNL-NEXT:    vpsrlw $4, %ymm1, %ymm1
+; KNL-NEXT:    vpand %ymm2, %ymm1, %ymm1
+; KNL-NEXT:    vpshufb %ymm1, %ymm4, %ymm1
+; KNL-NEXT:    vpaddb %ymm3, %ymm1, %ymm1
+; KNL-NEXT:    vpxor %xmm3, %xmm3, %xmm3
+; KNL-NEXT:    vpsadbw %ymm3, %ymm1, %ymm1
+; KNL-NEXT:    vpand %ymm2, %ymm0, %ymm5
+; KNL-NEXT:    vpshufb %ymm5, %ymm4, %ymm5
+; KNL-NEXT:    vpsrlw $4, %ymm0, %ymm0
+; KNL-NEXT:    vpand %ymm2, %ymm0, %ymm0
+; KNL-NEXT:    vpshufb %ymm0, %ymm4, %ymm0
+; KNL-NEXT:    vpaddb %ymm5, %ymm0, %ymm0
+; KNL-NEXT:    vpsadbw %ymm3, %ymm0, %ymm0
+; KNL-NEXT:    vinserti64x4 $1, %ymm1, %zmm0, %zmm0
+; KNL-NEXT:    vpmovqb %zmm0, %xmm0
+; KNL-NEXT:    vpternlogd {{.*#+}} zmm1 {%k1} {z} = -1
+; KNL-NEXT:    vpmovdb %zmm1, %xmm1
+; KNL-NEXT:    vpand %xmm0, %xmm1, %xmm0
+; KNL-NEXT:    vzeroupper
+; KNL-NEXT:    retq
+;
+; SKX-LABEL: test_mask_vpmovqb:
+; SKX:       ## %bb.0:
+; SKX-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
+; SKX-NEXT:    vpbroadcastb {{.*#+}} zmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15]
+; SKX-NEXT:    vpandq %zmm1, %zmm0, %zmm2
+; SKX-NEXT:    vbroadcasti32x4 {{.*#+}} zmm3 = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4]
+; SKX-NEXT:    ## zmm3 = mem[0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3]
+; SKX-NEXT:    vpshufb %zmm2, %zmm3, %zmm2
+; SKX-NEXT:    vpsrlw $4, %zmm0, %zmm0
+; SKX-NEXT:    vpandq %zmm1, %zmm0, %zmm0
+; SKX-NEXT:    vpshufb %zmm0, %zmm3, %zmm0
+; SKX-NEXT:    vpaddb %zmm2, %zmm0, %zmm0
+; SKX-NEXT:    vpxor %xmm1, %xmm1, %xmm1
+; SKX-NEXT:    vpsadbw %zmm1, %zmm0, %zmm0
+; SKX-NEXT:    vpmovqb %zmm0, %xmm0 {%k1} {z}
+; SKX-NEXT:    vzeroupper
+; SKX-NEXT:    retq
+  %3 = icmp eq <8 x i64> %0, %1
+  %4 = tail call range(i64 0, 65) <8 x i64> @llvm.ctpop.v8i64(<8 x i64> %0)
+  %5 = trunc nuw nsw <8 x i64> %4 to <8 x i8>
+  %6 = select <8 x i1> %3, <8 x i8> %5, <8 x i8> zeroinitializer
+  ret <8 x i8> %6
+}
diff --git a/llvm/test/CodeGen/X86/trunc-select-fold.ll b/llvm/test/CodeGen/X86/trunc-select-fold.ll
deleted file mode 100644
index 23a1e3a664941..0000000000000
--- a/llvm/test/CodeGen/X86/trunc-select-fold.ll
+++ /dev/null
@@ -1,18 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=znver5 | FileCheck %s
-
-define <8 x i8> @test_mask_vpmovqb(<8 x i64> %0, <8 x i64> %1) {
-; CHECK-LABEL: test_mask_vpmovqb:
-; CHECK:       # %bb.0: # %Entry
-; CHECK-NEXT:    vpcmpeqq %zmm1, %zmm0, %k1
-; CHECK-NEXT:    vpopcntq %zmm0, %zmm0
-; CHECK-NEXT:    vpmovqb %zmm0, %xmm0 {%k1}
-; CHECK-NEXT:    vzeroupper
-; CHECK-NEXT:    retq
-Entry:
-  %2 = icmp eq <8 x i64> %0, %1
-  %3 = tail call range(i64 0, 65) <8 x i64> @llvm.ctpop.v8i64(<8 x i64> %0)
-  %4 = trunc nuw nsw <8 x i64> %3 to <8 x i8>
-  %5 = select <8 x i1> %2, <8 x i8> %4, <8 x i8> zeroinitializer
-  ret <8 x i8> %5
-}



More information about the llvm-commits mailing list