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 RTL unswitching loop verification ICE


This fixes the reported ICE on arm.  Similar to tree level unswitching
RTL level unswitching can expose formerly irreducible regions as new
loops.  The following patch makes sure to discover them (we now
verify we do).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

Richard.

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

	* loop-init.c (loop_optimizer_init): Clear loop state when
	re-initializing preserved loops.
	* loop-unswitch.c (unswitch_single_loop): Return whether
	we unswitched the loop.  Do not verify loop state here.
	(unswitch_loops): When we unswitched a loop discover new
	loops.

Index: gcc/loop-init.c
===================================================================
*** gcc/loop-init.c	(revision 195997)
--- gcc/loop-init.c	(working copy)
*************** loop_optimizer_init (unsigned flags)
*** 99,104 ****
--- 99,107 ----
  #ifdef ENABLE_CHECKING
        verify_loop_structure ();
  #endif
+ 
+       /* Clear all flags.  */
+       loops_state_clear (~0U);
      }
  
    /* Apply flags to loops.  */
Index: gcc/loop-unswitch.c
===================================================================
*** gcc/loop-unswitch.c	(revision 195997)
--- gcc/loop-unswitch.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 78,84 ****
    with handling this case.  */
  
  static struct loop *unswitch_loop (struct loop *, basic_block, rtx, rtx);
! static void unswitch_single_loop (struct loop *, rtx, int);
  static rtx may_unswitch_on (basic_block, struct loop *, rtx *);
  
  /* Prepare a sequence comparing OP0 with OP1 using COMP and jumping to LABEL if
--- 78,84 ----
    with handling this case.  */
  
  static struct loop *unswitch_loop (struct loop *, basic_block, rtx, rtx);
! static bool unswitch_single_loop (struct loop *, rtx, int);
  static rtx may_unswitch_on (basic_block, struct loop *, rtx *);
  
  /* Prepare a sequence comparing OP0 with OP1 using COMP and jumping to LABEL if
*************** unswitch_loops (void)
*** 140,152 ****
  {
    loop_iterator li;
    struct loop *loop;
  
    /* Go through inner loops (only original ones).  */
  
    FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
!     unswitch_single_loop (loop, NULL_RTX, 0);
  
    iv_analysis_done ();
  }
  
  /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
--- 140,161 ----
  {
    loop_iterator li;
    struct loop *loop;
+   bool changed = false;
  
    /* Go through inner loops (only original ones).  */
  
    FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
!     changed |= unswitch_single_loop (loop, NULL_RTX, 0);
  
    iv_analysis_done ();
+ 
+   /* If we unswitched any loop discover new loops that are eventually
+      exposed by making irreducible regions reducible.  */
+   if (changed)
+     {
+       calculate_dominance_info (CDI_DOMINATORS);
+       fix_loop_structure (NULL);
+     }
  }
  
  /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
*************** reversed_condition (rtx cond)
*** 241,248 ****
  /* Unswitch single LOOP.  COND_CHECKED holds list of conditions we already
     unswitched on and are therefore known to be true in this LOOP.  NUM is
     number of unswitchings done; do not allow it to grow too much, it is too
!    easy to create example on that the code would grow exponentially.  */
! static void
  unswitch_single_loop (struct loop *loop, rtx cond_checked, int num)
  {
    basic_block *bbs;
--- 250,258 ----
  /* Unswitch single LOOP.  COND_CHECKED holds list of conditions we already
     unswitched on and are therefore known to be true in this LOOP.  NUM is
     number of unswitchings done; do not allow it to grow too much, it is too
!    easy to create example on that the code would grow exponentially.
!    Returns true LOOP was unswitched.  */
! static bool 
  unswitch_single_loop (struct loop *loop, rtx cond_checked, int num)
  {
    basic_block *bbs;
*************** unswitch_single_loop (struct loop *loop,
*** 258,264 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
!       return;
      }
  
    /* Only unswitch innermost loops.  */
--- 268,274 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
!       return false;
      }
  
    /* Only unswitch innermost loops.  */
*************** unswitch_single_loop (struct loop *loop,
*** 266,272 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
!       return;
      }
  
    /* We must be able to duplicate loop body.  */
--- 276,282 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
!       return false;
      }
  
    /* We must be able to duplicate loop body.  */
*************** unswitch_single_loop (struct loop *loop,
*** 274,280 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, can't duplicate loop\n");
!       return;
      }
  
    /* The loop should not be too large, to limit code growth.  */
--- 284,290 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, can't duplicate loop\n");
!       return false;
      }
  
    /* The loop should not be too large, to limit code growth.  */
*************** unswitch_single_loop (struct loop *loop,
*** 282,288 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, loop too big\n");
!       return;
      }
  
    /* Do not unswitch in cold areas.  */
--- 292,298 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, loop too big\n");
!       return false;
      }
  
    /* Do not unswitch in cold areas.  */
*************** unswitch_single_loop (struct loop *loop,
*** 290,296 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, not hot area\n");
!       return;
      }
  
    /* Nor if the loop usually does not roll.  */
--- 300,306 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, not hot area\n");
!       return false;
      }
  
    /* Nor if the loop usually does not roll.  */
*************** unswitch_single_loop (struct loop *loop,
*** 299,305 ****
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, loop iterations < 1\n");
!       return;
      }
  
    do
--- 309,315 ----
      {
        if (dump_file)
  	fprintf (dump_file, ";; Not unswitching, loop iterations < 1\n");
!       return false;
      }
  
    do
*************** unswitch_single_loop (struct loop *loop,
*** 317,323 ****
        if (i == loop->num_nodes)
  	{
  	  free (bbs);
! 	  return;
  	}
  
        if (cond != const0_rtx
--- 327,333 ----
        if (i == loop->num_nodes)
  	{
  	  free (bbs);
! 	  return false;
  	}
  
        if (cond != const0_rtx
*************** unswitch_single_loop (struct loop *loop,
*** 364,373 ****
    nloop = unswitch_loop (loop, bbs[i], copy_rtx_if_shared (cond), cinsn);
    gcc_assert (nloop);
  
- #ifdef ENABLE_CHECKING
-   verify_loop_structure ();
- #endif
- 
    /* Invoke itself on modified loops.  */
    unswitch_single_loop (nloop, rconds, num + 1);
    unswitch_single_loop (loop, conds, num + 1);
--- 374,379 ----
*************** unswitch_single_loop (struct loop *loop,
*** 377,382 ****
--- 383,390 ----
      free_EXPR_LIST_node (rconds);
  
    free (bbs);
+ 
+   return true;
  }
  
  /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON.  We only support


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