Fix IRTEMP clash bug. Add more cases to the constant propagation pass.

This commit is contained in:
Henrik Rydgard committed 2016-05-08 10:36:37 +02:00
1 parent aae32bd929
commit 14df39d7c9
9 files changed
+94 -29

No files matched your search

+49 -7
View File
@@ -26,6 +26,12 @@ u32 Evaluate(u32 a, u32 b, IROp op) {
case IROp::And: case IROp::AndConst: return a & b;
case IROp::Or: case IROp::OrConst: return a | b;
case IROp::Xor: case IROp::XorConst: return a ^ b;
case IROp::Shr: case IROp::ShrImm: return a >> b;
case IROp::Sar: case IROp::SarImm: return (s32)a >> b;
case IROp::Ror: case IROp::RorImm: return (a >> b) | (a << (32 - b));
case IROp::Shl: case IROp::ShlImm: return a << b;
case IROp::Slt: case IROp::SltConst: return ((s32)a < (s32)b);
case IROp::SltU: case IROp::SltUConst: return (a < b);
default:
return -1;
}
@@ -38,16 +44,19 @@ IROp ArithToArithConst(IROp op) {
case IROp::And: return IROp::AndConst;
case IROp::Or: return IROp::OrConst;
case IROp::Xor: return IROp::XorConst;
case IROp::Slt: return IROp::SltConst;
case IROp::SltU: return IROp::SltUConst;
default:
return (IROp)-1;
}
}
void PropagateConstants(const IRWriter &in, IRWriter &out) {
bool PropagateConstants(const IRWriter &in, IRWriter &out) {
IRRegCache gpr(&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];
bool symmetric = true;
@@ -57,6 +66,8 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
break;
case IROp::Sub:
case IROp::Slt:
case IROp::SltU:
symmetric = false; // fallthrough
case IROp::Add:
case IROp::And:
@@ -67,7 +78,8 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
} else if (gpr.IsImm(inst.src2) && inst.src1 != inst.src2 && inst.dest != inst.src2) {
gpr.MapDirtyIn(inst.dest, inst.src1);
if (gpr.GetImm(inst.src2) == 0 && (inst.op == IROp::Add || inst.op == IROp::Or)) {
out.Write(IROp::Mov, inst.dest, inst.src1);
if (inst.dest != inst.src1)
out.Write(IROp::Mov, inst.dest, inst.src1);
} else {
out.Write(ArithToArithConst(inst.op), inst.dest, inst.src1, out.AddConstant(gpr.GetImm(inst.src2)));
}
@@ -85,6 +97,8 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
case IROp::AndConst:
case IROp::OrConst:
case IROp::XorConst:
case IROp::SltConst:
case IROp::SltUConst:
if (gpr.IsImm(inst.src1)) {
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), constants[inst.src2], inst.op));
} else {
@@ -93,6 +107,18 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
}
break;
case IROp::ShlImm:
case IROp::ShrImm:
case IROp::RorImm:
case IROp::SarImm:
if (gpr.IsImm(inst.src1)) {
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), inst.src2, inst.op));
} else {
gpr.MapDirtyIn(inst.dest, inst.src1);
goto doDefault;
}
break;
case IROp::Mov:
if (inst.src1 == inst.src2) {
// Nop
@@ -107,18 +133,33 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
case IROp::Store8:
case IROp::Store16:
case IROp::Store32:
// Just pass through, no excessive flushing
gpr.MapInIn(inst.dest, inst.src1);
goto doDefault;
if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest) {
gpr.MapIn(inst.dest);
out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + constants[inst.src2]));
} else {
// Just pass through, no excessive flushing
gpr.MapInIn(inst.dest, inst.src1);
goto doDefault;
}
break;
case IROp::Load8:
case IROp::Load8Ext:
case IROp::Load16:
case IROp::Load16Ext:
case IROp::Load32:
gpr.MapDirtyIn(inst.dest, inst.src1);
goto doDefault;
if (gpr.IsImm(inst.src1) && inst.src1 != inst.dest && inst.src2 != inst.dest) {
gpr.MapDirty(inst.dest);
out.Write(inst.op, inst.dest, 0, out.AddConstant(gpr.GetImm(inst.src1) + constants[inst.src2]));
logBlocks = true;
} else {
gpr.MapDirtyIn(inst.dest, inst.src1);
goto doDefault;
}
break;
case IROp::Syscall:
case IROp::Interpret:
case IROp::ExitToConst:
case IROp::ExitToReg:
case IROp::ExitToConstIfEq:
@@ -155,4 +196,5 @@ void PropagateConstants(const IRWriter &in, IRWriter &out) {
}
}
}
return logBlocks;
}