diff --git a/Core/MIPS/IR/IRCompVFPU.cpp b/Core/MIPS/IR/IRCompVFPU.cpp index 74590a213..e0b5ecccd 100644 --- a/Core/MIPS/IR/IRCompVFPU.cpp +++ b/Core/MIPS/IR/IRCompVFPU.cpp @@ -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]); diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index d615f936f..c41c3cac0 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -232,8 +232,10 @@ void IRFrontend::DoJit(u32 em_address, std::vector &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 \ No newline at end of file diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index 1fd98a315..4f9da4e49 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -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); diff --git a/Core/MIPS/IR/IRPassSimplify.h b/Core/MIPS/IR/IRPassSimplify.h index d6dd04125..80b979fbf 100644 --- a/Core/MIPS/IR/IRPassSimplify.h +++ b/Core/MIPS/IR/IRPassSimplify.h @@ -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);