Commit 7299dbfb by Zdenek Dvorak Committed by Zdenek Dvorak

tree-ssa-loop-ivopts.c (get_address_cost): Add address elements in right order.

	* 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.

From-SVN: r90451
parent 96654664
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> 2004-11-10 Nathan Sidwell <nathan@codesourcery.com>
* tree.c (tree_check_failed): Emit general error if the list of * tree.c (tree_check_failed): Emit general error if the list of
......
...@@ -7074,11 +7074,9 @@ fold (tree expr) ...@@ -7074,11 +7074,9 @@ fold (tree expr)
{ {
HOST_WIDE_INT diff; HOST_WIDE_INT diff;
if (TREE_CODE (arg0) == ADDR_EXPR if ((TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (arg1) == ADDR_EXPR || TREE_CODE (arg1) == ADDR_EXPR)
&& ptr_difference_const (TREE_OPERAND (arg0, 0), && ptr_difference_const (arg0, arg1, &diff))
TREE_OPERAND (arg1, 0),
&diff))
return build_int_cst_type (type, diff); return build_int_cst_type (type, diff);
} }
...@@ -10815,23 +10813,49 @@ round_down (tree value, int divisor) ...@@ -10815,23 +10813,49 @@ round_down (tree value, int divisor)
return value; 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 /* 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 bool
ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff) ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
{ {
tree core1, core2; tree core1, core2;
HOST_WIDE_INT bitsize1, bitsize2;
HOST_WIDE_INT bitpos1, bitpos2; HOST_WIDE_INT bitpos1, bitpos2;
tree toffset1, toffset2, tdiff, type; tree toffset1, toffset2, tdiff, type;
enum machine_mode mode1, mode2;
int unsignedp1, unsignedp2, volatilep1, volatilep2;
core1 = get_inner_reference (e1, &bitsize1, &bitpos1, &toffset1, &mode1, core1 = split_address_to_core_and_offset (e1, &bitpos1, &toffset1);
&unsignedp1, &volatilep1); core2 = split_address_to_core_and_offset (e2, &bitpos2, &toffset2);
core2 = get_inner_reference (e2, &bitsize2, &bitpos2, &toffset2, &mode2,
&unsignedp2, &volatilep2);
if (bitpos1 % BITS_PER_UNIT != 0 if (bitpos1 % BITS_PER_UNIT != 0
|| bitpos2 % BITS_PER_UNIT != 0 || bitpos2 % BITS_PER_UNIT != 0
......
...@@ -678,6 +678,9 @@ determine_base_object (tree expr) ...@@ -678,6 +678,9 @@ determine_base_object (tree expr)
if (!base) if (!base)
return fold_convert (ptr_type_node, expr); 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)); return fold (build1 (ADDR_EXPR, ptr_type_node, base));
case PLUS_EXPR: case PLUS_EXPR:
...@@ -2613,7 +2616,7 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -2613,7 +2616,7 @@ get_address_cost (bool symbol_present, bool var_present,
addr = gen_rtx_fmt_ee (MULT, Pmode, addr, GEN_INT (rat)); addr = gen_rtx_fmt_ee (MULT, Pmode, addr, GEN_INT (rat));
if (var_present) if (var_present)
addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, addr); addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
if (symbol_present) if (symbol_present)
{ {
...@@ -2630,7 +2633,7 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -2630,7 +2633,7 @@ get_address_cost (bool symbol_present, bool var_present,
base = NULL_RTX; base = NULL_RTX;
if (base) if (base)
addr = gen_rtx_fmt_ee (PLUS, Pmode, base, addr); addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
start_sequence (); start_sequence ();
addr = memory_address (Pmode, addr); addr = memory_address (Pmode, addr);
...@@ -2672,7 +2675,7 @@ find_depends (tree *expr_p, int *ws ATTRIBUTE_UNUSED, void *data) ...@@ -2672,7 +2675,7 @@ find_depends (tree *expr_p, int *ws ATTRIBUTE_UNUSED, void *data)
return NULL_TREE; return NULL_TREE;
} }
/* Estimates cost of forcing EXPR into variable. DEPENDS_ON is a set of the /* Estimates cost of forcing EXPR into a variable. DEPENDS_ON is a set of the
invariants the computation depends on. */ invariants the computation depends on. */
static unsigned static unsigned
...@@ -2683,6 +2686,9 @@ force_var_cost (struct ivopts_data *data, ...@@ -2683,6 +2686,9 @@ force_var_cost (struct ivopts_data *data,
static unsigned integer_cost; static unsigned integer_cost;
static unsigned symbol_cost; static unsigned symbol_cost;
static unsigned address_cost; static unsigned address_cost;
tree op0, op1;
unsigned cost0, cost1, cost;
enum machine_mode mode;
if (!costs_initialized) if (!costs_initialized)
{ {
...@@ -2744,8 +2750,60 @@ force_var_cost (struct ivopts_data *data, ...@@ -2744,8 +2750,60 @@ force_var_cost (struct ivopts_data *data,
return address_cost; return address_cost;
} }
/* Just an arbitrary value, FIXME. */ switch (TREE_CODE (expr))
return target_spill_cost; {
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 /* Estimates cost of expressing address ADDR as var + symbol + offset. The
...@@ -2809,9 +2867,7 @@ ptr_difference_cost (struct ivopts_data *data, ...@@ -2809,9 +2867,7 @@ ptr_difference_cost (struct ivopts_data *data,
gcc_assert (TREE_CODE (e1) == ADDR_EXPR); gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
if (TREE_CODE (e2) == ADDR_EXPR if (ptr_difference_const (e1, e2, &diff))
&& ptr_difference_const (TREE_OPERAND (e1, 0),
TREE_OPERAND (e2, 0), &diff))
{ {
*offset += diff; *offset += diff;
*symbol_present = false; *symbol_present = false;
...@@ -2994,7 +3050,7 @@ get_computation_cost_at (struct ivopts_data *data, ...@@ -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, (symbol/var/const parts may be omitted). If we are looking for an address,
find the cost of addressing this. */ find the cost of addressing this. */
if (address_p) 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. */ /* Otherwise estimate the costs for computing the expression. */
aratio = ratio > 0 ? ratio : -ratio; aratio = ratio > 0 ? ratio : -ratio;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment