OSDN Git Service

update the sample output
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index 3297107..d23fd3a 100644 (file)
@@ -32,6 +32,7 @@
 #include "expr.h"
 #include "real.h"
 #include "output.h"
+#include "toplev.h"
 #include "tm_p.h"
 
 
 #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)
@@ -65,6 +72,9 @@ static int num_updated_if_blocks;
 /* # of basic blocks that were removed.  */
 static int num_removed_blocks;
 
+/* True if life data ok at present.  */
+static bool life_data_ok;
+
 /* The post-dominator relation on the original block numbers.  */
 static sbitmap *post_dominators;
 
@@ -93,9 +103,11 @@ static int find_if_header           PARAMS ((basic_block));
 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));
+static void noce_emit_move_insn                PARAMS ((rtx, rtx));
 \f
 /* Abuse the basic_block AUX field to store the original block index,
    as well as a flag indicating that the block should be rescaned for
@@ -286,9 +298,14 @@ cond_exec_get_condition (jump)
      reverse the condition.  */
   if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
       && XEXP (XEXP (test_if, 2), 0) == JUMP_LABEL (jump))
-    cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
-                          GET_MODE (cond), XEXP (cond, 0),
-                          XEXP (cond, 1));
+    {
+      enum rtx_code rev = reversed_comparison_code (cond, jump);
+      if (rev == UNKNOWN)
+       return NULL_RTX;
+
+      cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
+                            XEXP (cond, 1));
+    }
 
   return cond;
 }
@@ -316,6 +333,7 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
   rtx true_prob_val;           /* probability of else block */
   rtx false_prob_val;          /* probability of then block */
   int n_insns;
+  enum rtx_code false_code;
 
   /* Find the conditional jump to the ELSE or JOIN part, and isolate
      the test.  */
@@ -377,9 +395,13 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
      the conditionally executed code.  */
   
   true_expr = test_expr;
-  false_expr = gen_rtx_fmt_ee (reverse_condition (GET_CODE (true_expr)),
-                              GET_MODE (true_expr), XEXP (true_expr, 0),
-                              XEXP (true_expr, 1));
+
+  false_code = reversed_comparison_code (true_expr, test_bb->end);
+  if (false_code != UNKNOWN)
+    false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
+                                XEXP (true_expr, 0), XEXP (true_expr, 1));
+  else
+    false_expr = NULL_RTX;
 
 #ifdef IFCVT_MODIFY_TESTS
   /* If the machine description needs to modify the tests, such as setting a
@@ -409,8 +431,9 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
      to conditional execution.  */
 
   if (then_end
-      && ! cond_exec_process_insns (then_start, then_end,
-                                   false_expr, false_prob_val, then_mod_ok))
+      && (! false_expr
+         || ! cond_exec_process_insns (then_start, then_end, false_expr,
+                                       false_prob_val, then_mod_ok)))
     goto fail;
 
   if (else_bb
@@ -537,6 +560,31 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
                           || code == GEU || code == GTU), normalize);
 }
 
+/* Emit instruction to move a rtx into STRICT_LOW_PART.  */
+static void
+noce_emit_move_insn (x, y)
+     rtx x, y;
+{
+  enum machine_mode outmode, inmode;
+  rtx outer, inner;
+  int bitpos;
+
+  if (GET_CODE (x) != STRICT_LOW_PART)
+    {
+      emit_move_insn (x, y);
+      return;
+    }
+
+  outer = XEXP (x, 0);
+  inner = XEXP (outer, 0);
+  outmode = GET_MODE (outer);
+  inmode = GET_MODE (inner);
+  bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
+  store_bit_field (inner, GET_MODE_BITSIZE (outmode),
+                  bitpos, outmode, y, GET_MODE_BITSIZE (inmode),
+                  GET_MODE_BITSIZE (inmode));
+}
+
 /* Convert "if (test) x = 1; else x = 0".
 
    Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
@@ -569,7 +617,7 @@ noce_try_store_flag (if_info)
   if (target)
     {
       if (target != if_info->x)
-       emit_move_insn (if_info->x, target);
+       noce_emit_move_insn (if_info->x, target);
 
       seq = get_insns ();
       end_sequence ();
@@ -692,7 +740,7 @@ noce_try_store_flag_constants (if_info)
        }
 
       if (target != if_info->x)
-       emit_move_insn (if_info->x, target);
+       noce_emit_move_insn (if_info->x, target);
 
       seq = get_insns ();
       end_sequence ();
@@ -751,7 +799,7 @@ noce_try_store_flag_inc (if_info)
       if (target)
        {
          if (target != if_info->x)
-           emit_move_insn (if_info->x, target);
+           noce_emit_move_insn (if_info->x, target);
 
          seq = get_insns ();
          end_sequence ();
@@ -803,7 +851,7 @@ noce_try_store_flag_mask (if_info)
       if (target)
        {
          if (target != if_info->x)
-           emit_move_insn (if_info->x, target);
+           noce_emit_move_insn (if_info->x, target);
 
          seq = get_insns ();
          end_sequence ();
@@ -902,7 +950,7 @@ noce_try_cmove (if_info)
       if (target)
        {
          if (target != if_info->x)
-           emit_move_insn (if_info->x, target);
+           noce_emit_move_insn (if_info->x, target);
 
          seq = get_insns ();
          end_sequence ();
@@ -1057,12 +1105,12 @@ noce_try_cmove_arith (if_info)
       if (MEM_SCALAR_P (if_info->a) && MEM_SCALAR_P (if_info->b))
        MEM_SCALAR_P (tmp) = 1;
       if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
-       MEM_ALIAS_SET (tmp) = MEM_ALIAS_SET (if_info->a);
+       set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a));
 
-      emit_move_insn (if_info->x, tmp);
+      noce_emit_move_insn (if_info->x, tmp);
     }
   else if (target != x)
-    emit_move_insn (x, target);
+    noce_emit_move_insn (x, target);
 
   tmp = get_insns ();
   end_sequence ();
@@ -1209,7 +1257,7 @@ noce_try_minmax (if_info)
       return FALSE;
     }
   if (target != if_info->x)
-    emit_move_insn (if_info->x, target);
+    noce_emit_move_insn (if_info->x, target);
 
   seq = get_insns ();
   end_sequence ();  
@@ -1327,7 +1375,7 @@ noce_try_abs (if_info)
     }
 
   if (target != if_info->x)
-    emit_move_insn (if_info->x, target);
+    noce_emit_move_insn (if_info->x, target);
 
   seq = get_insns ();
   end_sequence ();  
@@ -1532,7 +1580,8 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
     {
       if (no_new_pseudos)
        return FALSE;
-      x = gen_reg_rtx (GET_MODE (x));
+      x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
+                                ? XEXP (x, 0) : x));
     }
 
   /* Don't operate on sources that may trap or are volatile.  */
