diff mbox

[GIMPLE,FE] Fix parsing of switch stmts

Message ID alpine.LSU.2.11.1610261517530.5294@t29.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Oct. 26, 2016, 1:20 p.m. UTC
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  <rguenther@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 mbox

Patch

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