[llvm] [X86] Lower vector 8-bit rotr(x, 1) to pavgb pattern (PR #198980)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sat May 23 03:21:05 PDT 2026
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/198980
>From b26873c8728e1b56a46847964c9e7873adbae9e2 Mon Sep 17 00:00:00 2001
From: WenYuan Huang <michael881017 at gmail.com>
Date: Wed, 20 May 2026 15:07:14 -0500
Subject: [PATCH 1/4] [X86] Lower vector 8-bit rotr(x, 1) to pavgb pattern
Signed-off-by: WenYuan Huang <michael881017 at gmail.com>
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 9 ++
llvm/test/CodeGen/X86/vector-fshr-rot-128.ll | 84 +++++++-------
llvm/test/CodeGen/X86/vector-fshr-rot-256.ll | 111 +++++++++---------
llvm/test/CodeGen/X86/vector-fshr-rot-512.ll | 116 ++++++++++---------
4 files changed, 172 insertions(+), 148 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index f37d896b9c69e..b00eb8604a0f1 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32249,6 +32249,15 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget,
SDValue Z = DAG.getConstant(0, DL, VT);
if (!IsROTL) {
+ // rotr(x,1) -> pavgb(x, 0 - (x & 1))
+ if (EltSizeInBits == 8 && IsCstSplat && CstSplatValue.urem(EltSizeInBits) == 1) {
+ SDValue One = DAG.getConstant(1, DL, VT);
+ SDValue LSB = DAG.getNode(ISD::AND, DL, VT, R, One);
+ SDValue Zero = DAG.getConstant(0, DL, VT);
+ SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, Zero, LSB);
+ return DAG.getNode(ISD::AVGCEILU, DL, VT, R, Neg);
+ }
+
// If the ISD::ROTR amount is constant, we're always better converting to
// ISD::ROTL.
if (SDValue NegAmt = DAG.FoldConstantArithmetic(ISD::SUB, DL, VT, {Z, Amt}))
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
index 77109a9e87f95..0f8ebdaf04e78 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
@@ -1998,84 +1998,84 @@ define <16 x i8> @splatconstant_funnnel_v16i8(<16 x i8> %x) nounwind {
define <16 x i8> @splatconstant_funnnel_v16i8_by_one(<16 x i8> %x) nounwind {
; SSE-LABEL: splatconstant_funnnel_v16i8_by_one:
; SSE: # %bb.0:
-; SSE-NEXT: movdqa %xmm0, %xmm1
-; SSE-NEXT: psrlw $1, %xmm1
-; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
-; SSE-NEXT: psllw $7, %xmm0
-; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; SSE-NEXT: por %xmm1, %xmm0
+; SSE-NEXT: movdqa {{.*#+}} xmm1 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; SSE-NEXT: pand %xmm0, %xmm1
+; SSE-NEXT: pxor %xmm2, %xmm2
+; SSE-NEXT: psubb %xmm1, %xmm2
+; SSE-NEXT: pavgb %xmm2, %xmm0
; SSE-NEXT: retq
;
; AVX-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX: # %bb.0:
-; AVX-NEXT: vpsrlw $1, %xmm0, %xmm1
-; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1
-; AVX-NEXT: vpsllw $7, %xmm0, %xmm0
-; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
-; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX-NEXT: retq
;
; AVX512F-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512F-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
-; AVX512F-NEXT: vzeroupper
+; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX512F-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512F-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512F-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512VL-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512VL-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
+; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
+; AVX512VL-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VL-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512VL-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512BW-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512BW-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
-; AVX512BW-NEXT: vzeroupper
+; AVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512BW-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512BW-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512VLBW-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512VLBW-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
+; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
+; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLBW-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512VLBW-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512VBMI2-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512VBMI2-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
-; AVX512VBMI2-NEXT: vzeroupper
+; AVX512VBMI2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VBMI2-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512VBMI2-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpsllw $7, %xmm0, %xmm1
-; AVX512VLVBMI2-NEXT: vpsrlw $1, %xmm0, %xmm0
-; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
+; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
+; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLVBMI2-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; AVX512VLVBMI2-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX512VLVBMI2-NEXT: retq
;
; XOP-LABEL: splatconstant_funnnel_v16i8_by_one:
; XOP: # %bb.0:
-; XOP-NEXT: vprotb $7, %xmm0, %xmm0
+; XOP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; XOP-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; XOP-NEXT: vpsubb %xmm1, %xmm2, %xmm1
+; XOP-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; XOP-NEXT: retq
;
; X86-SSE2-LABEL: splatconstant_funnnel_v16i8_by_one:
; X86-SSE2: # %bb.0:
-; X86-SSE2-NEXT: movdqa %xmm0, %xmm1
-; X86-SSE2-NEXT: psrlw $1, %xmm1
-; X86-SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1
-; X86-SSE2-NEXT: psllw $7, %xmm0
-; X86-SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0
-; X86-SSE2-NEXT: por %xmm1, %xmm0
+; X86-SSE2-NEXT: movdqa {{.*#+}} xmm1 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; X86-SSE2-NEXT: pand %xmm0, %xmm1
+; X86-SSE2-NEXT: pxor %xmm2, %xmm2
+; X86-SSE2-NEXT: psubb %xmm1, %xmm2
+; X86-SSE2-NEXT: pavgb %xmm2, %xmm0
; X86-SSE2-NEXT: retl
%res = call <16 x i8> @llvm.fshr.v16i8(<16 x i8> %x, <16 x i8> %x, <16 x i8> splat (i8 1))
ret <16 x i8> %res
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
index ecb3c2c059cd6..4c02772773fc5 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
@@ -477,11 +477,12 @@ define <32 x i8> @var_funnnel_v32i8(<32 x i8> %x, <32 x i8> %amt) nounwind {
; AVX512F-NEXT: vpternlogd {{.*#+}} zmm3 = zmm3 ^ (m32bcst & (zmm3 ^ zmm2))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
-; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm2
-; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm3
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm3 = zmm3 ^ (m32bcst & (zmm3 ^ zmm2))
+; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2
+; AVX512F-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX512F-NEXT: vpsubb %ymm2, %ymm3, %ymm2
+; AVX512F-NEXT: vpavgb %ymm2, %ymm0, %ymm2
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm2, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: var_funnnel_v32i8:
@@ -496,11 +497,12 @@ define <32 x i8> @var_funnnel_v32i8(<32 x i8> %x, <32 x i8> %amt) nounwind {
; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm3 = ymm3 ^ (m32bcst & (ymm3 ^ ymm2))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
-; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm2
-; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm3
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm3 = ymm3 ^ (m32bcst & (ymm3 ^ ymm2))
+; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm2
+; AVX512VL-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX512VL-NEXT: vpsubb %ymm2, %ymm3, %ymm2
+; AVX512VL-NEXT: vpavgb %ymm2, %ymm0, %ymm2
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm2, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: var_funnnel_v32i8:
@@ -1756,87 +1758,92 @@ define <32 x i8> @splatconstant_funnnel_v32i8(<32 x i8> %x) nounwind {
define <32 x i8> @splatconstant_funnnel_v32i8_by_one(<32 x i8> %x) nounwind {
; AVX1-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX1: # %bb.0:
-; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1
-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2
-; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm3
-; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1
-; AVX1-NEXT: vbroadcastss {{.*#+}} ymm3 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128]
-; AVX1-NEXT: vandnps %ymm1, %ymm3, %ymm1
-; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0
-; AVX1-NEXT: vpsllw $7, %xmm2, %xmm2
+; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
+; AVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX1-NEXT: vpsubb %xmm2, %xmm3, %xmm2
+; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4
+; AVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2
+; AVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1
+; AVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0
; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
-; AVX1-NEXT: vandps %ymm3, %ymm0, %ymm0
-; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX2: # %bb.0:
-; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm1
-; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1
-; AVX2-NEXT: vpsllw $7, %ymm0, %ymm0
-; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
-; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm0
+; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; AVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX2-NEXT: retq
;
; AVX512F-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512F-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
+; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; AVX512F-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512F-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512F-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
+; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
+; AVX512VL-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VL-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512VL-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512BW-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512BW-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
+; AVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512BW-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512BW-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512VLBW-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512VLBW-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
+; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
+; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLBW-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512VLBW-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512VBMI2-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
-; AVX512VBMI2-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
+; AVX512VBMI2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VBMI2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512VBMI2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512VLVBMI2-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
+; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
+; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLVBMI2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; AVX512VLVBMI2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512VLVBMI2-NEXT: retq
;
; XOPAVX1-LABEL: splatconstant_funnnel_v32i8_by_one:
; XOPAVX1: # %bb.0:
-; XOPAVX1-NEXT: vprotb $7, %xmm0, %xmm1
-; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm0
-; XOPAVX1-NEXT: vprotb $7, %xmm0, %xmm0
-; XOPAVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0
+; XOPAVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
+; XOPAVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; XOPAVX1-NEXT: vpsubb %xmm2, %xmm3, %xmm2
+; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm4
+; XOPAVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2
+; XOPAVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1
+; XOPAVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
; XOPAVX1-NEXT: retq
;
; XOPAVX2-LABEL: splatconstant_funnnel_v32i8_by_one:
; XOPAVX2: # %bb.0:
-; XOPAVX2-NEXT: vprotb $7, %xmm0, %xmm1
-; XOPAVX2-NEXT: vextracti128 $1, %ymm0, %xmm0
-; XOPAVX2-NEXT: vprotb $7, %xmm0, %xmm0
-; XOPAVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
+; XOPAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
+; XOPAVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; XOPAVX2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
+; XOPAVX2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; XOPAVX2-NEXT: retq
%res = call <32 x i8> @llvm.fshr.v32i8(<32 x i8> %x, <32 x i8> %x, <32 x i8> splat (i8 1))
ret <32 x i8> %res
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
index 27de093e5a985..01a5e444038ff 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
@@ -142,27 +142,28 @@ define <64 x i8> @var_funnnel_v64i8(<64 x i8> %x, <64 x i8> %amt) nounwind {
; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm4 ^ (zmm7 & (zmm6 ^ zmm4))
; AVX512F-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512F-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
-; AVX512F-NEXT: vpsrlw $1, %ymm2, %ymm4
-; AVX512F-NEXT: vpsllw $7, %ymm2, %ymm6
-; AVX512F-NEXT: vpbroadcastd {{.*#+}} zmm8 = [2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152]
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm4 ^ (zmm8 & (zmm6 ^ zmm4))
+; AVX512F-NEXT: vpbroadcastb {{.*#+}} ymm4 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; AVX512F-NEXT: vpand %ymm4, %ymm2, %ymm6
+; AVX512F-NEXT: vpxor %xmm8, %xmm8, %xmm8
+; AVX512F-NEXT: vpsubb %ymm6, %ymm8, %ymm6
+; AVX512F-NEXT: vpavgb %ymm6, %ymm2, %ymm6
; AVX512F-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512F-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
; AVX512F-NEXT: vpsrlw $4, %ymm0, %ymm3
-; AVX512F-NEXT: vpsllw $4, %ymm0, %ymm4
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm5 & (zmm4 ^ zmm3))
+; AVX512F-NEXT: vpsllw $4, %ymm0, %ymm6
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm3 ^ (zmm5 & (zmm6 ^ zmm3))
; AVX512F-NEXT: vpsllw $5, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm6, %ymm0, %ymm0
; AVX512F-NEXT: vpsrlw $2, %ymm0, %ymm3
-; AVX512F-NEXT: vpsllw $6, %ymm0, %ymm4
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm7 & (zmm4 ^ zmm3))
+; AVX512F-NEXT: vpsllw $6, %ymm0, %ymm5
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm5 = zmm3 ^ (zmm7 & (zmm5 ^ zmm3))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
-; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm3
-; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm4
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm8 & (zmm4 ^ zmm3))
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm5, %ymm0, %ymm0
+; AVX512F-NEXT: vpand %ymm4, %ymm0, %ymm3
+; AVX512F-NEXT: vpsubb %ymm3, %ymm8, %ymm3
+; AVX512F-NEXT: vpavgb %ymm3, %ymm0, %ymm3
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
; AVX512F-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
; AVX512F-NEXT: retq
;
@@ -182,27 +183,28 @@ define <64 x i8> @var_funnnel_v64i8(<64 x i8> %x, <64 x i8> %amt) nounwind {
; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm4 ^ (ymm7 & (ymm6 ^ ymm4))
; AVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512VL-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
-; AVX512VL-NEXT: vpsrlw $1, %ymm2, %ymm4
-; AVX512VL-NEXT: vpsllw $7, %ymm2, %ymm6
-; AVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm8 = [2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152]
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm4 ^ (ymm8 & (ymm6 ^ ymm4))
+; AVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm4 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; AVX512VL-NEXT: vpand %ymm4, %ymm2, %ymm6
+; AVX512VL-NEXT: vpxor %xmm8, %xmm8, %xmm8
+; AVX512VL-NEXT: vpsubb %ymm6, %ymm8, %ymm6
+; AVX512VL-NEXT: vpavgb %ymm6, %ymm2, %ymm6
; AVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512VL-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
; AVX512VL-NEXT: vpsrlw $4, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm5 & (ymm4 ^ ymm3))
+; AVX512VL-NEXT: vpsllw $4, %ymm0, %ymm6
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm3 ^ (ymm5 & (ymm6 ^ ymm3))
; AVX512VL-NEXT: vpsllw $5, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm6, %ymm0, %ymm0
; AVX512VL-NEXT: vpsrlw $2, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsllw $6, %ymm0, %ymm4
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm7 & (ymm4 ^ ymm3))
+; AVX512VL-NEXT: vpsllw $6, %ymm0, %ymm5
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm5 = ymm3 ^ (ymm7 & (ymm5 ^ ymm3))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
-; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm4
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm8 & (ymm4 ^ ymm3))
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm5, %ymm0, %ymm0
+; AVX512VL-NEXT: vpand %ymm4, %ymm0, %ymm3
+; AVX512VL-NEXT: vpsubb %ymm3, %ymm8, %ymm3
+; AVX512VL-NEXT: vpavgb %ymm3, %ymm0, %ymm3
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
; AVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
; AVX512VL-NEXT: retq
;
@@ -772,54 +774,60 @@ define <64 x i8> @splatconstant_funnnel_v64i8(<64 x i8> %x) nounwind {
define <64 x i8> @splatconstant_funnnel_v64i8_by_one(<64 x i8> %x) nounwind {
; AVX512F-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512F-NEXT: vextracti64x4 $1, %zmm0, %ymm2
-; AVX512F-NEXT: vpsllw $7, %ymm2, %ymm3
-; AVX512F-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1
-; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512F-NEXT: vpsrlw $1, %ymm2, %ymm2
+; AVX512F-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512F-NEXT: vextracti64x4 $1, %zmm1, %ymm2
+; AVX512F-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX512F-NEXT: vpsubb %ymm2, %ymm3, %ymm2
+; AVX512F-NEXT: vextracti64x4 $1, %zmm0, %ymm4
+; AVX512F-NEXT: vpavgb %ymm2, %ymm4, %ymm2
+; AVX512F-NEXT: vpsubb %ymm1, %ymm3, %ymm1
+; AVX512F-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512F-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm1
-; AVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm2
-; AVX512VL-NEXT: vpsllw $7, %ymm2, %ymm3
-; AVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1
-; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm0
-; AVX512VL-NEXT: vpsrlw $1, %ymm2, %ymm2
+; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm2
+; AVX512VL-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX512VL-NEXT: vpsubb %ymm2, %ymm3, %ymm2
+; AVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm4
+; AVX512VL-NEXT: vpavgb %ymm2, %ymm4, %ymm2
+; AVX512VL-NEXT: vpsubb %ymm1, %ymm3, %ymm1
+; AVX512VL-NEXT: vpavgb %ymm1, %ymm0, %ymm0
; AVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
-; AVX512VL-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpsllw $7, %zmm0, %zmm1
-; AVX512BW-NEXT: vpsrlw $1, %zmm0, %zmm0
-; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512BW-NEXT: vpsubb %zmm1, %zmm2, %zmm1
+; AVX512BW-NEXT: vpavgb %zmm1, %zmm0, %zmm0
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpsllw $7, %zmm0, %zmm1
-; AVX512VLBW-NEXT: vpsrlw $1, %zmm0, %zmm0
-; AVX512VLBW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLBW-NEXT: vpsubb %zmm1, %zmm2, %zmm1
+; AVX512VLBW-NEXT: vpavgb %zmm1, %zmm0, %zmm0
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpsllw $7, %zmm0, %zmm1
-; AVX512VBMI2-NEXT: vpsrlw $1, %zmm0, %zmm0
-; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512VBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VBMI2-NEXT: vpsubb %zmm1, %zmm2, %zmm1
+; AVX512VBMI2-NEXT: vpavgb %zmm1, %zmm0, %zmm0
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpsllw $7, %zmm0, %zmm1
-; AVX512VLVBMI2-NEXT: vpsrlw $1, %zmm0, %zmm0
-; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
+; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
+; AVX512VLVBMI2-NEXT: vpsubb %zmm1, %zmm2, %zmm1
+; AVX512VLVBMI2-NEXT: vpavgb %zmm1, %zmm0, %zmm0
; AVX512VLVBMI2-NEXT: retq
%res = call <64 x i8> @llvm.fshr.v64i8(<64 x i8> %x, <64 x i8> %x, <64 x i8> splat (i8 1))
ret <64 x i8> %res
>From 1b54fe70d56a75cca7d41d471d387c5f8ce8afbf Mon Sep 17 00:00:00 2001
From: WenYuan Huang <michael881017 at gmail.com>
Date: Thu, 21 May 2026 03:02:30 -0500
Subject: [PATCH 2/4] [X86] Apply rotr(x,1) -> pavgb(x, 0 - (x & 1)) only when
Subtarget.hasGFNI() is false
Signed-off-by: WenYuan Huang <michael881017 at gmail.com>
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b00eb8604a0f1..38d189547826b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32250,14 +32250,15 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget,
if (!IsROTL) {
// rotr(x,1) -> pavgb(x, 0 - (x & 1))
- if (EltSizeInBits == 8 && IsCstSplat && CstSplatValue.urem(EltSizeInBits) == 1) {
+ if (EltSizeInBits == 8 && IsCstSplat &&
+ CstSplatValue.urem(EltSizeInBits) == 1 && !Subtarget.hasGFNI()) {
SDValue One = DAG.getConstant(1, DL, VT);
SDValue LSB = DAG.getNode(ISD::AND, DL, VT, R, One);
SDValue Zero = DAG.getConstant(0, DL, VT);
SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, Zero, LSB);
return DAG.getNode(ISD::AVGCEILU, DL, VT, R, Neg);
}
-
+
// If the ISD::ROTR amount is constant, we're always better converting to
// ISD::ROTL.
if (SDValue NegAmt = DAG.FoldConstantArithmetic(ISD::SUB, DL, VT, {Z, Amt}))
>From 2b9071a7b4e81c26b0aca7a12fba669ee0217b93 Mon Sep 17 00:00:00 2001
From: WenYuan Huang <michael881017 at gmail.com>
Date: Thu, 21 May 2026 15:35:52 -0500
Subject: [PATCH 3/4] [X86] Lower rotl(x,7) to pavgb when x is 8-bit
Signed-off-by: WenYuan Huang <michael881017 at gmail.com>
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 20 +++++-----
llvm/test/CodeGen/X86/vector-fshr-rot-128.ll | 5 +--
llvm/test/CodeGen/X86/vector-fshr-rot-256.ll | 40 +++++++++-----------
3 files changed, 29 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 38d189547826b..e05215e9567f0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32249,16 +32249,6 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget,
SDValue Z = DAG.getConstant(0, DL, VT);
if (!IsROTL) {
- // rotr(x,1) -> pavgb(x, 0 - (x & 1))
- if (EltSizeInBits == 8 && IsCstSplat &&
- CstSplatValue.urem(EltSizeInBits) == 1 && !Subtarget.hasGFNI()) {
- SDValue One = DAG.getConstant(1, DL, VT);
- SDValue LSB = DAG.getNode(ISD::AND, DL, VT, R, One);
- SDValue Zero = DAG.getConstant(0, DL, VT);
- SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, Zero, LSB);
- return DAG.getNode(ISD::AVGCEILU, DL, VT, R, Neg);
- }
-
// If the ISD::ROTR amount is constant, we're always better converting to
// ISD::ROTL.
if (SDValue NegAmt = DAG.FoldConstantArithmetic(ISD::SUB, DL, VT, {Z, Amt}))
@@ -32283,6 +32273,16 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget,
if (VT.is256BitVector() && (Subtarget.hasXOP() || !Subtarget.hasAVX2()))
return splitVectorIntBinary(Op, DAG, DL);
+ // rotl(x,7) -> pavgb(x, 0 - (x & 1))
+ if (EltSizeInBits == 8 && IsCstSplat &&
+ CstSplatValue.urem(EltSizeInBits) == 7 && IsROTL) {
+ SDValue One = DAG.getConstant(1, DL, VT);
+ SDValue LSB = DAG.getNode(ISD::AND, DL, VT, R, One);
+ SDValue Zero = DAG.getConstant(0, DL, VT);
+ SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, Zero, LSB);
+ return DAG.getNode(ISD::AVGCEILU, DL, VT, R, Neg);
+ }
+
// Rotate by an uniform constant - expand back to shifts.
// TODO: Can't use generic expansion as UNDEF amt elements can be converted
// to other values when folded to shift amounts, losing the splat.
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
index 0f8ebdaf04e78..e0da87b910298 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
@@ -2063,10 +2063,7 @@ define <16 x i8> @splatconstant_funnnel_v16i8_by_one(<16 x i8> %x) nounwind {
;
; XOP-LABEL: splatconstant_funnnel_v16i8_by_one:
; XOP: # %bb.0:
-; XOP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
-; XOP-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; XOP-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; XOP-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; XOP-NEXT: vprotb $7, %xmm0, %xmm0
; XOP-NEXT: retq
;
; X86-SSE2-LABEL: splatconstant_funnnel_v16i8_by_one:
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
index 4c02772773fc5..efdad88e69e88 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
@@ -1758,15 +1758,16 @@ define <32 x i8> @splatconstant_funnnel_v32i8(<32 x i8> %x) nounwind {
define <32 x i8> @splatconstant_funnnel_v32i8_by_one(<32 x i8> %x) nounwind {
; AVX1-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX1: # %bb.0:
-; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
-; AVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; AVX1-NEXT: vpsubb %xmm2, %xmm3, %xmm2
-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4
-; AVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2
-; AVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1
-; AVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0
-; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
+; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1
+; AVX1-NEXT: vbroadcastss {{.*#+}} xmm2 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm3
+; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4
+; AVX1-NEXT: vpsubb %xmm3, %xmm4, %xmm3
+; AVX1-NEXT: vpavgb %xmm3, %xmm1, %xmm1
+; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm2
+; AVX1-NEXT: vpsubb %xmm2, %xmm4, %xmm2
+; AVX1-NEXT: vpavgb %xmm2, %xmm0, %xmm0
+; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
; AVX1-NEXT: retq
;
; AVX2-LABEL: splatconstant_funnnel_v32i8_by_one:
@@ -1827,23 +1828,18 @@ define <32 x i8> @splatconstant_funnnel_v32i8_by_one(<32 x i8> %x) nounwind {
;
; XOPAVX1-LABEL: splatconstant_funnnel_v32i8_by_one:
; XOPAVX1: # %bb.0:
-; XOPAVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; XOPAVX1-NEXT: vextractf128 $1, %ymm1, %xmm2
-; XOPAVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; XOPAVX1-NEXT: vpsubb %xmm2, %xmm3, %xmm2
-; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm4
-; XOPAVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2
-; XOPAVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1
-; XOPAVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0
-; XOPAVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0
+; XOPAVX1-NEXT: vprotb $7, %xmm0, %xmm1
+; XOPAVX1-NEXT: vextractf128 $1, %ymm0, %xmm0
+; XOPAVX1-NEXT: vprotb $7, %xmm0, %xmm0
+; XOPAVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0
; XOPAVX1-NEXT: retq
;
; XOPAVX2-LABEL: splatconstant_funnnel_v32i8_by_one:
; XOPAVX2: # %bb.0:
-; XOPAVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; XOPAVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; XOPAVX2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; XOPAVX2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; XOPAVX2-NEXT: vprotb $7, %xmm0, %xmm1
+; XOPAVX2-NEXT: vextracti128 $1, %ymm0, %xmm0
+; XOPAVX2-NEXT: vprotb $7, %xmm0, %xmm0
+; XOPAVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
; XOPAVX2-NEXT: retq
%res = call <32 x i8> @llvm.fshr.v32i8(<32 x i8> %x, <32 x i8> %x, <32 x i8> splat (i8 1))
ret <32 x i8> %res
>From 328d7c8a0565f7399f3dfbb2e6a90442ab2899eb Mon Sep 17 00:00:00 2001
From: WenYuan Huang <michael881017 at gmail.com>
Date: Sat, 23 May 2026 00:39:14 -0500
Subject: [PATCH 4/4] [X86] Lower rotl(x,7) to pavgb(x, 0 - (x & 1)) only when
AVX512 is unavailable
Signed-off-by: WenYuan Huang <michael881017 at gmail.com>
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 6 +-
llvm/test/CodeGen/X86/vector-fshr-rot-128.ll | 48 ++++----
llvm/test/CodeGen/X86/vector-fshr-rot-256.ll | 63 +++++-----
llvm/test/CodeGen/X86/vector-fshr-rot-512.ll | 116 +++++++++----------
4 files changed, 110 insertions(+), 123 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index e05215e9567f0..7d9c389efd1e3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -32275,11 +32275,11 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget,
// rotl(x,7) -> pavgb(x, 0 - (x & 1))
if (EltSizeInBits == 8 && IsCstSplat &&
- CstSplatValue.urem(EltSizeInBits) == 7 && IsROTL) {
+ CstSplatValue.urem(EltSizeInBits) == 7 && IsROTL &&
+ !Subtarget.hasAVX512()) {
SDValue One = DAG.getConstant(1, DL, VT);
SDValue LSB = DAG.getNode(ISD::AND, DL, VT, R, One);
- SDValue Zero = DAG.getConstant(0, DL, VT);
- SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, Zero, LSB);
+ SDValue Neg = DAG.getNegative(LSB, DL, VT);
return DAG.getNode(ISD::AVGCEILU, DL, VT, R, Neg);
}
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
index e0da87b910298..313cb18e36f3b 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-128.ll
@@ -2015,50 +2015,50 @@ define <16 x i8> @splatconstant_funnnel_v16i8_by_one(<16 x i8> %x) nounwind {
;
; AVX512F-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
-; AVX512F-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512F-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512F-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512F-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512F-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
+; AVX512F-NEXT: vzeroupper
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
-; AVX512VL-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VL-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512VL-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512VL-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512VL-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512VL-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
-; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512BW-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512BW-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512BW-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512BW-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512BW-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
+; AVX512BW-NEXT: vzeroupper
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
-; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLBW-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512VLBW-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512VLBW-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512VLBW-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512VLBW-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
-; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VBMI2-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512VBMI2-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512VBMI2-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512VBMI2-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512VBMI2-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0
+; AVX512VBMI2-NEXT: vzeroupper
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v16i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm1
-; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLVBMI2-NEXT: vpsubb %xmm1, %xmm2, %xmm1
-; AVX512VLVBMI2-NEXT: vpavgb %xmm1, %xmm0, %xmm0
+; AVX512VLVBMI2-NEXT: vpsllw $7, %xmm0, %xmm1
+; AVX512VLVBMI2-NEXT: vpsrlw $1, %xmm0, %xmm0
+; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} xmm0 = xmm0 ^ (m32bcst & (xmm0 ^ xmm1))
; AVX512VLVBMI2-NEXT: retq
;
; XOP-LABEL: splatconstant_funnnel_v16i8_by_one:
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
index efdad88e69e88..fbd7b722bab04 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-256.ll
@@ -477,12 +477,11 @@ define <32 x i8> @var_funnnel_v32i8(<32 x i8> %x, <32 x i8> %amt) nounwind {
; AVX512F-NEXT: vpternlogd {{.*#+}} zmm3 = zmm3 ^ (m32bcst & (zmm3 ^ zmm2))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
-; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2
-; AVX512F-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; AVX512F-NEXT: vpsubb %ymm2, %ymm3, %ymm2
-; AVX512F-NEXT: vpavgb %ymm2, %ymm0, %ymm2
+; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm2
+; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm3
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm3 = zmm3 ^ (m32bcst & (zmm3 ^ zmm2))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm2, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: var_funnnel_v32i8:
@@ -497,12 +496,11 @@ define <32 x i8> @var_funnnel_v32i8(<32 x i8> %x, <32 x i8> %amt) nounwind {
; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm3 = ymm3 ^ (m32bcst & (ymm3 ^ ymm2))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
-; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm2
-; AVX512VL-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; AVX512VL-NEXT: vpsubb %ymm2, %ymm3, %ymm2
-; AVX512VL-NEXT: vpavgb %ymm2, %ymm0, %ymm2
+; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm2
+; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm3
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm3 = ymm3 ^ (m32bcst & (ymm3 ^ ymm2))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm2, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: var_funnnel_v32i8:
@@ -1780,50 +1778,47 @@ define <32 x i8> @splatconstant_funnnel_v32i8_by_one(<32 x i8> %x) nounwind {
;
; AVX512F-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; AVX512F-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512F-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512F-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512F-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
-; AVX512VL-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VL-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512VL-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512BW-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512BW-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512BW-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512BW-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512BW-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
-; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLBW-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512VLBW-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512VLBW-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512VLBW-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512VLBW-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1
-; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VBMI2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512VBMI2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512VBMI2-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512VBMI2-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
+; AVX512VBMI2-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v32i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm1
-; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLVBMI2-NEXT: vpsubb %ymm1, %ymm2, %ymm1
-; AVX512VLVBMI2-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512VLVBMI2-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512VLVBMI2-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} ymm0 = ymm0 ^ (m32bcst & (ymm0 ^ ymm1))
; AVX512VLVBMI2-NEXT: retq
;
; XOPAVX1-LABEL: splatconstant_funnnel_v32i8_by_one:
diff --git a/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll b/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
index 01a5e444038ff..27de093e5a985 100644
--- a/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
+++ b/llvm/test/CodeGen/X86/vector-fshr-rot-512.ll
@@ -142,28 +142,27 @@ define <64 x i8> @var_funnnel_v64i8(<64 x i8> %x, <64 x i8> %amt) nounwind {
; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm4 ^ (zmm7 & (zmm6 ^ zmm4))
; AVX512F-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512F-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
-; AVX512F-NEXT: vpbroadcastb {{.*#+}} ymm4 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
-; AVX512F-NEXT: vpand %ymm4, %ymm2, %ymm6
-; AVX512F-NEXT: vpxor %xmm8, %xmm8, %xmm8
-; AVX512F-NEXT: vpsubb %ymm6, %ymm8, %ymm6
-; AVX512F-NEXT: vpavgb %ymm6, %ymm2, %ymm6
+; AVX512F-NEXT: vpsrlw $1, %ymm2, %ymm4
+; AVX512F-NEXT: vpsllw $7, %ymm2, %ymm6
+; AVX512F-NEXT: vpbroadcastd {{.*#+}} zmm8 = [2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152]
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm4 ^ (zmm8 & (zmm6 ^ zmm4))
; AVX512F-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512F-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
; AVX512F-NEXT: vpsrlw $4, %ymm0, %ymm3
-; AVX512F-NEXT: vpsllw $4, %ymm0, %ymm6
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm6 = zmm3 ^ (zmm5 & (zmm6 ^ zmm3))
+; AVX512F-NEXT: vpsllw $4, %ymm0, %ymm4
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm5 & (zmm4 ^ zmm3))
; AVX512F-NEXT: vpsllw $5, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm6, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
; AVX512F-NEXT: vpsrlw $2, %ymm0, %ymm3
-; AVX512F-NEXT: vpsllw $6, %ymm0, %ymm5
-; AVX512F-NEXT: vpternlogd {{.*#+}} zmm5 = zmm3 ^ (zmm7 & (zmm5 ^ zmm3))
+; AVX512F-NEXT: vpsllw $6, %ymm0, %ymm4
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm7 & (zmm4 ^ zmm3))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm5, %ymm0, %ymm0
-; AVX512F-NEXT: vpand %ymm4, %ymm0, %ymm3
-; AVX512F-NEXT: vpsubb %ymm3, %ymm8, %ymm3
-; AVX512F-NEXT: vpavgb %ymm3, %ymm0, %ymm3
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm3
+; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm4
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm4 = zmm3 ^ (zmm8 & (zmm4 ^ zmm3))
; AVX512F-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512F-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
+; AVX512F-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
; AVX512F-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
; AVX512F-NEXT: retq
;
@@ -183,28 +182,27 @@ define <64 x i8> @var_funnnel_v64i8(<64 x i8> %x, <64 x i8> %amt) nounwind {
; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm4 ^ (ymm7 & (ymm6 ^ ymm4))
; AVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512VL-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
-; AVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm4 = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
-; AVX512VL-NEXT: vpand %ymm4, %ymm2, %ymm6
-; AVX512VL-NEXT: vpxor %xmm8, %xmm8, %xmm8
-; AVX512VL-NEXT: vpsubb %ymm6, %ymm8, %ymm6
-; AVX512VL-NEXT: vpavgb %ymm6, %ymm2, %ymm6
+; AVX512VL-NEXT: vpsrlw $1, %ymm2, %ymm4
+; AVX512VL-NEXT: vpsllw $7, %ymm2, %ymm6
+; AVX512VL-NEXT: vpbroadcastd {{.*#+}} ymm8 = [2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152,2155905152]
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm4 ^ (ymm8 & (ymm6 ^ ymm4))
; AVX512VL-NEXT: vpaddb %ymm3, %ymm3, %ymm3
; AVX512VL-NEXT: vpblendvb %ymm3, %ymm6, %ymm2, %ymm2
; AVX512VL-NEXT: vpsrlw $4, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsllw $4, %ymm0, %ymm6
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm6 = ymm3 ^ (ymm5 & (ymm6 ^ ymm3))
+; AVX512VL-NEXT: vpsllw $4, %ymm0, %ymm4
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm5 & (ymm4 ^ ymm3))
; AVX512VL-NEXT: vpsllw $5, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm6, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
; AVX512VL-NEXT: vpsrlw $2, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsllw $6, %ymm0, %ymm5
-; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm5 = ymm3 ^ (ymm7 & (ymm5 ^ ymm3))
+; AVX512VL-NEXT: vpsllw $6, %ymm0, %ymm4
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm7 & (ymm4 ^ ymm3))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm5, %ymm0, %ymm0
-; AVX512VL-NEXT: vpand %ymm4, %ymm0, %ymm3
-; AVX512VL-NEXT: vpsubb %ymm3, %ymm8, %ymm3
-; AVX512VL-NEXT: vpavgb %ymm3, %ymm0, %ymm3
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
+; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm3
+; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm4
+; AVX512VL-NEXT: vpternlogd {{.*#+}} ymm4 = ymm3 ^ (ymm8 & (ymm4 ^ ymm3))
; AVX512VL-NEXT: vpaddb %ymm1, %ymm1, %ymm1
-; AVX512VL-NEXT: vpblendvb %ymm1, %ymm3, %ymm0, %ymm0
+; AVX512VL-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0
; AVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
; AVX512VL-NEXT: retq
;
@@ -774,60 +772,54 @@ define <64 x i8> @splatconstant_funnnel_v64i8(<64 x i8> %x) nounwind {
define <64 x i8> @splatconstant_funnnel_v64i8_by_one(<64 x i8> %x) nounwind {
; AVX512F-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512F: # %bb.0:
-; AVX512F-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512F-NEXT: vextracti64x4 $1, %zmm1, %ymm2
-; AVX512F-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; AVX512F-NEXT: vpsubb %ymm2, %ymm3, %ymm2
-; AVX512F-NEXT: vextracti64x4 $1, %zmm0, %ymm4
-; AVX512F-NEXT: vpavgb %ymm2, %ymm4, %ymm2
-; AVX512F-NEXT: vpsubb %ymm1, %ymm3, %ymm1
-; AVX512F-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512F-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512F-NEXT: vextracti64x4 $1, %zmm0, %ymm2
+; AVX512F-NEXT: vpsllw $7, %ymm2, %ymm3
+; AVX512F-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1
+; AVX512F-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512F-NEXT: vpsrlw $1, %ymm2, %ymm2
; AVX512F-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
+; AVX512F-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512F-NEXT: retq
;
; AVX512VL-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VL: # %bb.0:
-; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm2
-; AVX512VL-NEXT: vpxor %xmm3, %xmm3, %xmm3
-; AVX512VL-NEXT: vpsubb %ymm2, %ymm3, %ymm2
-; AVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm4
-; AVX512VL-NEXT: vpavgb %ymm2, %ymm4, %ymm2
-; AVX512VL-NEXT: vpsubb %ymm1, %ymm3, %ymm1
-; AVX512VL-NEXT: vpavgb %ymm1, %ymm0, %ymm0
+; AVX512VL-NEXT: vpsllw $7, %ymm0, %ymm1
+; AVX512VL-NEXT: vextracti64x4 $1, %zmm0, %ymm2
+; AVX512VL-NEXT: vpsllw $7, %ymm2, %ymm3
+; AVX512VL-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1
+; AVX512VL-NEXT: vpsrlw $1, %ymm0, %ymm0
+; AVX512VL-NEXT: vpsrlw $1, %ymm2, %ymm2
; AVX512VL-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0
+; AVX512VL-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512VL-NEXT: retq
;
; AVX512BW-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512BW: # %bb.0:
-; AVX512BW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512BW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512BW-NEXT: vpsubb %zmm1, %zmm2, %zmm1
-; AVX512BW-NEXT: vpavgb %zmm1, %zmm0, %zmm0
+; AVX512BW-NEXT: vpsllw $7, %zmm0, %zmm1
+; AVX512BW-NEXT: vpsrlw $1, %zmm0, %zmm0
+; AVX512BW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512BW-NEXT: retq
;
; AVX512VLBW-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VLBW: # %bb.0:
-; AVX512VLBW-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512VLBW-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLBW-NEXT: vpsubb %zmm1, %zmm2, %zmm1
-; AVX512VLBW-NEXT: vpavgb %zmm1, %zmm0, %zmm0
+; AVX512VLBW-NEXT: vpsllw $7, %zmm0, %zmm1
+; AVX512VLBW-NEXT: vpsrlw $1, %zmm0, %zmm0
+; AVX512VLBW-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512VLBW-NEXT: retq
;
; AVX512VBMI2-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VBMI2: # %bb.0:
-; AVX512VBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512VBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VBMI2-NEXT: vpsubb %zmm1, %zmm2, %zmm1
-; AVX512VBMI2-NEXT: vpavgb %zmm1, %zmm0, %zmm0
+; AVX512VBMI2-NEXT: vpsllw $7, %zmm0, %zmm1
+; AVX512VBMI2-NEXT: vpsrlw $1, %zmm0, %zmm0
+; AVX512VBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512VBMI2-NEXT: retq
;
; AVX512VLVBMI2-LABEL: splatconstant_funnnel_v64i8_by_one:
; AVX512VLVBMI2: # %bb.0:
-; AVX512VLVBMI2-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm1
-; AVX512VLVBMI2-NEXT: vpxor %xmm2, %xmm2, %xmm2
-; AVX512VLVBMI2-NEXT: vpsubb %zmm1, %zmm2, %zmm1
-; AVX512VLVBMI2-NEXT: vpavgb %zmm1, %zmm0, %zmm0
+; AVX512VLVBMI2-NEXT: vpsllw $7, %zmm0, %zmm1
+; AVX512VLVBMI2-NEXT: vpsrlw $1, %zmm0, %zmm0
+; AVX512VLVBMI2-NEXT: vpternlogd {{.*#+}} zmm0 = zmm0 ^ (m32bcst & (zmm0 ^ zmm1))
; AVX512VLVBMI2-NEXT: retq
%res = call <64 x i8> @llvm.fshr.v64i8(<64 x i8> %x, <64 x i8> %x, <64 x i8> splat (i8 1))
ret <64 x i8> %res
More information about the llvm-commits
mailing list