------- 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