[llvm] [X86] Fold OR of constant splats into GF2P8AFFINEQB (PR #194330)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 27 03:34:19 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: hanbeom (ParkHanbum)

<details>
<summary>Changes</summary>

Fold OR of a constant byte splat into X86ISD::GF2P8AFFINEQB when the
affine matrix is known at compile time.

For bits forced to 1 by the OR mask, zero the corresponding matrix rows
(in reverse row order within each 64-bit lane) and set the same bits in
the immediate. This turns:

  gf2p8affineqb(x, M, imm) | C

into:

  gf2p8affineqb(x, M & KeepMask, imm | C)

where KeepMask clears the rows for output bits selected by C.

This removes a separate OR after GF2P8AFFINEQB for constant-matrix cases
and extends the existing GFNI combine coverage beyond XOR folds.

Fixes: https://github.com/llvm/llvm-project/issues/191173

---

Patch is 26.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/194330.diff


3 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+50) 
- (added) llvm/test/CodeGen/X86/gfni-or-fold-avx512.ll (+248) 
- (added) llvm/test/CodeGen/X86/gfni-or-fold.ll (+436) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index ebc8766969251..e37080cc62e80 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -53171,6 +53171,53 @@ static SDValue combineAddOrSubToADCOrSBB(SDNode *N, const SDLoc &DL,
   return SDValue();
 }
 
