From: Daniel Golle Subject: [PATCH] JavaScriptCore: RISCV64: fix nonPreservedNonArgumentFPR0 aliasing argumentFPR1 On RISCV64, FPRInfo declared nonPreservedNonArgumentFPR0 = RISCV64Registers::f11 but f11 is fa1 = argumentFPR1. BBQJIT pins wasmScratchFPR to nonPreservedNonArgumentFPR0 and uses it to materialise f32/f64 immediates for binary float comparisons (emitCompareF32/F64). When the non-immediate operand is bound to fa1 (e.g. wasm result/argument 1), emitMoveConst into the "scratch" register silently overwrites that value before the comparison runs. Symptom: spec-tests/wasm/stress multi-return tests that compare each returned f32/f64 against a constant fail at the fa1 slot: wasm-wasm-call-many-return-types-on-stack-no-args.js wasm-wasm-call-indirect-many-return-types-on-stack.js wasm-js-call-many-return-types-on-stack-no-args.js The bug is not about spill pressure; it is the scratch FPR aliasing an argument/return FPR for any value bound to fa1. Use f0 (ft0) -- a RISC-V caller-saved temporary outside the f10..f17 argument/return set -- matching the pattern used by ARM64 (q16) and X86_64 (xmm8). Signed-off-by: Daniel Golle --- --- a/Source/JavaScriptCore/jit/FPRInfo.h +++ b/Source/JavaScriptCore/jit/FPRInfo.h @@ -366,7 +366,7 @@ public: static constexpr FPRReg argumentFPR7 = RISCV64Registers::f17; // fpRegT7 static constexpr FPRReg returnValueFPR = RISCV64Registers::f10; // fpRegT0 - static constexpr FPRReg nonPreservedNonArgumentFPR0 = RISCV64Registers::f11; + static constexpr FPRReg nonPreservedNonArgumentFPR0 = RISCV64Registers::f0; static FPRReg toRegister(unsigned index) {