Add avx10.2nvl family of targets (Intel Nova Lake)

Add the avx10.2nvl-x{4,8,16,32,64} x86 target family for Intel Nova Lake
(NVL). NVL implements AVX10.2 but, unlike Diamond Rapids (DMR), has no AMX.
It is therefore modeled as "DMR without AMX": its target hierarchy inherits
from ICL (avx512icl) rather than DMR/GNR, and none of the AMX capabilities
(AmxTile/AmxInt8/AmxBf16/AmxFp16) are advertised. The half-precision
rcp/rsqrt builtins are reused from the shared target-avx512fp16-x*-common.ll
files. The targets require LLVM >= 22 and are gated accordingly throughout.
This commit is contained in:
Arina Neshlyaeva
2026-06-16 11:19:20 -07:00
committed by aneshlya
parent 1112f68241
commit 4bfe359a35
43 changed files with 908 additions and 50 deletions
+2 -1
View File
@@ -46,7 +46,8 @@ jobs:
"avx512icl-x4", "avx512icl-x8", "avx512icl-x16", "avx512icl-x64", "avx512icl-x32",
"avx512spr-x4", "avx512spr-x8", "avx512spr-x16", "avx512spr-x64", "avx512spr-x32",
"avx512gnr-x4", "avx512gnr-x8", "avx512gnr-x16", "avx512gnr-x64", "avx512gnr-x32",
"avx10.2dmr-x4", "avx10.2dmr-x8", "avx10.2dmr-x16", "avx10.2dmr-x64", "avx10.2dmr-x32"]
"avx10.2dmr-x4", "avx10.2dmr-x8", "avx10.2dmr-x16", "avx10.2dmr-x64", "avx10.2dmr-x32",
"avx10.2nvl-x4", "avx10.2nvl-x8", "avx10.2nvl-x16", "avx10.2nvl-x64", "avx10.2nvl-x32"]
llvm_sha: ${{ steps.get-llvm-sha.outputs.llvm_sha }}
steps:
- name: Get LLVM SHA
+2 -1
View File
@@ -38,7 +38,8 @@ jobs:
"avx512icl-x4", "avx512icl-x8", "avx512icl-x16", "avx512icl-x64", "avx512icl-x32",
"avx512spr-x4", "avx512spr-x8", "avx512spr-x16", "avx512spr-x64", "avx512spr-x32",
"avx512gnr-x4", "avx512gnr-x8", "avx512gnr-x16", "avx512gnr-x64", "avx512gnr-x32",
"avx10.2dmr-x4", "avx10.2dmr-x8", "avx10.2dmr-x16", "avx10.2dmr-x64", "avx10.2dmr-x32"]
"avx10.2dmr-x4", "avx10.2dmr-x8", "avx10.2dmr-x16", "avx10.2dmr-x64", "avx10.2dmr-x32",
"avx10.2nvl-x4", "avx10.2nvl-x8", "avx10.2nvl-x16", "avx10.2nvl-x64", "avx10.2nvl-x32"]
steps:
- run: echo "Defining targets"
+4
View File
@@ -401,6 +401,10 @@ if (${LLVM_VERSION_NUMBER} VERSION_GREATER_EQUAL "20.1.2")
list(APPEND X86_TARGETS avx10_2dmr-x4 avx10_2dmr-x8 avx10_2dmr-x16 avx10_2dmr-x32 avx10_2dmr-x64)
endif()
if (${LLVM_VERSION_NUMBER} VERSION_GREATER_EQUAL "22.0.0")
list(APPEND X86_TARGETS avx10_2nvl-x4 avx10_2nvl-x8 avx10_2nvl-x16 avx10_2nvl-x32 avx10_2nvl-x64)
endif()
list(APPEND ARM_TARGETS neon-i8x16 neon-i16x8 neon-i32x4 neon-i32x8 neon-i8x32 neon-i16x16)
list(APPEND PPC64_TARGETS vsx-i8x16 vsx-i8x32 vsx-i16x8 vsx-i16x16 vsx-i32x4 vsx-i32x8)
list(APPEND RISCV_TARGETS rvv-x4)
+8
View File
@@ -0,0 +1,8 @@
;; Copyright (c) 2026, Intel Corporation
;;
;; SPDX-License-Identifier: BSD-3-Clause
define(`WIDTH',`16')
define(`ISA',`NVL_AVX10_2')
include(`target-avx10_2-x16-common.ll')
include(`target-avx512fp16-x16-common.ll')
+8
View File
@@ -0,0 +1,8 @@
;; Copyright (c) 2026, Intel Corporation
;;
;; SPDX-License-Identifier: BSD-3-Clause
define(`WIDTH',`32')
define(`ISA',`NVL_AVX10_2')
include(`target-avx10_2-x32-common.ll')
include(`target-avx512fp16-x32-common.ll')
+8
View File
@@ -0,0 +1,8 @@
;; Copyright (c) 2026, Intel Corporation
;;
;; SPDX-License-Identifier: BSD-3-Clause
define(`WIDTH',`4')
define(`ISA',`NVL_AVX10_2')
include(`target-avx10_2-x4-common.ll')
include(`target-avx512fp16-x4-common.ll')
+8
View File
@@ -0,0 +1,8 @@
;; Copyright (c) 2026, Intel Corporation
;;
;; SPDX-License-Identifier: BSD-3-Clause
define(`WIDTH',`64')
define(`ISA',`NVL_AVX10_2')
include(`target-avx10_2-x64-common.ll')
include(`target-avx512fp16-x64-common.ll')
+8
View File
@@ -0,0 +1,8 @@
;; Copyright (c) 2026, Intel Corporation
;;
;; SPDX-License-Identifier: BSD-3-Clause
define(`WIDTH',`8')
define(`ISA',`NVL_AVX10_2')
include(`target-avx10_2-x8-common.ll')
include(`target-avx512fp16-x8-common.ll')
+7
View File
@@ -41,6 +41,13 @@ function(define_stdlib_families)
list(APPEND AVX10_X32 "avx10_2dmr-x32")
list(APPEND AVX10_X64 "avx10_2dmr-x64")
endif()
if (${LLVM_VERSION_NUMBER} VERSION_GREATER_EQUAL "22.0.0")
list(APPEND AVX10_X4 "avx10_2nvl-x4")
list(APPEND AVX10_X8 "avx10_2nvl-x8")
list(APPEND AVX10_X16 "avx10_2nvl-x16")
list(APPEND AVX10_X32 "avx10_2nvl-x32")
list(APPEND AVX10_X64 "avx10_2nvl-x64")
endif()
# Convert lists to comma-separated strings with leading comma
foreach(width IN ITEMS X4 X8 X16 X32 X64)
if (AVX10_${width})
+16 -1
View File
@@ -46,6 +46,7 @@ Contents:
* `Recent Changes to ISPC`_
+ `Updating ISPC Programs For Changes In ISPC 1.31.0`_
+ `Updating ISPC Programs For Changes In ISPC 1.30.0`_
+ `Updating ISPC Programs For Changes In ISPC 1.29.0`_
+ `Updating ISPC Programs For Changes In ISPC 1.28.0`_
@@ -282,6 +283,19 @@ New Architecture Support:
* The hyperbolic functions ``sinh``, ``cosh`` and ``tanh`` have also been added
to the standard library.
ISPC Targets:
* New ``avx10.2nvl-x4``, ``avx10.2nvl-x8``, ``avx10.2nvl-x16``,
``avx10.2nvl-x32``, and ``avx10.2nvl-x64`` targets have been added for Intel
Nova Lake processors. These targets implement AVX10.2 with full AVX-512
support but, unlike the ``avx10.2dmr`` (Diamond Rapids) targets, they do not
include AMX. The corresponding predefined macro is ``ISPC_TARGET_AVX10_2NVL``.
* The multi-target runtime dispatcher now selects an AMX-bearing server target
variant (``avx512spr``, ``avx512gnr``, ``avx10.2dmr``) only when the system
supports AMX, instead of relying solely on the ISA ordering. AMX support is
checked the same way AVX-512 already is: the CPU must advertise the feature in
CPUID and the OS must manage its XSAVE state.
Updating ISPC Programs For Changes In ISPC 1.30.0
-------------------------------------------------
@@ -1316,6 +1330,7 @@ avx512icl AVX-512 Intel Icelake (2019), AMD Zen4 (2022)
avx512spr AVX-512 + AMX Intel Sapphire Rapids (2023)
avx512gnr AVX-512 + AMX FP16 Intel Granite Rapids (2024)
avx10.2dmr AVX10.2 + AMX Intel Diamond Rapids (2026+)
avx10.2nvl AVX10.2 Intel Nova Lake (2026+)
neon ARMv8 NEON ARM Cortex-A35/A53/A57 (2012-2015)
============= ========================= ===========================================================
@@ -1479,7 +1494,7 @@ preprocessor runs:
* - ISPC
- 1
- Enables detecting that the ``ispc`` compiler is processing the file
* - ISPC_TARGET_{NEON, SSE2, SSE4, AVX, AVX2, AVX512SKX, AVX512ICL, AVX512SPR, AVX512GNR, AVX10_2DMR}
* - ISPC_TARGET_{NEON, SSE2, SSE4, AVX, AVX2, AVX512SKX, AVX512ICL, AVX512SPR, AVX512GNR, AVX10_2DMR, AVX10_2NVL}
- 1
- One of these will be set, depending on the compilation target
* - ISPC_POINTER_SIZE
+13 -5
View File
@@ -360,10 +360,16 @@ def build_LLVM(version_LLVM, folder, debug, selfbuild, extra, openmp, from_valid
def unsupported_llvm_targets(LLVM_VERSION):
prohibited_list = {"6.0":["avx512skx-x8", "avx512skx-x4", "avx512skx-x64", "avx512skx-x32"],
"7.0":["avx512skx-x8", "avx512skx-x4", "avx512skx-x64", "avx512skx-x32"],
"8.0":["avx512skx-x64", "avx512skx-x32"],
"9.0":["avx512skx-x64", "avx512skx-x32"]
# NVL (Nova Lake) targets are only parsed by ISPC under LLVM 22.0+.
nvl_targets = ["avx10.2nvl-x16", "avx10.2nvl-x8", "avx10.2nvl-x4", "avx10.2nvl-x64", "avx10.2nvl-x32"]
prohibited_list = {"6.0":["avx512skx-x8", "avx512skx-x4", "avx512skx-x64", "avx512skx-x32"] + nvl_targets,
"7.0":["avx512skx-x8", "avx512skx-x4", "avx512skx-x64", "avx512skx-x32"] + nvl_targets,
"8.0":["avx512skx-x64", "avx512skx-x32"] + nvl_targets,
"9.0":["avx512skx-x64", "avx512skx-x32"] + nvl_targets,
"10.0":nvl_targets, "11.0":nvl_targets, "12.0":nvl_targets,
"13.0":nvl_targets, "14.0":nvl_targets, "15.0":nvl_targets,
"16.0":nvl_targets, "17.0":nvl_targets, "18.1":nvl_targets,
"19.1":nvl_targets, "20.1":nvl_targets, "21.1":nvl_targets,
}
if LLVM_VERSION in prohibited_list:
return prohibited_list[LLVM_VERSION]
@@ -428,7 +434,9 @@ def check_targets():
("GNR", [["avx512gnr-x16", "avx512gnr-x8", "avx512gnr-x4", "avx512gnr-x64", "avx512gnr-x32"],
["SSE2", "SSE4.1", "SSE4.2", "AVX", "AVX1.1", "AVX2", "AVX2VNNI", "SKX", "ICL", "SPR", "GNR"], "-gnr", False]),
("DMR", [["avx10.2dmr-x16", "avx10.2dmr-x8", "avx10.2dmr-x4", "avx10.2dmr-x64", "avx10.2dmr-x32"],
["SSE2", "SSE4.1", "SSE4.2", "AVX", "AVX1.1", "AVX2", "AVX2VNNI", "SKX", "ICL", "SPR", "GNR", "DMR"], "-dmr", False])
["SSE2", "SSE4.1", "SSE4.2", "AVX", "AVX1.1", "AVX2", "AVX2VNNI", "SKX", "ICL", "SPR", "GNR", "DMR"], "-dmr", False]),
("NVL", [["avx10.2nvl-x16", "avx10.2nvl-x8", "avx10.2nvl-x4", "avx10.2nvl-x64", "avx10.2nvl-x32"],
["SSE2", "SSE4.1", "SSE4.2", "AVX", "AVX1.1", "AVX2", "AVX2VNNI", "SKX", "ICL", "NVL"], "-nvl", False])
])
hw_arch = take_lines(check_isa, "first").split()[1]
+10 -3
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (c) 2025, Intel Corporation
# Copyright (c) 2025-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -163,13 +163,20 @@ class ISPCTarget:
'neon-i32x4': 'generic-i32x4',
'neon-i32x8': 'generic-i32x8',
# AVX10.2 targets
# AVX10.2 DMR targets
'avx10.2dmr-x4': 'avx512gnr-x4',
'avx10.2dmr-x8': 'avx512gnr-x8',
'avx10.2dmr-x16': 'avx512gnr-x16',
'avx10.2dmr-x32': 'avx512gnr-x32',
'avx10.2dmr-x64': 'avx512gnr-x64',
# AVX10.2 NVL targets (NVL doesn't have AMX, so inherit it from ICL)
'avx10.2nvl-x4': 'avx512icl-x4',
'avx10.2nvl-x8': 'avx512icl-x8',
'avx10.2nvl-x16': 'avx512icl-x16',
'avx10.2nvl-x32': 'avx512icl-x32',
'avx10.2nvl-x64': 'avx512icl-x64',
# AVX512 hierarchy
'avx512gnr-x4': 'avx512spr-x4',
'avx512spr-x4': 'avx512icl-x4',
@@ -238,7 +245,7 @@ class ISPCTarget:
@classmethod
def normalize_target_name(cls, target: str) -> str:
"""Normalize target name format (e.g., avx512spr-x4 -> avx512spr_x4, avx10.2dmr-x4 -> avx10_2dmr_x4)"""
"""Normalize target name format (e.g., avx512spr-x4 -> avx512spr_x4, avx10.2dmr-x4 -> avx10_2dmr_x4, avx10.2nvl-x4 -> avx10_2nvl_x4)"""
return target.replace('-', '_').replace('.', '_')
@classmethod
+8
View File
@@ -492,6 +492,14 @@ std::unordered_map<ISPCTarget, ISPCTarget> targetParentMap = {
{ISPCTarget::avx10_2dmr_x32, ISPCTarget::avx512gnr_x32},
{ISPCTarget::avx10_2dmr_x64, ISPCTarget::avx512gnr_x64},
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
{ISPCTarget::avx10_2nvl_x4, ISPCTarget::avx512icl_x4},
{ISPCTarget::avx10_2nvl_x8, ISPCTarget::avx512icl_x8},
{ISPCTarget::avx10_2nvl_x16, ISPCTarget::avx512icl_x16},
{ISPCTarget::avx10_2nvl_x32, ISPCTarget::avx512icl_x32},
{ISPCTarget::avx10_2nvl_x64, ISPCTarget::avx512icl_x64},
#endif
{ISPCTarget::avx512gnr_x4, ISPCTarget::avx512spr_x4},
{ISPCTarget::avx512spr_x4, ISPCTarget::avx512icl_x4},
{ISPCTarget::avx512icl_x4, ISPCTarget::avx512skx_x4},
+11 -4
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2025, Intel Corporation
Copyright (c) 2025-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,7 +22,8 @@ enum ISA {
ICL_AVX512 = 9,
SPR_AVX512 = 10,
GNR_AVX512 = 11,
DMR_AVX10_2 = 12,
NVL_AVX10_2 = 12,
DMR_AVX10_2 = 13,
COUNT
};
@@ -193,10 +194,14 @@ UNUSED_ATTR static enum ISA get_x86_isa() {
UNUSED_ATTR int cpx = clx && avx512_bf16;
int icl =
clx && avx512_vbmi2 && avx512_gfni && avx512_vaes && avx512_vpclmulqdq && avx512_bitalg && avx512_vpopcntdq;
// Server platforms
UNUSED_ATTR int tgl = icl && avx512_vp2intersect;
int spr =
icl && avx512_bf16 && avx512_amx_bf16 && avx512_amx_tile && avx512_amx_int8 && avx_vnni && avx512_fp16;
int gnr = spr && amxfp16 && prefetchi;
// Client platforms
UNUSED_ATTR int arl =
icl && avxvnniint8 && avxvnniint16 && avxneconvert && sha512 && sm3 && sm4 && avxifma && cmpccxadd;
int avx10 = (info3[3] & (1 << 19)) != 0;
@@ -212,13 +217,15 @@ UNUSED_ATTR static enum ISA get_x86_isa() {
// clang-format on
// Diamond Rapids: DMR = GNR + AVX10_2 + APX + ... (For the whole list see x86TargetParser.cpp)
// TODO: according to spec the presence of avx10.2 should cover the whole set of features, but let's keep it
// now aligned with LLVM logic
int dmr = gnr && avx10_2 && apx && cmpccxadd && avxneconvert && avxifma && avxvnniint8 && avxvnniint16 &&
amxcomplex && sha512 && sm3 && sm4;
// Nova Lake: NVL = ARL + AVX10_2 + APX + ...
int nvl = arl && avx10_2 && apx && avx512_fp16;
if (dmr) {
return DMR_AVX10_2;
} else if (nvl) {
return NVL_AVX10_2;
}
}
if (gnr) {
+131 -22
View File
@@ -257,6 +257,16 @@ static ISPCTarget lGetSystemISA() {
return ISPCTarget::avx512spr_x16;
case Target::ISA::GNR_AVX512:
return ISPCTarget::avx512gnr_x16;
case Target::ISA::NVL_AVX10_2:
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
return ISPCTarget::avx10_2nvl_x8;
#else
// NVL targets are only available under LLVM 22.0+. On older LLVM we
// still detect NVL hardware (lGetSystemISA), but cannot emit an NVL
// target, so fall back to ICL: NVL is a superset of ICL (full AVX-512
// without AMX), so an ICL build runs correctly on NVL hardware.
return ISPCTarget::avx512icl_x8;
#endif
case Target::ISA::DMR_AVX10_2:
return ISPCTarget::avx10_2dmr_x16;
default:
@@ -355,6 +365,9 @@ typedef enum {
CPU_ARL,
CPU_LNL,
CPU_DMR,
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPU_NVL,
#endif
// Zen1 to Zen5
CPU_ZNVER1,
CPU_ZNVER2,
@@ -470,10 +483,14 @@ std::map<DeviceType, std::set<std::string>> CPUFeatures = {
{"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx512", "avx_vnni", "avx512_vnni", "amxtile",
"amxint8", "amxfp16"}},
{CPU_DMR,
{"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx512", "avx_vnni", "avx512_vnni", "amxtile",
"amxint8", "amxfp16"}},
{"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx512", "avx10", "avx_vnni", "avx512_vnni",
"amxtile", "amxint8", "amxfp16"}},
{CPU_ARL, {"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx_vnni"}},
{CPU_LNL, {"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx_vnni"}},
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
{CPU_NVL,
{"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2", "avx512", "avx10", "avx_vnni", "avx512_vnni"}},
#endif
{CPU_ZNVER1, {"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2"}},
{CPU_ZNVER2, {"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2"}},
{CPU_ZNVER3, {"mmx", "sse", "sse2", "ssse3", "sse41", "sse42", "avx", "avx2"}},
@@ -598,6 +615,10 @@ class AllCPUs {
names[CPU_LNL].push_back("lnl");
names[CPU_DMR].push_back("diamondrapids");
names[CPU_DMR].push_back("dmr");
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
names[CPU_NVL].push_back("novalake");
names[CPU_NVL].push_back("nvl");
#endif
names[CPU_ZNVER1].push_back("znver1");
names[CPU_ZNVER2].push_back("znver2");
names[CPU_ZNVER2].push_back("ps5");
@@ -676,6 +697,14 @@ class AllCPUs {
compat[CPU_LNL] =
Set(CPU_LNL, CPU_x86_64, CPU_Bonnell, CPU_Penryn, CPU_Core2, CPU_Nehalem, CPU_Silvermont, CPU_SandyBridge,
CPU_IvyBridge, CPU_Haswell, CPU_Broadwell, CPU_Skylake, CPU_ADL, CPU_ARL, CPU_None);
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
// NVL has full AVX-512 but no AMX, so it is backward-compatible with the
// non-AMX AVX-512 CPUs (SKX, ICL, ICX, TGL) and the client lineage, but
// not with the AMX-capable server CPUs (SPR, GNR, DMR).
compat[CPU_NVL] = Set(CPU_NVL, CPU_x86_64, CPU_Bonnell, CPU_Penryn, CPU_Core2, CPU_Nehalem, CPU_Silvermont,
CPU_SandyBridge, CPU_IvyBridge, CPU_Haswell, CPU_Broadwell, CPU_Skylake, CPU_SKX, CPU_ICL,
CPU_ICX, CPU_TGL, CPU_ADL, CPU_ARL, CPU_LNL, CPU_None);
#endif
compat[CPU_TGL] =
Set(CPU_TGL, CPU_x86_64, CPU_Bonnell, CPU_Penryn, CPU_Core2, CPU_Nehalem, CPU_Silvermont, CPU_SandyBridge,
CPU_IvyBridge, CPU_Haswell, CPU_Broadwell, CPU_Skylake, CPU_SKX, CPU_ICL, CPU_ICX, CPU_None);
@@ -1057,11 +1086,14 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
case CPU_LNL:
m_ispc_target = ISPCTarget::avx2vnni_i32x8;
break;
case CPU_DMR:
m_ispc_target = ISPCTarget::avx10_2dmr_x16;
break;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case CPU_NVL:
m_ispc_target = ISPCTarget::avx10_2nvl_x8;
break;
#endif
case CPU_ZNVER1:
case CPU_ZNVER2:
case CPU_ZNVER3:
@@ -1676,7 +1708,10 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
CPUfromISA = (m_ispc_target == ISPCTarget::avx512gnr_x32) ? CPU_GNR : CPU_SPR;
break;
case ISPCTarget::avx10_2dmr_x4:
this->m_isa = Target::DMR_AVX10_2;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case ISPCTarget::avx10_2nvl_x4:
#endif
this->m_isa = (m_ispc_target == ISPCTarget::avx10_2dmr_x4) ? Target::DMR_AVX10_2 : Target::NVL_AVX10_2;
this->m_nativeVectorWidth = 16;
this->m_nativeVectorAlignment = 64;
this->m_dataTypeWidth = 32;
@@ -1687,14 +1722,25 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
setCapabilities({TargetCapability::HalfConverts, TargetCapability::HalfFullSupport, TargetCapability::Rand,
TargetCapability::Fp16Support, TargetCapability::IntelVNNI, TargetCapability::IntelVNNI_Int8,
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection,
TargetCapability::Rsqrtd, TargetCapability::Rcpd, TargetCapability::AmxTile,
TargetCapability::AmxInt8, TargetCapability::AmxBf16, TargetCapability::AmxFp16});
TargetCapability::Rsqrtd, TargetCapability::Rcpd});
// DMR has AMX capabilities, NVL does not (under LLVM < 22 only DMR reaches this case).
setCapability(TargetCapability::AmxTile, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxInt8, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxBf16, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxFp16, (this->m_isa == Target::DMR_AVX10_2));
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPUfromISA = (this->m_isa == Target::DMR_AVX10_2) ? CPU_DMR : CPU_NVL;
#else
CPUfromISA = CPU_DMR;
#endif
this->m_funcAttributes.push_back(std::make_pair("prefer-vector-width", "256"));
this->m_funcAttributes.push_back(std::make_pair("min-legal-vector-width", "256"));
break;
case ISPCTarget::avx10_2dmr_x8:
this->m_isa = Target::DMR_AVX10_2;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case ISPCTarget::avx10_2nvl_x8:
#endif
this->m_isa = (m_ispc_target == ISPCTarget::avx10_2dmr_x8) ? Target::DMR_AVX10_2 : Target::NVL_AVX10_2;
this->m_nativeVectorWidth = 16;
this->m_nativeVectorAlignment = 64;
this->m_dataTypeWidth = 32;
@@ -1705,14 +1751,25 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
setCapabilities({TargetCapability::HalfConverts, TargetCapability::HalfFullSupport, TargetCapability::Rand,
TargetCapability::Fp16Support, TargetCapability::IntelVNNI, TargetCapability::IntelVNNI_Int8,
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection,
TargetCapability::Rsqrtd, TargetCapability::Rcpd, TargetCapability::AmxTile,
TargetCapability::AmxInt8, TargetCapability::AmxBf16, TargetCapability::AmxFp16});
TargetCapability::Rsqrtd, TargetCapability::Rcpd});
// DMR has AMX capabilities, NVL does not (under LLVM < 22 only DMR reaches this case).
setCapability(TargetCapability::AmxTile, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxInt8, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxBf16, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxFp16, (this->m_isa == Target::DMR_AVX10_2));
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPUfromISA = (this->m_isa == Target::DMR_AVX10_2) ? CPU_DMR : CPU_NVL;
#else
CPUfromISA = CPU_DMR;
#endif
this->m_funcAttributes.push_back(std::make_pair("prefer-vector-width", "256"));
this->m_funcAttributes.push_back(std::make_pair("min-legal-vector-width", "256"));
break;
case ISPCTarget::avx10_2dmr_x16:
this->m_isa = Target::DMR_AVX10_2;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case ISPCTarget::avx10_2nvl_x16:
#endif
this->m_isa = (m_ispc_target == ISPCTarget::avx10_2dmr_x16) ? Target::DMR_AVX10_2 : Target::NVL_AVX10_2;
this->m_nativeVectorWidth = 16;
this->m_nativeVectorAlignment = 64;
this->m_dataTypeWidth = 32;
@@ -1723,14 +1780,25 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
setCapabilities({TargetCapability::HalfConverts, TargetCapability::HalfFullSupport, TargetCapability::Rand,
TargetCapability::Fp16Support, TargetCapability::IntelVNNI, TargetCapability::IntelVNNI_Int8,
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection,
TargetCapability::Rsqrtd, TargetCapability::Rcpd, TargetCapability::AmxTile,
TargetCapability::AmxInt8, TargetCapability::AmxBf16, TargetCapability::AmxFp16});
TargetCapability::Rsqrtd, TargetCapability::Rcpd});
// DMR has AMX capabilities, NVL does not (under LLVM < 22 only DMR reaches this case).
setCapability(TargetCapability::AmxTile, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxInt8, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxBf16, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxFp16, (this->m_isa == Target::DMR_AVX10_2));
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPUfromISA = (this->m_isa == Target::DMR_AVX10_2) ? CPU_DMR : CPU_NVL;
#else
CPUfromISA = CPU_DMR;
#endif
this->m_funcAttributes.push_back(std::make_pair("prefer-vector-width", "512"));
this->m_funcAttributes.push_back(std::make_pair("min-legal-vector-width", "512"));
break;
case ISPCTarget::avx10_2dmr_x32:
this->m_isa = Target::DMR_AVX10_2;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case ISPCTarget::avx10_2nvl_x32:
#endif
this->m_isa = (m_ispc_target == ISPCTarget::avx10_2dmr_x32) ? Target::DMR_AVX10_2 : Target::NVL_AVX10_2;
this->m_nativeVectorWidth = 64;
this->m_nativeVectorAlignment = 64;
this->m_dataTypeWidth = 16;
@@ -1740,13 +1808,23 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
this->m_hasGather = this->m_hasScatter = true;
setCapabilities({TargetCapability::HalfConverts, TargetCapability::HalfFullSupport, TargetCapability::Rand,
TargetCapability::Fp16Support, TargetCapability::IntelVNNI, TargetCapability::IntelVNNI_Int8,
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection,
TargetCapability::AmxTile, TargetCapability::AmxInt8, TargetCapability::AmxBf16,
TargetCapability::AmxFp16});
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection});
// DMR has AMX capabilities, NVL does not (under LLVM < 22 only DMR reaches this case).
setCapability(TargetCapability::AmxTile, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxInt8, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxBf16, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxFp16, (this->m_isa == Target::DMR_AVX10_2));
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPUfromISA = (this->m_isa == Target::DMR_AVX10_2) ? CPU_DMR : CPU_NVL;
#else
CPUfromISA = CPU_DMR;
#endif
break;
case ISPCTarget::avx10_2dmr_x64:
this->m_isa = Target::DMR_AVX10_2;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
case ISPCTarget::avx10_2nvl_x64:
#endif
this->m_isa = (m_ispc_target == ISPCTarget::avx10_2dmr_x64) ? Target::DMR_AVX10_2 : Target::NVL_AVX10_2;
this->m_nativeVectorWidth = 64;
this->m_nativeVectorAlignment = 64;
this->m_dataTypeWidth = 8;
@@ -1756,11 +1834,28 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
this->m_hasGather = this->m_hasScatter = true;
setCapabilities({TargetCapability::HalfConverts, TargetCapability::HalfFullSupport, TargetCapability::Rand,
TargetCapability::Fp16Support, TargetCapability::IntelVNNI, TargetCapability::IntelVNNI_Int8,
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection,
TargetCapability::AmxTile, TargetCapability::AmxInt8, TargetCapability::AmxBf16,
TargetCapability::AmxFp16});
TargetCapability::IntelVNNI_Int16, TargetCapability::ConflictDetection});
// DMR has AMX capabilities, NVL does not (under LLVM < 22 only DMR reaches this case).
setCapability(TargetCapability::AmxTile, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxInt8, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxBf16, (this->m_isa == Target::DMR_AVX10_2));
setCapability(TargetCapability::AmxFp16, (this->m_isa == Target::DMR_AVX10_2));
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
CPUfromISA = (this->m_isa == Target::DMR_AVX10_2) ? CPU_DMR : CPU_NVL;
#else
CPUfromISA = CPU_DMR;
#endif
break;
#if ISPC_LLVM_VERSION < ISPC_LLVM_22_0
// For LLVM 20-21, NVL targets are not supported yet
case ISPCTarget::avx10_2nvl_x4:
case ISPCTarget::avx10_2nvl_x8:
case ISPCTarget::avx10_2nvl_x16:
case ISPCTarget::avx10_2nvl_x32:
case ISPCTarget::avx10_2nvl_x64:
unsupported_target = true;
break;
#endif
#ifdef ISPC_ARM_ENABLED
case ISPCTarget::neon_i8x16:
this->m_isa = Target::NEON;
@@ -2233,7 +2328,11 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
if ((m_ispc_target == ISPCTarget::generic_i32x16 || m_ispc_target == ISPCTarget::generic_i1x16 ||
m_ispc_target == ISPCTarget::generic_i1x32 || m_ispc_target == ISPCTarget::generic_i1x64) &&
(CPUID == CPU_SKX || CPUID == CPU_ICL || CPUID == CPU_SPR || CPUID == CPU_GNR || CPUID == CPU_DMR)) {
(CPUID == CPU_SKX || CPUID == CPU_ICL || CPUID == CPU_SPR || CPUID == CPU_GNR || CPUID == CPU_DMR
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
|| CPUID == CPU_NVL
#endif
)) {
// Support --opt=disable-zmm for generic targets when CPU with avx512 support is specified.
if (g->opt.disableZMM) {
this->m_funcAttributes.push_back(std::make_pair("prefer-vector-width", "256"));
@@ -2790,6 +2889,8 @@ const char *Target::ISAToString(ISA isa) {
return "avx512gnr";
case Target::DMR_AVX10_2:
return "avx10_2dmr";
case Target::NVL_AVX10_2:
return "avx10_2nvl";
#ifdef ISPC_XE_ENABLED
case Target::XELP:
return "xelp";
@@ -2863,6 +2964,8 @@ const char *Target::ISAToTargetString(ISA isa) {
return "avx512gnr-x16";
case Target::DMR_AVX10_2:
return "avx10.2dmr-x16";
case Target::NVL_AVX10_2:
return "avx10.2nvl-x8";
default:
FATAL("Unhandled target in ISAToTargetString()");
}
@@ -2934,6 +3037,12 @@ Target::ISA Target::TargetToISA(ISPCTarget target) {
case ISPCTarget::avx10_2dmr_x32:
case ISPCTarget::avx10_2dmr_x64:
return Target::ISA::DMR_AVX10_2;
case ISPCTarget::avx10_2nvl_x4:
case ISPCTarget::avx10_2nvl_x8:
case ISPCTarget::avx10_2nvl_x16:
case ISPCTarget::avx10_2nvl_x32:
case ISPCTarget::avx10_2nvl_x64:
return Target::ISA::NVL_AVX10_2;
#ifdef ISPC_ARM_ENABLED
case ISPCTarget::neon_i8x16:
case ISPCTarget::neon_i8x32:
+1
View File
@@ -256,6 +256,7 @@ class Target {
ICL_AVX512 = dispatch::ISA::ICL_AVX512,
SPR_AVX512 = dispatch::ISA::SPR_AVX512,
GNR_AVX512 = dispatch::ISA::GNR_AVX512,
NVL_AVX10_2 = dispatch::ISA::NVL_AVX10_2,
DMR_AVX10_2 = dispatch::ISA::DMR_AVX10_2,
#ifdef ISPC_ARM_ENABLED
NEON,
+28 -5
View File
@@ -1952,6 +1952,29 @@ static llvm::FunctionType *lGetVaryingDispatchType(FunctionTargetVariants &funcs
return resultFuncTy;
}
/** Emit the predicate deciding whether a system reporting @p systemISA may run
the @p candidate variant.
The base test is the linear "systemISA >= candidate", which assumes the
Target::ISA enumerant is a total order in which each ISA is a superset of all
lower-numbered ones. Nova Lake (NVL) breaks that: it implements AVX10.2 (so it
sorts above SPR/GNR) but, unlike SPR/GNR/DMR, has no AMX. So an NVL system must
not select the AMX-bearing SPR/GNR variants -- it falls back to an ICL-or-lower
variant (NVL has full AVX-512) or to a present NVL/AVX10.2 variant. DMR (a
higher enumerant than NVL) is already excluded from SPR/GNR by the ">=" test,
and NVL selecting its own variant is fine. */
static llvm::Value *lEmitISACompatibilityTest(int candidate, llvm::Value *systemISA, llvm::BasicBlock *bblock) {
// "is the system's ISA enumerant value >= the enumerant value of the current candidate?"
llvm::Value *ok = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, systemISA,
LLVMInt32(candidate), "isa_ok", bblock);
if (candidate == Target::SPR_AVX512 || candidate == Target::GNR_AVX512) {
llvm::Value *notNVL = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_NE, systemISA,
LLVMInt32(Target::NVL_AVX10_2), "not_nvl", bblock);
ok = llvm::BinaryOperator::Create(llvm::Instruction::And, ok, notNVL, "isa_ok_nvl", bblock);
}
return ok;
}
/** Create the dispatch function for an exported ispc function.
This function checks to see which vector ISAs the system the
code is running on supports and calls out to the best available
@@ -2068,12 +2091,12 @@ static void lCreateDispatchFunction(llvm::Module *module, llvm::Function *getBes
continue;
}
// Emit code to see if the system can run the current candidate
// variant successfully--"is the system's ISA enumerant value >=
// the enumerant value of the current candidate?"
// Emit code to see if the system can run the current candidate variant
// successfully. The base test is the linear "systemISA >= candidate", with
// an extra guard for NVL on the AMX-bearing SPR/GNR variants (see the
// helper for details).
llvm::Value *ok = lEmitISACompatibilityTest(i, systemISA, bblock);
llvm::Value *ok = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, systemISA,
LLVMInt32(i), "isa_ok", bblock);
llvm::BasicBlock *callBBlock = llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc);
llvm::BasicBlock *nextBBlock = llvm::BasicBlock::Create(*g->ctx, "next_try", dispatchFunc);
#if ISPC_LLVM_VERSION >= ISPC_LLVM_23_0
+43 -1
View File
@@ -220,9 +220,24 @@ ISPCTarget operator++(ISPCTarget &target, int dummy) {
static_assert(static_cast<underlying>(ISPCTarget::avx10_2dmr_x64) ==
static_cast<underlying>(ISPCTarget::avx10_2dmr_x32) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::neon_i8x16) ==
static_assert(static_cast<underlying>(ISPCTarget::avx10_2nvl_x4) ==
static_cast<underlying>(ISPCTarget::avx10_2dmr_x64) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::avx10_2nvl_x8) ==
static_cast<underlying>(ISPCTarget::avx10_2nvl_x4) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::avx10_2nvl_x16) ==
static_cast<underlying>(ISPCTarget::avx10_2nvl_x8) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::avx10_2nvl_x32) ==
static_cast<underlying>(ISPCTarget::avx10_2nvl_x16) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::avx10_2nvl_x64) ==
static_cast<underlying>(ISPCTarget::avx10_2nvl_x32) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::neon_i8x16) ==
static_cast<underlying>(ISPCTarget::avx10_2nvl_x64) + 1,
"Enum ISPCTarget is not sequential");
static_assert(static_cast<underlying>(ISPCTarget::neon_i8x32) ==
static_cast<underlying>(ISPCTarget::neon_i8x16) + 1,
"Enum ISPCTarget is not sequential");
@@ -487,6 +502,18 @@ ISPCTarget ParseISPCTarget(std::string target) {
return ISPCTarget::avx10_2dmr_x32;
} else if (target == "avx10.2dmr-x64") {
return ISPCTarget::avx10_2dmr_x64;
#if ISPC_LLVM_VERSION >= ISPC_LLVM_22_0
} else if (target == "avx10.2nvl-x4") {
return ISPCTarget::avx10_2nvl_x4;
} else if (target == "avx10.2nvl-x8") {
return ISPCTarget::avx10_2nvl_x8;
} else if (target == "avx10.2nvl-x16") {
return ISPCTarget::avx10_2nvl_x16;
} else if (target == "avx10.2nvl-x32") {
return ISPCTarget::avx10_2nvl_x32;
} else if (target == "avx10.2nvl-x64") {
return ISPCTarget::avx10_2nvl_x64;
#endif
} else if (target == "neon-i8x16") {
return ISPCTarget::neon_i8x16;
} else if (target == "neon-i8x32") {
@@ -702,6 +729,16 @@ std::string ISPCTargetToString(ISPCTarget target) {
return "avx10.2dmr-x32";
case ISPCTarget::avx10_2dmr_x64:
return "avx10.2dmr-x64";
case ISPCTarget::avx10_2nvl_x4:
return "avx10.2nvl-x4";
case ISPCTarget::avx10_2nvl_x8:
return "avx10.2nvl-x8";
case ISPCTarget::avx10_2nvl_x16:
return "avx10.2nvl-x16";
case ISPCTarget::avx10_2nvl_x32:
return "avx10.2nvl-x32";
case ISPCTarget::avx10_2nvl_x64:
return "avx10.2nvl-x64";
case ISPCTarget::neon_i8x16:
return "neon-i8x16";
case ISPCTarget::neon_i8x32:
@@ -842,6 +879,11 @@ bool ISPCTargetIsX86(ISPCTarget target) {
case ISPCTarget::avx10_2dmr_x16:
case ISPCTarget::avx10_2dmr_x32:
case ISPCTarget::avx10_2dmr_x64:
case ISPCTarget::avx10_2nvl_x4:
case ISPCTarget::avx10_2nvl_x8:
case ISPCTarget::avx10_2nvl_x16:
case ISPCTarget::avx10_2nvl_x32:
case ISPCTarget::avx10_2nvl_x64:
return true;
default:
return false;
+5
View File
@@ -85,6 +85,11 @@ enum class ISPCTarget {
avx10_2dmr_x16,
avx10_2dmr_x32,
avx10_2dmr_x64,
avx10_2nvl_x4,
avx10_2nvl_x8,
avx10_2nvl_x16,
avx10_2nvl_x32,
avx10_2nvl_x64,
neon_i8x16,
neon_i8x32,
neon_i16x8,
+3 -1
View File
@@ -183,7 +183,9 @@ static ISPCTarget lCanonicalizeTarget(ISPCTarget target, TargetOS os, bool apply
target == ISPCTarget::avx512gnr_x32 || target == ISPCTarget::avx512gnr_x64 ||
target == ISPCTarget::avx10_2dmr_x4 || target == ISPCTarget::avx10_2dmr_x8 ||
target == ISPCTarget::avx10_2dmr_x16 || target == ISPCTarget::avx10_2dmr_x32 ||
target == ISPCTarget::avx10_2dmr_x64)) {
target == ISPCTarget::avx10_2dmr_x64 || target == ISPCTarget::avx10_2nvl_x4 ||
target == ISPCTarget::avx10_2nvl_x8 || target == ISPCTarget::avx10_2nvl_x16 ||
target == ISPCTarget::avx10_2nvl_x32 || target == ISPCTarget::avx10_2nvl_x64)) {
return ISPCTarget::none;
}
+2 -2
View File
@@ -171,7 +171,7 @@ static const int32 programIndex = {ISPC_PROGRAM_INDEX_INITIALIZER};
#endif
#if defined(ISPC_TARGET_AVX512SKX) || defined(ISPC_TARGET_AVX512ICL) || defined(ISPC_TARGET_AVX512SPR) || \
defined(ISPC_TARGET_AVX512GNR) || defined(ISPC_TARGET_AVX10_2DMR)
defined(ISPC_TARGET_AVX512GNR) || defined(ISPC_TARGET_AVX10_2DMR) || defined(ISPC_TARGET_AVX10_2NVL)
#define ISPC_TARGET_HAS_ROTATE_VIA_SHUFFLE_8_VAL 1
#define ISPC_TARGET_HAS_ROTATE_VIA_SHUFFLE_16_VAL 1
#if TARGET_WIDTH <= 32
@@ -197,7 +197,7 @@ static const int32 programIndex = {ISPC_PROGRAM_INDEX_INITIALIZER};
#endif
#if defined(ISPC_TARGET_AVX512SKX) || defined(ISPC_TARGET_AVX512ICL) || defined(ISPC_TARGET_AVX512SPR) || \
defined(ISPC_TARGET_AVX512GNR) || defined(ISPC_TARGET_AVX10_2DMR)
defined(ISPC_TARGET_AVX512GNR) || defined(ISPC_TARGET_AVX10_2DMR) || defined(ISPC_TARGET_AVX10_2NVL)
#define ISPC_TARGET_HAS_SHIFT_VIA_SHUFFLE_8_VAL 1
#define ISPC_TARGET_HAS_SHIFT_VIA_SHUFFLE_16_VAL 1
#if TARGET_WIDTH < 64
@@ -0,0 +1,25 @@
// Verifies that the "avx10" entry in ISPC's CPUFeatures map lets an AVX10
// LLVM intrinsic be used from ISPC source on the diamondrapids (DMR) and
// novalake (NVL) CPUs. Without the "avx10" CPUFeatures entry for these CPUs,
// Target::checkIntrinsticSupport rejects @llvm.x86.avx10.* with
// "Target specific LLVM intrinsic ... not supported on ... CPU".
// The @llvm.x86.avx10.mask.vminmaxps256 intrinsic exists in LLVM 22 and
// lowers to the vminmaxps instruction, proving the intrinsic is both accepted
// (feature gate works) and selected by the backend.
// RUN: %{ispc} %s --target=avx10.2dmr-x16 --enable-llvm-intrinsics --nowrap --emit-asm -o - | FileCheck %s
// RUN: %{ispc} %s --target=avx10.2nvl-x16 --enable-llvm-intrinsics --nowrap --emit-asm -o - | FileCheck %s
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK-LABEL: f___
// CHECK: vminmaxps
export void f(uniform float a[8], uniform float b[8], uniform float passthru[8], uniform float out[8]) {
uniform float<8> va = {a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]};
uniform float<8> vb = {b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]};
uniform float<8> vp = {passthru[0], passthru[1], passthru[2], passthru[3],
passthru[4], passthru[5], passthru[6], passthru[7]};
uniform float<8> r = @llvm.x86.avx10.mask.vminmaxps256(va, vb, (uniform int)0, vp, (uniform int8)-1);
for (uniform int i = 0; i < 8; i++)
out[i] = r[i];
}
@@ -0,0 +1,46 @@
// Case 1: Checks avx10.2nvl-x16 assembly output for zmm registers.
//; RUN: %{ispc} %s --target=avx10.2nvl-x16 --emit-asm -o - | FileCheck %s -check-prefix=CHECK_ZMM_32x16
// Case 2a: Checks avx10.2nvl-x4 assembly output to ensure there are no zmm registers.
//; RUN: %{ispc} %s --target=avx10.2nvl-x4 --emit-asm -o - | FileCheck %s --implicit-check-not "zmm"
// Case 2b: Checks avx10.2nvl-x8 assembly output to ensure there are no zmm registers.
//; RUN: %{ispc} %s --target=avx10.2nvl-x8 --emit-asm -o - | FileCheck %s --implicit-check-not "zmm"
// Case 3: Checks avx10.2nvl-x16 LLVM IR to ensure avx10.2nvl-x8 func attributes are not present.
//; RUN: %{ispc} %s --target=avx10.2nvl-x16 --emit-llvm -o %t_8.bc
//; RUN: llvm-dis %t_8.bc -o - | FileCheck %s --implicit-check-not ""min-legal-vector-width"="256"" --implicit-check-not ""prefer-vector-width"="256""
// Case 4a: Checks avx10.2nvl-x4 LLVM IR to ensure avx10.2nvl-x4 func attributes are present (same as for x8).
//; RUN: %{ispc} %s --target=avx10.2nvl-x4 --emit-llvm -o %t_4.bc
//; RUN: llvm-dis %t_4.bc -o - | FileCheck %s -check-prefix=CHECK_ATTR_8
// Case 4b: Checks avx10.2nvl-x8 LLVM IR to ensure avx10.2nvl-x8 func attributes are present.
//; RUN: %{ispc} %s --target=avx10.2nvl-x8 --emit-llvm -o %t_8.bc
//; RUN: llvm-dis %t_8.bc -o - | FileCheck %s -check-prefix=CHECK_ATTR_8
// REQUIRES: X86_ENABLED && !MACOS_HOST && LLVM_22_0+
double ret_round(double val)
{
//; CHECK_ZMM_32x16: zmm
return round(val+.49999);
}
double foo(double val1, double val2)
{
//; CHECK_ZMM_32x16: zmm
double sub_val = val1 - val2;
return ret_round(sub_val);
}
export void infoo(uniform double afoo1[], uniform double afoo2[], uniform double afoo3[])
{
double a = afoo1[programIndex];
double b = afoo2[programIndex];
double c = foo(a, b);
//; CHECK_ZMM_32x16: zmm
afoo3[programIndex] = c;
}
// The avx10.2-x8 specific function attribute list will be present at 2 places.
// Once where function attributes for exported functions are aggregated and
// again where function attributes for non-exported functions are aggregated.
//; CHECK_ATTR_8: "min-legal-vector-width"="256"
//; CHECK_ATTR_8: "prefer-vector-width"="256"
//; CHECK_ATTR_8: "min-legal-vector-width"="256"
//; CHECK_ATTR_8: "prefer-vector-width"="256"
@@ -0,0 +1,19 @@
// This test checks that AMX FP16 (amxfp16) builtins are correctly handled by ISPC on NVL target
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x8 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x16 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x32 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x64 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_NVL_ERROR: Error: Some AMX functions used in the source are not supported on the current target
#include <amx.isph>
__attribute__((external_only))
export void test_amx_fp16() {
// require amxfp16 feature (GNR+)
amx_dpfp16ps(2, 0, 1);
}
@@ -0,0 +1,28 @@
// This test checks that AMX INT8 (amxint8) and BF16 builtins are correctly handled by ISPC on NVL target
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x8 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x16 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x32 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x64 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_NVL_ERROR: Error: Some AMX functions used in the source are not supported on the current target
#include <amx.isph>
__attribute__((external_only))
export void test_amx_int8() {
// require amxint8 feature (SPR+)
amx_dpbssd(2, 0, 1);
amx_dpbsud(2, 0, 1);
amx_dpbusd(2, 0, 1);
amx_dpbuud(2, 0, 1);
}
__attribute__((external_only))
export void test_amx_bf16() {
// require amxbf16 feature (SPR+)
amx_dpbf16ps(2, 0, 1);
}
@@ -0,0 +1,25 @@
// This test checks that AMX tile (amxtile) builtins are correctly handled by ISPC on NVL target
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x8 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x16 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x32 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x64 --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_NVL_ERROR: Error: Some AMX functions used in the source are not supported on the current target
#include <amx.isph>
__attribute__((external_only))
export void test_amx_tile(uniform int8* uniform config, uniform int8* uniform data) {
// Base AMX tile operations - require amxtile feature
amx_tile_loadconfig(config);
amx_tile_storeconfig(config);
amx_tile_zero(2);
amx_tile_load(0, data, (uniform int64)64);
amx_tile_load_t1(1, data, (uniform int64)64);
amx_tile_store(0, data, (uniform int64)64);
amx_tile_release();
}
+3
View File
@@ -37,6 +37,9 @@ int main() {
case 11:
printf("AVX10_2DMR\n");
break;
case 12:
printf("AVX10_2NVL\n");
break;
default:
printf("Unknown ISA\n");
break;
@@ -5,13 +5,15 @@
// RUN: sde -mrm -- %t.exe | FileCheck %s -check-prefix=CHECK_SSE2
// RUN: sde -dmr -- %t.exe | FileCheck %s -check-prefix=CHECK_DMR
// REQUIRES: X86_ENABLED && SDE_INSTALLED && LLVM_20_0+
// REQUIRES: X86_ENABLED && SDE_INSTALLED && LLVM_20_0+ && !LLVM_22_0+
// CHECK_SSE2: SSE2
// CHECK_DMR: AVX10_2DMR
export uniform int detect_isa() {
#if defined(ISPC_TARGET_AVX10_2DMR)
#if defined(ISPC_TARGET_AVX10_2NVL)
return 12;
#elif defined(ISPC_TARGET_AVX10_2DMR)
return 11;
#elif defined(ISPC_TARGET_AVX512GNR)
return 10;
@@ -0,0 +1,39 @@
// Compile the test for different x86 targets available with LLVM_22+ with auto-dispatch enabled and run the test under SDE to verify that correct platform was picked in runtime.
// RUN: %{ispc} %s --target=sse2-i32x4,avx10.2nvl-x16 -o %t_ispc0.o --nostdlib
// RUN: %{cc} -O2 %S/check_dispatch.c %t_ispc0*.o -o %t.exe
// RUN: sde -mrm -- %t.exe | FileCheck %s -check-prefix=CHECK_SSE2
// RUN: sde -nvl -- %t.exe | FileCheck %s -check-prefix=CHECK_NVL
// REQUIRES: X86_ENABLED && SDE_INSTALLED && LLVM_22_0+
// CHECK_SSE2: SSE2
// CHECK_NVL: AVX10_2NVL
export uniform int detect_isa() {
#if defined(ISPC_TARGET_AVX10_2NVL)
return 12;
#elif defined(ISPC_TARGET_AVX10_2DMR)
return 11;
#elif defined(ISPC_TARGET_AVX512GNR)
return 10;
#elif defined(ISPC_TARGET_AVX512SPR)
return 9;
#elif defined(ISPC_TARGET_AVX512ICL)
return 8;
#elif defined(ISPC_TARGET_AVX512SKX)
return 7;
#elif defined(ISPC_TARGET_AVX2VNNI)
return 5;
#elif defined(ISPC_TARGET_AVX2)
return 4;
#elif defined(ISPC_TARGET_AVX)
return 3;
#elif defined(ISPC_TARGET_SSE4)
return 2;
#elif defined(ISPC_TARGET_SSE2)
return 1;
#else
return 0;
#endif
}
+10
View File
@@ -0,0 +1,10 @@
// The test checks that cpu definitions (including all synonyms) are successfully consumed by compiler.
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=sse2-i32x4 --cpu=nvl
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=sse2-i32x4 --cpu=novalake
// REQUIRES: X86_ENABLED && LLVM_22_0+
uniform int i;
void foo() {}
@@ -0,0 +1,39 @@
// The multi-target runtime dispatcher selects a variant via a linear ">="
// (ICMP_SGE) walk over the Target::ISA enumerant, assuming each ISA is a
// superset of all lower-numbered ones. Nova Lake (NVL=12) breaks that: it has
// AVX10.2 (sorts above SPR=9/GNR=11) but, unlike SPR/GNR/DMR, has no AMX. So an
// AMX-bearing SPR/GNR candidate must carry an extra "system_isa != NVL" guard,
// otherwise an NVL system would select it and fault on AMX instructions.
//
// This test verifies that the guard is emitted for SPR and GNR candidates, and
// is NOT emitted for non-AMX candidates (e.g. avx2). DMR (13) is already
// excluded by the ">=" test and needs no guard.
// RUN: %{ispc} %s -O0 --target=sse2-i32x4,avx512gnr-x16 --emit-llvm-text -o %t.ll --nostdlib
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=GNR
// RUN: %{ispc} %s -O0 --target=sse2-i32x4,avx512spr-x16 --emit-llvm-text -o %t.ll --nostdlib
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=SPR
// RUN: %{ispc} %s -O0 --target=sse2-i32x4,avx2-i32x8 --emit-llvm-text -o %t.ll --nostdlib
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=AVX2
// REQUIRES: X86_ENABLED && !MACOS_HOST
// GNR: %system_isa = call i32 @__get_system_best_isa()
// GNR-NEXT: %isa_ok = icmp sge i32 %system_isa, 11
// GNR-NEXT: %not_nvl = icmp ne i32 %system_isa, 12
// GNR-NEXT: %isa_ok_nvl = and i1 %isa_ok, %not_nvl
// GNR-NEXT: br i1 %isa_ok_nvl, label %do_call, label %next_try
// SPR: %system_isa = call i32 @__get_system_best_isa()
// SPR-NEXT: %isa_ok = icmp sge i32 %system_isa, 10
// SPR-NEXT: %not_nvl = icmp ne i32 %system_isa, 12
// SPR-NEXT: %isa_ok_nvl = and i1 %isa_ok, %not_nvl
// SPR-NEXT: br i1 %isa_ok_nvl, label %do_call, label %next_try
// A non-AMX candidate (avx2) must not get the NVL guard.
// AVX2: %system_isa = call i32 @__get_system_best_isa()
// AVX2-NEXT: %isa_ok = icmp sge i32 %system_isa, {{[0-9]+}}
// AVX2-NEXT: br i1 %isa_ok, label %do_call, label %next_try
// AVX2-NOT: not_nvl
export uniform int which() { return 0; }
@@ -0,0 +1,33 @@
// Companion to dispatch-nvl-amx-guard.ispc, exercising target sets that
// include the LLVM-22+ avx10.2nvl / avx10.2dmr targets. Verifies that:
// - when an NVL variant IS present, the NVL candidate (i=12) itself is
// selected by the plain ">=" test and does NOT carry the not_nvl guard
// (the guard is keyed on the candidate index, not on target-set membership),
// while a co-present SPR candidate still carries the guard;
// - the DMR candidate (i=13) carries no guard, since it is already excluded
// for an NVL system by the ">=" test (12 >= 13 is false).
// RUN: %{ispc} %s -O0 --target=avx512spr-x16,avx10.2nvl-x16 --emit-llvm-text -o %t.ll --nostdlib
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=SPRNVL
// RUN: %{ispc} %s -O0 --target=sse2-i32x4,avx10.2dmr-x16 --emit-llvm-text -o %t.ll --nostdlib
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=DMR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// NVL candidate (12) is selected by ">=" and must NOT get the not_nvl guard.
// SPRNVL: %isa_ok = icmp sge i32 %{{.*}}, 12
// SPRNVL-NEXT: br i1 %isa_ok, label %do_call, label %next_try
// SPRNVL: store atomic ptr @which_avx10_2nvl
// The co-present SPR candidate (10) still gets the guard.
// SPRNVL: %isa_ok1 = icmp sge i32 %{{.*}}, 10
// SPRNVL-NEXT: %not_nvl = icmp ne i32 %{{.*}}, 12
// SPRNVL-NEXT: %isa_ok_nvl = and i1 %isa_ok1, %not_nvl
// SPRNVL-NEXT: br i1 %isa_ok_nvl, label %do_call2, label %next_try3
// SPRNVL: store atomic ptr @which_avx512spr
// DMR candidate (13) is already excluded for NVL by ">="; no guard needed.
// DMR: %isa_ok = icmp sge i32 %system_isa, 13
// DMR-NEXT: br i1 %isa_ok, label %do_call, label %next_try
// DMR-NOT: not_nvl
export uniform int which() { return 0; }
+54
View File
@@ -0,0 +1,54 @@
// RUN: %{ispc} --pic --target=sse2-i32x4,avx512icl-x4,avx512spr-x4,avx512gnr-x4,avx10.2dmr-x4,avx10.2nvl-x4 -h %t.h %s -o %t.o -g
// RUN: %{cc} -x c -c %s -o %t.c.o --include %t.h -g
// RUN: %{cc} %t.c.o -o %t.c.bin -g -rdynamic %t.o %t_sse2.o %t_avx512icl.o %t_avx512spr.o %t_avx512gnr.o %t_avx10_2dmr.o %t_avx10_2nvl.o
// RUN: sde -mrm -- %t.c.bin | FileCheck %s --check-prefix=CHECK-SSE2
// RUN: sde -icl -- %t.c.bin | FileCheck %s --check-prefix=CHECK-ICL
// RUN: sde -spr -- %t.c.bin | FileCheck %s --check-prefix=CHECK-SPR
// RUN: sde -gnr -- %t.c.bin | FileCheck %s --check-prefix=CHECK-GNR
// RUN: sde -dmr -- %t.c.bin | FileCheck %s --check-prefix=CHECK-DMR
// RUN: sde -nvl -- %t.c.bin | FileCheck %s --check-prefix=CHECK-NVL
// REQUIRES: LINUX_HOST && X86_ENABLED && SDE_INSTALLED && LLVM_22_0+
// CHECK-SSE2: ispc_foo_sse2
// CHECK-ICL: ispc_foo_avx512icl
// CHECK-SPR: ispc_foo_avx512spr
// CHECK-GNR: ispc_foo_avx512gnr
// CHECK-DMR: ispc_foo_avx10_2dmr
// CHECK-NVL: ispc_foo_avx10_2nvl
#ifdef ISPC
extern "C" void print_stack_trace();
void check_isa() {
print_stack_trace();
print("check_isa");
}
export void ispc_foo() {
check_isa();
}
#else
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
void print_stack_trace() {
const int max_frames = 64;
void *buffer[max_frames];
int num_frames = backtrace(buffer, max_frames);
char **symbols = backtrace_symbols(buffer, num_frames);
if (symbols == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
printf("Stack trace:\n");
for (int i = 0; i < num_frames; i++) {
printf("%s\n", symbols[i]);
}
free(symbols);
}
extern void ispc_foo();
int main() {
ispc_foo();
return 0;
}
#endif // ISPC
@@ -0,0 +1,14 @@
//; RUN: %{ispc} %s --target=avx2-i32x8 --enable-llvm-intrinsics
//; RUN: %{ispc} %s --cpu=ps4 --target=avx1-i32x8 --enable-llvm-intrinsics
//; RUN: %{ispc} %s --nowrap --cpu=spr --target=avx512spr-x8 --enable-llvm-intrinsics
//; RUN: %{ispc} %s --nowrap --cpu=gnr --target=avx512spr-x8 --enable-llvm-intrinsics
//; RUN: %{ispc} %s --nowrap --cpu=nvl --target=avx10.2nvl-x8 --enable-llvm-intrinsics
//; RUN: not %{ispc} %s --target=sse2-i32x8 --enable-llvm-intrinsics --nowrap 2>&1 | FileCheck %s -check-prefix=CHECK_SSE2
//; REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
//; CHECK_SSE2: Error: Target specific LLVM intrinsic "avx.addsub.ps.256" not supported
float foo(float a, float b) {
float c = @llvm.x86.avx.addsub.ps.256(a, b);
return c;
}
@@ -0,0 +1,19 @@
// This test checks that AMX FP16 (amxfp16) intrinsics are correctly handled by ISPC
// RUN: not %{ispc} --nowrap %s --target=avx512spr-x4 --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_SPR_ERROR
// RUN: %{ispc} --nowrap %s --target=avx512spr-x4 --cpu=gnr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_GNR_SUCCESS
// RUN: %{ispc} --nowrap %s --target=avx10.2dmr-x4 --cpu=dmr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_DMR_SUCCESS
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --cpu=nvl --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_SPR_ERROR: Target specific LLVM intrinsic "tdpfp16ps" requires feature "amxfp16" not supported on "sapphirerapids" CPU
// CHECK_GNR_SUCCESS: call void @llvm.x86.tdpfp16ps
// CHECK_DMR_SUCCESS: call void @llvm.x86.tdpfp16ps
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tdpfp16ps" requires feature "amxfp16" not supported on "novalake" CPU
__attribute__((external_only))
export void test_amx_fp16() {
// require amxfp16 feature (GNR+)
@llvm.x86.tdpfp16ps((uniform int8)2, (uniform int8)0, (uniform int8)1);
}
@@ -0,0 +1,37 @@
// This test checks that AMX INT8 (amxint8) intrinsics are correctly handled by ISPC
// RUN: %{ispc} --nowrap %s --target=avx512spr-x4 --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_SPR_SUCCESS
// RUN: %{ispc} --nowrap %s --target=avx512spr-x4 --cpu=gnr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_GNR_SUCCESS
// RUN: %{ispc} --nowrap %s --target=avx10.2dmr-x4 --cpu=dmr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_DMR_SUCCESS
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --cpu=nvl --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_SPR_SUCCESS: call void @llvm.x86.tdpbssd
// CHECK_SPR_SUCCESS: call void @llvm.x86.tdpbsud
// CHECK_SPR_SUCCESS: call void @llvm.x86.tdpbusd
// CHECK_SPR_SUCCESS: call void @llvm.x86.tdpbuud
// CHECK_GNR_SUCCESS: call void @llvm.x86.tdpbssd
// CHECK_GNR_SUCCESS: call void @llvm.x86.tdpbsud
// CHECK_GNR_SUCCESS: call void @llvm.x86.tdpbusd
// CHECK_GNR_SUCCESS: call void @llvm.x86.tdpbuud
// CHECK_DMR_SUCCESS: call void @llvm.x86.tdpbssd
// CHECK_DMR_SUCCESS: call void @llvm.x86.tdpbsud
// CHECK_DMR_SUCCESS: call void @llvm.x86.tdpbusd
// CHECK_DMR_SUCCESS: call void @llvm.x86.tdpbuud
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tdpbssd" requires feature "amxint8" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tdpbsud" requires feature "amxint8" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tdpbusd" requires feature "amxint8" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tdpbuud" requires feature "amxint8" not supported on "novalake" CPU
__attribute__((external_only))
export void test_amx_int8() {
// require amxint8 feature (SPR+)
@llvm.x86.tdpbssd((uniform int8)2, (uniform int8)0, (uniform int8)1);
@llvm.x86.tdpbsud((uniform int8)2, (uniform int8)0, (uniform int8)1);
@llvm.x86.tdpbusd((uniform int8)2, (uniform int8)0, (uniform int8)1);
@llvm.x86.tdpbuud((uniform int8)2, (uniform int8)0, (uniform int8)1);
}
@@ -0,0 +1,52 @@
// This test checks that AMX tile (amxtile) intrinsics are correctly handled by ISPC
// RUN: %{ispc} --nowrap %s --target=avx512spr-x4 --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_SPR_SUCCESS
// RUN: %{ispc} --nowrap %s --target=avx512spr-x4 --cpu=gnr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_GNR_SUCCESS
// RUN: %{ispc} --nowrap %s --target=avx10.2dmr-x4 --cpu=dmr --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_DMR_SUCCESS
// RUN: not %{ispc} --nowrap %s --target=avx10.2nvl-x4 --cpu=nvl --enable-llvm-intrinsics --emit-llvm-text -O2 -o - 2>&1 | FileCheck %s -check-prefix=CHECK_NVL_ERROR
// REQUIRES: X86_ENABLED && LLVM_22_0+ && !MACOS_HOST
// CHECK_SPR_SUCCESS: call void @llvm.x86.ldtilecfg
// CHECK_SPR_SUCCESS: call void @llvm.x86.sttilecfg
// CHECK_SPR_SUCCESS: call void @llvm.x86.tilezero
// CHECK_SPR_SUCCESS: call void @llvm.x86.tileloadd64
// CHECK_SPR_SUCCESS: call void @llvm.x86.tileloaddt164
// CHECK_SPR_SUCCESS: call void @llvm.x86.tilestored64
// CHECK_SPR_SUCCESS: call void @llvm.x86.tilerelease
// CHECK_GNR_SUCCESS: call void @llvm.x86.ldtilecfg
// CHECK_GNR_SUCCESS: call void @llvm.x86.sttilecfg
// CHECK_GNR_SUCCESS: call void @llvm.x86.tilezero
// CHECK_GNR_SUCCESS: call void @llvm.x86.tileloadd64
// CHECK_GNR_SUCCESS: call void @llvm.x86.tileloaddt164
// CHECK_GNR_SUCCESS: call void @llvm.x86.tilestored64
// CHECK_GNR_SUCCESS: call void @llvm.x86.tilerelease
// CHECK_DMR_SUCCESS: call void @llvm.x86.ldtilecfg
// CHECK_DMR_SUCCESS: call void @llvm.x86.sttilecfg
// CHECK_DMR_SUCCESS: call void @llvm.x86.tilezero
// CHECK_DMR_SUCCESS: call void @llvm.x86.tileloadd64
// CHECK_DMR_SUCCESS: call void @llvm.x86.tileloaddt164
// CHECK_DMR_SUCCESS: call void @llvm.x86.tilestored64
// CHECK_DMR_SUCCESS: call void @llvm.x86.tilerelease
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "ldtilecfg" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "sttilecfg" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tilezero" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tileloadd64" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tileloaddt164" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tilestored64" requires feature "amxtile" not supported on "novalake" CPU
// CHECK_NVL_ERROR: Target specific LLVM intrinsic "tilerelease" requires feature "amxtile" not supported on "novalake" CPU
__attribute__((external_only))
export void test_amx_tile(uniform int8* uniform config, uniform int8* uniform data) {
// Base AMX tile operations - require amxtile feature
@llvm.x86.ldtilecfg(config);
@llvm.x86.sttilecfg(config);
@llvm.x86.tilezero((uniform int8)2);
@llvm.x86.tileloadd64((uniform int8)0, data, (uniform int64)64);
@llvm.x86.tileloaddt164((uniform int8)1, data, (uniform int64)64);
@llvm.x86.tilestored64((uniform int8)0, data, (uniform int64)64);
@llvm.x86.tilerelease();
}
@@ -0,0 +1,15 @@
// The test checks that target definitions for AVX10.2 NVL are not accepted on macOS.
//; RUN: not %{ispc} %s -o %t.o --nostdlib --target-os=macos --arch=x86-64 --nowrap --target=avx10.2nvl-x4 2>&1 | FileCheck %s
//; RUN: not %{ispc} %s -o %t.o --nostdlib --target-os=macos --arch=x86-64 --nowrap --target=avx10.2nvl-x8 2>&1 | FileCheck %s
//; RUN: not %{ispc} %s -o %t.o --nostdlib --target-os=macos --arch=x86-64 --nowrap --target=avx10.2nvl-x16 2>&1 | FileCheck %s
//; RUN: not %{ispc} %s -o %t.o --nostdlib --target-os=macos --arch=x86-64 --nowrap --target=avx10.2nvl-x32 2>&1 | FileCheck %s
//; RUN: not %{ispc} %s -o %t.o --nostdlib --target-os=macos --arch=x86-64 --nowrap --target=avx10.2nvl-x64 2>&1 | FileCheck %s
// REQUIRES: X86_ENABLED && MACOS_HOST && LLVM_22_0+
// CHECK: Error: avx10.2nvl-x{{.*}} target for x86-64 on macOS is not supported in current build.
uniform int j;
int foo(int i) { return i + 1; }
@@ -0,0 +1,14 @@
// The test checks that avx10.2nvl-x* targets are not recognized before LLVM 22.
// RUN: not %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x4 2>&1 | FileCheck %s
// RUN: not %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x8 2>&1 | FileCheck %s
// RUN: not %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x16 2>&1 | FileCheck %s
// RUN: not %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x32 2>&1 | FileCheck %s
// RUN: not %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x64 2>&1 | FileCheck %s
// REQUIRES: X86_ENABLED && !MACOS_HOST && LLVM_20_0+ && !LLVM_22_0+
// CHECK: Error: Incorrect targets: avx10.2nvl
uniform int j;
int foo(int i) { return i + 1; }
@@ -0,0 +1,13 @@
// The test checks that target definitions (including all synonyms) are successfully consumed by compiler.
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x4
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x8
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x16
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x32
//; RUN: %{ispc} %s -o %t.o --nostdlib --target=avx10.2nvl-x64
// REQUIRES: X86_ENABLED && !MACOS_HOST && LLVM_22_0+
uniform int j;
int foo(int i) { return i + 1; }
+1 -1
View File
@@ -12,7 +12,7 @@
// CHECK_XMM: vpdpbssd {{.*}} %xmm
// CHECK_YMM: vpdpbssd {{.*}} %ymm
// CHECK_ZMM: vpdpbssd {{.*}} %zmm
// CEHCK_ZMMX2-COUNT-2: vpdpbssd {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpbssd {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpbssd {{.*}} %zmm
unmasked void dot4add_i8i8(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot4add_i8i8packed(a[programIndex], b[programIndex], programIndex);
@@ -0,0 +1,89 @@
// Test checks emitted code for VNNI dot product instructions.
// RUN: %{ispc} %s --target=avx10.2nvl-x4 --emit-asm -o - | FileCheck %s -check-prefixes=CHECK_ALL,CHECK_XMM
// RUN: %{ispc} %s --target=avx10.2nvl-x8 --emit-asm -o - | FileCheck %s -check-prefixes=CHECK_ALL,CHECK_YMM
// RUN: %{ispc} %s --target=avx10.2nvl-x16 --emit-asm -o - | FileCheck %s -check-prefixes=CHECK_ALL,CHECK_ZMM
// RUN: %{ispc} %s --target=avx10.2nvl-x32 --emit-asm -o - | FileCheck %s -check-prefixes=CHECK_ALL,CHECK_ZMMX2
// RUN: %{ispc} %s --target=avx10.2nvl-x64 --emit-asm -o - | FileCheck %s -check-prefixes=CHECK_ALL,CHECK_ZMMX4
// REQUIRES: X86_ENABLED && !MACOS_HOST && LLVM_22_0+
// CHECK_ALL-LABEL: dot4add_i8i8
// CHECK_XMM: vpdpbssd {{.*}} %xmm
// CHECK_YMM: vpdpbssd {{.*}} %ymm
// CHECK_ZMM: vpdpbssd {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpbssd {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpbssd {{.*}} %zmm
unmasked void dot4add_i8i8(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot4add_i8i8packed(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot4add_i8i8_sat
// CHECK_XMM: vpdpbssds {{.*}} %xmm
// CHECK_YMM: vpdpbssds {{.*}} %ymm
// CHECK_ZMM: vpdpbssds {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpbssds {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpbssds {{.*}} %zmm
unmasked void dot4add_i8i8_sat(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot4add_i8i8packed_sat(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot4add_u8u8
// CHECK_XMM: vpdpbuud {{.*}} %xmm
// CHECK_YMM: vpdpbuud {{.*}} %ymm
// CHECK_ZMM: vpdpbuud {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpbuud {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpbuud {{.*}} %zmm
unmasked void dot4add_u8u8(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot4add_u8u8packed(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot4add_u8u8_sat
// CHECK_XMM: vpdpbuuds {{.*}} %xmm
// CHECK_YMM: vpdpbuuds {{.*}} %ymm
// CHECK_ZMM: vpdpbuuds {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpbuuds {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpbuuds {{.*}} %zmm
unmasked void dot4add_u8u8_sat(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot4add_u8u8packed_sat(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot2add_u16u16
// CHECK_XMM: vpdpwuud {{.*}} %xmm
// CHECK_YMM: vpdpwuud {{.*}} %ymm
// CHECK_ZMM: vpdpwuud {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpwuud {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpwuud {{.*}} %zmm
unmasked void dot2add_u16u16(uniform uint a[], uniform uint b[], uniform uint dst[]) {
dst[programIndex] = dot2add_u16u16packed(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot2add_u16u16_sat
// CHECK_XMM: vpdpwuuds {{.*}} %xmm
// CHECK_YMM: vpdpwuuds {{.*}} %ymm
// CHECK_ZMM: vpdpwuuds {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpwuuds {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpwuuds {{.*}} %zmm
unmasked void dot2add_u16u16_sat(uniform uint a[], uniform uint b[], uniform uint dst[]) {
dst[programIndex] = dot2add_u16u16packed_sat(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot2add_u16i16
// CHECK_XMM: vpdpwusd {{.*}} %xmm
// CHECK_YMM: vpdpwusd {{.*}} %ymm
// CHECK_ZMM: vpdpwusd {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpwusd {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpwusd {{.*}} %zmm
unmasked void dot2add_u16i16(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot2add_u16i16packed(a[programIndex], b[programIndex], programIndex);
}
// CHECK_ALL-LABEL: dot2add_u16i16_sat
// CHECK_XMM: vpdpwusds {{.*}} %xmm
// CHECK_YMM: vpdpwusds {{.*}} %ymm
// CHECK_ZMM: vpdpwusds {{.*}} %zmm
// CHECK_ZMMX2-COUNT-2: vpdpwusds {{.*}} %zmm
// CHECK_ZMMX4-COUNT-4: vpdpwusds {{.*}} %zmm
unmasked void dot2add_u16i16_sat(uniform uint a[], uniform uint b[], uniform int dst[]) {
dst[programIndex] = dot2add_u16i16packed_sat(a[programIndex], b[programIndex], programIndex);
}
+3 -1
View File
@@ -48,6 +48,7 @@ const char *const isa_strings[] = {
"ICL",
"SPR",
"GNR",
"NVL",
"DMR",
};
@@ -61,7 +62,8 @@ static const char *lGetSystemISA() {
return "Unknown x86 ISA";
}
const char *isa = isa_strings[isa_id];
if (isa_id >= SPR_AVX512) {
// Only show AMX status for AMX-capable ISAs (SPR, GNR, DMR - not NVL)
if (isa_id == SPR_AVX512 || isa_id == GNR_AVX512 || isa_id == DMR_AVX10_2) {
snprintf(amx_isa_string, sizeof(amx_isa_string), "%s (AMX %s)", isa,
__os_enabled_amx_support() ? "on" : "off");
return amx_isa_string;