[llvm] [X86] Fold nested VGF2P8AFFINEQB instructions (PR #195210)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 30 19:55:12 PDT 2026
https://github.com/WalterKruger created https://github.com/llvm/llvm-project/pull/195210
Given that `vgf2p8affineqb` can perform arbitrary XOR permutations of the input, all nested affine transformations can be performed with a single instruction. The matrix for such fold can be calculated by permuting the sub-matrix by the super-matrix at a byte, rather than bit, granularity. This patch:
- Folds nested `vgf2p8affineqb` instructions with constant matrix operands into one.
- Folds the sub-immediate by performing a affine transformation by the super-matrix.
- Can fold non-splat super-matrices if the sub-immediate is zero.
- Includes test coverage for complex nested affine transformations, verifying the correctness of the folded matrix and immediate.
- Includes negative test coverage for when the fold isn't possible.
Fixes #179607
>From dcbcef5495b4dfd066431af9550120201b633d1d Mon Sep 17 00:00:00 2001
From: Walter <walter.kruger at hotmail.com>
Date: Fri, 1 May 2026 11:02:05 +1000
Subject: [PATCH 1/2] [NFC] Baseline test without fold
Current codegen for nested GF2P8AFFINEQB instructions.
---
llvm/test/CodeGen/X86/gfni-nested-fold.ll | 205 ++++++++++++++++++++++
1 file changed, 205 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/gfni-nested-fold.ll
diff --git a/llvm/test/CodeGen/X86/gfni-nested-fold.ll b/llvm/test/CodeGen/X86/gfni-nested-fold.ll
new file mode 100644
index 0000000000000..e268ec95a820f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/gfni-nested-fold.ll
@@ -0,0 +1,205 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-- -mattr=+gfni,+avx2 | FileCheck %s
+
+declare <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8>, <16 x i8>, i8)
+
+define <16 x i8> @test_ashr1_rotl2(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_ashr1_rotl2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [32,16,8,4,2,1,128,64,32,16,8,4,2,1,128,64]
+; CHECK-NEXT: retq
+ %ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 0)
+ %rotl2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr1, <16 x i8> <i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64>, i8 0)
+ ret <16 x i8> %rotl2
+}
+
+define <16 x i8> @test_ashr2_reverse(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_ashr2_reverse:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,128,64,32,16,8,4,128,128,128,64,32,16,8,4]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: retq
+ %ashr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr2, <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)
+ ret <16 x i8> %rev
+}
+
+define <16 x i8> @test_ashr2_splat_lsb(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_ashr2_splat_lsb:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,128,64,32,16,8,4,128,128,128,64,32,16,8,4]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; CHECK-NEXT: retq
+ %ashr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
+ %lsb = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr2, <16 x i8> splat(i8 1), i8 0)
+ ret <16 x i8> %lsb
+}
+
+define <16 x i8> @test_cumulative_parity_both_directions(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_cumulative_parity_both_directions:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,192,224,240,248,252,254,255,128,192,224,240,248,252,254,255]
+; CHECK-NEXT: retq
+ %left = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
+ %right = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %left, <16 x i8> <i8 128, i8 192, i8 224, i8 240, i8 248, i8 252, i8 254, i8 255, i8 128, i8 192, i8 224, i8 240, i8 248, i8 252, i8 254, i8 255>, i8 0)
+ ret <16 x i8> %right
+}
+
+define <16 x i8> @test_reverse_reverse_reverse(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_reverse_reverse_reverse:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpbroadcastq {{.*#+}} xmm1 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: retq
+ %rev1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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)
+ %rev2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev1, <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)
+ %rev3 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev2, <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)
+ ret <16 x i8> %rev3
+}
+
+define <16 x i8> @test_parity_fill_cumulative_parity(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_parity_fill_cumulative_parity:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: retq
+ %fill = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> splat(i8 -1), i8 0)
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %fill, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
+ ret <16 x i8> %parity
+}
+
+define <16 x i8> @test_ashr1_reverse_non_zero_imm(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_ashr1_reverse_non_zero_imm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: retq
+ %ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 15)
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr1, <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)
+ ret <16 x i8> %rev
+}
+
+define <16 x i8> @test_reverse_ashr1_non_zero_imm(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_reverse_ashr1_non_zero_imm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $129, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
+; CHECK-NEXT: retq
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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 129)
+ %ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 0)
+ ret <16 x i8> %ashr1
+}
+
+define <16 x i8> @test_const_gen_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_const_gen_cumulative_parity_non_zero_imm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $127, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [64,32,32,32,32,32,32,32,64,32,32,32,32,32,32,32]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: retq
+ %gen = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 64, i8 32, i8 32, i8 32,i8 32, i8 32, i8 32, i8 32, i8 64, i8 32, i8 32, i8 32,i8 32, i8 32, i8 32, i8 32>, i8 127)
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %gen, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
+ ret <16 x i8> %parity
+}
+
+define <16 x i8> @test_rotr2_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_rotr2_cumulative_parity_non_zero_imm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $255, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,1,128,64,32,16,8,4,2,1,128,64,32,16,8,4]
+; CHECK-NEXT: vgf2p8affineqb $255, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: retq
+ %rotr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 255)
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rotr2, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 255)
+ ret <16 x i8> %parity
+}
+
+;; Positive case: Same number of instructions but shortens dependency chain
+define <16 x i8> @test_multi_use(<16 x i8> %src, ptr %sink) nounwind {
+; CHECK-LABEL: test_multi_use:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vmovdqa %xmm0, (%rdi)
+; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: retq
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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)
+ store <16 x i8> %rev, ptr %sink
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev, <16 x i8> splat(i8 -1), i8 0)
+ ret <16 x i8> %parity
+}
+
+;; Positive case: Non-splat sub-matrix can still fold
+define <16 x i8> @test_ashr12_reverse(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_ashr12_reverse:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,128,64,32,16,8,4]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: retq
+ %ashr12 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr12, <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)
+ ret <16 x i8> %rev
+}
+
+;; Positive case: Non-splat super-matrix can still fold with a zero immediate
+define <16 x i8> @test_cumulative_parity_fill_17(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_cumulative_parity_fill_17:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,2,2,2,2,2,2,2,128,128,128,128,128,128,128,128]
+; CHECK-NEXT: retq
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
+ %fill12 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %parity, <16 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128>, i8 0)
+ ret <16 x i8> %fill12
+}
+
+;; Negative case: Non-splat super-matrix can't fold a non-zero immediate
+define <16 x i8> @test_cumulative_parity_fill_17_non_zero_imm(<16 x i8> %src) nounwind {
+; CHECK-LABEL: test_cumulative_parity_fill_17_non_zero_imm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $1, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,2,2,2,2,2,2,2,128,128,128,128,128,128,128,128]
+; CHECK-NEXT: retq
+ %parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 1)
+ %fill12 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %parity, <16 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128>, i8 0)
+ ret <16 x i8> %fill12
+}
+
+;; Negative case: Can't fold if sub-matrix isn't constant
+define <16 x i8> @test_variable_sub(<16 x i8> %src, <16 x i8> %matrix) nounwind {
+; CHECK-LABEL: test_variable_sub:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: retq
+ %gfni = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> %matrix, i8 0)
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %gfni, <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)
+ ret <16 x i8> %rev
+}
+
+;; Negative case: Can't fold if super-matrix isn't constant
+define <16 x i8> @test_variable_super(<16 x i8> %src, <16 x i8> %matrix) nounwind {
+; CHECK-LABEL: test_variable_super:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: retq
+ %rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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)
+ %gfni = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev, <16 x i8> %matrix, i8 0)
+ ret <16 x i8> %gfni
+}
+
+;; Negative case: Can't fold with both variable
+define <16 x i8> @test_both_variable(<16 x i8> %src, <16 x i8> %submatrix, <16 x i8> %supmatrix) nounwind {
+; CHECK-LABEL: test_both_variable:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, %xmm2, %xmm0, %xmm0
+; CHECK-NEXT: retq
+ %sub = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> %submatrix, i8 0)
+ %sup = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %sub, <16 x i8> %supmatrix, i8 0)
+ ret <16 x i8> %sup
+}
>From 27a986adf5621764612c2d6fa09ef351df0e1592 Mon Sep 17 00:00:00 2001
From: Walter <walter.kruger at hotmail.com>
Date: Fri, 1 May 2026 11:16:27 +1000
Subject: [PATCH 2/2] Nested GF2P8AFFINEQB fold + update test
- Added the nested GF2P8AFFINEQB fold
- Updated the regression test to reflect this change
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 97 +++++++++++++++++++++++
llvm/test/CodeGen/X86/gfni-nested-fold.ll | 43 ++++------
2 files changed, 111 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 79929a66fd192..be0fe0362881f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -29420,6 +29420,25 @@ SDValue getGFNICtrlMask(unsigned Opcode, SelectionDAG &DAG, const SDLoc &DL,
return DAG.getBuildVector(VT, DL, MaskBits);
}
+static APInt getGFNIByteAffine(const APInt &ByteToAffine, const APInt &Matrix64,
+ const APInt &Addend8) {
+ assert(ByteToAffine.getBitWidth() == 8 && "Byte input unexpected size!");
+ assert(Addend8.getBitWidth() == 8 && "8-bit addend input unexpected size!");
+ assert(Matrix64.getBitWidth() == 64 &&
+ "64-bit matrix input unexpected size!");
+
+ APInt ByteSplat = APInt::getSplat(64, ByteToAffine);
+ ByteSplat &= Matrix64.byteSwap();
+
+ // Cumulative parity
+ for (unsigned i = 0; i < 3; ++i)
+ ByteSplat ^= ByteSplat.lshr(1 << i);
+ ByteSplat &= 0x0101010101010101ull;
+
+ APInt Affined = APIntOps::ScaleBitMask(ByteSplat, 8);
+ return Affined ^ Addend8;
+}
+
/// Lower a vector CTLZ using native supported vector CTLZ instruction.
//
// i8/i16 vector implemented using dword LZCNT vector instruction
@@ -62136,6 +62155,83 @@ static SDValue combineKSHIFT(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+// Fold: GF2P8AFFINEQB(GF2P8AFFINEQB(X, YSub), YSup)
+// => GF2P8AFFINEQB(X, YFolded)
+// Permuting the sub-matrix by the super-matrix at a byte, rather than bit,
+// granularity produces a matrix that performs both permutations at once.
+static SDValue combineNestedGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
+ SelectionDAG &DAG, EVT VT) {
+ using namespace SDPatternMatch;
+
+ unsigned VecWidth = VT.getSizeInBits();
+ unsigned NumElts = VT.getVectorNumElements();
+ unsigned EltWidth = VT.getScalarSizeInBits();
+
+ SDValue X, YSub, YSup;
+ APInt ImmSub, ImmSup, ConstUndef;
+ SmallVector<APInt> YSubEltBits, YSupEltBits;
+
+ if (!(sd_match(N, m_TernaryOp(X86ISD::GF2P8AFFINEQB,
+ m_TernaryOp(X86ISD::GF2P8AFFINEQB, m_Value(X),
+ m_Value(YSub), m_ConstInt(ImmSub)),
+ m_Value(YSup), m_ConstInt(ImmSup))) &&
+ getTargetConstantBitsFromNode(YSub, EltWidth, ConstUndef, YSubEltBits,
+ /*AllowWholeUndefs=*/false) &&
+ getTargetConstantBitsFromNode(YSup, EltWidth, ConstUndef, YSupEltBits,
+ /*AllowWholeUndefs=*/false)))
+ return SDValue();
+
+ APInt SubM(VecWidth, 0);
+ APInt SupM(VecWidth, 0);
+ for (unsigned i = 0; i < NumElts; ++i) {
+ SubM.insertBits(YSubEltBits[i], i * EltWidth);
+ SupM.insertBits(YSupEltBits[i], i * EltWidth);
+ }
+
+ // Immediate is shared and needs to be permuted in the same manner
+ if (!SupM.isSplat(64) && ImmSub != 0)
+ return SDValue();
+
+ // Immediate permute
+ APInt FoldedImm = getGFNIByteAffine(ImmSub, SupM.trunc(64), ImmSup);
+
+ // Matrix permute
+ APInt FoldedMatrix = APInt(VecWidth, 0);
+ APInt LeastRowMask = APInt::getSplat(VecWidth, APInt(64, 0xFF));
+ APInt LeastBitInByte = APInt::getSplat(VecWidth, APInt(8, 0x01));
+ APInt RowSplatter = APInt(VecWidth, 0x0101010101010101ull);
+
+ for (unsigned Row = 0; Row < 8; ++Row) {
+ APInt RowSplat = (SubM & LeastRowMask) * RowSplatter;
+ SubM = SubM.lshr(EltWidth);
+
+ APInt ByteMaskIfSet = (SupM.lshr(7 - Row)) & LeastBitInByte;
+ ByteMaskIfSet *= 0xFF;
+
+ FoldedMatrix ^= RowSplat & ByteMaskIfSet;
+ }
+
+ SmallVector<SDValue> FoldedVector;
+ for (unsigned i = 0; i < NumElts; ++i) {
+ APInt FoldedElt = FoldedMatrix.extractBits(EltWidth, i * EltWidth);
+ FoldedVector.push_back(DAG.getConstant(FoldedElt, DL, MVT::i8));
+ }
+ SDValue NewMatrix = DAG.getBuildVector(VT, DL, FoldedVector);
+
+ return DAG.getNode(X86ISD::GF2P8AFFINEQB, DL, VT, X, NewMatrix,
+ DAG.getTargetConstant(FoldedImm, DL, MVT::i8));
+}
+
+static SDValue combineGF2P8AFFINEQB(SDNode *N, SelectionDAG &DAG) {
+ EVT VT = N->getValueType(0);
+ SDLoc dl(N);
+
+ if (SDValue R = combineNestedGF2P8AFFINEQB(N, dl, DAG, VT))
+ return R;
+
+ return SDValue();
+}
+
// Optimize (fp16_to_fp (fp_to_fp16 X)) to VCVTPS2PH followed by VCVTPH2PS.
// Done as a combine because the lowering for fp16_to_fp and fp_to_fp16 produce
// extra instructions between the conversion due to going to scalar and back.
@@ -62735,6 +62831,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::VPMADD52H: return combineVPMADD52LH(N, DAG, DCI);
case X86ISD::KSHIFTL:
case X86ISD::KSHIFTR: return combineKSHIFT(N, DAG, DCI);
+ case X86ISD::GF2P8AFFINEQB: return combineGF2P8AFFINEQB(N, DAG);
case ISD::FP16_TO_FP: return combineFP16_TO_FP(N, DAG, Subtarget);
case ISD::STRICT_FP_EXTEND:
case ISD::FP_EXTEND: return combineFP_EXTEND(N, DAG, DCI, Subtarget);
diff --git a/llvm/test/CodeGen/X86/gfni-nested-fold.ll b/llvm/test/CodeGen/X86/gfni-nested-fold.ll
index e268ec95a820f..b13ce1d83946f 100644
--- a/llvm/test/CodeGen/X86/gfni-nested-fold.ll
+++ b/llvm/test/CodeGen/X86/gfni-nested-fold.ll
@@ -6,8 +6,7 @@ declare <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8>, <16 x i8>, i8)
define <16 x i8> @test_ashr1_rotl2(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_ashr1_rotl2:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [32,16,8,4,2,1,128,64,32,16,8,4,2,1,128,64]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [64,32,16,8,4,2,128,128,64,32,16,8,4,2,128,128]
; CHECK-NEXT: retq
%ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 0)
%rotl2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr1, <16 x i8> <i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64>, i8 0)
@@ -17,8 +16,7 @@ define <16 x i8> @test_ashr1_rotl2(<16 x i8> %src) nounwind {
define <16 x i8> @test_ashr2_reverse(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_ashr2_reverse:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,128,64,32,16,8,4,128,128,128,64,32,16,8,4]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [4,8,16,32,64,128,128,128,4,8,16,32,64,128,128,128]
; CHECK-NEXT: retq
%ashr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
%rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr2, <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)
@@ -28,8 +26,7 @@ define <16 x i8> @test_ashr2_reverse(<16 x i8> %src) nounwind {
define <16 x i8> @test_ashr2_splat_lsb(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_ashr2_splat_lsb:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,128,64,32,16,8,4,128,128,128,64,32,16,8,4]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4]
; CHECK-NEXT: retq
%ashr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
%lsb = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr2, <16 x i8> splat(i8 1), i8 0)
@@ -39,8 +36,7 @@ define <16 x i8> @test_ashr2_splat_lsb(<16 x i8> %src) nounwind {
define <16 x i8> @test_cumulative_parity_both_directions(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_cumulative_parity_both_directions:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,192,224,240,248,252,254,255,128,192,224,240,248,252,254,255]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,128,191,160,175,168,171,170,255,128,191,160,175,168,171,170]
; CHECK-NEXT: retq
%left = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
%right = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %left, <16 x i8> <i8 128, i8 192, i8 224, i8 240, i8 248, i8 252, i8 254, i8 255, i8 128, i8 192, i8 224, i8 240, i8 248, i8 252, i8 254, i8 255>, i8 0)
@@ -50,10 +46,7 @@ define <16 x i8> @test_cumulative_parity_both_directions(<16 x i8> %src) nounwin
define <16 x i8> @test_reverse_reverse_reverse(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_reverse_reverse_reverse:
; CHECK: # %bb.0:
-; CHECK-NEXT: vpbroadcastq {{.*#+}} xmm1 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
-; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
-; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
-; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
; CHECK-NEXT: retq
%rev1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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)
%rev2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev1, <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)
@@ -64,9 +57,7 @@ define <16 x i8> @test_reverse_reverse_reverse(<16 x i8> %src) nounwind {
define <16 x i8> @test_parity_fill_cumulative_parity(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_parity_fill_cumulative_parity:
; CHECK: # %bb.0:
-; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255]
; CHECK-NEXT: retq
%fill = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> splat(i8 -1), i8 0)
%parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %fill, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
@@ -76,8 +67,7 @@ define <16 x i8> @test_parity_fill_cumulative_parity(<16 x i8> %src) nounwind {
define <16 x i8> @test_ashr1_reverse_non_zero_imm(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_ashr1_reverse_non_zero_imm:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $15, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $240, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,4,8,16,32,64,128,128,2,4,8,16,32,64,128,128]
; CHECK-NEXT: retq
%ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 15)
%rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr1, <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)
@@ -87,8 +77,7 @@ define <16 x i8> @test_ashr1_reverse_non_zero_imm(<16 x i8> %src) nounwind {
define <16 x i8> @test_reverse_ashr1_non_zero_imm(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_reverse_ashr1_non_zero_imm:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $129, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,64,32,16,8,4,2]
+; CHECK-NEXT: vgf2p8affineqb $192, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,1,2,4,8,16,32,64,1,1,2,4,8,16,32,64]
; CHECK-NEXT: retq
%rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <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 129)
%ashr1 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rev, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2>, i8 0)
@@ -98,8 +87,7 @@ define <16 x i8> @test_reverse_ashr1_non_zero_imm(<16 x i8> %src) nounwind {
define <16 x i8> @test_const_gen_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_const_gen_cumulative_parity_non_zero_imm:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $127, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [64,32,32,32,32,32,32,32,64,32,32,32,32,32,32,32]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $213, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [96,32,0,32,0,32,0,32,96,32,0,32,0,32,0,32]
; CHECK-NEXT: retq
%gen = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 64, i8 32, i8 32, i8 32,i8 32, i8 32, i8 32, i8 32, i8 64, i8 32, i8 32, i8 32,i8 32, i8 32, i8 32, i8 32>, i8 127)
%parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %gen, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
@@ -109,8 +97,7 @@ define <16 x i8> @test_const_gen_cumulative_parity_non_zero_imm(<16 x i8> %src)
define <16 x i8> @test_rotr2_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_rotr2_cumulative_parity_non_zero_imm:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $255, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,1,128,64,32,16,8,4,2,1,128,64,32,16,8,4]
-; CHECK-NEXT: vgf2p8affineqb $255, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; CHECK-NEXT: vgf2p8affineqb $170, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,253,252,124,60,28,12,4,255,253,252,124,60,28,12,4]
; CHECK-NEXT: retq
%rotr2 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 1, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 255)
%parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %rotr2, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 255)
@@ -121,8 +108,8 @@ define <16 x i8> @test_rotr2_cumulative_parity_non_zero_imm(<16 x i8> %src) noun
define <16 x i8> @test_multi_use(<16 x i8> %src, ptr %sink) nounwind {
; CHECK-LABEL: test_multi_use:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
-; CHECK-NEXT: vmovdqa %xmm0, (%rdi)
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vmovdqa %xmm1, (%rdi)
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
; CHECK-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
; CHECK-NEXT: retq
@@ -136,8 +123,7 @@ define <16 x i8> @test_multi_use(<16 x i8> %src, ptr %sink) nounwind {
define <16 x i8> @test_ashr12_reverse(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_ashr12_reverse:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [128,128,64,32,16,8,4,2,128,128,128,64,32,16,8,4]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,4,8,16,32,64,128,128,4,8,16,32,64,128,128,128]
; CHECK-NEXT: retq
%ashr12 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4, i8 2, i8 128, i8 128, i8 128, i8 64, i8 32, i8 16, i8 8, i8 4>, i8 0)
%rev = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %ashr12, <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)
@@ -148,8 +134,7 @@ define <16 x i8> @test_ashr12_reverse(<16 x i8> %src) nounwind {
define <16 x i8> @test_cumulative_parity_fill_17(<16 x i8> %src) nounwind {
; CHECK-LABEL: test_cumulative_parity_fill_17:
; CHECK: # %bb.0:
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
-; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [2,2,2,2,2,2,2,2,128,128,128,128,128,128,128,128]
+; CHECK-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,255]
; CHECK-NEXT: retq
%parity = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %src, <16 x i8> <i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1, i8 255, i8 127, i8 63, i8 31, i8 15, i8 7, i8 3, i8 1>, i8 0)
%fill12 = call <16 x i8> @llvm.x86.vgf2p8affineqb.128(<16 x i8> %parity, <16 x i8> <i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128, i8 128>, i8 0)
More information about the llvm-commits
mailing list