[PATCH][alias-improvements] Fix vectorization failures

Richard Guenther rguenther@suse.de
Sat Jan 3 21:38:00 GMT 2009


This fixes the vectorization testsuite failures by

1) properly implementing may_be_aliased - TREE_ADDRESSABLE is a too
   conservative answer for aggregates

2) be less conservative at creating PTA constraints for pointer offsets
   in case we deal with unknown offsets but variables which have not
   been decomposed

3) allow heap variables (-fargument-noalias-* and malloc attribute) to be
   disambiguated with specific global decls (but not pointers pointing
   to random global memory)

unrelated but uncovered this also fixes constraint generation for
asm statements.  It also fixes an oversight in handling indirect
references from ref_may_used_by_call_p.

Bootstrapped and tested on x86_64-unknown-linux-gnu.  This exposes a
latent vectorizer problem and causes

FAIL: gfortran.fortran-torture/execute/elemental.f90 execution,  -O3 -g 

on x86_64.  It also adds another libstdc++ FAIL,

FAIL: 23_containers/deque/cons/2.cc execution test

It in turn fixes

-FAIL: gcc.dg/tree-ssa/alias-1.c scan-tree-dump-times optimized 
"link_error" 0
-FAIL: gcc.dg/tree-ssa/ldist-12.c scan-tree-dump-times ldist "distributed: 
split
 to 2 loops" 1
-FAIL: gcc.dg/vect/vect-42.c scan-tree-dump-times vect "Vectorizing an 
unaligned
 access" 2
-FAIL: gcc.dg/vect/vect-42.c scan-tree-dump-times vect "Alignment of 
access forc
ed using peeling" 1
-FAIL: gcc.dg/vect/vect-96.c scan-tree-dump-times vect "Vectorizing an 
unaligned
 access" 1
-FAIL: gcc.dg/vect/vect-96.c scan-tree-dump-times vect "Alignment of 
access forc
ed using peeling" 1
-FAIL: gcc.dg/vect/vect-multitypes-6.c scan-tree-dump-times vect 
"vectorized 1 l
oops" 1
-FAIL: gcc.dg/vect/vect-multitypes-6.c scan-tree-dump-times vect 
"Vectorizing an
 unaligned access" 6
-FAIL: gcc.dg/vect/no-vfa-vect-43.c scan-tree-dump-times vect "vectorized 
1 loop
s" 1
-FAIL: gcc.dg/vect/no-scevccp-outer-6.c scan-tree-dump-times vect "OUTER 
LOOP VE
CTORIZED." 1

-FAIL: gfortran.dg/ldist-1.f90  -O  scan-tree-dump-times ldist 
"distributed: spl
it to 4 loops" 1
-FAIL: gfortran.dg/reassoc_4.f  -O  scan-tree-dump-times reassoc1 "[0-9] 
\\* " 2
2
-FAIL: gfortran.dg/vect/vect-2.f90  -O  scan-tree-dump-times vect 
"Alignment of 
access forced using peeling" 3
-FAIL: gfortran.dg/vect/vect-3.f90  -O  scan-tree-dump-times vect 
"Alignment of 
access forced using peeling" 1
-FAIL: gfortran.dg/vect/vect-3.f90  -O  scan-tree-dump-times vect 
"Vectorizing a
n unaligned access" 1
-FAIL: gfortran.dg/vect/vect-4.f90  -O  scan-tree-dump-times vect 
"Alignment of 
access forced using peeling" 1
-FAIL: gfortran.dg/vect/vect-4.f90  -O  scan-tree-dump-times vect 
"Vectorizing a
n unaligned access" 1
-FAIL: gfortran.dg/vect/no-vfa-pr32377.f90 scan-tree-dump-times vect 
"vectorized
 2 loops" 1

Installed to the branch.

Richard.

