diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index 0ccb7607de..80aa692f86 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -857,6 +857,15 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) { // We're changing "Mov A, B; Add C, C, A" to "Mov A, B; Add C, C, B" here. // srcReg should only be set when it was a Mov. inst = IRReplaceSrcGPR(inst, check.reg, check.srcReg); + + // If the Mov modified the same reg as this instruction, we can't optimize from it anymore. + if (inst.dest == check.reg) { + check.reg = 0; + // We can also optimize it out since we've essentially moved now. + insts[check.index].op = IROp::Mov; + insts[check.index].dest = 0; + insts[check.index].src1 = 0; + } } else if (!IRMutatesDestGPR(insts[check.index], check.reg) && inst.op == IROp::Mov && i == check.index + 1) { // As long as the previous inst wasn't modifying its dest reg, and this is a Mov, we can swap. // We're changing "Add A, B, C; Mov B, A" to "Add B, B, C; Mov A, B" here. diff --git a/unittest/TestIRPassSimplify.cpp b/unittest/TestIRPassSimplify.cpp index 2703a3edaf..2f47b80f56 100644 --- a/unittest/TestIRPassSimplify.cpp +++ b/unittest/TestIRPassSimplify.cpp @@ -92,6 +92,19 @@ static const IRVerification tests[] = { }, { &PurgeTemps }, }, + { + "Load32LeftPurgeTemps", + { + { IROp::Mov, { IRTEMP_LR_ADDR }, MIPS_REG_A0 }, + { IROp::AndConst, { IRTEMP_LR_ADDR }, IRTEMP_LR_ADDR, 0, 0xFFFFFFFC }, + { IROp::Load32, { MIPS_REG_V0 }, IRTEMP_LR_ADDR, 0, 0 }, + }, + { + { IROp::AndConst, { IRTEMP_LR_ADDR }, MIPS_REG_A0, 0, 0xFFFFFFFC }, + { IROp::Load32, { MIPS_REG_V0 }, IRTEMP_LR_ADDR, 0, 0 }, + }, + { &PurgeTemps }, + }, { "SwapClobberTemp", {