IR: Add FExp2 and FLog2 for vexp2, vlog2 and vrexp2

These were always interpreted. They're now IR ops that the native
backends compile to calls to vfpu_exp2 and vfpu_log2, like FSin and
FAsin. vrexp2 is FNeg followed by FExp2, which is how vfpu_rexp2
computes it.

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 13:34:19 -06:00
1 parent d313cf7626
commit b832ceab83
10 files changed
+75 -3

No files matched your search

+8
View File
@@ -563,6 +563,14 @@ void Arm64JitBackend::CompIR_FSpecial(IRInst inst) {
callFuncF_F(&vfpu_sqrt);
break;
case IROp::FExp2:
callFuncF_F(&vfpu_exp2);
break;
case IROp::FLog2:
callFuncF_F(&vfpu_log2);
break;
default:
INVALIDOP;
break;
+5 -3
View File
@@ -1122,10 +1122,10 @@ namespace MIPSComp {
ir.Write(IROp::FCos, tempregs[i], sregs[i]);
break;
case 20: // d[i] = powf(2.0f, s[i]); break; //vexp2
DISABLE;
ir.Write(IROp::FExp2, tempregs[i], sregs[i]);
break;
case 21: // d[i] = logf(s[i])/log(2.0f); break; //vlog2
DISABLE;
ir.Write(IROp::FLog2, tempregs[i], sregs[i]);
break;
case 22: // d[i] = sqrtf(s[i]); break; //vsqrt
ir.Write(IROp::FVSqrt, tempregs[i], sregs[i]);
@@ -1142,7 +1142,9 @@ namespace MIPSComp {
ir.Write(IROp::FNeg, tempregs[i], tempregs[i]);
break;
case 28: // d[i] = 1.0f / expf(s[i] * (float)M_LOG2E); break; // vrexp2
DISABLE;
// exp2(-x), as vfpu_rexp2 computes it.
ir.Write(IROp::FNeg, tempregs[i], sregs[i]);
ir.Write(IROp::FExp2, tempregs[i], tempregs[i]);
break;
default:
INVALIDOP;
+2
View File
@@ -110,6 +110,8 @@ static const IRMeta irMeta[] = {
{ IROp::FRecip, "FRecip", "FF" },
{ IROp::FAsin, "FAsin", "FF" },
{ IROp::FVSqrt, "FVSqrt", "FF" },
{ IROp::FExp2, "FExp2", "FF" },
{ IROp::FLog2, "FLog2", "FF" },
{ IROp::FNeg, "FNeg", "FF" },
{ IROp::FSign, "FSign", "FF" },
{ IROp::FAbs, "FAbs", "FF" },
+2
View File
@@ -201,6 +201,8 @@ enum class IROp : uint8_t {
FRecip, // vrcp, bit-exact with the PSP
FAsin,
FVSqrt, // vsqrt, bit-exact with the PSP (FSqrt is the FPU's IEEE sqrt.s)
FExp2, // vexp2, bit-exact with the PSP
FLog2, // vlog2, bit-exact with the PSP
// Fake/System instructions
Interpret,
+6
View File
@@ -640,6 +640,12 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) {
case IROp::FVSqrt:
mips->f[inst->dest] = vfpu_sqrt(mips->f[inst->src1]);
break;
case IROp::FExp2:
mips->f[inst->dest] = vfpu_exp2(mips->f[inst->src1]);
break;
case IROp::FLog2:
mips->f[inst->dest] = vfpu_log2(mips->f[inst->src1]);
break;
case IROp::ShlImm:
mips->r[inst->dest] = mips->r[inst->src1] << (int)inst->src2;
+2
View File
@@ -433,6 +433,8 @@ void IRNativeBackend::CompileIRInst(IRInst inst) {
case IROp::FRecip:
case IROp::FAsin:
case IROp::FVSqrt:
case IROp::FExp2:
case IROp::FLog2:
CompIR_FSpecial(inst);
break;
+2
View File
@@ -766,6 +766,8 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
case IROp::FRecip:
case IROp::FAsin:
case IROp::FVSqrt:
case IROp::FExp2:
case IROp::FLog2:
out.Write(inst);
break;
@@ -608,6 +608,14 @@ void LoongArch64JitBackend::CompIR_FSpecial(IRInst inst) {
callFuncF_F(&vfpu_sqrt);
break;
case IROp::FExp2:
callFuncF_F(&vfpu_exp2);
break;
case IROp::FLog2:
callFuncF_F(&vfpu_log2);
break;
default:
INVALIDOP;
break;
+8
View File
@@ -633,6 +633,14 @@ void RiscVJitBackend::CompIR_FSpecial(IRInst inst) {
callFuncF_F(&vfpu_sqrt);
break;
case IROp::FExp2:
callFuncF_F(&vfpu_exp2);
break;
case IROp::FLog2:
callFuncF_F(&vfpu_log2);
break;
default:
INVALIDOP;
break;
+32
View File
@@ -970,6 +970,14 @@ static float X64JIT_XMM_CALL x64_asin(float f) {
return vfpu_asin(f);
}
static float X64JIT_XMM_CALL x64_exp2(float f) {
return vfpu_exp2(f);
}
static float X64JIT_XMM_CALL x64_log2(float f) {
return vfpu_log2(f);
}
static float X64JIT_XMM_CALL x64_vsqrt(float f) {
return vfpu_sqrt(f);
}
@@ -1006,6 +1014,22 @@ static uint32_t x64_asin(uint32_t v) {
return v;
}
static uint32_t x64_exp2(uint32_t v) {
float f;
memcpy(&f, &v, sizeof(v));
f = vfpu_exp2(f);
memcpy(&v, &f, sizeof(v));
return v;
}
static uint32_t x64_log2(uint32_t v) {
float f;
memcpy(&f, &v, sizeof(v));
f = vfpu_log2(f);
memcpy(&v, &f, sizeof(v));
return v;
}
static uint32_t x64_vsqrt(uint32_t v) {
float f;
memcpy(&f, &v, sizeof(v));
@@ -1098,6 +1122,14 @@ void X64JitBackend::CompIR_FSpecial(IRInst inst) {
callFuncF_F((const void *)&x64_vsqrt);
break;
case IROp::FExp2:
callFuncF_F((const void *)&x64_exp2);
break;
case IROp::FLog2:
callFuncF_F((const void *)&x64_log2);
break;
default:
INVALIDOP;
break;