re PR target/43920 (Choosing conditional execution over conditional branches for...
authorTom de Vries <tom@codesourcery.com>
Thu, 7 Apr 2011 09:48:39 +0000 (09:48 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Thu, 7 Apr 2011 09:48:39 +0000 (09:48 +0000)
2011-04-07  Tom de Vries  <tom@codesourcery.com>

PR target/43920
* cfgcleanup.c (try_crossjump_to_edge): Add dir parameter.  Pass dir to
flow_find_cross_jump.  Swap variables to implement backward replacement.
(try_crossjump_bb): Add argument to try_crossjump_to_edge.

From-SVN: r172094

gcc/ChangeLog
gcc/cfgcleanup.c

index 8594a76907644bf3a7c8d42914122e12f5429e76..7d80ceaf10e92e4dbab5f1b6f9f0eb4709022359 100644 (file)
@@ -1,3 +1,10 @@
+2011-04-07  Tom de Vries  <tom@codesourcery.com>
+
+       PR target/43920
+       * cfgcleanup.c (try_crossjump_to_edge): Add dir parameter.  Pass dir to
+       flow_find_cross_jump.  Swap variables to implement backward replacement.
+       (try_crossjump_bb): Add argument to try_crossjump_to_edge.
+
 2011-04-07  Tom de Vries  <tom@codesourcery.com>
 
        PR target/43920
index 27af12f6437d8c49b0a1909a14ce3f61356e315c..98c51ad2573fd65e9c6593000b75dc877e828cc2 100644 (file)
@@ -69,7 +69,7 @@ static bool crossjumps_occured;
    information; we should run df_analyze to enable more opportunities.  */
 static bool block_was_dirty;
 
-static bool try_crossjump_to_edge (int, edge, edge);
+static bool try_crossjump_to_edge (int, edge, edge, enum replace_direction);
 static bool try_crossjump_bb (int, basic_block);
 static bool outgoing_edges_match (int, basic_block, basic_block);
 static enum replace_direction old_insns_match_p (int, rtx, rtx);
@@ -1761,16 +1761,18 @@ block_has_preserve_label (basic_block bb)
 
 /* E1 and E2 are edges with the same destination block.  Search their
    predecessors for common code.  If found, redirect control flow from
-   (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC.  */
+   (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC (dir_forward),
+   or the other way around (dir_backward).  DIR specifies the allowed
+   replacement direction.  */
 
 static bool
-try_crossjump_to_edge (int mode, edge e1, edge e2)
+try_crossjump_to_edge (int mode, edge e1, edge e2,
+                       enum replace_direction dir)
 {
   int nmatch;
   basic_block src1 = e1->src, src2 = e2->src;
   basic_block redirect_to, redirect_from, to_remove;
   basic_block osrc1, osrc2, redirect_edges_to, tmp;
-  enum replace_direction dir;
   rtx newpos1, newpos2;
   edge s;
   edge_iterator ei;
@@ -1826,7 +1828,6 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
     return false;
 
   /* ... and part the second.  */
-  dir = dir_forward;
   nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir);
 
   osrc1 = src1;
@@ -1836,6 +1837,16 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
   if (newpos2 != NULL_RTX)
     src2 = BLOCK_FOR_INSN (newpos2);
 
+  if (dir == dir_backward)
+    {
+#define SWAP(T, X, Y) do { T tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
+      SWAP (basic_block, osrc1, osrc2);
+      SWAP (basic_block, src1, src2);
+      SWAP (edge, e1, e2);
+      SWAP (rtx, newpos1, newpos2);
+#undef SWAP
+    }
+
   /* Don't proceed with the crossjump unless we found a sufficient number
      of matching instructions or the 'from' block was totally matched
      (such that its predecessors will hopefully be redirected and the
@@ -2088,7 +2099,7 @@ try_crossjump_bb (int mode, basic_block bb)
                   || (fallthru->src->flags & BB_MODIFIED)))
            continue;
 
-         if (try_crossjump_to_edge (mode, e, fallthru))
+         if (try_crossjump_to_edge (mode, e, fallthru, dir_forward))
            {
              changed = true;
              ix = 0;
@@ -2136,7 +2147,9 @@ try_crossjump_bb (int mode, basic_block bb)
                   || (e2->src->flags & BB_MODIFIED)))
            continue;
 
-         if (try_crossjump_to_edge (mode, e, e2))
+         /* Both e and e2 are not fallthru edges, so we can crossjump in either
+            direction.  */
+         if (try_crossjump_to_edge (mode, e, e2, dir_both))
            {
              changed = true;
              ix = 0;