OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index d9e9fad..a061817 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -42,6 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "except.h"
 #include "target.h"
+#include "params.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -251,8 +252,10 @@ struct qty_table_elem
   rtx comparison_const;
   int comparison_qty;
   unsigned int first_reg, last_reg;
-  enum machine_mode mode;
-  enum rtx_code comparison_code;
+  /* The sizes of these fields should match the sizes of the
+     code and mode fields of struct rtx_def (see rtl.h).  */
+  ENUM_BITFIELD(rtx_code) comparison_code : 16;
+  ENUM_BITFIELD(machine_mode) mode : 8;
 };
 
 /* The table of all qtys, indexed by qty number.  */
@@ -462,7 +465,9 @@ struct table_elt
   struct table_elt *related_value;
   int cost;
   int regcost;
-  enum machine_mode mode;
+  /* The size of this field should match the size
+     of the mode field of struct rtx_def (see rtl.h).  */
+  ENUM_BITFIELD(machine_mode) mode : 8;
   char in_memory;
   char is_const;
   char flag;
@@ -565,10 +570,6 @@ static struct table_elt *last_jump_equiv_class;
 
 static int constant_pool_entries_cost;
 
-/* Define maximum length of a branch path.  */
-
-#define PATHLENGTH     10
-
 /* This data describes a block that will be processed by cse_basic_block.  */
 
 struct cse_basic_block_data
@@ -592,7 +593,7 @@ struct cse_basic_block_data
         except that it is used when the destination label is not preceded
        by a BARRIER.  */
       enum taken {TAKEN, NOT_TAKEN, AROUND} status;
-    } path[PATHLENGTH];
+    } *path;
 };
 
 static bool fixed_base_plus_p  PARAMS ((rtx x));
@@ -3008,10 +3009,9 @@ find_best_addr (insn, loc, mode)
   if (flag_expensive_optimizations
       && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
          || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
-      && GET_CODE (XEXP (*loc, 0)) == REG
-      && GET_CODE (XEXP (*loc, 1)) == CONST_INT)
+      && GET_CODE (XEXP (*loc, 0)) == REG)
     {
-      rtx c = XEXP (*loc, 1);
+      rtx op1 = XEXP (*loc, 1);
 
       do_not_record = 0;
       hash = HASH (XEXP (*loc, 0), Pmode);
@@ -3053,7 +3053,7 @@ find_best_addr (insn, loc, mode)
                    || exp_equiv_p (p->exp, p->exp, 1, 0)))
              {
                rtx new = simplify_gen_binary (GET_CODE (*loc), Pmode,
-                                              p->exp, c);
+                                              p->exp, op1);
                int new_cost;
                new_cost = address_cost (new, mode);
 
@@ -3352,17 +3352,11 @@ fold_rtx (x, insn)
       /* If the next insn is a CODE_LABEL followed by a jump table,
         PC's value is a LABEL_REF pointing to that label.  That
         lets us fold switch statements on the VAX.  */
-      if (insn && GET_CODE (insn) == JUMP_INSN)
-       {
-         rtx next = next_nonnote_insn (insn);
-
-         if (next && GET_CODE (next) == CODE_LABEL
-             && NEXT_INSN (next) != 0
-             && GET_CODE (NEXT_INSN (next)) == JUMP_INSN
-             && (GET_CODE (PATTERN (NEXT_INSN (next))) == ADDR_VEC
-                 || GET_CODE (PATTERN (NEXT_INSN (next))) == ADDR_DIFF_VEC))
-           return gen_rtx_LABEL_REF (Pmode, next);
-       }
+      {
+       rtx next;
+       if (insn && tablejump_p (insn, &next, NULL))
+         return gen_rtx_LABEL_REF (Pmode, next);
+      }
       break;
 
     case SUBREG:
@@ -4718,8 +4712,10 @@ struct set
   /* Nonzero if the SET_SRC contains something
      whose value cannot be predicted and understood.  */
   char src_volatile;
-  /* Original machine mode, in case it becomes a CONST_INT.  */
-  enum machine_mode mode;
+  /* Original machine mode, in case it becomes a CONST_INT.
+     The size of this field should match the size of the mode
+     field of struct rtx_def (see rtl.h).  */
+  ENUM_BITFIELD(machine_mode) mode : 8;
   /* A constant equivalent for SET_SRC, if any.  */
   rtx src_const;
   /* Original SET_SRC value used for libcall notes.  */
@@ -5550,8 +5546,8 @@ cse_insn (insn, libcall_insn)
                  && (GET_CODE (sets[i].orig_src) == REG
                      || GET_CODE (sets[i].orig_src) == SUBREG
                      || GET_CODE (sets[i].orig_src) == MEM))
-               replace_rtx (REG_NOTES (libcall_insn), sets[i].orig_src,
-                            copy_rtx (new));
+               simplify_replace_rtx (REG_NOTES (libcall_insn),
+                                     sets[i].orig_src, copy_rtx (new));
 
              /* The result of apply_change_group can be ignored; see
                 canon_reg.  */
@@ -6658,9 +6654,7 @@ invalidate_skipped_set (dest, set, data)
     }
 
   if (GET_CODE (set) == CLOBBER
-#ifdef HAVE_cc0
-      || dest == cc0_rtx
-#endif
+      || CC0_P (dest)
       || dest == pc_rtx)
     return;
 
@@ -6949,7 +6943,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
         In this case invalidate_skipped_block will be called to invalidate any
         registers set in the block when following the jump.  */
 
