1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

Add fallback CPU detection when llvm is not aware of the CPU model

This commit is contained in:
kd-11 2024-08-03 04:54:37 +03:00 committed by kd-11
parent 8f51b0907a
commit 3e7c1e207d
3 changed files with 61 additions and 1 deletions

View File

@ -495,6 +495,7 @@ namespace llvm
class LLVMContext; class LLVMContext;
class ExecutionEngine; class ExecutionEngine;
class Module; class Module;
class StringRef;
} }
// Temporary compiler interface // Temporary compiler interface
@ -560,4 +561,6 @@ public:
bool add_sub_disk_space(ssz space); bool add_sub_disk_space(ssz space);
}; };
llvm::StringRef fallback_cpu_detection();
#endif // LLVM_AVAILABLE #endif // LLVM_AVAILABLE

View File

@ -440,6 +440,12 @@ std::string jit_compiler::cpu(const std::string& _cpu)
{ {
m_cpu = llvm::sys::getHostCPUName().str(); m_cpu = llvm::sys::getHostCPUName().str();
if (m_cpu == "generic")
{
// Try to detect a best match based on other criteria
m_cpu = fallback_cpu_detection();
}
if (m_cpu == "sandybridge" || if (m_cpu == "sandybridge" ||
m_cpu == "ivybridge" || m_cpu == "ivybridge" ||
m_cpu == "haswell" || m_cpu == "haswell" ||
@ -717,4 +723,49 @@ u64 jit_compiler::get(const std::string& name)
return m_engine->getGlobalValueAddress(name); return m_engine->getGlobalValueAddress(name);
} }
llvm::StringRef fallback_cpu_detection()
{
#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.
llvm::StringRef brand = utils::get_cpu_brand();
const auto family = utils::get_cpu_family();
const auto model = utils::get_cpu_model();
if (brand.startswith("AMD"))
{
switch (family)
{
case 0x17:
case 0x18:
// No major differences between znver1 and znver2, return the lesser
return "znver1";
case 0x19:
// Models 0-Fh are zen3 as are 20h-60h. The rest we can assume are zen4
return ((model >= 0x20 && model <= 0x60) || model < 0x10)
? "znver3"
: "znver4";
case 0x1a:
// Only one generation in family 1a so far
return "znver5";
default:
return "znver5"; // Return newest known model here
}
}
else if (brand.startswith("Virtual Apple"))
{
// No AVX. This will change in MacOS 15+, at which point we may revise this.
return "nehalem";
}
#elif defined(ARCH_ARM64)
// 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
// Failed to guess, use generic fallback
return "generic";
}
#endif // LLVM_AVAILABLE #endif // LLVM_AVAILABLE

View File

@ -90,7 +90,13 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
m_context = context; m_context = context;
m_engine = &engine; m_engine = &engine;
const auto cpu = m_engine->getTargetMachine()->getTargetCPU(); auto cpu = m_engine->getTargetMachine()->getTargetCPU();
if (cpu == "generic")
{
// Detection failed, try to guess
cpu = fallback_cpu_detection();
}
// Test SSSE3 feature (TODO) // Test SSSE3 feature (TODO)
if (cpu == "generic" || if (cpu == "generic" ||