OSDN Git Service

* config/m68k/m68k.h: Remove comments copied over from tm.texi.
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index 24c8fd8..a6066da 100644 (file)
@@ -1,5 +1,5 @@
 /* If-conversion support.
-   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -84,9 +84,6 @@ static int cond_exec_changed_p;
 /* True if life data ok at present.  */
 static bool life_data_ok;
 
-/* The post-dominator relation on the original block numbers.  */
-static dominance_info post_dominators;
-
 /* Forward references.  */
 static int count_bb_insns (basic_block);
 static rtx first_active_insn (basic_block);
@@ -123,6 +120,7 @@ mark_loop_exit_edges (void)
   edge e;
   
   flow_loops_find (&loops, LOOP_TREE);
+  free_dominance_info (CDI_DOMINATORS);
   
   if (loops.num > 1)
     {
@@ -568,8 +566,8 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
 #endif
 
   /* Conversion succeeded.  */
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "%d insn%s converted to conditional execution.\n",
+  if (dump_file)
+    fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
             n_insns, (n_insns == 1) ? " was" : "s were");
 
   /* Merge the blocks!  */
@@ -614,6 +612,7 @@ static int noce_try_cmove_arith (struct noce_if_info *);
 static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *);
 static int noce_try_minmax (struct noce_if_info *);
 static int noce_try_abs (struct noce_if_info *);
+static int noce_try_sign_mask (struct noce_if_info *);
 
 /* Helper function for noce_try_store_flag*.  */
 
@@ -1704,6 +1703,71 @@ noce_try_abs (struct noce_if_info *if_info)
   return TRUE;
 }
 
+/* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;".  */
+
+static int
+noce_try_sign_mask (struct noce_if_info *if_info)
+{
+  rtx cond, t, m, c, seq;
+  enum machine_mode mode;
+  enum rtx_code code;
+
+  if (no_new_pseudos)
+    return FALSE;
+
+  cond = if_info->cond;
+  code = GET_CODE (cond);
+  m = XEXP (cond, 0);
+  c = XEXP (cond, 1);
+
+  t = NULL_RTX;
+  if (if_info->a == const0_rtx)
+    {
+      if ((code == LT && c == const0_rtx)
+         || (code == LE && c == constm1_rtx))
+       t = if_info->b;
+    }
+  else if (if_info->b == const0_rtx)
+    {
+      if ((code == GE && c == const0_rtx)
+         || (code == GT && c == constm1_rtx))
+       t = if_info->a;
+    }
+
+  if (! t || side_effects_p (t))
+    return FALSE;
+
+  /* We currently don't handle different modes.  */
+  mode = GET_MODE (t);
+  if (GET_MODE (m) != mode)
+    return FALSE;
+
+  /* This is only profitable if T is cheap.  */
+  if (rtx_cost (t, SET) >= COSTS_N_INSNS (2))
+    return FALSE;
+
+  start_sequence ();
+  c = gen_int_mode (GET_MODE_BITSIZE (mode) - 1, mode);
+  m = expand_binop (mode, ashr_optab, m, c, NULL_RTX, 0, OPTAB_DIRECT);
+  t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
+       : NULL_RTX;
+
+  if (!t)
+    {
+      end_sequence ();
+      return FALSE;
+    }
+
+  noce_emit_move_insn (if_info->x, t);
+  seq = get_insns ();
+  unshare_ifcvt_sequence (if_info, seq);
+  end_sequence ();
+  emit_insn_before_setloc (seq, if_info->jump,
+                          INSN_LOCATOR (if_info->insn_a));
+  return TRUE;
+}
+
+
 /* Similar to get_condition, only the resulting condition must be
    valid at JUMP, instead of at EARLIEST.  */
 
@@ -1966,7 +2030,7 @@ noce_process_if_block (struct ce_if_block * ce_info)
     }
 
   /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
-     for most optimizations if writing to x may trap, i.e. its a memory
+     for most optimizations if writing to x may trap, i.e. it's a memory
      other than a static var or a stack slot.  */
   if (! set_b
       && GET_CODE (orig_x) == MEM
@@ -2006,6 +2070,8 @@ noce_process_if_block (struct ce_if_block * ce_info)
       if (HAVE_conditional_move
          && noce_try_cmove_arith (&if_info))
        goto success;
+      if (noce_try_sign_mask (&if_info))
+       goto success;
     }
 
   return FALSE;
@@ -2105,8 +2171,6 @@ merge_if_block (struct ce_if_block * ce_info)
        {
          bb = fallthru;
          fallthru = block_fallthru (bb);
-         if (post_dominators)
-           delete_from_dominance_info (post_dominators, bb);
          merge_blocks (combo_bb, bb);
          num_true_changes++;
        }
@@ -2122,8 +2186,6 @@ merge_if_block (struct ce_if_block * ce_info)
       if (combo_bb->global_live_at_end)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      then_bb->global_live_at_end);
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, then_bb);
       merge_blocks (combo_bb, then_bb);
       num_true_changes++;
     }
