Skip to content

Commit 9237cfa

Browse files
committed
[builtins] Refactor cpu_model support to reduce #if nesting. NFCI
Reviewers: petrhosek, DavidSpickett Pull Request: #75635
1 parent b72e160 commit 9237cfa

File tree

14 files changed

+745
-618
lines changed

14 files changed

+745
-618
lines changed

compiler-rt/lib/builtins/CMakeLists.txt

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

272272
# These files are used on 32-bit and 64-bit x86.
273273
set(x86_ARCH_SOURCES
274-
cpu_model.c
274+
cpu_model/x86.c
275275
)
276276

277277
if (NOT MSVC)
@@ -556,7 +556,7 @@ endif()
556556
set(aarch64_SOURCES
557557
${GENERIC_TF_SOURCES}
558558
${GENERIC_SOURCES}
559-
cpu_model.c
559+
cpu_model/aarch64.c
560560
aarch64/fp_mode.c
561561
)
562562

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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+
#include "aarch64/lse_atomics/freebsd.inc"
38+
#elif defined(__Fuchsia__)
39+
#include "aarch64/lse_atomics/fuchsia.inc"
40+
#elif defined(__ANDROID__)
41+
#include "aarch64/lse_atomics/android.inc"
42+
#elif __has_include(<sys/auxv.h>)
43+
#include "aarch64/lse_atomics/sysauxv.inc"
44+
#else
45+
// When unimplemented, we leave __aarch64_have_lse_atomics initialized to false.
46+
#endif
47+
48+
#if !defined(DISABLE_AARCH64_FMV)
49+
// CPUFeatures must correspond to the same AArch64 features in
50+
// AArch64TargetParser.h
51+
enum CPUFeatures {
52+
FEAT_RNG,
53+
FEAT_FLAGM,
54+
FEAT_FLAGM2,
55+
FEAT_FP16FML,
56+
FEAT_DOTPROD,
57+
FEAT_SM4,
58+
FEAT_RDM,
59+
FEAT_LSE,
60+
FEAT_FP,
61+
FEAT_SIMD,
62+
FEAT_CRC,
63+
FEAT_SHA1,
64+
FEAT_SHA2,
65+
FEAT_SHA3,
66+
FEAT_AES,
67+
FEAT_PMULL,
68+
FEAT_FP16,
69+
FEAT_DIT,
70+
FEAT_DPB,
71+
FEAT_DPB2,
72+
FEAT_JSCVT,
73+
FEAT_FCMA,
74+
FEAT_RCPC,
75+
FEAT_RCPC2,
76+
FEAT_FRINTTS,
77+
FEAT_DGH,
78+
FEAT_I8MM,
79+
FEAT_BF16,
80+
FEAT_EBF16,
81+
FEAT_RPRES,
82+
FEAT_SVE,
83+
FEAT_SVE_BF16,
84+
FEAT_SVE_EBF16,
85+
FEAT_SVE_I8MM,
86+
FEAT_SVE_F32MM,
87+
FEAT_SVE_F64MM,
88+
FEAT_SVE2,
89+
FEAT_SVE_AES,
90+
FEAT_SVE_PMULL128,
91+
FEAT_SVE_BITPERM,
92+
FEAT_SVE_SHA3,
93+
FEAT_SVE_SM4,
94+
FEAT_SME,
95+
FEAT_MEMTAG,
96+
FEAT_MEMTAG2,
97+
FEAT_MEMTAG3,
98+
FEAT_SB,
99+
FEAT_PREDRES,
100+
FEAT_SSBS,
101+
FEAT_SSBS2,
102+
FEAT_BTI,
103+
FEAT_LS64,
104+
FEAT_LS64_V,
105+
FEAT_LS64_ACCDATA,
106+
FEAT_WFXT,
107+
FEAT_SME_F64,
108+
FEAT_SME_I64,
109+
FEAT_SME2,
110+
FEAT_RCPC3,
111+
FEAT_MAX,
112+
FEAT_EXT = 62, // Reserved to indicate presence of additional features field
113+
// in __aarch64_cpu_features
114+
FEAT_INIT // Used as flag of features initialization completion
115+
};
116+
117+
// Architecture features used
118+
// in Function Multi Versioning
119+
struct {
120+
unsigned long long features;
121+
// As features grows new fields could be added
122+
} __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon));
123+
124+
// The formatter wants to re-order these includes, but doing so is incorrect:
125+
// clang-format off
126+
#if defined(__FreeBSD__)
127+
#include "aarch64/fmv/mrs.inc"
128+
#include "aarch64/fmv/freebsd.inc"
129+
#elif defined(__Fuchsia__)
130+
#include "aarch64/fmv/mrs.inc"
131+
#include "aarch64/fmv/fuchsia.inc"
132+
#elif defined(__ANDROID__)
133+
#include "aarch64/fmv/mrs.inc"
134+
#include "aarch64/fmv/android.inc"
135+
#elif __has_include(<sys/auxv.h>)
136+
#include "aarch64/fmv/mrs.inc"
137+
#include "aarch64/fmv/sysauxv.inc"
138+
#else
139+
#include "aarch64/fmv/unimplemented.inc"
140+
#endif
141+
// clang-format on
142+
143+
#endif // !defined(DISABLE_AARCH64_FMV)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
__ifunc_arg_t arg;
29+
arg._size = sizeof(__ifunc_arg_t);
30+
arg._hwcap = getauxval(AT_HWCAP);
31+
arg._hwcap2 = getauxval(AT_HWCAP2);
32+
__init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg);
33+
}
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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
// CPU features already initialized.
11+
if (__aarch64_cpu_features.features)
12+
return;
13+
14+
__ifunc_arg_t arg;
15+
arg._size = sizeof(__ifunc_arg_t);
16+
arg._hwcap = getauxval(AT_HWCAP);
17+
arg._hwcap2 = getauxval(AT_HWCAP2);
18+
__init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg);
19+
}

0 commit comments

Comments
 (0)