OSDN Git Service

* cse.c (CSE_ADDRESS_COST): Remove.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 27 Apr 2000 14:56:47 +0000 (14:56 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 27 Apr 2000 14:56:47 +0000 (14:56 +0000)
(find_best_addr): Add new parameter "MODE", use address_cost instead
of CSE_ADDRESS_COST
(address_cost): New.
(fold_rtx): Update call of find_best_addr.
* rtl.h (address_cost): Declare.
* loop.c (general_induction_var): Add new parameter "MODE", use
address_cost instead of ADDRESS_COST
(init_loop): Use address_cost instead of ADDRESS_COST.
(check_insn_for_givs): Update call of general_induction_var.
(find_mem_givs): Likewise.
(consec_sets_giv): Likewise.
* config/i386/i386.h (ADDRESS_COST): Call ix86_address_cost.
* i386.c (ix86_address_cost): New.
* i386-protos.h (ix86_address_cost): Declare.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33486 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/cse.c
gcc/loop.c
gcc/rtl.h

index c563b21..b485d4f 100644 (file)
@@ -1,3 +1,21 @@
+Thu Apr 27 16:55:28 MET DST 2000  Jan Hubicka  <jh@suse.cz>
+
+       * cse.c (CSE_ADDRESS_COST): Remove.
+       (find_best_addr): Add new parameter "MODE", use address_cost instead
+       of CSE_ADDRESS_COST
+       (address_cost): New.
+       (fold_rtx): Update call of find_best_addr.
+       * rtl.h (address_cost): Declare.
+       * loop.c (general_induction_var): Add new parameter "MODE", use
+       address_cost instead of ADDRESS_COST
+       (init_loop): Use address_cost instead of ADDRESS_COST.
+       (check_insn_for_givs): Update call of general_induction_var.
+       (find_mem_givs): Likewise.
+       (consec_sets_giv): Likewise.
+       * config/i386/i386.h (ADDRESS_COST): Call ix86_address_cost.
+       * i386.c (ix86_address_cost): New.
+       * i386-protos.h (ix86_address_cost): Declare.
+
 Thu Apr 27 11:45:16 2000  Alexandre Oliva  <aoliva@cygnus.com>
 
        * config/mn10300/mn10300.md (movqi): Simplify.  Prefer data
index 420435f..3bd06b1 100644 (file)
@@ -108,6 +108,7 @@ extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
 extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
 extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
 extern void ix86_expand_strlensi_unroll_1 PARAMS ((rtx, rtx, rtx));
+extern int ix86_address_cost PARAMS ((rtx));
 
 extern rtx assign_386_stack_local PARAMS ((enum machine_mode, int));
 extern int ix86_attr_length_default PARAMS ((rtx));
index b2e81a4..0d96728 100644 (file)
@@ -2253,7 +2253,65 @@ ix86_decompose_address (addr, out)
 
   return TRUE;
 }
+\f
+/* Return cost of the memory address x.
+   For i386, it is better to use a complex address than let gcc copy
+   the address into a reg and make a new pseudo.  But not if the address
+   requires to two regs - that would mean more pseudos with longer
+   lifetimes.  */
+int
+ix86_address_cost (x)
+     rtx x;
+{
+  struct ix86_address parts;
+  int cost = 1;
 
+  if (!ix86_decompose_address (x, &parts))
+    abort ();
+
+  /* More complex memory references are better.  */
+  if (parts.disp && parts.disp != const0_rtx)
+    cost--;
+
+  /* Attempt to minimize number of registers in the address.  */
+  if ((parts.base
+       && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER))
+      || (parts.index
+         && (!REG_P (parts.index)
+             || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)))
+    cost++;
+
+  if (parts.base
+      && (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER)
+      && parts.index
+      && (!REG_P (parts.index) || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)
+      && parts.base != parts.index)
+    cost++;
+
+  /* AMD-K6 don't like addresses with ModR/M set to 00_xxx_100b,
+     since it's predecode logic can't detect the length of instructions
+     and it degenerates to vector decoded.  Increase cost of such
+     addresses here.  The penalty is minimally 2 cycles.  It may be worthwhile
+     to split such addresses or even refuse such addresses at all.  
+
+     Following addressing modes are affected:
+      [base+scale*index]
+      [scale*index+disp]
+      [base+index]
+   
+     The first and last case  may be avoidable by explicitly coding the zero in
+     memory address, but I don't have AMD-K6 machine handy to check this
+     theory.  */
+
+  if (TARGET_K6
+      && ((!parts.disp && parts.base && parts.index && parts.scale != 1)
+         || (parts.disp && !parts.base && parts.index && parts.scale != 1)
+         || (!parts.disp && parts.base && parts.index && parts.scale == 1)))
+    cost += 10;
+      
+  return cost;
+}
+\f
 /* Determine if a given CONST RTX is a valid memory displacement
    in PIC mode.  */
    
index 8ae7be8..9f5a28d 100644 (file)
@@ -2040,11 +2040,7 @@ while (0)
    lifetimes.  */
 
 #define ADDRESS_COST(RTX) \
-  ((CONSTANT_P (RTX)                                           \
-    || (GET_CODE (RTX) == PLUS && CONSTANT_P (XEXP (RTX, 1))   \
-       && REG_P (XEXP (RTX, 0)))) ? 0                          \
-   : REG_P (RTX) ? 1                                           \
-   : 2)
+  ix86_address_cost (x)
 
 /* A C expression for the cost of moving data from a register in class FROM to
    one in class TO.  The classes are expressed using the enumeration values
index 3e872e2..fe5e4a6 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -537,16 +537,6 @@ struct table_elt
 
 #define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (int) (N))
 
-#ifdef ADDRESS_COST
-/* The ADDRESS_COST macro does not deal with ADDRESSOF nodes.  But,
-   during CSE, such nodes are present.  Using an ADDRESSOF node which
-   refers to the address of a REG is a good thing because we can then
-   turn (MEM (ADDRESSSOF (REG))) into just plain REG.  */
-#define CSE_ADDRESS_COST(RTX)                                  \
-  ((GET_CODE (RTX) == ADDRESSOF && REG_P (XEXP ((RTX), 0)))    \
-   ? -1 : ADDRESS_COST(RTX))
-#endif 
-
 static struct table_elt *table[HASH_SIZE];
 
 /* Chain of `struct table_elt's made so far for this function
@@ -683,7 +673,7 @@ static unsigned canon_hash  PARAMS ((rtx, enum machine_mode));
 static unsigned safe_hash      PARAMS ((rtx, enum machine_mode));
 static int exp_equiv_p         PARAMS ((rtx, rtx, int, int));
 static rtx canon_reg           PARAMS ((rtx, rtx));
-static void find_best_addr     PARAMS ((rtx, rtx *));
+static void find_best_addr     PARAMS ((rtx, rtx *, enum machine_mode));
 static enum rtx_code find_comparison_args PARAMS ((enum rtx_code, rtx *, rtx *,
                                                   enum machine_mode *,
                                                   enum machine_mode *));
@@ -849,6 +839,34 @@ rtx_cost (x, outer_code)
   return total;
 }
 \f
+/* Return cost of address expression X.  Expect that X is propertly formed address
+   reference.  */
+int
+address_cost (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  /* The ADDRESS_COST macro does not deal with ADDRESSOF nodes.  But,
+     during CSE, such nodes are present.  Using an ADDRESSOF node which
+     refers to the address of a REG is a good thing because we can then
+     turn (MEM (ADDRESSSOF (REG))) into just plain REG.  */
+
+  if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
+    return -1;
+
+  /* We may be asked for cost of various unusual addresses, such as operands
+     of push instruction.  It is not worthwhile to complicate writting
+     of ADDRESS_COST macro by such cases.  */
+
+  if (!memory_address_p (mode, x))
+    return 1000;
+#ifdef ADDRESS_COST
+  return ADDRESS_COST (x);
+#else
+  return rtx_cost (x, MEM);
+#endif
+}
+\f
 static struct cse_reg_info *
 get_cse_reg_info (regno)
      unsigned int regno;
@@ -2681,9 +2699,10 @@ canon_reg (x, insn)
   */
 
 static void
-find_best_addr (insn, loc)
+find_best_addr (insn, loc, mode)
      rtx insn;
      rtx *loc;