@@ -2133,8 +2195,6 @@ merge_if_block (struct ce_if_block * ce_info)
      get their addresses taken.  */
   if (else_bb)
     {
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, else_bb);
       merge_blocks (combo_bb, else_bb);
       num_true_changes++;
     }
@@ -2190,8 +2250,6 @@ merge_if_block (struct ce_if_block * ce_info)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      join_bb->global_live_at_end);
 
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, join_bb);
       merge_blocks (combo_bb, join_bb);
       num_true_changes++;
     }
@@ -2207,7 +2265,7 @@ merge_if_block (struct ce_if_block * ce_info)
 
       /* Remove the jump and cruft from the end of the COMBO block.  */
       if (join_bb != EXIT_BLOCK_PTR)
-       tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
+       tidy_fallthru_edge (combo_bb->succ);
     }
 
   num_updated_if_blocks++;
@@ -2271,7 +2329,7 @@ find_if_header (basic_block test_bb, int pass)
       && find_cond_trap (test_bb, then_edge, else_edge))
     goto success;
 
-  if (post_dominators
+  if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY
       && (! HAVE_conditional_execution || reload_completed))
     {
       if (find_if_case_1 (test_bb, then_edge, else_edge))
@@ -2283,8 +2341,8 @@ find_if_header (basic_block test_bb, int pass)
   return NULL;
 
  success:
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "Conversion succeeded on pass %d.\n", pass);
+  if (dump_file)
+    fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
   return ce_info.test_bb;
 }
 
@@ -2524,23 +2582,29 @@ find_if_block (struct ce_if_block * ce_info)
 
   num_possible_if_blocks++;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]",
+      fprintf (dump_file,
+              "\nIF-THEN%s block found, pass %d, start block %d "
+              "[insn %d], then %d [%d]",
               (else_bb) ? "-ELSE" : "",
               ce_info->pass,
-              test_bb->index, (BB_HEAD (test_bb)) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
-              then_bb->index, (BB_HEAD (then_bb)) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
+              test_bb->index,
+              BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
+              then_bb->index,
+              BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
 
       if (else_bb)
-       fprintf (rtl_dump_file, ", else %d [%d]",
-                else_bb->index, (BB_HEAD (else_bb)) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
+       fprintf (dump_file, ", else %d [%d]",
+                else_bb->index,
+                BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
 
-      fprintf (rtl_dump_file, ", join %d [%d]",
-              join_bb->index, (BB_HEAD (join_bb)) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
+      fprintf (dump_file, ", join %d [%d]",
+              join_bb->index,
+              BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
 
       if (ce_info->num_multiple_test_blocks > 0)
-       fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]",
+       fprintf (dump_file, ", %d %s block%s last test %d [%d]",
                 ce_info->num_multiple_test_blocks,
                 (ce_info->and_and_p) ? "&&" : "||",
                 (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
@@ -2549,7 +2613,7 @@ find_if_block (struct ce_if_block * ce_info)
                  ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
                  : -1));
 
-      fputc ('\n', rtl_dump_file);
+      fputc ('\n', dump_file);
     }
 
   /* Make sure IF, THEN, and ELSE, blocks are adjacent.  Actually, we get the
@@ -2600,9 +2664,9 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
   else
     return FALSE;
 
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
+      fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
               test_bb->index, trap_bb->index);
     }
 
@@ -2645,11 +2709,7 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
   /* Delete the trap block if possible.  */
   remove_edge (trap_bb == then_bb ? then_edge : else_edge);
   if (trap_bb->pred == NULL)
-    {
-      if (post_dominators)
-       delete_from_dominance_info (post_dominators, trap_bb);
-      delete_block (trap_bb);
-    }
+    delete_basic_block (trap_bb);
 
   /* If the non-trap block and the test are now adjacent, merge them.
      Otherwise we must insert a direct branch.  */
@@ -2791,6 +2851,18 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
   edge then_succ = then_bb->succ;
   int then_bb_index;
 
+  /* If we are partitioning hot/cold basic blocks, we don't want to
+     mess up unconditional or indirect jumps that cross between hot
+     and cold sections.  */
+  
+  if (flag_reorder_blocks_and_partition
+      && ((BB_END (then_bb) 
+          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+         || (BB_END (else_bb)
+             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                               NULL_RTX))))
+    return FALSE;
+
   /* THEN has one successor.  */
   if (!then_succ || then_succ->succ_next != NULL)
     return FALSE;
@@ -2808,8 +2880,8 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
     return FALSE;
 
   num_possible_if_blocks++;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "\nIF-CASE-1 found, start %d, then %d\n",
             test_bb->index, then_bb->index);
 
@@ -2831,9 +2903,7 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
 
   new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
   then_bb_index = then_bb->index;
-  if (post_dominators)
-    delete_from_dominance_info (post_dominators, then_bb);
-  delete_block (then_bb);
+  delete_basic_block (then_bb);
 
   /* Make rest of code believe that the newly created block is the THEN_BB
      block we removed.  */
@@ -2841,8 +2911,6 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
     {
       new_bb->index = then_bb_index;
       BASIC_BLOCK (then_bb_index) = new_bb;
-      if (post_dominators)
-       add_to_dominance_info (post_dominators, new_bb);
     }
   /* We've possibly created jump to next insn, cleanup_cfg will solve that
      later.  */
@@ -2863,6 +2931,18 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
   edge else_succ = else_bb->succ;
   rtx note;
 
+  /* If we are partitioning hot/cold basic blocks, we don't want to
+     mess up unconditional or indirect jumps that cross between hot
+     and cold sections.  */
+  
+  if (flag_reorder_blocks_and_partition
+      && ((BB_END (then_bb)
+          && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX))
+         || (BB_END (else_bb) 
+             && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, 
+                               NULL_RTX))))
+    return FALSE;
+
   /* ELSE has one successor.  */
   if (!else_succ || else_succ->succ_next != NULL)
     return FALSE;
