diff mbox

[PR43920,9/9] Cross-jumping - Allow both directions.

Message ID 4D94CBDD.9060304@codesourcery.com
State New
Headers show

Commit Message

Tom de Vries March 31, 2011, 6:45 p.m. UTC
Allow crossjumping in both directions. Crossjump was assumed to be
symmetric, and therefore only applied on edges e1,e2 and not on e2,e1.
Now given both the fallthru fix and the regnotes fix, crossjumping is
not symmetrical anymore, and we allow both directions (but not by
testing twice).

Thanks,
- Tom

Comments

Jeff Law March 31, 2011, 6:57 p.m. UTC | #1
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/31/11 12:45, Tom de Vries wrote:
> Allow crossjumping in both directions. Crossjump was assumed to be
> symmetric, and therefore only applied on edges e1,e2 and not on e2,e1.
> Now given both the fallthru fix and the regnotes fix, crossjumping is
> not symmetrical anymore, and we allow both directions (but not by
> testing twice).
OK.
jeff
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNlM6qAAoJEBRtltQi2kC7GaEIAJDs2K21ezAc1ubdSXEbbr8Z
Zryi/r6Euzns9e3+heNYYugn33XyVLc5kGiEgM8Ul2QEfg2cY//PAW6nAaFUnqQn
EMlKIUMdGM3ijAXC2AdLQ+4fim1n3y6kxlFyZQOvlyGtm+bp+V+EgGtBt9yA9s5x
y0TopSk2OITup0Vo7KQikt5wvCtspoMRd7qYry9TNMFEZokaAgdaI2B00jK9+UCn
aO9unwBaYoZEiUGNQBW/xYazdOG68IV+Q4Dh+7UAKVQ5aBqoQcZ+olRuy6Dtcrr+
mys+bEMx7T3qT/fTzIAmsH40ZuRTUIat9zAa+5wNWxzr9c6zS7C+UR0pJxiYKmc=
=/cNV
-----END PGP SIGNATURE-----
diff mbox

Patch

diff -u gcc/cfgcleanup.c gcc/cfgcleanup.c
--- gcc/cfgcleanup.c	(working copy)
+++ gcc/cfgcleanup.c	(working copy)
@@ -69,7 +69,7 @@ 
    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);
@@ -1695,15 +1695,17 @@ 
 /* 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;
@@ -1757,8 +1759,7 @@ 
     return false;
 
   /* ... and part the second.  */
-  dir = dir_forward;
   nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir);
 
   osrc1 = src1;
   osrc2 = src2;
@@ -1767,5 +1768,15 @@ 
   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
@@ -2020,7 +2031,7 @@ 
 		   || (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;
@@ -2068,7 +2079,9 @@ 
 		   || (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;