[patch] PR40525: Try noce path in dead_or_predicable if the ce path fails

Steven Bosscher stevenb.gcc@gmail.com
Thu Jun 25 21:06:00 GMT 2009


Hi,

The attached patch tries the non-cond_exec transformations of
dead_or_predicable if predicating MERGE_BB fails.

Consider the test case of the PR:

int foo(int x, int flag)
{
  int result = flag == 1 ? 2 : 0;
  return result + x;
}

Without this patch, targets like thumb never have any benefit from the
find_if_case_1 and find_if_case_2 transformations, simply because they
are never attempted -- the cond_exec path is always tries and always
fails.  The resulting code for thumb is:

        push    {lr}
        cmp     r1, #1
        bne     .L3
        mov     r3, #2
        b       .L2
.L3:
        mov     r3, #0
.L2:
        add     r0, r3, r0
        pop     {pc}


Note the jump over L3 to L2.  On targets with conditional moves (i.e.
most) that jump is optimized away.  On targets without conditional
move and no conditional execution support, the ce3 pass notices that
r3 is dead before the jump "bne .L3" and hoists one of the sets of r3
from the branch target, see find_if_case_1.  On targets without
conditional move but with (at least some subtarget with) conditional
execution support, this noce transformation in find_if_case_1 is never
even tried because the CE transformation fails and find_if_case_1
cancels all changes and bails out.

With the patch, this is fixed and we get this code for thumb:

foo:
        push    {lr}
        mov     r3, #2
        cmp     r1, #1
        beq     .L2
        mov     r3, #0
.L2:
        add     r0, r3, r0
        pop     {pc}

which saves one branch, good for speed and usually good for code size.

The patch was bootstrapped&tested on ia64-unknown-linux-gnu, and built
for arm and tested on CSiBE for "-Os -march=armv7-r" and "-Os
-march=armv7 -mthumb" (-0.0004% code size change for thumb, +0.00004%
code size for arm, i.e. no change).

OK for trunk?

Ciao!
Steven
-------------- next part --------------
	PR middle-end/40525
	* ifcvt.c (dead_or_predicable): If predicating MERGE_BB fails,
	try the non-cond_exec path also.

Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 148927)
+++ ifcvt.c	(working copy)
@@ -3780,6 +3780,8 @@ dead_or_predicable (basic_block test_bb,
 		    basic_block other_bb, basic_block new_dest, int reversep)
 {
   rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
+  /* Number of pending changes.  */
+  int n_validated_changes = 0;
 
   jump = BB_END (test_bb);
 
@@ -3849,13 +3851,15 @@ dead_or_predicable (basic_block test_bb,
 	}
 
       if (! cond_exec_process_insns ((ce_if_block_t *)0, head, end, cond,
-				     prob_val, 0))
-	goto cancel;
-
+				     prob_val, 0)
+	  || ! verify_changes (0))
+	cancel_changes (0);
+      n_validated_changes = num_validated_changes ();
       earliest = jump;
     }
-  else
 #endif
+  /* Try the NCE path if the CE path did not result in any changes.  */
+  if (n_validated_changes == 0)
     {
       /* In the non-conditional execution case, we have to verify that there
 	 are no trapping operations, no calls, no references to memory, and
@@ -3995,8 +3999,10 @@ dead_or_predicable (basic_block test_bb,
 	goto cancel;
     }
 
-  if (! apply_change_group ())
-    return FALSE;
+  if (verify_changes (n_validated_changes))
+    confirm_change_group ();
+  else
+    goto cancel;
 
   if (other_bb != new_dest)
     {


More information about the Gcc-patches mailing list