From d06c6c080cf9b7d53aba958efc30681722eba42d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 9 May 2016 22:25:35 -0700 Subject: [PATCH] jit-ir: Expand unused regs to regular GPRs. --- Core/MIPS/IR/IRInst.cpp | 26 +++++++++++++------------- Core/MIPS/IR/IRInst.h | 7 ++++++- Core/MIPS/IR/IRPassSimplify.cpp | 24 +++++++++++++++++++++--- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index b95d5fafa3..11db5bf1bf 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -33,8 +33,8 @@ static const IRMeta irMeta[] = { { IROp::SltU, "SltU", "GGG" }, { IROp::SltUConst, "SltUConst", "GGC" }, { IROp::Clz, "Clz", "GG" }, - { IROp::MovZ, "MovZ", "GGG" }, - { IROp::MovNZ, "MovNZ", "GGG" }, + { IROp::MovZ, "MovZ", "GGG", IRFLAG_SRC3DST }, + { IROp::MovNZ, "MovNZ", "GGG", IRFLAG_SRC3DST }, { IROp::Max, "Max", "GGG" }, { IROp::Min, "Min", "GGG" }, { IROp::BSwap16, "BSwap16", "GG" }, @@ -112,19 +112,19 @@ static const IRMeta irMeta[] = { { IROp::Interpret, "Interpret", "_C" }, { IROp::Downcount, "Downcount", "_II" }, - { IROp::ExitToConst, "Exit", "C" }, - { IROp::ExitToConstIfEq, "ExitIfEq", "CGG" }, - { IROp::ExitToConstIfNeq, "ExitIfNeq", "CGG" }, - { IROp::ExitToConstIfGtZ, "ExitIfGtZ", "CG" }, - { IROp::ExitToConstIfGeZ, "ExitIfGeZ", "CG" }, - { IROp::ExitToConstIfLeZ, "ExitIfLeZ", "CG" }, - { IROp::ExitToConstIfLtZ, "ExitIfLtZ", "CG" }, - { IROp::ExitToReg, "ExitToReg", "G" }, - { IROp::Syscall, "Syscall", "_C" }, - { IROp::Break, "Break", ""}, + { IROp::ExitToConst, "Exit", "C", IRFLAG_EXIT }, + { IROp::ExitToConstIfEq, "ExitIfEq", "CGG", IRFLAG_EXIT }, + { IROp::ExitToConstIfNeq, "ExitIfNeq", "CGG", IRFLAG_EXIT }, + { IROp::ExitToConstIfGtZ, "ExitIfGtZ", "CG", IRFLAG_EXIT }, + { IROp::ExitToConstIfGeZ, "ExitIfGeZ", "CG", IRFLAG_EXIT }, + { IROp::ExitToConstIfLeZ, "ExitIfLeZ", "CG", IRFLAG_EXIT }, + { IROp::ExitToConstIfLtZ, "ExitIfLtZ", "CG", IRFLAG_EXIT }, + { IROp::ExitToReg, "ExitToReg", "G", IRFLAG_EXIT | IRFLAG_SRC3 }, + { IROp::Syscall, "Syscall", "_C", IRFLAG_EXIT }, + { IROp::Break, "Break", "", IRFLAG_EXIT}, { IROp::SetPC, "SetPC", "_G" }, { IROp::SetPCConst, "SetPC", "_C" }, - { IROp::CallReplacement, "CallRepl", "_C"}, + { IROp::CallReplacement, "CallRepl", "_C" }, }; const IRMeta *metaIndex[256]; diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index b4e330aadc..d2195892ba 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -282,7 +282,12 @@ enum { }; enum IRFlags { - IRFLAG_SRC3 = 1, + // Uses src3, not dest. + IRFLAG_SRC3 = 0x0001, + // Uses src3 AND dest (i.e. mutates dest.) + IRFLAG_SRC3DST = 0x0002, + // Exit instruction (maybe conditional.) + IRFLAG_EXIT = 0x0004, }; struct IRMeta { diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index abb06fe89c..f33afef6ac 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -443,10 +443,10 @@ bool IRReadsFromGPR(const IRInst &inst, int reg) { if (m->types[2] == 'G' && inst.src2 == reg) { return true; } - if ((m->flags & IRFLAG_SRC3) != 0 && m->types[0] == 'G' && inst.src3 == reg) { + if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == 'G' && inst.src3 == reg) { return true; } - if (inst.op == IROp::Interpret) { + if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement) { return true; } return false; @@ -474,6 +474,7 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out) { int dest = IRDestGPR(inst); bool read = true; + bool readByExit = true; switch (dest) { case IRTEMP_0: case IRTEMP_1: @@ -482,21 +483,38 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out) { // Unlike other ops, these don't need to persist between blocks. // So we consider them not read unless proven read. read = false; + readByExit = false; + // Intentional fall-through. + + default: + if (dest > IRTEMP_RHS) { + // These might sometimes be implicitly read/written by other instructions. + break; + } for (int j = i + 1; j < n; j++) { const IRInst &laterInst = in.GetInstructions()[j]; + const IRMeta *m = GetIRMeta(laterInst.op); if (IRReadsFromGPR(laterInst, dest)) { // Read from, so we can't optimize out. read = true; break; } + if (readByExit && (m->flags & IRFLAG_EXIT) != 0) { + read = true; + break; + } + if (IRDestGPR(laterInst) == dest) { // Clobbered, we can optimize out. + // This happens sometimes with temporaries used for constant addresses. + read = false; break; } } break; - default: + // Not a GPR output. + case -1: break; }