This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]