mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			tree-ssa-threadupdate.c: Include ssa-iterators.h
* tree-ssa-threadupdate.c: Include ssa-iterators.h (copy_phi_arg_into_existing_phi): New function. (any_remaining_duplicated_blocks): Likewise. (ssa_fix_duplicate_block_edges): Handle multiple duplicated blocks on a jump threading path. From-SVN: r205004
This commit is contained in:
		
							parent
							
								
									01ccc98e19
								
							
						
					
					
						commit
						b06cbaac12
					
				|  | @ -1,5 +1,11 @@ | ||||||
| 2013-11-19  Jeff Law  <law@redhat.com> | 2013-11-19  Jeff Law  <law@redhat.com> | ||||||
| 
 | 
 | ||||||
|  | 	* tree-ssa-threadupdate.c: Include ssa-iterators.h | ||||||
|  | 	(copy_phi_arg_into_existing_phi): New function. | ||||||
|  | 	(any_remaining_duplicated_blocks): Likewise. | ||||||
|  | 	(ssa_fix_duplicate_block_edges): Handle multiple duplicated | ||||||
|  | 	blocks on a jump threading path. | ||||||
|  | 	 | ||||||
| 	* tree-ssa-threadupdate.c (thread_through_loop_header):  Do not | 	* tree-ssa-threadupdate.c (thread_through_loop_header):  Do not | ||||||
| 	thread through a joiner which has the latch edge. | 	thread through a joiner which has the latch edge. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see | ||||||
| #include "tree-phinodes.h" | #include "tree-phinodes.h" | ||||||
| #include "tree-ssa.h" | #include "tree-ssa.h" | ||||||
| #include "tree-ssa-threadupdate.h" | #include "tree-ssa-threadupdate.h" | ||||||
|  | #include "ssa-iterators.h" | ||||||
| #include "dumpfile.h" | #include "dumpfile.h" | ||||||
| #include "cfgloop.h" | #include "cfgloop.h" | ||||||
| #include "hash-table.h" | #include "hash-table.h" | ||||||
|  | @ -337,6 +338,31 @@ lookup_redirection_data (edge e, enum insert_option insert) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Similar to copy_phi_args, except that the PHI arg exists, it just
 | ||||||
