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] " : 
"");

Reply via email to