[llvm-commits] [llvm] r86999 - /llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp

Jim Grosbach grosbach at apple.com
Thu Nov 12 09:25:07 PST 2009


Author: grosbach
Date: Thu Nov 12 11:25:07 2009
New Revision: 86999

URL: http://llvm.org/viewvc/llvm-project?rev=86999&view=rev
Log:
Update TB[BH] layout optimization. Add support for moving the target block
to directly follow the jump table. Move the layout changes to prior to any
constant island handling.


Modified:
    llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp

Modified: llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp?rev=86999&r1=86998&r2=86999&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp Thu Nov 12 11:25:07 2009
@@ -44,6 +44,7 @@
 STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk");
 STATISTIC(NumCBZ,        "Number of CBZ / CBNZ formed");
 STATISTIC(NumJTMoved,    "Number of jump table destination blocks moved");
+STATISTIC(NumJTInserted, "Number of jump table intermediate blocks inserted");
 
 
 static cl::opt<bool>
@@ -181,6 +182,7 @@
     void DoInitialPlacement(MachineFunction &MF,
                             std::vector<MachineInstr*> &CPEMIs);
     CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
+    void JumpTableFunctionScan(MachineFunction &MF);
     void InitialFunctionScan(MachineFunction &MF,
                              const std::vector<MachineInstr*> &CPEMIs);
     MachineBasicBlock *SplitBlockBeforeInstr(MachineInstr *MI);
@@ -208,6 +210,7 @@
     bool UndoLRSpillRestore();
     bool OptimizeThumb2Instructions(MachineFunction &MF);
     bool OptimizeThumb2Branches(MachineFunction &MF);
+    bool ReorderThumb2JumpTables(MachineFunction &MF);
     bool OptimizeThumb2JumpTables(MachineFunction &MF);
     MachineBasicBlock *AdjustJTTargetBlockForward(MachineBasicBlock *BB,
                                                   MachineBasicBlock *JTBB);
@@ -271,6 +274,20 @@
   // the numbers agree with the position of the block in the function.
   MF.RenumberBlocks();
 
+  // Try to reorder and otherwise adjust the block layout to make good use
+  // of the TB[BH] instructions.
+  bool MadeChange = false;
+  if (isThumb2 && AdjustJumpTableBlocks) {
+    JumpTableFunctionScan(MF);
+    MadeChange |= ReorderThumb2JumpTables(MF);
+    // Data is out of date, so clear it. It'll be re-computed later.
+    BBSizes.clear();
+    BBOffsets.clear();
+    T2JumpTables.clear();
+    // Blocks may have shifted around. Keep the numbering up to date.
+    MF.RenumberBlocks();
+  }
+
   // Thumb1 functions containing constant pools get 4-byte alignment.
   // This is so we can keep exact track of where the alignment padding goes.
 
@@ -301,7 +318,6 @@
 
   // Iteratively place constant pool entries and fix up branches until there
   // is no change.
-  bool MadeChange = false;
   unsigned NoCPIters = 0, NoBRIters = 0;
   while (true) {
     bool CPChange = false;
@@ -418,6 +434,39 @@
   return NULL;
 }
 
+/// JumpTableFunctionScan - Do a scan of the function, building up
+/// information about the sizes of each block and the locations of all
+/// the jump tables.
+void ARMConstantIslands::JumpTableFunctionScan(MachineFunction &MF) {
+  unsigned Offset = 0;
+  for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end();
+       MBBI != E; ++MBBI) {
+    MachineBasicBlock &MBB = *MBBI;
+
+    unsigned MBBSize = 0;
+    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
+         I != E; ++I) {
+      // Add instruction size to MBBSize.
+      MBBSize += TII->GetInstSizeInBytes(I);
+
+      int Opc = I->getOpcode();
+      if (I->getDesc().isBranch()) {
+        switch (Opc) {
+        default:
+          continue;  // Ignore other JT branches
+        case ARM::t2BR_JT:
+          T2JumpTables.push_back(I);
+          continue;   // Does not get an entry in ImmBranches
+        }
+      }
+    }
+
+    BBSizes.push_back(MBBSize);
+    BBOffsets.push_back(Offset);
+    Offset += MBBSize;
+  }
+}
+
 /// InitialFunctionScan - Do the initial scan of the function, building up
 /// information about the sizes of each block, the location of all the water,
 /// and finding all of the constant pool users.
@@ -1561,7 +1610,6 @@
   return MadeChange;
 }
 
