[PATCH][GIMPLE FE] Simplify middle-end changes

Richard Biener rguenther@suse.de
Wed Oct 26 08:48:00 GMT 2016


The following patch removes the partial support present for "pass list",
thereby simplifying the middle-end changes, isolating them to
execute_one_pass plus a field in struct function (plus the SSA name
allocation support).

Tested on x86_64-unknown-linux-gnu, a bootstrap is in progress.

Will push to GIT soon.

What is left is to add a dump modifier (thinking of -gimple) to guard
the dump changes that otherwise will break a lot of testsuite scans.
Another option would be to drop them for now (and require unit tests
to be manually converted from "dumpfile GIMPLE" to "FE GIMPLE").

Thanks,
Richard.

2016-10-26  Richard Biener  <rguenther@suse.de>

	c/
	* c-parser.c (c_parser_declaration_or_fndef): Adjust for GIMPLE FE
	start-with change.
	* gimple-parser.c (c_parser_gimple_pass_list_params): Remove.
	(c_parser_gimple_pass_list): Parse only startwith.

	* function.h (pass_startwith): Change to char *.
	(startwith): Remove redundant flag.
	* coretypes.h: Revert all branch changes.
	* cgraphunit.c: Likewise.
	* tree-pass.h: Likewise.
	* passes.c: Likewise.
	(execute_one_pass): Handle startwith solely here.
	* tree-ssanames.c (make_ssa_name_fn): Document extended interface.

	testsuite/
	* gcc.dg/gimplefe-12.c: Adjust startwith pass.
	* gcc.dg/gimplefe-13.c: Likewise.

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 9b51c48..542b83b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1487,8 +1487,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
   bool diagnosed_no_specs = false;
   location_t here = c_parser_peek_token (parser)->location;
   bool gimple_body_p = false;
-  opt_pass *pass = NULL;
-  bool startwith_p = false;
+  char *pass = NULL;
 
   if (static_assert_ok
       && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1581,7 +1580,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	{
 	  gimple_body_p = true;
 	  c_parser_consume_token (parser);
-	  c_parser_gimple_pass_list (parser, &pass, &startwith_p);
+	  c_parser_gimple_pass_list (parser, &pass);
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
 	}
@@ -2001,12 +2000,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 				       true, false, NULL, vNULL);
       store_parm_decls ();
 
-      if (pass)
-	{
-	  cfun->pass_startwith = pass;
-	  cfun->startwith = startwith_p;
-	}
-
       if (omp_declare_simd_clauses.exists ()
 	  || !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
 	c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
@@ -2018,6 +2011,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 
       if (gimple_body_p && flag_gimple)
 	{
+	  cfun->pass_startwith = pass;
 	  bool saved = in_late_binary_op;
 	  in_late_binary_op = true;
 	  c_parser_parse_gimple_body (parser);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 30e8d88..c19f417 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -66,7 +66,6 @@ static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
 static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
 								       location_t,
 								       struct c_expr);
-static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
 static void c_parser_gimple_declaration (c_parser *);
 static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
 static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
@@ -112,7 +111,12 @@ c_parser_parse_gimple_body (c_parser *parser)
   gimple_bind_set_body (bind_stmt, seq);
   gimple_seq_add_stmt (&body, bind_stmt);
   gimple_set_body (current_function_decl, body);
-  cfun->curr_properties = PROP_gimple_any;
+
+  /* While we have SSA names in the IL we do not have a CFG built yet
+     and PHIs are represented using a PHI internal function.  We do
+     have lowered control flow and exception handling (well, we do not
+     have parser support for EH yet).  */
+  cfun->curr_properties = PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh;
 
   return;
 }
@@ -931,8 +935,7 @@ c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
  */
 
 void
