------- Comment #6 from abel at gcc dot gnu dot org 2010-02-16 15:43 ------- 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.
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; } -- abel at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |abel at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42859