[PATCH][alias-improvement] Fix PR38301, TBAA issues with the vectorizer

Richard Guenther rguenther@suse.de
Wed Jan 7 11:21:00 GMT 2009


As I chickened out for trunk to fix this this makes the fix on the
alias-improvements branch where it is really easy to do so.  I took
the opportunity to split out a get_deref_alias_set from get_alias_set
to avoid building indirect-ref trees just for querying alias sets.
TODO: go over the rest of the codebase and search for opportunities
to use that.  (note that it is also a correctness issue - using
get_alias_set on the memory type is incorrect!)

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.  It doesn't fix the x86_64 vectorizer issue as I hoped.

Richard.

2009-01-07  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38301
	* alias.c (get_deref_alias_set): New function split out from ...
	(get_alias_set): ... here.
	* alias.h (get_deref_alias_set): Declare.
	* tree-vect-transform.c (vect_create_data_ref_ptr): Remove unused
	type parameter.  Remove restrict pointer handling.  Create a
	ref-all pointer in case type-based alias sets do not conflict.
	(vectorizable_store): Re-instantiate TBAA assert.
	(vectorizable_load): Likewise.

Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 143063)
--- gcc/alias.c	(working copy)
*************** component_uses_parent_alias_set (const_t
*** 482,487 ****
--- 482,560 ----
      }
  }
  
+ /* Return the alias set for the memory pointed to by T, which may be
+    either a type or an expression.  */
+ 
+ alias_set_type
+ get_deref_alias_set (tree t)
+ {
+   /* If we're not doing any alias analysis, just assume everything
+      aliases everything else.  */
+   if (!flag_strict_aliasing)
+     return 0;
+ 
+   if (! TYPE_P (t))
+     {
+       tree decl = find_base_decl (t);
+ 
+       if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
+ 	{
+ 	  /* If we haven't computed the actual alias set, do it now.  */
+ 	  if (DECL_POINTER_ALIAS_SET (decl) == -2)
+ 	    {
+ 	      tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
+ 
+ 	      /* No two restricted pointers can point at the same thing.
+ 		 However, a restricted pointer can point at the same thing
+ 		 as an unrestricted pointer, if that unrestricted pointer
+ 		 is based on the restricted pointer.  So, we make the
+ 		 alias set for the restricted pointer a subset of the
+ 		 alias set for the type pointed to by the type of the
+ 		 decl.  */
+ 	      alias_set_type pointed_to_alias_set
+ 		  = get_alias_set (pointed_to_type);
+ 
+ 	      if (pointed_to_alias_set == 0)
+ 		/* It's not legal to make a subset of alias set zero.  */
+ 		DECL_POINTER_ALIAS_SET (decl) = 0;
+ 	      else if (AGGREGATE_TYPE_P (pointed_to_type))
+ 		/* For an aggregate, we must treat the restricted
+ 		   pointer the same as an ordinary pointer.  If we
+ 		   were to make the type pointed to by the
+ 		   restricted pointer a subset of the pointed-to
+ 		   type, then we would believe that other subsets
+ 		   of the pointed-to type (such as fields of that
+ 		   type) do not conflict with the type pointed to
+ 		   by the restricted pointer.  */
+ 		DECL_POINTER_ALIAS_SET (decl)
+ 		    = pointed_to_alias_set;
+ 	      else
+ 		{
+ 		  DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+ 		  record_alias_subset (pointed_to_alias_set,
+ 				       DECL_POINTER_ALIAS_SET (decl));
+ 		}
+ 	    }
+ 
+ 	  /* We use the alias set indicated in the declaration.  */
+ 	  return DECL_POINTER_ALIAS_SET (decl);
+ 	}
+ 
+       /* Now all we care about is the type.  */
+       t = TREE_TYPE (t);
+     }
+ 
+   /* If we have an INDIRECT_REF via a void pointer, we don't
+      know anything about what that might alias.  Likewise if the
+      pointer is marked that way.  */
+   if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
+       || TYPE_REF_CAN_ALIAS_ALL (t))
+     return 0;
+ 
+   /* Fall back to the alias-set of the pointed-to type.  */
+   return get_alias_set (TREE_TYPE (t));
+ }
+ 
  /* Return the alias set for T, which may be either a type or an
     expression.  Call language-specific routine for help, if needed.  */
  
*************** get_alias_set (tree t)
*** 522,588 ****
  	  STRIP_NOPS (inner);
  	}
  
-       /* Check for accesses through restrict-qualified pointers.  */
        if (INDIRECT_REF_P (inner))