+static SDValue combineOrWithGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
+                                          SelectionDAG &DAG, EVT VT) {
+  using namespace SDPatternMatch;
+  SDValue LHS = N->getOperand(0), RHS = N->getOperand(1);
+  auto TryMatch = [&](SDValue GFSide, SDValue ConstSide) -> SDValue {
+    SDValue GF = GFSide;
+    SDValue X, Matrix;
+    APInt Imm;
+    if (!sd_match(GF, m_OneUse(m_TernaryOp(X86ISD::GF2P8AFFINEQB, m_Value(X),
+                                           m_Value(Matrix), m_ConstInt(Imm)))))
+      return SDValue();
+
+    APInt SplatVal;
+    if (!X86::isConstantSplat(ConstSide, SplatVal,
+                              /*AllowPartialUndefs=*/false))
+      return SDValue();
+
+    APInt UndefElts;
+    SmallVector<APInt, 16> OldMatrix;
+    if (!getTargetConstantBitsFromNode(Matrix, 8, UndefElts, OldMatrix,
+                                       /*AllowWholeUndefs=*/false,
+                                       /*AllowPartialUndefs=*/false))
+      return SDValue();
+
+    EVT GFVT = GF.getValueType();
+    uint8_t Mask8 = SplatVal.getZExtValue() & 0xFF;
+    uint8_t NewImm = Imm.getZExtValue() | Mask8;
+    SmallVector<SDValue, 64> MaskOps;
+    for (unsigned I = 0, E = GFVT.getVectorNumElements(); I != E; ++I) {
+      unsigned OutBit = 7 - (I & 7);
+      uint8_t Keep = ((Mask8 >> OutBit) & 1) ? 0x00 : 0xFF;
+      MaskOps.push_back(DAG.getConstant(Keep, DL, MVT::i8));
+    }
+
+    SDValue KeepMask = DAG.getBuildVector(GFVT, DL, MaskOps);
+    SDValue NewMatrix = DAG.getNode(ISD::AND, DL, GFVT, Matrix, KeepMask);
+    SDValue NewGF = DAG.getNode(X86ISD::GF2P8AFFINEQB, DL, GFVT, X, NewMatrix,
+                                DAG.getTargetConstant(NewImm, DL, MVT::i8));
+    return NewGF;
+  };
+
+  if (SDValue R = TryMatch(LHS, RHS))
+    return R;
+
+  return TryMatch(RHS, LHS);
+}
+
 static SDValue combineOrXorWithSETCC(unsigned Opc, const SDLoc &DL, EVT VT,
                                      SDValue N0, SDValue N1,
                                      SelectionDAG &DAG) {
@@ -53375,6 +53422,9 @@ static SDValue combineOr(SDNode *N, SelectionDAG &DAG,
   if (SDValue R = combineOrXorWithSETCC(N->getOpcode(), dl, VT, N0, N1, DAG))
     return R;
 
+  if (SDValue R = combineOrWithGF2P8AFFINEQB(N, dl, DAG, VT))
+    return R;
+
   return SDValue();
 }
 
diff --git a/llvm/test/CodeGen/X86/gfni-or-fold-avx512.ll b/llvm/test/CodeGen/X86/gfni-or-fold-avx512.ll
new file mode 100644
index 0000000000000..020fdbc8db540
--- /dev/null
+++ b/llvm/test/CodeGen/X86/gfni-or-fold-avx512.ll
@@ -0,0 +1,248 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512bw,+gfni | FileCheck %s
+
+declare <64 x i8> @llvm.x86.vgf2p8affineqb.512(<64 x i8>, <64 x i8>, i8)
+
+define dso_local <64 x i8> @test_affine_or_fold_512_v64i8(<64 x i8> noundef %a) local_unnamed_addr {
+; CHECK:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   1
+; CHECK-NEXT:   .byte   2
+; CHECK-NEXT:   .byte   4
+; CHECK-NEXT:   .byte   8
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+;
+; CHECK-LABEL: test_affine_or_fold_512_v64i8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm0, %zmm0
+; CHECK-NEXT:    retq
+entry:
+  %gf = tail call <64 x i8> @llvm.x86.vgf2p8affineqb.512(
+      <64 x i8> %a,
+      <64 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128>,
+      i8 0)
+  %or = or <64 x i8> %gf, splat(i8 15)
+  ret <64 x i8> %or
+}
+
+define dso_local <64 x i8> @test_affine_or_fold_512_v64i8_commuted(<64 x i8> noundef %a) local_unnamed_addr {
+; CHECK-LABEL: test_affine_or_fold_512_v64i8_commuted:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm0, %zmm0
+; CHECK-NEXT:    retq
+entry:
+  %gf = tail call <64 x i8> @llvm.x86.vgf2p8affineqb.512(
+      <64 x i8> %a,
+      <64 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128>,
+      i8 0)
+  %or = or <64 x i8> splat (i8 15), %gf
+  ret <64 x i8> %or
+}
+
+define dso_local <64 x i8> @test_affine_or_fold_v64i8_mask33(<64 x i8> noundef %a) {
+; CHECK:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   90
+; CHECK-NEXT:   .byte   165
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   24
+; CHECK-NEXT:   .byte   129
+; CHECK-NEXT:   .byte   0
+; CHECK-NEXT:   .byte   0
+;
+; CHECK-LABEL: _v64i8_mask33:
+; CHECK:         # %bb.0: # %entry
+; CHECK-NEXT:    vgf2p8affineqb $51, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm0, %zmm0
+; CHECK-NEXT:    retq
+entry:
+  %gf = tail call <64 x i8> @llvm.x86.vgf2p8affineqb.512(
+      <64 x i8> %a,
+      <64 x i8> <i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1>,
+      i8 0)
+  %or = or <64 x i8> %gf, splat(i8 51)
+  ret <64 x i8> %or
+}
+
+; Negative
+
+define dso_local <64 x i8> @test_affine_or_nofold_nonconst_matrix_v64i8(<64 x i8> noundef %a, <64 x i8> noundef %m) {
+; CHECK-LABEL: test_affine_or_nofold_nonconst_matrix_v64i8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vgf2p8affineqb $0, %zmm1, %zmm0, %zmm0
+; CHECK-NEXT:    vpord {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm0
+; CHECK-NEXT:    retq
+entry:
+  %gf = tail call <64 x i8> @llvm.x86.vgf2p8affineqb.512(
+      <64 x i8> %a,
+      <64 x i8> %m,
+      i8 0)
+  %or = or <64 x i8> %gf, splat(i8 51)
+  ret <64 x i8> %or
+}
+
+define dso_local <64 x i8> @test_affine_or_nofold_nonsplat_mask_v64i8(<64 x i8> noundef %a) {
+; CHECK-LABEL: test_affine_or_nofold_nonsplat_mask_v64i8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm0, %zmm0
+; CHECK-NEXT:    vporq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm0
+; CHECK-NEXT:    retq
+entry:
+  %gf = tail call <64 x i8> @llvm.x86.vgf2p8affineqb.512(
+      <64 x i8> %a,
+      <64 x i8> <i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1>,
+      i8 0)
+  %or = or <64 x i8> %gf,
+            <i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51,
+            i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 51, i8 50>
+  ret <64 x i8> %or
+}
+
+
diff --git a/llvm/test/CodeGen/X86/gfni-or-fold.ll b/llvm/test/CodeGen/X86/gfni-or-fold.ll
new file mode 100644
index 0000000000000..92258158d4619
--- /dev/null
+++ b/llvm/test/CodeGen/X86/gfni-or-fold.ll
@@ -0,0 +1,436 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+gfni,+avx | FileCheck %s --check-prefixes=AVX
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512vl,+gfni,+avx512bw | FileCheck %s --check-prefixes=AVX512
+
+declare <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8>, <16 x i8>, i8)
+declare <32 x i8> @llvm.x86.vgf2p8affineqb.256(<32 x i8>, <32 x i8>, i8)
+
+define dso_local <16 x i8> @test_affine_or_fold_v16i8(<16 x i8> noundef %a) {
+; AVX:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+;
+; AVX-LABEL: test_affine_or_fold_v16i8:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX-NEXT:    retq
+;
+; AVX512:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+;
+; AVX512-LABEL: test_affine_or_fold_v16i8:
+; AVX512:       # %bb.0: # %entry
+; AVX512-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0
+; AVX512-NEXT:    retq
+entry:
+  %gf = tail call <16 x i8> @llvm.x86.vgf2p8affineqb.128(
+      <16 x i8> %a,
+      <16 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128>,
+      i8 0)
+  %or = or <16 x i8> %gf, splat(i8 15)
+  ret <16 x i8> %or
+}
+
+define dso_local <16 x i8> @test_affine_or_fold_v16i8_commuted(<16 x i8> noundef %a) {
+; AVX-LABEL: test_affine_or_fold_v16i8_commuted:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX-NEXT:    retq
+;
+; AVX512-LABEL: test_affine_or_fold_v16i8_commuted:
+; AVX512:       # %bb.0: # %entry
+; AVX512-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0
+; AVX512-NEXT:    retq
+entry:
+  %gf = tail call <16 x i8> @llvm.x86.vgf2p8affineqb.128(
+      <16 x i8> %a,
+      <16 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128>,
+      i8 0)
+  %or = or <16 x i8> splat(i8 15), %gf
+  ret <16 x i8> %or
+}
+
+define dso_local <16 x i8> @test_affine_or_fold_v16i8_mask33(<16 x i8> noundef %a) {
+; AVX:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX-NEXT:   .byte   90
+; AVX-NEXT:   .byte   165
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   24
+; AVX-NEXT:   .byte   129
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   90
+; AVX-NEXT:   .byte   165
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   24
+; AVX-NEXT:   .byte   129
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+;
+; AVX-LABEL: test_affine_or_fold_v16i8_mask33:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    vgf2p8affineqb $51, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
+; AVX-NEXT:    retq
+;
+; AVX512:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX512-NEXT:   .byte   90
+; AVX512-NEXT:   .byte   165
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   24
+; AVX512-NEXT:   .byte   129
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   90
+; AVX512-NEXT:   .byte   165
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   24
+; AVX512-NEXT:   .byte   129
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+;
+; AVX512-LABEL: test_affine_or_fold_v16i8_mask33:
+; AVX512:       # %bb.0: # %entry
+; AVX512-NEXT:    vgf2p8affineqb $51, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0
+; AVX512-NEXT:    retq
+entry:
+  %gf = tail call <16 x i8> @llvm.x86.vgf2p8affineqb.128(
+      <16 x i8> %a,
+      <16 x i8> <i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1,
+                 i8 90, i8 -91, i8 60, i8 -61, i8 24, i8 -127, i8 126, i8 1>,
+      i8 0)
+  %or = or <16 x i8> %gf, splat(i8 51)
+  ret <16 x i8> %or
+}
+
+
+define dso_local <32 x i8> @test_affine_or_fold_v32i8(<32 x i8> noundef %a) {
+; AVX:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   1
+; AVX-NEXT:   .byte   2
+; AVX-NEXT:   .byte   4
+; AVX-NEXT:   .byte   8
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-NEXT:   .byte   0
+; AVX-LABEL: test_affine_or_fold_v32i8:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
+; AVX-NEXT:    retq
+;
+; AVX512:        [[MAT:\.LCPI[0-9]+_[0-9]+]]:
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   1
+; AVX512-NEXT:   .byte   2
+; AVX512-NEXT:   .byte   4
+; AVX512-NEXT:   .byte   8
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-NEXT:   .byte   0
+; AVX512-LABEL: test_affine_or_fold_v32i8:
+; AVX512:       # %bb.0: # %entry
+; AVX512-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %ymm0, %ymm0
+; AVX512-NEXT:    retq
+entry:
+  %gf = tail call <32 x i8> @llvm.x86.vgf2p8affineqb.256(
+      <32 x i8> %a,
+      <32 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128>,
+      i8 0)
+  %or = or <32 x i8> %gf, splat (i8 15)
+  ret <32 x i8> %or
+}
+
+define dso_local <32 x i8> @test_affine_or_fold_v32i8_commuted(<32 x i8> noundef %a) {
+; AVX-LABEL: test_affine_or_fold_v32i8_commuted:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0
+; AVX-NEXT:    retq
+;
+; AVX512-LABEL: test_affine_or_fold_v32i8_commuted:
+; AVX512:       # %bb.0: # %entry
+; AVX512-NEXT:    vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %ymm0, %ymm0
+; AVX512-NEXT:    retq
+entry:
+  %gf = tail call <32 x i8> @llvm.x86.vgf2p8affineqb.256(
+      <32 x i8> %a,
+      <32 x i8> <i8 1, i8 2, i8 4, i8 8, i8 16, i8 32, i8 64, i8 -128,
+                 i8 1, i8 2, i8 4, i...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/194330


More information about the llvm-commits mailing list