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 PR middle-end/80775, -O3 produces ice in group_case_labels_stmt


On Tue, 16 May 2017, Peter Bergner wrote:

> The test case in PR80775 exposes a problem in handling two separate
> case labels that lead to the same block that contains a call to
> __builtin_unreachable().   The current code handles the first label
> and deletes the associated edge/block, but trips up when we see the
> second case label that now points to a removed block.  This patch moves
> the deletion of the unreachable case statement to after the merging
> of consecutive case labels, which easily fixes the issue.  It also has
> a side benefit of reducing the number of calls to gimple_seq_unreachable_p()
> when we have consecutive case labels that point to unreachable blocks.
> 
> This bootstrapped and regtested with no regressions on both powerpc64le-linux
> and x86_64-linux.  Is this ok for trunk?

Ok.

Thanks,
Richard.

> Peter
> 
> gcc/
> 	PR middle-end/80775
> 	* tree-cfg.c: Move deletion of unreachable case statements to after
> 	the merging of consecutive case labels.
> 
> gcc/testsuite/
> 	PR middle-end/80775
> 	* gcc.dg/pr80775.c: New test.
> 
> Index: gcc/tree-cfg.c
> ===================================================================
> --- gcc/tree-cfg.c	(revision 248119)
> +++ gcc/tree-cfg.c	(working copy)
> @@ -1661,7 +1661,7 @@ void
>  group_case_labels_stmt (gswitch *stmt)
>  {
>    int old_size = gimple_switch_num_labels (stmt);
> -  int i, j, new_size = old_size;
> +  int i, j, base_index, new_size = old_size;
>    basic_block default_bb = NULL;
>  
>    default_bb = label_to_block (CASE_LABEL (gimple_switch_default_label (stmt)));
> @@ -1678,16 +1678,9 @@ group_case_labels_stmt (gswitch *stmt)
>        gcc_assert (base_case);
>        base_bb = label_to_block (CASE_LABEL (base_case));
>  
> -      /* Discard cases that have the same destination as the default case
> -	 or if their destination block is unreachable.  */
> -      if (base_bb == default_bb
> -	  || (EDGE_COUNT (base_bb->succs) == 0
> -	      && gimple_seq_unreachable_p (bb_seq (base_bb))))
> +      /* Discard cases that have the same destination as the default case.  */
> +      if (base_bb == default_bb)
>  	{
> -	  edge e;
> -	  if (base_bb != default_bb
> -	      && (e = find_edge (gimple_bb (stmt), base_bb)) != NULL)
> -	    remove_edge_and_dominated_blocks (e);
>  	  gimple_switch_set_label (stmt, i, NULL_TREE);
>  	  i++;
>  	  new_size--;
> @@ -1697,7 +1690,7 @@ group_case_labels_stmt (gswitch *stmt)
>        base_high = CASE_HIGH (base_case)
>  	  ? CASE_HIGH (base_case)
>  	  : CASE_LOW (base_case);
> -      i++;
> +      base_index = i++;
>  
>        /* Try to merge case labels.  Break out when we reach the end
>  	 of the label vector or when we cannot merge the next case
> @@ -1723,6 +1716,18 @@ group_case_labels_stmt (gswitch *stmt)
>  	  else
>  	    break;
>  	}
> +
> +      /* Discard cases that have an unreachable destination block.  */
> +      if (EDGE_COUNT (base_bb->succs) == 0
> +	  && gimple_seq_unreachable_p (bb_seq (base_bb)))
> +	{
> +	  edge base_edge = find_edge (gimple_bb (stmt), base_bb);
> +	  if (base_edge != NULL)
> +	    remove_edge_and_dominated_blocks (base_edge);
> +	  gimple_switch_set_label (stmt, base_index, NULL_TREE);
> +	  new_size--;
> +	  i++;
> +	}
>      }
>  
>    /* Compress the case labels in the label vector, and adjust the
> Index: gcc/testsuite/gcc.dg/pr80775.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/pr80775.c	(nonexistent)
> +++ gcc/testsuite/gcc.dg/pr80775.c	(working copy)
> @@ -0,0 +1,21 @@
> +/* PR middle-end/80775 ICE: -O3 produces ice in group_case_labels_stmt.  */
> +/* { dg-do compile }  */
> +/* { dg-options "-O3" }  */
> +
> +typedef struct { short a; } b;
> +b c[10];
> +int d, e, f, g, h;
> +int
> +i (void)
> +{
> +  f = 0;
> +  for (; f < e; f++) {
> +    switch (g) {
> +    case 1:
> +      d = 1;
> +    case 2:
> +      c[2 + f].a = 1;
> +    }
> +    h += c[f].a;
> +  }
> +}
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)


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