! 	{
! 	  tree decl;
! 
! 	  if (TREE_CODE (TREE_OPERAND (inner, 0)) == SSA_NAME)
! 	    decl = SSA_NAME_VAR (TREE_OPERAND (inner, 0));
!  	  else
! 	    decl = find_base_decl (TREE_OPERAND (inner, 0));
! 
! 	  if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
! 	    {
! 	      /* If we haven't computed the actual alias set, do it now.  */
! 	      if (DECL_POINTER_ALIAS_SET (decl) == -2)
! 		{
! 		  tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
! 
! 		  /* No two restricted pointers can point at the same thing.
! 		     However, a restricted pointer can point at the same thing
! 		     as an unrestricted pointer, if that unrestricted pointer
! 		     is based on the restricted pointer.  So, we make the
! 		     alias set for the restricted pointer a subset of the
! 		     alias set for the type pointed to by the type of the
! 		     decl.  */
! 		  alias_set_type pointed_to_alias_set
! 		    = get_alias_set (pointed_to_type);
! 
! 		  if (pointed_to_alias_set == 0)
! 		    /* It's not legal to make a subset of alias set zero.  */
! 		    DECL_POINTER_ALIAS_SET (decl) = 0;
! 		  else if (AGGREGATE_TYPE_P (pointed_to_type))
! 		    /* For an aggregate, we must treat the restricted
! 		       pointer the same as an ordinary pointer.  If we
! 		       were to make the type pointed to by the
! 		       restricted pointer a subset of the pointed-to
! 		       type, then we would believe that other subsets
! 		       of the pointed-to type (such as fields of that
! 		       type) do not conflict with the type pointed to
! 		       by the restricted pointer.  */
! 		    DECL_POINTER_ALIAS_SET (decl)
! 		      = pointed_to_alias_set;
! 		  else
! 		    {
! 		      DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
! 		      record_alias_subset (pointed_to_alias_set,
! 					   DECL_POINTER_ALIAS_SET (decl));
! 		    }
! 		}
! 
! 	      /* We use the alias set indicated in the declaration.  */
! 	      return DECL_POINTER_ALIAS_SET (decl);
! 	    }
! 
! 	  /* If we have an INDIRECT_REF via a void pointer, we don't
! 	     know anything about what that might alias.  Likewise if the
! 	     pointer is marked that way.  */
! 	  else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE
! 		   || (TYPE_REF_CAN_ALIAS_ALL
! 		       (TREE_TYPE (TREE_OPERAND (inner, 0)))))
! 	    return 0;
! 	}
  
        /* Otherwise, pick up the outermost object that we could have a pointer
  	 to, processing conversions as above.  */
--- 595,602 ----
  	  STRIP_NOPS (inner);
  	}
  
        if (INDIRECT_REF_P (inner))
! 	return get_deref_alias_set (TREE_OPERAND (inner, 0));
  
        /* Otherwise, pick up the outermost object that we could have a pointer
  	 to, processing conversions as above.  */
Index: gcc/alias.h
===================================================================
*** gcc/alias.h	(revision 143063)
--- gcc/alias.h	(working copy)
*************** typedef int alias_set_type;
*** 32,37 ****
--- 32,38 ----
  
  extern alias_set_type new_alias_set (void);
  extern alias_set_type get_alias_set (tree);
+ extern alias_set_type get_deref_alias_set (tree);
  extern alias_set_type get_varargs_alias_set (void);
  extern alias_set_type get_frame_alias_set (void);
  extern bool component_uses_parent_alias_set (const_tree);
Index: gcc/tree-vect-transform.c
===================================================================
*** gcc/tree-vect-transform.c	(revision 143063)
--- gcc/tree-vect-transform.c	(working copy)
*************** static bool vect_transform_stmt (gimple,
*** 50,56 ****
  				 slp_tree, slp_instance);
  static tree vect_create_destination_var (tree, tree);
  static tree vect_create_data_ref_ptr 
!   (gimple, struct loop*, tree, tree *, gimple *, bool, bool *, tree);
  static tree vect_create_addr_base_for_vector_ref 
    (gimple, gimple_seq *, tree, struct loop *);
  static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
--- 50,56 ----
  				 slp_tree, slp_instance);
  static tree vect_create_destination_var (tree, tree);
  static tree vect_create_data_ref_ptr 
!   (gimple, struct loop*, tree, tree *, gimple *, bool, bool *);
  static tree vect_create_addr_base_for_vector_ref 
    (gimple, gimple_seq *, tree, struct loop *);
  static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
*************** vect_create_addr_base_for_vector_ref (gi
*** 1013,1019 ****
  static tree
  vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
  			  tree offset, tree *initial_address, gimple *ptr_incr,
! 			  bool only_init, bool *inv_p, tree type)
  {
    tree base_name;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
--- 1013,1019 ----
  static tree
  vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
  			  tree offset, tree *initial_address, gimple *ptr_incr,
! 			  bool only_init, bool *inv_p)
  {
    tree base_name;
    stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1071,1092 ****
      }
  
    /** (1) Create the new vector-pointer variable:  **/
!   if (type)
!     vect_ptr_type = build_pointer_type (type);
!   else
!     vect_ptr_type = build_pointer_type (vectype);
! 
!   if (TREE_CODE (DR_BASE_ADDRESS (dr)) == SSA_NAME
!       && TYPE_RESTRICT (TREE_TYPE (DR_BASE_ADDRESS (dr))))
!     vect_ptr_type = build_qualified_type (vect_ptr_type, TYPE_QUAL_RESTRICT);
    vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
                                      get_name (base_name));
