summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-10 20:49:55 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2004-11-10 20:49:55 +0000
commiteb91f88e98bb0d3fe37ca0e3dc3b2c971c3b2ea0 (patch)
tree74c265b69ab975f9fd5932220b599547ade0412e /gcc/fold-const.c
parent6cf06ccde6dfe5c6a525a16bacaafca12242a9ca (diff)
downloadgcc-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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c50
1 files changed, 37 insertions, 13 deletions
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