OSDN Git Service

PR c/12553
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index 5e6c9e4..7612a5a 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -569,6 +569,7 @@ static struct table_elt *last_jump_equiv_class;
    the insn.  */
 
 static int constant_pool_entries_cost;
+static int constant_pool_entries_regcost;
 
 /* This data describes a block that will be processed by cse_basic_block.  */
 
@@ -647,7 +648,7 @@ static void invalidate_skipped_block (rtx);
 static void cse_check_loop_start (rtx, rtx, void *);
 static void cse_set_around_loop (rtx, rtx, rtx);
 static rtx cse_basic_block (rtx, rtx, struct branch_path *, int);
-static void count_reg_usage (rtx, int *, rtx, int);
+static void count_reg_usage (rtx, int *, int);
 static int check_for_label_ref (rtx *, void *);
 extern void dump_class (struct table_elt*);
 static struct cse_reg_info * get_cse_reg_info (unsigned int);
@@ -929,7 +930,7 @@ get_cse_reg_info (unsigned int regno)
          cse_reg_info_free_list = p->next;
        }
       else
-       p = (struct cse_reg_info *) xmalloc (sizeof (struct cse_reg_info));
+       p = xmalloc (sizeof (struct cse_reg_info));
 
       /* Insert into hash table.  */
       p->hash_next = *hash_head;
@@ -967,7 +968,7 @@ new_basic_block (void)
 
   /* Clear out hash table state for this pass.  */
 
-  memset ((char *) reg_hash, 0, sizeof reg_hash);
+  memset (reg_hash, 0, sizeof reg_hash);
 
   if (cse_reg_info_used_list)
     {
@@ -1540,7 +1541,7 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
   else
     {
       n_elements_made++;
-      elt = (struct table_elt *) xmalloc (sizeof (struct table_elt));
+      elt = xmalloc (sizeof (struct table_elt));
     }
 
   elt->exp = x;
@@ -3529,7 +3530,10 @@ fold_rtx (rtx x, rtx insn)
            rtx new;
 
            if (CONSTANT_P (constant) && GET_CODE (constant) != CONST_INT)
-             constant_pool_entries_cost = COST (constant);
+             {
+               constant_pool_entries_cost = COST (constant);
+               constant_pool_entries_regcost = approx_reg_cost (constant);
+             }
 
            /* If we are loading the full constant, we have an equivalence.  */
            if (offset == 0 && mode == const_mode)
@@ -3783,10 +3787,11 @@ fold_rtx (rtx x, rtx insn)
       || code == LTGT || code == UNEQ || code == ORDERED
       || code == UNORDERED)
     {
-      if (must_swap || (const_arg0
-                       && (const_arg1 == 0
-                           || (GET_CODE (const_arg0) == CONST_INT
-                               && GET_CODE (const_arg1) != CONST_INT))))
+      if (must_swap
+         || swap_commutative_operands_p (const_arg0 ? const_arg0
+                                                    : XEXP (x, 0),
+                                         const_arg1 ? const_arg1
+                                                    : XEXP (x, 1)))
        {
          rtx tem = XEXP (x, 0);
 
@@ -4692,7 +4697,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 
   if (GET_CODE (x) == SET)
     {
-      sets = (struct set *) alloca (sizeof (struct set));
+      sets = alloca (sizeof (struct set));
       sets[0].rtl = x;
 
       /* Ignore SETs that are unconditional jumps.
@@ -4727,7 +4732,7 @@ cse_insn (rtx insn, rtx libcall_insn)
     {
       int lim = XVECLEN (x, 0);
 
-      sets = (struct set *) alloca (lim * sizeof (struct set));
+      sets = alloca (lim * sizeof (struct set));
 
       /* Find all regs explicitly clobbered in this insn,
         and ensure they are not replaced with any other regs
@@ -5411,7 +5416,11 @@ cse_insn (rtx insn, rtx libcall_insn)
            {
              trial = src_folded, src_folded_cost = MAX_COST;
              if (src_folded_force_flag)
-               trial = force_const_mem (mode, trial);
+               {
+                 rtx forced = force_const_mem (mode, trial);
+                 if (forced)
+                   trial = forced;
+               }
            }
          else if (src
                   && preferrable (src_cost, src_regcost,
@@ -5506,6 +5515,7 @@ cse_insn (rtx insn, rtx libcall_insn)
              src_folded_force_flag = 1;
              src_folded = trial;
              src_folded_cost = constant_pool_entries_cost;
+             src_folded_regcost = constant_pool_entries_regcost;
            }
        }
 
@@ -6665,7 +6675,15 @@ cse_set_around_loop (rtx x, rtx insn, rtx loop_start)
                              abort ();
                          }
                        else
-                         emit_insn_after (move, p);
+                         {
+                           if (control_flow_insn_p (p))
+                             /* p can cause a control flow transfer so it
+                                is the last insn of a basic block.  We can't
+                                therefore use emit_insn_after.  */
+                             emit_insn_before (move, next_nonnote_insn (p));
+                           else
+                             emit_insn_after (move, p);
+                         }
                      }
                    break;
                  }
