diff options
Diffstat (limited to 'lib/Target/ARM/ARMLoadStoreOptimizer.cpp')
-rw-r--r-- | lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 245 |
1 files changed, 130 insertions, 115 deletions
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index 19f1e3b..8fbcf45 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -243,8 +243,9 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, BaseKill = true; // New base is always killed right its use. } - bool isDPR = Opcode == ARM::VLDRD || Opcode == ARM::VSTRD; - bool isDef = isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD; + bool isDPR = (Opcode == ARM::VLDRD || Opcode == ARM::VSTRD); + bool isDef = (isi32Load(Opcode) || Opcode == ARM::VLDRS || + Opcode == ARM::VLDRD); Opcode = getLoadStoreMultipleOpcode(Opcode); MachineInstrBuilder MIB = (isAM4) ? BuildMI(MBB, MBBI, dl, TII->get(Opcode)) @@ -254,7 +255,6 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, .addReg(Base, getKillRegState(BaseKill)) .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs)) .addImm(Pred).addReg(PredReg); - MIB.addReg(0); // Add optional writeback (0 for now). for (unsigned i = 0; i != NumRegs; ++i) MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef) | getKillRegState(Regs[i].second)); @@ -443,7 +443,7 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { case ARM::STM: case ARM::t2LDM: case ARM::t2STM: - return (MI->getNumOperands() - 5) * 4; + return (MI->getNumOperands() - 4) * 4; case ARM::VLDMS: case ARM::VSTMS: case ARM::VLDMD: @@ -452,6 +452,21 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { } } +static unsigned getUpdatingLSMultipleOpcode(unsigned Opc) { + switch (Opc) { + case ARM::LDM: return ARM::LDM_UPD; + case ARM::STM: return ARM::STM_UPD; + case ARM::t2LDM: return ARM::t2LDM_UPD; + case ARM::t2STM: return ARM::t2STM_UPD; + case ARM::VLDMS: return ARM::VLDMS_UPD; + case ARM::VLDMD: return ARM::VLDMD_UPD; + case ARM::VSTMS: return ARM::VSTMS_UPD; + case ARM::VSTMD: return ARM::VSTMD_UPD; + default: llvm_unreachable("Unhandled opcode!"); + } + return 0; +} + /// MergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base /// register into the LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible: /// @@ -470,117 +485,119 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I) { MachineInstr *MI = MBBI; unsigned Base = MI->getOperand(0).getReg(); + bool BaseKill = MI->getOperand(0).isKill(); unsigned Bytes = getLSMultipleTransferSize(MI); unsigned PredReg = 0; ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg); int Opcode = MI->getOpcode(); - bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::t2LDM || - Opcode == ARM::STM || Opcode == ARM::t2STM; + DebugLoc dl = MI->getDebugLoc(); + bool isAM4 = (Opcode == ARM::LDM || Opcode == ARM::t2LDM || + Opcode == ARM::STM || Opcode == ARM::t2STM); - if (isAM4) { - if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm())) - return false; + bool DoMerge = false; + ARM_AM::AMSubMode Mode = ARM_AM::ia; + unsigned Offset = 0; - // Can't use the updating AM4 sub-mode if the base register is also a dest + if (isAM4) { + // Can't use an updating ld/st if the base register is also a dest // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined. for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) { if (MI->getOperand(i).getReg() == Base) return false; } + assert(!ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm())); + Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); + } else { + // VLDM{D|S}, VSTM{D|S} addressing mode 5 ops. + assert(!ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm())); + Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm()); + Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm()); + } - ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); - if (MBBI != MBB.begin()) { - MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + // Try merging with the previous instruction. + if (MBBI != MBB.begin()) { + MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + if (isAM4) { if (Mode == ARM_AM::ia && isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true)); - MI->getOperand(4).setReg(Base); - MI->getOperand(4).setIsDef(); - MBB.erase(PrevMBBI); - return true; - } else if (Mode == ARM_AM::ib && + DoMerge = true; + Mode = ARM_AM::db; + } else if (isAM4 && Mode == ARM_AM::ib && isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true)); - MI->getOperand(4).setReg(Base); // WB to base - MI->getOperand(4).setIsDef(); - MBB.erase(PrevMBBI); - return true; + DoMerge = true; + Mode = ARM_AM::da; + } + } else { + if (Mode == ARM_AM::ia && + isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { + Mode = ARM_AM::db; + DoMerge = true; } } + if (DoMerge) + MBB.erase(PrevMBBI); + } - if (MBBI != MBB.end()) { - MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI); + // Try merging with the next instruction. + if (!DoMerge && MBBI != MBB.end()) { + MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI); + if (isAM4) { if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) && isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); - MI->getOperand(4).setReg(Base); // WB to base - MI->getOperand(4).setIsDef(); - if (NextMBBI == I) { - Advance = true; - ++I; - } - MBB.erase(NextMBBI); - return true; + DoMerge = true; } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) && isMatchingDecrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); - MI->getOperand(4).setReg(Base); // WB to base - MI->getOperand(4).setIsDef(); - if (NextMBBI == I) { - Advance = true; - ++I; - } - MBB.erase(NextMBBI); - return true; + DoMerge = true; } - } - } else { - // VLDM{D|S}, VSTM{D|S} addressing mode 5 ops. - if (ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm())) - return false; - - ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm()); - unsigned Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm()); - if (MBBI != MBB.begin()) { - MachineBasicBlock::iterator PrevMBBI = prior(MBBI); + } else { if (Mode == ARM_AM::ia && - isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset)); - MI->getOperand(4).setReg(Base); // WB to base - MI->getOperand(4).setIsDef(); - MBB.erase(PrevMBBI); - return true; + isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { + DoMerge = true; } } - - if (MBBI != MBB.end()) { - MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI); - if (Mode == ARM_AM::ia && - isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) { - MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset)); - MI->getOperand(4).setReg(Base); // WB to base - MI->getOperand(4).setIsDef(); - if (NextMBBI == I) { - Advance = true; - ++I; - } - MBB.erase(NextMBBI); + if (DoMerge) { + if (NextMBBI == I) { + Advance = true; + ++I; } - return true; + MBB.erase(NextMBBI); } } - return false; + if (!DoMerge) + return false; + + unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode); + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) + .addReg(Base, getDefRegState(true)) // WB base register + .addReg(Base, getKillRegState(BaseKill)); + if (isAM4) { + // [t2]LDM_UPD, [t2]STM_UPD + MIB.addImm(ARM_AM::getAM4ModeImm(Mode, true)) + .addImm(Pred).addReg(PredReg); + } else { + // VLDM[SD}_UPD, VSTM[SD]_UPD + MIB.addImm(ARM_AM::getAM5Opc(Mode, true, Offset)) + .addImm(Pred).addReg(PredReg); + } + // Transfer the rest of operands. + for (unsigned OpNum = 4, e = MI->getNumOperands(); OpNum != e; ++OpNum) + MIB.addOperand(MI->getOperand(OpNum)); + // Transfer memoperands. + (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); + + MBB.erase(MBBI); + return true; } static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { switch (Opc) { case ARM::LDR: return ARM::LDR_PRE; case ARM::STR: return ARM::STR_PRE; - case ARM::VLDRS: return ARM::VLDMS; - case ARM::VLDRD: return ARM::VLDMD; - case ARM::VSTRS: return ARM::VSTMS; - case ARM::VSTRD: return ARM::VSTMD; + case ARM::VLDRS: return ARM::VLDMS_UPD; + case ARM::VLDRD: return ARM::VLDMD_UPD; + case ARM::VSTRS: return ARM::VSTMS_UPD; + case ARM::VSTRD: return ARM::VSTMD_UPD; case ARM::t2LDRi8: case ARM::t2LDRi12: return ARM::t2LDR_PRE; @@ -596,10 +613,10 @@ static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) { switch (Opc) { case ARM::LDR: return ARM::LDR_POST; case ARM::STR: return ARM::STR_POST; - case ARM::VLDRS: return ARM::VLDMS; - case ARM::VLDRD: return ARM::VLDMD; - case ARM::VSTRS: return ARM::VSTMS; - case ARM::VSTRD: return ARM::VSTMD; + case ARM::VLDRS: return ARM::VLDMS_UPD; + case ARM::VLDRD: return ARM::VLDMD_UPD; + case ARM::VSTRS: return ARM::VSTMS_UPD; + case ARM::VSTRD: return ARM::VSTMD_UPD; case ARM::t2LDRi8: case ARM::t2LDRi12: return ARM::t2LDR_POST; @@ -624,14 +641,14 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, unsigned Bytes = getLSMultipleTransferSize(MI); int Opcode = MI->getOpcode(); DebugLoc dl = MI->getDebugLoc(); - bool isAM5 = Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || - Opcode == ARM::VSTRD || Opcode == ARM::VSTRS; - bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; + bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS || + Opcode == ARM::VSTRD || Opcode == ARM::VSTRS); + bool isAM2 = (Opcode == ARM::LDR || Opcode == ARM::STR); if (isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) return false; - else if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) + if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0) return false; - else if (isT2i32Load(Opcode) || isT2i32Store(Opcode)) + if (isT2i32Load(Opcode) || isT2i32Store(Opcode)) if (MI->getOperand(2).getImm() != 0) return false; @@ -648,33 +665,35 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, unsigned NewOpc = 0; // AM2 - 12 bits, thumb2 - 8 bits. unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100); + + // Try merging with the previous instruction. if (MBBI != MBB.begin()) { MachineBasicBlock::iterator PrevMBBI = prior(MBBI); if (isMatchingDecrement(PrevMBBI, Base, Bytes, Limit, Pred, PredReg)) { DoMerge = true; AddSub = ARM_AM::sub; - NewOpc = getPreIndexedLoadStoreOpcode(Opcode); } else if (!isAM5 && isMatchingIncrement(PrevMBBI, Base, Bytes, Limit,Pred,PredReg)) { DoMerge = true; - NewOpc = getPreIndexedLoadStoreOpcode(Opcode); } - if (DoMerge) + if (DoMerge) { + NewOpc = getPreIndexedLoadStoreOpcode(Opcode); MBB.erase(PrevMBBI); + } } + // Try merging with the next instruction. if (!DoMerge && MBBI != MBB.end()) { MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI); if (!isAM5 && isMatchingDecrement(NextMBBI, Base, Bytes, Limit, Pred, PredReg)) { DoMerge = true; AddSub = ARM_AM::sub; - NewOpc = getPostIndexedLoadStoreOpcode(Opcode); } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Limit,Pred,PredReg)) { DoMerge = true; - NewOpc = getPostIndexedLoadStoreOpcode(Opcode); } if (DoMerge) { + NewOpc = getPostIndexedLoadStoreOpcode(Opcode); if (NextMBBI == I) { Advance = true; ++I; @@ -689,22 +708,25 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, bool isDPR = NewOpc == ARM::VLDMD || NewOpc == ARM::VSTMD; unsigned Offset = 0; if (isAM5) - Offset = ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) - ? ARM_AM::db - : ARM_AM::ia, true, (isDPR ? 2 : 1)); + Offset = ARM_AM::getAM5Opc(AddSub == ARM_AM::sub ? ARM_AM::db : ARM_AM::ia, + true, (isDPR ? 2 : 1)); else if (isAM2) Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); else Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; - if (isLd) { - if (isAM5) - // VLDMS, VLDMD - BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) - .addReg(Base, getKillRegState(BaseKill)) - .addImm(Offset).addImm(Pred).addReg(PredReg) - .addReg(Base, getDefRegState(true)) // WB base register - .addReg(MI->getOperand(0).getReg(), RegState::Define); - else if (isAM2) + + if (isAM5) { + // VLDM[SD}_UPD, VSTM[SD]_UPD + MachineOperand &MO = MI->getOperand(0); + BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) + .addReg(Base, getDefRegState(true)) // WB base register + .addReg(Base, getKillRegState(isLd ? BaseKill : false)) + .addImm(Offset) + .addImm(Pred).addReg(PredReg) + .addReg(MO.getReg(), (isLd ? getDefRegState(true) : + getKillRegState(MO.isKill()))); + } else if (isLd) { + if (isAM2) // LDR_PRE, LDR_POST, BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg()) .addReg(Base, RegState::Define) @@ -716,13 +738,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg); } else { MachineOperand &MO = MI->getOperand(0); - if (isAM5) - // VSTMS, VSTMD - BuildMI(MBB, MBBI, dl, TII->get(NewOpc)).addReg(Base).addImm(Offset) - .addImm(Pred).addReg(PredReg) - .addReg(Base, getDefRegState(true)) // WB base register - .addReg(MO.getReg(), getKillRegState(MO.isKill())); - else if (isAM2) + if (isAM2) // STR_PRE, STR_POST BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base) .addReg(MO.getReg(), getKillRegState(MO.isKill())) @@ -910,7 +926,6 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, .addReg(BaseReg, getKillRegState(BaseKill)) .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addImm(Pred).addReg(PredReg) - .addReg(0) .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill)) .addReg(OddReg, getDefRegState(isLd) | getDeadRegState(OddDeadKill)); ++NumLDRD2LDM; @@ -919,7 +934,6 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, .addReg(BaseReg, getKillRegState(BaseKill)) .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addImm(Pred).addReg(PredReg) - .addReg(0) .addReg(EvenReg, getKillRegState(EvenDeadKill) | getUndefRegState(EvenUndef)) .addReg(OddReg, @@ -1157,7 +1171,8 @@ bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) { if (MBBI != MBB.begin() && (MBBI->getOpcode() == ARM::BX_RET || MBBI->getOpcode() == ARM::tBX_RET)) { MachineInstr *PrevMI = prior(MBBI); - if (PrevMI->getOpcode() == ARM::LDM || PrevMI->getOpcode() == ARM::t2LDM) { + if (PrevMI->getOpcode() == ARM::LDM_UPD || + PrevMI->getOpcode() == ARM::t2LDM_UPD) { MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1); if (MO.getReg() != ARM::LR) return false; |