mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #18282 from unknownbrackets/ir-compiling
Improve IR compilation performance
This commit is contained in:
commit
db805cc4cc
7 changed files with 127 additions and 113 deletions
|
@ -93,12 +93,11 @@ bool Arm64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
|
||||
regs_.Start(block);
|
||||
|
||||
std::map<const u8 *, int> addresses;
|
||||
std::vector<const u8 *> addresses;
|
||||
for (int i = 0; i < block->GetNumInstructions(); ++i) {
|
||||
const IRInst &inst = block->GetInstructions()[i];
|
||||
regs_.SetIRIndex(i);
|
||||
// TODO: This might be a little wasteful when compiling if we're not debugging jit...
|
||||
addresses[GetCodePtr()] = i;
|
||||
addresses.push_back(GetCodePtr());
|
||||
|
||||
CompileIRInst(inst);
|
||||
|
||||
|
@ -150,10 +149,14 @@ bool Arm64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
if (logBlocks_ > 0) {
|
||||
--logBlocks_;
|
||||
|
||||
std::map<const u8 *, int> addressesLookup;
|
||||
for (int i = 0; i < (int)addresses.size(); ++i)
|
||||
addressesLookup[addresses[i]] = i;
|
||||
|
||||
INFO_LOG(JIT, "=============== ARM64 (%08x, %d bytes) ===============", startPC, len);
|
||||
for (const u8 *p = blockStart; p < GetCodePointer(); ) {
|
||||
auto it = addresses.find(p);
|
||||
if (it != addresses.end()) {
|
||||
auto it = addressesLookup.find(p);
|
||||
if (it != addressesLookup.end()) {
|
||||
const IRInst &inst = block->GetInstructions()[it->second];
|
||||
|
||||
char temp[512];
|
||||
|
@ -162,7 +165,7 @@ bool Arm64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
}
|
||||
|
||||
auto next = std::next(it);
|
||||
const u8 *nextp = next == addresses.end() ? GetCodePointer() : next->first;
|
||||
const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first;
|
||||
|
||||
auto lines = DisassembleArm64(p, (int)(nextp - p));
|
||||
for (const auto &line : lines)
|
||||
|
|
|
@ -21,20 +21,18 @@
|
|||
#include <algorithm>
|
||||
|
||||
|
||||
static bool IRReadsFrom(const IRInst &inst, int reg, char type, bool *directly) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if (m->types[1] == type && inst.src1 == reg) {
|
||||
static bool IRReadsFrom(const IRInstMeta &inst, int reg, char type, bool *directly) {
|
||||
if (inst.m.types[1] == type && inst.src1 == reg) {
|
||||
if (directly)
|
||||
*directly = true;
|
||||
return true;
|
||||
}
|
||||
if (m->types[2] == type && inst.src2 == reg) {
|
||||
if (inst.m.types[2] == type && inst.src2 == reg) {
|
||||
if (directly)
|
||||
*directly = true;
|
||||
return true;
|
||||
}
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == type && inst.src3 == reg) {
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == type && inst.src3 == reg) {
|
||||
if (directly)
|
||||
*directly = true;
|
||||
return true;
|
||||
|
@ -42,44 +40,41 @@ static bool IRReadsFrom(const IRInst &inst, int reg, char type, bool *directly)
|
|||
|
||||
if (directly)
|
||||
*directly = false;
|
||||
if ((m->flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0)
|
||||
if ((inst.m.flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IRReadsFromFPR(const IRInst &inst, int reg, bool *directly) {
|
||||
bool IRReadsFromFPR(const IRInstMeta &inst, int reg, bool *directly) {
|
||||
if (IRReadsFrom(inst, reg, 'F', directly))
|
||||
return true;
|
||||
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
// We also need to check V and 2. Indirect reads already checked, don't check again.
|
||||
if (m->types[1] == 'V' && reg >= inst.src1 && reg < inst.src1 + 4)
|
||||
if (inst.m.types[1] == 'V' && reg >= inst.src1 && reg < inst.src1 + 4)
|
||||
return true;
|
||||
if (m->types[1] == '2' && reg >= inst.src1 && reg < inst.src1 + 2)
|
||||
if (inst.m.types[1] == '2' && reg >= inst.src1 && reg < inst.src1 + 2)
|
||||
return true;
|
||||
if (m->types[2] == 'V' && reg >= inst.src2 && reg < inst.src2 + 4)
|
||||
if (inst.m.types[2] == 'V' && reg >= inst.src2 && reg < inst.src2 + 4)
|
||||
return true;
|
||||
if (m->types[2] == '2' && reg >= inst.src2 && reg < inst.src2 + 2)
|
||||
if (inst.m.types[2] == '2' && reg >= inst.src2 && reg < inst.src2 + 2)
|
||||
return true;
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) {
|
||||
if (m->types[0] == 'V' && reg >= inst.src3 && reg <= inst.src3 + 4)
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) {
|
||||
if (inst.m.types[0] == 'V' && reg >= inst.src3 && reg <= inst.src3 + 4)
|
||||
return true;
|
||||
if (m->types[0] == '2' && reg >= inst.src3 && reg <= inst.src3 + 2)
|
||||
if (inst.m.types[0] == '2' && reg >= inst.src3 && reg <= inst.src3 + 2)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int IRReadsFromList(const IRInst &inst, IRReg regs[4], char type) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
static int IRReadsFromList(const IRInstMeta &inst, IRReg regs[4], char type) {
|
||||
int c = 0;
|
||||
|
||||
if (m->types[1] == type)
|
||||
if (inst.m.types[1] == type)
|
||||
regs[c++] = inst.src1;
|
||||
if (m->types[2] == type)
|
||||
if (inst.m.types[2] == type)
|
||||
regs[c++] = inst.src2;
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == type)
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == type)
|
||||
regs[c++] = inst.src3;
|
||||
|
||||
if (inst.op == IROp::Interpret || inst.op == IROp::CallReplacement || inst.op == IROp::Syscall || inst.op == IROp::Break)
|
||||
|
@ -90,56 +85,50 @@ static int IRReadsFromList(const IRInst &inst, IRReg regs[4], char type) {
|
|||
return c;
|
||||
}
|
||||
|
||||
bool IRReadsFromGPR(const IRInst &inst, int reg, bool *directly) {
|
||||
bool IRReadsFromGPR(const IRInstMeta &inst, int reg, bool *directly) {
|
||||
return IRReadsFrom(inst, reg, 'G', directly);
|
||||
}
|
||||
|
||||
int IRDestGPR(const IRInst &inst) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G') {
|
||||
int IRDestGPR(const IRInstMeta &inst) {
|
||||
if ((inst.m.flags & IRFLAG_SRC3) == 0 && inst.m.types[0] == 'G') {
|
||||
return inst.dest;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IRWritesToGPR(const IRInst &inst, int reg) {
|
||||
bool IRWritesToGPR(const IRInstMeta &inst, int reg) {
|
||||
return IRDestGPR(inst) == reg;
|
||||
}
|
||||
|
||||
bool IRWritesToFPR(const IRInst &inst, int reg) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
bool IRWritesToFPR(const IRInstMeta &inst, int reg) {
|
||||
// Doesn't write to anything.
|
||||
if ((m->flags & IRFLAG_SRC3) != 0)
|
||||
if ((inst.m.flags & IRFLAG_SRC3) != 0)
|
||||
return false;
|
||||
|
||||
if (m->types[0] == 'F' && reg == inst.dest)
|
||||
if (inst.m.types[0] == 'F' && reg == inst.dest)
|
||||
return true;
|
||||
if (m->types[0] == 'V' && reg >= inst.dest && reg < inst.dest + 4)
|
||||
if (inst.m.types[0] == 'V' && reg >= inst.dest && reg < inst.dest + 4)
|
||||
return true;
|
||||
if (m->types[0] == '2' && reg >= inst.dest && reg < inst.dest + 2)
|
||||
if (inst.m.types[0] == '2' && reg >= inst.dest && reg < inst.dest + 2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int IRDestFPRs(const IRInst &inst, IRReg regs[4]) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
int IRDestFPRs(const IRInstMeta &inst, IRReg regs[4]) {
|
||||
// Doesn't write to anything.
|
||||
if ((m->flags & IRFLAG_SRC3) != 0)
|
||||
if ((inst.m.flags & IRFLAG_SRC3) != 0)
|
||||
return 0;
|
||||
|
||||
if (m->types[0] == 'F') {
|
||||
if (inst.m.types[0] == 'F') {
|
||||
regs[0] = inst.dest;
|
||||
return 1;
|
||||
}
|
||||
if (m->types[0] == 'V') {
|
||||
if (inst.m.types[0] == 'V') {
|
||||
for (int i = 0; i < 4; ++i)
|
||||
regs[i] = inst.dest + i;
|
||||
return 4;
|
||||
}
|
||||
if (m->types[0] == '2') {
|
||||
if (inst.m.types[0] == '2') {
|
||||
for (int i = 0; i < 2; ++i)
|
||||
regs[i] = inst.dest + i;
|
||||
return 2;
|
||||
|
@ -147,29 +136,27 @@ int IRDestFPRs(const IRInst &inst, IRReg regs[4]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int IRReadsFromGPRs(const IRInst &inst, IRReg regs[4]) {
|
||||
int IRReadsFromGPRs(const IRInstMeta &inst, IRReg regs[4]) {
|
||||
return IRReadsFromList(inst, regs, 'G');
|
||||
}
|
||||
|
||||
int IRReadsFromFPRs(const IRInst &inst, IRReg regs[16]) {
|
||||
int IRReadsFromFPRs(const IRInstMeta &inst, IRReg regs[16]) {
|
||||
int c = IRReadsFromList(inst, regs, 'F');
|
||||
if (c != 0)
|
||||
return c;
|
||||
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
|
||||
// We also need to check V and 2. Indirect reads already checked, don't check again.
|
||||
if (m->types[1] == 'V' || m->types[1] == '2') {
|
||||
for (int i = 0; i < (m->types[1] == 'V' ? 4 : 2); ++i)
|
||||
if (inst.m.types[1] == 'V' || inst.m.types[1] == '2') {
|
||||
for (int i = 0; i < (inst.m.types[1] == 'V' ? 4 : 2); ++i)
|
||||
regs[c++] = inst.src1 + i;
|
||||
}
|
||||
if (m->types[2] == 'V' || m->types[2] == '2') {
|
||||
for (int i = 0; i < (m->types[2] == 'V' ? 4 : 2); ++i)
|
||||
if (inst.m.types[2] == 'V' || inst.m.types[2] == '2') {
|
||||
for (int i = 0; i < (inst.m.types[2] == 'V' ? 4 : 2); ++i)
|
||||
regs[c++] = inst.src2 + i;
|
||||
}
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) {
|
||||
if (m->types[0] == 'V' || m->types[0] == '2') {
|
||||
for (int i = 0; i < (m->types[0] == 'V' ? 4 : 2); ++i)
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0) {
|
||||
if (inst.m.types[0] == 'V' || inst.m.types[0] == '2') {
|
||||
for (int i = 0; i < (inst.m.types[0] == 'V' ? 4 : 2); ++i)
|
||||
regs[c++] = inst.src3 + i;
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +170,7 @@ IRUsage IRNextGPRUsage(int gpr, const IRSituation &info) {
|
|||
|
||||
int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const IRInst inst = info.instructions[info.currentIndex + i];
|
||||
const IRInstMeta inst = GetIRMeta(info.instructions[info.currentIndex + i]);
|
||||
if (IRReadsFromGPR(inst, gpr))
|
||||
return IRUsage::READ;
|
||||
// We say WRITE when the current instruction writes. It's not useful for spilling.
|
||||
|
@ -202,7 +189,7 @@ IRUsage IRNextFPRUsage(int fpr, const IRSituation &info) {
|
|||
|
||||
int count = std::min(info.numInstructions - info.currentIndex, info.lookaheadCount);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const IRInst inst = info.instructions[info.currentIndex + i];
|
||||
const IRInstMeta inst = GetIRMeta(info.instructions[info.currentIndex + i]);
|
||||
|
||||
if (IRReadsFromFPR(inst, fpr)) {
|
||||
// Special case a broadcast that clobbers it.
|
||||
|
|
|
@ -19,14 +19,37 @@
|
|||
|
||||
#include "Core/MIPS/IR/IRInst.h"
|
||||
|
||||
bool IRReadsFromFPR(const IRInst &inst, int reg, bool *directly = nullptr);
|
||||
bool IRReadsFromGPR(const IRInst &inst, int reg, bool *directly = nullptr);
|
||||
bool IRWritesToGPR(const IRInst &inst, int reg);
|
||||
bool IRWritesToFPR(const IRInst &inst, int reg);
|
||||
int IRDestGPR(const IRInst &inst);
|
||||
int IRDestFPRs(const IRInst &inst, IRReg regs[4]);
|
||||
int IRReadsFromGPRs(const IRInst &inst, IRReg regs[4]);
|
||||
int IRReadsFromFPRs(const IRInst &inst, IRReg regs[16]);
|
||||
struct IRInstMeta {
|
||||
union {
|
||||
IRInst i;
|
||||
struct {
|
||||
IROp op;
|
||||
union {
|
||||
IRReg dest;
|
||||
IRReg src3;
|
||||
};
|
||||
IRReg src1;
|
||||
IRReg src2;
|
||||
u32 constant;
|
||||
};
|
||||
};
|
||||
IRMeta m;
|
||||
};
|
||||
|
||||
static_assert(offsetof(IRInst, src2) == offsetof(IRInstMeta, src2));
|
||||
|
||||
inline IRInstMeta GetIRMeta(const IRInst &inst) {
|
||||
return { { inst }, *GetIRMeta(inst.op) };
|
||||
}
|
||||
|
||||
bool IRReadsFromFPR(const IRInstMeta &inst, int reg, bool *directly = nullptr);
|
||||
bool IRReadsFromGPR(const IRInstMeta &inst, int reg, bool *directly = nullptr);
|
||||
bool IRWritesToGPR(const IRInstMeta &inst, int reg);
|
||||
bool IRWritesToFPR(const IRInstMeta &inst, int reg);
|
||||
int IRDestGPR(const IRInstMeta &inst);
|
||||
int IRDestFPRs(const IRInstMeta &inst, IRReg regs[4]);
|
||||
int IRReadsFromGPRs(const IRInstMeta &inst, IRReg regs[4]);
|
||||
int IRReadsFromFPRs(const IRInstMeta &inst, IRReg regs[16]);
|
||||
|
||||
struct IRSituation {
|
||||
int lookaheadCount;
|
||||
|
|
|
@ -341,7 +341,7 @@ enum IRFlags {
|
|||
struct IRMeta {
|
||||
IROp op;
|
||||
const char *name;
|
||||
const char types[5]; // GGG
|
||||
char types[5]; // GGG
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
|
|
|
@ -919,40 +919,37 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
return logBlocks;
|
||||
}
|
||||
|
||||
IRInst IRReplaceSrcGPR(const IRInst &inst, int fromReg, int toReg) {
|
||||
IRInst newInst = inst;
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
IRInstMeta IRReplaceSrcGPR(const IRInstMeta &inst, int fromReg, int toReg) {
|
||||
IRInstMeta newInst = inst;
|
||||
|
||||
if (m->types[1] == 'G' && inst.src1 == fromReg) {
|
||||
if (inst.m.types[1] == 'G' && inst.src1 == fromReg) {
|
||||
newInst.src1 = toReg;
|
||||
}
|
||||
if (m->types[2] == 'G' && inst.src2 == fromReg) {
|
||||
if (inst.m.types[2] == 'G' && inst.src2 == fromReg) {
|
||||
newInst.src2 = toReg;
|
||||
}
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && m->types[0] == 'G' && inst.src3 == fromReg) {
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0 && inst.m.types[0] == 'G' && inst.src3 == fromReg) {
|
||||
newInst.src3 = toReg;
|
||||
}
|
||||
return newInst;
|
||||
}
|
||||
|
||||
IRInst IRReplaceDestGPR(const IRInst &inst, int fromReg, int toReg) {
|
||||
IRInst newInst = inst;
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
IRInstMeta IRReplaceDestGPR(const IRInstMeta &inst, int fromReg, int toReg) {
|
||||
IRInstMeta newInst = inst;
|
||||
|
||||
if ((m->flags & IRFLAG_SRC3) == 0 && m->types[0] == 'G' && inst.dest == fromReg) {
|
||||
if ((inst.m.flags & IRFLAG_SRC3) == 0 && inst.m.types[0] == 'G' && inst.dest == fromReg) {
|
||||
newInst.dest = toReg;
|
||||
}
|
||||
return newInst;
|
||||
}
|
||||
|
||||
bool IRMutatesDestGPR(const IRInst &inst, int reg) {
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
return (m->flags & IRFLAG_SRC3DST) != 0 && m->types[0] == 'G' && inst.src3 == reg;
|
||||
bool IRMutatesDestGPR(const IRInstMeta &inst, int reg) {
|
||||
return (inst.m.flags & IRFLAG_SRC3DST) != 0 && inst.m.types[0] == 'G' && inst.src3 == reg;
|
||||
}
|
||||
|
||||
bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
||||
CONDITIONAL_DISABLE;
|
||||
std::vector<IRInst> insts;
|
||||
std::vector<IRInstMeta> insts;
|
||||
insts.reserve(in.GetInstructions().size());
|
||||
|
||||
// We track writes both to rename regs and to purge dead stores.
|
||||
|
@ -979,7 +976,7 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
memset(lastWrittenTo, -1, sizeof(lastWrittenTo));
|
||||
memset(lastReadFrom, -1, sizeof(lastReadFrom));
|
||||
|
||||
auto readsFromFPRCheck = [](IRInst &inst, Check &check, bool *directly) {
|
||||
auto readsFromFPRCheck = [](IRInstMeta &inst, Check &check, bool *directly) {
|
||||
if (check.reg < 32)
|
||||
return false;
|
||||
|
||||
|
@ -1001,8 +998,7 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
bool logBlocks = false;
|
||||
size_t firstCheck = 0;
|
||||
for (int i = 0, n = (int)in.GetInstructions().size(); i < n; i++) {
|
||||
IRInst inst = in.GetInstructions()[i];
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
IRInstMeta inst = GetIRMeta(in.GetInstructions()[i]);
|
||||
|
||||
// It helps to skip through rechecking ones we already discarded.
|
||||
for (size_t ch = firstCheck; ch < checks.size(); ++ch) {
|
||||
|
@ -1060,14 +1056,13 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
} else {
|
||||
// Legitimately read from, so we can't optimize out.
|
||||
// Unless this is an exit and a temp not read directly by the exit.
|
||||
if ((m->flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly)
|
||||
if ((inst.m.flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly)
|
||||
check.reg = 0;
|
||||
}
|
||||
} else if (check.fplen >= 1 && readsFromFPRCheck(inst, check, &readsDirectly)) {
|
||||
// If one or the other is a Vec, they must match.
|
||||
bool lenMismatch = false;
|
||||
|
||||
const IRMeta *m = GetIRMeta(inst.op);
|
||||
auto checkMismatch = [&check, &lenMismatch](IRReg src, char type) {
|
||||
int srclen = 1;
|
||||
if (type == 'V')
|
||||
|
@ -1083,10 +1078,10 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
}
|
||||
};
|
||||
|
||||
checkMismatch(inst.src1, m->types[1]);
|
||||
checkMismatch(inst.src2, m->types[2]);
|
||||
if ((m->flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0)
|
||||
checkMismatch(inst.src3, m->types[3]);
|
||||
checkMismatch(inst.src1, inst.m.types[1]);
|
||||
checkMismatch(inst.src2, inst.m.types[2]);
|
||||
if ((inst.m.flags & (IRFLAG_SRC3 | IRFLAG_SRC3DST)) != 0)
|
||||
checkMismatch(inst.src3, inst.m.types[3]);
|
||||
|
||||
bool cannotReplace = !readsDirectly || lenMismatch;
|
||||
if (!cannotReplace && check.srcReg >= 32 && lastWrittenTo[check.srcReg] < check.index) {
|
||||
|
@ -1137,10 +1132,10 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
}
|
||||
} else {
|
||||
// Legitimately read from, so we can't optimize out.
|
||||
if ((m->flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly)
|
||||
if ((inst.m.flags & IRFLAG_EXIT) == 0 || check.readByExit || readsDirectly)
|
||||
check.reg = 0;
|
||||
}
|
||||
} else if (check.readByExit && (m->flags & IRFLAG_EXIT) != 0) {
|
||||
} else if (check.readByExit && (inst.m.flags & IRFLAG_EXIT) != 0) {
|
||||
// This is an exit, and the reg is read by any exit. Clear it.
|
||||
check.reg = 0;
|
||||
} else if (IRDestGPR(inst) == check.reg) {
|
||||
|
@ -1261,10 +1256,10 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
}
|
||||
}
|
||||
|
||||
for (const IRInst &inst : insts) {
|
||||
for (const IRInstMeta &inst : insts) {
|
||||
// Simply skip any Mov 0, 0 instructions, since that's how we nuke one.
|
||||
if (inst.op != IROp::Mov || inst.dest != 0 || inst.src1 != 0) {
|
||||
out.Write(inst);
|
||||
out.Write(inst.i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1282,12 +1277,11 @@ bool ReduceLoads(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
IRInst inst = in.GetInstructions()[i];
|
||||
|
||||
if (inst.op == IROp::Load32 || inst.op == IROp::Load16 || inst.op == IROp::Load16Ext) {
|
||||
int dest = IRDestGPR(inst);
|
||||
int dest = IRDestGPR(GetIRMeta(inst));
|
||||
for (int j = i + 1; j < n; j++) {
|
||||
const IRInst &laterInst = in.GetInstructions()[j];
|
||||
const IRMeta *m = GetIRMeta(laterInst.op);
|
||||
const IRInstMeta laterInst = GetIRMeta(in.GetInstructions()[j]);
|
||||
|
||||
if ((m->flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0) {
|
||||
if ((laterInst.m.flags & (IRFLAG_EXIT | IRFLAG_BARRIER)) != 0) {
|
||||
// Exit, so we can't do the optimization.
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -82,12 +82,11 @@ bool RiscVJitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
|
||||
regs_.Start(block);
|
||||
|
||||
std::map<const u8 *, int> addresses;
|
||||
std::vector<const u8 *> addresses;
|
||||
for (int i = 0; i < block->GetNumInstructions(); ++i) {
|
||||
const IRInst &inst = block->GetInstructions()[i];
|
||||
regs_.SetIRIndex(i);
|
||||
// TODO: This might be a little wasteful when compiling if we're not debugging jit...
|
||||
addresses[GetCodePtr()] = i;
|
||||
addresses.push_back(GetCodePtr());
|
||||
|
||||
CompileIRInst(inst);
|
||||
|
||||
|
@ -137,10 +136,14 @@ bool RiscVJitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
if (logBlocks_ > 0) {
|
||||
--logBlocks_;
|
||||
|
||||
std::map<const u8 *, int> addressesLookup;
|
||||
for (int i = 0; i < (int)addresses.size(); ++i)
|
||||
addressesLookup[addresses[i]] = i;
|
||||
|
||||
INFO_LOG(JIT, "=============== RISCV (%08x, %d bytes) ===============", startPC, len);
|
||||
for (const u8 *p = blockStart; p < GetCodePointer(); ) {
|
||||
auto it = addresses.find(p);
|
||||
if (it != addresses.end()) {
|
||||
auto it = addressesLookup.find(p);
|
||||
if (it != addressesLookup.end()) {
|
||||
const IRInst &inst = block->GetInstructions()[it->second];
|
||||
|
||||
char temp[512];
|
||||
|
@ -149,7 +152,7 @@ bool RiscVJitBackend::CompileBlock(IRBlock *block, int block_num, bool preload)
|
|||
}
|
||||
|
||||
auto next = std::next(it);
|
||||
const u8 *nextp = next == addresses.end() ? GetCodePointer() : next->first;
|
||||
const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first;
|
||||
|
||||
#if PPSSPP_ARCH(RISCV64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__))
|
||||
auto lines = DisassembleRV64(p, (int)(nextp - p));
|
||||
|
|
|
@ -86,12 +86,12 @@ bool X64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) {
|
|||
|
||||
regs_.Start(block);
|
||||
|
||||
std::map<const u8 *, int> addresses;
|
||||
std::vector<const u8 *> addresses;
|
||||
addresses.reserve(block->GetNumInstructions());
|
||||
for (int i = 0; i < block->GetNumInstructions(); ++i) {
|
||||
const IRInst &inst = block->GetInstructions()[i];
|
||||
regs_.SetIRIndex(i);
|
||||
// TODO: This might be a little wasteful when compiling if we're not debugging jit...
|
||||
addresses[GetCodePtr()] = i;
|
||||
addresses.push_back(GetCodePtr());
|
||||
|
||||
CompileIRInst(inst);
|
||||
|
||||
|
@ -140,10 +140,14 @@ bool X64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) {
|
|||
if (logBlocks_ > 0) {
|
||||
--logBlocks_;
|
||||
|
||||
std::map<const u8 *, int> addressesLookup;
|
||||
for (int i = 0; i < (int)addresses.size(); ++i)
|
||||
addressesLookup[addresses[i]] = i;
|
||||
|
||||
INFO_LOG(JIT, "=============== x86 (%08x, %d bytes) ===============", startPC, len);
|
||||
for (const u8 *p = blockStart; p < GetCodePointer(); ) {
|
||||
auto it = addresses.find(p);
|
||||
if (it != addresses.end()) {
|
||||
auto it = addressesLookup.find(p);
|
||||
if (it != addressesLookup.end()) {
|
||||
const IRInst &inst = block->GetInstructions()[it->second];
|
||||
|
||||
char temp[512];
|
||||
|
@ -152,7 +156,7 @@ bool X64JitBackend::CompileBlock(IRBlock *block, int block_num, bool preload) {
|
|||
}
|
||||
|
||||
auto next = std::next(it);
|
||||
const u8 *nextp = next == addresses.end() ? GetCodePointer() : next->first;
|
||||
const u8 *nextp = next == addressesLookup.end() ? GetCodePointer() : next->first;
|
||||
|
||||
auto lines = DisassembleX86(p, (int)(nextp - p));
|
||||
for (const auto &line : lines)
|
||||
|
|
Loading…
Add table
Reference in a new issue