diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-10 20:49:55 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-10 20:49:55 +0000 |
commit | eb91f88e98bb0d3fe37ca0e3dc3b2c971c3b2ea0 (patch) | |
tree | 74c265b69ab975f9fd5932220b599547ade0412e | |
parent | 6cf06ccde6dfe5c6a525a16bacaafca12242a9ca (diff) | |
download | gcc-eb91f88e98bb0d3fe37ca0e3dc3b2c971c3b2ea0.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@90451 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/fold-const.c | 50 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 74 |
3 files changed, 120 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f17008d7a35..57c0622dbb5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a14bfb762d4..b8ccfa1d207 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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 diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 557fd219462..417c4635943 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -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; |