OSDN Git Service

* tree-ssa-loop-ivopts.c (get_address_cost): Add address elements in
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Nov 2004 20:49:55 +0000 (20:49 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Nov 2004 20:49:55 +0000 (20:49 +0000)
right order.
(force_var_cost): Determine cost of addition and multiplication more
precisely.
(get_computation_cost_at): Add cost for computing address elements to
the final cost.

* fold-const.c (fold): Attempt to use ptr_difference_const whenever
one of the arguments of MINUS_EXPR is an address.
(split_address_to_core_and_offset): New function.
(ptr_difference_const): Handle case when one of the operands is a
pointer.
* tree-ssa-loop-ivopts.c (determine_base_object): Fold &*addr.
(ptr_difference_cost): Pass addresses instead of objects to
ptr_difference_const.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/tree-ssa-loop-ivopts.c

index f17008d..57c0622 100644 (file)
@@ -1,3 +1,21 @@
+2004-11-10  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       * tree-ssa-loop-ivopts.c (get_address_cost): Add address elements in
+       right order.
+       (force_var_cost): Determine cost of addition and multiplication more
+       precisely.
+       (get_computation_cost_at): Add cost for computing address elements to
+       the final cost.
+
+       * fold-const.c (fold): Attempt to use ptr_difference_const whenever
+       one of the arguments of MINUS_EXPR is an address.
+       (split_address_to_core_and_offset): New function.
+       (ptr_difference_const): Handle case when one of the operands is a
+       pointer.
+       * tree-ssa-loop-ivopts.c (determine_base_object): Fold &*addr.
+       (ptr_difference_cost): Pass addresses instead of objects to
+       ptr_difference_const.
+
 2004-11-10  Nathan Sidwell  <nathan@codesourcery.com>
 
        * tree.c (tree_check_failed): Emit general error if the list of
index a14bfb7..b8ccfa1 100644 (file)
@@ -7074,11 +7074,9 @@ fold (tree expr)
       {
        HOST_WIDE_INT diff;
 
-       if (TREE_CODE (arg0) == ADDR_EXPR
-           && TREE_CODE (arg1) == ADDR_EXPR
-           && ptr_difference_const (TREE_OPERAND (arg0, 0),
-                                    TREE_OPERAND (arg1, 0),
-                                    &diff))
+       if ((TREE_CODE (arg0) == ADDR_EXPR
+            || TREE_CODE (arg1) == ADDR_EXPR)
+           && ptr_difference_const (arg0, arg1, &diff))
          return build_int_cst_type (type, diff);
       }
          
@@ -10815,23 +10813,49 @@ round_down (tree value, int divisor)
   return value;
 }
 
