android: jit: teach fallback_cpu_detection provide meaningful results for aarch64

This commit is contained in:
DH 2025-02-28 21:12:22 +03:00 committed by Megamouse
parent 3080b55d02
commit 94f52d6dc0
4 changed files with 71 additions and 7 deletions

View file

@ -569,6 +569,6 @@ public:
bool add_sub_disk_space(ssz space);
};
llvm::StringRef fallback_cpu_detection();
const char *fallback_cpu_detection();
#endif // LLVM_AVAILABLE

View file

@ -46,6 +46,10 @@ LOG_CHANNEL(jit_log, "JIT");
#pragma GCC diagnostic pop
#endif
#ifdef ARCH_ARM64
#include "Emu/CPU/Backends/AArch64/AArch64Common.h"
#endif
const bool jit_initialize = []() -> bool
{
llvm::InitializeNativeTarget();
@ -590,8 +594,10 @@ std::string jit_compiler::triple1()
return llvm::Triple::normalize(llvm::sys::getProcessTriple());
#elif defined(__APPLE__) && defined(ARCH_X64)
return llvm::Triple::normalize("x86_64-unknown-linux-gnu");
#elif defined(__APPLE__) && defined(ARCH_ARM64)
#elif (defined(__ANDROID__) || defined(__APPLE__)) && defined(ARCH_ARM64)
return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18
#elif defined(__ANDROID__) && defined(ARCH_X64)
return llvm::Triple::normalize("x86_64-unknown-linux-android");
#else
return llvm::Triple::normalize(llvm::sys::getProcessTriple());
#endif
@ -605,8 +611,10 @@ std::string jit_compiler::triple2()
return llvm::Triple::normalize("aarch64-unknown-linux-gnu");
#elif defined(__APPLE__) && defined(ARCH_X64)
return llvm::Triple::normalize("x86_64-unknown-linux-gnu");
#elif defined(__APPLE__) && defined(ARCH_ARM64)
#elif (defined(__ANDROID__) || defined(__APPLE__)) && defined(ARCH_ARM64)
return llvm::Triple::normalize("aarch64-unknown-linux-android"); // Set environment to android to reserve x18
#elif defined(__ANDROID__) && defined(ARCH_X64)
return llvm::Triple::normalize("x86_64-unknown-linux-android"); // Set environment to android to reserve x18
#else
return llvm::Triple::normalize(llvm::sys::getProcessTriple());
#endif
@ -817,9 +825,9 @@ u64 jit_compiler::get(const std::string& name)
return m_engine->getGlobalValueAddress(name);
}
llvm::StringRef fallback_cpu_detection()
const char * fallback_cpu_detection()
{
#if defined (ARCH_X64)
#if defined(ARCH_X64)
// If we got here we either have a very old and outdated CPU or a new CPU that has not been seen by LLVM yet.
const std::string brand = utils::get_cpu_brand();
const auto family = utils::get_cpu_family();
@ -851,8 +859,8 @@ llvm::StringRef fallback_cpu_detection()
default:
// Safest guesses
return utils::has_avx512() ? "znver4" :
utils::has_avx2() ? "znver1" :
utils::has_avx() ? "bdver1" :
utils::has_avx2() ? "znver1" :
utils::has_avx() ? "bdver1" :
"nehalem";
}
}
@ -883,10 +891,26 @@ llvm::StringRef fallback_cpu_detection()
}
#elif defined(ARCH_ARM64)
#ifdef ANDROID
static std::string s_result = []() -> std::string
{
std::string result = aarch64::get_cpu_name();
if (result.empty())
{
return "cortex-a78";
}
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
return result;
}();
return s_result.c_str();
#else
// TODO: Read the data from /proc/cpuinfo. ARM CPU registers are not accessible from usermode.
// This will be a pain when supporting snapdragon on windows but we'll cross that bridge when we get there.
// Require at least armv8-2a. Older chips are going to be useless anyway.
return "cortex-a78";
#endif
#endif
// Failed to guess, use generic fallback

View file

@ -136,6 +136,45 @@ namespace aarch64
#endif
}
std::string get_cpu_name()
{
std::map<u64, int> core_layout;
for (u32 i = 0; i < std::thread::hardware_concurrency(); ++i)
{
const auto midr = read_MIDR_EL1(i);
if (midr == umax)
{
break;
}
core_layout[midr]++;
}
if (core_layout.empty())
{
return {};
}
const cpu_entry_t *lowest_part_info = nullptr;
for (const auto& [midr, count] : core_layout)
{
const auto implementer_id = (midr >> 24) & 0xff;
const auto part_id = (midr >> 4) & 0xfff;
const auto part_info = find_cpu_part(implementer_id, part_id);
if (!part_info)
{
return {};
}
if (lowest_part_info == nullptr || lowest_part_info > part_info) {
lowest_part_info = part_info;
}
}
return lowest_part_info == nullptr ? "" : lowest_part_info->name;
}
std::string get_cpu_brand()
{
// Fetch vendor and part numbers. ARM CPUs often have more than 1 architecture on the SoC, so we check all of them.

View file

@ -37,5 +37,6 @@ namespace aarch64
"xzr", ".", "sp"
};
std::string get_cpu_name();
std::string get_cpu_brand();
}