[llvm] r182460 - [SystemZ] Fix thinko in long branch pass

Richard Sandiford rsandifo at linux.vnet.ibm.com
Wed May 22 02:57:57 PDT 2013


Author: rsandifo
Date: Wed May 22 04:57:57 2013
New Revision: 182460

URL: http://llvm.org/viewvc/llvm-project?rev=182460&view=rev
Log:
[SystemZ] Fix thinko in long branch pass

The original version of the pass could underestimate the length of a backward
branch in cases like:

    alignment to N bytes or more
    ...
    relaxable branch A
    ...
 foo: (aligned to M<N bytes)
    ...
 bar: (aligned to N bytes)
    ...
    relaxable branch B to foo

We don't add any misalignment gap for "bar" because N bytes of alignment
had already been reached earlier in the function.  In this case, assuming
that A is relaxed can push "foo" closer to "bar", and make B appear to be
in range.  Similar problems can occur for forward branches.

I don't think it's possible to create blocks with mixed alignments as
things stand, not least because we haven't yet defined getPrefLoopAlignment()
for SystemZ (that would need benchmarking).  So I don't think we can test
this yet.

Thanks to Rafael EspĂ­ndola for spotting the bug.

Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZLongBranch.cpp

Modified: llvm/trunk/lib/Target/SystemZ/SystemZLongBranch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZLongBranch.cpp?rev=182460&r1=182459&r2=182460&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZLongBranch.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZLongBranch.cpp Wed May 22 04:57:57 2013
@@ -37,12 +37,19 @@
 // are actually relatively cheap.  It therefore doesn't seem worth spending
 // much compilation time on the problem.  Instead, the approach we take is:
 //
-// (1) Check whether all branches can be short (the usual case).  Exit the
-//     pass if so.
-// (2) If one branch needs to be long, work out the address that each block
-//     would have if all branches need to be long, as for shortening above.
-// (3) Relax any branch that is out of range according to this pessimistic
-//     assumption.
+// (1) Work out the address that each block would have if no branches
+//     need relaxing.  Exit the pass early if all branches are in range
+//     according to this assumption.
+//
+// (2) Work out the address that each block would have if all branches
+//     need relaxing.
+//
+// (3) Walk through the block calculating the final address of each instruction
+//     and relaxing those that need to be relaxed.  For backward branches,
+//     this check uses the final address of the target block, as calculated
+//     earlier in the walk.  For forward branches, this check uses the
+//     address of the target block that was calculated in (2).  Both checks
+//     give a conservatively-correct range.
 //
 //===----------------------------------------------------------------------===//
 
@@ -68,10 +75,7 @@ namespace {
 
   // Represents positional information about a basic block.
   struct MBBInfo {
-    // The address that we currently assume the block has, relative to
-    // the start of the function.  This is designed so that taking the
-    // difference between two addresses gives a conservative upper bound
-    // on the distance between them.
+    // The address that we currently assume the block has.
     uint64_t Address;
 
     // The size of the block in bytes, excluding terminators.
@@ -95,8 +99,7 @@ namespace {
     // instruction, otherwise it is null.
     MachineInstr *Branch;
 
-    // The current address of the terminator, in the same form as
-    // for BlockInfo.
+    // The address that we currently assume the terminator has.
     uint64_t Address;
 
     // The current size of the terminator in bytes.
@@ -115,8 +118,7 @@ namespace {
 
   // Used to keep track of the current position while iterating over the blocks.
   struct BlockPosition {
-    // The offset from the start of the function, in the same form
-    // as BlockInfo.
+    // The address that we assume this position has.
     uint64_t Address;
 
     // The number of low bits in Address that are known to be the same
@@ -146,7 +148,7 @@ namespace {
                         bool AssumeRelaxed);
     TerminatorInfo describeTerminator(MachineInstr *MI);
     uint64_t initMBBInfo();
-    bool mustRelaxBranch(const TerminatorInfo &Terminator);
+    bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
     bool mustRelaxABranch();
     void setWorstCaseAddresses();
     void relaxBranch(TerminatorInfo &Terminator);
@@ -274,17 +276,19 @@ uint64_t SystemZLongBranch::initMBBInfo(
   return Position.Address;
 }
 
-// Return true if, under current assumptions, Terminator needs to be relaxed.
-bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator) {
+// Return true if, under current assumptions, Terminator would need to be
+// relaxed if it were placed at address Address.
+bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator,
+                                        uint64_t Address) {
   if (!Terminator.Branch)
     return false;
 
   const MBBInfo &Target = MBBs[Terminator.TargetBlock];
-  if (Target.Address < Terminator.Address) {
-    if (Terminator.Address - Target.Address <= MaxBackwardRange)
+  if (Address >= Target.Address) {
+    if (Address - Target.Address <= MaxBackwardRange)
       return false;
   } else {
-    if (Target.Address - Terminator.Address <= MaxForwardRange)
+    if (Target.Address - Address <= MaxForwardRange)
       return false;
   }
 
@@ -296,7 +300,7 @@ bool SystemZLongBranch::mustRelaxBranch(
 bool SystemZLongBranch::mustRelaxABranch() {
   for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
          TE = Terminators.end(); TI != TE; ++TI)
-    if (mustRelaxBranch(*TI))
+    if (mustRelaxBranch(*TI, TI->Address))
       return true;
   return false;
 }
@@ -337,12 +341,22 @@ void SystemZLongBranch::relaxBranch(Term
   ++LongBranches;
 }
 
-// Relax any branches that need to be relaxed, under current assumptions.
+// Run a shortening pass and relax any branches that need to be relaxed.
 void SystemZLongBranch::relaxBranches() {
-  for (SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(),
-         TE = Terminators.end(); TI != TE; ++TI)
-    if (mustRelaxBranch(*TI))
-      relaxBranch(*TI);
+  SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin();
+  BlockPosition Position(MF->getAlignment());
+  for (SmallVector<MBBInfo, 16>::iterator BI = MBBs.begin(), BE = MBBs.end();
+       BI != BE; ++BI) {
+    skipNonTerminators(Position, *BI);
+    for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) {
+      assert(Position.Address <= TI->Address &&
+             "Addresses shouldn't go forwards");
+      if (mustRelaxBranch(*TI, Position.Address))
+        relaxBranch(*TI);
+      skipTerminator(Position, *TI, false);
+      ++TI;
+    }
+  }
 }
 
 bool SystemZLongBranch::runOnMachineFunction(MachineFunction &F) {





More information about the llvm-commits mailing list