[llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp

Chris Lattner sabre at nondot.org
Sun Oct 29 13:05:55 PST 2006



Changes in directory llvm/lib/CodeGen:

BranchFolding.cpp updated: 1.26 -> 1.27
---
Log message:

Make CanFallThrough more intelligent (so it can handle blocks with (e.g.) no
successors), and make island block movement more general.

This compiles CodeGen/X86/2006-04-27-ISelFoldingBug.ll to:

_loadAndRLEsource_no_exit_2E_1_label_2E_0:
        subl $8, %esp
        movl %esi, 4(%esp)
        movl %ebx, (%esp)
        movl 16(%esp), %eax
        movl 12(%esp), %ecx
LBB1_3: #label.0
        movl _last, %edx
        movl %edx, %esi
        incl %esi
        movl %esi, _last
        movl %ecx, %ebx
        # TRUNCATE movb %bl, %bl
        movl _block, %esi
        movb %bl, 1(%esi,%edx)
        cmpl %eax, _last
        jge LBB1_2      #codeRepl5.exitStub
LBB1_4: #label.0
        cmpl $257, %ecx
        je LBB1_2       #codeRepl5.exitStub
LBB1_1: #label.0.no_exit.1_crit_edge.exitStub
        movl $1, %eax
        movl (%esp), %ebx
        movl 4(%esp), %esi
        addl $8, %esp
        ret
LBB1_2: #codeRepl5.exitStub
        xorl %eax, %eax
        movl (%esp), %ebx
        movl 4(%esp), %esi
        addl $8, %esp
        ret

instead of:

_loadAndRLEsource_no_exit_2E_1_label_2E_0:
        subl $8, %esp
        movl %esi, 4(%esp)
        movl %ebx, (%esp)
        movl 16(%esp), %eax
        movl 12(%esp), %ecx
        jmp LBB1_3      #label.0
LBB1_1: #label.0.no_exit.1_crit_edge.exitStub
        movl $1, %eax
        movl (%esp), %ebx
        movl 4(%esp), %esi
        addl $8, %esp
        ret
LBB1_2: #codeRepl5.exitStub
        xorl %eax, %eax
        movl (%esp), %ebx
        movl 4(%esp), %esi
        addl $8, %esp
        ret
LBB1_3: #label.0
        movl _last, %edx
        movl %edx, %esi
        incl %esi
        movl %esi, _last
        movl %ecx, %ebx
        # TRUNCATE movb %bl, %bl
        movl _block, %esi
        movb %bl, 1(%esi,%edx)
        cmpl %eax, _last
        jge LBB1_2      #codeRepl5.exitStub
LBB1_4: #label.0
        cmpl $257, %ecx
        jne LBB1_1      #label.0.no_exit.1_crit_edge.exitStub
        jmp LBB1_2      #codeRepl5.exitStub

... which is much better layout :)



---
Diffs of the changes:  (+94 -62)

 BranchFolding.cpp |  156 ++++++++++++++++++++++++++++++++----------------------
 1 files changed, 94 insertions(+), 62 deletions(-)


Index: llvm/lib/CodeGen/BranchFolding.cpp
diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.26 llvm/lib/CodeGen/BranchFolding.cpp:1.27
--- llvm/lib/CodeGen/BranchFolding.cpp:1.26	Sat Oct 28 13:34:47 2006
+++ llvm/lib/CodeGen/BranchFolding.cpp	Sun Oct 29 15:05:41 2006
@@ -48,6 +48,11 @@
     bool OptimizeBranches(MachineFunction &MF);
     void OptimizeBlock(MachineBasicBlock *MBB);
     void RemoveDeadBlock(MachineBasicBlock *MBB);
+    
+    bool CanFallThrough(MachineBasicBlock *CurBB);
+    bool CanFallThrough(MachineBasicBlock *CurBB, bool BranchUnAnalyzable,
+                        MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+                        const std::vector<MachineOperand> &Cond);
   };
 }
 
@@ -443,19 +448,37 @@
     }
 }
 
