mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
IR interpreter: Merge a conditional exit with the ExitToConst after it
Blocks ending in a branch dispatch a conditional exit and then the fallthrough ExitToConst. One op now returns either target, reading the second from the ExitToConst, which stays behind unexecuted. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
c6aea794f6
commit
7eb371b231
5 files changed
+53
No files matched your search
@@ -131,6 +131,12 @@ static const IRMeta irMeta[] = {
|
||||
{ IROp::FMovToGPR, "FMovToGPR", "GF" },
|
||||
{ IROp::OptFMovToGPRShr8, "OptFMovToGPRShr8", "GF" },
|
||||
{ IROp::OptFCvtSWFromGPR, "OptFCvtSWFromGPR", "FG" },
|
||||
{ IROp::OptExitToConstIfEqElse, "OptExitIfEqElse", "CGG", IRFLAG_EXIT },
|
||||
{ IROp::OptExitToConstIfNeqElse, "OptExitIfNeqElse", "CGG", IRFLAG_EXIT },
|
||||
{ IROp::OptExitToConstIfGtZElse, "OptExitIfGtZElse", "CG", IRFLAG_EXIT },
|
||||
{ IROp::OptExitToConstIfGeZElse, "OptExitIfGeZElse", "CG", IRFLAG_EXIT },
|
||||
{ IROp::OptExitToConstIfLtZElse, "OptExitIfLtZElse", "CG", IRFLAG_EXIT },
|
||||
{ IROp::OptExitToConstIfLeZElse, "OptExitIfLeZElse", "CG", IRFLAG_EXIT },
|
||||
{ IROp::FpCondFromReg, "FpCondFromReg", "_G" },
|
||||
{ IROp::FpCondToReg, "FpCondToReg", "G" },
|
||||
{ IROp::FpCtrlFromReg, "FpCtrlFromReg", "_G" },
|
||||
|
||||
@@ -141,6 +141,14 @@ enum class IROp : uint8_t {
|
||||
OptFCvtSWFromGPR,
|
||||
FMovToGPR,
|
||||
OptFMovToGPRShr8,
|
||||
// A conditional exit merged with the ExitToConst after it, which stays behind as the target
|
||||
// to take otherwise (in its constant).
|
||||
OptExitToConstIfEqElse,
|
||||
OptExitToConstIfNeqElse,
|
||||
OptExitToConstIfGtZElse,
|
||||
OptExitToConstIfGeZElse,
|
||||
OptExitToConstIfLtZElse,
|
||||
OptExitToConstIfLeZElse,
|
||||
|
||||
FSat0_1,
|
||||
FSatMinus1_1,
|
||||
|
||||
@@ -1034,6 +1034,19 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) {
|
||||
case IROp::ExitToReg:
|
||||
return mips->r[inst->src1];
|
||||
|
||||
// The next instruction is the ExitToConst to take otherwise, never run itself.
|
||||
case IROp::OptExitToConstIfEqElse:
|
||||
return mips->r[inst->src1] == mips->r[inst->src2] ? inst->constant : inst[1].constant;
|
||||
case IROp::OptExitToConstIfNeqElse:
|
||||
return mips->r[inst->src1] != mips->r[inst->src2] ? inst->constant : inst[1].constant;
|
||||
case IROp::OptExitToConstIfGtZElse:
|
||||
return (s32)mips->r[inst->src1] > 0 ? inst->constant : inst[1].constant;
|
||||
case IROp::OptExitToConstIfGeZElse:
|
||||
return (s32)mips->r[inst->src1] >= 0 ? inst->constant : inst[1].constant;
|
||||
case IROp::OptExitToConstIfLtZElse:
|
||||
return (s32)mips->r[inst->src1] < 0 ? inst->constant : inst[1].constant;
|
||||
case IROp::OptExitToConstIfLeZElse:
|
||||
return (s32)mips->r[inst->src1] <= 0 ? inst->constant : inst[1].constant;
|
||||
case IROp::ExitToConstIfEq:
|
||||
if (mips->r[inst->src1] == mips->r[inst->src2])
|
||||
return inst->constant;
|
||||
|
||||
@@ -2407,6 +2407,19 @@ bool OptimizeForInterpreter(const IRWriter &in, IRWriter &out, const IROptions &
|
||||
}
|
||||
out.Write(inst);
|
||||
break;
|
||||
case IROp::ExitToConstIfEq:
|
||||
case IROp::ExitToConstIfNeq:
|
||||
case IROp::ExitToConstIfGtZ:
|
||||
case IROp::ExitToConstIfGeZ:
|
||||
case IROp::ExitToConstIfLtZ:
|
||||
case IROp::ExitToConstIfLeZ:
|
||||
// With an ExitToConst right after, one op can pick either target. The ExitToConst stays
|
||||
// as the second target's holder.
|
||||
static_assert((int)IROp::OptExitToConstIfLeZElse - (int)IROp::OptExitToConstIfEqElse == (int)IROp::ExitToConstIfLeZ - (int)IROp::ExitToConstIfEq, "Else exits must match the exits' order");
|
||||
if (!last && in.GetInstructions()[i + 1].op == IROp::ExitToConst)
|
||||
inst.op = (IROp)((int)IROp::OptExitToConstIfEqElse + ((int)inst.op - (int)IROp::ExitToConstIfEq));
|
||||
out.Write(inst);
|
||||
break;
|
||||
default:
|
||||
out.Write(inst);
|
||||
break;
|
||||
|
||||
@@ -510,6 +510,19 @@ static const IRVerification tests[] = {
|
||||
},
|
||||
{ &OptimizeLoadsAfterStores },
|
||||
},
|
||||
{
|
||||
"InterpreterExitElse",
|
||||
{
|
||||
{ IROp::ExitToConstIfLtZ, { 0 }, MIPS_REG_A0, 0, 0x08804000 },
|
||||
{ IROp::ExitToConst, { 0 }, 0, 0, 0x08804100 },
|
||||
},
|
||||
{
|
||||
{ IROp::Downcount, { 0 }, 0, 0, 0 },
|
||||
{ IROp::OptExitToConstIfLtZElse, { 0 }, MIPS_REG_A0, 0, 0x08804000 },
|
||||
{ IROp::ExitToConst, { 0 }, 0, 0, 0x08804100 },
|
||||
},
|
||||
{ &OptimizeForInterpreter },
|
||||
},
|
||||
};
|
||||
|
||||
bool TestIRPassSimplify() {
|
||||
|
||||
Reference in new issue
Block a user