[llvm] [X86] Fold compares of widened vectors into masked compares (PR #228350)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 03:49:08 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Akash Manna (akash-manna-sky)
<details>
<summary>Changes</summary>
Part of #<!-- -->226389
Masked compares are only matched from an `and` that has the same mask type as the compare. When the compared vectors have to be widened, e.g. `<2 x float>` to `v4f32`, the compare gives a `v4i1` and the `v2i1` `and` only sees it through an `extract_subvector`. The same shape shows up with legal types too, because DAGCombiner narrows an `and` when only its low elements are used. Either way nothing matched, and we ended up with separate compares and a chain of `kandw` instead of `vcmpltps ... %k1 {%k1}`.
`PreprocessISelDAG` now widens such an `and` to the type of the compare and takes the low elements of the result, so the existing patterns do the rest. It has to happen there rather than in a DAG combine, since `narrowExtractedVectorBinOp` would narrow the `and` right back. An `and` that already has a compare of its own type as an operand is left alone: `isel` can fold that one, and it is what tells us the upper mask bits are zero.
---
Patch is 21.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/228350.diff
6 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelDAGToDAG.cpp (+55)
- (modified) llvm/test/CodeGen/X86/avx512-insert-extract.ll (+2-3)
- (modified) llvm/test/CodeGen/X86/avx512bw-intrinsics-fast-isel.ll (+4-6)
- (modified) llvm/test/CodeGen/X86/bitcast-and-setcc-128.ll (+34-46)
- (modified) llvm/test/CodeGen/X86/icmp-abs-C-vec.ll (+2-4)
- (added) llvm/test/CodeGen/X86/pr226389.ll (+196)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index c2de8283f15ff8..5692683f1ba340 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -985,6 +985,21 @@ static bool needBWI(MVT VT) {
return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
}
+// Return true if V is a compare that an AND can fold as a masked compare.
+static bool isSingleUseMaskCompare(SDValue V) {
+ return (V.getOpcode() == ISD::SETCC || V.getOpcode() == X86ISD::CMPM) &&
+ V.hasOneUse();
+}
+
+// Return the single-use wider compare that V is the low subvector of, if any.
+static SDValue getLowSubvectorMaskCompare(SDValue V) {
+ if (V.getOpcode() != ISD::EXTRACT_SUBVECTOR || !V.hasOneUse() ||
+ !isNullConstant(V.getOperand(1)))
+ return SDValue();
+ SDValue Src = V.getOperand(0);
+ return isSingleUseMaskCompare(Src) ? Src : SDValue();
+}
+
void X86DAGToDAGISel::PreprocessISelDAG() {
bool MadeChange = false;
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
@@ -1398,6 +1413,46 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
MadeChange = true;
continue;
}
+ case ISD::AND: {
+ // Masked compares only match an AND of the compare's type; widen the AND.
+ MVT VT = N->getSimpleValueType(0);
+ if (!VT.isVectorOf(MVT::i1))
+ break;
+
+ // Isel already folds this AND, or relies on its upper bits being zero.
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ if (isSingleUseMaskCompare(N0) || isSingleUseMaskCompare(N1) ||
+ isMaskZeroExtended(N))
+ break;
+
+ SDValue Cmp = getLowSubvectorMaskCompare(N1);
+ if (!Cmp)
+ Cmp = getLowSubvectorMaskCompare(N0);
+ if (!Cmp)
+ break;
+
+ SDLoc dl(N);
+ MVT WideVT = Cmp.getSimpleValueType();
+ SDValue ZeroIdx = CurDAG->getIntPtrConstant(0, dl);
+ auto Widen = [&](SDValue V) {
+ if (V.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
+ isNullConstant(V.getOperand(1)) &&
+ V.getOperand(0).getValueType() == WideVT)
+ return V.getOperand(0);
+ return CurDAG->getNode(ISD::INSERT_SUBVECTOR, dl, WideVT,
+ CurDAG->getUNDEF(WideVT), V, ZeroIdx);
+ };
+ SDValue Wide0 = Widen(N0);
+ SDValue Wide1 = Widen(N1);
+ SDValue Res = CurDAG->getNode(ISD::AND, dl, WideVT, Wide0, Wide1);
+ Res = CurDAG->getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Res, ZeroIdx);
+ --I;
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Res);
+ ++I;
+ MadeChange = true;
+ continue;
+ }
}
if (OptLevel != CodeGenOptLevel::None &&
diff --git a/llvm/test/CodeGen/X86/avx512-insert-extract.ll b/llvm/test/CodeGen/X86/avx512-insert-extract.ll
index 4efc4678f1d002..b890a74cc2416e 100644
--- a/llvm/test/CodeGen/X86/avx512-insert-extract.ll
+++ b/llvm/test/CodeGen/X86/avx512-insert-extract.ll
@@ -2071,11 +2071,10 @@ define void @test_concat_v2i1(ptr %arg, ptr %arg1, ptr %arg2) nounwind {
; SKX-LABEL: test_concat_v2i1:
; SKX: ## %bb.0:
; SKX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; SKX-NEXT: vcvtph2ps %xmm0, %ymm0
-; SKX-NEXT: vcmpltps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %k0
; SKX-NEXT: vxorps %xmm1, %xmm1, %xmm1
+; SKX-NEXT: vcvtph2ps %xmm0, %ymm0
; SKX-NEXT: vcmpltps %ymm0, %ymm1, %k1
-; SKX-NEXT: kandw %k1, %k0, %k1
+; SKX-NEXT: vcmpltps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %k1 {%k1}
; SKX-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero
; SKX-NEXT: vmovdqu16 %xmm0, %xmm0 {%k1} {z}
; SKX-NEXT: vmovd %xmm0, (%rdx)
diff --git a/llvm/test/CodeGen/X86/avx512bw-intrinsics-fast-isel.ll b/llvm/test/CodeGen/X86/avx512bw-intrinsics-fast-isel.ll
index ada2c8d53aa53a..4a5eb84d171701 100644
--- a/llvm/test/CodeGen/X86/avx512bw-intrinsics-fast-isel.ll
+++ b/llvm/test/CodeGen/X86/avx512bw-intrinsics-fast-isel.ll
@@ -15,13 +15,11 @@ define i64 @test_mm512_kunpackd(<8 x i64> %__A, <8 x i64> %__B, <8 x i64> %__C,
; X86-NEXT: andl $-64, %esp
; X86-NEXT: subl $64, %esp
; X86-NEXT: vmovdqa64 136(%ebp), %zmm3
-; X86-NEXT: vpcmpneqb %zmm0, %zmm1, %k0
-; X86-NEXT: vpcmpneqb 8(%ebp), %zmm2, %k1
-; X86-NEXT: vpcmpneqb 72(%ebp), %zmm3, %k2
-; X86-NEXT: kandd %k0, %k2, %k0
+; X86-NEXT: vpcmpneqb 72(%ebp), %zmm3, %k1
+; X86-NEXT: vpcmpneqb %zmm0, %zmm1, %k0 {%k1}
; X86-NEXT: kmovd %k0, %eax
-; X86-NEXT: kshiftrq $32, %k2, %k0
-; X86-NEXT: kandd %k1, %k0, %k0
+; X86-NEXT: kshiftrq $32, %k1, %k1
+; X86-NEXT: vpcmpneqb 8(%ebp), %zmm2, %k0 {%k1}
; X86-NEXT: kmovd %k0, %edx
; X86-NEXT: movl %ebp, %esp
; X86-NEXT: popl %ebp
diff --git a/llvm/test/CodeGen/X86/bitcast-and-setcc-128.ll b/llvm/test/CodeGen/X86/bitcast-and-setcc-128.ll
index de030f1b78d3dc..055fb7bafbe81e 100644
--- a/llvm/test/CodeGen/X86/bitcast-and-setcc-128.ll
+++ b/llvm/test/CodeGen/X86/bitcast-and-setcc-128.ll
@@ -214,11 +214,10 @@ define i2 @v2i8(<2 x i8> %a, <2 x i8> %b, <2 x i8> %c, <2 x i8> %d) {
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpcmpgtb %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0
-; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm0
-; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm1
+; AVX512F-NEXT: vpmovsxbd %xmm1, %zmm1
+; AVX512F-NEXT: vptestmd %zmm1, %zmm1, %k1
+; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: vzeroupper
@@ -226,9 +225,8 @@ define i2 @v2i8(<2 x i8> %a, <2 x i8> %b, <2 x i8> %c, <2 x i8> %d) {
;
; AVX512BW-LABEL: v2i8:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
@@ -265,11 +263,10 @@ define i2 @v2i16(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x i16> %d) {
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpcmpgtw %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: vpmovsxwd %xmm0, %ymm0
-; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k0
-; AVX512F-NEXT: vpcmpgtw %xmm3, %xmm2, %xmm0
-; AVX512F-NEXT: vpmovsxwd %xmm0, %ymm0
-; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtw %xmm3, %xmm2, %xmm1
+; AVX512F-NEXT: vpmovsxwd %xmm1, %ymm1
+; AVX512F-NEXT: vptestmd %ymm1, %ymm1, %k1
+; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: vzeroupper
@@ -277,9 +274,8 @@ define i2 @v2i16(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x i16> %d) {
;
; AVX512BW-LABEL: v2i16:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtw %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtw %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtw %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtw %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
@@ -313,18 +309,16 @@ define i2 @v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c, <2 x i32> %d) {
;
; AVX512F-LABEL: v2i32:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpcmpgtd %xmm1, %xmm0, %k0
-; AVX512F-NEXT: vpcmpgtd %xmm3, %xmm2, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtd %xmm1, %xmm0, %k1
+; AVX512F-NEXT: vpcmpgtd %xmm3, %xmm2, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: retq
;
; AVX512BW-LABEL: v2i32:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtd %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtd %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtd %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtd %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
@@ -462,11 +456,10 @@ define i4 @v4i8(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) {
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpcmpgtb %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0
-; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm0
-; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm1
+; AVX512F-NEXT: vpmovsxbd %xmm1, %zmm1
+; AVX512F-NEXT: vptestmd %zmm1, %zmm1, %k1
+; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: vzeroupper
@@ -474,9 +467,8 @@ define i4 @v4i8(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) {
;
; AVX512BW-LABEL: v4i8:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
@@ -512,11 +504,10 @@ define i4 @v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c, <4 x i16> %d) {
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpcmpgtw %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: vpmovsxwd %xmm0, %ymm0
-; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k0
-; AVX512F-NEXT: vpcmpgtw %xmm3, %xmm2, %xmm0
-; AVX512F-NEXT: vpmovsxwd %xmm0, %ymm0
-; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtw %xmm3, %xmm2, %xmm1
+; AVX512F-NEXT: vpmovsxwd %xmm1, %ymm1
+; AVX512F-NEXT: vptestmd %ymm1, %ymm1, %k1
+; AVX512F-NEXT: vptestmd %ymm0, %ymm0, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: vzeroupper
@@ -524,9 +515,8 @@ define i4 @v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c, <4 x i16> %d) {
;
; AVX512BW-LABEL: v4i16:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtw %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtw %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtw %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtw %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
@@ -560,11 +550,10 @@ define i8 @v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d) {
; AVX512F: # %bb.0:
; AVX512F-NEXT: vpcmpgtb %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0
-; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm0
-; AVX512F-NEXT: vpmovsxbd %xmm0, %zmm0
-; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k1
-; AVX512F-NEXT: kandw %k1, %k0, %k0
+; AVX512F-NEXT: vpcmpgtb %xmm3, %xmm2, %xmm1
+; AVX512F-NEXT: vpmovsxbd %xmm1, %zmm1
+; AVX512F-NEXT: vptestmd %zmm1, %zmm1, %k1
+; AVX512F-NEXT: vptestmd %zmm0, %zmm0, %k0 {%k1}
; AVX512F-NEXT: kmovw %k0, %eax
; AVX512F-NEXT: # kill: def $al killed $al killed $eax
; AVX512F-NEXT: vzeroupper
@@ -572,9 +561,8 @@ define i8 @v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d) {
;
; AVX512BW-LABEL: v8i8:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k0
-; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k1
-; AVX512BW-NEXT: kandw %k1, %k0, %k0
+; AVX512BW-NEXT: vpcmpgtb %xmm1, %xmm0, %k1
+; AVX512BW-NEXT: vpcmpgtb %xmm3, %xmm2, %k0 {%k1}
; AVX512BW-NEXT: kmovd %k0, %eax
; AVX512BW-NEXT: # kill: def $al killed $al killed $eax
; AVX512BW-NEXT: retq
diff --git a/llvm/test/CodeGen/X86/icmp-abs-C-vec.ll b/llvm/test/CodeGen/X86/icmp-abs-C-vec.ll
index 23dcf334124c05..90d086c045fa67 100644
--- a/llvm/test/CodeGen/X86/icmp-abs-C-vec.ll
+++ b/llvm/test/CodeGen/X86/icmp-abs-C-vec.ll
@@ -1015,12 +1015,11 @@ define <4 x i1> @ne_and_to_abs_vec4x8(<4 x i8> %x) {
; AVX512-NEXT: vpcmpeqb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
; AVX512-NEXT: vpternlogq {{.*#+}} xmm1 = ~xmm1
; AVX512-NEXT: vpmovsxbd %xmm1, %zmm1
-; AVX512-NEXT: vptestmd %zmm1, %zmm1, %k0
; AVX512-NEXT: vpcmpeqb {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
; AVX512-NEXT: vpternlogq {{.*#+}} xmm0 = ~xmm0
; AVX512-NEXT: vpmovsxbd %xmm0, %zmm0
; AVX512-NEXT: vptestmd %zmm0, %zmm0, %k1
-; AVX512-NEXT: kandw %k1, %k0, %k1
+; AVX512-NEXT: vptestmd %zmm1, %zmm1, %k1 {%k1}
; AVX512-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0
; AVX512-NEXT: vmovdqa32 %xmm0, %xmm0 {%k1} {z}
; AVX512-NEXT: vzeroupper
@@ -1070,12 +1069,11 @@ define <4 x i16> @ne_and_to_abs_vec4x16_sext(<4 x i16> %x) {
; AVX512-NEXT: vpcmpeqw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
; AVX512-NEXT: vpternlogq {{.*#+}} xmm1 = ~xmm1
; AVX512-NEXT: vpmovsxwd %xmm1, %ymm1
-; AVX512-NEXT: vptestmd %ymm1, %ymm1, %k0
; AVX512-NEXT: vpcmpeqw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
; AVX512-NEXT: vpternlogq {{.*#+}} xmm0 = ~xmm0
; AVX512-NEXT: vpmovsxwd %xmm0, %ymm0
; AVX512-NEXT: vptestmd %ymm0, %ymm0, %k1
-; AVX512-NEXT: kandw %k1, %k0, %k1
+; AVX512-NEXT: vptestmd %ymm1, %ymm1, %k1 {%k1}
; AVX512-NEXT: vpcmpeqd %ymm0, %ymm0, %ymm0
; AVX512-NEXT: vmovdqa32 %ymm0, %ymm0 {%k1} {z}
; AVX512-NEXT: vpmovdw %ymm0, %xmm0
diff --git a/llvm/test/CodeGen/X86/pr226389.ll b/llvm/test/CodeGen/X86/pr226389.ll
new file mode 100644
index 00000000000000..b25c7113dde0c3
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr226389.ll
@@ -0,0 +1,196 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512vl,+avx512bw,+avx512dq | FileCheck %s
+
+; A compare of vectors that get widened should still be folded into the AND of
+; its result as a masked compare.
+
+define i8 @cmp_v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c, <2 x float> %d, <2 x float> %e, <2 x float> %f) nounwind {
+; CHECK-LABEL: cmp_v2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vcmpltps %xmm0, %xmm1, %k1
+; CHECK-NEXT: vcmpltps %xmm0, %xmm2, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm3, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm4, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm5, %k0 {%k1}
+; CHECK-NEXT: kshiftlb $6, %k0, %k0
+; CHECK-NEXT: kshiftrb $6, %k0, %k0
+; CHECK-NEXT: kmovb %k0, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: kmovd %k0, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: retq
+ %retval = alloca <2 x i1>, align 1
+ %cmp0 = fcmp ogt <2 x float> %a, %b
+ %cmp1 = fcmp ogt <2 x float> %a, %c
+ %and0 = and <2 x i1> %cmp0, %cmp1
+ %cmp2 = fcmp ogt <2 x float> %a, %d
+ %and1 = and <2 x i1> %and0, %cmp2
+ %cmp3 = fcmp ogt <2 x float> %a, %e
+ %and2 = and <2 x i1> %and1, %cmp3
+ %cmp4 = fcmp ogt <2 x float> %a, %f
+ %and3 = and <2 x i1> %and2, %cmp4
+ store <2 x i1> %and3, ptr %retval, align 1
+ %res = load i8, ptr %retval, align 1
+ ret i8 %res
+}
+
+define i8 @cmp_v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c, <2 x i32> %d, <2 x i32> %e, <2 x i32> %f) nounwind {
+; CHECK-LABEL: cmp_v2i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %k1
+; CHECK-NEXT: vpcmpgtd %xmm2, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtd %xmm3, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtd %xmm4, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtd %xmm5, %xmm0, %k0 {%k1}
+; CHECK-NEXT: kshiftlb $6, %k0, %k0
+; CHECK-NEXT: kshiftrb $6, %k0, %k0
+; CHECK-NEXT: kmovb %k0, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: kmovd %k0, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: retq
+ %retval = alloca <2 x i1>, align 1
+ %cmp0 = icmp sgt <2 x i32> %a, %b
+ %cmp1 = icmp sgt <2 x i32> %a, %c
+ %and0 = and <2 x i1> %cmp0, %cmp1
+ %cmp2 = icmp sgt <2 x i32> %a, %d
+ %and1 = and <2 x i1> %and0, %cmp2
+ %cmp3 = icmp sgt <2 x i32> %a, %e
+ %and2 = and <2 x i1> %and1, %cmp3
+ %cmp4 = icmp sgt <2 x i32> %a, %f
+ %and3 = and <2 x i1> %and2, %cmp4
+ store <2 x i1> %and3, ptr %retval, align 1
+ %res = load i8, ptr %retval, align 1
+ ret i8 %res
+}
+
+define i8 @cmp_v2i16(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x i16> %d, <2 x i16> %e, <2 x i16> %f) nounwind {
+; CHECK-LABEL: cmp_v2i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpcmpgtw %xmm1, %xmm0, %k1
+; CHECK-NEXT: vpcmpgtw %xmm2, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm3, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm4, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm5, %xmm0, %k0 {%k1}
+; CHECK-NEXT: kshiftlb $6, %k0, %k0
+; CHECK-NEXT: kshiftrb $6, %k0, %k0
+; CHECK-NEXT: kmovb %k0, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: kmovd %k0, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: retq
+ %retval = alloca <2 x i1>, align 1
+ %cmp0 = icmp sgt <2 x i16> %a, %b
+ %cmp1 = icmp sgt <2 x i16> %a, %c
+ %and0 = and <2 x i1> %cmp0, %cmp1
+ %cmp2 = icmp sgt <2 x i16> %a, %d
+ %and1 = and <2 x i1> %and0, %cmp2
+ %cmp3 = icmp sgt <2 x i16> %a, %e
+ %and2 = and <2 x i1> %and1, %cmp3
+ %cmp4 = icmp sgt <2 x i16> %a, %f
+ %and3 = and <2 x i1> %and2, %cmp4
+ store <2 x i1> %and3, ptr %retval, align 1
+ %res = load i8, ptr %retval, align 1
+ ret i8 %res
+}
+
+define i8 @cmp_v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c, <4 x i16> %d, <4 x i16> %e, <4 x i16> %f) nounwind {
+; CHECK-LABEL: cmp_v4i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpcmpgtw %xmm1, %xmm0, %k1
+; CHECK-NEXT: vpcmpgtw %xmm2, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm3, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm4, %xmm0, %k1 {%k1}
+; CHECK-NEXT: vpcmpgtw %xmm5, %xmm0, %k0 {%k1}
+; CHECK-NEXT: kshiftlb $4, %k0, %k0
+; CHECK-NEXT: kshiftrb $4, %k0, %k0
+; CHECK-NEXT: kmovb %k0, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: kmovd %k0, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: retq
+ %retval = alloca <4 x i1>, align 1
+ %cmp0 = icmp sgt <4 x i16> %a, %b
+ %cmp1 = icmp sgt <4 x i16> %a, %c
+ %and0 = and <4 x i1> %cmp0, %cmp1
+ %cmp2 = icmp sgt <4 x i16> %a, %d
+ %and1 = and <4 x i1> %and0, %cmp2
+ %cmp3 = icmp sgt <4 x i16> %a, %e
+ %and2 = and <4 x i1> %and1, %cmp3
+ %cmp4 = icmp sgt <4 x i16> %a, %f
+ %and3 = and <4 x i1> %and2, %cmp4
+ store <4 x i1> %and3, ptr %retval, align 1
+ %res = load i8, ptr %retval, align 1
+ ret i8 %res
+}
+
+define i8 @cmp_v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, <4 x float> %e, <4 x float> %f) nounwind {
+; CHECK-LABEL: cmp_v4f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vcmpltps %xmm0, %xmm1, %k1
+; CHECK-NEXT: vcmpltps %xmm0, %xmm2, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm3, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm4, %k1 {%k1}
+; CHECK-NEXT: vcmpltps %xmm0, %xmm5, %k0 {%k1}
+; CHECK-NEXT: kmovb %k0, -{{[0-9]+}}(%rsp)
+; CHECK-NEXT: kmovd %k0, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: retq
+ %retval = alloca <4 x i1>, align 1
+ %cmp0 = fcmp ogt <4 x float> %a, %b
+ %cmp1 = fcmp ogt <4 x float> %a, %c
+ %and0 = and <4 x i1> %cmp0, %cmp1
+ %cmp2 = fcmp ogt <4 x float> %a, %d
+ %and1 = and <4 x i1> %and0, %cmp2
+ %cmp3 = fcmp ogt <4 x float> %a, %e
+ %and2 = and <4 x i1> %and1, %cmp3
+ %cmp4 = fcmp ogt <4 x float> %a, %f
+ %and3 = and <4 x i1> %and2, %cmp4
+ store <4 x i1> %and3, ptr %retval, align 1
+ %res = load i8, ptr %retval, align 1
+ ret i8 %res
+}
+
+; Only the low half of the AND is used.
+define i2 @cmp_v4f32_extract(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d) nounwind {
+; CHECK-LABEL: cmp_v4f32_extract:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vcmpltps %xmm0, %xmm1, %k1
+; CHECK-NEXT: vcmpltps %xmm0, %xmm2, %k1 {%k1}
+; CHECK-NEXT: vcmpl...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/228350
More information about the llvm-commits
mailing list