Skip to content

Commit 7e0da36

Browse files
committed
[Target][CI] Add LLVM functions for current system info
1 parent a79f632 commit 7e0da36

File tree

11 files changed

+128
-83
lines changed

11 files changed

+128
-83
lines changed

python/tvm/target/codegen.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,48 @@ def llvm_get_intrinsic_name(intrin_id: int) -> str:
9696
return _ffi_api.llvm_get_intrinsic_name(intrin_id)
9797

9898

99+
def llvm_get_system_x86_vendor():
100+
"""Get system x86 vendor info.
101+
102+
Parameters
103+
----------
104+
105+
Returns
106+
-------
107+
vendor : str
108+
The current system's cpu vendor.
109+
"""
110+
return _ffi_api.llvm_get_system_x86_vendor()
111+
112+
113+
def llvm_get_system_triple():
114+
"""Get system host triple.
115+
116+
Parameters
117+
----------
118+
119+
Returns
120+
-------
121+
triple : str
122+
The current system's triple.
123+
"""
124+
return _ffi_api.llvm_get_system_triple()
125+
126+
127+
def llvm_get_system_cpu():
128+
"""Get system host cpu name.
129+
130+
Parameters
131+
----------
132+
133+
Returns
134+
-------
135+
cpu_name : str
136+
The current system's cpu name.
137+
"""
138+
return _ffi_api.llvm_get_system_cpu()
139+
140+
99141
def llvm_get_targets():
100142
"""Get LLVM target list.
101143

python/tvm/testing/utils.py

Lines changed: 28 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def test_something():
7777
import textwrap
7878
import time
7979
import shutil
80-
import subprocess
8180

8281
from pathlib import Path
8382
from typing import Optional, Callable, Union, List, Tuple
@@ -91,6 +90,7 @@ def test_something():
9190
import tvm.te
9291
import tvm._ffi
9392

93+
from tvm.target import codegen
9494
from tvm.contrib import nvcc, cudnn, rocm
9595
import tvm.contrib.hexagon._ci_env_check as hexagon
9696
from tvm.driver.tvmc.frontends import load_model
@@ -1002,76 +1002,43 @@ def _corstone300_compile_time_check():
10021002
requires_vitis_ai = Feature("vitis_ai", "Vitis AI", cmake_flag="USE_VITIS_AI")
10031003

10041004

1005-
def _arm_dot_supported():
1006-
arch = platform.machine()
1005+
# check cpu features
1006+
def _has_cpu_feat(features):
1007+
cpu = codegen.llvm_get_system_cpu()
1008+
triple = codegen.llvm_get_system_triple()
1009+
target = "llvm -mtriple=%s -mcpu=%s" % (triple, cpu)
1010+
has_feat = codegen.target_has_features(features, tvm.target.Target(target))
10071011

1008-
if arch not in ["arm64", "aarch64"]:
1009-
return False
1012+
return has_feat
10101013

1011-
if sys.platform.startswith("darwin"):
1012-
cpu_info = subprocess.check_output("sysctl -a", shell=True).strip().decode()
1013-
for line in cpu_info.split("\n"):
1014-
if line.startswith("hw.optional.arm.FEAT_DotProd"):
1015-
return bool(int(line.split(":", 1)[1]))
1016-
elif sys.platform.startswith("linux"):
1017-
return True
10181014

1019-
return False
1020-
1021-
1022-
def _is_intel():
1023-
# Only linux is supported for now.
1024-
if sys.platform.startswith("linux"):
1025-
with open("/proc/cpuinfo", "r") as content:
1026-
return "Intel" in content.read()
1027-
1028-
return False
1029-
1030-
1031-
def _has_vnni():
1032-
arch = platform.machine()
1033-
# Only linux is supported for now.
1034-
if arch == "x86_64" and sys.platform.startswith("linux"):
1035-
with open("/proc/cpuinfo", "r") as content:
1036-
return "avx512_vnni" in content.read()
1037-
1038-
return False
1039-
1040-
1041-
# check avx512 intrinsic groups for SkyLake X
1042-
def _has_slavx512():
1043-
# Check LLVM support
1044-
llvm_version = tvm.target.codegen.llvm_version_major()
1045-
is_llvm_support = llvm_version >= 8
1046-
arch = platform.machine()
1047-
# Only linux is supported for now.
1048-
if arch == "x86_64" and sys.platform.startswith("linux"):
1049-
with open("/proc/cpuinfo", "r") as content:
1050-
ctx = content.read()
1051-
check = (
1052-
"avx512f" in ctx
1053-
and "avx512cd" in ctx
1054-
and "avx512bw" in ctx
1055-
and "avx512dq" in ctx
1056-
and "avx512vl" in ctx
1057-
)
1058-
return check and is_llvm_support
1059-
1060-
return False
1015+
requires_arm_dot = Feature(
1016+
"arm_dot",
1017+
"ARM dot product",
1018+
run_time_check=lambda: _has_cpu_feat("dotprod"),
1019+
)
10611020

10621021

1063-
requires_arm_dot = Feature("arm_dot", "ARM dot product", run_time_check=_arm_dot_supported)
1022+
requires_x86_vnni = Feature(
1023+
"x86_vnni",
1024+
"x86 VNNI Extensions",
1025+
run_time_check=lambda: (_has_cpu_feat("avx512vnni") or _has_cpu_feat("avxvnni")),
1026+
)
10641027

10651028

1066-
requires_cascadelake = Feature(
1067-
"cascadelake", "x86 CascadeLake", run_time_check=lambda: _has_vnni() and _is_intel()
1029+
requires_x86_avx512 = Feature(
1030+
"x86_avx512",
1031+
"x86 AVX512 Extensions",
1032+
run_time_check=lambda: _has_cpu_feat(
1033+
["avx512bw", "avx512cd", "avx512dq", "avx512vl", "avx512f"]
1034+
),
10681035
)
10691036

10701037

1071-
requires_skylake_avx512 = Feature(
1072-
"skylake_avx512",
1073-
"x86 SkyLake AVX512",
1074-
run_time_check=lambda: _has_slavx512() and _is_intel(),
1038+
requires_x86_amx = Feature(
1039+
"x86_amx",
1040+
"x86 AMX Extensions",
1041+
run_time_check=lambda: _has_cpu_feat("amx-int8"),
10751042
)
10761043

10771044

src/target/llvm/llvm_module.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <llvm/IR/Module.h>
4242
#include <llvm/IRReader/IRReader.h>
4343
#include <llvm/Support/FileSystem.h>
44+
#include <llvm/Support/Host.h>
4445
#include <llvm/Support/SourceMgr.h>
4546
#include <llvm/Support/raw_ostream.h>
4647
#include <llvm/Target/TargetMachine.h>
@@ -485,6 +486,30 @@ TVM_REGISTER_GLOBAL("target.llvm_get_intrinsic_name").set_body_typed([](int64_t
485486
#endif
486487
});
487488

489+
TVM_REGISTER_GLOBAL("target.llvm_get_system_x86_vendor").set_body_typed([]() -> String {
490+
#if TVM_LLVM_VERSION >= 120
491+
#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
492+
using namespace llvm::sys::detail::x86;
493+
const auto x86_sign = getVendorSignature();
494+
if (x86_sign == VendorSignatures::GENUINE_INTEL)
495+
return "intel";
496+
else if (x86_sign == VendorSignatures::AUTHENTIC_AMD)
497+
return "amd";
498+
else if (x86_sign == VendorSignatures::UNKNOWN)
499+
return "unknown";
500+
#endif
501+
#endif
502+
return "unimplemented";
503+
});
504+
505+
TVM_REGISTER_GLOBAL("target.llvm_get_system_triple").set_body_typed([]() -> String {
506+
return llvm::sys::getProcessTriple();
507+
});
508+
509+
TVM_REGISTER_GLOBAL("target.llvm_get_system_cpu").set_body_typed([]() -> String {
510+
return llvm::sys::getHostCPUName().str();
511+
});
512+
488513
TVM_REGISTER_GLOBAL("target.llvm_get_targets").set_body_typed([]() -> Array<String> {
489514
auto llvm_instance = std::make_unique<LLVMInstance>();
490515
LLVMTargetInfo llvm_backend(*llvm_instance, "llvm");

tests/python/contrib/test_amx.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
import pytest
2828

2929

30-
@tvm.testing.requires_llvm
31-
@pytest.mark.skip("skip due to AMX feature not avaliable yet")
30+
has_amx_runtime = pytest.mark.skipif(
31+
not tvm.get_global_func("runtime.amx_init", True), reason="AMX runtime not available"
32+
)
33+
34+
35+
@has_amx_runtime
36+
@tvm.testing.requires_x86_amx
3237
def test_amx_u8s8s32_matmul_tensorize():
3338
m = 1024
3439
k = 1024
@@ -113,8 +118,8 @@ def test_amx_u8s8s32_matmul_tensorize():
113118
tvm.testing.assert_allclose(y.numpy(), np.dot(a.astype("int32"), b.T.astype("int32")), rtol=0)
114119

115120

116-
@tvm.testing.requires_llvm
117-
@pytest.mark.skip("skip due to AMX feature not avaliable yet")
121+
@has_amx_runtime
122+
@tvm.testing.requires_x86_amx
118123
def test_amx_check_support():
119124
amx_init = tvm.get_global_func("runtime.amx_init")
120125
amx_tileconfig = tvm.get_global_func("runtime.amx_tileconfig")

tests/python/contrib/test_gemm_acc32_vnni.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ def verify_fc_int8_acc32(m=1024, n=1024, k=1024, target="llvm -mcpu=cascadelake"
9797
# t_func.export_library("tensorize_acc32.o")
9898

9999

100-
@tvm.testing.requires_cascadelake
100+
@tvm.testing.requires_x86_vnni
101101
def test_fc_int8_acc32_vnni():
102102
# For LLVM < 8.0, it shows "'cascadelake' is not a recognized processor for this target
103103
# (ignoring processor)" error with the following setting. After LLVM 8.0 is enabled in the
104104
# test, we should use cascadelake setting.
105105
verify_fc_int8_acc32()
106106

107107

108-
@tvm.testing.requires_skylake_avx512
108+
@tvm.testing.requires_x86_avx512
109109
def test_fc_int8_acc32_avx512():
110110
verify_fc_int8_acc32(target="llvm -mcpu=skylake-avx512")
111111

tests/python/integration/test_auto_tensorize.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,12 @@ def _test_bert_int8(relay_mod, params, input_info, target, sch_rules, postprocs)
287287
print(runtime.benchmark(dev, number=1, repeat=50).mean)
288288

289289

290-
@tvm.testing.requires_cascadelake
290+
@tvm.testing.requires_x86_vnni
291291
def test_vnni_dense():
292292
_test_dense("uint8", SCH_RULES_FOR_VNNI, POSTPROCS_FOR_VNNI, CASCADELAKE_VNNI_TARGET)
293293

294294

295-
@tvm.testing.requires_skylake_avx512
295+
@tvm.testing.requires_x86_avx512
296296
def test_avx512_dense():
297297
_test_dense("uint8", SCH_RULES_FOR_AVX512, POSTPROCS_FOR_VNNI, SKYLAKE_AVX512_TARGET)
298298

@@ -310,12 +310,12 @@ def test_dp4a_dense():
310310
# )
311311

312312

313-
@tvm.testing.requires_cascadelake
313+
@tvm.testing.requires_x86_vnni
314314
def test_vnni_conv2d():
315315
_test_conv2d("uint8", SCH_RULES_FOR_VNNI, POSTPROCS_FOR_VNNI, CASCADELAKE_VNNI_TARGET)
316316

317317

318-
@tvm.testing.requires_skylake_avx512
318+
@tvm.testing.requires_x86_avx512
319319
def test_avx512_conv2d():
320320
_test_conv2d("uint8", SCH_RULES_FOR_AVX512, POSTPROCS_FOR_VNNI, SKYLAKE_AVX512_TARGET)
321321

@@ -333,7 +333,7 @@ def test_dp4a_conv2d():
333333
# )
334334

335335

336-
@tvm.testing.requires_cascadelake
336+
@tvm.testing.requires_x86_vnni
337337
@pytest.mark.skipif(tvm.testing.IS_IN_CI, reason="Slow on CI")
338338
def test_vnni_bert_int8():
339339
pytest.importorskip("onnx")
@@ -348,7 +348,7 @@ def test_vnni_bert_int8():
348348
)
349349

350350

351-
@tvm.testing.requires_skylake_avx512
351+
@tvm.testing.requires_x86_avx512
352352
@pytest.mark.skip("Due to quantized BERT download issue")
353353
def test_avx512_bert_int8():
354354
relay_mod, params, input_info = load_quantized_bert_base()

tests/python/relay/test_op_level1.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -846,13 +846,13 @@ def test_dense_amx_int8():
846846
np.testing.assert_equal(out, ref)
847847

848848

849-
@tvm.testing.requires_cascadelake
849+
@tvm.testing.requires_x86_vnni
850850
@pytest.mark.parametrize("m,n,k", [(32, 128, 96), (32, 128, 97)])
851851
def test_dense_vnni(m, n, k):
852852
dense_x86_test(m, n, k)
853853

854854

855-
@tvm.testing.requires_skylake_avx512
855+
@tvm.testing.requires_x86_avx512
856856
@pytest.mark.parametrize("m,n,k", [(32, 128, 96), (32, 128, 97)])
857857
def test_dense_skylake_avx512(m, n, k):
858858
dense_x86_test(m, n, k, "llvm -mcpu=skylake-avx512", ["pmaddubs", "pmaddw", "vpaddd"])

tests/python/relay/test_op_level10.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ def test_batch_matmul_amx(b, m, n, k):
568568
np.testing.assert_equal(out, ref)
569569

570570

571-
@tvm.testing.requires_cascadelake
571+
@tvm.testing.requires_x86_vnni
572572
@pytest.mark.parametrize(
573573
"b,m,n,k",
574574
[
@@ -581,7 +581,7 @@ def test_batch_matmul_vnni(b, m, n, k):
581581
batch_matmul_x86_test(b, m, n, k)
582582

583583

584-
@tvm.testing.requires_skylake_avx512
584+
@tvm.testing.requires_x86_avx512
585585
@pytest.mark.parametrize(
586586
"b,m,n,k",
587587
[

tests/python/relay/test_op_level2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,12 +2237,12 @@ def test_conv2d_int8_alter_dtype_arm():
22372237
)
22382238

22392239

2240-
@tvm.testing.requires_cascadelake
2240+
@tvm.testing.requires_x86_vnni
22412241
def test_conv2d_int8_alter_dtype_vnni():
22422242
_test_conv2d_int8_alter_dtype("int8", "llvm -mcpu=cascadelake", ["vpdpbusd"])
22432243

22442244

2245-
@tvm.testing.requires_skylake_avx512
2245+
@tvm.testing.requires_x86_avx512
22462246
def test_conv2d_int8_alter_dtype_avx512():
22472247
_test_conv2d_int8_alter_dtype(
22482248
"int8", "llvm -mcpu=skylake-avx512", ["pmaddubs", "pmaddw", "vpaddd"]

tests/python/target/test_llvm_features_info.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ def test_llvm_targets():
3030

3131
# check blank results
3232
assert len(codegen.llvm_get_targets())
33+
assert len(codegen.llvm_get_system_cpu())
34+
assert len(codegen.llvm_get_system_triple())
35+
assert len(codegen.llvm_get_system_x86_vendor())
3336
# check ffi vs python
37+
assert codegen.llvm_get_system_cpu() == _ffi_api.llvm_get_system_cpu()
38+
assert codegen.llvm_get_system_triple() == _ffi_api.llvm_get_system_triple()
39+
assert codegen.llvm_get_system_x86_vendor() == _ffi_api.llvm_get_system_x86_vendor()
3440
assert str(codegen.llvm_get_targets()) == str(_ffi_api.llvm_get_targets())
3541

3642
# check LLVM target -mcpu legality

0 commit comments

Comments
 (0)