mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			re PR tree-optimization/58508 ([Missed-Optimization] Redundant vector load of "actual" loop invariant in loop body.)
PR tree-optimization/58508 * tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant statement that contains data refs with zero-step. * gcc.dg/vect/pr58508.c: New test. From-SVN: r203842
This commit is contained in:
		
							parent
							
								
									6b8fe121af
								
							
						
					
					
						commit
						6f978a2a78
					
				|  | @ -1,3 +1,9 @@ | ||||||
|  | 2013-10-18  Cong Hou  <congh@google.com> | ||||||
|  | 
 | ||||||
|  | 	PR tree-optimization/58508 | ||||||
|  | 	* tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant | ||||||
|  | 	statement that contains data refs with zero-step. | ||||||
|  | 
 | ||||||
| 2013-10-18  Andrew MacLeod  <amacleod@redhat.com> | 2013-10-18  Andrew MacLeod  <amacleod@redhat.com> | ||||||
| 
 | 
 | ||||||
| 	* tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h, sbitmap.h, | 	* tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h, sbitmap.h, | ||||||
|  |  | ||||||
|  | @ -1,3 +1,7 @@ | ||||||
|  | 2013-10-18  Cong Hou  <congh@google.com> | ||||||
|  | 
 | ||||||
|  | 	* gcc.dg/vect/pr58508.c: New test. | ||||||
|  | 
 | ||||||
| 2013-10-18  Paolo Carlini  <paolo.carlini@oracle.com> | 2013-10-18  Paolo Carlini  <paolo.carlini@oracle.com> | ||||||
| 
 | 
 | ||||||
| 	PR c++/58466 | 	PR c++/58466 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,70 @@ | ||||||
|  | /* { dg-do compile } */ | ||||||
|  | /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* The GCC vectorizer generates loop versioning for the following loop
 | ||||||
|  |    since there may exist aliasing between A and B.  The predicate checks | ||||||
|  |    if A may alias with B across all iterations.  Then for the loop in | ||||||
|  |    the true body, we can assert that *B is a loop invariant so that | ||||||
|  |    we can hoist the load of *B before the loop body.  */ | ||||||
|  | 
 | ||||||
|  | void test1 (int* a, int* b) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |   for (i = 0; i < 100000; ++i) | ||||||
|  |     a[i] = *b + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* A test case with nested loops.  The load of b[j+1] in the inner
 | ||||||
|  |    loop should be hoisted.  */ | ||||||
|  | 
 | ||||||
|  | void test2 (int* a, int* b) | ||||||
|  | { | ||||||
|  |   int i, j; | ||||||
|  |   for (j = 0; j < 100000; ++j) | ||||||
|  |     for (i = 0; i < 100000; ++i) | ||||||
|  |       a[i] = b[j+1] + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* A test case with ifcvt transformation.  */ | ||||||
|  | 
 | ||||||
|  | void test3 (int* a, int* b) | ||||||
|  | { | ||||||
|  |   int i, t; | ||||||
|  |   for (i = 0; i < 10000; ++i) | ||||||
|  |     { | ||||||
|  |       if (*b > 0) | ||||||
|  | 	t = *b * 2; | ||||||
|  |       else | ||||||
|  | 	t = *b / 2; | ||||||
|  |       a[i] = t; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* A test case in which the store in the loop can be moved outside
 | ||||||
|  |    in the versioned loop with alias checks.  Note this loop won't | ||||||
|  |    be vectorized.  */ | ||||||
|  | 
 | ||||||
|  | void test4 (int* a, int* b) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |   for (i = 0; i < 100000; ++i) | ||||||
|  |     *a += b[i]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* A test case in which the load and store in the loop to b
 | ||||||
|  |    can be moved outside in the versioned loop with alias checks. | ||||||
|  |    Note this loop won't be vectorized.  */ | ||||||
|  | 
 | ||||||
|  | void test5 (int* a, int* b) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |   for (i = 0; i < 100000; ++i) | ||||||
|  |     { | ||||||
|  |       *b += a[i]; | ||||||
|  |       a[i] = *b; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-tree-dump-times "hoist" 8 "vect" } } */ | ||||||
|  | /* { dg-final { cleanup-tree-dump "vect" } } */ | ||||||
|  | @ -2477,6 +2477,73 @@ vect_loop_versioning (loop_vec_info loop_vinfo, | ||||||
|       adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi)); |       adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |   /* Extract load statements on memrefs with zero-stride accesses.  */ | ||||||
|  | 
 | ||||||
|  |   if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo)) | ||||||
|  |     { | ||||||
|  |       /* In the loop body, we iterate each statement to check if it is a load.
 | ||||||
|  | 	 Then we check the DR_STEP of the data reference.  If DR_STEP is zero, | ||||||
|  | 	 then we will hoist the load statement to the loop preheader.  */ | ||||||
|  | 
 | ||||||
|  |       basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); | ||||||
|  |       int nbbs = loop->num_nodes; | ||||||
|  | 
 | ||||||
