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][RFC] Fix PR37955 / PR37742


This "fixes" the ICEs for various vectorization related aliasing issues.
I moved the ref-all pointer creation to vect_create_data_ref instead of
fixing up the pointers after the fact.  This patch also inherits the
fixes Jakub proposed for the restrict related failures.  Note that this
still doesn't fix the restrict stuff because IMHO restrict is simply
broken - so I have disabled the assert causing the ICEs.

Re-computing aliases after vectorization is required because of the
new ref-all pointers.  This also has the odd side-effect of SSA
verification failures which I tried to work around.  Ugh.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

I'd like to have opinions on what to do about the restrict stuff.  If
we disable the assert we can as well do without all the restrict related
fixes and even back out the earlier restrict related fix.

Thanks,
Richard.

2008-11-07  Richard Guenther  <rguenther@suse.de>
	Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/37955
	PR middle-end/37742
	* alias.h (find_base_decl): Declare.
	* alias.c (find_base_decl): Handle SSA_NAME.  Export.
	(get_alias_set): Call find_base_decl even for SSA_NAME.
	* tree-vectorizer.c (vectorize_loops): Run TODO_rebuild_alias.
	* tree-vect-transform.c (vect_create_data_ref_ptr): Use
	find_base_decl to find a restrict-qualified pointer base.
	Use a ref-all pointer if the vectorized stmt doesn't conflict
	with the original one.  Do not manually update alias information.
	(bump_vector_ptr): Do not merge alias info.
	(vectorizable_store): Adjust alias checks.
	(vectorizable_load): Likewise.
	* tree-ssa.c (verify_use): If aliases are not computed ignore
	virtual SSA names.

	* gcc.c-torture/compile/pr37955.c: New testcase.
	* gcc.c-torture/compile/pr37742-2.c: Likewise.


Index: gcc/tree-vectorizer.c
===================================================================
*** gcc/tree-vectorizer.c.orig	2008-11-20 17:25:37.000000000 +0100
--- gcc/tree-vectorizer.c	2008-11-20 17:26:05.000000000 +0100
*************** vectorize_loops (void)
*** 2847,2853 ****
  
    free_stmt_vec_info_vec ();
  
!   return num_vectorized_loops > 0 ? TODO_cleanup_cfg : 0;
  }
  
  /* Increase alignment of global arrays to improve vectorization potential.
--- 2847,2853 ----
  
    free_stmt_vec_info_vec ();
  
!   return num_vectorized_loops > 0 ? TODO_cleanup_cfg | TODO_rebuild_alias : 0;
  }
  
  /* Increase alignment of global arrays to improve vectorization potential.
Index: gcc/tree-vect-transform.c
===================================================================
*** gcc/tree-vect-transform.c.orig	2008-11-20 17:25:37.000000000 +0100
--- gcc/tree-vect-transform.c	2008-11-21 14:49:50.000000000 +0100
*************** 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
*** 1024,1030 ****
    tree vectype = STMT_VINFO_VECTYPE (stmt_info);
    tree vect_ptr_type;
    tree vect_ptr;
-   tree tag;
    tree new_temp;
    gimple vec_stmt;
    gimple_seq new_stmt_list = NULL;
--- 1024,1029 ----
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1038,1043 ****
--- 1037,1043 ----
    tree indx_before_incr, indx_after_incr;
    gimple incr;
    tree step;
+   tree base_decl;
  
    /* Check the step (evolution) of the load in LOOP, and record
       whether it's invariant.  */
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1072,1109 ****
      }
  
    /** (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);
! 
!   /** (2) Add aliasing information to the new vector-pointer:
!           (The points-to info (DR_PTR_INFO) may be defined later.)  **/
!   
!   tag = DR_SYMBOL_TAG (dr);
!   gcc_assert (tag);
  
!   /* If tag is a variable (and NOT_A_TAG) than a new symbol memory
!      tag must be created with tag added to its may alias list.  */
!   if (!MTAG_P (tag))
!     new_type_alias (vect_ptr, tag, DR_REF (dr));
!   else
!     set_symbol_mem_tag (vect_ptr, tag);
  
    /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
        vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
--- 1072,1118 ----
      }
  
    /** (1) Create the new vector-pointer variable:  **/
!   vect_ptr_type = build_pointer_type (vectype);
  