-c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
-			   bool *startwith_p)
+c_parser_gimple_pass_list (c_parser *parser, char **pass)
 {
   if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return;
@@ -946,11 +949,17 @@ c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
       c_parser_consume_token (parser);
       if (! strcmp (op, "startwith"))
 	{
-	  *pass = c_parser_gimple_pass_list_params (parser, pass);
-	  if (! *pass)
+	  if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	    return;
-
-	  *startwith_p = true;
+	  if (c_parser_next_token_is_not (parser, CPP_STRING))
+	    {
+	      error_at (c_parser_peek_token (parser)->location,
+			"expected pass name");
+	      return;
+	    }
+	  *pass = xstrdup (TREE_STRING_POINTER
+				(c_parser_peek_token (parser)->value));
+	  c_parser_consume_token (parser);
 	  if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
 	    return;
 	}
@@ -970,66 +979,6 @@ c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
   return;
 }
 
-/* Support function for c_parser_gimple_pass_list.  */
-
-static opt_pass *
-c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
-{
-  opt_pass *pass_start = NULL, *new_pass;
-  if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-    return NULL;
-
-  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
-    return NULL;
-
-  while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
-    {
-      if (c_parser_next_token_is (parser, CPP_EOF))
-	{
-	  error_at (c_parser_peek_token (parser)->location,
-		    "expected pass names");
-	  return NULL;
-	}
-
-      if (c_parser_next_token_is (parser, CPP_STRING))
-	{
-	  const char *name = NULL;
-	  name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
-	  c_parser_consume_token (parser);
-	  new_pass = g->get_passes ()->get_pass_by_name (name);
-
-	  if (! new_pass)
-	    {
-	      error_at (c_parser_peek_token (parser)->location,
-			"invalid pass name");
-	      parser->error = true;
-	      c_parser_consume_token (parser);
-	      return NULL;
-	    }
-	  if (*pass)
-	    {
-	      (*pass)->next = new_pass;
-	      (*pass) = (*pass)->next;
-	    }
-	  else
-	    {
-	      *pass = new_pass;
-	      pass_start = *pass;
-	    }
-	}
-      else if (c_parser_next_token_is (parser, CPP_COMMA))
-	c_parser_consume_token (parser);
-      else
-	{
-	  error_at (c_parser_peek_token (parser)->location,
-		    "invalid pass name");
-	  c_parser_consume_token (parser);
-	  return NULL;
-	}
-    }
-  return pass_start;
-}
-
 /* Parse gimple local declaration.
 
    declaration-specifiers:
diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
index d88d9e5..860695b 100644
--- a/gcc/c/gimple-parser.h
+++ b/gcc/c/gimple-parser.h
@@ -22,6 +22,6 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Gimple parsing functions.  */
 extern void c_parser_parse_gimple_body (c_parser *);
-extern void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+extern void c_parser_gimple_pass_list (c_parser *, char **);
 
 #endif
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 8c447f7..b1812b2 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1960,7 +1960,6 @@ cgraph_node::assemble_thunks_and_aliases (void)
 void
 cgraph_node::expand (void)
 {
-  bool startwith_p = true;
   location_t saved_loc;
 
   /* We ought to not compile any inline clones.  */
@@ -1999,7 +1998,7 @@ cgraph_node::expand (void)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p);
+  execute_pass_list (cfun, g->get_passes ()->all_passes);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -2052,8 +2051,7 @@ cgraph_node::expand (void)
   timevar_pop (TV_REST_OF_COMPILATION);
 
   /* Make sure that BE didn't give up on compiling.  */
-  if (!(flag_gimple && cfun->pass_startwith))  /* FIXME : for gimplefe custom_pass_list */
-    gcc_assert (TREE_ASM_WRITTEN (decl));
+  gcc_assert (TREE_ASM_WRITTEN (decl));
 
   if (cfun)
     pop_cfun ();
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index c0f22c9..869f858 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -85,7 +85,6 @@ typedef const union tree_node *const_tree;
 struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
-class opt_pass;
 
 /* Forward decls for leaf gimple subclasses (for individual gimple codes).
    Keep this in the same order as the corresponding codes in gimple.def.  */
