From 24e1ce4ceb37292ee52970bd84f24f12898c3e21 Mon Sep 17 00:00:00 2001 From: RipleyTom Date: Sat, 18 Jul 2026 06:32:14 +0200 Subject: [PATCH] Fix: get_known_bits fix --- rpcs3/Emu/CPU/CPUTranslator.h | 45 ++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 0e7f79b167..93a0733bac 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -4271,10 +4271,53 @@ template template llvm::Constant* make_const_vector(T, llvm::Type*, u32 = __builtin_LINE()); + // IR is emitted in a single pass: phi nodes may still be missing their back-edge incoming + // values, so any known bits computeKnownBits derives through a phi are unsound for the + // final IR. Whether a phi is complete cannot be queried (the CFG edges from not-yet-emitted + // predecessors don't exist either), so reject every value whose bits may derive from a phi. + static bool is_known_bits_safe(llvm::Value* value) + { + llvm::SmallPtrSet visited; + llvm::SmallVector worklist{value}; + + while (!worklist.empty()) + { + const llvm::Value* v = worklist.pop_back_val(); + + if (!visited.insert(v).second) + { + continue; + } + + if (llvm::isa(v) || visited.size() > 256) + { + return false; + } + + // Loads don't propagate operand bits; constants and arguments are leaves + if (auto i = llvm::dyn_cast(v); i && !llvm::isa(i)) + { + for (const llvm::Use& op : i->operands()) + { + worklist.push_back(op.get()); + } + } + } + + return true; + } + template llvm::KnownBits get_known_bits(T a) { - return llvm::computeKnownBits(a.eval(m_ir), m_module->getDataLayout()); + llvm::Value* value = a.eval(m_ir); + + if (!is_known_bits_safe(value)) + { + return llvm::KnownBits(value->getType()->getScalarSizeInBits()); + } + + return llvm::computeKnownBits(value, m_module->getDataLayout()); } template