Skip to content

More minor IR optimizations #19265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions Core/MIPS/IR/IRCompALU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,20 @@ void IRFrontend::Comp_Special3(MIPSOpcode op) {
{
u32 sourcemask = mask >> pos;
u32 destmask = ~(sourcemask << pos);
ir.Write(IROp::AndConst, IRTEMP_0, rs, ir.AddConstant(sourcemask));
if (pos != 0) {
ir.Write(IROp::ShlImm, IRTEMP_0, IRTEMP_0, pos);

if (size != 32) {
// Need to use the sourcemask.
ir.Write(IROp::AndConst, IRTEMP_0, rs, ir.AddConstant(sourcemask));
if (pos != 0) {
ir.Write(IROp::ShlImm, IRTEMP_0, IRTEMP_0, pos);
}
} else {
// If the shl takes care of the sourcemask, don't need to and.
if (pos != 0) {
ir.Write(IROp::ShlImm, IRTEMP_0, rs, pos);
} else {
ir.Write(IROp::Mov, IRTEMP_0, rs);
}
}
ir.Write(IROp::AndConst, rt, rt, ir.AddConstant(destmask));
ir.Write(IROp::Or, rt, rt, IRTEMP_0);
Expand Down
1 change: 1 addition & 0 deletions Core/MIPS/IR/IRInst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static const IRMeta irMeta[] = {
{ IROp::FMovFromGPR, "FMovFromGPR", "FG" },
{ IROp::FMovToGPR, "FMovToGPR", "GF" },
{ IROp::OptFMovToGPRShr8, "OptFMovToGPRShr8", "GF" },
{ IROp::OptFCvtSWFromGPR, "OptFCvtSWFromGPR", "FG" },
{ IROp::FpCondFromReg, "FpCondFromReg", "_G" },
{ IROp::FpCondToReg, "FpCondToReg", "G" },
{ IROp::FpCtrlFromReg, "FpCtrlFromReg", "_G" },
Expand Down
1 change: 1 addition & 0 deletions Core/MIPS/IR/IRInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ enum class IROp : uint8_t {
FCvtScaledSW,

FMovFromGPR,
OptFCvtSWFromGPR,
FMovToGPR,
OptFMovToGPRShr8,

Expand Down
4 changes: 4 additions & 0 deletions Core/MIPS/IR/IRInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) {
case IROp::FMovFromGPR:
memcpy(&mips->f[inst->dest], &mips->r[inst->src1], 4);
break;
case IROp::OptFCvtSWFromGPR:
mips->f[inst->dest] = (float)(int)mips->r[inst->src1];
break;
case IROp::FMovToGPR:
memcpy(&mips->r[inst->dest], &mips->f[inst->src1], 4);
break;
Expand All @@ -1007,6 +1010,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) {
mips->r[inst->dest] = temp >> 8;
break;
}

case IROp::ExitToConst:
return inst->constant;

Expand Down
52 changes: 48 additions & 4 deletions Core/MIPS/IR/IRPassSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,15 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions
CONDITIONAL_DISABLE;

bool logBlocks = false;

bool letThroughHalves = false;
if (opts.optimizeForInterpreter) {
// If we're using the interpreter, which can handle these instructions directly,
// don't break "half" instructions up.
// Of course, we still want to combine if possible.
letThroughHalves = true;
}

for (int i = 0, n = (int)in.GetInstructions().size(); i < n; ++i) {
const IRInst &inst = in.GetInstructions()[i];

Expand Down Expand Up @@ -305,6 +314,11 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions
switch (inst.op) {
case IROp::Load32Left:
if (!combineOpposite(IROp::Load32Right, -3, IROp::Load32, -3)) {
if (letThroughHalves) {
out.Write(inst);
break;
}

addCommonProlog();
// dest &= (0x00ffffff >> shift)
// Alternatively, could shift to a wall and back (but would require two shifts each way.)
Expand Down Expand Up @@ -339,6 +353,10 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions

case IROp::Load32Right:
if (!combineOpposite(IROp::Load32Left, 3, IROp::Load32, 0)) {
if (letThroughHalves) {
out.Write(inst);
break;
}
addCommonProlog();
// IRTEMP_LR_VALUE >>= shift
out.Write(IROp::Shr, IRTEMP_LR_VALUE, IRTEMP_LR_VALUE, IRTEMP_LR_SHIFT);
Expand Down Expand Up @@ -382,6 +400,10 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions

case IROp::Store32Left:
if (!combineOpposite(IROp::Store32Right, -3, IROp::Store32, -3)) {
if (letThroughHalves) {
out.Write(inst);
break;
}
addCommonProlog();
// IRTEMP_LR_VALUE &= 0xffffff00 << shift
out.WriteSetConstant(IRTEMP_LR_MASK, 0xffffff00);
Expand All @@ -399,6 +421,10 @@ bool RemoveLoadStoreLeftRight(const IRWriter &in, IRWriter &out, const IROptions

case IROp::Store32Right:
if (!combineOpposite(IROp::Store32Left, 3, IROp::Store32, 0)) {
if (letThroughHalves) {
out.Write(inst);
break;
}
addCommonProlog();
// IRTEMP_LR_VALUE &= 0x00ffffff << (24 - shift)
out.WriteSetConstant(IRTEMP_LR_MASK, 0x00ffffff);
Expand Down Expand Up @@ -2174,13 +2200,23 @@ bool OptimizeLoadsAfterStores(const IRWriter &in, IRWriter &out, const IROptions
case IROp::Store32:
if (next.op == IROp::Load32 &&
next.constant == inst.constant &&
next.dest == inst.src3 &&
next.dest == inst.dest &&
next.src1 == inst.src1) {
// The upcoming load is completely redundant.
// Skip it.
i++;
}
break;
case IROp::StoreVec4:
if (next.op == IROp::LoadVec4 &&
next.constant == inst.constant &&
next.dest == inst.dest &&
next.src1 == inst.src1) {
// The upcoming load is completely redundant. These are common in Wipeout.
// Skip it. NOTE: It looks like vector load/stores uses different register assignments, but there's a union between dest and src3.
i++;
}
break;
default:
break;
}
Expand Down Expand Up @@ -2243,10 +2279,18 @@ bool OptimizeForInterpreter(const IRWriter &in, IRWriter &out, const IROptions &
inst.op = IROp::OptFMovToGPRShr8;
i++; // Skip the next instruction.
}
out.Write(inst);
} else {
out.Write(inst);
}
out.Write(inst);
break;
case IROp::FMovFromGPR:
if (!last) {
IRInst next = in.GetInstructions()[i + 1];
if (next.op == IROp::FCvtSW && next.src1 == inst.dest && next.dest == inst.dest) {
inst.op = IROp::OptFCvtSWFromGPR;
i++; // Skip the next
}
}
out.Write(inst);
break;
default:
out.Write(inst);
Expand Down
Loading