@@ -2884,15 +2964,15 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
   if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
     ;
   else if (else_succ->dest->index < 0
-          || dominated_by_p (post_dominators, then_bb,
+          || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
                              else_succ->dest))
     ;
   else
     return FALSE;
 
   num_possible_if_blocks++;
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file,
+  if (dump_file)
+    fprintf (dump_file,
             "\nIF-CASE-2 found, start %d, else %d\n",
             test_bb->index, else_bb->index);
 
@@ -2911,9 +2991,7 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
                    then_bb->global_live_at_start,
                    else_bb->global_live_at_end, BITMAP_IOR);
 
-  if (post_dominators)
-    delete_from_dominance_info (post_dominators, else_bb);
-  delete_block (else_bb);
+  delete_basic_block (else_bb);
 
   num_true_changes++;
   num_updated_if_blocks++;
@@ -2945,7 +3023,7 @@ static int
 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
                    basic_block other_bb, basic_block new_dest, int reversep)
 {
-  rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX;
+  rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
 
   jump = BB_END (test_bb);
 
@@ -3209,19 +3287,14 @@ if_convert (int x_life_data_ok)
   num_true_changes = 0;
   life_data_ok = (x_life_data_ok != 0);
 
-  if (! (* targetm.cannot_modify_jumps_p) ())
+  if ((! targetm.cannot_modify_jumps_p ())
+      && (!flag_reorder_blocks_and_partition || !no_new_pseudos))
     mark_loop_exit_edges ();
 
-  /* Free up basic_block_for_insn so that we don't have to keep it
-     up to date, either here or in merge_blocks.  */
-  free_basic_block_vars (1);
-
   /* Compute postdominators if we think we'll use them.  */
-  post_dominators = NULL;
   if (HAVE_conditional_execution || life_data_ok)
-    {
-      post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
-    }
+    calculate_dominance_info (CDI_POST_DOMINATORS);
+
   if (life_data_ok)
     clear_bb_flags ();
 
@@ -3235,8 +3308,8 @@ if_convert (int x_life_data_ok)
       pass++;
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-      if (rtl_dump_file && pass > 1)
-       fprintf (rtl_dump_file, "\n\n========== Pass %d ==========\n", pass);
+      if (dump_file && pass > 1)
+       fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
 #endif
 
       FOR_EACH_BB (bb)
@@ -3247,22 +3320,21 @@ if_convert (int x_life_data_ok)
        }
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-      if (rtl_dump_file && cond_exec_changed_p)
-       print_rtl_with_bb (rtl_dump_file, get_insns ());
+      if (dump_file && cond_exec_changed_p)
+       print_rtl_with_bb (dump_file, get_insns ());
 #endif
     }
   while (cond_exec_changed_p);
 
 #ifdef IFCVT_MULTIPLE_DUMPS
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "\n\n========== no more changes\n");
+  if (dump_file)
+    fprintf (dump_file, "\n\n========== no more changes\n");
 #endif
 
-  if (post_dominators)
-    free_dominance_info (post_dominators);
+  free_dominance_info (CDI_POST_DOMINATORS);
 
-  if (rtl_dump_file)
-    fflush (rtl_dump_file);
+  if (dump_file)
+    fflush (dump_file);
 
   clear_aux_for_blocks ();
 
@@ -3281,15 +3353,15 @@ if_convert (int x_life_data_ok)
     }
 
   /* Write the final stats.  */
-  if (rtl_dump_file && num_possible_if_blocks > 0)
+  if (dump_file && num_possible_if_blocks > 0)
     {
-      fprintf (rtl_dump_file,
+      fprintf (dump_file,
               "\n%d possible IF blocks searched.\n",
               num_possible_if_blocks);
-      fprintf (rtl_dump_file,
+      fprintf (dump_file,
               "%d IF blocks converted.\n",
               num_updated_if_blocks);
-      fprintf (rtl_dump_file,
+      fprintf (dump_file,
               "%d true changes made.\n\n\n",
               num_true_changes);
     }