Skip to content

Commit 1d13258

Browse files
committed
Refactor cpu_model support to reduce #if nesting. NFCI
Reviewers: petrhosek, DavidSpickett Pull Request: llvm#75635
1 parent 37ecec1 commit 1d13258

File tree

15 files changed

+793
-595
lines changed

15 files changed

+793
-595
lines changed

compiler-rt/lib/builtins/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ endif()
266266

267267
# These files are used on 32-bit and 64-bit x86.
268268
set(x86_ARCH_SOURCES
269-
cpu_model.c
269+
cpu_model/x86.c
270270
)
271271

272272
if (NOT MSVC)
@@ -551,7 +551,7 @@ endif()
551551
set(aarch64_SOURCES
552552
${GENERIC_TF_SOURCES}
553553
${GENERIC_SOURCES}
554-
cpu_model.c
554+
cpu_model/aarch64.c
555555
aarch64/fp_mode.c
556556
)
557557

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
//===-- cpu_model/aarch64.c - Support for __cpu_model builtin ----*- C -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is based on LLVM's lib/Support/Host.cpp.
10+
// It implements __aarch64_have_lse_atomics, __aarch64_cpu_features for
11+
// AArch64.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "cpu_model.h"
16+
17+
#if !defined(__aarch64__)
18+
#error This file is intended only for aarch64-based targets
19+
#endif
20+
21+
#if __has_include(<sys/ifunc.h>)
22+
#include <sys/ifunc.h>
23+
#else
24+
typedef struct __ifunc_arg_t {
25+
unsigned long _size;
26+
unsigned long _hwcap;
27+
unsigned long _hwcap2;
28+
} __ifunc_arg_t;
29+
#endif // __has_include(<sys/ifunc.h>)
30+
31+
// LSE support detection for out-of-line atomics
32+
// using HWCAP and Auxiliary vector
33+
_Bool __aarch64_have_lse_atomics
34+
__attribute__((visibility("hidden"), nocommon)) = false;
35+
36+
#if defined(__FreeBSD__)
37+
// clang-format off: should not reorder sys/auxv.h alphabetically
38+
#include <sys/auxv.h>
39+
// clang-format on
40+
#include "aarch64/hwcap.inc"
41+
#include "aarch64/lse_atomics/freebsd.inc"
42+
#elif defined(__Fuchsia__)
43+
#include "aarch64/hwcap.inc"
44+
#include "aarch64/lse_atomics/fuchsia.inc"
45+
#elif defined(__ANDROID__)
46+
#include "aarch64/hwcap.inc"
47+
#include "aarch64/lse_atomics/android.inc"
48+
#elif __has_include(<sys/auxv.h>)
49+
#include "aarch64/hwcap.inc"
50+
#include "aarch64/lse_atomics/sysauxv.inc"
51+
#else
52+
// When unimplemented, we leave __aarch64_have_lse_atomics initialized to false.
53+
#endif
54+
55+
#if !defined(DISABLE_AARCH64_FMV)
56+
// CPUFeatures must correspond to the same AArch64 features in
57+
// AArch64TargetParser.h
58+
enum CPUFeatures {
59+
FEAT_RNG,
60+
FEAT_FLAGM,
61+
FEAT_FLAGM2,
62+
FEAT_FP16FML,
63+
FEAT_DOTPROD,
64+
FEAT_SM4,
65+
FEAT_RDM,
66+
FEAT_LSE,
67+
FEAT_FP,
68+
FEAT_SIMD,
69+
FEAT_CRC,
70+
FEAT_SHA1,
71+
FEAT_SHA2,
72+
FEAT_SHA3,
73+
FEAT_AES,
74+
FEAT_PMULL,
75+
FEAT_FP16,
76+
FEAT_DIT,
77+
FEAT_DPB,
78+
FEAT_DPB2,
79+
FEAT_JSCVT,
80+
FEAT_FCMA,
81+
FEAT_RCPC,
82+
FEAT_RCPC2,
83+
FEAT_FRINTTS,
84+
FEAT_DGH,
85+
FEAT_I8MM,
86+
FEAT_BF16,
87+
FEAT_EBF16,
88+
FEAT_RPRES,
89+
FEAT_SVE,
90+
FEAT_SVE_BF16,
91+
FEAT_SVE_EBF16,
92+
FEAT_SVE_I8MM,
93+
FEAT_SVE_F32MM,
94+
FEAT_SVE_F64MM,
95+
FEAT_SVE2,
96+
FEAT_SVE_AES,
97+
FEAT_SVE_PMULL128,
98+
FEAT_SVE_BITPERM,
99+
FEAT_SVE_SHA3,
100+
FEAT_SVE_SM4,
101+
FEAT_SME,
102+
FEAT_MEMTAG,
103+
FEAT_MEMTAG2,
104+
FEAT_MEMTAG3,
105+
FEAT_SB,
106+
FEAT_PREDRES,
107+
FEAT_SSBS,
108+
FEAT_SSBS2,
109+
FEAT_BTI,
110+
FEAT_LS64,
111+
FEAT_LS64_V,
112+
FEAT_LS64_ACCDATA,
113+
FEAT_WFXT,
114+
FEAT_SME_F64,
115+
FEAT_SME_I64,
116+
FEAT_SME2,
117+
FEAT_RCPC3,
118+
FEAT_MAX,
119+
FEAT_EXT = 62, // Reserved to indicate presence of additional features field
120+
// in __aarch64_cpu_features
121+
FEAT_INIT // Used as flag of features initialization completion
122+
};
123+
124+
// Architecture features used
125+
// in Function Multi Versioning
126+
struct {
127+
unsigned long long features;
128+
// As features grows new fields could be added
129+
} __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon));
130+
131+
// The formatter wants to re-order these includes, but doing so is incorrect:
132+
// clang-format off
133+
#if defined(__FreeBSD__)
134+
#include "aarch64/fmv/mrs.inc"
135+
#include "aarch64/fmv/freebsd.inc"
136+
#elif defined(__Fuchsia__)
137+
#include "aarch64/fmv/fuchsia.inc"
138+
#elif defined(__ANDROID__)
139+
#include "aarch64/fmv/mrs.inc"
140+
#include "aarch64/fmv/android.inc"
141+
#elif __has_include(<sys/auxv.h>)
142+
#include "aarch64/fmv/mrs.inc"
143+
#include "aarch64/fmv/sysauxv.inc"
144+
#else
145+
#include "aarch64/fmv/unimplemented.inc"
146+
#endif
147+
// clang-format on
148+
149+
#endif // !defined(DISABLE_AARCH64_FMV)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
void __init_cpu_features_resolver(unsigned long hwcap,
2+
const __ifunc_arg_t *arg) {
3+
if (__aarch64_cpu_features.features)
4+
return;
5+
6+
// ifunc resolvers don't have hwcaps in arguments on Android API lower
7+
// than 30. If so, set feature detection done and keep all CPU features
8+
// unsupported (zeros). To detect this case in runtime we check existence
9+
// of memfd_create function from Standard C library which was introduced in
10+
// Android API 30.
11+
int memfd_create(const char *, unsigned int) __attribute__((weak));
12+
if (!memfd_create)
13+
return;
14+
15+
__init_cpu_features_constructor(hwcap, arg);
16+
}
17+
18+
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
19+
// CPU features already initialized.
20+
if (__aarch64_cpu_features.features)
21+
return;
22+
23+
// Don't set any CPU features,
24+
// detection could be wrong on Exynos 9810.
25+
if (__isExynos9810())
26+
return;
27+
28+
unsigned long hwcap = getauxval(AT_HWCAP);
29+
unsigned long hwcap2 = getauxval(AT_HWCAP2);
30+
31+
__ifunc_arg_t arg;
32+
arg._size = sizeof(__ifunc_arg_t);
33+
arg._hwcap = hwcap;
34+
arg._hwcap2 = hwcap2;
35+
__init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg);
36+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
void __init_cpu_features_resolver(unsigned long hwcap,
2+
const __ifunc_arg_t *arg) {
3+
if (__aarch64_cpu_features.features)
4+
return;
5+
6+
__init_cpu_features_constructor(hwcap, arg);
7+
}
8+
9+
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
10+
unsigned long hwcap = 0;
11+
unsigned long hwcap2 = 0;
12+
// CPU features already initialized.
13+
if (__aarch64_cpu_features.features)
14+
return;
15+
16+
int res = 0;
17+
res = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap);
18+
res |= elf_aux_info(AT_HWCAP2, &hwcap2, sizeof hwcap2);
19+
if (res)
20+
return;
21+
22+
__ifunc_arg_t arg;
23+
arg._size = sizeof(__ifunc_arg_t);
24+
arg._hwcap = hwcap;
25+
arg._hwcap2 = hwcap2;
26+
__init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg);
27+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include <zircon/features.h>
2+
#include <zircon/syscalls.h>
3+
4+
void __init_cpu_features_resolver() {
5+
if (__aarch64_cpu_features.features)
6+
return;
7+
8+
// This ensures the vDSO is a direct link-time dependency of anything that
9+
// needs this initializer code.
10+
#pragma comment(lib, "zircon")
11+
uint32_t features;
12+
zx_status_t status = _zx_system_get_features(ZX_FEATURE_KIND_CPU, &features);
13+
if (status != ZX_OK)
14+
return;
15+
16+
#define setCPUFeature(cpu_feature) \
17+
__aarch64_cpu_features.features |= 1ULL << cpu_feature
18+
19+
if (features & ZX_ARM64_FEATURE_ISA_FP)
20+
setCPUFeature(FEAT_FP);
21+
if (features & ZX_ARM64_FEATURE_ISA_ASIMD)
22+
setCPUFeature(FEAT_SIMD);
23+
if (features & ZX_ARM64_FEATURE_ISA_AES)
24+
setCPUFeature(FEAT_AES);
25+
if (features & ZX_ARM64_FEATURE_ISA_PMULL)
26+
setCPUFeature(FEAT_PMULL);
27+
if (features & ZX_ARM64_FEATURE_ISA_SHA1)
28+
setCPUFeature(FEAT_SHA1);
29+
if (features & ZX_ARM64_FEATURE_ISA_SHA256)
30+
setCPUFeature(FEAT_SHA2);
31+
if (features & ZX_ARM64_FEATURE_ISA_CRC32)
32+
setCPUFeature(FEAT_CRC);
33+
if (features & ZX_ARM64_FEATURE_ISA_RDM)
34+
setCPUFeature(FEAT_RDM);
35+
if (features & ZX_ARM64_FEATURE_ISA_SHA3)
36+
setCPUFeature(FEAT_SHA3);
37+
if (features & ZX_ARM64_FEATURE_ISA_SM4)
38+
setCPUFeature(FEAT_SM4);
39+
if (features & ZX_ARM64_FEATURE_ISA_DP)
40+
setCPUFeature(FEAT_DOTPROD);
41+
if (features & ZX_ARM64_FEATURE_ISA_FHM)
42+
setCPUFeature(FEAT_FP16FML);
43+
if (features & ZX_ARM64_FEATURE_ISA_SHA512)
44+
setCPUFeature(FEAT_SHA3);
45+
if (features & ZX_ARM64_FEATURE_ISA_I8MM)
46+
setCPUFeature(FEAT_I8MM);
47+
if (features & ZX_ARM64_FEATURE_ISA_SVE)
48+
setCPUFeature(FEAT_SVE);
49+
50+
setCPUFeature(FEAT_INIT);
51+
}

0 commit comments

Comments
 (0)