OSDN Git Service

Index: gcc/ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / ifcvt.c
index 4de879d..2939de4 100644 (file)
@@ -1,22 +1,22 @@
 /* If-conversion support.
    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
 
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-   GNU CC is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
 
-   GNU CC is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GNU CC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -326,7 +326,7 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
   rtx then_end;                        /* last insn + 1 in THEN block */
   rtx else_start = NULL_RTX;   /* first insn in ELSE block or NULL */
   rtx else_end = NULL_RTX;     /* last insn + 1 in ELSE block */
-  int max;                     /* max # of insns to convert. */
+  int max;                     /* max # of insns to convert.  */
   int then_mod_ok;             /* whether conditional mods are ok in THEN */
   rtx true_expr;               /* test for else block insns */
   rtx false_expr;              /* test for then block insns */
@@ -560,7 +560,7 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
                           || code == GEU || code == GTU), normalize);
 }
 
-/* Emit instruction to move a rtx into STRICT_LOW_PART.  */
+/* Emit instruction to move an rtx into STRICT_LOW_PART.  */
 static void
 noce_emit_move_insn (x, y)
      rtx x, y;
@@ -580,8 +580,7 @@ noce_emit_move_insn (x, y)
   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),
+  store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y,
                   GET_MODE_BITSIZE (inmode));
 }
 
@@ -651,6 +650,12 @@ noce_try_store_flag_constants (if_info)
       mode = GET_MODE (if_info->x);
       ifalse = INTVAL (if_info->a);
       itrue = INTVAL (if_info->b);
+
+      /* Make sure we can represent the difference between the two values.  */
+      if ((itrue - ifalse > 0)
+         != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
+       return FALSE;
+
       diff = trunc_int_for_mode (itrue - ifalse, mode);
 
       can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
@@ -697,42 +702,42 @@ noce_try_store_flag_constants (if_info)
         =>   x = 3 + (test == 0);  */
       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
        {
-         target = expand_binop (mode,
-                                (diff == STORE_FLAG_VALUE
-                                 ? add_optab : sub_optab),
-                                GEN_INT (ifalse), target, if_info->x, 0,
-                                OPTAB_WIDEN);
+         target = expand_simple_binop (mode,
+                                       (diff == STORE_FLAG_VALUE
+                                        ? PLUS : MINUS),
+                                       GEN_INT (ifalse), target, if_info->x, 0,
+                                       OPTAB_WIDEN);
        }
 
       /* if (test) x = 8; else x = 0;
         =>   x = (test != 0) << 3;  */
       else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
        {
-         target = expand_binop (mode, ashl_optab,
-                                target, GEN_INT (tmp), if_info->x, 0,
-                                OPTAB_WIDEN);
+         target = expand_simple_binop (mode, ASHIFT,
+                                       target, GEN_INT (tmp), if_info->x, 0,
+                                       OPTAB_WIDEN);
        }
 
       /* if (test) x = -1; else x = b;
         =>   x = -(test != 0) | b;  */
       else if (itrue == -1)
        {
-         target = expand_binop (mode, ior_optab,
-                                target, GEN_INT (ifalse), if_info->x, 0,
-                                OPTAB_WIDEN);
+         target = expand_simple_binop (mode, IOR,
+                                       target, GEN_INT (ifalse), if_info->x, 0,
+                                       OPTAB_WIDEN);
        }
 
       /* if (test) x = a; else x = b;
         =>   x = (-(test != 0) & (b - a)) + a;  */
       else
        {
-         target = expand_binop (mode, and_optab,
-                                target, GEN_INT (diff), if_info->x, 0,
-                                OPTAB_WIDEN);
+         target = expand_simple_binop (mode, AND,
+                                       target, GEN_INT (diff), if_info->x, 0,
+                                       OPTAB_WIDEN);
          if (target)
-           target = expand_binop (mode, add_optab,
-                                  target, GEN_INT (ifalse), if_info->x, 0,
-                                  OPTAB_WIDEN);
+           target = expand_simple_binop (mode, PLUS,
+                                         target, GEN_INT (ifalse),
+                                         if_info->x, 0, OPTAB_WIDEN);
        }
 
       if (! target)
@@ -795,9 +800,10 @@ noce_try_store_flag_inc (if_info)
                                     1, normalize);
 
       if (target)
