From c3dfddebd74816feef96545c089f5c30af02e435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Oct 2025 20:55:56 +0200 Subject: [PATCH] IR interpreter: Improve code gen for the main interpreter loop Thanks to fp64 for the idea of using unreachable markers to avoid the range check on the switch! Additionally, use it in a few more places. --- Common/CommonFuncs.h | 12 ++++++++++++ Common/GPU/Vulkan/VulkanQueueRunner.cpp | 6 +++++- Common/GPU/Vulkan/VulkanRenderManager.cpp | 3 ++- Core/MIPS/IR/IRInterpreter.cpp | 5 +++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Common/CommonFuncs.h b/Common/CommonFuncs.h index 32b44d3d11..d3916a8ad8 100644 --- a/Common/CommonFuncs.h +++ b/Common/CommonFuncs.h @@ -75,6 +75,18 @@ #include #endif +#ifdef _DEBUG +#define UNREACHABLE() Crash() +#else +#if defined(_MSC_VER) +#define UNREACHABLE() __assume(0) +#elif defined(__GNUC__) || defined(__clang__) +#define UNREACHABLE() __builtin_unreachable() +#else +#define UNREACHABLE() ((void)0) +#endif +#endif + inline u32 __rotl(u32 x, int shift) { #if defined(_MSC_VER) return _rotl(x, shift); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 4c92d4acaa..e5763c8a63 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -366,6 +366,9 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, Fr break; case VKRStepType::RENDER_SKIP: break; + default: + UNREACHABLE(); + break; } if (profile && profile->timestampsEnabled && profile->timestampDescriptions.size() + 1 < MAX_TIMESTAMP_QUERIES) { @@ -813,6 +816,7 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector &steps) { break; default: // We added a new step? Might be unsafe. + _dbg_assert_(false); goto done_fb; } } @@ -1239,7 +1243,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c break; default: - ERROR_LOG(Log::G3D, "Unimpl queue command"); + UNREACHABLE(); break; } } diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 99296ea8a8..34ee1126ec 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -1637,6 +1637,7 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { default: _dbg_assert_(false); + break; } VLOG("PULL: Finished running frame %d", task.frame); @@ -1739,7 +1740,7 @@ VKRPipelineLayout *VulkanRenderManager::CreatePipelineLayout(BindingType *bindin bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; break; default: - _dbg_assert_(false); + UNREACHABLE(); break; } } diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index ff39c19096..4636f27067 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -10,6 +10,7 @@ #include "Common/BitSet.h" #include "Common/BitScan.h" #include "Common/Common.h" +#include "Common/CommonFuncs.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Math/math_util.h" #include "Common/Math/SIMDHeaders.h" @@ -1257,9 +1258,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) { case IROp::Nop: // TODO: This shouldn't crash, but for now we should not emit nops, so... case IROp::Bad: default: - Crash(); + // Unimplemented IR op. Bad. We define it as unreachable so the compiler can optimize better (remove the range check). + UNREACHABLE(); break; - // Unimplemented IR op. Bad. } #ifdef _DEBUG