[PING][PATCH]: Allow CFG with empty BBs in selective scheduler

Alexander Monakov amonakov@ispras.ru
Mon Jan 26 00:04:00 GMT 2009


Hi,

I'm not sure if this may count as a regression, as empty basic blocks are
rarely expected at the start of second scheduling pass (the testcase enables
selective scheduling at -Os to reproduce).  OK for stage 1?

On Fri, Oct 31, 2008 at 01:52:40PM +0300, Alexander Monakov wrote:
> Hello,
> 
> This is a submission of a patch installed earlier on sel-sched branch:
> http://gcc.gnu.org/ml/gcc-patches/2008-09/msg01946.html
> 
> We were asserting that there are no empty basic blocks in the region.  This is
> no longer required, and some empty blocks may be hard to delete.  In the
> failing testcase empty blocks were created during cfg_layout_finalize in the
> end of pass_duplicate_computed_gotos, and they are hard to delete due to
> multiple incoming complex edges.  I would like to note that this behaviour is
> only triggered with -Os on this testcase, because otherwise computed gotos are
> duplicated during bb-reorder pass, which calls cfg_cleanup (CLEANUP_EXPENSIVE)
> before doing cfg_layout_finalize.
> 
> The patch deletes the assert, and also includes some related cleanups and
> changes.
> 
> Bootstrapped and regtested on ia64-linux, also bootstrapped and regtested
> earlier on sel-sched branch with selective scheduler enabled at -O2.
> OK for trunk?
> 
> gcc/testsuite/Changelog:
> 
> 2008-10-31  Alexander Monakov  <amonakov@ispras.ru>
> 	* gcc.target/ia64/20071210-2.c: New testcase.
> 
> gcc/Changelog:
> 
> 2008-10-31  Alexander Monakov  <amonakov@ispras.ru>
>         * sel-sched-ir.c (maybe_tidy_empty_bb): Do not attempt to delete a 
>         block if there are complex incoming edges.
>         (sel_merge_blocks): Remove useless assert.
>         (sel_redirect_edge_and_branch): Check that edge was redirected.
>         * sel-sched-ir.h (_eligible_successor_edge_p): Remove assert.
>         (sel_find_rgns): Delete declaration.
>         * sel-sched.c (purge_empty_blocks): Attempt to remove first block of 
>         the region when it is not a preheader.
> 
> Index: gcc/sel-sched.c
> ===================================================================
> --- gcc/sel-sched.c	(revision 141459)
> +++ gcc/sel-sched.c	(working copy)
> @@ -6476,9 +6476,10 @@
>  static void
>  purge_empty_blocks (void)
>  {
> -  int i ;
> +  /* Do not attempt to delete preheader.  */
> +  int i = sel_is_loop_preheader_p (BASIC_BLOCK (BB_TO_BLOCK (0))) ? 1 : 0;
>  
> -  for (i = 1; i < current_nr_blocks; )
> +  while (i < current_nr_blocks)
>      {
>        basic_block b = BASIC_BLOCK (BB_TO_BLOCK (i));
>  
> Index: gcc/sel-sched-ir.c
> ===================================================================
> --- gcc/sel-sched-ir.c	(revision 141459)
> +++ gcc/sel-sched-ir.c	(working copy)
> @@ -3489,6 +3489,8 @@
>  maybe_tidy_empty_bb (basic_block bb)
>  {
>    basic_block succ_bb, pred_bb;
> +  edge e;
> +  edge_iterator ei;
>    bool rescan_p;
>  
>    /* Keep empty bb only if this block immediately precedes EXIT and
> @@ -3500,6 +3502,11 @@
>                || !(single_pred_edge (bb)->flags & EDGE_FALLTHRU))))
>      return false;
>  
> +  /* Do not attempt to redirect complex edges.  */
> +  FOR_EACH_EDGE (e, ei, bb->preds)
> +    if (e->flags & EDGE_COMPLEX)
> +      return false;
> +
>    free_data_sets (bb);
>  
>    /* Do not delete BB if it has more than one successor.
> @@ -3518,9 +3525,6 @@
>    /* Redirect all non-fallthru edges to the next bb.  */
>    while (rescan_p)
>      {
> -      edge e;
> -      edge_iterator ei;
> -
>        rescan_p = false;
>  
>        FOR_EACH_EDGE (e, ei, bb->preds)
> @@ -5252,8 +5256,6 @@
>  void
>  sel_merge_blocks (basic_block a, basic_block b)
>  {
> -  gcc_assert (can_merge_blocks_p (a, b));
> -
>    sel_remove_empty_bb (b, true, false);
>    merge_blocks (a, b);
>  
> @@ -5298,6 +5300,7 @@
>    basic_block src;
>    int prev_max_uid;
>    rtx jump;
> +  edge redirected;
>  
>    latch_edge_p = (pipelining_p
>                    && current_loop_nest
> @@ -5305,10 +5308,11 @@
>  
>    src = e->src;
>    prev_max_uid = get_max_uid ();
> -  
> -  redirect_edge_and_branch (e, to);
> -  gcc_assert (last_added_blocks == NULL);
>  
> +  redirected = redirect_edge_and_branch (e, to);
> +
> +  gcc_assert (redirected && last_added_blocks == NULL);
> +
>    /* When we've redirected a latch edge, update the header.  */
>    if (latch_edge_p)
>      {
> Index: gcc/sel-sched-ir.h
> ===================================================================
> --- gcc/sel-sched-ir.h	(revision 141459)
> +++ gcc/sel-sched-ir.h	(working copy)
> @@ -1358,10 +1358,6 @@
>  
>        e2 = EDGE_SUCC (bb, 0);
>        bb = e2->dest;
> -      
> -      /* This couldn't happen inside a region.  */
> -      gcc_assert (! in_current_region_p (bb)
> -                  || (flags & SUCCS_OUT));
>      }
>    
>    /* Save the second edge for later checks.  */
> @@ -1584,7 +1580,6 @@
>  extern void sel_init_pipelining (void);
>  extern void sel_finish_pipelining (void);
>  extern void sel_sched_region (int);
> -extern void sel_find_rgns (void);
>  extern loop_p get_loop_nest_for_rgn (unsigned int);
>  extern bool considered_for_pipelining_p (struct loop *);
>  extern void make_region_from_loop_preheader (VEC(basic_block, heap) **);
> 
> Index: gcc/testsuite/gcc.target/ia64/20071210-2.c
> ===================================================================
> --- gcc/testsuite/gcc.target/ia64/20071210-2.c	(revision 0)
> +++ gcc/testsuite/gcc.target/ia64/20071210-2.c	(revision 0)
> @@ -0,0 +1,68 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Os -fselective-scheduling2" } */
> +
> +extern void abort (void);
> +
> +struct S
> +{
> +  int n1, n2, n3, n4;
> +};
> +
> +__attribute__((noinline)) struct S
> +foo (int x, int y, int z)
> +{
> +  if (x != 10 || y != 9 || z != 8)
> +    abort ();
> +  struct S s = { 1, 2, 3, 4 };
> +  return s;
> +}
> +
> +__attribute__((noinline)) void **
> +bar (void **u, int *v)
> +{
> +  void **w = u;
> +  int *s = v, x, y, z;
> +  void **p, **q;
> +  static void *l[] = { &&lab1, &&lab1, &&lab2, &&lab3, &&lab4 };
> +
> +  if (!u)
> +    return l;
> +
> +  q = *w++;
> +  goto *q;
> +lab2:
> +  p = q;
> +  q = *w++;
> +  x = s[2];
> +  y = s[1];
> +  z = s[0];
> +  s -= 1;
> +  struct S r = foo (x, y, z);
> +  s[3] = r.n1;
> +  s[2] = r.n2;
> +  s[1] = r.n3;
> +  s[0] = r.n4;
> +  goto *q;
> +lab3:
> +  p = q;
> +  q = *w++;
> +  s += 1;
> +  s[0] = 23;
> +lab1:
> +  goto *q;
> +lab4:
> +  return 0;
> +}
> +
> +int
> +main (void)
> +{
> +  void **u = bar ((void **) 0, (int *) 0);
> +  void *t[] = { u[2], u[4] };
> +  int s[] = { 7, 8, 9, 10, 11, 12 };
> +  if (bar (t, &s[1]) != (void **) 0
> +      || s[0] != 4 || s[1] != 3 || s[2] != 2 || s[3] != 1
> +      || s[4] != 11 || s[5] != 12)
> +    abort ();
> +  return 0;
> +}



More information about the Gcc-patches mailing list