-
 /// OptimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller
 /// jumptables when it's possible.
 bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) {
@@ -1580,33 +1628,10 @@
     unsigned JTI = JTOP.getIndex();
     assert(JTI < JT.size());
 
-    // We prefer if target blocks for the jump table come after the jump
-    // instruction so we can use TB[BH]. Loop through the target blocks
-    // and try to adjust them such that that's true.
-    unsigned JTOffset = GetOffsetOf(MI) + 4;
-    const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
-    if (AdjustJumpTableBlocks) {
-      for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) {
-        MachineBasicBlock *MBB = JTBBs[j];
-        unsigned DstOffset = BBOffsets[MBB->getNumber()];
-
-        if (DstOffset < JTOffset) {
-          // The destination precedes the switch. Try to move the block forward
-          // so we have a positive offset.
-          MachineBasicBlock *NewBB =
-            AdjustJTTargetBlockForward(MBB, MI->getParent());
-          if (NewBB) {
-            MJTI->ReplaceMBBInJumpTables(JTBBs[j], NewBB);
-            JTOffset = GetOffsetOf(MI) + 4;
-            DstOffset = BBOffsets[MBB->getNumber()];
-          }
-        }
-      }
-    }
-
     bool ByteOk = true;
     bool HalfWordOk = true;
-    JTOffset = GetOffsetOf(MI) + 4;
+    unsigned JTOffset = GetOffsetOf(MI) + 4;
+    const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
     for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) {
       MachineBasicBlock *MBB = JTBBs[j];
       unsigned DstOffset = BBOffsets[MBB->getNumber()];
@@ -1693,16 +1718,73 @@
   return MadeChange;
 }
 
+/// ReorderThumb2JumpTables - Use tbb / tbh instructions to generate smaller
+/// jumptables when it's possible.
+bool ARMConstantIslands::ReorderThumb2JumpTables(MachineFunction &MF) {
+  bool MadeChange = false;
+
+  MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
+  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+  for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) {
+    MachineInstr *MI = T2JumpTables[i];
+    const TargetInstrDesc &TID = MI->getDesc();
+    unsigned NumOps = TID.getNumOperands();
+    unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2);
+    MachineOperand JTOP = MI->getOperand(JTOpIdx);
+    unsigned JTI = JTOP.getIndex();
+    assert(JTI < JT.size());
+
+    // We prefer if target blocks for the jump table come after the jump
+    // instruction so we can use TB[BH]. Loop through the target blocks
+    // and try to adjust them such that that's true.
+    unsigned JTOffset = GetOffsetOf(MI) + 4;
+    const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+    for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) {
+      MachineBasicBlock *MBB = JTBBs[j];
+      unsigned DstOffset = BBOffsets[MBB->getNumber()];
+
+      if (DstOffset < JTOffset) {
+        // The destination precedes the switch. Try to move the block forward
+        // so we have a positive offset.
+        MachineBasicBlock *NewBB =
+          AdjustJTTargetBlockForward(MBB, MI->getParent());
+        if (NewBB)
+          MJTI->ReplaceMBBInJumpTables(JTBBs[j], NewBB);
+        MadeChange = true;
+      }
+    }
+  }
+
+  return MadeChange;
+}
+
 MachineBasicBlock *ARMConstantIslands::
 AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB)
 {
   MachineFunction &MF = *BB->getParent();
 
-  // FIXME: For now, instead of moving the block, we'll create a new block
-  // immediate following the jump that's an unconditional branch to the
-  // actual target. This is obviously not what we want for a real solution,
-  // but it's useful for proof of concept, and it may be a useful fallback
-  // later for cases where we otherwise can't move a block.
+  // FIXME: If it's a small block terminated by an unconditional branch,
+  // try to move it; otherwise, create a new block following the jump
+  // table that branches back to the actual target. This is an overly
+  // simplistic heuristic here for proof-of-concept.
+
+  int BBI = BB->getNumber();
+  int Size = BBSizes[BBI];
+  MachineBasicBlock *TBB = 0, *FBB = 0;
+  SmallVector<MachineOperand, 4> Cond;
+  // If the block terminator isn't analyzable, don't try to move the block
+  if (TII->AnalyzeBranch(*BB, TBB, FBB, Cond))
+    return NULL;
+
+  // If the block is small and ends in an unconditional branch, move it.
+  if (Size < 50 && Cond.empty()) {
+    MachineFunction::iterator OldPrior = prior(BB);
+    BB->moveAfter(JTBB);
+    OldPrior->updateTerminator();
+    //BB->updateTerminator();
+    ++NumJTMoved;
+    return NULL;
+  }
 
   // Create a new MBB for the code after the jump BB.
   MachineBasicBlock *NewBB =
@@ -1750,6 +1832,6 @@
   // All BBOffsets following these blocks must be modified.
   AdjustBBOffsetsAfter(NewBB, 4);
 
-  ++NumJTMoved;
+  ++NumJTInserted;
   return NewBB;
 }





More information about the llvm-commits mailing list