@@ -1638,7 +1687,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
   if (orig_x != x)
     {
       start_sequence ();
-      emit_move_insn (orig_x, x);
+      noce_emit_move_insn (orig_x, x);
       insn_b = gen_sequence ();
       end_sequence ();
 
@@ -1691,7 +1740,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
   /* First merge TEST block into THEN block.  This is a no-brainer since
      the THEN block did not have a code label to begin with.  */
 
-  if (combo_bb->global_live_at_end)
+  if (life_data_ok)
     COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end);
   merge_blocks_nomove (combo_bb, then_bb);
   num_removed_blocks++;
@@ -1715,10 +1764,9 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
       if (combo_bb->succ == NULL_EDGE)
        abort ();
 
-      /* There should sill be a branch at the end of the THEN or ELSE
+      /* There should still be a branch at the end of the THEN or ELSE
          blocks taking us to our final destination.  */
-      if (! simplejump_p (combo_bb->end)
-          && ! returnjump_p (combo_bb->end))
+      if (GET_CODE (combo_bb->end) != JUMP_INSN)
        abort ();
     }
 
@@ -1731,7 +1779,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
   else if (join_bb->pred == NULL || join_bb->pred->pred_next == NULL)
     {
       /* We can merge the JOIN.  */
-      if (combo_bb->global_live_at_end)
+      if (life_data_ok)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      join_bb->global_live_at_end);
       merge_blocks_nomove (combo_bb, join_bb);
@@ -1793,6 +1841,9 @@ find_if_header (test_bb)
 
   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))
     {
@@ -1923,6 +1974,130 @@ find_if_block (test_bb, then_edge, else_edge)
   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;
+
+  /* Don't confuse a conditional return with something we want to
+     optimize here.  */
+  if (trap_bb == EXIT_BLOCK_PTR)
+    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
    transformable, but not necessarily the other.  There need be no
    JOIN block.
@@ -2230,6 +2405,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       rtx cond, prob_val;
 
       cond = cond_exec_get_condition (jump);
+      if (! cond)
+       return FALSE;
 
       prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
       if (prob_val)
@@ -2237,8 +2414,10 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
 
       if (reversep)
        {
-         cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
-                                GET_MODE (cond), XEXP (cond, 0),
+         enum rtx_code rev = reversed_comparison_code (cond, jump);
+         if (rev == UNKNOWN)
+           return FALSE;
+         cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
                                 XEXP (cond, 1));
          if (prob_val)
            prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
@@ -2382,11 +2561,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
   JUMP_LABEL (jump) = new_dest;
 
   if (reversep)
-    {
-      rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
-      if (note)
-       XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
-    }
+    invert_br_probabilities (jump);
 
   /* Move the insns out of MERGE_BB to before the branch.  */
   if (head != NULL)
@@ -2420,14 +2595,15 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
 /* Main entry point for all if-conversion.  */
 
 void
-if_convert (life_data_ok)
-     int life_data_ok;
+if_convert (x_life_data_ok)
+     int x_life_data_ok;
 {
   int block_num;
 
   num_possible_if_blocks = 0;
   num_updated_if_blocks = 0;
   num_removed_blocks = 0;
+  life_data_ok = (x_life_data_ok != 0);
 
   /* Free up basic_block_for_insn so that we don't have to keep it 
      up to date, either here or in merge_blocks_nomove.  */