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
This commit is contained in:
Zdenek Dvorak 2004-11-10 21:49:55 +01:00 committed by Zdenek Dvorak
parent 9665466484
commit 7299dbfbf1
3 changed files with 120 additions and 22 deletions

View 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

View 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

View 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 a 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;