[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