On 3/15/07, Steven Bosscher <[EMAIL PROTECTED]> wrote:
On 3/15/07, Uros Bizjak <[EMAIL PROTECTED]> wrote:
> The testcase is:
>
> double x;
> q()
> {
>   x=x<5?5:x;
> }
>
> compile this with -O2 -msse2 -mfpmath=sse, and this testcase should
> compile to maxsd.

This happens because a "fallthrough edge" is meaningless in cfglayout
mode, but ifcvt.c still gives special meaning to the fallthrough edge.
 This should not matter, but it does for some reason, and I'm
investigating this right now. I'll try to come up with a fix asap.

This is what my fix will probably look like.  I've bootstrapped C only
on x86_64 and I have verified that it restores the CE1 transformation
for your test case.  I'll do a full bootstrap with testing over the
weekend. Early comments welcome ;-)

Gr.
Steven
	* ifcvt.c (noce_try_store_flag_constants): Don't check
	no_new_pseudos here.
	(noce_try_store_flag_constants): Don't check no_new_pseudos.
	(noce_try_addcc, noce_try_store_flag_mask, noce_try_cmove_arith,
	noce_try_cmove_arith, noce_try_minmax, noce_try_abs,
	noce_try_sign_mask): Likewise.
	(if_convert): Check no_new_pseudos here.

	(cond_exec_process_if_block, noce_process_if_block, find_if_block):
	Remove prototypes.
	(struct noce_if_info): Add then_bb, else_bb, join_bb members.
	(noce_get_condition): Handle new then_else_reversed argument.
	(noce_init_if_info): Remove, fold into noce_find_if_block.
	(noce_process_if_block): Take a struct noce_if_info as the
	argument.  Don't set up one based on ce_if_info.  Update pointer
	references accordingly.
	(cond_move_process_if_block): Likewise.
	(process_if_block): Removed.
	(find_if_block): Removed.  Move functionality two new functions,
	noce_find_if_block and cond_exec_find_if_block.
	(noce_find_if_block): New function.  Be aware of IF-THEN-JOIN
	blocks and the symmetric IF-ELSE-JOIN case.
	(cond_exec_find_if_block): Also new function mostly based on old
	find_if_block and process_if_block.
	(find_if_header): Replace find_if_block call with separately
	guarded calls to noce_find_if_block and cond_exec_find_if_block.
	(find_cond_trap): Update noce_get_condition call.
	(dead_or_predicable): Likewise.

