Add a couple more passes (2-op, optimize f<->v fp moves)

This commit is contained in:
Henrik Rydgard 2016-05-13 20:14:03 +02:00
parent f636b2a315
commit 91a6cf5e44
4 changed files with 114 additions and 3 deletions

View File

@ -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]);

View File

@ -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

View File

@ -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);

View File

@ -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);