+/* Returns the pointer to the base of the object addressed by EXP and
+   extracts the information about the offset of the access, storing it
+   to PBITPOS and POFFSET.  */
+
+static tree
+split_address_to_core_and_offset (tree exp,
+                                 HOST_WIDE_INT *pbitpos, tree *poffset)
+{
+  tree core;
+  enum machine_mode mode;
+  int unsignedp, volatilep;
+  HOST_WIDE_INT bitsize;
+
+  if (TREE_CODE (exp) == ADDR_EXPR)
+    {
+      core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
+                                 poffset, &mode, &unsignedp, &volatilep);
+
+      if (TREE_CODE (core) == INDIRECT_REF)
+       core = TREE_OPERAND (core, 0);
+    }
+  else
+    {
+      core = exp;
+      *pbitpos = 0;
+      *poffset = NULL_TREE;
+    }
+
+  return core;
+}
+
 /* Returns true if addresses of E1 and E2 differ by a constant, false
-   otherwise.  If they do, &E1 - &E2 is stored in *DIFF.  */
+   otherwise.  If they do, E1 - E2 is stored in *DIFF.  */
 
 bool
 ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
 {
   tree core1, core2;
-  HOST_WIDE_INT bitsize1, bitsize2;
   HOST_WIDE_INT bitpos1, bitpos2;
   tree toffset1, toffset2, tdiff, type;
-  enum machine_mode mode1, mode2;
-  int unsignedp1, unsignedp2, volatilep1, volatilep2;
 
-  core1 = get_inner_reference (e1, &bitsize1, &bitpos1, &toffset1, &mode1,
-                              &unsignedp1, &volatilep1);
-  core2 = get_inner_reference (e2, &bitsize2, &bitpos2, &toffset2, &mode2,
-                              &unsignedp2, &volatilep2);
+  core1 = split_address_to_core_and_offset (e1, &bitpos1, &toffset1);
+  core2 = split_address_to_core_and_offset (e2, &bitpos2, &toffset2);
 
   if (bitpos1 % BITS_PER_UNIT != 0
       || bitpos2 % BITS_PER_UNIT != 0
index 557fd21..417c463 100644 (file)
@@ -678,6 +678,9 @@ determine_base_object (tree expr)
       if (!base)
        return fold_convert (ptr_type_node, expr);
 
+      if (TREE_CODE (base) == INDIRECT_REF)
+       return fold_convert (ptr_type_node, TREE_OPERAND (base, 0));
+
       return fold (build1 (ADDR_EXPR, ptr_type_node, base));
 
     case PLUS_EXPR:
@@ -2613,7 +2616,7 @@ get_address_cost (bool symbol_present, bool var_present,
        addr = gen_rtx_fmt_ee (MULT, Pmode, addr, GEN_INT (rat));
 
       if (var_present)
-       addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, addr);
+       addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
 
       if (symbol_present)
        {
@@ -2630,7 +2633,7 @@ get_address_cost (bool symbol_present, bool var_present,
        base = NULL_RTX;
     
       if (base)
-       addr = gen_rtx_fmt_ee (PLUS, Pmode, base, addr);
+       addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
   
       start_sequence ();
       addr = memory_address (Pmode, addr);
@@ -2672,7 +2675,7 @@ find_depends (tree *expr_p, int *ws ATTRIBUTE_UNUSED, void *data)
   return NULL_TREE;
 }
 
-/* Estimates cost of forcing EXPR into variable.  DEPENDS_ON is a set of the
+/* Estimates cost of forcing EXPR into variable.  DEPENDS_ON is a set of the
    invariants the computation depends on.  */
 
 static unsigned
@@ -2683,6 +2686,9 @@ force_var_cost (struct ivopts_data *data,
   static unsigned integer_cost;
   static unsigned symbol_cost;
   static unsigned address_cost;
+  tree op0, op1;
+  unsigned cost0, cost1, cost;
+  enum machine_mode mode;
 
   if (!costs_initialized)
     {
@@ -2744,8 +2750,60 @@ force_var_cost (struct ivopts_data *data,
       return address_cost;
     }
 
-  /* Just an arbitrary value, FIXME.  */
-  return target_spill_cost;
+  switch (TREE_CODE (expr))
+    {
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+      op0 = TREE_OPERAND (expr, 0);
+      op1 = TREE_OPERAND (expr, 1);
+
+      if (is_gimple_val (op0))
+       cost0 = 0;
+      else
+       cost0 = force_var_cost (data, op0, NULL);
+
+      if (is_gimple_val (op1))
+       cost1 = 0;
+      else
+       cost1 = force_var_cost (data, op1, NULL);
+
+      break;
+
+    default:
+      /* Just an arbitrary value, FIXME.  */
+      return target_spill_cost;
+    }
+
+  mode = TYPE_MODE (TREE_TYPE (expr));
+  switch (TREE_CODE (expr))
+    {
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+      cost = add_cost (mode);
+      break;
+
+    case MULT_EXPR:
+      if (cst_and_fits_in_hwi (op0))
+       cost = multiply_by_cost (int_cst_value (op0), mode);
+      else if (cst_and_fits_in_hwi (op1))
+       cost = multiply_by_cost (int_cst_value (op1), mode);
+      else
+       return target_spill_cost;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  cost += cost0;
+  cost += cost1;
+
+  /* Bound the cost by target_spill_cost.  The parts of complicated
+     computations often are either loop invariant or at least can
+     be shared between several iv uses, so letting this grow without
+     limits would not give reasonable results.  */
+  return cost < target_spill_cost ? cost : target_spill_cost;
 }
 
 /* Estimates cost of expressing address ADDR  as var + symbol + offset.  The
@@ -2809,9 +2867,7 @@ ptr_difference_cost (struct ivopts_data *data,
 
   gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
 
-  if (TREE_CODE (e2) == ADDR_EXPR
-      && ptr_difference_const (TREE_OPERAND (e1, 0),
-                              TREE_OPERAND (e2, 0), &diff))
+  if (ptr_difference_const (e1, e2, &diff))
     {
       *offset += diff;
       *symbol_present = false;
@@ -2994,7 +3050,7 @@ get_computation_cost_at (struct ivopts_data *data,
      (symbol/var/const parts may be omitted).  If we are looking for an address,
      find the cost of addressing this.  */
   if (address_p)
-    return get_address_cost (symbol_present, var_present, offset, ratio);
+    return cost + get_address_cost (symbol_present, var_present, offset, ratio);
 
   /* Otherwise estimate the costs for computing the expression.  */
   aratio = ratio > 0 ? ratio : -ratio;