-      else if ((follow_jumps || skip_blocks) && path_size < PATHLENGTH - 1
+      else if ((follow_jumps || skip_blocks) && path_size < PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH) - 1
               && GET_CODE (p) == JUMP_INSN
               && GET_CODE (PATTERN (p)) == SET
               && GET_CODE (SET_SRC (PATTERN (p))) == IF_THEN_ELSE
@@ -7079,6 +7073,9 @@ cse_main (f, nregs, after_loop, file)
   rtx insn = f;
   int i;
 
+  val.path = xmalloc (sizeof (struct branch_path)
+                     * PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
+
   cse_jumps_altered = 0;
   recorded_label_ref = 0;
   constant_pool_entries_cost = 0;
@@ -7202,6 +7199,7 @@ cse_main (f, nregs, after_loop, file)
   end_alias_analysis ();
   free (uid_cuid);
   free (reg_eqv_table);
+  free (val.path);
 
   return cse_jumps_altered || recorded_label_ref;
 }
@@ -7379,7 +7377,10 @@ cse_basic_block (from, to, next_branch, around_loop)
             following branches in this case.  */
          to_usage = 0;
          val.path_size = 0;
+         val.path = xmalloc (sizeof (struct branch_path)
+                             * PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
          cse_end_of_basic_block (insn, &val, 0, 0, 0);
+         free (val.path);
 
          /* If the tables we allocated have enough space left
             to handle all the SETs in the next basic block,
@@ -7461,6 +7462,7 @@ count_reg_usage (x, counts, dest, incr)
      int incr;
 {
   enum rtx_code code;
+  rtx note;
   const char *fmt;
   int i, j;
 
@@ -7495,15 +7497,8 @@ count_reg_usage (x, counts, dest, incr)
       /* Unless we are setting a REG, count everything in SET_DEST.  */
       if (GET_CODE (SET_DEST (x)) != REG)
        count_reg_usage (SET_DEST (x), counts, NULL_RTX, incr);
-
-      /* If SRC has side-effects, then we can't delete this insn, so the
-        usage of SET_DEST inside SRC counts.
-
-        ??? Strictly-speaking, we might be preserving this insn
-        because some other SET has side-effects, but that's hard
-        to do and can't happen now.  */
       count_reg_usage (SET_SRC (x), counts,
-                      side_effects_p (SET_SRC (x)) ? NULL_RTX : SET_DEST (x),
+                      SET_DEST (x),
                       incr);
       return;
 
@@ -7518,17 +7513,39 @@ count_reg_usage (x, counts, dest, incr)
       /* Things used in a REG_EQUAL note aren't dead since loop may try to
         use them.  */
 
-      count_reg_usage (REG_NOTES (x), counts, NULL_RTX, incr);
+      note = find_reg_equal_equiv_note (x);
+      if (note)
+       {
+         rtx eqv = XEXP (note, 0);
+
+         if (GET_CODE (eqv) == EXPR_LIST)
+         /* This REG_EQUAL note describes the result of a function call.
+            Process all the arguments.  */
+           do
+             {
+               count_reg_usage (XEXP (eqv, 0), counts, NULL_RTX, incr);
+               eqv = XEXP (eqv, 1);
+             }
+           while (eqv && GET_CODE (eqv) == EXPR_LIST);
+         else
+           count_reg_usage (eqv, counts, NULL_RTX, incr);
+       }
       return;
 
     case EXPR_LIST:
-    case INSN_LIST:
       if (REG_NOTE_KIND (x) == REG_EQUAL
-         || (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE))
+         || (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE)
+         /* FUNCTION_USAGE expression lists may include (CLOBBER (mem /u)),
+            involving registers in the address.  */
+         || GET_CODE (XEXP (x, 0)) == CLOBBER)
        count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
+
       count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
       return;
 
+    case INSN_LIST:
+      abort ();
+
     default:
       break;
     }
@@ -7618,33 +7635,49 @@ dead_libcall_p (insn, counts)
      rtx insn;
      int *counts;
 {
-  rtx note;
+  rtx note, set, new;
+
   /* See if there's a REG_EQUAL note on this insn and try to
      replace the source with the REG_EQUAL expression.
 
      We assume that insns with REG_RETVALs can only be reg->reg
      copies at this point.  */
   note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-  if (note)
-    {
-      rtx set = single_set (insn);
-      rtx new = simplify_rtx (XEXP (note, 0));
+  if (!note)
+    return false;
 
-      if (!new)
-       new = XEXP (note, 0);
+  set = single_set (insn);
+  if (!set)
+    return false;
 
-      /* While changing insn, we must update the counts accordingly.  */
-      count_reg_usage (insn, counts, NULL_RTX, -1);
+  new = simplify_rtx (XEXP (note, 0));
+  if (!new)
+    new = XEXP (note, 0);
 
-      if (set && validate_change (insn, &SET_SRC (set), new, 0))
+  /* While changing insn, we must update the counts accordingly.  */
+  count_reg_usage (insn, counts, NULL_RTX, -1);
+
+  if (validate_change (insn, &SET_SRC (set), new, 0))
+    {
+      count_reg_usage (insn, counts, NULL_RTX, 1);
+      remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
+      remove_note (insn, note);
+      return true;
+    }
+
+  if (CONSTANT_P (new))
+    {
+      new = force_const_mem (GET_MODE (SET_DEST (set)), new);
+      if (new && validate_change (insn, &SET_SRC (set), new, 0))
        {
-          count_reg_usage (insn, counts, NULL_RTX, 1);
+         count_reg_usage (insn, counts, NULL_RTX, 1);
          remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
          remove_note (insn, note);
          return true;
        }
-       count_reg_usage (insn, counts, NULL_RTX, 1);
     }
+      
+  count_reg_usage (insn, counts, NULL_RTX, 1);
   return false;
 }