[PATCH] Fix PR56264

Richard Biener rguenther@suse.de
Mon Feb 11 13:24:00 GMT 2013


This fixes PR56264 - the machinery to communicate changed-blocks from
fix_loop_structure to cfgcleanups call to rewrite_into_loop_closed_ssa
doesn't work (at least) in the face of newly discovered loops as that
exposes new definition sites and not only new use sites (as the code
assumes).

Fixed by completely re-scanning the whole function if we discover
new loops (in this case unswitching makes one subloop no longer
irreducible).

Bootstrapped and tested on x86_64-unknown-linux-gnu, need to retest
because I combined it with removing the find_uses_to_rename ??? and
that exposes PR56286.

Richard.

2013-02-11  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/56264
	* cfgloop.h (fix_loop_structure): Adjust prototype.
	* loop-init.c (fix_loop_structure): Return the number of
	newly discovered loops.
	* tree-cfgcleanup.c (repair_loop_structures): When new loops
	are discovered, do a full loop-closed SSA rewrite.

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

Index: gcc/cfgloop.h
===================================================================
*** gcc/cfgloop.h	(revision 195938)
--- gcc/cfgloop.h	(working copy)
*************** extern void flow_loop_dump (const struct
*** 216,222 ****
  struct loop *alloc_loop (void);
  extern void flow_loop_free (struct loop *);
  int flow_loop_nodes_find (basic_block, struct loop *);
! void fix_loop_structure (bitmap changed_bbs);
  bool mark_irreducible_loops (void);
  void release_recorded_exits (void);
  void record_loop_exits (void);
--- 216,222 ----
  struct loop *alloc_loop (void);
  extern void flow_loop_free (struct loop *);
  int flow_loop_nodes_find (basic_block, struct loop *);
! unsigned fix_loop_structure (bitmap changed_bbs);
  bool mark_irreducible_loops (void);
  void release_recorded_exits (void);
  void record_loop_exits (void);
Index: gcc/loop-init.c
===================================================================
*** gcc/loop-init.c	(revision 195938)
--- gcc/loop-init.c	(working copy)
*************** loop_fini_done:
*** 171,186 ****
     the latch, and loops did not get new subloops (new loops might possibly
     get created, but we are not interested in them).  Fix up the mess.
  
!    If CHANGED_BBS is not NULL, basic blocks whose loop has changed are
!    marked in it.  */
  
! void
  fix_loop_structure (bitmap changed_bbs)
  {
    basic_block bb;
    int record_exits = 0;
    loop_iterator li;
    struct loop *loop;
  
    timevar_push (TV_LOOP_INIT);
  
--- 171,189 ----
     the latch, and loops did not get new subloops (new loops might possibly
     get created, but we are not interested in them).  Fix up the mess.
  
!    If CHANGED_BBS is not NULL, basic blocks whose loop depth has changed are
!    marked in it.
  
!    Returns the number of new discovered loops.  */
! 
! unsigned
  fix_loop_structure (bitmap changed_bbs)
  {
    basic_block bb;
    int record_exits = 0;
    loop_iterator li;
    struct loop *loop;
+   unsigned old_nloops;
  
    timevar_push (TV_LOOP_INIT);
  
*************** fix_loop_structure (bitmap changed_bbs)
*** 228,233 ****
--- 231,240 ----
        delete_loop (loop);
      }
  
+   /* Remember the number of loops so we can return how many new loops
+      flow_loops_find discovered.  */
+   old_nloops = number_of_loops ();
+ 
    /* Re-compute loop structure in-place.  */
    flow_loops_find (current_loops);
  
*************** fix_loop_structure (bitmap changed_bbs)
*** 253,258 ****
--- 260,267 ----
  #endif
  
    timevar_pop (TV_LOOP_INIT);
+ 
+   return number_of_loops () - old_nloops;
  }
  
  /* Gate for the RTL loop superpass.  The actual passes are subpasses.
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c	(revision 195938)
--- gcc/tree-cfgcleanup.c	(working copy)
*************** static void
*** 707,724 ****
  repair_loop_structures (void)
  {
    bitmap changed_bbs;
  
    calculate_dominance_info (CDI_DOMINATORS);
  
    timevar_push (TV_REPAIR_LOOPS);
    changed_bbs = BITMAP_ALLOC (NULL);
!   fix_loop_structure (changed_bbs);
  
    /* This usually does nothing.  But sometimes parts of cfg that originally
       were inside a loop get out of it due to edge removal (since they
!      become unreachable by back edges from latch).  */
    if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
!     rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
  
    BITMAP_FREE (changed_bbs);
  
--- 707,728 ----
  repair_loop_structures (void)
  {
    bitmap changed_bbs;
+   unsigned n_new_loops;
  
    calculate_dominance_info (CDI_DOMINATORS);
  
    timevar_push (TV_REPAIR_LOOPS);
    changed_bbs = BITMAP_ALLOC (NULL);
!   n_new_loops = fix_loop_structure (changed_bbs);
  
    /* This usually does nothing.  But sometimes parts of cfg that originally
       were inside a loop get out of it due to edge removal (since they
!      become unreachable by back edges from latch).  Also a former
!      irreducible loop can become reducible - in this case force a full
!      rewrite into loop-closed SSA form.  */
    if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
!     rewrite_into_loop_closed_ssa (n_new_loops ? NULL : changed_bbs,
! 				  TODO_update_ssa);
  
    BITMAP_FREE (changed_bbs);
  
Index: gcc/testsuite/gcc.dg/torture/pr56264.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr56264.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr56264.c	(working copy)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-funswitch-loops" } */
+ 
+ int a, b, c;
+ 
+ void f(void)
+ {
+   if(b)
+     {
+       for(a = 0; a < 1; a++)
+ 	lbl:
+ 	    c = c && b ? : 0;
+ 
+       c = 0;
+       goto lbl;
+     }
+ 
+   if(a)
+     goto lbl;
+ }



More information about the Gcc-patches mailing list