This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Improve cost computation in ivopts
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 9 Nov 2004 12:39:15 +0100
- Subject: [patch] Improve cost computation in ivopts
Hello,
currently ivopts do not recognize that it is possible to base (*ptr).field
access on induction variable with value equal to ptr. There are two
reasons:
1) determine_base_object returns &*ptr for the former and ptr for the
later, thus making the rest of the optimization think that the
addresses access different objects.
2) ptr_difference_const does not recognize this case, so the cost for
this is too high even with 1) fixed.
This patch fixes these shortcomings (thus fixing significant regression
in one of the skidmarks benchmarks reported by David Edelsohn).
Bootstrapped & regtested on i686 and x86_64.
* fold-const.c (fold): Attempt to use ptr_difference_const whenever
one of the arguments of MINUS_EXPR is an address.
(get_core): 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.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.471
diff -c -3 -p -r1.471 fold-const.c
*** fold-const.c 6 Nov 2004 19:16:59 -0000 1.471
--- fold-const.c 8 Nov 2004 23:39:53 -0000
*************** fold (tree expr)
*** 7074,7084 ****
{
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))
return build_int_cst_type (type, diff);
}
--- 7074,7082 ----
{
HOST_WIDE_INT 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);
}
*************** round_down (tree value, int divisor)
*** 10815,10837 ****
return value;
}
/* Returns true if addresses of E1 and E2 differ by a constant, false
! 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);
if (bitpos1 % BITS_PER_UNIT != 0
|| bitpos2 % BITS_PER_UNIT != 0
--- 10813,10860 ----
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
+ get_core (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. */
bool
ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
{
tree core1, core2;
HOST_WIDE_INT bitpos1, bitpos2;
tree toffset1, toffset2, tdiff, type;
! core1 = get_core (e1, &bitpos1, &toffset1);
! core2 = get_core (e2, &bitpos2, &toffset2);
if (bitpos1 % BITS_PER_UNIT != 0
|| bitpos2 % BITS_PER_UNIT != 0
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.26
diff -c -3 -p -r2.26 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 8 Nov 2004 21:49:08 -0000 2.26
--- tree-ssa-loop-ivopts.c 8 Nov 2004 23:39:53 -0000
*************** determine_base_object (tree expr)
*** 678,683 ****
--- 678,686 ----
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:
*************** ptr_difference_cost (struct ivopts_data
*** 2809,2817 ****
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))
{
*offset += diff;
*symbol_present = false;
--- 2867,2873 ----
gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
! if (ptr_difference_const (e1, e2, &diff))
{
*offset += diff;
*symbol_present = false;