!   if ((base_decl = find_base_decl (DR_BASE_ADDRESS (dr)))
!       && TYPE_RESTRICT (TREE_TYPE (base_decl)))
      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 (base_decl)
      {
!       /* Make sure the restrict pointed-to alias set is computed and copy
!          it over to the vector pointer.  */
!       get_alias_set (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (base_decl)),
! 			     base_decl));
        DECL_POINTER_ALIAS_SET (vect_ptr)
! 	= DECL_POINTER_ALIAS_SET (base_decl);
      }
  
!   /* 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);
!       tree data_ref = build_fold_indirect_ref (vect_ptr);
!       do
! 	{
! 	  if (!alias_sets_conflict_p (get_alias_set (data_ref),
! 				      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);
  
    /** Note: If the dataref is in an inner-loop nested in LOOP, and we are
        vectorizing LOOP (i.e. outer-loop vectorization), we need to create two
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1197,1204 ****
  	  duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
  	  duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
  	}
-       merge_alias_info (vect_ptr_init, indx_before_incr);
-       merge_alias_info (vect_ptr_init, indx_after_incr);
        if (ptr_incr)
  	*ptr_incr = incr;
  
--- 1206,1211 ----
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 1229,1236 ****
  	  duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
  	  duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
  	}
-       merge_alias_info (vect_ptr_init, indx_before_incr);
-       merge_alias_info (vect_ptr_init, indx_after_incr);
        if (ptr_incr)
  	*ptr_incr = incr;
  
--- 1236,1241 ----
*************** bump_vector_ptr (tree dataref_ptr, gimpl
*** 1301,1307 ****
    /* Copy the points-to information if it exists. */
    if (DR_PTR_INFO (dr))
      duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
-   merge_alias_info (new_dataref_ptr, dataref_ptr);
  
    if (!ptr_incr)
      return new_dataref_ptr;
