xref: /aosp_15_r20/external/XNNPACK/tools/xnncommon.py (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1#!/usr/bin/env python
2# Copyright 2019 Google LLC
3#
4# This source code is licensed under the BSD-style license found in the
5# LICENSE file in the root directory of this source tree.
6
7
8def _indent(text):
9  return "\n".join(map(lambda t: "  " + t if t else t, text.splitlines()))
10
11
12def _remove_duplicate_newlines(text):
13  filtered_lines = list()
14  last_newline = False
15  for line in text.splitlines():
16    is_newline = len(line.strip()) == 0
17    if not is_newline or not last_newline:
18      filtered_lines.append(line)
19    last_newline = is_newline
20  return "\n".join(filtered_lines)
21
22
23_ARCH_TO_MACRO_MAP = {
24  "aarch32": "XNN_ARCH_ARM",
25  "aarch64": "XNN_ARCH_ARM64",
26  "x86-32": "XNN_ARCH_X86",
27  "x86-64": "XNN_ARCH_X86_64",
28  "wasm": "XNN_ARCH_WASM",
29  "wasmsimd": "XNN_ARCH_WASMSIMD",
30  "wasmrelaxedsimd": "XNN_ARCH_WASMRELAXEDSIMD",
31}
32
33# Mapping from ISA extension to macro guarding build-time enabled/disabled
34# status for the ISA. Only ISAs that can be enabled/disabled have an entry.
35_ISA_TO_MACRO_MAP = {
36  "neonfp16arith": "XNN_ENABLE_ARM_FP16",
37  "neonbf16": "XNN_ENABLE_ARM_BF16",
38  "neondot": "XNN_ENABLE_ARM_DOTPROD",
39}
40
41_ISA_TO_ARCH_MAP = {
42  "armsimd32": ["aarch32"],
43  "neon": ["aarch32", "aarch64"],
44  "neonfp16": ["aarch32", "aarch64"],
45  "neonfma": ["aarch32", "aarch64"],
46  "neonv8": ["aarch32", "aarch64"],
47  "neonfp16arith": ["aarch32", "aarch64"],
48  "neonbf16": ["aarch32", "aarch64"],
49  "neondot": ["aarch32", "aarch64"],
50  "sse": ["x86-32", "x86-64"],
51  "sse2": ["x86-32", "x86-64"],
52  "ssse3": ["x86-32", "x86-64"],
53  "sse41": ["x86-32", "x86-64"],
54  "avx": ["x86-32", "x86-64"],
55  "f16c": ["x86-32", "x86-64"],
56  "xop": ["x86-32", "x86-64"],
57  "fma3": ["x86-32", "x86-64"],
58  "avx2": ["x86-32", "x86-64"],
59  "avx512f": ["x86-32", "x86-64"],
60  "avx512skx": ["x86-32", "x86-64"],
61  "wasm32": ["wasm", "wasmsimd"],
62  "wasm": ["wasm", "wasmsimd", "wasmrelaxedsimd"],
63  "wasmsimd": ["wasmsimd", "wasmrelaxedsimd"],
64  "wasmrelaxedsimd": ["wasmrelaxedsimd"],
65}
66
67_ISA_TO_CHECK_MAP = {
68  "armsimd32": "TEST_REQUIRES_ARM_SIMD32",
69  "neon": "TEST_REQUIRES_ARM_NEON",
70  "neonfp16": "TEST_REQUIRES_ARM_NEON_FP16",
71  "neonfma": "TEST_REQUIRES_ARM_NEON_FMA",
72  "neonv8": "TEST_REQUIRES_ARM_NEON_V8",
73  "neonfp16arith": "TEST_REQUIRES_ARM_NEON_FP16_ARITH",
74  "neonbf16": "TEST_REQUIRES_ARM_NEON_BF16",
75  "neondot": "TEST_REQUIRES_ARM_NEON_DOT",
76  "sse": "TEST_REQUIRES_X86_SSE",
77  "sse2": "TEST_REQUIRES_X86_SSE2",
78  "ssse3": "TEST_REQUIRES_X86_SSSE3",
79  "sse41": "TEST_REQUIRES_X86_SSE41",
80  "avx": "TEST_REQUIRES_X86_AVX",
81  "f16c": "TEST_REQUIRES_X86_F16C",
82  "xop": "TEST_REQUIRES_X86_XOP",
83  "avx2": "TEST_REQUIRES_X86_AVX2",
84  "fma3": "TEST_REQUIRES_X86_FMA3",
85  "avx512f": "TEST_REQUIRES_X86_AVX512F",
86  "avx512skx": "TEST_REQUIRES_X86_AVX512SKX",
87}
88
89
90def parse_target_name(target_name):
91  arch = list()
92  isa = None
93  for target_part in target_name.split("_"):
94    if target_part in _ARCH_TO_MACRO_MAP:
95      if target_part in _ISA_TO_ARCH_MAP:
96        arch = _ISA_TO_ARCH_MAP[target_part]
97        isa = target_part
98      else:
99        arch = [target_part]
100    elif target_part in _ISA_TO_ARCH_MAP:
101      isa = target_part
102  if isa and not arch:
103    arch = _ISA_TO_ARCH_MAP[isa]
104
105  return arch, isa
106
107
108def generate_isa_check_macro(isa):
109  return _ISA_TO_CHECK_MAP.get(isa, "")
110
111
112def arch_to_macro(arch, isa):
113  if arch == "aarch32" and isa == "neondot":
114    return _ARCH_TO_MACRO_MAP[arch] + " && !XNN_PLATFORM_IOS"
115  else:
116    return _ARCH_TO_MACRO_MAP[arch]
117
118
119def postprocess_test_case(test_case, arch, isa, assembly=False, jit=False):
120  test_case = _remove_duplicate_newlines(test_case)
121  if arch:
122    guard = " || ".join(arch_to_macro(a, isa) for a in arch)
123    if isa in _ISA_TO_MACRO_MAP:
124      if len(arch) > 1:
125        guard = "%s && (%s)" % (_ISA_TO_MACRO_MAP[isa], guard)
126      else:
127        guard = "%s && %s" % (_ISA_TO_MACRO_MAP[isa], guard)
128    if assembly:
129      guard += " && XNN_ENABLE_ASSEMBLY"
130    if jit:
131      guard += " && XNN_PLATFORM_JIT"
132    return "#if %s\n" % guard + _indent(test_case) + "\n" + \
133      "#endif  // %s\n" % guard
134  else:
135    return test_case
136