OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index 4109b58..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);
 
@@ -4712,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.  */
@@ -5544,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.  */
@@ -6941,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
@@ -7071,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;
@@ -7194,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;
 }
@@ -7371,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,
@@ -7506,7 +7515,32 @@ count_reg_usage (x, counts, dest, incr)
 
       note = find_reg_equal_equiv_note (x);
       if (note)
-        count_reg_usage (XEXP (note, 0), counts, NULL_RTX, incr);
+       {
+         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:
+      if (REG_NOTE_KIND (x) == REG_EQUAL
+         || (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:
@@ -7601,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;
 }