[clang] [compiler-rt] [llvm] [X86] AVX10_V2_AUX Implementation (PR #206888)
Evgenii Kudriashov via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 16 05:02:21 PDT 2026
================
@@ -0,0 +1,611 @@
+//===-- X86InstrAVX10_V2_AUX.td - AVX10 V2 AUX Instructions --*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the X86 AVX10 V2 AUX instruction set, defining the
+// instructions and their encoding.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// AVX10 V2 AUX Multiclass Definitions
+//===----------------------------------------------------------------------===//
+
+// Convert from FP32 to FP8: truncating conversion, quarter-size output
+// Output is always xmm for all VL variants.
+multiclass avx10_v2aux_cvt_trunc_ps2i8<bits<8> opc, string OpcodeStr,
+ SDPatternOperator OpNode,
+ SDPatternOperator MaskOpNode> {
+ let ExeDomain = SSEPackedSingle in {
+ let Uses = []<Register>, mayRaiseFPException = 0 in {
+ defm Z : avx512_vcvt_fp<opc, OpcodeStr, v16i8x_info, v16f32_info,
+ OpNode, OpNode, WriteCvtPH2PSZ,
+ v16f32_info.BroadcastStr, "{z}">, EVEX_V512;
+ // Z256/Z128: use null_frag because element count mismatch between
+ // dest (v16i8) and source (v8f32/v4f32) prevents avx512_vcvt_fp from
+ // generating correct masked patterns. Explicit Pat patterns below.
+ defm Z256 : avx512_vcvt_fp<opc, OpcodeStr, v16i8x_info, v8f32x_info,
+ null_frag, null_frag,
+ WriteCvtPH2PSZ, v8f32x_info.BroadcastStr,
+ "{y}", v8f32x_info.MemOp,
+ v8f32x_info.KRCWM>, EVEX_V256;
+ defm Z128 : avx512_vcvt_fp<opc, OpcodeStr, v16i8x_info, v4f32x_info,
+ null_frag, null_frag,
+ WriteCvtPH2PSZ, v4f32x_info.BroadcastStr,
+ "{x}", f128mem,
+ v4f32x_info.KRCWM>, EVEX_V128;
+ }
+ }
+
+ // InstAliases for x/y/z suffixes (dest is always xmm). Priority 0 so they
+ // are accepted but not printed by default. Same precedent as vcvtpd2ph.
+ def : InstAlias<OpcodeStr#"x\t{$src, $dst|$dst, $src}",
+ (!cast<Instruction>(NAME # "Z128rr") VR128X:$dst,
+ VR128X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"x\t{$src, $dst {${mask}}|$dst {${mask}}, $src}",
+ (!cast<Instruction>(NAME # "Z128rrk") VR128X:$dst,
+ VK4WM:$mask, VR128X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"x\t{$src, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, $src}",
+ (!cast<Instruction>(NAME # "Z128rrkz") VR128X:$dst,
+ VK4WM:$mask, VR128X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"x\t{${src}{1to4}, $dst|$dst, ${src}{1to4}}",
+ (!cast<Instruction>(NAME # "Z128rmb") VR128X:$dst,
+ f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"x\t{${src}{1to4}, $dst {${mask}}|"
+ "$dst {${mask}}, ${src}{1to4}}",
+ (!cast<Instruction>(NAME # "Z128rmbk") VR128X:$dst,
+ VK4WM:$mask, f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"x\t{${src}{1to4}, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, ${src}{1to4}}",
+ (!cast<Instruction>(NAME # "Z128rmbkz") VR128X:$dst,
+ VK4WM:$mask, f32mem:$src), 0, "att">;
+
+ def : InstAlias<OpcodeStr#"y\t{$src, $dst|$dst, $src}",
+ (!cast<Instruction>(NAME # "Z256rr") VR128X:$dst,
+ VR256X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"y\t{$src, $dst {${mask}}|$dst {${mask}}, $src}",
+ (!cast<Instruction>(NAME # "Z256rrk") VR128X:$dst,
+ VK8WM:$mask, VR256X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"y\t{$src, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, $src}",
+ (!cast<Instruction>(NAME # "Z256rrkz") VR128X:$dst,
+ VK8WM:$mask, VR256X:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"y\t{${src}{1to8}, $dst|$dst, ${src}{1to8}}",
+ (!cast<Instruction>(NAME # "Z256rmb") VR128X:$dst,
+ f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"y\t{${src}{1to8}, $dst {${mask}}|"
+ "$dst {${mask}}, ${src}{1to8}}",
+ (!cast<Instruction>(NAME # "Z256rmbk") VR128X:$dst,
+ VK8WM:$mask, f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"y\t{${src}{1to8}, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, ${src}{1to8}}",
+ (!cast<Instruction>(NAME # "Z256rmbkz") VR128X:$dst,
+ VK8WM:$mask, f32mem:$src), 0, "att">;
+
+ def : InstAlias<OpcodeStr#"z\t{$src, $dst|$dst, $src}",
+ (!cast<Instruction>(NAME # "Zrr") VR128X:$dst,
+ VR512:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"z\t{$src, $dst {${mask}}|$dst {${mask}}, $src}",
+ (!cast<Instruction>(NAME # "Zrrk") VR128X:$dst,
+ VK16WM:$mask, VR512:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"z\t{$src, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, $src}",
+ (!cast<Instruction>(NAME # "Zrrkz") VR128X:$dst,
+ VK16WM:$mask, VR512:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"z\t{${src}{1to16}, $dst|$dst, ${src}{1to16}}",
+ (!cast<Instruction>(NAME # "Zrmb") VR128X:$dst,
+ f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"z\t{${src}{1to16}, $dst {${mask}}|"
+ "$dst {${mask}}, ${src}{1to16}}",
+ (!cast<Instruction>(NAME # "Zrmbk") VR128X:$dst,
+ VK16WM:$mask, f32mem:$src), 0, "att">;
+ def : InstAlias<OpcodeStr#"z\t{${src}{1to16}, $dst {${mask}} {z}|"
+ "$dst {${mask}} {z}, ${src}{1to16}}",
+ (!cast<Instruction>(NAME # "Zrmbkz") VR128X:$dst,
+ VK16WM:$mask, f32mem:$src), 0, "att">;
+
+ // Explicit patterns for Z256 (8 source elements, VK8WM mask)
+ // Unmasked
+ def : Pat<(v16i8 (OpNode (v8f32 VR256X:$src))),
+ (!cast<Instruction>(NAME # "Z256rr") VR256X:$src)>;
+ // Masked (merge)
+ def : Pat<(MaskOpNode (v8f32 VR256X:$src), (v16i8 VR128X:$src0),
+ VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rrk") VR128X:$src0, VK8WM:$mask,
+ VR256X:$src)>;
+ // Masked (zero)
+ def : Pat<(MaskOpNode (v8f32 VR256X:$src), v16i8x_info.ImmAllZerosV,
+ VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rrkz") VK8WM:$mask,
+ VR256X:$src)>;
+ // Memory
+ def : Pat<(v16i8 (OpNode (loadv8f32 addr:$src))),
+ (!cast<Instruction>(NAME # "Z256rm") addr:$src)>;
+ def : Pat<(MaskOpNode (loadv8f32 addr:$src), (v16i8 VR128X:$src0),
+ VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rmk") VR128X:$src0, VK8WM:$mask,
+ addr:$src)>;
+ def : Pat<(MaskOpNode (loadv8f32 addr:$src), v16i8x_info.ImmAllZerosV,
+ VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rmkz") VK8WM:$mask, addr:$src)>;
+ // Broadcast
+ def : Pat<(v16i8 (OpNode (v8f32 (X86VBroadcastld32 addr:$src)))),
+ (!cast<Instruction>(NAME # "Z256rmb") addr:$src)>;
+ def : Pat<(MaskOpNode (v8f32 (X86VBroadcastld32 addr:$src)),
+ (v16i8 VR128X:$src0), VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rmbk") VR128X:$src0, VK8WM:$mask,
+ addr:$src)>;
+ def : Pat<(MaskOpNode (v8f32 (X86VBroadcastld32 addr:$src)),
+ v16i8x_info.ImmAllZerosV, VK8WM:$mask),
+ (!cast<Instruction>(NAME # "Z256rmbkz") VK8WM:$mask, addr:$src)>;
+
+ // Explicit patterns for Z128 (4 source elements, VK4WM mask)
+ // Unmasked
+ def : Pat<(v16i8 (OpNode (v4f32 VR128X:$src))),
+ (!cast<Instruction>(NAME # "Z128rr") VR128X:$src)>;
+ // Masked (merge)
+ def : Pat<(MaskOpNode (v4f32 VR128X:$src), (v16i8 VR128X:$src0),
+ VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rrk") VR128X:$src0, VK4WM:$mask,
+ VR128X:$src)>;
+ // Masked (zero)
+ def : Pat<(MaskOpNode (v4f32 VR128X:$src), v16i8x_info.ImmAllZerosV,
+ VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rrkz") VK4WM:$mask,
+ VR128X:$src)>;
+ // Memory
+ def : Pat<(v16i8 (OpNode (loadv4f32 addr:$src))),
+ (!cast<Instruction>(NAME # "Z128rm") addr:$src)>;
+ def : Pat<(MaskOpNode (loadv4f32 addr:$src), (v16i8 VR128X:$src0),
+ VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rmk") VR128X:$src0, VK4WM:$mask,
+ addr:$src)>;
+ def : Pat<(MaskOpNode (loadv4f32 addr:$src), v16i8x_info.ImmAllZerosV,
+ VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rmkz") VK4WM:$mask, addr:$src)>;
+ // Broadcast
+ def : Pat<(v16i8 (OpNode (v4f32 (X86VBroadcastld32 addr:$src)))),
+ (!cast<Instruction>(NAME # "Z128rmb") addr:$src)>;
+ def : Pat<(MaskOpNode (v4f32 (X86VBroadcastld32 addr:$src)),
+ (v16i8 VR128X:$src0), VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rmbk") VR128X:$src0, VK4WM:$mask,
+ addr:$src)>;
+ def : Pat<(MaskOpNode (v4f32 (X86VBroadcastld32 addr:$src)),
+ v16i8x_info.ImmAllZerosV, VK4WM:$mask),
+ (!cast<Instruction>(NAME # "Z128rmbkz") VK4WM:$mask, addr:$src)>;
+}
+
+// Convert from FP32 to FP8 with bias: 3-operand, quarter-size output
+// bias dword per FP32 lane + f32 source -> i8 dest
+multiclass avx10_v2aux_cvt_3op_ps<bits<8> opc, string OpcodeStr,
+ SDPatternOperator OpNode,
+ SDPatternOperator MaskOpNode> {
+ // Z (512-bit): bias=v16i32(zmm), src=v16f32(zmm), dst=v16i8(xmm)
+ // Element counts match (16), so vselect_mask works directly.
+ defm Z : avx10_convert_3op_packed<opc, OpcodeStr, v16i8x_info,
+ v16i32_info, v16f32_info, OpNode, OpNode, WriteCvtPH2PSZ>,
+ EVEX_V512, EVEX_CD8<32, CD8VF>;
+ // Z256/Z128: use null_frag because element count mismatch between
+ // dest (v16i8) and source (v8f32/v4f32) prevents vselect_mask from
+ // generating correct masked patterns. Explicit Pat patterns below.
+ defm Z256 : avx10_convert_3op_packed<opc, OpcodeStr, v16i8x_info,
+ v8i32x_info, v8f32x_info,
+ null_frag, null_frag, WriteCvtPH2PSZ>,
+ EVEX_V256, EVEX_CD8<32, CD8VF>;
+ defm Z128 : avx10_convert_3op_packed<opc, OpcodeStr, v16i8x_info,
+ v4i32x_info, v4f32x_info,
+ null_frag, null_frag, WriteCvtPH2PSZ>,
+ EVEX_V128, EVEX_CD8<32, CD8VF>;
----------------
e-kud wrote:
Basically tests for disp32 are missing as no tests with displacement were introduced.
https://github.com/llvm/llvm-project/pull/206888
More information about the cfe-commits
mailing list