-static unsigned getImmScale(unsigned Opc) {
- switch (Opc) {
- default: llvm_unreachable("Unhandled opcode!");
- case ARM::tLDRi:
- case ARM::tSTRi:
- return 1;
- case ARM::tLDRHi:
- case ARM::tSTRHi:
- return 2;
- case ARM::tLDRBi:
- case ARM::tSTRBi:
- return 4;
- }
-}
-
-/// Update future uses of the base register with the offset introduced
-/// due to writeback. This function only works on Thumb1.
-void
-ARMLoadStoreOpt::UpdateBaseRegUses(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- DebugLoc dl, unsigned Base,
- unsigned WordOffset,
- ARMCC::CondCodes Pred, unsigned PredReg) {
- assert(isThumb1 && "Can only update base register uses for Thumb1!");
-
- // Start updating any instructions with immediate offsets. Insert a sub before
- // the first non-updateable instruction (if any).
- for (; MBBI != MBB.end(); ++MBBI) {
- if (MBBI->readsRegister(Base)) {
- unsigned Opc = MBBI->getOpcode();
- int Offset;
- bool InsertSub = false;
-
- if (Opc == ARM::tLDRi || Opc == ARM::tSTRi ||
- Opc == ARM::tLDRHi || Opc == ARM::tSTRHi ||
- Opc == ARM::tLDRBi || Opc == ARM::tSTRBi) {
- // Loads and stores with immediate offsets can be updated, but only if
- // the new offset isn't negative.
- // The MachineOperand containing the offset immediate is the last one
- // before predicates.
- MachineOperand &MO =
- MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
- // The offsets are scaled by 1, 2 or 4 depending on the Opcode
- Offset = MO.getImm() - WordOffset * getImmScale(Opc);
- if (Offset >= 0)
- MO.setImm(Offset);
- else
- InsertSub = true;
-
- } else if (Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) {
- // SUB/ADD using this register. Merge it with the update.
- // If the merged offset is too large, insert a new sub instead.
- MachineOperand &MO =
- MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);
- Offset = (Opc == ARM::tSUBi8) ?
- MO.getImm() + WordOffset * 4 :
- MO.getImm() - WordOffset * 4 ;
- if (TL->isLegalAddImmediate(Offset)) {
- MO.setImm(Offset);
- // The base register has now been reset, so exit early.
- return;
- } else {
- InsertSub = true;
- }
-
- } else {
- // Can't update the instruction.
- InsertSub = true;
- }
-
- if (InsertSub) {
- // An instruction above couldn't be updated, so insert a sub.
- AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII->get(ARM::tSUBi8), Base))
- .addReg(Base, getKillRegState(true)).addImm(WordOffset * 4)
- .addImm(Pred).addReg(PredReg);
- return;
- }
- }
-
- if (MBBI->killsRegister(Base))
- // Register got killed. Stop updating.
- return;
- }
-
- // The end of the block was reached. This means register liveness escapes the
- // block, and it's necessary to insert a sub before the last instruction.
- if (MBB.succ_size() > 0)
- // But only insert the SUB if there is actually a successor block.
- // FIXME: Check more carefully if register is live at this point, e.g. by
- // also examining the successor block's register liveness information.
- AddDefaultT1CC(BuildMI(MBB, --MBBI, dl, TII->get(ARM::tSUBi8), Base))
- .addReg(Base, getKillRegState(true)).addImm(WordOffset * 4)
- .addImm(Pred).addReg(PredReg);
-}
-