------- Comment #7 from rguenth at gcc dot gnu dot org  2010-02-22 10:54 -------
(In reply to comment #6)
> How about the below patch?  It fixes all testcases for me.  I'm not sure
> whether it makes sense to filter duplicate labels this late, but I don't know
> how to do this earlier, as catches seem to be lowering independently of each
> other.
Looks sensible, though unreachable block removal should be conditional on
us removing an edge, not on lowering anything.

> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index 2cb334f..c18b807 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "flags.h"
>  #include "function.h"
>  #include "except.h"
> +#include "pointer-set.h"
>  #include "tree-flow.h"
>  #include "tree-dump.h"
>  #include "tree-inline.h"
> @@ -3063,6 +3064,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>         eh_catch c;
>         edge_iterator ei;
>         edge e;
> +       struct pointer_set_t *seen_values = pointer_set_create ();
> 
>         /* Collect the labels for a switch.  Zero the post_landing_pad
>            field becase we'll no longer have anything keeping these labels
> @@ -3071,6 +3073,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>         for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
>           {
>             tree tp_node, flt_node, lab = c->label;
> +           bool have_label = false;
> 
>             c->label = NULL;
>             tp_node = c->type_list;
> @@ -3083,14 +3086,26 @@ lower_eh_dispatch (basic_block src, gimple stmt)
>               }
>             do
>               {
> -               tree t = build3 (CASE_LABEL_EXPR, void_type_node,
> -                                TREE_VALUE (flt_node), NULL, lab);
> -               VEC_safe_push (tree, heap, labels, t);
> +               /* Filter out duplicate labels that arise when this handler 
> +                  is shadowed by an earlier one.  When no labels are 
> +                  attached to the handler anymore, we remove 
> +                  the corresponding edge and then we delete unreachable 
> +                  blocks at the end of this pass.  */
> +               if (! pointer_set_contains (seen_values, TREE_VALUE
> (flt_node)))
> +                 {
> +                   tree t = build3 (CASE_LABEL_EXPR, void_type_node,
> +                                    TREE_VALUE (flt_node), NULL, lab);
> +                   VEC_safe_push (tree, heap, labels, t);
> +                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
> +                   have_label = true;
> +                 }
> 
>                 tp_node = TREE_CHAIN (tp_node);
>                 flt_node = TREE_CHAIN (flt_node);
>               }
>             while (tp_node);
> +           if (! have_label)
> +             remove_edge (find_edge (src, label_to_block (lab)));
>           }
> 
>         /* Clean up the edge flags.  */
> @@ -3132,6 +3147,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
> 
>             VEC_free (tree, heap, labels);
>           }
> +       pointer_set_destroy (seen_values);
>        }
>        break;
> 
> @@ -3185,6 +3201,8 @@ execute_lower_eh_dispatch (void)
>         }
>      }
> 
> +  if (any_rewritten)
> +    delete_unreachable_blocks ();
>    return any_rewritten ? TODO_update_ssa_only_virtuals : 0;
>  }
> 
> 


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42859

Reply via email to