RISC-V/LoongArch IR: Get vrot's sine and cosine from one call

Like arm64 and x64, call vfpu_sincos_packed and split the double it returns.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-24 16:22:41 -06:00
1 parent f92340c092
commit c38d04a10c
2 files changed
+32 -22

No files matched your search

+16 -11
View File
@@ -562,7 +562,7 @@ void LoongArch64JitBackend::CompIR_RoundingMode(IRInst inst) {
void LoongArch64JitBackend::CompIR_FSpecial(IRInst inst) {
CONDITIONAL_DISABLE;
auto callFuncF_F = [&](float (*func)(float)) {
auto callWithF0 = [&](const u8 *func) {
regs_.FlushBeforeCall();
WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER);
@@ -579,6 +579,10 @@ void LoongArch64JitBackend::CompIR_FSpecial(IRInst inst) {
FLD_S(F0, CTXREG, offset);
}
QuickCallFunction(func, SCRATCH1);
};
auto callFuncF_F = [&](float (*func)(float)) {
callWithF0((const u8 *)func);
regs_.MapFPR(inst.dest, MIPSMap::NOINIT);
// If it's already F0, we're done - MapReg doesn't actually overwrite the reg in that case.
@@ -627,17 +631,18 @@ void LoongArch64JitBackend::CompIR_FSpecial(IRInst inst) {
break;
case IROp::FSinCos:
{
// Two calls here. The frontend makes sure dest doesn't overlap src1.
IRInst sinInst = inst;
sinInst.op = IROp::FSin;
CompIR_FSpecial(sinInst);
IRInst cosInst = inst;
cosInst.op = IROp::FCos;
cosInst.dest = inst.dest + 1;
CompIR_FSpecial(cosInst);
// The sine comes back in the low 32 bits of F0, the cosine in the high.
callWithF0((const u8 *)&vfpu_sincos_packed);
MOVFR2GR_S(SCRATCH1, F0);
MOVFRH2GR_S(SCRATCH2, F0);
regs_.SpillLockFPR(inst.dest, inst.dest + 1);
regs_.MapFPR(inst.dest, MIPSMap::NOINIT);
regs_.MapFPR(inst.dest + 1, MIPSMap::NOINIT);
regs_.ReleaseSpillLockFPR(inst.dest, inst.dest + 1);
MOVGR2FR_W(regs_.F(inst.dest), SCRATCH1);
MOVGR2FR_W(regs_.F(inst.dest + 1), SCRATCH2);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
break;
}
default:
INVALIDOP;
+16 -11
View File
@@ -589,7 +589,7 @@ void RiscVJitBackend::CompIR_FSpecial(IRInst inst) {
#error Currently hard float is required.
#endif
auto callFuncF_F = [&](float (*func)(float)) {
auto callWithF10 = [&](const u8 *func) {
regs_.FlushBeforeCall();
WriteDebugProfilerStatus(IRProfilerStatus::MATH_HELPER);
@@ -602,6 +602,10 @@ void RiscVJitBackend::CompIR_FSpecial(IRInst inst) {
FL(32, F10, CTXREG, offset);
}
QuickCallFunction(func, SCRATCH1);
};
auto callFuncF_F = [&](float (*func)(float)) {
callWithF10((const u8 *)func);
regs_.MapFPR(inst.dest, MIPSMap::NOINIT);
// If it's already F10, we're done - MapReg doesn't actually overwrite the reg in that case.
@@ -650,17 +654,18 @@ void RiscVJitBackend::CompIR_FSpecial(IRInst inst) {
break;
case IROp::FSinCos:
{
// Two calls here. The frontend makes sure dest doesn't overlap src1.
IRInst sinInst = inst;
sinInst.op = IROp::FSin;
CompIR_FSpecial(sinInst);
IRInst cosInst = inst;
cosInst.op = IROp::FCos;
cosInst.dest = inst.dest + 1;
CompIR_FSpecial(cosInst);
// The sine comes back in the low 32 bits of F10, the cosine in the high.
callWithF10((const u8 *)&vfpu_sincos_packed);
FMV(FMv::X, FMv::D, SCRATCH1, F10);
regs_.SpillLockFPR(inst.dest, inst.dest + 1);
regs_.MapFPR(inst.dest, MIPSMap::NOINIT);
regs_.MapFPR(inst.dest + 1, MIPSMap::NOINIT);
regs_.ReleaseSpillLockFPR(inst.dest, inst.dest + 1);
FMV(FMv::W, FMv::X, regs_.F(inst.dest), SCRATCH1);
SRLI(SCRATCH1, SCRATCH1, 32);
FMV(FMv::W, FMv::X, regs_.F(inst.dest + 1), SCRATCH1);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
break;
}
default:
INVALIDOP;