+     enum machine_mode mode;
 {
   struct table_elt *elt;
   rtx addr = *loc;
@@ -2695,6 +2714,7 @@ find_best_addr (insn, loc)
   int save_hash_arg_in_memory = hash_arg_in_memory;
   int addr_volatile;
   int regno;
+  int folded_cost, addr_cost;
   unsigned hash;
 
   /* Do not try to replace constant addresses or addresses of local and
@@ -2728,14 +2748,13 @@ find_best_addr (insn, loc)
     {
       rtx folded = fold_rtx (copy_rtx (addr), NULL_RTX);
 
-      if (1
-#ifdef ADDRESS_COST
-         && (CSE_ADDRESS_COST (folded) < CSE_ADDRESS_COST (addr)
-             || (CSE_ADDRESS_COST (folded) == CSE_ADDRESS_COST (addr)
-                 && rtx_cost (folded, MEM) > rtx_cost (addr, MEM)))
-#else
+      folded_cost = address_cost (folded, mode);
+      addr_cost = address_cost (addr, mode);
+
+      if ((folded_cost < addr_cost
+          || (folded_cost == addr_cost
+              && rtx_cost (folded, MEM) > rtx_cost (addr, MEM)))
          && rtx_cost (folded, MEM) < rtx_cost (addr, MEM)
-#endif
          && validate_change (insn, loc, folded, 0))
        addr = folded;
     }
@@ -2782,8 +2801,9 @@ find_best_addr (insn, loc)
 
       while (found_better)
        {
-         int best_addr_cost = CSE_ADDRESS_COST (*loc);
+         int best_addr_cost = address_cost (*loc, mode);
          int best_rtx_cost = (elt->cost + 1) >> 1;
+         int exp_cost;
          struct table_elt *best_elt = elt; 
 
          found_better = 0;
@@ -2792,12 +2812,12 @@ find_best_addr (insn, loc)
              {
                if ((GET_CODE (p->exp) == REG
                     || exp_equiv_p (p->exp, p->exp, 1, 0))
-                   && (CSE_ADDRESS_COST (p->exp) < best_addr_cost
-                       || (CSE_ADDRESS_COST (p->exp) == best_addr_cost
-                           && (p->cost + 1) >> 1 > best_rtx_cost)))
+                   && ((exp_cost = address_cost (p->exp, mode)) < best_addr_cost
+                       || (exp_cost == best_addr_cost
+                           && (p->cost + 1) >> 1 < best_rtx_cost)))
                  {
                    found_better = 1;
-                   best_addr_cost = CSE_ADDRESS_COST (p->exp);
+                   best_addr_cost = exp_cost;
                    best_rtx_cost = (p->cost + 1) >> 1;
                    best_elt = p;
                  }
@@ -2851,7 +2871,7 @@ find_best_addr (insn, loc)
 
       while (found_better)
        {
-         int best_addr_cost = CSE_ADDRESS_COST (*loc);
+         int best_addr_cost = address_cost (*loc, mode);
          int best_rtx_cost = (COST (*loc) + 1) >> 1;
          struct table_elt *best_elt = elt; 
          rtx best_rtx = *loc;
@@ -2873,13 +2893,15 @@ find_best_addr (insn, loc)
              {
                rtx new = simplify_gen_binary (GET_CODE (*loc), Pmode,
                                               p->exp, c);
+               int new_cost;
+               new_cost = address_cost (new, mode);
 
-               if ((CSE_ADDRESS_COST (new) < best_addr_cost
-                   || (CSE_ADDRESS_COST (new) == best_addr_cost
-                       && (COST (new) + 1) >> 1 > best_rtx_cost)))
+               if (new_cost < best_addr_cost
+                   || (new_cost == best_addr_cost
+                       && (COST (new) + 1) >> 1 > best_rtx_cost))
                  {
                    found_better = 1;
-                   best_addr_cost = CSE_ADDRESS_COST (new);
+                   best_addr_cost = new_cost;
                    best_rtx_cost = (COST (new) + 1) >> 1;
                    best_elt = p;
                    best_rtx = new;
@@ -3350,7 +3372,7 @@ fold_rtx (x, insn)
         best address.  Not only don't we care, but we could modify the
         MEM in an invalid way since we have no insn to validate against.  */
       if (insn != 0)
-       find_best_addr (insn, &XEXP (x, 0));
+       find_best_addr (insn, &XEXP (x, 0), GET_MODE (x));
 
       {
        /* Even if we don't fold in the insn itself,
index 02ac5d7..0969678 100644 (file)
@@ -278,7 +278,7 @@ static int basic_induction_var PARAMS ((const struct loop *, rtx,
                                        rtx *, rtx *, rtx **, int *));
 static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, int *));
 static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
-                                         rtx *, rtx *, int, int *));
+                                         rtx *, rtx *, int, int *, enum machine_mode));
 static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
                                    rtx, rtx, rtx *, rtx *, rtx *));
 static int check_dbra_loop PARAMS ((struct loop *, int));
@@ -367,11 +367,7 @@ init_loop ()
 
   add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
 
-#ifdef ADDRESS_COST
-  reg_address_cost = ADDRESS_COST (reg);
-#else
-  reg_address_cost = rtx_cost (reg, MEM);
-#endif
+  reg_address_cost = address_cost (reg, SImode);
 
   /* We multiply by 2 to reconcile the difference in scale between
      these two ways of computing costs.  Otherwise the cost of a copy
@@ -5133,12 +5129,12 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
 
       if (/* SET_SRC is a giv.  */
          (general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
-                                 &mult_val, 0, &benefit)
+                                 &mult_val, 0, &benefit, VOIDmode)
           /* Equivalent expression is a giv.  */
           || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
               && general_induction_var (loop, XEXP (regnote, 0), &src_reg,
                                         &add_val, &mult_val, 0,
-                                        &benefit)))
+                                        &benefit, VOIDmode)))
          /* Don't try to handle any regs made by loop optimization.
             We have nothing on them in regno_first_uid, etc.  */
          && REGNO (dest_reg) < max_reg_before_loop
