mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-09 02:26:19 +00:00
Add a couple more passes (2-op, optimize f<->v fp moves)
This commit is contained in:
parent
f636b2a315
commit
91a6cf5e44
@ -1221,12 +1221,11 @@ namespace MIPSComp {
|
||||
VectorSize sz = GetVecSize(op);
|
||||
int n = GetNumVectorElements(sz);
|
||||
|
||||
VCondition cond = (VCondition)(op & 0xF);
|
||||
|
||||
u8 sregs[4], tregs[4];
|
||||
GetVectorRegsPrefixS(sregs, sz, _VS);
|
||||
GetVectorRegsPrefixT(tregs, sz, _VT);
|
||||
|
||||
VCondition cond = (VCondition)(op & 0xF);
|
||||
int mask = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
ir.Write(IROp::FCmpVfpuBit, cond | (i << 4), sregs[i], tregs[i]);
|
||||
|
@ -232,8 +232,10 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, std::v
|
||||
IRWriter *code = &ir;
|
||||
if (true) {
|
||||
static const IRPassFunc passes[] = {
|
||||
&OptimizeFPMoves,
|
||||
&PropagateConstants,
|
||||
&PurgeTemps,
|
||||
// &ThreeOpToTwoOp,
|
||||
};
|
||||
if (IRApplyPasses(passes, ARRAY_SIZE(passes), ir, simplified))
|
||||
logBlocks = 1;
|
||||
@ -286,5 +288,4 @@ void IRFrontend::Comp_RunBlock(MIPSOpcode op) {
|
||||
ERROR_LOG(JIT, "Comp_RunBlock should never be reached!");
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
@ -95,6 +95,114 @@ bool IRApplyPasses(const IRPassFunc *passes, size_t c, const IRWriter &in, IRWri
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
bool OptimizeFPMoves(const IRWriter &in, IRWriter &out) {
|
||||
//FMovToGPR a0, f12
|
||||
//FMovFromGPR f14, a0
|
||||
// to
|
||||
//FMovToGPR a0, f12
|
||||
//FMov f14, f12
|
||||
|
||||
const u32 *constants = in.GetConstants().data();
|
||||
bool logBlocks = false;
|
||||
IRInst prev;
|
||||
prev.op = IROp::Nop;
|
||||
for (int i = 0; i < (int)in.GetInstructions().size(); i++) {
|
||||
IRInst inst = in.GetInstructions()[i];
|
||||
switch (inst.op) {
|
||||
case IROp::FMovFromGPR:
|
||||
if (prev.op == IROp::FMovToGPR && prev.dest == inst.src1) {
|
||||
inst.op = IROp::FMov;
|
||||
inst.src1 = prev.src1;
|
||||
out.Write(inst);
|
||||
logBlocks = true;
|
||||
} else {
|
||||
out.Write(inst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Remap constants to the new reality
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
switch (m->types[0]) {
|
||||
case 'C':
|
||||
inst.dest = out.AddConstant(constants[inst.dest]);
|
||||
break;
|
||||
}
|
||||
switch (m->types[1]) {
|
||||
case 'C':
|
||||
inst.src1 = out.AddConstant(constants[inst.src1]);
|
||||
break;
|
||||
}
|
||||
switch (m->types[2]) {
|
||||
case 'C':
|
||||
inst.src2 = out.AddConstant(constants[inst.src2]);
|
||||
break;
|
||||
}
|
||||
out.Write(inst);
|
||||
break;
|
||||
}
|
||||
prev = inst;
|
||||
}
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
// Might be useful later on x86.
|
||||
bool ThreeOpToTwoOp(const IRWriter &in, IRWriter &out) {
|
||||
const u32 *constants = in.GetConstants().data();
|
||||
bool logBlocks = false;
|
||||
for (int i = 0; i < (int)in.GetInstructions().size(); i++) {
|
||||
IRInst inst = in.GetInstructions()[i];
|
||||
const IRMeta *meta = GetIRMeta(inst.op);
|
||||
switch (inst.op) {
|
||||
case IROp::Sub:
|
||||
case IROp::Slt:
|
||||
case IROp::SltU:
|
||||
case IROp::Add:
|
||||
case IROp::And:
|
||||
case IROp::Or:
|
||||
case IROp::Xor:
|
||||
if (inst.src1 != inst.dest && inst.src2 != inst.dest) {
|
||||
out.Write(IROp::Mov, inst.dest, inst.src1);
|
||||
out.Write(inst.op, inst.dest, inst.dest, inst.src2);
|
||||
} else {
|
||||
out.Write(inst);
|
||||
}
|
||||
break;
|
||||
case IROp::FMul:
|
||||
case IROp::FAdd:
|
||||
if (inst.src1 != inst.dest && inst.src2 != inst.dest) {
|
||||
out.Write(IROp::FMov, inst.dest, inst.src1);
|
||||
out.Write(inst.op, inst.dest, inst.dest, inst.src2);
|
||||
} else {
|
||||
out.Write(inst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Remap constants to the new reality
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
switch (m->types[0]) {
|
||||
case 'C':
|
||||
inst.dest = out.AddConstant(constants[inst.dest]);
|
||||
break;
|
||||
}
|
||||
switch (m->types[1]) {
|
||||
case 'C':
|
||||
inst.src1 = out.AddConstant(constants[inst.src1]);
|
||||
break;
|
||||
}
|
||||
switch (m->types[2]) {
|
||||
case 'C':
|
||||
inst.src2 = out.AddConstant(constants[inst.src2]);
|
||||
break;
|
||||
}
|
||||
out.Write(inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
bool PropagateConstants(const IRWriter &in, IRWriter &out) {
|
||||
IRRegCache gpr(&out);
|
||||
|
||||
|
@ -5,6 +5,9 @@
|
||||
typedef bool (*IRPassFunc)(const IRWriter &in, IRWriter &out);
|
||||
bool IRApplyPasses(const IRPassFunc *passes, size_t c, const IRWriter &in, IRWriter &out);
|
||||
|
||||
// Block optimizer passes of varying usefulness.
|
||||
bool PropagateConstants(const IRWriter &in, IRWriter &out);
|
||||
bool PurgeTemps(const IRWriter &in, IRWriter &out);
|
||||
bool ReduceLoads(const IRWriter &in, IRWriter &out);
|
||||
bool ThreeOpToTwoOp(const IRWriter &in, IRWriter &out);
|
||||
bool OptimizeFPMoves(const IRWriter &in, IRWriter &out);
|
||||
|
Loading…
x
Reference in New Issue
Block a user