--- 1306,1311 ----
*************** vectorizable_store (gimple stmt, gimple_
*** 5391,5397 ****
  						 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 
--- 5395,5401 ----
  						 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_
*** 5440,5450 ****
  	    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 (get_alias_set (data_ref) == get_alias_set (gimple_assign_lhs (stmt))
! 		      || alias_set_subset_of (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);
--- 5444,5452 ----
  	    vec_oprnd = VEC_index (tree, result_chain, i);
  
  	  data_ref = build_fold_indirect_ref (dataref_ptr);
! 	  /* ???  Restrict is broken.
! 	  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
*** 5635,5641 ****
        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);
--- 5637,5643 ----
        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
*** 6607,6613 ****
          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);
--- 6609,6615 ----
          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
*** 6668,6678 ****
  	    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 (get_alias_set (data_ref) == get_alias_set (gimple_assign_rhs1 (stmt))
! 		      || alias_set_subset_of (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);
--- 6670,6678 ----
  	    default:
  	      gcc_unreachable ();
  	    }
! 	  /* ???  Restrict is broken.
! 	  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);
*************** vect_loop_versioning (loop_vec_info loop
*** 8098,8107 ****
--- 8098,8112 ----
      force_gimple_operand (cond_expr, &gimplify_stmt_list, true, NULL_TREE);
    gimple_seq_add_seq (&cond_expr_stmt_list, gimplify_stmt_list);
  
+   /* Loop versioning ends up calling verify_alias_info which barfs on
+      the new dereferenced pointers we inserted.  Defer that until after
+      we recomputed alias information.  */
+   cfun->gimple_df->aliases_computed_p = false;
    initialize_original_copy_tables ();
    nloop = loop_version (loop, cond_expr, &condition_bb,
  			prob, prob, REG_BR_PROB_BASE - prob, true);
    free_original_copy_tables();
+   cfun->gimple_df->aliases_computed_p = true;
  
    /* Loop versioning violates an assumption we try to maintain during 
       vectorization - that the loop exit block has a single predecessor.
Index: gcc/alias.h
===================================================================
*** gcc/alias.h.orig	2008-11-20 17:25:37.000000000 +0100
--- gcc/alias.h	2008-11-20 17:26:05.000000000 +0100
*************** extern int alias_sets_conflict_p (alias_
*** 41,46 ****
--- 41,47 ----
  extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
  extern int objects_must_conflict_p (tree, tree);
  extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
+ extern tree find_base_decl (tree);
  
  /* This alias set can be used to force a memory to conflict with all
     other memories, creating a barrier across which no memory reference
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig	2008-11-20 17:25:37.000000000 +0100
--- gcc/alias.c	2008-11-20 17:26:05.000000000 +0100
*************** static int base_alias_check (rtx, rtx, e
*** 156,162 ****
  static rtx find_base_value (rtx);
  static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
  static int insert_subset_children (splay_tree_node, void*);
- static tree find_base_decl (tree);
  static alias_set_entry get_alias_set_entry (alias_set_type);
  static const_rtx fixed_scalar_and_varying_struct_p (const_rtx, const_rtx, rtx, rtx,
  						    bool (*) (const_rtx, bool));
--- 156,161 ----
*************** objects_must_conflict_p (tree t1, tree t
*** 392,398 ****
     If there is no such DECL, or a unique decl cannot be determined,
     NULL_TREE is returned.  */
  
! static tree
  find_base_decl (tree t)
  {
    tree d0, d1;
--- 391,397 ----
     If there is no such DECL, or a unique decl cannot be determined,
     NULL_TREE is returned.  */
  
! tree
  find_base_decl (tree t)
  {
    tree d0, d1;
*************** find_base_decl (tree t)
*** 430,435 ****
--- 429,439 ----
        else
  	return 0;
  
+     case tcc_exceptional:
+       if (TREE_CODE (t) == SSA_NAME)
+ 	return find_base_decl (SSA_NAME_VAR (t));
+       return 0;
+ 
      default:
        return 0;
      }
*************** get_alias_set (tree t)
*** 525,536 ****
        /* 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))
  	    {
--- 529,535 ----
        /* Check for accesses through restrict-qualified pointers.  */
        if (INDIRECT_REF_P (inner))
  	{
! 	  tree decl = find_base_decl (TREE_OPERAND (inner, 0));
  
  	  if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
  	    {
Index: gcc/testsuite/gcc.c-torture/compile/pr37955.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr37955.c	2008-11-20 17:26:05.000000000 +0100
***************
*** 0 ****
--- 1,19 ----
+ typedef struct
+ {
+   enum { NotConnected = 0 } conn_state;
+   unsigned int conn_hndl;
+ } AEP_CONNECTION_ENTRY;
+ 
+ static AEP_CONNECTION_ENTRY aep_app_conn_table[256];
+ 
+ void aep_mod_exp (void)
+ {
+   int count;
+ 
+   for (count = 0; count < 256; count++)
+     {
+       aep_app_conn_table[count].conn_state = NotConnected;
+       aep_app_conn_table[count].conn_hndl = 0;
+     }
+ }
+ 
Index: gcc/testsuite/gcc.c-torture/compile/pr37742-2.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr37742-2.c	2008-11-20 17:26:05.000000000 +0100
***************
*** 0 ****
--- 1,14 ----
+ /* PR middle-end/37742 */
+ 
+ typedef struct { float re; float im; } S;
+ 
+ void
+ foo (S * __restrict a, S * __restrict b, int len)
+ {
+   int i;
+   for (i = 0; i < len; i++)
+     {
+       a[i].re = a[i].re + b[i].re;
+       a[i].im = a[i].im + b[i].im;
+     }
+ }
Index: gcc/testsuite/gcc.c-torture/compile/pr37742-3.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr37742-3.c	2008-11-20 17:26:37.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ void matmul_i4 (int * __restrict dest_y,
+ 		const int * __restrict abase,
+ 		const int * __restrict bbase_y,
+ 		int count, int xcount, int ycount, int aystride)
+ {
+   int x, y, n;
+   const int * __restrict abase_n;
+   int bbase_yn;
+   for (y = 0; y < ycount; y++)
+     for (n = 0; n < count; n++) {
+ 	abase_n = abase + n*aystride;
+ 	bbase_yn = bbase_y[n];
+ 	for (x = 0; x < xcount; x++)
+ 	  dest_y[x] += abase_n[x] * bbase_yn; 
+     }
+ }
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c.orig	2008-11-21 11:15:50.000000000 +0100
--- gcc/tree-ssa.c	2008-11-21 13:15:20.000000000 +0100
*************** verify_use (basic_block bb, basic_block
*** 358,363 ****
--- 358,367 ----
    bool err = false;
    tree ssa_name = USE_FROM_PTR (use_p);
  
+   if (!is_gimple_reg (ssa_name)
+       && !gimple_aliases_computed_p (cfun))
+     return false;
+ 
    if (!TREE_VISITED (ssa_name))
      if (verify_imm_links (stderr, ssa_name))
        err = true;


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