[llvm-commits] CVS: llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp

Evan Cheng evan.cheng at apple.com
Tue Mar 6 13:59:37 PST 2007



Changes in directory llvm/lib/Target/ARM:

ARMLoadStoreOptimizer.cpp updated: 1.2 -> 1.3
---
Log message:

Make load / store optimizer use register scavenger.

---
Diffs of the changes:  (+58 -21)

 ARMLoadStoreOptimizer.cpp |   79 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 58 insertions(+), 21 deletions(-)


Index: llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
diff -u llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp:1.2 llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp:1.3
--- llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp:1.2	Tue Mar  6 12:02:41 2007
+++ llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp	Tue Mar  6 15:59:20 2007
@@ -59,6 +59,8 @@
     typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
     typedef MemOpQueue::iterator MemOpQueueIter;
 
+    void AdvanceRS(MachineBasicBlock *MBB, MemOpQueue &MemOps);
+
     SmallVector<MachineBasicBlock::iterator, 4>
     MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
                  int Opcode, unsigned Size, MemOpQueue &MemOps);
@@ -103,8 +105,9 @@
 /// registers in Regs as the register operands that would be loaded / stored.
 /// It returns true if the transformation is done. 
 static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
-                     int Offset, unsigned Base, int Opcode,
-                     SmallVector<unsigned, 8> &Regs,
+                     int Offset, unsigned Base, bool BaseKill, int Opcode,
+                     SmallVector<std::pair<unsigned, bool>, 8> &Regs,
+                     RegScavenger *RS,
                      const TargetInstrInfo *TII) {
   // Only a single register to load / store. Don't bother.
   unsigned NumRegs = Regs.size();
@@ -130,10 +133,12 @@
     if (Opcode == ARM::LDR)
       // If it is a load, then just use one of the destination register to
       // use as the new base.
-      NewBase = Regs[NumRegs-1];
+      NewBase = Regs[NumRegs-1].first;
     else {
-      // FIXME: Try scavenging a register to use as a new base.
-      NewBase = ARM::R12;
+      // Try to find a free register to use as a new base.
+      NewBase = RS ? RS->FindUnusedReg(&ARM::GPRRegClass) : (unsigned)ARM::R12;
+      if (NewBase == 0)
+        return false;
     }
     int BaseOpc = ARM::ADDri;
     if (Offset < 0) {
@@ -143,52 +148,78 @@
     int ImmedOffset = ARM_AM::getSOImmVal(Offset);
     if (ImmedOffset == -1)
       return false;  // Probably not worth it then.
-    BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase).addReg(Base).addImm(ImmedOffset);
+
+    BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase)
+      .addReg(Base, false, false, BaseKill).addImm(ImmedOffset);
     Base = NewBase;
+    BaseKill = true;  // New base is always killed right its use.
   }
 
   bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD;
   bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
   Opcode = getLoadStoreMultipleOpcode(Opcode);
   MachineInstrBuilder MIB = (isAM4)
-    ? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
+    ? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
         .addImm(ARM_AM::getAM4ModeImm(Mode))
-    : BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
+    : BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base, false, false, BaseKill)
         .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs));
   for (unsigned i = 0; i != NumRegs; ++i)
-    MIB = MIB.addReg(Regs[i], Opcode == isDef);
+    MIB = MIB.addReg(Regs[i].first, isDef, false, Regs[i].second);
 
   return true;
 }
 
