This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ifcvt conditional traps


Moves conditional trap generation from jump.c to ifcvt.c.

Tested on sparc and powerpc cross-compilers.


r~


        * ifcvt.c (find_cond_trap): New.
        (find_if_header): Call it.
        (merge_if_block): Relax existing jump sanity check.
        * jump.c (jump_optimize_1): Remove conditional trap handling.

Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.53
diff -c -p -d -r1.53 ifcvt.c
*** ifcvt.c	2001/07/11 20:35:52	1.53
--- ifcvt.c	2001/07/14 18:34:43
***************
*** 48,53 ****
--- 48,59 ----
  #ifndef HAVE_decscc
  #define HAVE_decscc 0
  #endif
+ #ifndef HAVE_trap
+ #define HAVE_trap 0
+ #endif
+ #ifndef HAVE_conditional_trap
+ #define HAVE_conditional_trap 0
+ #endif
  
  #ifndef MAX_CONDITIONAL_EXECUTE
  #define MAX_CONDITIONAL_EXECUTE   (BRANCH_COST + 1)
*************** static int find_if_header		PARAMS ((basi
*** 97,102 ****
--- 103,109 ----
  static int find_if_block		PARAMS ((basic_block, edge, edge));
  static int find_if_case_1		PARAMS ((basic_block, edge, edge));
  static int find_if_case_2		PARAMS ((basic_block, edge, edge));
+ static int find_cond_trap		PARAMS ((basic_block, edge, edge));
  static int find_memory			PARAMS ((rtx *, void *));
  static int dead_or_predicable		PARAMS ((basic_block, basic_block,
  						 basic_block, rtx, int));
*************** merge_if_block (test_bb, then_bb, else_b
*** 1757,1766 ****
        if (combo_bb->succ == NULL_EDGE)
  	abort ();
  
!       /* There should sill be a branch at the end of the THEN or ELSE
           blocks taking us to our final destination.  */
!       if (! any_uncondjump_p (combo_bb->end)
!           && ! returnjump_p (combo_bb->end))
  	abort ();
      }
  
--- 1764,1772 ----
        if (combo_bb->succ == NULL_EDGE)
  	abort ();
  
!       /* There should still be a branch at the end of the THEN or ELSE
           blocks taking us to our final destination.  */
!       if (GET_CODE (combo_bb->end) != JUMP_INSN)
  	abort ();
      }
  
*************** find_if_header (test_bb)
*** 1835,1840 ****
--- 1841,1849 ----
  
    if (find_if_block (test_bb, then_edge, else_edge))
      goto success;
+   if (HAVE_trap && HAVE_conditional_trap
+       && find_cond_trap (test_bb, then_edge, else_edge))
+     goto success;
    if (post_dominators
        && (! HAVE_conditional_execution || reload_completed))
      {
*************** find_if_block (test_bb, then_edge, else_
*** 1963,1968 ****
--- 1972,2096 ----
  
    /* Do the real work.  */
    return process_if_block (test_bb, then_bb, else_bb, join_bb);
+ }
+ 
+ /* Convert a branch over a trap, or a branch to a trap,
+    into a conditional trap.  */
+ 
+ static int
+ find_cond_trap (test_bb, then_edge, else_edge)
+      basic_block test_bb;
+      edge then_edge, else_edge;
+ {
+   basic_block then_bb, else_bb, join_bb, trap_bb;
+   rtx trap, jump, cond, cond_earliest, seq;
+   enum rtx_code code;
+ 
+   then_bb = then_edge->dest;
+   else_bb = else_edge->dest;
+   join_bb = NULL;
+ 
+   /* Locate the block with the trap instruction.  */
+   /* ??? While we look for no successors, we really ought to allow
+      EH successors.  Need to fix merge_if_block for that to work.  */
+   /* ??? We can't currently handle merging the blocks if they are not
+      already adjacent.  Prevent losage in merge_if_block by detecting
+      this now.  */
+   if (then_bb->succ == NULL)
+     {
+       trap_bb = then_bb;
+       if (else_bb->index != then_bb->index + 1)
+ 	return FALSE;
+       join_bb = else_bb;
+       else_bb = NULL;
+     }
+   else if (else_bb->succ == NULL)
+     {
+       trap_bb = else_bb;
+       if (else_bb->index != then_bb->index + 1)
+ 	else_bb = NULL;
+       else if (then_bb->succ
+ 	  && ! then_bb->succ->succ_next
+ 	  && ! (then_bb->succ->flags & EDGE_COMPLEX)
+ 	  && then_bb->succ->dest->index == else_bb->index + 1)
+ 	join_bb = then_bb->succ->dest;
+     }
+   else
+     return FALSE;
+ 
+   /* The only instruction in the THEN block must be the trap.  */
+   trap = first_active_insn (trap_bb);
+   if (! (trap == trap_bb->end
+ 	 && GET_CODE (PATTERN (trap)) == TRAP_IF
+          && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
+     return FALSE;
+ 
+   if (rtl_dump_file)
+     {
+       if (trap_bb == then_bb)
+ 	fprintf (rtl_dump_file,
+ 		 "\nTRAP-IF block found, start %d, trap %d",
+ 		 test_bb->index, then_bb->index);
+       else
+ 	fprintf (rtl_dump_file,
+ 		 "\nTRAP-IF block found, start %d, then %d, trap %d",
+ 		 test_bb->index, then_bb->index, trap_bb->index);
+       if (join_bb)
+ 	fprintf (rtl_dump_file, ", join %d\n", join_bb->index);
+       else
+ 	fputc ('\n', rtl_dump_file);
+     }
+ 
+   /* If this is not a standard conditional jump, we can't parse it.  */
+   jump = test_bb->end;
+   cond = noce_get_condition (jump, &cond_earliest);
+   if (! cond)
+     return FALSE;
+ 
+   /* If the conditional jump is more than just a conditional jump,
+      then we can not do if-conversion on this block.  */
+   if (! onlyjump_p (jump))
+     return FALSE;
+ 
+   /* We must be comparing objects whose modes imply the size.  */
+   if (GET_MODE (XEXP (cond, 0)) == BLKmode)
+     return FALSE;
+ 
+   /* Reverse the comparison code, if necessary.  */
+   code = GET_CODE (cond);
+   if (then_bb == trap_bb)
+     {
+       code = reversed_comparison_code (cond, jump);
+       if (code == UNKNOWN)
+ 	return FALSE;
+     }
+ 
+   /* Attempt to generate the conditional trap.  */
+   seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+ 		       TRAP_CODE (PATTERN (trap)));
+   if (seq == NULL)
+     return FALSE;
+ 
+   /* Emit the new insns before cond_earliest; delete the old jump
+      and trap insns.  */
+ 
+   emit_insn_before (seq, cond_earliest);
+ 
+   test_bb->end = PREV_INSN (jump);
+   flow_delete_insn (jump);
+ 
+   trap_bb->end = PREV_INSN (trap);
+   flow_delete_insn (trap);
+ 
+   /* Merge the blocks!  */
+   if (trap_bb != then_bb && ! else_bb)
+     {
+       flow_delete_block (trap_bb);
+       num_removed_blocks++;
+     }
+   merge_if_block (test_bb, then_bb, else_bb, join_bb);
+ 
+   return TRUE;
  }
  
  /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
Index: jump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/jump.c,v
retrieving revision 1.182
diff -c -p -d -r1.182 jump.c
*** jump.c	2001/07/13 18:32:30	1.182
--- jump.c	2001/07/14 18:34:43
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 208,216 ****
    int first = 1;
    int max_uid = 0;
    rtx last_insn;
- #ifdef HAVE_trap
-   enum rtx_code reversed_code;
- #endif
  
    cross_jump_death_matters = (cross_jump == 2);
    max_uid = init_label_info (f) + 1;
--- 208,213 ----
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 498,579 ****
  	      changed = 1;
  	      next = NEXT_INSN (insn);
  	    }
- 
- #ifdef HAVE_trap
- 	  /* Detect a conditional jump jumping over an unconditional trap.  */
- 	  if (HAVE_trap
- 	      && this_is_any_condjump && this_is_onlyjump
- 	      && reallabelprev != 0
- 	      && GET_CODE (reallabelprev) == INSN
- 	      && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF
- 	      && TRAP_CONDITION (PATTERN (reallabelprev)) == const_true_rtx
- 	      && prev_active_insn (reallabelprev) == insn
- 	      && no_labels_between_p (insn, reallabelprev)
- 	      && (temp2 = get_condition (insn, &temp4))
- 	      && ((reversed_code = reversed_comparison_code (temp2, insn))
- 		  != UNKNOWN))
- 	    {
- 	      rtx new = gen_cond_trap (reversed_code,
- 				       XEXP (temp2, 0), XEXP (temp2, 1),
- 				       TRAP_CODE (PATTERN (reallabelprev)));
- 
- 	      if (new)
- 		{
- 		  emit_insn_before (new, temp4);
- 		  delete_insn (reallabelprev);
- 		  delete_jump (insn);
- 		  changed = 1;
- 		  continue;
- 		}
- 	    }
- 	  /* Detect a jump jumping to an unconditional trap.  */
- 	  else if (HAVE_trap && this_is_onlyjump
- 		   && (temp = next_active_insn (JUMP_LABEL (insn)))
- 		   && GET_CODE (temp) == INSN
- 		   && GET_CODE (PATTERN (temp)) == TRAP_IF
- 		   && (this_is_any_uncondjump
- 		       || (this_is_any_condjump
- 			   && (temp2 = get_condition (insn, &temp4)))))
- 	    {
- 	      rtx tc = TRAP_CONDITION (PATTERN (temp));
- 
- 	      if (tc == const_true_rtx
- 		  || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc)))
- 		{
- 		  rtx new;
- 		  /* Replace an unconditional jump to a trap with a trap.  */
- 		  if (this_is_any_uncondjump)
- 		    {
- 		      emit_barrier_after (emit_insn_before (gen_trap (), insn));
- 		      delete_jump (insn);
- 		      changed = 1;
- 		      continue;
- 		    }
- 		  new = gen_cond_trap (GET_CODE (temp2), XEXP (temp2, 0),
- 				       XEXP (temp2, 1),
- 				       TRAP_CODE (PATTERN (temp)));
- 		  if (new)
- 		    {
- 		      emit_insn_before (new, temp4);
- 		      delete_jump (insn);
- 		      changed = 1;
- 		      continue;
- 		    }
- 		}
- 	      /* If the trap condition and jump condition are mutually
- 		 exclusive, redirect the jump to the following insn.  */
- 	      else if (GET_RTX_CLASS (GET_CODE (tc)) == '<'
- 		       && this_is_any_condjump
- 		       && swap_condition (GET_CODE (temp2)) == GET_CODE (tc)
- 		       && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0))
- 		       && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1))
- 		       && redirect_jump (insn, get_label_after (temp), 1))
- 		{
- 		  changed = 1;
- 		  continue;
- 		}
- 	    }
- #endif
  	  else
  	    {
  	      /* Now that the jump has been tensioned,
--- 495,500 ----
Index: testsuite/gcc.dg/iftrap-1.c
===================================================================
RCS file: iftrap-1.c
diff -N iftrap-1.c
*** /dev/null	Tue May  5 13:32:27 1998
--- iftrap-1.c	Sat Jul 14 11:34:43 2001
***************
*** 0 ****
--- 1,38 ----
+ /* Verify that we optimize to conditional traps.  */
+ /* { dg-options "-O" } */
+ /* { dg-do compile { target rs6000-* powerpc-* sparc*-* } } */
+ /* { dg-final { scan-assembler-not iftrap-1.c "^\t(trap|ta)\[ \t\]" } } */
+ 
+ void f1(int p)
+ {
+   if (p)
+     __builtin_trap();
+ }
+ 
+ void f2(int p)
+ {
+   if (p)
+     __builtin_trap();
+   else
+     bar();
+ }
+ 
+ void f3(int p)
+ {
+   if (p)
+     bar();
+   else
+     __builtin_trap();
+ }
+ 
+ void f4(int p, int q)
+ {
+   if (p)
+     {
+       bar();
+       if (q)
+ 	bar();
+     }
+   else
+     __builtin_trap();
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]