[llvm] [X86] Fold nested VGF2P8AFFINEQB instructions (PR #195210)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 15 03:43:22 PDT 2026
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/195210
>From 2db95f79842a70a332995fde6c2922a6cf7f9d0e 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/5] [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 146339c069dbc46f99eb5426d683d3538aa164bc 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/5] Nested GF2P8AFFINEQB fold + update test
- Added the nested GF2P8AFFINEQB fold
- Updated the regression test to reflect this change
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 89 +++++++++++++++++++++++
llvm/test/CodeGen/X86/gfni-nested-fold.ll | 43 ++++-------
2 files changed, 103 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b6aee44b4de2e..075fb157ba351 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -29543,6 +29543,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
@@ -62411,6 +62430,73 @@ static SDValue combineAndOnGF2P8AFFINEQBOperand(SDNode *N, const SDLoc &DL,
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);
@@ -62418,6 +62504,9 @@ static SDValue combineGF2P8AFFINEQB(SDNode *N, SelectionDAG &DAG) {
if (SDValue R = combineAndOnGF2P8AFFINEQBOperand(N, dl, DAG, VT))
return R;
+ if (SDValue R = combineNestedGF2P8AFFINEQB(N, dl, DAG, VT))
+ return R;
+
return SDValue();
}
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)
>From 9789e984e2909a3481ba91c8ba381dbfe27f5bcb Mon Sep 17 00:00:00 2001
From: Walter <walter.kruger at hotmail.com>
Date: Fri, 8 May 2026 15:00:20 +1000
Subject: [PATCH 3/5] Loop style + move regression tests
- Style: Changed loop variables to upper case
- Style: Change loop condition to equality check (rather than range)
- Moved test cases to existing file
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 16 +-
llvm/test/CodeGen/X86/combine-gfni.ll | 373 ++++++++++++++++++++++
llvm/test/CodeGen/X86/gfni-nested-fold.ll | 190 -----------
3 files changed, 381 insertions(+), 198 deletions(-)
delete mode 100644 llvm/test/CodeGen/X86/gfni-nested-fold.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 075fb157ba351..bd3c119ea4225 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -29554,8 +29554,8 @@ static APInt getGFNIByteAffine(const APInt &ByteToAffine, const APInt &Matrix64,
ByteSplat &= Matrix64.byteSwap();
// Cumulative parity
- for (unsigned i = 0; i < 3; ++i)
- ByteSplat ^= ByteSplat.lshr(1 << i);
+ for (unsigned I = 0; I != 3; ++I)
+ ByteSplat ^= ByteSplat.lshr(1 << I);
ByteSplat &= 0x0101010101010101ull;
APInt Affined = APIntOps::ScaleBitMask(ByteSplat, 8);
@@ -62458,9 +62458,9 @@ static SDValue combineNestedGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
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);
+ 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
@@ -62476,7 +62476,7 @@ static SDValue combineNestedGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
APInt LeastBitInByte = APInt::getSplat(VecWidth, APInt(8, 0x01));
APInt RowSplatter = APInt(VecWidth, 0x0101010101010101ull);
- for (unsigned Row = 0; Row < 8; ++Row) {
+ for (unsigned Row = 0; Row != 8; ++Row) {
APInt RowSplat = (SubM & LeastRowMask) * RowSplatter;
SubM = SubM.lshr(EltWidth);
@@ -62487,8 +62487,8 @@ static SDValue combineNestedGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
}
SmallVector<SDValue> FoldedVector;
- for (unsigned i = 0; i < NumElts; ++i) {
- APInt FoldedElt = FoldedMatrix.extractBits(EltWidth, i * EltWidth);
+ 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);
diff --git a/llvm/test/CodeGen/X86/combine-gfni.ll b/llvm/test/CodeGen/X86/combine-gfni.ll
index b105cdf7ea895..85d5a4ce4cf38 100644
--- a/llvm/test/CodeGen/X86/combine-gfni.ll
+++ b/llvm/test/CodeGen/X86/combine-gfni.ll
@@ -93,6 +93,379 @@ define <16 x i8> @gf2p8mulb_freeze(<16 x i8> %a0, <16 x i8> %a1, <16 x i8> %a2)
ret <16 x i8> %r
}
+;; Nested GF2P8AFFINEQB fold
+
+define <16 x i8> @nested_fold_ashr1_rotl2(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_ashr1_rotl2:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [64,32,16,8,4,2,128,128,64,32,16,8,4,2,128,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_ashr1_rotl2:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_ashr1_rotl2:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [64,32,16,8,4,2,128,128,64,32,16,8,4,2,128,128]
+; AVX512-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> @nested_fold_ashr2_reverse(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_ashr2_reverse:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [4,8,16,32,64,128,128,128,4,8,16,32,64,128,128,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_ashr2_reverse:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_ashr2_reverse:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [4,8,16,32,64,128,128,128,4,8,16,32,64,128,128,128]
+; AVX512-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> @nested_fold_ashr2_splat_lsb(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_ashr2_splat_lsb:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_ashr2_splat_lsb:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_ashr2_splat_lsb:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4]
+; AVX512-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> @nested_fold_cumulative_parity_both_directions(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_cumulative_parity_both_directions:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [255,128,191,160,175,168,171,170,255,128,191,160,175,168,171,170]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_cumulative_parity_both_directions:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_cumulative_parity_both_directions:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [255,128,191,160,175,168,171,170,255,128,191,160,175,168,171,170]
+; AVX512-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> @nested_fold_reverse_reverse_reverse(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_reverse_reverse_reverse:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_reverse_reverse_reverse:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_reverse_reverse_reverse:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; AVX512-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> @nested_fold_parity_fill_cumulative_parity(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_parity_fill_cumulative_parity:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_parity_fill_cumulative_parity:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_parity_fill_cumulative_parity:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255]
+; AVX512-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> @nested_fold_ashr1_reverse_non_zero_imm(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_ashr1_reverse_non_zero_imm:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $240, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [2,4,8,16,32,64,128,128,2,4,8,16,32,64,128,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_ashr1_reverse_non_zero_imm:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_ashr1_reverse_non_zero_imm:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $240, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [2,4,8,16,32,64,128,128,2,4,8,16,32,64,128,128]
+; AVX512-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> @nested_fold_reverse_ashr1_non_zero_imm(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_reverse_ashr1_non_zero_imm:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $192, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [1,1,2,4,8,16,32,64,1,1,2,4,8,16,32,64]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_reverse_ashr1_non_zero_imm:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_reverse_ashr1_non_zero_imm:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $192, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [1,1,2,4,8,16,32,64,1,1,2,4,8,16,32,64]
+; AVX512-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> @nested_fold_const_gen_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_const_gen_cumulative_parity_non_zero_imm:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $213, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [96,32,0,32,0,32,0,32,96,32,0,32,0,32,0,32]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_const_gen_cumulative_parity_non_zero_imm:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_const_gen_cumulative_parity_non_zero_imm:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $213, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [96,32,0,32,0,32,0,32,96,32,0,32,0,32,0,32]
+; AVX512-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> @nested_fold_rotr2_cumulative_parity_non_zero_imm(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_rotr2_cumulative_parity_non_zero_imm:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $170, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [255,253,252,124,60,28,12,4,255,253,252,124,60,28,12,4]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_rotr2_cumulative_parity_non_zero_imm:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_rotr2_cumulative_parity_non_zero_imm:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $170, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [255,253,252,124,60,28,12,4,255,253,252,124,60,28,12,4]
+; AVX512-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> @nested_fold_multi_use(<16 x i8> %src, ptr %sink) nounwind {
+; SSE-LABEL: nested_fold_multi_use:
+; SSE: # %bb.0:
+; SSE-NEXT: movdqa %xmm0, %xmm1
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; SSE-NEXT: movdqa %xmm1, (%rdi)
+; SSE-NEXT: pcmpeqd %xmm1, %xmm1
+; SSE-NEXT: gf2p8affineqb $0, %xmm1, %xmm0
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_multi_use:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: vmovdqa %xmm1, (%rdi)
+; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
+; AVX-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_multi_use:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm1 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; AVX512-NEXT: vmovdqa %xmm1, (%rdi)
+; AVX512-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
+; AVX512-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX512-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> @nested_fold_ashr12_reverse(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_ashr12_reverse:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [2,4,8,16,32,64,128,128,4,8,16,32,64,128,128,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_ashr12_reverse:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_ashr12_reverse:
+; AVX512: # %bb.0:
+; AVX512-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]
+; AVX512-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> @nested_fold_cumulative_parity_fill_17(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_cumulative_parity_fill_17:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,255]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_cumulative_parity_fill_17:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_cumulative_parity_fill_17:
+; AVX512: # %bb.0:
+; AVX512-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]
+; AVX512-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> @nested_fold_cumulative_parity_fill_17_non_zero_imm(<16 x i8> %src) nounwind {
+; SSE-LABEL: nested_fold_cumulative_parity_fill_17_non_zero_imm:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $1, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [2,2,2,2,2,2,2,2,128,128,128,128,128,128,128,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_cumulative_parity_fill_17_non_zero_imm:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_cumulative_parity_fill_17_non_zero_imm:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $1, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [255,127,63,31,15,7,3,1,255,127,63,31,15,7,3,1]
+; AVX512-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]
+; AVX512-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> @nested_fold_variable_sub(<16 x i8> %src, <16 x i8> %matrix) nounwind {
+; SSE-LABEL: nested_fold_variable_sub:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, %xmm1, %xmm0
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_variable_sub:
+; AVX: # %bb.0:
+; AVX-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX-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]
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_variable_sub:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; AVX512-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> @nested_fold_variable_super(<16 x i8> %src, <16 x i8> %matrix) nounwind {
+; SSE-LABEL: nested_fold_variable_super:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; SSE-NEXT: gf2p8affineqb $0, %xmm1, %xmm0
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_variable_super:
+; AVX: # %bb.0:
+; AVX-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]
+; AVX-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_variable_super:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to2}, %xmm0, %xmm0 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
+; AVX512-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX512-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> @nested_fold_both_variable(<16 x i8> %src, <16 x i8> %submatrix, <16 x i8> %supmatrix) nounwind {
+; SSE-LABEL: nested_fold_both_variable:
+; SSE: # %bb.0:
+; SSE-NEXT: gf2p8affineqb $0, %xmm1, %xmm0
+; SSE-NEXT: gf2p8affineqb $0, %xmm2, %xmm0
+; SSE-NEXT: retq
+;
+; AVX-LABEL: nested_fold_both_variable:
+; AVX: # %bb.0:
+; AVX-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vgf2p8affineqb $0, %xmm2, %xmm0, %xmm0
+; AVX-NEXT: retq
+;
+; AVX512-LABEL: nested_fold_both_variable:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vgf2p8affineqb $0, %xmm1, %xmm0, %xmm0
+; AVX512-NEXT: vgf2p8affineqb $0, %xmm2, %xmm0, %xmm0
+; AVX512-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
+}
+
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)
declare <16 x i8> @llvm.x86.vgf2p8affineinvqb.128(<16 x i8>, <16 x i8>, i8)
diff --git a/llvm/test/CodeGen/X86/gfni-nested-fold.ll b/llvm/test/CodeGen/X86/gfni-nested-fold.ll
deleted file mode 100644
index b13ce1d83946f..0000000000000
--- a/llvm/test/CodeGen/X86/gfni-nested-fold.ll
+++ /dev/null
@@ -1,190 +0,0 @@
-; 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 # [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)
- 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 # [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)
- 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 # [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)
- 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,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)
- 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: 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)
- %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: 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)
- 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 $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)
- 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 $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)
- 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 $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)
- 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 $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)
- 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, %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
- %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 # [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)
- 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 # [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)
- 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 2fa026a711f34f7b80ada42ed8714e67dd95122c Mon Sep 17 00:00:00 2001
From: Walter <walter.kruger at hotmail.com>
Date: Fri, 8 May 2026 20:16:57 +1000
Subject: [PATCH 4/5] Update funnel shift test
The funnel regression test included a nested GFNI operation (`bit_reverse(lshr(x, 1))`) which was improved as a result of this fold. I failed to include it during my previous commits.
It also caused the following bit reverse to use a embedded memory operand as the bit reverse matrix was folded away.
---
llvm/test/CodeGen/X86/gfni-funnel-shifts.ll | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll b/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll
index 87db9d1410c6d..2026046917ea0 100644
--- a/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll
+++ b/llvm/test/CodeGen/X86/gfni-funnel-shifts.ll
@@ -679,14 +679,12 @@ define <32 x i8> @var_fshl_v32i8(<32 x i8> %a, <32 x i8> %b, <32 x i8> %amt) nou
; GFNIAVX512VL-NEXT: vpand %ymm4, %ymm0, %ymm0
; GFNIAVX512VL-NEXT: vgf2p8mulb %ymm6, %ymm0, %ymm0
; GFNIAVX512VL-NEXT: vpandn %ymm3, %ymm2, %ymm2
-; GFNIAVX512VL-NEXT: vpshufb %ymm2, %ymm7, %ymm3
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %ymm1, %ymm1 # [0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2]
-; GFNIAVX512VL-NEXT: vpbroadcastq {{.*#+}} ymm4 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, %ymm4, %ymm1, %ymm1
-; GFNIAVX512VL-NEXT: vpand %ymm3, %ymm1, %ymm1
-; GFNIAVX512VL-NEXT: vpshufb %ymm2, %ymm5, %ymm2
-; GFNIAVX512VL-NEXT: vgf2p8mulb %ymm2, %ymm1, %ymm1
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, %ymm4, %ymm1, %ymm1
+; GFNIAVX512VL-NEXT: vpshufb %ymm2, %ymm5, %ymm3
+; GFNIAVX512VL-NEXT: vpshufb %ymm2, %ymm7, %ymm2
+; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %ymm1, %ymm1 # [2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0]
+; GFNIAVX512VL-NEXT: vpand %ymm2, %ymm1, %ymm1
+; GFNIAVX512VL-NEXT: vgf2p8mulb %ymm3, %ymm1, %ymm1
+; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %ymm1, %ymm1 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
; GFNIAVX512VL-NEXT: vpor %ymm1, %ymm0, %ymm0
; GFNIAVX512VL-NEXT: retq
;
@@ -1608,12 +1606,10 @@ define <64 x i8> @var_fshl_v64i8(<64 x i8> %a, <64 x i8> %b, <64 x i8> %amt) nou
; GFNIAVX512VL-NEXT: vpshufb %ymm4, %ymm7, %ymm4
; GFNIAVX512VL-NEXT: vpshufb %ymm2, %ymm7, %ymm2
; GFNIAVX512VL-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm2
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm1, %zmm1 # [0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2,0,128,64,32,16,8,4,2]
-; GFNIAVX512VL-NEXT: vpbroadcastq {{.*#+}} zmm4 = [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, %zmm4, %zmm1, %zmm1
+; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm1, %zmm1 # [2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0]
; GFNIAVX512VL-NEXT: vpandq %zmm2, %zmm1, %zmm1
; GFNIAVX512VL-NEXT: vgf2p8mulb %zmm3, %zmm1, %zmm1
-; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, %zmm4, %zmm1, %zmm1
+; GFNIAVX512VL-NEXT: vgf2p8affineqb $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %zmm1, %zmm1 # [1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128,1,2,4,8,16,32,64,128]
; GFNIAVX512VL-NEXT: vporq %zmm1, %zmm0, %zmm0
; GFNIAVX512VL-NEXT: retq
;
>From 366c44289f03f4562dcfd1b7698c3b2627baa868 Mon Sep 17 00:00:00 2001
From: Walter <walter.kruger at hotmail.com>
Date: Sat, 30 May 2026 14:12:57 +1000
Subject: [PATCH 5/5] Make immediate logic more explicit
Refactored immediate permute using if statement. This is logically identical but this pattern makes it clearer as it show the "non-splat, zero immediate" case just passing the super's.
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index bd3c119ea4225..a183f9644a5e3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -62463,12 +62463,16 @@ static SDValue combineNestedGF2P8AFFINEQB(SDNode *N, const SDLoc &DL,
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);
+ APInt FoldedImm;
+ if (SupM.isSplat(64)) {
+ FoldedImm = getGFNIByteAffine(ImmSub, SupM.trunc(64), ImmSup);
+ } else {
+ // Immediate is shared and needs to be permuted in the same manner
+ if (ImmSub != 0)
+ return SDValue();
+ FoldedImm = ImmSup;
+ }
// Matrix permute
APInt FoldedMatrix = APInt(VecWidth, 0);
More information about the llvm-commits
mailing list