2008-01-03  Richard Guenther  <rguenther@suse.de>

	* tree-flow-inline.h (may_be_aliased): Query the addressable
	vars bitmap in addition to checking TREE_ADDRESSABLE.
	* tree-ssa-structalias.c (get_constraint_for_ptr_offset):
	For field-sensitive analysis also handle variable offsets
	on addresses of variables that did not get decomposed.
	(find_func_aliases): Fix constraint generation for asm statements.
	(find_what_var_points_to): Do not set pt_nonlocal for heap
	variables.
	* tree-dfa.c (refs_may_alias_p): Disambiguate two indirect
	references with PTA information.
	* tree-ssa-alias.c (may_point_to_same_object): Declare.
	* tree-ssa-alias.c (may_point_to_same_object): New function.
	(ref_may_used_by_call_p): Fix handling of indirect references.

Index: gcc/tree-flow-inline.h
===================================================================
*** gcc/tree-flow-inline.h.orig	2009-01-03 17:01:18.000000000 +0100
--- gcc/tree-flow-inline.h	2009-01-03 17:02:52.000000000 +0100
*************** is_global_var (const_tree t)
*** 590,596 ****
  static inline bool
  may_be_aliased (tree var)
  {
!   return TREE_ADDRESSABLE (var) || is_global_var (var);
  }
  
  
--- 590,603 ----
  static inline bool
  may_be_aliased (tree var)
  {
!   return (is_global_var (var)
! 	  || (TREE_ADDRESSABLE (var)
! 	      /* TREE_ADDRESSABLE is a pre-requesite for sth to have its
! 	         address taken, but for aggregates only the addressable
! 		 vars bitmap is a precise answer.  */
! 	      && (!gimple_addressable_vars (cfun)
! 		  || bitmap_bit_p (gimple_addressable_vars (cfun),
! 				   DECL_UID (var)))));
  }
  
  