@@ -6930,6 +6948,7 @@ cse_main (rtx f, int nregs, int after_loop, FILE *file)
   cse_jumps_altered = 0;
   recorded_label_ref = 0;
   constant_pool_entries_cost = 0;
+  constant_pool_entries_regcost = 0;
   val.path_size = 0;
 
   init_recog ();
@@ -6939,8 +6958,7 @@ cse_main (rtx f, int nregs, int after_loop, FILE *file)
 
   max_insn_uid = get_max_uid ();
 
-  reg_eqv_table = (struct reg_eqv_elem *)
-    xmalloc (nregs * sizeof (struct reg_eqv_elem));
+  reg_eqv_table = xmalloc (nregs * sizeof (struct reg_eqv_elem));
 
 #ifdef LOAD_EXTEND_OP
 
@@ -6956,7 +6974,7 @@ cse_main (rtx f, int nregs, int after_loop, FILE *file)
   /* Find the largest uid.  */
 
   max_uid = get_max_uid ();
-  uid_cuid = (int *) xcalloc (max_uid + 1, sizeof (int));
+  uid_cuid = xcalloc (max_uid + 1, sizeof (int));
 
   /* Compute the mapping from uids to cuids.
      CUIDs are numbers assigned to insns, like uids,
@@ -7075,9 +7093,7 @@ cse_basic_block (rtx from, rtx to, struct branch_path *next_branch,
   /* This array is undefined before max_reg, so only allocate
      the space actually needed and adjust the start.  */
 
-  qty_table
-    = (struct qty_table_elem *) xmalloc ((max_qty - max_reg)
-                                        * sizeof (struct qty_table_elem));
+  qty_table = xmalloc ((max_qty - max_reg) * sizeof (struct qty_table_elem));
   qty_table -= max_reg;
 
   new_basic_block ();
@@ -7295,14 +7311,10 @@ check_for_label_ref (rtx *rtl, void *data)
 \f
 /* Count the number of times registers are used (not set) in X.
    COUNTS is an array in which we accumulate the count, INCR is how much
-   we count each register usage.
-
-   Don't count a usage of DEST, which is the SET_DEST of a SET which
-   contains X in its SET_SRC.  This is because such a SET does not
-   modify the liveness of DEST.  */
+   we count each register usage.  */
 
 static void
