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] Fix PR42956


With PR42956 IVOPTs uses fold_indirect_ref which constructs
an array-ref from an indirect-ref.  The problem is that the
array referenced by the array-ref has variable element size
and introducing such after gimplification is a no-no.

Thus, fixed by using gimple_fold_indirect_ref, fixing that
in this regard after fixing it to reproduce the problem.
I also completed gimple_fold_indirect_ref according to
fold_indirect_ref so we do not regress by chance from
using it from IVOPTs.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk,
queued for 4.4.

Richard.

2010-02-07  Richard Guenther  <rguenther@suse.de>

	PR middle-end/42956
	* gimplify.c (gimple_fold_indirect_ref): Avoid generating
	new ARRAY_REFs on variable size element or minimal index arrays.
	Complete.
	* tree-ssa-loop-ivopts.c (find_interesting_uses_address): Use
	gimple_fold_indirect_ref.

	* gcc.c-torture/compile/pr42956.c: New testcase.

Index: gcc/testsuite/gcc.c-torture/compile/pr42956.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr42956.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr42956.c	(revision 0)
***************
*** 0 ****
--- 1,33 ----
+ typedef const int cint;
+ typedef struct {
+ } Bounds;
+ int ndim_, ncomp_, selectedcomp_, nregions_;
+ void *voidregion_;
+ typedef struct {
+     double diff, err, spread;
+ } Errors;
+ typedef const Errors cErrors;
+ void Split(int iregion, int depth, int xregion)
+ {
+   typedef struct {
+       double avg, err, spread, chisq;
+       double xmin[ndim_], xmax[ndim_];
+   } Result;
+   typedef struct region {
+       Result result[ncomp_];
+   } Region;
+   Errors errors[ncomp_];
+   int comp, ireg, xreg;
+   for( ireg = iregion, xreg = xregion; ireg < nregions_; ireg = xreg++ )
+     {
+       Result *result = ((Region *)voidregion_)[ireg].result;
+       for( comp = 0; comp < ncomp_; ++comp )
+ 	{
+ 	  Result *r = &result[comp];
+ 	  cErrors *e = &errors[comp];
+ 	  double c = e->diff;
+ 	  if( r->err > 0 ) r->err = r->err*e->err + c;
+ 	}
+     }
+ }
+ 
Index: gcc/gimplify.c
===================================================================
*** gcc/gimplify.c	(revision 156539)
--- gcc/gimplify.c	(working copy)
*************** gimple_fold_indirect_ref (tree t)
*** 3935,3941 ****
    tree sub = t;
    tree subtype;
  
!   STRIP_USELESS_TYPE_CONVERSION (sub);
    subtype = TREE_TYPE (sub);
    if (!POINTER_TYPE_P (subtype))
      return NULL_TREE;
--- 3935,3941 ----
    tree sub = t;
    tree subtype;
  
!   STRIP_NOPS (sub);
    subtype = TREE_TYPE (sub);
    if (!POINTER_TYPE_P (subtype))
      return NULL_TREE;