!   if (TREE_CODE (DR_BASE_ADDRESS (dr)) == SSA_NAME
!       && TYPE_RESTRICT (TREE_TYPE (DR_BASE_ADDRESS (dr))))
      {
!       get_alias_set (base_name);
!       DECL_POINTER_ALIAS_SET (vect_ptr)
! 	= DECL_POINTER_ALIAS_SET (SSA_NAME_VAR (DR_BASE_ADDRESS (dr)));
      }
  
    add_referenced_var (vect_ptr);
--- 1071,1099 ----
      }
  
    /** (1) Create the new vector-pointer variable:  **/
!   vect_ptr_type = build_pointer_type (vectype);
    vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
                                      get_name (base_name));
! 
!   /* If any of the data-references in the stmt group does not conflict
!      with the created vector data-reference use a ref-all pointer instead.  */
!   if (STMT_VINFO_DR_GROUP_SIZE (stmt_info) > 1)
      {
!       gimple orig_stmt = STMT_VINFO_DR_GROUP_FIRST_DR (stmt_info);
!       do
! 	{
! 	  if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
! 				      get_alias_set (gimple_assign_lhs (orig_stmt))))
! 	    {
! 	      vect_ptr_type = build_pointer_type_for_mode (vectype,
! 							   ptr_mode, true);
! 	      vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
! 						get_name (base_name));
! 	      break;
! 	    }
! 	  orig_stmt = STMT_VINFO_DR_GROUP_NEXT_DR (vinfo_for_stmt (orig_stmt));
! 	}
!       while (orig_stmt);
      }
  
    add_referenced_var (vect_ptr);
*************** vectorizable_store (gimple stmt, gimple_
*** 5377,5383 ****
  						 TREE_TYPE (vec_oprnd)));
  	  dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE, 
  						  &dummy, &ptr_incr, false, 
! 						  &inv_p, NULL);
  	  gcc_assert (!inv_p);
  	}
        else 
--- 5379,5385 ----
  						 TREE_TYPE (vec_oprnd)));
  	  dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE, 
  						  &dummy, &ptr_incr, false, 
! 						  &inv_p);
  	  gcc_assert (!inv_p);
  	}
        else 
*************** vectorizable_store (gimple stmt, gimple_
*** 5426,5431 ****
--- 5428,5437 ----
  	    vec_oprnd = VEC_index (tree, result_chain, i);
  
  	  data_ref = build_fold_indirect_ref (dataref_ptr);
+ 	  /* If accesses through a pointer to vectype do not alias the original
+ 	     memory reference we have a problem.  This should never happen.  */
+ 	  gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
+ 					     get_alias_set (gimple_assign_lhs (stmt))));
  
  	  /* Arguments are ready. Create the new vector stmt.  */
  	  new_stmt = gimple_build_assign (data_ref, vec_oprnd);
*************** vect_setup_realignment (gimple stmt, gim
*** 5616,5622 ****
        pe = loop_preheader_edge (loop_for_initial_load);
        vec_dest = vect_create_destination_var (scalar_dest, vectype);
        ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
! 		                  &init_addr, &inc, true, &inv_p, NULL_TREE);
        data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
        new_stmt = gimple_build_assign (vec_dest, data_ref);
        new_temp = make_ssa_name (vec_dest, new_stmt);
--- 5622,5628 ----
        pe = loop_preheader_edge (loop_for_initial_load);
        vec_dest = vect_create_destination_var (scalar_dest, vectype);
        ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
! 				      &init_addr, &inc, true, &inv_p);
        data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
        new_stmt = gimple_build_assign (vec_dest, data_ref);
        new_temp = make_ssa_name (vec_dest, new_stmt);
*************** vectorizable_load (gimple stmt, gimple_s
*** 6588,6594 ****
          dataref_ptr = vect_create_data_ref_ptr (first_stmt,
  					        at_loop, offset, 
  						&dummy, &ptr_incr, false, 
! 						&inv_p, NULL_TREE);
        else
          dataref_ptr = 
  		bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt, NULL_TREE);
--- 6594,6600 ----
          dataref_ptr = vect_create_data_ref_ptr (first_stmt,
  					        at_loop, offset, 
  						&dummy, &ptr_incr, false, 
! 						&inv_p);
        else
          dataref_ptr = 
  		bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt, NULL_TREE);
*************** vectorizable_load (gimple stmt, gimple_s
*** 6649,6654 ****
--- 6655,6664 ----
  	    default:
  	      gcc_unreachable ();
  	    }
+ 	  /* If accesses through a pointer to vectype do not alias the original
+ 	     memory reference we have a problem.  This should never happen.  */
+ 	  gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
+ 					     get_alias_set (gimple_assign_rhs1 (stmt))));
  	  vec_dest = vect_create_destination_var (scalar_dest, vectype);
  	  new_stmt = gimple_build_assign (vec_dest, data_ref);
  	  new_temp = make_ssa_name (vec_dest, new_stmt);



More information about the Gcc-patches mailing list