Index: gcc/tree-ssa-structalias.c
===================================================================
*** gcc/tree-ssa-structalias.c.orig	2009-01-03 17:01:18.000000000 +0100
--- gcc/tree-ssa-structalias.c	2009-01-03 19:36:21.000000000 +0100
*************** get_constraint_for_ptr_offset (tree ptr,
*** 2765,2774 ****
    struct constraint_expr *c;
    unsigned int j, n;
    unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
  
    /* If we do not do field-sensitive PTA adding offsets to pointers
       does not change the points-to solution.  */
!   if (!use_field_sensitive)
      {
        get_constraint_for (ptr, results);
        return;
--- 2765,2785 ----
    struct constraint_expr *c;
    unsigned int j, n;
    unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
+   varinfo_t vi;
+   tree var;
  
    /* If we do not do field-sensitive PTA adding offsets to pointers
       does not change the points-to solution.  */
!   if (!use_field_sensitive
!       /* The same is true if we are offsetting a variable that has not
!          been decomposed.
! 	 ???  This can be done more generally as well, with support in
! 	      the solver.  */
!       || (TREE_CODE (ptr) == ADDR_EXPR
! 	  && (var = get_base_address (TREE_OPERAND (ptr, 0)))
! 	  && DECL_P (var)
! 	  && (vi = get_vi_for_tree (var))
! 	  && vi->is_full_var))
      {
        get_constraint_for (ptr, results);
        return;
*************** find_func_aliases (gimple origt)
*** 3881,3900 ****
      }
    else if (stmt_escape_type == ESCAPE_TO_ASM)
      {
!       unsigned i;
!       for (i = 0; i < gimple_asm_noutputs (t); ++i)
! 	{
! 	  tree op = TREE_VALUE (gimple_asm_output_op (t, i));
  	  if (op && could_have_pointers (op))
! 	    /* Strictly we'd only need the constraints from ESCAPED and
! 	       NONLOCAL.  */
! 	    make_escape_constraint (op);
  	}
        for (i = 0; i < gimple_asm_ninputs (t); ++i)
  	{
! 	  tree op = TREE_VALUE (gimple_asm_input_op (t, i));
! 	  if (op && could_have_pointers (op))
! 	    /* Strictly we'd only need the constraint to ESCAPED.  */
  	    make_escape_constraint (op);
  	}
      }
--- 3892,3941 ----
      }
    else if (stmt_escape_type == ESCAPE_TO_ASM)
      {
!       unsigned i, noutputs;
!       const char **oconstraints;
!       const char *constraint;
!       bool allows_mem, allows_reg, is_inout;
! 
!       noutputs = gimple_asm_noutputs (t);
!       oconstraints = XALLOCAVEC (const char *, noutputs);
! 
!       for (i = 0; i < noutputs; ++i)
! 	{
! 	  tree link = gimple_asm_output_op (t, i);
! 	  tree op = TREE_VALUE (link);
! 
! 	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
! 	  oconstraints[i] = constraint;
! 	  parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
! 				   &allows_reg, &is_inout);
! 
! 	  /* A memory constraint makes the address of the operand escape.  */
! 	  if (!allows_reg && allows_mem)
! 	    make_escape_constraint (build_fold_addr_expr (op));
! 
  	  if (op && could_have_pointers (op))
! 	    /* The asm may read global memory, so outputs may point to
! 	       any escaped memory.  */
! 	    handle_lhs_call (op, 0);
  	}
        for (i = 0; i < gimple_asm_ninputs (t); ++i)
  	{
! 	  tree link = gimple_asm_input_op (t, i);
! 	  tree op = TREE_VALUE (link);
! 
! 	  constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
! 
! 	  parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints,
! 				  &allows_mem, &allows_reg);
! 
! 	  /* A memory constraint makes the address of the operand escape.  */
! 	  if (!allows_reg && allows_mem)
! 	    make_escape_constraint (build_fold_addr_expr (op));
! 	  /* Strictly we'd only need the constraint to ESCAPED if
! 	     the asm clobbers memory, otherwise using CALLUSED
! 	     would be enough.  */
! 	  else if (op && could_have_pointers (op))
  	    make_escape_constraint (op);
  	}
      }
*************** find_what_var_points_to (varinfo_t vi, s
*** 4864,4872 ****
  	         it somewhere.  */
  	      pt->anything = 1;
  	    }
! 	  else if (vi->id == nonlocal_id
! 		   || vi->is_heap_var)
  	    pt->nonlocal = 1;
  	  else if (vi->id == anything_id
  		   || vi->id == callused_id
  		   || vi->id == readonly_id
--- 4905,4915 ----
  	         it somewhere.  */
  	      pt->anything = 1;
  	    }
! 	  else if (vi->id == nonlocal_id)
  	    pt->nonlocal = 1;
+ 	  else if (vi->is_heap_var)
+ 	    /* We represent heapvars in the points-to set properly.  */
+ 	    ;
  	  else if (vi->id == anything_id
  		   || vi->id == callused_id
  		   || vi->id == readonly_id
Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c.orig	2009-01-03 17:01:18.000000000 +0100
--- gcc/tree-dfa.c	2009-01-03 17:02:52.000000000 +0100
*************** refs_may_alias_p (tree ref1, tree ref2)
*** 1003,1008 ****
--- 1003,1019 ----
  	return false;
      }
  
+   /* If both bases are based on pointers they cannot alias if they may not
+      point to the same memory object.  */
+   else if (INDIRECT_REF_P (base1)
+ 	   && INDIRECT_REF_P (base2))
+     {
+       if (!may_point_to_same_object (TREE_OPERAND (base1, 0),
+ 				     TREE_OPERAND (base2, 0)))
+ 	return false;
+     }
+ 
+ 
    /* If one base is a ref-all pointer or a TARGET_MEM_REF weird things
       are allowed.  */
    strict_aliasing_applies = (flag_strict_aliasing
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c.orig	2009-01-03 17:01:18.000000000 +0100
--- gcc/tree-ssa-alias.c	2009-01-03 19:51:51.000000000 +0100
*************** may_point_to_decl (tree ptr, tree decl)
*** 134,139 ****
--- 134,180 ----
    return false;
  }
  
