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] Fix PR52756


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.

Thanks,
Richard.

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

	PR tree-optimization/52756
	* tree-ssa-threadupdate.c (thread_through_loop_header): After
	threading through the loop latch re-start the function to
	double-check the rest of the threading opportunities.

	* 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 186066)
--- gcc/tree-ssa-threadupdate.c	(working copy)
*************** thread_through_loop_header (struct loop
*** 838,843 ****
--- 838,844 ----
    edge_iterator ei;
    basic_block tgt_bb, atgt_bb;
    enum bb_dom_status domst;
+   bool threaded_latch = false;
  
    /* We have already threaded through headers to exits, so all the threading
       requests now are to the inside of the loop.  We need to avoid creating
*************** thread_through_loop_header (struct loop
*** 908,913 ****
--- 909,915 ----
    if (single_succ_p (header))
      goto fail;
  
+ thread_rest:
    if (latch->aux)
      {
        if (THREAD_TARGET2 (latch))
*************** thread_through_loop_header (struct loop
*** 916,922 ****
        tgt_bb = tgt_edge->dest;
      }
    else if (!may_peel_loop_headers
! 	   && !redirection_block_p (loop->header))
      goto fail;
    else
      {
--- 918,924 ----
        tgt_bb = tgt_edge->dest;
      }
    else if (!may_peel_loop_headers
! 	   && !redirection_block_p (header))
      goto fail;
    else
      {
*************** thread_through_loop_header (struct loop
*** 950,956 ****
        if (!tgt_bb)
  	{
  	  /* There are no threading requests.  */
! 	  return false;
  	}
  
        /* Redirecting to empty loop latch is useless.  */
--- 952,958 ----
        if (!tgt_bb)
  	{
  	  /* There are no threading requests.  */
! 	  return threaded_latch;
  	}
  
        /* Redirecting to empty loop latch is useless.  */
*************** thread_through_loop_header (struct loop
*** 971,977 ****
        loop->header = NULL;
        loop->latch = NULL;
        loops_state_set (LOOPS_NEED_FIXUP);
!       return thread_block (header, false);
      }
  
    if (tgt_bb->loop_father->header == tgt_bb)
--- 973,979 ----
        loop->header = NULL;
        loop->latch = NULL;
        loops_state_set (LOOPS_NEED_FIXUP);
!       return threaded_latch | thread_block (header, false);
      }
  
    if (tgt_bb->loop_father->header == tgt_bb)
*************** thread_through_loop_header (struct loop
*** 994,1002 ****
        loop->latch = thread_single_edge (latch);
        gcc_assert (single_succ (loop->latch) == tgt_bb);
        loop->header = tgt_bb;
  
        /* Thread the remaining edges through the former header.  */
!       thread_block (header, false);
      }
    else
      {
--- 996,1005 ----
        loop->latch = thread_single_edge (latch);
        gcc_assert (single_succ (loop->latch) == tgt_bb);
        loop->header = tgt_bb;
+       threaded_latch = true;
  
        /* Thread the remaining edges through the former header.  */
!       goto thread_rest;
      }
    else
      {
*************** fail:
*** 1039,1045 ****
        free (e->aux);
        e->aux = NULL;
      }
!   return false;
  }
  
  /* Walk through the registered jump threads and convert them into a
--- 1042,1048 ----
        free (e->aux);
        e->aux = NULL;
      }
!   return threaded_latch;
  }
  
  /* Walk through the registered jump threads and convert them into a


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