Index: ifcvt.c
===================================================================
--- ifcvt.c	(revision 123180)
+++ ifcvt.c	(working copy)
@@ -96,16 +96,14 @@ static rtx last_active_insn (basic_block
 static basic_block block_fallthru (basic_block);
 static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
 static rtx cond_exec_get_condition (rtx);
-static int cond_exec_process_if_block (ce_if_block_t *, int);
-static rtx noce_get_condition (rtx, rtx *);
+static rtx noce_get_condition (rtx, rtx *, bool);
 static int noce_operand_ok (rtx);
-static int noce_process_if_block (ce_if_block_t *);
-static int process_if_block (ce_if_block_t *);
 static void merge_if_block (ce_if_block_t *);
 static int find_cond_trap (basic_block, edge, edge);
 static basic_block find_if_header (basic_block, int);
 static int block_jumps_and_fallthru_p (basic_block, basic_block);
-static int find_if_block (ce_if_block_t *);
+static int noce_find_if_block (basic_block, edge, edge, int);
+static int cond_exec_find_if_block (ce_if_block_t *);
 static int find_if_case_1 (basic_block, edge, edge);
 static int find_if_case_2 (basic_block, edge, edge);
 static int find_memory (rtx *, void *);
@@ -598,8 +596,8 @@ cond_exec_process_if_block (ce_if_block_
 
 struct noce_if_info
 {
-  /* A basic block that ends in a simple conditional jump.  */
-  basic_block test_bb;
+  /* The basic blocks that make up the IF-THEN-{ELSE-,}JOIN block.  */
+  basic_block test_bb, then_bb, else_bb, join_bb;
 
   /* The jump that ends TEST_BB.  */
   rtx jump;
@@ -938,8 +936,7 @@ noce_try_store_flag_constants (struct no
   int normalize, can_reverse;
   enum machine_mode mode;
 
-  if (! no_new_pseudos
-      && GET_CODE (if_info->a) == CONST_INT
+  if (GET_CODE (if_info->a) == CONST_INT
       && GET_CODE (if_info->b) == CONST_INT)
     {
       mode = GET_MODE (if_info->x);
@@ -1065,8 +1062,7 @@ noce_try_addcc (struct noce_if_info *if_
   rtx target, seq;
   int subtract, normalize;
 
-  if (! no_new_pseudos
-      && GET_CODE (if_info->a) == PLUS
+  if (GET_CODE (if_info->a) == PLUS
       && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
       && (reversed_comparison_code (if_info->cond, if_info->jump)
 	  != UNKNOWN))
@@ -1157,9 +1153,8 @@ noce_try_store_flag_mask (struct noce_if
   int reversep;
 
   reversep = 0;
-  if (! no_new_pseudos
-      && (BRANCH_COST >= 2
-	  || STORE_FLAG_VALUE == -1)
+  if ((BRANCH_COST >= 2
+       || STORE_FLAG_VALUE == -1)
       && ((if_info->a == const0_rtx
 	   && rtx_equal_p (if_info->b, if_info->x))
 	  || ((reversep = (reversed_comparison_code (if_info->cond,
@@ -1314,7 +1309,8 @@ noce_try_cmove_arith (struct noce_if_inf
      conditional on their addresses followed by a load.  Don't do this
      early because it'll screw alias analysis.  Note that we've
      already checked for no side effects.  */
-  if (! no_new_pseudos && cse_not_expected
+  /* ??? FIXME: Magic number 5.  */
+  if (cse_not_expected
       && MEM_P (a) && MEM_P (b)
       && BRANCH_COST >= 5)
     {
@@ -1389,9 +1385,6 @@ noce_try_cmove_arith (struct noce_if_inf
     {
       rtx set;
 
-      if (no_new_pseudos)
-	goto end_seq_and_fail;
-
       if (is_mem)
 	{
 	  tmp = gen_reg_rtx (GET_MODE (a));
@@ -1414,9 +1407,6 @@ noce_try_cmove_arith (struct noce_if_inf
     {
       rtx set, last;
 
-      if (no_new_pseudos)
-	goto end_seq_and_fail;
-
       if (is_mem)
 	{
           tmp = gen_reg_rtx (GET_MODE (b));
@@ -1648,10 +1638,6 @@ noce_try_minmax (struct noce_if_info *if
   enum rtx_code code, op;
   int unsignedp;
 
-  /* ??? Can't guarantee that expand_binop won't create pseudos.  */
-  if (no_new_pseudos)
-    return FALSE;
-
   /* ??? Reject modes with NaNs or signed zeros since we don't know how
      they will be resolved with an SMIN/SMAX.  It wouldn't be too hard
      to get the target to tell us...  */
@@ -1744,10 +1730,6 @@ noce_try_abs (struct noce_if_info *if_in
   rtx cond, earliest, target, seq, a, b, c;
   int negate;
 
-  /* ??? Can't guarantee that expand_binop won't create pseudos.  */
-  if (no_new_pseudos)
-    return FALSE;
-
   /* Recognize A and B as constituting an ABS or NABS.  The canonical
      form is a branch around the negation, taken when the object is the
      first operand of a comparison against 0 that evaluates to true.  */
@@ -1868,9 +1850,6 @@ noce_try_sign_mask (struct noce_if_info 
   enum rtx_code code;
   bool b_unconditional;
 
-  if (no_new_pseudos)
-    return FALSE;
-
   cond = if_info->cond;
   code = GET_CODE (cond);
   m = XEXP (cond, 0);
@@ -2036,10 +2015,13 @@ noce_try_bitop (struct noce_if_info *if_
 
 
 /* Similar to get_condition, only the resulting condition must be
-   valid at JUMP, instead of at EARLIEST.  */
+   valid at JUMP, instead of at EARLIEST.
+
+   If THEN_ELSE_REVERSED is true, the fallthrough goes to the THEN
+   block of the caller, and we have to reverse the condition.  */
 
 static rtx
-noce_get_condition (rtx jump, rtx *earliest)
+noce_get_condition (rtx jump, rtx *earliest, bool then_else_reversed)
 {
   rtx cond, set, tmp;
   bool reverse;
@@ -2054,6 +2036,11 @@ noce_get_condition (rtx jump, rtx *earli
   reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
 	     && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump));
 
+  /* We may have to reverse because the caller's if block is not canonical
+     (i.e. the ELSE block isn't the fallthrough block for the TEST block).  */
+  if (then_else_reversed)
+    reverse = !reverse;
+
   /* If the condition variable is a register and is MODE_INT, accept it.  */
 
   cond = XEXP (SET_SRC (set), 0);
@@ -2074,52 +2061,6 @@ noce_get_condition (rtx jump, rtx *earli
 				 NULL_RTX, false, true);
 }
 
-/* Initialize for a simple IF-THEN or IF-THEN-ELSE block.  We will not
-   be using conditional execution.  Set some fields of IF_INFO based
-   on CE_INFO: test_bb, cond, jump, cond_earliest.  Return TRUE if
-   things look OK.  */
-
-static int
-noce_init_if_info (struct ce_if_block *ce_info, struct noce_if_info *if_info)
-{
-  basic_block test_bb = ce_info->test_bb;
-  rtx cond, jump;
-
-  /* If test is comprised of && or || elements, don't handle it unless
-     it is the special case of && elements without an ELSE block.  */
-  if (ce_info->num_multiple_test_blocks)
-    {
-      if (ce_info->else_bb || !ce_info->and_and_p)
-	return FALSE;
-
-      ce_info->test_bb = test_bb = ce_info->last_test_bb;
-      ce_info->num_multiple_test_blocks = 0;
-      ce_info->num_and_and_blocks = 0;
-      ce_info->num_or_or_blocks = 0;
-    }
-
-  /* If this is not a standard conditional jump, we can't parse it.  */
-  jump = BB_END (test_bb);
-  cond = noce_get_condition (jump, &if_info->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;
-
-  if_info->test_bb = test_bb;
-  if_info->cond = cond;
-  if_info->jump = jump;
-
-  return TRUE;
-}
-
 /* Return true if OP is ok for if-then-else processing.  */
 
 static int
@@ -2189,22 +2130,22 @@ noce_mem_write_may_trap_or_fault_p (rtx 
   return false;
 }
 
-/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
-   without using conditional execution.  Return TRUE if we were
-   successful at converting the block.  */
+/* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
+   it without using conditional execution.  Return TRUE if we were successful
+   at converting the block.  */
 
 static int
-noce_process_if_block (struct ce_if_block * ce_info)
-{
-  basic_block test_bb = ce_info->test_bb;	/* test block */
-  basic_block then_bb = ce_info->then_bb;	/* THEN */
-  basic_block else_bb = ce_info->else_bb;	/* ELSE or NULL */
-  basic_block join_bb;
-  struct noce_if_info if_info;
+noce_process_if_block (struct noce_if_info *if_info)
+{
+  basic_block test_bb = if_info->test_bb;	/* test block */
+  basic_block then_bb = if_info->then_bb;	/* THEN */
+  basic_block else_bb = if_info->else_bb;	/* ELSE or NULL */
+  basic_block join_bb = if_info->join_bb;	/* JOIN */
+  rtx jump = if_info->jump;
+  rtx cond = if_info->cond;
   rtx insn_a, insn_b;
   rtx set_a, set_b;
   rtx orig_x, x, a, b;
-  rtx jump, cond;
 
   /* We're looking for patterns of the form
 
@@ -2216,12 +2157,6 @@ noce_process_if_block (struct ce_if_bloc
 
      ??? For future expansion, look for multiple X in such patterns.  */
 
-  if (!noce_init_if_info (ce_info, &if_info))
-    return FALSE;
-
-  cond = if_info.cond;
-  jump = if_info.jump;
-
   /* Look for one of the potential sets.  */
   insn_a = first_active_insn (then_bb);
   if (! insn_a
@@ -2251,7 +2186,7 @@ noce_process_if_block (struct ce_if_bloc
     }
   else
     {
-      insn_b = prev_nonnote_insn (if_info.cond_earliest);
+      insn_b = prev_nonnote_insn (if_info->cond_earliest);
       /* We're going to be moving the evaluation of B down from above
 	 COND_EARLIEST to JUMP.  Make sure the relevant data is still
 	 intact.  */
@@ -2261,13 +2196,13 @@ noce_process_if_block (struct ce_if_bloc
 	  || ! rtx_equal_p (x, SET_DEST (set_b))
 	  || reg_overlap_mentioned_p (x, SET_SRC (set_b))
 	  || modified_between_p (SET_SRC (set_b),
-				 PREV_INSN (if_info.cond_earliest), jump)
+				 PREV_INSN (if_info->cond_earliest), jump)
 	  /* Likewise with X.  In particular this can happen when
 	     noce_get_condition looks farther back in the instruction
 	     stream than one might expect.  */
 	  || reg_overlap_mentioned_p (x, cond)
 	  || reg_overlap_mentioned_p (x, a)
-	  || modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump))
+	  || modified_between_p (x, PREV_INSN (if_info->cond_earliest), jump))
 	insn_b = set_b = NULL_RTX;
     }
 
@@ -2288,7 +2223,7 @@ noce_process_if_block (struct ce_if_bloc
       || (SMALL_REGISTER_CLASSES
 	  && REGNO (x) < FIRST_PSEUDO_REGISTER))
     {
-      if (no_new_pseudos || GET_MODE (x) == BLKmode)
+      if (GET_MODE (x) == BLKmode)
 	return FALSE;
 
       if (GET_MODE (x) == ZERO_EXTRACT
@@ -2305,11 +2240,11 @@ noce_process_if_block (struct ce_if_bloc
     return FALSE;
 
   /* Set up the info block for our subroutines.  */
-  if_info.insn_a = insn_a;
-  if_info.insn_b = insn_b;
-  if_info.x = x;
-  if_info.a = a;
-  if_info.b = b;
+  if_info->insn_a = insn_a;
+  if_info->insn_b = insn_b;
+  if_info->x = x;
+  if_info->a = a;
+  if_info->b = b;
 
   /* Try optimizations in some approximation of a useful order.  */
   /* ??? Should first look to see if X is live incoming at all.  If it
@@ -2359,31 +2294,31 @@ noce_process_if_block (struct ce_if_bloc
   if (!set_b && MEM_P (orig_x) && noce_mem_write_may_trap_or_fault_p (orig_x))
     return FALSE;
 
-  if (noce_try_move (&if_info))
+  if (noce_try_move (if_info))
     goto success;
-  if (noce_try_store_flag (&if_info))
+  if (noce_try_store_flag (if_info))
     goto success;
-  if (noce_try_bitop (&if_info))
+  if (noce_try_bitop (if_info))
     goto success;
-  if (noce_try_minmax (&if_info))
+  if (noce_try_minmax (if_info))
     goto success;
-  if (noce_try_abs (&if_info))
+  if (noce_try_abs (if_info))
     goto success;
   if (HAVE_conditional_move
-      && noce_try_cmove (&if_info))
+      && noce_try_cmove (if_info))
     goto success;
   if (! HAVE_conditional_execution)
     {
-      if (noce_try_store_flag_constants (&if_info))
+      if (noce_try_store_flag_constants (if_info))
 	goto success;
-      if (noce_try_addcc (&if_info))
+      if (noce_try_addcc (if_info))
 	goto success;
-      if (noce_try_store_flag_mask (&if_info))
+      if (noce_try_store_flag_mask (if_info))
 	goto success;
       if (HAVE_conditional_move
-	  && noce_try_cmove_arith (&if_info))
+	  && noce_try_cmove_arith (if_info))
 	goto success;
-      if (noce_try_sign_mask (&if_info))
+      if (noce_try_sign_mask (if_info))
 	goto success;
     }
 
@@ -2409,8 +2344,6 @@ noce_process_if_block (struct ce_if_bloc
   /* The original THEN and ELSE blocks may now be removed.  The test block
      must now jump to the join block.  If the test block and the join block
      can be merged, do so.  */
-
-  join_bb = single_succ (then_bb);
   if (else_bb)
     {
       delete_basic_block (else_bb);
@@ -2572,19 +2505,20 @@ cond_move_convert_if_block (struct noce_
   return true;
 }
 
-/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
-   using only conditional moves.  Return TRUE if we were successful at
+/* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
+   it using only conditional moves.  Return TRUE if we were successful at
    converting the block.  */
 
 static int
-cond_move_process_if_block (struct ce_if_block *ce_info)
+cond_move_process_if_block (struct noce_if_info *if_info)
 {
-  basic_block test_bb = ce_info->test_bb;
-  basic_block then_bb = ce_info->then_bb;
-  basic_block else_bb = ce_info->else_bb;
-  basic_block join_bb;
-  struct noce_if_info if_info;
-  rtx jump, cond, seq, loc_insn;
+  basic_block test_bb = if_info->test_bb;
+  basic_block then_bb = if_info->then_bb;
+  basic_block else_bb = if_info->else_bb;
+  basic_block join_bb = if_info->join_bb;
+  rtx jump = if_info->jump;
+  rtx cond = if_info->cond;
+  rtx seq, loc_insn;
   int max_reg, size, c, reg;
   rtx *then_vals;
   rtx *else_vals;
@@ -2592,17 +2526,6 @@ cond_move_process_if_block (struct ce_if
   VEC (int, heap) *else_regs = NULL;
   unsigned int i;
 
-  if (!HAVE_conditional_move || no_new_pseudos)
-    return FALSE;
-
-  memset (&if_info, 0, sizeof if_info);
-
-  if (!noce_init_if_info (ce_info, &if_info))
-    return FALSE;
-
-  cond = if_info.cond;
-  jump = if_info.jump;
-
   /* Build a mapping for each block to the value used for each
      register.  */
   max_reg = max_reg_num ();
@@ -2655,16 +2578,16 @@ cond_move_process_if_block (struct ce_if
   /* Try to emit the conditional moves.  First do the then block,
      then do anything left in the else blocks.  */
   start_sequence ();
-  if (!cond_move_convert_if_block (&if_info, then_bb, cond,
+  if (!cond_move_convert_if_block (if_info, then_bb, cond,
 				   then_vals, else_vals, false)
       || (else_bb
-	  && !cond_move_convert_if_block (&if_info, else_bb, cond,
+	  && !cond_move_convert_if_block (if_info, else_bb, cond,
 					  then_vals, else_vals, true)))
     {
       end_sequence ();
       return FALSE;
     }
-  seq = end_ifcvt_sequence (&if_info);
+  seq = end_ifcvt_sequence (if_info);
   if (!seq)
     return FALSE;
 
@@ -2676,7 +2599,6 @@ cond_move_process_if_block (struct ce_if
     }
   emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
 
-  join_bb = single_succ (then_bb);
   if (else_bb)
     {
       delete_basic_block (else_bb);
@@ -2705,40 +2627,128 @@ cond_move_process_if_block (struct ce_if
 }
 
 
-/* Attempt to convert an IF-THEN or IF-THEN-ELSE block into
-   straight line code.  Return true if successful.  */
+/* Determine if a given basic block heads a simple IF-THEN-JOIN or an
+   IF-THEN-ELSE-JOIN block.
+
+   If so, we'll try to convert the insns to not require the branch,
+   using only transformations that do not require conditional execution.
+
+   Return TRUE if we were successful at converting the block.  */
 
 static int
-process_if_block (struct ce_if_block * ce_info)
+noce_find_if_block (basic_block test_bb,
+		    edge then_edge, edge else_edge,
+		    int pass)
 {
-  if (! reload_completed
-      && noce_process_if_block (ce_info))
-    return TRUE;
+  basic_block then_bb, else_bb, join_bb;
+  bool then_else_reversed = false;
+  rtx jump, cond;
+  struct noce_if_info if_info;
 
-  if (HAVE_conditional_move
-      && cond_move_process_if_block (ce_info))
-    return TRUE;
+  /* We only ever should get here before reload.  */
+  gcc_assert (!reload_completed);
 
-  if (HAVE_conditional_execution && reload_completed)
+  /* Recognize an IF-THEN-ELSE-JOIN block.  */
+  if (single_pred_p (then_edge->dest)
+      && single_succ_p (then_edge->dest)
+      && single_pred_p (else_edge->dest)
+      && single_succ_p (else_edge->dest)
+      && single_succ (then_edge->dest) == single_succ (else_edge->dest))
+    {
+      then_bb = then_edge->dest;
+      else_bb = else_edge->dest;
+      join_bb = single_succ (then_bb);
+    }
+  /* Recognize an IF-THEN-JOIN block.  */
+  else if (single_pred_p (then_edge->dest)
+	   && single_succ_p (then_edge->dest)
+	   && single_succ (then_edge->dest) == else_edge->dest)
     {
-      /* If we have && and || tests, try to first handle combining the && and
-         || tests into the conditional code, and if that fails, go back and
-         handle it without the && and ||, which at present handles the && case
-         if there was no ELSE block.  */
-      if (cond_exec_process_if_block (ce_info, TRUE))
-	return TRUE;
+      then_bb = then_edge->dest;
+      else_bb = NULL_BLOCK;
+      join_bb = else_edge->dest;
+    }
+  /* Recognize an IF-ELSE-JOIN block.  We can have those because the order
+     of basic blocks in cfglayout mode does not matter, so the fallthrough
+     edge can go to any basic block (and not just to bb->next_bb, like in
+     cfgrtl mode).  */ 
+  else if (single_pred_p (else_edge->dest)
+	   && single_succ_p (else_edge->dest)
+	   && single_succ (else_edge->dest) == then_edge->dest)
+    {
+      /* The noce transformations do not apply to IF-ELSE-JOIN blocks.
+	 To make this work, we have to invert the THEN and ELSE blocks
+	 and reverse the jump condition.  */
+      then_bb = else_edge->dest;
+      else_bb = NULL_BLOCK;
+      join_bb = single_succ (then_bb);
+      then_else_reversed = true;
+    }
+  else
+    /* Not a form we can handle.  */
+    return FALSE;
+     
+  /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
+  if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
+    return FALSE;
+  if (else_bb
+      && single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
+    return FALSE;
 
-      if (ce_info->num_multiple_test_blocks)
-	{
-	  cancel_changes (0);
+  num_possible_if_blocks++;
 
-	  if (cond_exec_process_if_block (ce_info, FALSE))
-	    return TRUE;
-	}
+  if (dump_file)
+    {
+      fprintf (dump_file,
+	       "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
+	       (else_bb) ? "-ELSE" : "",
+	       pass, test_bb->index, then_bb->index);
+
+      if (else_bb)
+	fprintf (dump_file, ", else %d", else_bb->index);
+
+      fprintf (dump_file, ", join %d\n", join_bb->index);
     }
 
+  /* If the conditional jump is more than just a conditional
+     jump, then we can not do if-conversion on this block.  */
+  jump = BB_END (test_bb);
+  if (! onlyjump_p (jump))
+    return FALSE;
+
+  /* If this is not a standard conditional jump, we can't parse it.  */
+  /* FIXME STEVEN must revert jump condition here.  */
+  cond = noce_get_condition (jump,
+			     &if_info.cond_earliest,
+			     then_else_reversed);
+  if (!cond)
+    return FALSE;
+
+  /* We must be comparing objects whose modes imply the size.  */
+  if (GET_MODE (XEXP (cond, 0)) == BLKmode)
+    return FALSE;
+
+  /* Initialize an IF_INFO struct to pass around.  */
+  memset (&if_info, 0, sizeof if_info);
+  if_info.test_bb = test_bb;
+  if_info.then_bb = then_bb;
+  if_info.else_bb = else_bb;
+  if_info.join_bb = join_bb;
+  if_info.cond = cond;
+  if_info.jump = jump;
+
+  /* Do the real work.  */
+
+  if (noce_process_if_block (&if_info))
+    return TRUE;
+
+  if (HAVE_conditional_move
+      && cond_move_process_if_block (&if_info))
+    return TRUE;
+
   return FALSE;
 }
+
 
 /* Merge the blocks and mark for local life update.  */
 
@@ -2901,7 +2911,12 @@ find_if_header (basic_block test_bb, int
   IFCVT_INIT_EXTRA_FIELDS (&ce_info);
 #endif
 
-  if (find_if_block (&ce_info))
+  if (! reload_completed
+      && noce_find_if_block (test_bb, then_edge, else_edge, pass))
+    goto success;
+
+  if (HAVE_conditional_execution && reload_completed
+      && cond_exec_find_if_block (&ce_info))
     goto success;
 
   if (HAVE_trap && HAVE_conditional_trap
@@ -2999,7 +3014,7 @@ block_jumps_and_fallthru_p (basic_block 
    Return TRUE if we were successful at converting the block.  */
 
 static int
-find_if_block (struct ce_if_block * ce_info)
+cond_exec_find_if_block (struct ce_if_block * ce_info)
 {
   basic_block test_bb = ce_info->test_bb;
   basic_block then_bb = ce_info->then_bb;
@@ -3011,11 +3026,14 @@ find_if_block (struct ce_if_block * ce_i
 
   ce_info->last_test_bb = test_bb;
 
+  /* We only ever should get here after reload,
+     and only if we have conditional execution.  */
+  gcc_assert (HAVE_conditional_execution && reload_completed);
+
   /* Discover if any fall through predecessors of the current test basic block
      were && tests (which jump to the else block) or || tests (which jump to
      the then block).  */
-  if (HAVE_conditional_execution && reload_completed
-      && single_pred_p (test_bb)
+  if (single_pred_p (test_bb)
       && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
     {
       basic_block bb = single_pred (test_bb);
@@ -3201,10 +3219,24 @@ find_if_block (struct ce_if_block * ce_i
     }
 
   /* Do the real work.  */
+
   ce_info->else_bb = else_bb;
   ce_info->join_bb = join_bb;
 
-  return process_if_block (ce_info);
+  /* If we have && and || tests, try to first handle combining the && and ||
+     tests into the conditional code, and if that fails, go back and handle
+     it without the && and ||, which at present handles the && case if there
+     was no ELSE block.  */
+  if (cond_exec_process_if_block (ce_info, TRUE))
+    return TRUE;
+
+  if (ce_info->num_multiple_test_blocks)
+    {
+      cancel_changes (0);
+
+      if (cond_exec_process_if_block (ce_info, FALSE))
+	return TRUE;
+    }
 }
 
 /* Convert a branch over a trap, or a branch
@@ -3237,7 +3269,7 @@ find_cond_trap (basic_block test_bb, edg
 
   /* If this is not a standard conditional jump, we can't parse it.  */
   jump = BB_END (test_bb);
-  cond = noce_get_condition (jump, &cond_earliest);
+  cond = noce_get_condition (jump, &cond_earliest, false);
   if (! cond)
     return FALSE;
 
@@ -3733,7 +3765,7 @@ dead_or_predicable (basic_block test_bb,
 	return FALSE;
 
       /* Find the extent of the conditional.  */
-      cond = noce_get_condition (jump, &earliest);
+      cond = noce_get_condition (jump, &earliest, false);
       if (! cond)
 	return FALSE;
 
@@ -3908,6 +3940,10 @@ if_convert (int x_life_data_ok)
   num_true_changes = 0;
   life_data_ok = (x_life_data_ok != 0);
 
+  /* Some transformations in this pass can create new pseudos,
+     if the pass runs before reload.  Make sure we can do so.  */
+  gcc_assert (! no_new_pseudos || reload_completed);
+
   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
   if (current_loops)
     {

Reply via email to