+ /* Return true if PTR1 and PTR2 may point to the same memory object.  */
+ 
+ bool
+ may_point_to_same_object (tree ptr1, tree ptr2)
+ {
+   struct ptr_info_def *pi1, *pi2;
+ 
+   /* ???  During SCCVN/PRE we can end up with *&x during valueizing
+      operands.  Likewise we can end up with dereferencing constant
+      pointers.  Just bail out in these cases for now.  */
+   if (TREE_CODE (ptr1) == ADDR_EXPR
+       || TREE_CODE (ptr1) == INTEGER_CST
+       || TREE_CODE (ptr2) == ADDR_EXPR
+       || TREE_CODE (ptr2) == INTEGER_CST)
+     return true;
+ 
+   gcc_assert (TREE_CODE (ptr1) == SSA_NAME
+ 	      && TREE_CODE (ptr2) == SSA_NAME);
+ 
+   /* If we do not have useful points-to information for either pointer
+      we cannot disambiguate anything else.  */
+   pi1 = SSA_NAME_PTR_INFO (ptr1);
+   pi2 = SSA_NAME_PTR_INFO (ptr2);
+   if (!pi1 || !pi2
+       || pi1->pt.anything || pi2->pt.anything)
+     return true;
+ 
+   /* If either points to unknown global memory and the other points to
+      any global memory they alias.  */
+   if ((pi1->pt.nonlocal
+        && (pi2->pt.nonlocal
+ 	   || pi2->pt.vars_contains_global))
+       || (pi2->pt.nonlocal
+ 	  && pi1->pt.vars_contains_global))
+     return true;
+ 
+   /* Now both pointers alias if their points-to solution intersects.  */
+   return (pi1->pt.vars
+ 	  && pi2->pt.vars
+ 	  && bitmap_intersect_p (pi1->pt.vars, pi2->pt.vars));
+ }
  
  /* Return true if STMT is an "escape" site from the current function.  Escape
     sites those statements which might expose the address of a variable
*************** ref_may_used_by_call_p (gimple call ATTR
*** 340,349 ****
    tree base = get_base_address (ref);
    unsigned i;
  
    /* If the base variable is call-used then it may be used.  */
!   if (base
!       && DECL_P (base)
!       && is_call_used (base))
      return true;
  
    /* Inspect call arguments for passed-by-value aliases.  */
--- 381,395 ----
    tree base = get_base_address (ref);
    unsigned i;
  
+   /* If the reference is not based on a decl give up.
+      ???  Handle indirect references by intersecting the call-used
+      	  solution with that of the pointer.  */
+   if (!base
+       || !DECL_P (base))
+     return true;
+ 
    /* If the base variable is call-used then it may be used.  */
!   if (is_call_used (base))
      return true;
  
    /* Inspect call arguments for passed-by-value aliases.  */
Index: gcc/tree-ssa-alias.h
===================================================================
*** gcc/tree-ssa-alias.h.orig	2009-01-03 17:01:18.000000000 +0100
--- gcc/tree-ssa-alias.h	2009-01-03 17:02:52.000000000 +0100
*************** enum escape_type 
*** 47,52 ****
--- 47,53 ----
  extern enum escape_type is_escape_site (gimple);
  extern bool may_point_to_global_var (tree);
  extern bool may_point_to_decl (tree, tree);
+ extern bool may_point_to_same_object (tree, tree);
  extern bool ref_may_used_by_stmt_p (gimple, tree);
  extern bool stmt_may_clobber_ref_p (gimple, tree);
  extern void *walk_non_aliased_vuses (tree, tree,



More information about the Gcc-patches mailing list