*************** gimple_fold_indirect_ref (tree t)
*** 3950,3967 ****
  
        /* *(foo *)&fooarray => fooarray[0] */
        if (TREE_CODE (optype) == ARRAY_TYPE
  	  && useless_type_conversion_p (type, TREE_TYPE (optype)))
         {
           tree type_domain = TYPE_DOMAIN (optype);
           tree min_val = size_zero_node;
           if (type_domain && TYPE_MIN_VALUE (type_domain))
             min_val = TYPE_MIN_VALUE (type_domain);
!          return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
         }
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
    if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
        && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
      {
        tree type_domain;
--- 3950,4029 ----
  
        /* *(foo *)&fooarray => fooarray[0] */
        if (TREE_CODE (optype) == ARRAY_TYPE
+ 	  && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
  	  && useless_type_conversion_p (type, TREE_TYPE (optype)))
         {
           tree type_domain = TYPE_DOMAIN (optype);
           tree min_val = size_zero_node;
           if (type_domain && TYPE_MIN_VALUE (type_domain))
             min_val = TYPE_MIN_VALUE (type_domain);
! 	 if (TREE_CODE (min_val) == INTEGER_CST)
! 	   return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
         }
+       /* *(foo *)&complexfoo => __real__ complexfoo */
+       else if (TREE_CODE (optype) == COMPLEX_TYPE
+                && useless_type_conversion_p (type, TREE_TYPE (optype)))
+         return fold_build1 (REALPART_EXPR, type, op);
+       /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
+       else if (TREE_CODE (optype) == VECTOR_TYPE
+                && useless_type_conversion_p (type, TREE_TYPE (optype)))
+         {
+           tree part_width = TYPE_SIZE (type);
+           tree index = bitsize_int (0);
+           return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
+         }
+     }
+ 
+   /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+     {
+       tree op00 = TREE_OPERAND (sub, 0);
+       tree op01 = TREE_OPERAND (sub, 1);
+       tree op00type;
+ 
+       STRIP_NOPS (op00);
+       op00type = TREE_TYPE (op00);
+       if (TREE_CODE (op00) == ADDR_EXPR
+ 	  && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
+ 	  && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+ 	{
+ 	  HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+ 	  tree part_width = TYPE_SIZE (type);
+ 	  unsigned HOST_WIDE_INT part_widthi
+ 	    = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
+ 	  unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ 	  tree index = bitsize_int (indexi);
+ 	  if (offset / part_widthi
+ 	      <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
+ 	    return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
+ 				part_width, index);
+ 	}
+     }
+ 
+   /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+     {
+       tree op00 = TREE_OPERAND (sub, 0);
+       tree op01 = TREE_OPERAND (sub, 1);
+       tree op00type;
+ 
+       STRIP_NOPS (op00);
+       op00type = TREE_TYPE (op00);
+       if (TREE_CODE (op00) == ADDR_EXPR
+ 	  && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
+ 	  && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type))))
+ 	{
+ 	  tree size = TYPE_SIZE_UNIT (type);
+ 	  if (tree_int_cst_equal (size, op01))
+ 	    return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+ 	}
      }
  
    /* *(foo *)fooarrptr => (*fooarrptr)[0] */
    if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+       && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
        && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
      {
        tree type_domain;
*************** gimple_fold_indirect_ref (tree t)
*** 3973,3979 ****
        type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
        if (type_domain && TYPE_MIN_VALUE (type_domain))
          min_val = TYPE_MIN_VALUE (type_domain);
!       return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
      }
  
    return NULL_TREE;
--- 4035,4042 ----
        type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
        if (type_domain && TYPE_MIN_VALUE (type_domain))
          min_val = TYPE_MIN_VALUE (type_domain);
!       if (TREE_CODE (min_val) == INTEGER_CST)
! 	return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
      }
  
    return NULL_TREE;
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
*** gcc/tree-ssa-loop-ivopts.c	(revision 156539)
--- gcc/tree-ssa-loop-ivopts.c	(working copy)
*************** find_interesting_uses_address (struct iv
*** 1686,1692 ****
  	  while (handled_component_p (*ref))
  	    ref = &TREE_OPERAND (*ref, 0);
  	  if (TREE_CODE (*ref) == INDIRECT_REF)
! 	    *ref = fold_indirect_ref (*ref);
  	}
      }
  
--- 1686,1696 ----
  	  while (handled_component_p (*ref))
  	    ref = &TREE_OPERAND (*ref, 0);
  	  if (TREE_CODE (*ref) == INDIRECT_REF)
! 	    {
! 	      tree tem = gimple_fold_indirect_ref (TREE_OPERAND (*ref, 0));
! 	      if (tem)
! 		*ref = tem;
! 	    }
  	}
      }
  


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