@@ -5276,7 +5272,7 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
           this one would not be seen.   */
 
        if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
-                                  &mult_val, 1, &benefit))
+                                  &mult_val, 1, &benefit, GET_MODE (x)))
          {
            /* Found one; record it.  */
            struct induction *v
@@ -6126,7 +6122,8 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
      such that the value of X is biv * mult + add;  */
 
 static int
-general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
+general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr,
+                      pbenefit, addr_mode)
      const struct loop *loop;
      rtx x;
      rtx *src_reg;
@@ -6134,6 +6131,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
      rtx *mult_val;
      int is_addr;
      int *pbenefit;
+     enum machine_mode addr_mode;
 {
   rtx orig_x = x;
   char *storage;
@@ -6207,13 +6205,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
     *mult_val = XEXP (*mult_val, 0);
 
   if (is_addr)
-    {
-#ifdef ADDRESS_COST
-      *pbenefit += ADDRESS_COST (orig_x) - reg_address_cost;
-#else
-      *pbenefit += rtx_cost (orig_x, MEM) - reg_address_cost;
-#endif
-    }
+    *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
   else
     *pbenefit += rtx_cost (orig_x, SET);
 
@@ -6745,11 +6737,12 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
          && GET_CODE (SET_DEST (set)) == REG
          && SET_DEST (set) == dest_reg
          && (general_induction_var (loop, SET_SRC (set), &src_reg,
-                                    add_val, mult_val, 0, &benefit)
+                                    add_val, mult_val, 0, &benefit, VOIDmode)
              /* Giv created by equivalent expression.  */
              || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
                  && general_induction_var (loop, XEXP (temp, 0), &src_reg,
-                                           add_val, mult_val, 0, &benefit)))
+                                           add_val, mult_val, 0, &benefit,
+                                           VOIDmode)))
          && src_reg == v->src_reg)
        {
          if (find_reg_note (p, REG_RETVAL, NULL_RTX))
index 172691e..7a4d493 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1486,6 +1486,7 @@ extern void push_obstacks         PARAMS ((struct obstack *,
 /* In cse.c */
 struct cse_basic_block_data;
 extern int rtx_cost                    PARAMS ((rtx, enum rtx_code));
+extern int address_cost                        PARAMS ((rtx, enum machine_mode));
 extern void delete_trivially_dead_insns        PARAMS ((rtx, int));
 #ifdef BUFSIZ
 extern int cse_main                    PARAMS ((rtx, int, int, FILE *));