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]

Re: [PATCH] Fix PR52756


On Mon, 2 Apr 2012, Richard Guenther wrote:

> 
> After going through a gazillion of candidate fixes for PR52756, a
> case where jump threading destroys loops in a non-recoverable way,
> I settled with the following.  The issue is that we thread both
> the loop latch and the loop entry edge but the code is not prepared
> for that.  Another possible fix would be to unconditionally throw
> away threadings if we threaded the latch based on the fact that
> the rest of the edges no longer are loop entry edges (but threading
> them may create one, I think even still one that will end up
> creating a multiple entry loop).
> 
> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

And revealed one missed optimization, gcc.dg/tree-ssa/ssa-dom-thread-2.c

Thus the following is another try to fix things.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2012-04-02  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/52756
	* tree-ssa-threadupdate.c (def_split_header_continue_p): New function.
	(thread_through_loop_header): After threading through the loop latch
	remove the split part from the loop and clear further threading
	opportunities that would create a multiple entry loop.

	* gcc.dg/torture/pr52756.c: New testcase.

Index: gcc/testsuite/gcc.dg/torture/pr52756.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr52756.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr52756.c	(revision 0)
***************
*** 0 ****
--- 1,9 ----
+ /* { dg-do compile } */
+ 
+ void Env_FetchObj0AttrOffset (unsigned int NumFields,  int *Status)
+ {
+   int Found = 0;
+   if (NumFields)      
+     while ((*Status == 0) && NumFields-- > 0 && Found == 0)       
+       Found = 1;
+ }
Index: gcc/tree-ssa-threadupdate.c
===================================================================
*** gcc/tree-ssa-threadupdate.c	(revision 186082)
--- gcc/tree-ssa-threadupdate.c	(working copy)
*************** determine_bb_domination_status (struct l
*** 826,831 ****
--- 826,842 ----
    return (bb_reachable ? DOMST_DOMINATING : DOMST_LOOP_BROKEN);
  }
  
+ /* Return true if BB is part of the new pre-header that is created
+    when threading the latch to DATA.  */
+ 
+ static bool
+ def_split_header_continue_p (const_basic_block bb, const void *data)
+ {
+   const_basic_block new_header = (const_basic_block) data;
+   return (bb->loop_father == new_header->loop_father
+ 	  && bb != new_header);
+ }
+ 
  /* Thread jumps through the header of LOOP.  Returns true if cfg changes.
     If MAY_PEEL_LOOP_HEADERS is false, we avoid threading from entry edges
     to the inside of the loop.  */
*************** thread_through_loop_header (struct loop
*** 990,1000 ****
--- 1001,1046 ----
  
    if (latch->aux)
      {
+       basic_block *bblocks;
+       unsigned nblocks, i;
+ 
        /* First handle the case latch edge is redirected.  */
        loop->latch = thread_single_edge (latch);
        gcc_assert (single_succ (loop->latch) == tgt_bb);
        loop->header = tgt_bb;
  
+       /* Remove the new pre-header blocks from our loop.  */
+       bblocks = XCNEWVEC (basic_block, loop->num_nodes);
+       nblocks = dfs_enumerate_from (header, 0, def_split_header_continue_p,
+ 				    bblocks, loop->num_nodes, tgt_bb);
+       for (i = 0; i < nblocks; i++)
+ 	{
+ 	  remove_bb_from_loops (bblocks[i]);
+ 	  add_bb_to_loop (bblocks[i], loop_outer (loop));
+ 	}
+       free (bblocks);
+ 
+       /* Cancel remaining threading requests that would make the
+ 	 loop a multiple entry loop.  */
+       FOR_EACH_EDGE (e, ei, header->preds)
+ 	{
+ 	  edge e2;
+ 	  if (e->aux == NULL)
+ 	    continue;
+ 
+ 	  if (THREAD_TARGET2 (e))
+ 	    e2 = THREAD_TARGET2 (e);
+ 	  else
+ 	    e2 = THREAD_TARGET (e);
+ 
+ 	  if (e->src->loop_father != e2->dest->loop_father
+ 	      && e2->dest != loop->header)
+ 	    {
+ 	      free (e->aux);
+ 	      e->aux = NULL;
+ 	    }
+ 	}
+ 
        /* Thread the remaining edges through the former header.  */
        thread_block (header, false);
      }


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