|  |    does not have a value associated with it.  */ | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | copy_phi_arg_into_existing_phi (edge src_e, edge tgt_e) | ||||||
|  | { | ||||||
|  |   int src_idx = src_e->dest_idx; | ||||||
|  |   int tgt_idx = tgt_e->dest_idx; | ||||||
|  | 
 | ||||||
|  |   /* Iterate over each PHI in e->dest.  */ | ||||||
|  |   for (gimple_stmt_iterator gsi = gsi_start_phis (src_e->dest), | ||||||
|  | 			    gsi2 = gsi_start_phis (tgt_e->dest); | ||||||
|  |        !gsi_end_p (gsi); | ||||||
|  |        gsi_next (&gsi), gsi_next (&gsi2)) | ||||||
|  |     { | ||||||
|  |       gimple src_phi = gsi_stmt (gsi); | ||||||
|  |       gimple dest_phi = gsi_stmt (gsi2); | ||||||
|  |       tree val = gimple_phi_arg_def (src_phi, src_idx); | ||||||
|  |       source_location locus = gimple_phi_arg_location (src_phi, src_idx); | ||||||
|  | 
 | ||||||
|  |       SET_PHI_ARG_DEF (dest_phi, tgt_idx, val); | ||||||
|  |       gimple_phi_arg_set_location (dest_phi, tgt_idx, locus); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* For each PHI in BB, copy the argument associated with SRC_E to TGT_E.  */ | /* For each PHI in BB, copy the argument associated with SRC_E to TGT_E.  */ | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -418,7 +444,23 @@ create_edge_and_update_destination_phis (struct redirection_data *rd, | ||||||
|   copy_phi_args (e->dest, rd->path->last ()->e, e); |   copy_phi_args (e->dest, rd->path->last ()->e, e); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Wire up the outgoing edges from the duplicate block and
 | /* Look through PATH beginning at START and return TRUE if there are
 | ||||||
|  |    any additional blocks that need to be duplicated.  Otherwise, | ||||||
|  |    return FALSE.  */ | ||||||
|  | static bool | ||||||
|  | any_remaining_duplicated_blocks (vec<jump_thread_edge *> *path, | ||||||
|  | 				 unsigned int start) | ||||||
|  | { | ||||||
|  |   for (unsigned int i = start + 1; i < path->length (); i++) | ||||||
|  |     { | ||||||
|  |       if ((*path)[i]->type == EDGE_COPY_SRC_JOINER_BLOCK | ||||||
|  | 	  || (*path)[i]->type == EDGE_COPY_SRC_BLOCK) | ||||||
|  | 	return true; | ||||||
|  |     } | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Wire up the outgoing edges from the duplicate blocks and
 | ||||||
|    update any PHIs as needed.  */ |    update any PHIs as needed.  */ | ||||||
| void | void | ||||||
| ssa_fix_duplicate_block_edges (struct redirection_data *rd, | ssa_fix_duplicate_block_edges (struct redirection_data *rd, | ||||||
|  | @ -427,37 +469,77 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd, | ||||||
|   edge e = rd->incoming_edges->e; |   edge e = rd->incoming_edges->e; | ||||||
|   vec<jump_thread_edge *> *path = THREAD_PATH (e); |   vec<jump_thread_edge *> *path = THREAD_PATH (e); | ||||||
| 
 | 
 | ||||||
|  |   for (unsigned int count = 0, i = 1; i < path->length (); i++) | ||||||
|  |     {  | ||||||
|       /* If we were threading through an joiner block, then we want
 |       /* If we were threading through an joiner block, then we want
 | ||||||
| 	 to keep its control statement and redirect an outgoing edge. | 	 to keep its control statement and redirect an outgoing edge. | ||||||
| 	 Else we want to remove the control statement & edges, then create | 	 Else we want to remove the control statement & edges, then create | ||||||
| 	 a new outgoing edge.  In both cases we may need to update PHIs.  */ | 	 a new outgoing edge.  In both cases we may need to update PHIs.  */ | ||||||
|   if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK) |       if ((*path)[i]->type == EDGE_COPY_SRC_JOINER_BLOCK) | ||||||
| 	{ | 	{ | ||||||
| 	  edge victim; | 	  edge victim; | ||||||
| 	  edge e2; | 	  edge e2; | ||||||
| 
 | 
 | ||||||
| 	  /* This updates the PHIs at the destination of the duplicate
 | 	  /* This updates the PHIs at the destination of the duplicate
 | ||||||
| 	     block.  */ | 	     block.  */ | ||||||
|       update_destination_phis (local_info->bb, rd->dup_blocks[0]); | 	  update_destination_phis (local_info->bb, rd->dup_blocks[count]); | ||||||
| 
 | 
 | ||||||
| 	  /* Find the edge from the duplicate block to the block we're
 | 	  /* Find the edge from the duplicate block to the block we're
 | ||||||
| 	     threading through.  That's the edge we want to redirect.  */ | 	     threading through.  That's the edge we want to redirect.  */ | ||||||
|       victim = find_edge (rd->dup_blocks[0], (*path)[1]->e->dest); | 	  victim = find_edge (rd->dup_blocks[count], (*path)[i]->e->dest); | ||||||
|  | 
 | ||||||
|  | 	  /* If there are no remaining blocks on the path to duplicate,
 | ||||||
|  | 	     then redirect VICTIM to the final destination of the jump | ||||||
|  | 	     threading path.  */ | ||||||
|  | 	  if (!any_remaining_duplicated_blocks (path, i)) | ||||||
|  | 	    { | ||||||
| 	      e2 = redirect_edge_and_branch (victim, path->last ()->e->dest); | 	      e2 = redirect_edge_and_branch (victim, path->last ()->e->dest); | ||||||
| 	      e2->count = path->last ()->e->count; | 	      e2->count = path->last ()->e->count; | ||||||
| 
 |  | ||||||
| 	      /* If we redirected the edge, then we need to copy PHI arguments
 | 	      /* If we redirected the edge, then we need to copy PHI arguments
 | ||||||
| 	 at the target.  If the edge already existed (e2 != victim case), | 	         at the target.  If the edge already existed (e2 != victim | ||||||
| 	 then the PHIs in the target already have the correct arguments.  */ | 		 case), then the PHIs in the target already have the correct | ||||||
|  | 		 arguments.  */ | ||||||
| 	      if (e2 == victim) | 	      if (e2 == victim) | ||||||
| 	        copy_phi_args (e2->dest, path->last ()->e, e2); | 	        copy_phi_args (e2->dest, path->last ()->e, e2); | ||||||
| 	    } | 	    } | ||||||
| 	  else | 	  else | ||||||
| 	    { | 	    { | ||||||
|       remove_ctrl_stmt_and_useless_edges (rd->dup_blocks[0], NULL); | 	      /* Redirect VICTIM to the next duplicated block in the path.  */ | ||||||
|       create_edge_and_update_destination_phis (rd, rd->dup_blocks[0]); | 	      e2 = redirect_edge_and_branch (victim, rd->dup_blocks[count + 1]); | ||||||
|  | 
 | ||||||
|  | 	      /* We need to update the PHIs in the next duplicated block.  We
 | ||||||
|  | 		 want the new PHI args to have the same value as they had | ||||||
|  | 		 in the source of the next duplicate block. | ||||||
|  | 
 | ||||||
|  | 		 Thus, we need to know which edge we traversed into the | ||||||
|  | 		 source of the duplicate.  Furthermore, we may have | ||||||
|  | 		 traversed many edges to reach the source of the duplicate. | ||||||
|  | 
 | ||||||
|  | 		 Walk through the path starting at element I until we | ||||||
|  | 		 hit an edge marked with EDGE_COPY_SRC_BLOCK.  We want | ||||||
|  | 		 the edge from the prior element.  */ | ||||||
|  | 	      for (unsigned int j = i + 1; j < path->length (); j++) | ||||||
|  | 		{ | ||||||
|  | 		  if ((*path)[j]->type == EDGE_COPY_SRC_BLOCK) | ||||||
|  | 		    { | ||||||
|  | 		      copy_phi_arg_into_existing_phi ((*path)[j - 1]->e, e2); | ||||||
|  | 		      break; | ||||||
|  | 		    } | ||||||
|  | 		} | ||||||
|  | 	    } | ||||||
|  | 	  count++; | ||||||
|  | 	} | ||||||
|  |       else if ((*path)[i]->type == EDGE_COPY_SRC_BLOCK) | ||||||
|  | 	{ | ||||||
|  | 	  remove_ctrl_stmt_and_useless_edges (rd->dup_blocks[count], NULL); | ||||||
|  | 	  create_edge_and_update_destination_phis (rd, rd->dup_blocks[count]); | ||||||
|  | 	  if (count == 1) | ||||||
|  | 	    single_succ_edge (rd->dup_blocks[1])->aux = NULL; | ||||||
|  | 	  count++; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| /* Hash table traversal callback routine to create duplicate blocks.  */ | /* Hash table traversal callback routine to create duplicate blocks.  */ | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Jeff Law
						Jeff Law