|  |       for (int i = 0; i < nbbs; ++i) | ||||||
|  | 	{ | ||||||
|  | 	  for (gimple_stmt_iterator si = gsi_start_bb (bbs[i]); | ||||||
|  | 	       !gsi_end_p (si);) | ||||||
|  | 	    { | ||||||
|  | 	      gimple stmt = gsi_stmt (si); | ||||||
|  | 	      stmt_vec_info stmt_info = vinfo_for_stmt (stmt); | ||||||
|  | 	      struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); | ||||||
|  | 
 | ||||||
|  | 	      if (is_gimple_assign (stmt) | ||||||
|  | 		  && (!dr | ||||||
|  | 		      || (DR_IS_READ (dr) && integer_zerop (DR_STEP (dr))))) | ||||||
|  | 		{ | ||||||
|  | 		  bool hoist = true; | ||||||
|  | 		  ssa_op_iter iter; | ||||||
|  | 		  tree var; | ||||||
|  | 
 | ||||||
|  | 		  /* We hoist a statement if all SSA uses in it are defined
 | ||||||
|  | 		     outside of the loop.  */ | ||||||
|  | 		  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE) | ||||||
|  | 		    { | ||||||
|  | 		      gimple def = SSA_NAME_DEF_STMT (var); | ||||||
|  | 		      if (!gimple_nop_p (def) | ||||||
|  | 			  && flow_bb_inside_loop_p (loop, gimple_bb (def))) | ||||||
|  | 			{ | ||||||
|  | 			  hoist = false; | ||||||
|  | 			  break; | ||||||
|  | 			} | ||||||
|  | 		    } | ||||||
|  | 
 | ||||||
|  | 		  if (hoist) | ||||||
|  | 		    { | ||||||
|  | 		      if (dr) | ||||||
|  | 			gimple_set_vuse (stmt, NULL); | ||||||
|  | 
 | ||||||
|  | 		      gsi_remove (&si, false); | ||||||
|  | 		      gsi_insert_on_edge_immediate (loop_preheader_edge (loop), | ||||||
|  | 						    stmt); | ||||||
|  | 
 | ||||||
|  | 		      if (dump_enabled_p ()) | ||||||
|  | 			{ | ||||||
|  | 			  dump_printf_loc | ||||||
|  | 			      (MSG_NOTE, vect_location, | ||||||
|  | 			       "hoisting out of the vectorized loop: "); | ||||||
|  | 			  dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0); | ||||||
|  | 			  dump_printf (MSG_NOTE, "\n"); | ||||||
|  | 			} | ||||||
|  | 		      continue; | ||||||
|  | 		    } | ||||||
|  | 		} | ||||||
|  | 	      gsi_next (&si); | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|   /* End loop-exit-fixes after versioning.  */ |   /* End loop-exit-fixes after versioning.  */ | ||||||
| 
 | 
 | ||||||
|   if (cond_expr_stmt_list) |   if (cond_expr_stmt_list) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Cong Hou
						Cong Hou