@@ -353,8 +352,6 @@ typedef unsigned char uchar;
 #include "input.h"
 #include "is-a.h"
 #include "memory-block.h"
-#include "pass_manager.h"
-#include "tree-pass.h"
 #endif /* GENERATOR_FILE && !USED_FOR_TARGET */
 
 #endif /* coretypes.h */
diff --git a/gcc/function.h b/gcc/function.h
index 7775c08..600c6a0 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -228,18 +228,15 @@ struct GTY(()) function {
   /* GIMPLE body for this function.  */
   gimple_seq gimple_body;
 
-  /* GIMPLEFE pass to start with */
-  opt_pass *pass_startwith;
-
-  /* Startwith flag */
-  bool startwith;
-
   /* SSA and dataflow information.  */
   struct gimple_df *gimple_df;
 
   /* The loops in this function.  */
   struct loops *x_current_loops;
 
+  /* Filled by the GIMPLE FE, pass to start compilation with.  */
+  char *pass_startwith;
+
   /* The stack usage of this function.  */
   struct stack_usage *su;
 
diff --git a/gcc/passes.c b/gcc/passes.c
index ec1902a..61eea90 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1686,13 +1686,12 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data)
    call CALLBACK on the current function.
    This function is global so that plugins can use it.  */
 void
-do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
-			  void *data, void *flag)
+do_per_function_toporder (void (*callback) (function *, void *data), void *data)
 {
   int i;
 
   if (current_function_decl)
-    callback (cfun, data, flag);
+    callback (cfun, data);
   else
     {
       cgraph_node_hook_list *hook;
@@ -1727,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data, void *flag),
 	    {
 	      struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
 	      push_cfun (fn);
-	      callback (fn, data, flag);
+	      callback (fn, data);
 	      pop_cfun ();
 	    }
 	}
@@ -2278,18 +2277,8 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status)
 /* Execute PASS. */
 
 bool
-execute_one_pass (opt_pass *pass, bool startwith_p)
+execute_one_pass (opt_pass *pass)
 {
-  /* For skipping passes until startwith pass */
-  if (cfun && startwith_p && cfun->startwith)
-    {
-      if (!strcmp (pass->name, cfun->pass_startwith->name)
-	  || !strcmp (pass->name, "*clean_state"))
-	cfun->startwith = false;
-      else
-	return true;
-    }
-
   unsigned int todo_after = 0;
 
   bool gate_status;
@@ -2324,6 +2313,35 @@ execute_one_pass (opt_pass *pass, bool startwith_p)
       return false;
     }
 
+  /* For skipping passes until startwith pass */
+  if (cfun
+      && cfun->pass_startwith
+      /* But we can't skip the lowering phase yet -- ideally we'd
+         drive that phase fully via properties.  */
+      && (cfun->curr_properties & PROP_ssa))
+    {
+      size_t namelen = strlen (pass->name);
+      if (! strncmp (pass->name, cfun->pass_startwith, namelen))
+	{
+	  /* The following supports starting with the Nth invocation
+	     of a pass (where N does not necessarily is equal to the
+	     dump file suffix).  */
+	  if (cfun->pass_startwith[namelen] == '\0'
+	      || (cfun->pass_startwith[namelen] == '1'
+		  && cfun->pass_startwith[namelen + 1] == '\0'))
+	    cfun->pass_startwith = NULL;
+	  else
+	    {
+	      if (cfun->pass_startwith[namelen + 1] != '\0')
+		return true;
+	      --cfun->pass_startwith[namelen];
+	      return true;
+	    }
+	}
+      else
+	return true;
+    }
+
   /* Pass execution event trigger: useful to identify passes being
      executed.  */
   invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
@@ -2429,7 +2447,7 @@ execute_one_pass (opt_pass *pass, bool startwith_p)
 }
 
 static void