-       target = expand_binop (GET_MODE (if_info->x),
-                              subtract ? sub_optab : add_optab,
-                              if_info->x, target, if_info->x, 0, OPTAB_WIDEN);
+       target = expand_simple_binop (GET_MODE (if_info->x),
+                                     subtract ? MINUS : PLUS,
+                                     if_info->x, target, if_info->x,
+                                     0, OPTAB_WIDEN);
       if (target)
        {
          if (target != if_info->x)
@@ -846,9 +852,9 @@ noce_try_store_flag_mask (if_info)
                                     gen_reg_rtx (GET_MODE (if_info->x)),
                                     reversep, -1);
       if (target)
-        target = expand_binop (GET_MODE (if_info->x), and_optab,
-                              if_info->x, target, if_info->x, 0,
-                              OPTAB_WIDEN);
+        target = expand_simple_binop (GET_MODE (if_info->x), AND,
+                                     if_info->x, target, if_info->x, 0,
+                                     OPTAB_WIDEN);
 
       if (target)
        {
@@ -1108,6 +1114,8 @@ noce_try_cmove_arith (if_info)
        MEM_SCALAR_P (tmp) = 1;
       if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
        set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a));
+      set_mem_align (tmp,
+                    MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
 
       noce_emit_move_insn (if_info->x, tmp);
     }
