1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

ARM load/store optimizer: Don't materialize a new base register with

ADDS/SUBS unless it's safe to clobber the condition flags.

If the merged instructions are in a range where the CPSR is live,
e.g. between a CMP -> Bcc, we can't safely materialize a new base
register.

This problem is quite rare, I couldn't come up with a test case and I've
never actually seen this happen in the tests I'm running - there is a
potential trigger for this in LNT/oggenc (spills being inserted between
a CMP/Bcc), but at the moment this isn't being merged. I'll try to
reduce that into a small test case once I've committed my upcoming patch
to make merging less conservative.

llvm-svn: 217881
This commit is contained in:
Moritz Roth 2014-09-16 16:25:07 +00:00
parent 52a36b272a
commit 735d692499

View File

@ -323,6 +323,12 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
if (NumRegs <= 1) if (NumRegs <= 1)
return false; return false;
// For Thumb1 targets, it might be necessary to clobber the CPSR to merge.
// Compute liveness information for that register to make the decision.
bool SafeToClobberCPSR = !isThumb1 ||
(MBB.computeRegisterLiveness(TRI, ARM::CPSR, std::prev(MBBI), 15) ==
MachineBasicBlock::LQR_Dead);
ARM_AM::AMSubMode Mode = ARM_AM::ia; ARM_AM::AMSubMode Mode = ARM_AM::ia;
// VFP and Thumb2 do not support IB or DA modes. Thumb1 only supports IA. // VFP and Thumb2 do not support IB or DA modes. Thumb1 only supports IA.
bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode); bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
@ -346,6 +352,11 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
if (NumRegs <= 2) if (NumRegs <= 2)
return false; return false;
// On Thumb1, it's not worth materializing a new base register without
// clobbering the CPSR (i.e. not using ADDS/SUBS).
if (!SafeToClobberCPSR)
return false;
unsigned NewBase; unsigned NewBase;
if (isi32Load(Opcode)) { if (isi32Load(Opcode)) {
// If it is a load, then just use one of the destination register to // If it is a load, then just use one of the destination register to
@ -377,10 +388,10 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
if (isThumb1) { if (isThumb1) {
// Thumb1: depending on immediate size, use either // Thumb1: depending on immediate size, use either
// ADD NewBase, Base, #imm3 // ADDS NewBase, Base, #imm3
// or // or
// MOV NewBase, Base // MOV NewBase, Base
// ADD NewBase, #imm8. // ADDS NewBase, #imm8.
if (Base != NewBase && Offset >= 8) { if (Base != NewBase && Offset >= 8) {
// Need to insert a MOV to the new base first. // Need to insert a MOV to the new base first.
BuildMI(MBB, MBBI, dl, TII->get(ARM::tMOVr), NewBase) BuildMI(MBB, MBBI, dl, TII->get(ARM::tMOVr), NewBase)
@ -390,7 +401,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
Base = NewBase; Base = NewBase;
BaseKill = false; BaseKill = false;
} }
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)) AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase), true)
.addReg(Base, getKillRegState(BaseKill)).addImm(Offset) .addReg(Base, getKillRegState(BaseKill)).addImm(Offset)
.addImm(Pred).addReg(PredReg); .addImm(Pred).addReg(PredReg);
} else { } else {