-execute_pass_list_1 (opt_pass *pass, bool startwith_p)
+execute_pass_list_1 (opt_pass *pass)
 {
   do
     {
@@ -2438,23 +2456,18 @@ execute_pass_list_1 (opt_pass *pass, bool startwith_p)
 
       if (cfun == NULL)
 	return;
-      if (execute_one_pass (pass, startwith_p) && pass->sub)
-	execute_pass_list_1 (pass->sub, startwith_p);
+      if (execute_one_pass (pass) && pass->sub)
+	execute_pass_list_1 (pass->sub);
       pass = pass->next;
     }
   while (pass);
 }
 
 void
-execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p)
+execute_pass_list (function *fn, opt_pass *pass)
 {
   gcc_assert (fn == cfun);
-
-  if (startwith_p)
-    execute_pass_list_1 (pass, *startwith_p);
-  else
-    execute_pass_list_1 (pass, false);
-
+  execute_pass_list_1 (pass);
   if (cfun && fn->cfg)
     {
       free_dominance_info (CDI_DOMINATORS);
@@ -2784,22 +2797,19 @@ ipa_read_optimization_summaries (void)
 void
 execute_ipa_pass_list (opt_pass *pass)
 {
-  bool startwith_p = false;
   do
     {
       gcc_assert (!current_function_decl);
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
-      if (!strcmp (pass->name, "opt_local_passes"))
-	startwith_p = true;
-      if (execute_one_pass (pass, startwith_p) && pass->sub)
+      if (execute_one_pass (pass) && pass->sub)
 	{
 	  if (pass->sub->type == GIMPLE_PASS)
 	    {
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL);
-	      do_per_function_toporder ((void (*)(function *, void *, void *))
+	      do_per_function_toporder ((void (*)(function *, void *))
 					  execute_pass_list,
-					pass->sub, &startwith_p);
+					pass->sub);
 	      invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL);
 	    }
 	  else if (pass->sub->type == SIMPLE_IPA_PASS
diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c
index cbaf8a6..2863228 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-12.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-12.c
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-fgimple" } */
+/* { dg-options "-O -fgimple" } */
 
-void __GIMPLE (startwith ("tree-ccp1")) foo ()
+void __GIMPLE (startwith ("ccp1")) foo ()
 {
   int a;
   int b;
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c
index c0da9fa..f0af761 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-13.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-fgimple" } */
+/* { dg-options "-O -fgimple" } */
 
-void __GIMPLE (startwith ("tree-dse1")) foo ()
+void __GIMPLE (startwith ("dse2")) foo ()
 {
   int a;
 
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 93124b1..fce9839 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -622,9 +622,8 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
 /* Current optimization pass.  */
 extern opt_pass *current_pass;
 
-extern bool execute_one_pass (opt_pass *, bool startwith_p = false);
-extern void execute_pass_list (function *, opt_pass *,
-			       bool *startwith_p = NULL);
+extern bool execute_one_pass (opt_pass *);
+extern void execute_pass_list (function *, opt_pass *);
 extern void execute_ipa_pass_list (opt_pass *);
 extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
 extern void execute_all_ipa_transforms (void);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 51ec80a..bd5d10a 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -252,7 +252,8 @@ flush_ssaname_freelist (void)
 /* Return an SSA_NAME node for variable VAR defined in statement STMT
    in function FN.  STMT may be an empty statement for artificial
    references (e.g., default definitions created when a variable is
-   used without a preceding definition).  */
+   used without a preceding definition).  If VERISON is not zero then
+   allocate the SSA name with that version.  */
 
 tree
 make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
@@ -266,7 +267,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
 	      || TREE_CODE (var) == RESULT_DECL
 	      || (TYPE_P (var) && is_gimple_reg_type (var)));
 
-  /* parsing ssa names with versions.	*/
+  /* Get the specified SSA name version.  */
   if (version != 0)
     {
       t = make_node (SSA_NAME);



More information about the Gcc-patches mailing list