This fixes parsing and dumping of switch stmts as well as dumping of PHI nodes in case a src BB has a label. It also fixes PHI lowering (the gsi_remove already does the gsi_next).
Tested on x86_64-unknown-linux-gnu. New testcase is /* { dg-do run } */ /* { dg-options "-O -fgimple" } */ int __GIMPLE () main (int argc, char * * argv) { int a; bb_2: switch (argc_2(D)) {default: L2; case 1: L0; case 2: L1; } L0: a_4 = 0; goto bb_6; L1: a_3 = 3; goto bb_6; L2: a_5 = -1; bb_6: a_1 = __PHI (L0: a_4, L1: a_3, L2: a_5); return a_1; } Richard. 2016-10-26 Richard Biener <rguent...@suse.de> c/ * gimple-parser.c (c_parser_gimple_switch_stmt): Fix. * gimple-pretty-print.c (dump_gimple_switch): Add missing semicolon. (dump_gimple_phi): Dump BB label instead of artificial one. Add missing semicolon. * tree-cfg.c (lower_phi_internal_fn): Properly do stmt removal. (dump_function_to_file): Dump __GIMPLE (). * gcc.dg/gimplefe-14.c: New testcase. diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index a1e8988..e9e3aae 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -1201,13 +1201,21 @@ c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - label = create_artificial_label (loc); - case_label = build_case_label (exp1.value, NULL_TREE, - label); - labels.safe_push (case_label); - gimple_seq_add_stmt (&switch_body, - gimple_build_label - (CASE_LABEL (case_label))); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + label = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + tree decl = lookup_label_for_goto (loc, label); + case_label = build_case_label (exp1.value, NULL_TREE, + decl); + labels.safe_push (case_label); + if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return; + } + else if (! c_parser_require (parser, CPP_NAME, + "expected label")) + return; } else if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<:%>")) @@ -1220,12 +1228,20 @@ c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - default_label = build_case_label (NULL_TREE, NULL_TREE, - create_artificial_label - (UNKNOWN_LOCATION)); - gimple_seq_add_stmt (&switch_body, - gimple_build_label - (CASE_LABEL (default_label))); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + label = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + tree decl = lookup_label_for_goto (loc, label); + default_label = build_case_label (NULL_TREE, NULL_TREE, + decl); + if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return; + } + else if (! c_parser_require (parser, CPP_NAME, + "expected label")) + return; } else if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<:%>")) diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 9914adf..9d47f7f 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -909,7 +909,7 @@ dump_gimple_switch (pretty_printer *buffer, gswitch *gs, int spc, } } if (flags & TDF_GIMPLE) - pp_right_brace (buffer); + pp_string (buffer, "; }"); else pp_greater (buffer); } @@ -2057,8 +2057,16 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment, dump_location (buffer, gimple_phi_arg_location (phi, i)); if (flags & TDF_GIMPLE) { - pp_string (buffer, "bb_"); - pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index); + basic_block src = gimple_phi_arg_edge (phi, i)->src; + gimple *stmt = first_stmt (src); + if (!stmt || gimple_code (stmt) != GIMPLE_LABEL) + { + pp_string (buffer, "bb_"); + pp_decimal_int (buffer, src->index); + } + else + dump_generic_node (buffer, gimple_label_label (as_a <glabel *> (stmt)), 0, flags, + false); pp_string (buffer, ": "); } dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags, @@ -2073,7 +2081,7 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int spc, bool comment, pp_string (buffer, ", "); } if (flags & TDF_GIMPLE) - pp_right_paren (buffer); + pp_string (buffer, ");"); else pp_greater (buffer); } diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 11bf6d6..7d7763d 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -361,33 +361,32 @@ lower_phi_internal_fn () /* After edge creation, handle __PHI function from GIMPLE FE. */ FOR_EACH_BB_FN (bb, cfun) { - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) { stmt = gsi_stmt (gsi); - if (gimple_code (stmt) != GIMPLE_CALL) - continue; - - if (gimple_call_internal_p (stmt) && - gimple_call_internal_fn (stmt) == IFN_PHI) + if (! gimple_call_internal_p (stmt, IFN_PHI)) { - gsi_remove (&gsi, true); - unsigned int i; - lhs = gimple_call_lhs (stmt); - phi_node = create_phi_node (lhs, bb); + gsi_next (&gsi); + continue; + } + + lhs = gimple_call_lhs (stmt); + phi_node = create_phi_node (lhs, bb); - /* Add arguments to the PHI node. */ - for (i = 0; i < gimple_call_num_args (stmt); ++i) + /* Add arguments to the PHI node. */ + for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i) + { + tree arg = gimple_call_arg (stmt, i); + if (TREE_CODE (arg) == LABEL_DECL) + pred = label_to_block (arg); + else { - tree arg = gimple_call_arg (stmt, i); - if (TREE_CODE (arg) == LABEL_DECL) - pred = label_to_block (arg); - else - { - edge e = find_edge (pred, bb); - add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION); - } + edge e = find_edge (pred, bb); + add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION); } } + + gsi_remove (&gsi, true); } } } @@ -7552,7 +7551,7 @@ dump_function_to_file (tree fndecl, FILE *file, int flags) { print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), dump_flags | TDF_SLIM); - fprintf (file, "\n%s (", function_name (fun)); + fprintf (file, " __GIMPLE ()\n%s (", function_name (fun)); } else fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");