-/// CanFallThrough - Return true of the specified branch condition can transfer
-/// control to FallthroughBlock, the block immediately after the branch.
-static bool CanFallThrough(MachineBasicBlock *TBB,
-                           MachineBasicBlock *FBB,
-                           const std::vector<MachineOperand> &Cond,
-                           MachineFunction::iterator FallthroughBlock) {
+/// CanFallThrough - Return true if the specified block (with the specified
+/// branch condition) can implicitly transfer control to the block after it by
+/// falling off the end of it.  This should return false if it can reach the
+/// block after it, but it uses an explicit branch to do so (e.g. a table jump).
+///
+/// True is a conservative answer.
+///
+bool BranchFolder::CanFallThrough(MachineBasicBlock *CurBB,
+                                  bool BranchUnAnalyzable,
+                                  MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+                                  const std::vector<MachineOperand> &Cond) {
+  MachineFunction::iterator Fallthrough = CurBB;
+  ++Fallthrough;
+  // If FallthroughBlock is off the end of the function, it can't fall through.
+  if (Fallthrough == CurBB->getParent()->end())
+    return false;
+  
+  // If FallthroughBlock isn't a successor of CurBB, no fallthrough is possible.
+  if (!CurBB->isSuccessor(Fallthrough))
+    return false;
+  
+  // If we couldn't analyze the branch, assume it could fall through.
+  if (BranchUnAnalyzable) return true;
+  
   // If there is no branch, control always falls through.
   if (TBB == 0) return true;
 
   // If there is some explicit branch to the fallthrough block, it can obviously
   // reach, even though the branch should get folded to fall through implicitly.
-  if (MachineFunction::iterator(TBB) == FallthroughBlock ||
-      MachineFunction::iterator(FBB) == FallthroughBlock)
+  if (MachineFunction::iterator(TBB) == Fallthrough ||
+      MachineFunction::iterator(FBB) == Fallthrough)
     return true;
   
   // If it's an unconditional branch to some block not the fall through, it 
@@ -467,6 +490,20 @@
   return FBB == 0;
 }
 
+/// CanFallThrough - Return true if the specified can implicitly transfer
+/// control to the block after it by falling off the end of it.  This should
+/// return false if it can reach the block after it, but it uses an explicit
+/// branch to do so (e.g. a table jump).
+///
+/// True is a conservative answer.
+///
+bool BranchFolder::CanFallThrough(MachineBasicBlock *CurBB) {
+  MachineBasicBlock *TBB = 0, *FBB = 0;
+  std::vector<MachineOperand> Cond;
+  bool CurUnAnalyzable = TII->AnalyzeBranch(*CurBB, TBB, FBB, Cond);
+  return CanFallThrough(CurBB, CurUnAnalyzable, TBB, FBB, Cond);
+}
+
 /// OptimizeBlock - Analyze and optimize control flow related to the specified
 /// block.  This is never called on the entry block.
 void BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
@@ -504,8 +541,8 @@
 
   MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0;
   std::vector<MachineOperand> PriorCond;
-  bool PriorUnAnalyzable = false;
-  PriorUnAnalyzable = TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond);
+  bool PriorUnAnalyzable =
+    TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond);
   if (!PriorUnAnalyzable) {
     // If the CFG for the prior block has extra edges, remove them.
     MadeChange |= CorrectExtraCFGEdges(PrevBB, PriorTBB, PriorFBB,
@@ -561,7 +598,8 @@
   // Analyze the branch in the current block.
   MachineBasicBlock *CurTBB = 0, *CurFBB = 0;
   std::vector<MachineOperand> CurCond;
-  if (!TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond)) {
+  bool CurUnAnalyzable = TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond);
+  if (!CurUnAnalyzable) {
     // If the CFG for the prior block has extra edges, remove them.
     MadeChange |= CorrectExtraCFGEdges(*MBB, CurTBB, CurFBB,
                                        !CurCond.empty(),
@@ -630,62 +668,56 @@
       // Add the branch back if the block is more than just an uncond branch.
       TII->InsertBranch(*MBB, CurTBB, 0, CurCond);
     }
-    
-    // If the prior block doesn't fall through into this block, and if this
-    // block doesn't fall through into some other block, see if we can find a
-    // place to move this block where a fall-through will happen.
-    if (!PriorUnAnalyzable && !CanFallThrough(PriorTBB, PriorFBB,
-                                              PriorCond, MBB)) {
-      // Now we know that there was no fall-through into this block, check to
-      // see if it has fall-throughs.
-      if (!CanFallThrough(CurTBB, CurFBB, CurCond, FallThrough)) {
-        
-        // Check all the predecessors of this block.  If one of them has no fall
-        // throughs, move this block right after it.
-        for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
-             E = MBB->pred_end(); PI != E; ++PI) {
-          // Analyze the branch at the end of the pred.
-          MachineBasicBlock *PredBB = *PI;
-          MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough;
-          MachineBasicBlock *PredTBB = 0, *PredFBB = 0;
-          std::vector<MachineOperand> PredCond;
-          if (PredBB != MBB &&
-              !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond) &&
-              !CanFallThrough(PredTBB, PredFBB, PredCond, PredFallthrough)) {
-            MBB->moveAfter(PredBB);
-            MadeChange = true;
-            return OptimizeBlock(MBB);
-          }
-        }
-        
-        // Check all successors to see if we can move this block before it.
-        for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
-             E = MBB->succ_end(); SI != E; ++SI) {
-          // Analyze the branch at the end of the block before the succ.
-          MachineBasicBlock *SuccBB = *SI;
-          MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev;
-          MachineBasicBlock *SuccPrevTBB = 0, *SuccPrevFBB = 0;
-          std::vector<MachineOperand> SuccPrevCond;
-          if (SuccBB != MBB &&
-              !TII->AnalyzeBranch(*SuccPrev, SuccPrevTBB, SuccPrevFBB,
-                                  SuccPrevCond) &&
-              !CanFallThrough(SuccPrevTBB, SuccPrevFBB, SuccPrevCond, SuccBB)) {
-            MBB->moveBefore(SuccBB);
-            MadeChange = true;
-            return OptimizeBlock(MBB);
-          }
+  }
+
+  // If the prior block doesn't fall through into this block, and if this
+  // block doesn't fall through into some other block, see if we can find a
+  // place to move this block where a fall-through will happen.
+  if (!CanFallThrough(&PrevBB, PriorUnAnalyzable,
+                      PriorTBB, PriorFBB, PriorCond)) {
+    // Now we know that there was no fall-through into this block, check to
+    // see if it has a fall-through into its successor.
+    if (!CanFallThrough(MBB, CurUnAnalyzable, CurTBB, CurFBB, CurCond)) {
+      // Check all the predecessors of this block.  If one of them has no fall
+      // throughs, move this block right after it.
+      for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
+           E = MBB->pred_end(); PI != E; ++PI) {
+        // Analyze the branch at the end of the pred.
+        MachineBasicBlock *PredBB = *PI;
+        MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough;
+        MachineBasicBlock *PredTBB = 0, *PredFBB = 0;
+        std::vector<MachineOperand> PredCond;
+        if (PredBB != MBB && !CanFallThrough(PredBB)) {
+          MBB->moveAfter(PredBB);
+          MadeChange = true;
+          return OptimizeBlock(MBB);
         }
+      }
         
-        // Okay, there is no really great place to put this block.  If, however,
-        // the block before this one would be a fall-through if this block were
-        // removed, move this block to the end of the function.
-        if (FallThrough != MBB->getParent()->end() &&
-            CanFallThrough(PriorTBB, PriorFBB, PriorCond, FallThrough)) {
-          MBB->moveAfter(--MBB->getParent()->end());
+      // Check all successors to see if we can move this block before it.
+      for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+           E = MBB->succ_end(); SI != E; ++SI) {
+        // Analyze the branch at the end of the block before the succ.
+        MachineBasicBlock *SuccBB = *SI;
+        MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev;
+        MachineBasicBlock *SuccPrevTBB = 0, *SuccPrevFBB = 0;
+        std::vector<MachineOperand> SuccPrevCond;
+        if (SuccBB != MBB && !CanFallThrough(SuccPrev)) {
+          MBB->moveBefore(SuccBB);
           MadeChange = true;
-          return;
+          return OptimizeBlock(MBB);
         }
       }
+      
+      // Okay, there is no really great place to put this block.  If, however,
+      // the block before this one would be a fall-through if this block were
+      // removed, move this block to the end of the function.
+      if (FallThrough != MBB->getParent()->end() &&
+          PrevBB.isSuccessor(FallThrough)) {
+        MBB->moveAfter(--MBB->getParent()->end());
+        MadeChange = true;
+        return;
+      }
     }
   }
 }






More information about the llvm-commits mailing list