diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7497,6 +7497,7 @@ if (Triple.isAArch64() && (Args.hasArg(options::OPT_mno_fmv) || + (Triple.isAndroid() && Triple.isAndroidVersionLT(23)) || getToolChain().GetRuntimeLibType(Args) != ToolChain::RLT_CompilerRT)) { // Disable Function Multiversioning on AArch64 target. CmdArgs.push_back("-target-feature"); diff --git a/clang/test/Driver/aarch64-features.c b/clang/test/Driver/aarch64-features.c --- a/clang/test/Driver/aarch64-features.c +++ b/clang/test/Driver/aarch64-features.c @@ -7,12 +7,18 @@ // CHECK: fno-signed-char // Check Function Multi Versioning option and rtlib dependency. -// RUN: %clang --target=aarch64-linux-android -rtlib=compiler-rt \ +// RUN: %clang --target=aarch64-linux-android23 -rtlib=compiler-rt \ // RUN: -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FMV %s +// RUN: %clang --target=aarch64-linux-android -rtlib=compiler-rt \ +// RUN: -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FMV-OFF %s + // RUN: %clang --target=aarch64-linux-android -rtlib=compiler-rt -mno-fmv \ // RUN: -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FMV-OFF %s +// RUN: %clang --target=aarch64-linux-android22 -rtlib=compiler-rt \ +// RUN: -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FMV-OFF %s + // RUN: %clang --target=aarch64-linux-gnu -rtlib=libgcc \ // RUN: -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-FMV-OFF %s diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -894,6 +894,7 @@ #include #if defined(__ANDROID__) +#include #include #include #elif defined(__Fuchsia__) @@ -1186,7 +1187,8 @@ // As features grows new fields could be added } __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon)); -void init_cpu_features_resolver(unsigned long hwcap, const __ifunc_arg_t *arg) { +static void init_cpu_features_constructor(unsigned long hwcap, + const __ifunc_arg_t *arg) { #define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F #define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) #define extractBits(val, start, number) \ @@ -1374,6 +1376,21 @@ setCPUFeature(FEAT_MAX); } +void init_cpu_features_resolver(unsigned long hwcap, const __ifunc_arg_t *arg) { + if (__aarch64_cpu_features.features) + return; +#if defined(__ANDROID__) + // ifunc resolvers don't have hwcaps in arguments on Android API lower + // than 30. In this case set detection done and keep all CPU features + // unsupported (zeros). + if (android_get_device_api_level() < 30) { + setCPUFeature(FEAT_MAX); + return; + } +#endif // defined(__ANDROID__) + init_cpu_features_constructor(hwcap, arg); +} + void CONSTRUCTOR_ATTRIBUTE init_cpu_features(void) { unsigned long hwcap; unsigned long hwcap2; @@ -1399,7 +1416,7 @@ arg._size = sizeof(__ifunc_arg_t); arg._hwcap = hwcap; arg._hwcap2 = hwcap2; - init_cpu_features_resolver(hwcap | _IFUNC_ARG_HWCAP, &arg); + init_cpu_features_constructor(hwcap | _IFUNC_ARG_HWCAP, &arg); #undef extractBits #undef getCPUFeature #undef setCPUFeature