@@ -1183,15 +1191,9 @@ noce_get_alt_condition (if_info, target, earliest)
          if (GET_CODE (src) == CONST_INT)
            {
              if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
-               {
-                 op_a = src;
-                 if_info->cond_earliest = prev_insn;
-               }
+               op_a = src;
              else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
-               {
-                 op_b = src;
-                 if_info->cond_earliest = prev_insn;
-               }
+               op_b = src;
 
              if (GET_CODE (op_a) == CONST_INT)
                {
@@ -1288,9 +1290,8 @@ noce_try_minmax (if_info)
      struct noce_if_info *if_info;
 { 
   rtx cond, earliest, target, seq;
-  enum rtx_code code;
+  enum rtx_code code, op;
   int unsignedp;
-  optab op;
 
   /* ??? Can't guarantee that expand_binop won't create pseudos.  */
   if (no_new_pseudos)
@@ -1333,24 +1334,24 @@ noce_try_minmax (if_info)
     case LE:
     case UNLT:
     case UNLE:
-      op = smax_optab;
+      op = SMAX;
       unsignedp = 0;
       break;
     case GT:
     case GE:
     case UNGT:
     case UNGE:
-      op = smin_optab;
+      op = SMIN;
       unsignedp = 0;
       break;
     case LTU:
     case LEU:
-      op = umax_optab;
+      op = UMAX;
       unsignedp = 1;
       break;
     case GTU:
     case GEU:
-      op = umin_optab;
+      op = UMIN;
       unsignedp = 1;
       break;
     default:
@@ -1359,8 +1360,9 @@ noce_try_minmax (if_info)
 
   start_sequence ();
 
-  target = expand_binop (GET_MODE (if_info->x), op, if_info->a, if_info->b,
-                        if_info->x, unsignedp, OPTAB_WIDEN);
+  target = expand_simple_binop (GET_MODE (if_info->x), op,
+                               if_info->a, if_info->b,
+                               if_info->x, unsignedp, OPTAB_WIDEN);
   if (! target)
     {
       end_sequence ();
@@ -1471,12 +1473,12 @@ noce_try_abs (if_info)
 
   start_sequence ();
 
-  target = expand_unop (GET_MODE (if_info->x), abs_optab, b, if_info->x, 0);
+  target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0);
 
   /* ??? It's a quandry whether cmove would be better here, especially
      for integers.  Perhaps combine will clean things up.  */
   if (target && negate)
-    target = expand_unop (GET_MODE (target), neg_optab, target, if_info->x, 0);
+    target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0);
 
   if (! target)
     {
@@ -1770,9 +1772,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
 
  success:
   /* The original sets may now be killed.  */
-  if (insn_a == then_bb->end)
-    then_bb->end = PREV_INSN (insn_a);
-  flow_delete_insn (insn_a);
+  delete_insn (insn_a);
 
   /* Several special cases here: First, we may have reused insn_b above,
      in which case insn_b is now NULL.  Second, we want to delete insn_b
@@ -1781,17 +1781,12 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
      the TEST block, it may in fact be loading data needed for the comparison.
      We'll let life_analysis remove the insn if it's really dead.  */
   if (insn_b && else_bb)
-    {
-      if (insn_b == else_bb->end)
-       else_bb->end = PREV_INSN (insn_b);
-      flow_delete_insn (insn_b);
-    }
+    delete_insn (insn_b);
 
   /* The new insns will have been inserted before cond_earliest.  We should
      be able to remove the jump with impunity, but the condition itself may
      have been modified by gcse to be shared across basic blocks.  */
-  test_bb->end = PREV_INSN (jump);
-  flow_delete_insn (jump);
+  delete_insn (jump);
 
   /* If we used a temporary, fix it up now.  */
   if (orig_x != x)
@@ -1801,7 +1796,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
       insn_b = gen_sequence ();
       end_sequence ();
 
-      test_bb->end = emit_insn_after (insn_b, test_bb->end);
+      emit_insn_after (insn_b, test_bb->end);
     }
 
   /* Merge the blocks!  */
@@ -1886,7 +1881,9 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
      is more than one remaining edge, it must come from elsewhere.  There
      may be zero incoming edges if the THEN block didn't actually join 
      back up (as with a call to abort).  */
-  else if (join_bb->pred == NULL || join_bb->pred->pred_next == NULL)
+  else if ((join_bb->pred == NULL
+           || join_bb->pred->pred_next == NULL)
+          && join_bb != EXIT_BLOCK_PTR)
     {
       /* We can merge the JOIN.  */
       if (life_data_ok)
@@ -1906,7 +1903,8 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
        abort ();
 
       /* Remove the jump and cruft from the end of the COMBO block.  */
-      tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
+      if (join_bb != EXIT_BLOCK_PTR)
+        tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
     }
 
   /* Make sure we update life info properly.  */
@@ -2072,7 +2070,7 @@ find_if_block (test_bb, then_edge, else_edge)
   next_index = then_bb->index;
   if (else_bb && ++next_index != else_bb->index)
     return FALSE;
-  if (++next_index != join_bb->index)
+  if (++next_index != join_bb->index && join_bb->index != EXIT_BLOCK)
     {
       if (else_bb)
        join_bb = NULL;
@@ -2191,11 +2189,9 @@ find_cond_trap (test_bb, then_edge, else_edge)
 
   emit_insn_before (seq, cond_earliest);
 
-  test_bb->end = PREV_INSN (jump);
-  flow_delete_insn (jump);
+  delete_insn (jump);
 
-  trap_bb->end = PREV_INSN (trap);
-  flow_delete_insn (trap);
+  delete_insn (trap);
 
   /* Merge the blocks!  */
   if (trap_bb != then_bb && ! else_bb)
@@ -2541,7 +2537,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
              /* ??? Even non-trapping memories such as stack frame
                 references must be avoided.  For stores, we collect
                 no lifetime info; for reads, we'd have to assert
-                true_dependance false against every store in the
+                true_dependence false against every store in the
                 TEST range.  */
              if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
                return FALSE;
@@ -2661,6 +2657,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       probability = BRANCH_EDGE (test_bb)->probability;
       BRANCH_EDGE (test_bb)->probability = FALLTHRU_EDGE (test_bb)->probability;
       FALLTHRU_EDGE (test_bb)->probability = probability;
+      update_br_prob_note (test_bb);
     }
 
   /* Move the insns out of MERGE_BB to before the branch.  */
@@ -2669,19 +2666,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
       if (end == merge_bb->end)
        merge_bb->end = PREV_INSN (head);
 
-      head = squeeze_notes (head, end);
-      if (GET_CODE (end) == NOTE
-         && (NOTE_LINE_NUMBER (end) == NOTE_INSN_BLOCK_END
-              || NOTE_LINE_NUMBER (end) == NOTE_INSN_BLOCK_BEG
-              || NOTE_LINE_NUMBER (end) == NOTE_INSN_LOOP_BEG
-              || NOTE_LINE_NUMBER (end) == NOTE_INSN_LOOP_END
-              || NOTE_LINE_NUMBER (end) == NOTE_INSN_LOOP_CONT
-              || NOTE_LINE_NUMBER (end) == NOTE_INSN_LOOP_VTOP))
-       {
-         if (head == end)
-           return TRUE;
-         end = PREV_INSN (end);
-       }
+      if (squeeze_notes (&head, &end))
+       return TRUE;
 
       reorder_insns (head, end, PREV_INSN (earliest));
     }
@@ -2737,9 +2723,6 @@ if_convert (x_life_data_ok)
   if (rtl_dump_file)
     fflush (rtl_dump_file);
 
-  /* Rebuild basic_block_for_insn for update_life_info and for gcse.  */
-  compute_bb_for_insn (get_max_uid ());
-
   /* Rebuild life info for basic blocks that require it.  */
   if (num_removed_blocks && life_data_ok)
     {
@@ -2766,6 +2749,7 @@ if_convert (x_life_data_ok)
 
       sbitmap_free (update_life_blocks);
     }
+  clear_aux_for_blocks ();
 
   /* Write the final stats.  */
   if (rtl_dump_file && num_possible_if_blocks > 0)