[PATCH 2/2] x86: fold F16C templates with their AVX512VL counterparts
Jan Beulich
jbeulich@suse.com
Fri Jul 17 13:50:22 GMT 2026
It's not quite clear why this wasn't done so far. These, conceptually,
aren't any different from the FMA ones.
Doing so actually made me notice a flaw in FMA template handling, which is
being fixed alongside making the necessary changes to accommodate F16C:
Both features aren't prereqs of AVX512F. When they're disabled, enabling
AVX512VL would still not allow the 128- and 256-bit forms to assemble.
---
This actually points out another issue with FMA and F16C: Code created
prior to the introduction of AVX512 might have used ".arch .no{fma,f16c}"
to have uses of the respective insns properly rejected. That protection
suddenly ceased to work properly when AVX512 support was added to the
assembler: Those insns would now assemble to their AVX512VL EVEX forms.
The least bad option to deal with this looks to be to reject the AVX512VL
forms also when FMA/F16C are explicitly disabled while AVX512VL isn't
explicitly enabled. Are there any better suggestions?
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2314,14 +2314,18 @@ cpu_flags_match (const insn_template *t)
{
/* Dual AVX/AVX512 templates need to retain AVX512* only if we already
know that EVEX encoding will be needed. */
- if ((any.bitfield.cpuavx || any.bitfield.cpuavx2 || any.bitfield.cpufma)
+ if ((any.bitfield.cpuavx || any.bitfield.cpuavx2
+ || any.bitfield.cpufma || any.bitfield.cpuf16c)
&& (any.bitfield.cpuavx512f || any.bitfield.cpuavx512vl))
{
- if (need_evex_encoding (t))
+ if (need_evex_encoding (t)
+ || (any.bitfield.cpufma && !cpu_arch_flags.bitfield.cpufma)
+ || (any.bitfield.cpuf16c && !cpu_arch_flags.bitfield.cpuf16c))
{
any.bitfield.cpuavx = 0;
any.bitfield.cpuavx2 = 0;
any.bitfield.cpufma = 0;
+ any.bitfield.cpuf16c = 0;
}
/* need_evex_encoding(t) isn't reliable before operands were
parsed. */
@@ -4232,10 +4236,12 @@ install_template (const insn_template *t
if (t->opcode_modifier.vex && t->opcode_modifier.evex)
{
if ((maybe_cpu (t, CpuAVX) || maybe_cpu (t, CpuAVX2)
- || maybe_cpu (t, CpuFMA))
+ || maybe_cpu (t, CpuFMA) || maybe_cpu (t, CpuF16C))
&& (maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512VL)))
{
- if (need_evex_encoding (t))
+ if (need_evex_encoding (t)
+ || (maybe_cpu (t, CpuFMA) && !cpu_arch_flags.bitfield.cpufma)
+ || (maybe_cpu (t, CpuF16C) && !cpu_arch_flags.bitfield.cpuf16c))
{
i.tm.opcode_modifier.vex = 0;
i.tm.cpu.bitfield.cpuavx512f = i.tm.cpu_any.bitfield.cpuavx512f;
@@ -8799,7 +8805,10 @@ check_VecOperands (const insn_template *
if (!cpu_flags_all_zero (&cpu)
&& !cpu.bitfield.cpuavx512vl
&& !cpu_arch_flags.bitfield.cpuavx512vl
- && (!t->opcode_modifier.vex || need_evex_encoding (t)))
+ && (!t->opcode_modifier.vex || need_evex_encoding (t)
+ /* Note: No need to check F16C here. Those insns have distinct
+ templates for distinct VEX.L / EVEX.L'L. */
+ || (maybe_cpu (t, CpuFMA) && !cpu_arch_flags.bitfield.cpufma)))
{
for (op = 0; op < t->operands; ++op)
{
--- a/gas/testsuite/gas/i386/avx512vl-plain.l
+++ b/gas/testsuite/gas/i386/avx512vl-plain.l
@@ -1,8 +1,8 @@
.*: Assembler messages:
.*:5: Error: .*
-.*:6: Error: .*
-.*:7: Error: .*
-.*:20: Error: .*
+.*:8: Error: .*
+.*:9: Error: .*
+.*:22: Error: .*
GAS LISTING .*
@@ -11,23 +11,27 @@ GAS LISTING .*
[ ]*3[ ]+\.arch \.avx512vl
[ ]*4[ ]+_start:
[ ]*5[ ]+\{evex\} vaesenc[ ]+%ymm1, %ymm2, %ymm3
-[ ]*6[ ]+vgf2p8mulb[ ]+%ymm1, %ymm2, %ymm3\{%k4\}
-[ ]*7[ ]+\{evex\} vpclmulqdq[ ]+\$0, %ymm1, %ymm2, %ymm3
-[ ]*8[ ]*
-[ ]*9[ ]+\.arch \.vaes
-[ ]*10[ ]+\?\?\?\? 62F26D28[ ]+\{evex\} vaesenc[ ]+%ymm1, %ymm2, %ymm3
-[ ]*10[ ]+DCD9
-[ ]*11[ ]*
-[ ]*12[ ]+\.arch \.gfni
-[ ]*13[ ]+\?\?\?\? 62F26D2C[ ]+vgf2p8mulb[ ]+%ymm1, %ymm2, %ymm3\{%k4\}
-[ ]*13[ ]+CFD9
-[ ]*14[ ]*
-[ ]*15[ ]+\.arch \.vpclmulqdq
-[ ]*16[ ]+\?\?\?\? 62F36D28[ ]+\{evex\} vpclmulqdq[ ]+\$0, %ymm1, %ymm2, %ymm3
-[ ]*16[ ]+44D900
-[ ]*17[ ]*
-[ ]*18[ ]+\.arch generic32
-[ ]*19[ ]+\.arch \.avx512f
-[ ]*20[ ]+\{evex\}[ ]+vpermd[ ]+%ymm1, %ymm2, %ymm3
-[ ]*21[ ]+\?\?\?\? C4E26D36[ ]+vpermd[ ]+%ymm1, %ymm2, %ymm3
+[ ]*6[ ]+\?\?\?\? 62F27D08[ ]+vcvtph2ps[ ]+%xmm1, %xmm2
+[ ]*6[ ]+13D1
+[ ]*7[ ]+\?\?\?\? 62F26D08[ ]+vfmadd132ps[ ]+%xmm1, %xmm2, %xmm3
+[ ]*7[ ]+98D9
+[ ]*8[ ]+vgf2p8mulb[ ]+%ymm1, %ymm2, %ymm3\{%k4\}
+[ ]*9[ ]+\{evex\} vpclmulqdq[ ]+\$0, %ymm1, %ymm2, %ymm3
+[ ]*10[ ]*
+[ ]*11[ ]+\.arch \.vaes
+[ ]*12[ ]+\?\?\?\? 62F26D28[ ]+\{evex\} vaesenc[ ]+%ymm1, %ymm2, %ymm3
+[ ]*12[ ]+DCD9
+[ ]*13[ ]*
+[ ]*14[ ]+\.arch \.gfni
+[ ]*15[ ]+\?\?\?\? 62F26D2C[ ]+vgf2p8mulb[ ]+%ymm1, %ymm2, %ymm3\{%k4\}
+[ ]*15[ ]+CFD9
+[ ]*16[ ]*
+[ ]*17[ ]+\.arch \.vpclmulqdq
+[ ]*18[ ]+\?\?\?\? 62F36D28[ ]+\{evex\} vpclmulqdq[ ]+\$0, %ymm1, %ymm2, %ymm3
+[ ]*18[ ]+44D900
+[ ]*19[ ]*
+[ ]*20[ ]+\.arch generic32
+[ ]*21[ ]+\.arch \.avx512f
+[ ]*22[ ]+\{evex\}[ ]+vpermd[ ]+%ymm1, %ymm2, %ymm3
+[ ]*23[ ]+\?\?\?\? C4E26D36[ ]+vpermd[ ]+%ymm1, %ymm2, %ymm3
#pass
--- a/gas/testsuite/gas/i386/avx512vl-plain.s
+++ b/gas/testsuite/gas/i386/avx512vl-plain.s
@@ -3,6 +3,8 @@
.arch .avx512vl
_start:
{evex} vaesenc %ymm1, %ymm2, %ymm3
+ vcvtph2ps %xmm1, %xmm2
+ vfmadd132ps %xmm1, %xmm2, %xmm3
vgf2p8mulb %ymm1, %ymm2, %ymm3{%k4}
{evex} vpclmulqdq $0, %ymm1, %ymm2, %ymm3
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -1922,17 +1922,20 @@ vgf2p8affineinvqb, 0x66cf, AVX&GFNI, Mod
vgf2p8affineqb, 0x66ce, AVX&GFNI, Modrm|Vex|Space0F3A|Src1VVVV|VexW1|CheckOperandSize|NoSuf, { Imm8, Unspecified|BaseIndex|RegXMM|RegYMM, RegXMM|RegYMM, RegXMM|RegYMM }
vgf2p8mulb, 0x66cf, GFNI&(AVX|AVX512F), Modrm|Vex|EVexDYN|Masking|Space0F38|Src1VVVV|VexW0|Disp8ShiftVL|CheckOperandSize|NoSuf, { RegXMM|RegYMM|RegZMM|Unspecified|BaseIndex, RegXMM|RegYMM|RegZMM, RegXMM|RegYMM|RegZMM }
-// FSGSBASE, RDRND and F16C
+// FSGSBASE and RDRND
rdfsbase, 0xf30fae/0, FSGSBase, Modrm|IgnoreSize|NoSuf, { Reg32|Reg64 }
rdgsbase, 0xf30fae/1, FSGSBase, Modrm|IgnoreSize|NoSuf, { Reg32|Reg64 }
rdrand, 0xfc7/6, RdRnd, Modrm|NoSuf, { Reg16|Reg32|Reg64 }
wrfsbase, 0xf30fae/2, FSGSBase, Modrm|IgnoreSize|NoSuf, { Reg32|Reg64 }
wrgsbase, 0xf30fae/3, FSGSBase, Modrm|IgnoreSize|NoSuf, { Reg32|Reg64 }
-vcvtph2ps, 0x6613, F16C, Modrm|Vex|Space0F38|VexW0|NoSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
-vcvtph2ps, 0x6613, F16C, Modrm|Vex=2|Space0F38|VexW=1|NoSuf, { Unspecified|BaseIndex|RegXMM, RegYMM }
-vcvtps2ph, 0x661d, F16C, Modrm|Vex|Space0F3A|VexW0|NoSuf, { Imm8, RegXMM, Qword|Unspecified|BaseIndex|RegXMM }
-vcvtps2ph, 0x661d, F16C, Modrm|Vex=2|Space0F3A|VexW=1|NoSuf, { Imm8, RegYMM, Unspecified|BaseIndex|RegXMM }
+
+// F16C instructions
+
+vcvtph2ps, 0x6613, F16C|AVX512VL, Modrm|Vex128|EVex128|Masking|Space0F38|VexW0|Disp8MemShift=3|NoSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
+vcvtph2ps, 0x6613, F16C|AVX512VL, Modrm|Vex256|EVex256|Masking|Space0F38|VexW0|Disp8MemShift=4|NoSuf, { Unspecified|BaseIndex|RegXMM, RegYMM }
+vcvtps2ph, 0x661d, F16C|AVX512VL, Modrm|Vex128|EVex128|Masking|Space0F3A|VexW0|Disp8MemShift=3|NoSuf, { Imm8, RegXMM, Qword|Unspecified|BaseIndex|RegXMM }
+vcvtps2ph, 0x661d, F16C|AVX512VL, Modrm|Vex256|EVex256|Masking|Space0F3A|VexW0|Disp8MemShift=4|NoSuf, { Imm8, RegYMM, Unspecified|BaseIndex|RegXMM }
// FMA instructions
@@ -2655,15 +2658,9 @@ vcvtdq2pd, 0xF3E6, AVX512VL, Modrm|EVex2
vcvtudq2pd, 0xF37A, AVX512VL, Modrm|EVex128|Masking|Space0F|VexW0|Broadcast|Disp8MemShift=3|NoSuf, { RegXMM|Dword|Qword|Unspecified|BaseIndex, RegXMM }
vcvtudq2pd, 0xF37A, AVX512VL, Modrm|EVex256|Masking|Space0F|VexW0|Broadcast|Disp8MemShift=4|NoSuf, { RegXMM|Dword|Unspecified|BaseIndex, RegYMM }
-vcvtph2ps, 0x6613, AVX512VL, Modrm|EVex=2|Masking|Space0F38|VexW0|Disp8MemShift=3|NoSuf, { RegXMM|Qword|Unspecified|BaseIndex, RegXMM }
-vcvtph2ps, 0x6613, AVX512VL, Modrm|EVex=3|Masking|Space0F38|VexW=1|Disp8MemShift=4|NoSuf, { RegXMM|Unspecified|BaseIndex, RegYMM }
-
vcvtps2pd, 0x5A, AVX512VL, Modrm|EVex128|Masking|Space0F|VexW0|Broadcast|Disp8MemShift=3|NoSuf, { RegXMM|Dword|Qword|Unspecified|BaseIndex, RegXMM }
vcvtps2pd, 0x5A, AVX512VL, Modrm|EVex256|Masking|Space0F|VexW0|Broadcast|Disp8MemShift=4|NoSuf, { RegXMM|Dword|Unspecified|BaseIndex, RegYMM }
-vcvtps2ph, 0x661D, AVX512VL, Modrm|EVex128|Masking|Space0F3A|VexW0|Disp8MemShift=3|NoSuf, { Imm8, RegXMM, RegXMM|Qword|Unspecified|BaseIndex }
-vcvtps2ph, 0x661D, AVX512VL, Modrm|EVex256|Masking|Space0F3A|VexW0|Disp8MemShift=4|NoSuf, { Imm8, RegYMM, RegXMM|Unspecified|BaseIndex }
-
vmovddup, 0xF212, AVX512VL, Modrm|EVex=2|Masking|Space0F|VexW1|Disp8MemShift=3|NoSuf, { RegXMM|Qword|Unspecified|BaseIndex, RegXMM }
vp<movn>db, 0xf3<movn:opc>1, AVX512VL, Modrm|EVex128|Masking|Space0F38|VexW0|Disp8MemShift=2|NoSuf, { RegXMM, RegXMM|Dword|Unspecified|BaseIndex }
More information about the Binutils
mailing list