+/// AdvanceRS - Advance register scavenger to just before the earliest memory
+/// op that is being merged.
+void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock *MBB, MemOpQueue &MemOps) {
+  MachineBasicBlock::iterator Loc = MemOps[0].MBBI;
+  unsigned Position = MemOps[0].Position;
+  for (unsigned i = 1, e = MemOps.size(); i != e; ++i) {
+    if (MemOps[i].Position < Position) {
+      Position = MemOps[i].Position;
+      Loc = MemOps[i].MBBI;
+    }
+  }
+
+  if (Loc != MBB->begin())
+    RS->forward(prior(Loc));
+}
+
+/// MergeLDR_STR - Merge a number of load / store instructions into one or more
+/// load / store multiple instructions.
 SmallVector<MachineBasicBlock::iterator, 4>
 ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB,
                               unsigned SIndex, unsigned Base, int Opcode,
                               unsigned Size, MemOpQueue &MemOps) {
-  bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
+  if (RS && SIndex == 0)
+    AdvanceRS(&MBB, MemOps);
+
   SmallVector<MachineBasicBlock::iterator, 4> Merges;
+  SmallVector<std::pair<unsigned,bool>, 8> Regs;
+  bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
   int Offset = MemOps[SIndex].Offset;
   int SOffset = Offset;
   unsigned Pos = MemOps[SIndex].Position;
   MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
-  SmallVector<unsigned, 8> Regs;
   unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
   unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
-  Regs.push_back(PReg);
+  bool isKill = MemOps[SIndex].MBBI->getOperand(0).isKill();
+  Regs.push_back(std::make_pair(PReg, isKill));
   for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
     int NewOffset = MemOps[i].Offset;
     unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg();
     unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
+    isKill = MemOps[i].MBBI->getOperand(0).isKill();
     // AM4 - register numbers in ascending order.
     // AM5 - consecutive register numbers in ascending order.
     if (NewOffset == Offset + (int)Size &&
         ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) {
       Offset += Size;
-      Regs.push_back(Reg);
+      Regs.push_back(std::make_pair(Reg, isKill));
       PRegNum = RegNum;
     } else {
       // Can't merge this in. Try merge the earlier ones first.
-      if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
+      if (mergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Regs, RS, TII)) {
         Merges.push_back(prior(Loc));
         for (unsigned j = SIndex; j < i; ++j) {
           MBB.erase(MemOps[j].MBBI);
@@ -207,7 +238,8 @@
     }
   }
 
-  if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
+  bool BaseKill = Loc->findRegisterUseOperand(Base, true) != NULL;
+  if (mergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Regs, RS, TII)) {
     Merges.push_back(prior(Loc));
     for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
       MBB.erase(MemOps[i].MBBI);
@@ -381,6 +413,7 @@
                                      const TargetInstrInfo *TII) {
   MachineInstr *MI = MBBI;
   unsigned Base = MI->getOperand(1).getReg();
+  bool BaseKill = MI->getOperand(1).isKill();
   unsigned Bytes = getLSMultipleTransferSize(MI);
   int Opcode = MI->getOpcode();
   bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
@@ -434,18 +467,23 @@
                         true, isDPR ? 2 : 1);
   if (isLd) {
     if (isAM2)
+      // LDR_PRE, LDR_POST;
       BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
-        .addReg(Base, true).addReg(Base).addReg(0).addImm(Offset);
+        .addReg(Base, true)
+        .addReg(Base).addReg(0).addImm(Offset);
     else
-      BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
+      BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base, false, false, BaseKill)
         .addImm(Offset).addReg(MI->getOperand(0).getReg(), true);
   } else {
+    MachineOperand &MO = MI->getOperand(0);
     if (isAM2)
-      BuildMI(MBB, MBBI, TII->get(NewOpc), Base).addReg(MI->getOperand(0).getReg())
+      // STR_PRE, STR_POST;
+      BuildMI(MBB, MBBI, TII->get(NewOpc), Base)
+        .addReg(MO.getReg(), false, false, MO.isKill())
         .addReg(Base).addReg(0).addImm(Offset);
     else
       BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
-        .addImm(Offset).addReg(MI->getOperand(0).getReg(), false);
+        .addImm(Offset).addReg(MO.getReg(), false, false, MO.isKill());
   }
   MBB.erase(MBBI);
 
@@ -494,7 +532,6 @@
       int Opcode = MBBI->getOpcode();
       bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
       unsigned Size = getLSMultipleTransferSize(MBBI);
-
       unsigned Base = MBBI->getOperand(1).getReg();
       unsigned OffIdx = MBBI->getNumOperands()-1;
       unsigned OffField = MBBI->getOperand(OffIdx).getImm();
@@ -564,7 +601,7 @@
     if (TryMerge) {
       if (NumMemOps > 1) {
         SmallVector<MachineBasicBlock::iterator,4> MBBII =
-          MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,MemOps);
+          MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, MemOps);
         // Try folding preceeding/trailing base inc/dec into the generated
         // LDM/STM ops.
         for (unsigned i = 0, e = MBBII.size(); i < e; ++i)






More information about the llvm-commits mailing list