[llvm-commits] CVS: llvm/lib/Target/ARM/ARMConstantIslandPass.cpp README.txt

Dale Johannesen dalej at apple.com
Wed Feb 28 10:41:39 PST 2007



Changes in directory llvm/lib/Target/ARM:

ARMConstantIslandPass.cpp updated: 1.30 -> 1.31
README.txt updated: 1.14 -> 1.15
---
Log message:

Add intelligence about where to break large blocks.


---
Diffs of the changes:  (+80 -35)

 ARMConstantIslandPass.cpp |   96 ++++++++++++++++++++++++++++++++++------------
 README.txt                |   19 +++------
 2 files changed, 80 insertions(+), 35 deletions(-)


Index: llvm/lib/Target/ARM/ARMConstantIslandPass.cpp
diff -u llvm/lib/Target/ARM/ARMConstantIslandPass.cpp:1.30 llvm/lib/Target/ARM/ARMConstantIslandPass.cpp:1.31
--- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp:1.30	Sun Feb 25 12:31:31 2007
+++ llvm/lib/Target/ARM/ARMConstantIslandPass.cpp	Wed Feb 28 12:41:22 2007
@@ -140,7 +140,7 @@
     void AdjustBBOffsetsAfter(MachineBasicBlock *BB, int delta);
     bool DecrementOldEntry(unsigned CPI, MachineInstr* CPEMI, unsigned Size);
     int LookForExistingCPEntry(CPUser& U, unsigned UserOffset);
-    bool HandleConstantPoolUser(MachineFunction &Fn, CPUser &U);
+    bool HandleConstantPoolUser(MachineFunction &Fn, unsigned CPUserIndex);
     bool CPEIsInRange(MachineInstr *MI, unsigned UserOffset, 
                       MachineInstr *CPEMI, unsigned Disp,
                       bool DoDump);
@@ -197,7 +197,7 @@
   while (true) {
     bool Change = false;
     for (unsigned i = 0, e = CPUsers.size(); i != e; ++i)
-      Change |= HandleConstantPoolUser(Fn, CPUsers[i]);
+      Change |= HandleConstantPoolUser(Fn, i);
     for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
       Change |= FixUpImmediateBr(Fn, ImmBranches[i]);
     if (!Change)
@@ -722,11 +722,19 @@
   return 0;
 }
 
+/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in
+/// the specific unconditional branch instruction.
+static inline unsigned getUnconditionalBrDisp(int Opc) {
+  return (Opc == ARM::tB) ? ((1<<10)-1)*2 : ((1<<23)-1)*4;
+}
+
 /// HandleConstantPoolUser - Analyze the specified user, checking to see if it
 /// is out-of-range.  If so, pick it up the constant pool value and move it some
 /// place in-range.  Return true if we changed any addresses (thus must run
 /// another pass of branch lengthening), false otherwise.
-bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, CPUser &U){
+bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn, 
+                                                unsigned CPUserIndex){
+  CPUser &U = CPUsers[CPUserIndex];
   MachineInstr *UserMI = U.MI;
   MachineInstr *CPEMI  = U.CPEMI;
   unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
@@ -750,6 +758,7 @@
   // away that will work.  Forward references only for now (although later
   // we might find some that are backwards).
   bool WaterFound = false;
+  bool PadNewWater = true;
   if (!WaterList.empty()) {
     for (std::vector<MachineBasicBlock*>::iterator IP = prior(WaterList.end()),
         B = WaterList.begin();; --IP) {
@@ -759,6 +768,17 @@
         DOUT << "found water in range\n";
         // CPE goes before following block (NewMBB).
         NewMBB = next(MachineFunction::iterator(WaterBB));
+        // If WaterBB is an island, don't pad the new island.
+        // If WaterBB is empty, go backwards until we find something that
+        // isn't.  WaterBB may become empty if it's an island whose
+        // contents were moved farther back.
+        if (isThumb) {
+          MachineBasicBlock* BB = WaterBB;
+          while (BB->empty())
+            BB = BB->Prev;
+          if (BB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY)
+            PadNewWater = false;
+        }
         // Remove the original WaterList entry; we want subsequent
         // insertions in this vicinity to go after the one we're
         // about to insert.  This considerably reduces the number
@@ -776,22 +796,32 @@
 
     DOUT << "No water found\n";
     MachineBasicBlock *UserMBB = UserMI->getParent();
-    unsigned TrialOffset = BBOffsets[UserMBB->getNumber()] + 
-                           BBSizes[UserMBB->getNumber()] +
-                           isThumb ? 2 : 4; /* for branch to be added */
+    unsigned OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()] + 
+                                 BBSizes[UserMBB->getNumber()];
+    assert(OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()+1]);
 
     // If the use is at the end of the block, or the end of the block
-    // is within range, make new water there.  (If the block ends in
+    // is within range, make new water there.  (The +2 or 4 below is
+    // for the unconditional branch we will be adding.  If the block ends in
     // an unconditional branch already, it is water, and is known to
-    // be out of range; so it's OK to assume above we'll be adding a Br.)
+    // be out of range, so we'll always be adding one.)
     if (&UserMBB->back() == UserMI ||
-        OffsetIsInRange(UserOffset, TrialOffset, U.MaxDisp, !isThumb)) {
+        OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb ? 2 : 4),
+                        U.MaxDisp, !isThumb)) {
+      DOUT << "Split at end of block\n";
       if (&UserMBB->back() == UserMI)
         assert(BBHasFallthrough(UserMBB) && "Expected a fallthrough BB!");
       NewMBB = next(MachineFunction::iterator(UserMBB));
       // Add an unconditional branch from UserMBB to fallthrough block.
-      // Note the new unconditional branch is not being recorded.
-      BuildMI(UserMBB, TII->get(isThumb ? ARM::tB : ARM::B)).addMBB(NewMBB);
+      // Record it for branch lengthening; this new branch will not get out of
+      // range, but if the preceding conditional branch is out of range, the
+      // targets will be exchanged, and the altered branch may be out of
+      // range, so the machinery has to know about it.
+      int UncondBr = isThumb ? ARM::tB : ARM::B;
+      BuildMI(UserMBB, TII->get(UncondBr)).addMBB(NewMBB);
+      unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
+      ImmBranches.push_back(ImmBranch(&UserMBB->back(), 
+                            MaxDisp, false, UncondBr));
       int delta = isThumb ? 2 : 4;
       BBSizes[UserMBB->getNumber()] += delta;
       AdjustBBOffsetsAfter(UserMBB, delta);
@@ -804,11 +834,37 @@
       // CPE' cannot immediately follow it (that location is 2 bytes
       // farther away from I+1 than CPE was from I) and we'd need to create
       // a new island.
-
-      // Solution of last resort: split the user's MBB right after the user
-      // and insert a clone of the CPE into the newly created water.
-      MachineInstr *NextMI = next(MachineBasicBlock::iterator(UserMI));
-      NewMBB = SplitBlockBeforeInstr(NextMI);
+      // The 4 in the following is for the unconditional branch we'll be
+      // inserting (allows for long branch on Thumb).  The 2 or 0 is for
+      // alignment of the island.
+      unsigned BaseInsertOffset = UserOffset + U.MaxDisp -4 + (isThumb ? 2 : 0);
+      // This could point off the end of the block if we've already got
+      // constant pool entries following this block; only the last one is
+      // in the water list.  Back past any possible branches.
+      if (BaseInsertOffset >= BBOffsets[UserMBB->getNumber()+1])
+        BaseInsertOffset = BBOffsets[UserMBB->getNumber()+1] - 6;
+      unsigned EndInsertOffset = BaseInsertOffset +
+             CPEMI->getOperand(2).getImm();
+      MachineBasicBlock::iterator MI = UserMI;  ++MI;
+      unsigned CPUIndex = CPUserIndex+1;
+      for (unsigned Offset = UserOffset+ARM::GetInstSize(UserMI);
+           Offset < BaseInsertOffset;
+           Offset += ARM::GetInstSize(MI),
+              MI = next(MI)) {
+        if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) {
+          if (!OffsetIsInRange(Offset, EndInsertOffset, 
+                CPUsers[CPUIndex].MaxDisp, !isThumb)) {
+            BaseInsertOffset -= (isThumb ? 2 : 4);
+            EndInsertOffset -= (isThumb ? 2 : 4);
+          }
+          // This is overly conservative, as we don't account for CPEMIs
+          // being reused within the block, but it doesn't matter much.
+          EndInsertOffset += CPUsers[CPUIndex].CPEMI->getOperand(2).getImm();
+          CPUIndex++;
+        }
+      }
+      DOUT << "Split in middle of big block\n";
+      NewMBB = SplitBlockBeforeInstr(prior(MI));
     }
   }
 
@@ -830,7 +886,7 @@
   NumCPEs++;
 
   // Compensate for .align 2 in thumb mode.
-  if (isThumb) Size += 2;  
+  if (isThumb && PadNewWater) Size += 2;
   // Increase the size of the island block to account for the new entry.
   BBSizes[NewIsland->getNumber()] += Size;
   BBOffsets[NewIsland->getNumber()] = BBOffsets[NewMBB->getNumber()];
@@ -902,12 +958,6 @@
   return true;
 }
 
-/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in
-/// the specific unconditional branch instruction.
-static inline unsigned getUnconditionalBrDisp(int Opc) {
-  return (Opc == ARM::tB) ? (1<<10)*2 : (1<<23)*4;
-}
-
 /// FixUpConditionalBr - Fix up a conditional branch whose destination is too
 /// far away to fit in its displacement field. It is converted to an inverse
 /// conditional branch + an unconditional branch to the destination.


Index: llvm/lib/Target/ARM/README.txt
diff -u llvm/lib/Target/ARM/README.txt:1.14 llvm/lib/Target/ARM/README.txt:1.15
--- llvm/lib/Target/ARM/README.txt:1.14	Sun Feb 25 12:31:31 2007
+++ llvm/lib/Target/ARM/README.txt	Wed Feb 28 12:41:23 2007
@@ -17,24 +17,19 @@
 
 //===---------------------------------------------------------------------===//
 
-The constant island pass has been much improved; all the todo items in the
-previous version of this document have been addressed.  However, there are still
-things that can be done:
-
-1.  When there isn't an existing water, the current MBB is split right after 
-the use.  It would be profitable to look farther forward, especially on Thumb,
-where negative offsets won't work.
-(Partially fixed:  it will put the island at the end of the block if that is 
-in range.  If it is not in range things still work as above, which is poor on 
-Thumb.)
+The constant island pass is in good shape.  Some cleanups might be desirable,
+but there is unlikely to be much improvement in the generated code.
 
-2.  There may be some advantage to trying to be smarter about the initial
+1.  There may be some advantage to trying to be smarter about the initial
 placement, rather than putting everything at the end.
 
-3.  The handling of 2-byte padding for Thumb is overly conservative.  There 
+2.  The handling of 2-byte padding for Thumb is overly conservative.  There 
 would be a small gain to keeping accurate track of the padding (which would
 require aligning functions containing constant pools to 4-byte boundaries).
 
+3.  There might be some compile-time efficiency to be had by representing
+consecutive islands as a single block rather than multiple blocks.
+
 //===---------------------------------------------------------------------===//
 
 We need to start generating predicated instructions.  The .td files have a way






More information about the llvm-commits mailing list