-count_reg_usage (rtx x, int *counts, rtx dest, int incr)
+count_reg_usage (rtx x, int *counts, int incr)
 {
   enum rtx_code code;
   rtx note;
@@ -7315,8 +7327,7 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
   switch (code = GET_CODE (x))
     {
     case REG:
-      if (x != dest)
-       counts[REGNO (x)] += incr;
+      counts[REGNO (x)] += incr;
       return;
 
     case PC:
@@ -7333,25 +7344,23 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
       /* If we are clobbering a MEM, mark any registers inside the address
          as being used.  */
       if (GET_CODE (XEXP (x, 0)) == MEM)
-       count_reg_usage (XEXP (XEXP (x, 0), 0), counts, NULL_RTX, incr);
+       count_reg_usage (XEXP (XEXP (x, 0), 0), counts, incr);
       return;
 
     case SET:
       /* 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);
-      count_reg_usage (SET_SRC (x), counts,
-                      SET_DEST (x),
-                      incr);
+       count_reg_usage (SET_DEST (x), counts, incr);
+      count_reg_usage (SET_SRC (x), counts, incr);
       return;
 
     case CALL_INSN:
-      count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, NULL_RTX, incr);
+      count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, incr);
       /* Fall through.  */
 
     case INSN:
     case JUMP_INSN:
-      count_reg_usage (PATTERN (x), counts, NULL_RTX, incr);
+      count_reg_usage (PATTERN (x), counts, incr);
 
       /* Things used in a REG_EQUAL note aren't dead since loop may try to
         use them.  */
@@ -7366,12 +7375,12 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
             Process all the arguments.  */
            do
              {
-               count_reg_usage (XEXP (eqv, 0), counts, NULL_RTX, incr);
+               count_reg_usage (XEXP (eqv, 0), counts, incr);
                eqv = XEXP (eqv, 1);
              }
            while (eqv && GET_CODE (eqv) == EXPR_LIST);
          else
-           count_reg_usage (eqv, counts, NULL_RTX, incr);
+           count_reg_usage (eqv, counts, incr);
        }
       return;
 
@@ -7381,9 +7390,15 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
          /* 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, 0), counts, incr);
+
+      count_reg_usage (XEXP (x, 1), counts, incr);
+      return;
 
-      count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
+    case ASM_OPERANDS:
+      /* Iterate over just the inputs, not the constraints as well.  */
+      for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
+       count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, incr);
       return;
 
     case INSN_LIST:
@@ -7397,10 +7412,10 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       count_reg_usage (XEXP (x, i), counts, dest, incr);
+       count_reg_usage (XEXP (x, i), counts, incr);
       else if (fmt[i] == 'E')
        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         count_reg_usage (XVECEXP (x, i, j), counts, dest, incr);
+         count_reg_usage (XVECEXP (x, i, j), counts, incr);
     }
 }
 \f
@@ -7492,11 +7507,11 @@ dead_libcall_p (rtx insn, int *counts)
     new = XEXP (note, 0);
 
   /* While changing insn, we must update the counts accordingly.  */
-  count_reg_usage (insn, counts, NULL_RTX, -1);
+  count_reg_usage (insn, counts, -1);
 
   if (validate_change (insn, &SET_SRC (set), new, 0))
     {
-      count_reg_usage (insn, counts, NULL_RTX, 1);
+      count_reg_usage (insn, counts, 1);
       remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
       remove_note (insn, note);
       return true;
@@ -7507,14 +7522,14 @@ dead_libcall_p (rtx insn, int *counts)
       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, 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, 1);
   return false;
 }
 
@@ -7536,9 +7551,9 @@ delete_trivially_dead_insns (rtx insns, int nreg)
 
   timevar_push (TV_DELETE_TRIVIALLY_DEAD);
   /* First count the number of times each register is used.  */
-  counts = (int *) xcalloc (nreg, sizeof (int));
+  counts = xcalloc (nreg, sizeof (int));
   for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
-    count_reg_usage (insn, counts, NULL_RTX, 1);
+    count_reg_usage (insn, counts, 1);
 
   do
     {
@@ -7582,7 +7597,7 @@ delete_trivially_dead_insns (rtx insns, int nreg)
 
          if (! live_insn)
            {
-             count_reg_usage (insn, counts, NULL_RTX, -1);
+             count_reg_usage (insn, counts, -1);
              delete_insn_and_edges (insn);
              ndead++;
            }