This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add warnings about GENERIC code-gen deficiencies in genmatch


This adds warnings when a pattern requires inputs to have no side-effects
to match for GENERIC code-gen.  It also improves on some obvious cases
like escapes through predicates or a few special cases such as
TREE_REAL_CST.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2015-07-30  Richard Biener  <rguenther@suse.de>

	* genmatch.c (verbose): New global.
	(warning_at): Add overload with source_location.
	(capture_info::capture_info): Add bool whether generating gimple
	or generic.  Add gimple member.
	(capture_info::cinfo): Add capture member.
	(capture_info::walk_match): Record capture.  Warn on
	non-captured leafs.
	(capture_info::walk_c_expr): Add more fragments captures cannot
	escape through.  Warn on escaped captures.
	(dt_simplify::gen_1): Warn on operands we force to have no
	side-effects.
	(main): Initialize verbose.
	* match.pd: Add integer_nonzerop and HONOR_NANS predicates.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 226348)
+++ gcc/genmatch.c	(working copy)
@@ -43,6 +43,12 @@ void ggc_free (void *)
 }
 
 
+/* Global state.  */
+
+/* Verboseness.  0 is quiet, 1 adds some warnings, 2 is for debugging.  */
+unsigned verbose;
+
+
 /* libccp helpers.  */
 
 static struct line_maps *line_table;
@@ -126,6 +132,18 @@ warning_at (const cpp_token *tk, const c
   va_end (ap);
 }
 
+static void
+#if GCC_VERSION >= 4001
+__attribute__((format (printf, 2, 3)))
+#endif
+warning_at (source_location loc, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap, msg);
+  error_cb (NULL, CPP_DL_WARNING, 0, loc, 0, msg, &ap);
+  va_end (ap);
+}
+
 /* Like fprintf, but print INDENT spaces at the beginning.  */
 
 static void
@@ -1599,7 +1630,7 @@ decision_tree::print (FILE *f)
 
 struct capture_info
 {
-  capture_info (simplify *s, operand *);
+  capture_info (simplify *s, operand *, bool);
   void walk_match (operand *o, unsigned toplevel_arg, bool, bool);
   bool walk_result (operand *o, bool, operand *);
   void walk_c_expr (c_expr *);
@@ -1614,16 +1645,20 @@ struct capture_info
       unsigned long toplevel_msk;
       int result_use_count;
       unsigned same_as;
+      capture *c;
     };
 
   auto_vec<cinfo> info;
   unsigned long force_no_side_effects;
+  bool gimple;
 };
 
 /* Analyze captures in S.  */
 
-capture_info::capture_info (simplify *s, operand *result)
+capture_info::capture_info (simplify *s, operand *result, bool gimple_)
 {
+  gimple = gimple_;
+
   expr *e;
   if (s->kind == simplify::MATCH)
     {
@@ -1661,6 +1696,8 @@ capture_info::walk_match (operand *o, un
       info[where].toplevel_msk |= 1 << toplevel_arg;
       info[where].force_no_side_effects_p |= conditional_p;
       info[where].cond_expr_cond_p |= cond_expr_cond_p;
+      if (!info[where].c)
+	info[where].c = c;
       if (!c->what)
 	return;
       /* Recurse to exprs and captures.  */
@@ -1710,6 +1747,10 @@ capture_info::walk_match (operand *o, un
     {
       /* Mark non-captured leafs toplevel arg for checking.  */
       force_no_side_effects |= 1 << toplevel_arg;
+      if (verbose >= 1
+	  && !gimple)
+	warning_at (o->location,
+		    "forcing no side-effects on possibly lost leaf");
     }
   else
     gcc_unreachable ();
@@ -1801,15 +1842,25 @@ capture_info::walk_result (operand *o, b
 void
 capture_info::walk_c_expr (c_expr *e)
 {
-  /* Give up for C exprs mentioning captures not inside TREE_TYPE ().  */
+  /* Give up for C exprs mentioning captures not inside TREE_TYPE,
+     TREE_REAL_CST, TREE_CODE or a predicate where they cannot
+     really escape through.  */
   unsigned p_depth = 0;
   for (unsigned i = 0; i < e->code.length (); ++i)
     {
       const cpp_token *t = &e->code[i];
       const cpp_token *n = i < e->code.length () - 1 ? &e->code[i+1] : NULL;
+      id_base *id;
       if (t->type == CPP_NAME
-	  && strcmp ((const char *)CPP_HASHNODE
-		       (t->val.node.node)->ident.str, "TREE_TYPE") == 0
+	  && (strcmp ((const char *)CPP_HASHNODE
+		      (t->val.node.node)->ident.str, "TREE_TYPE") == 0
+	      || strcmp ((const char *)CPP_HASHNODE
+			 (t->val.node.node)->ident.str, "TREE_CODE") == 0
+	      || strcmp ((const char *)CPP_HASHNODE
+			 (t->val.node.node)->ident.str, "TREE_REAL_CST") == 0
+	      || ((id = get_operator ((const char *)CPP_HASHNODE
+				      (t->val.node.node)->ident.str))
+		  && is_a <predicate_id *> (id)))
 	  && n->type == CPP_OPEN_PAREN)
 	p_depth++;
       else if (t->type == CPP_CLOSE_PAREN
@@ -1828,6 +1879,9 @@ capture_info::walk_c_expr (c_expr *e)
 	    id = (const char *)CPP_HASHNODE (n->val.node.node)->ident.str;
 	  unsigned where = *e->capture_ids->get(id);
 	  info[info[where].same_as].force_no_side_effects_p = true;
+	  if (verbose >= 1
+	      && !gimple)
+	    warning_at (t, "capture escapes");
 	}
     }
 }
@@ -2662,25 +2744,37 @@ dt_simplify::gen_1 (FILE *f, int indent,
 
   /* Analyze captures and perform early-outs on the incoming arguments
      that cover cases we cannot handle.  */
-  capture_info cinfo (s, result);
+  capture_info cinfo (s, result, gimple);
   if (s->kind == simplify::SIMPLIFY)
     {
       if (!gimple)
 	{
 	  for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i)
 	    if (cinfo.force_no_side_effects & (1 << i))
-	      fprintf_indent (f, indent,
-			      "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n",
-			      i);
+	      {
+		fprintf_indent (f, indent,
+				"if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n",
+				i);
+		if (verbose >= 1)
+		  warning_at (as_a <expr *> (s->match)->ops[i]->location,
+			      "forcing toplevel operand to have no "
+			      "side-effects");
+	      }
 	  for (int i = 0; i <= s->capture_max; ++i)
 	    if (cinfo.info[i].cse_p)
 	      ;
 	    else if (cinfo.info[i].force_no_side_effects_p
 		     && (cinfo.info[i].toplevel_msk
 			 & cinfo.force_no_side_effects) == 0)
-	      fprintf_indent (f, indent,
-			      "if (TREE_SIDE_EFFECTS (captures[%d])) "
-			      "return NULL_TREE;\n", i);
+	      {
+		fprintf_indent (f, indent,
+				"if (TREE_SIDE_EFFECTS (captures[%d])) "
+				"return NULL_TREE;\n", i);
+		if (verbose >= 1)
+		  warning_at (cinfo.info[i].c->location,
+			      "forcing captured operand to have no "
+			      "side-effects");
+	      }
 	    else if ((cinfo.info[i].toplevel_msk
 		      & cinfo.force_no_side_effects) != 0)
 	      /* Mark capture as having no side-effects if we had to verify
@@ -4165,7 +4259,6 @@ main (int argc, char **argv)
     return 1;
 
   bool gimple = true;
-  bool verbose = false;
   char *input = argv[argc-1];
   for (int i = 1; i < argc - 1; ++i)
     {
@@ -4174,11 +4267,13 @@ main (int argc, char **argv)
       else if (strcmp (argv[i], "--generic") == 0)
 	gimple = false;
       else if (strcmp (argv[i], "-v") == 0)
-	verbose = true;
+	verbose = 1;
+      else if (strcmp (argv[i], "-vv") == 0)
+	verbose = 2;
       else
 	{
 	  fprintf (stderr, "Usage: genmatch "
-		   "[--gimple] [--generic] [-v] input\n");
+		   "[--gimple] [--generic] [-v[v]] input\n");
 	  return 1;
 	}
     }
@@ -4235,15 +4330,15 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVE
       predicate_id *pred = p.user_predicates[i];
       lower (pred->matchers, gimple);
 
-      if (verbose)
+      if (verbose == 2)
 	for (unsigned i = 0; i < pred->matchers.length (); ++i)
-	  print_matches (pred->matchers[i]);
+	  print_matches (pred->matchers[i]);
 
       decision_tree dt;
       for (unsigned i = 0; i < pred->matchers.length (); ++i)
 	dt.insert (pred->matchers[i], i);
 
-      if (verbose)
+      if (verbose == 2)
 	dt.print (stderr);
 
       write_predicate (stdout, pred, dt, gimple);
@@ -4252,15 +4347,15 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVE
   /* Lower the main simplifiers and generate code for them.  */
   lower (p.simplifiers, gimple);
 
-  if (verbose)
+  if (verbose == 2)
     for (unsigned i = 0; i < p.simplifiers.length (); ++i)
-      print_matches (p.simplifiers[i]);
+      print_matches (p.simplifiers[i]);
 
   decision_tree dt;
   for (unsigned i = 0; i < p.simplifiers.length (); ++i)
     dt.insert (p.simplifiers[i], i);
 
-  if (verbose)
+  if (verbose == 2)
     dt.print (stderr);
 
   if (gimple)
Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 226348)
+++ gcc/match.pd	(working copy)
@@ -26,11 +26,12 @@ along with GCC; see the file COPYING3.
 /* Generic tree predicates we inherit.  */
 (define_predicates
    integer_onep integer_zerop integer_all_onesp integer_minus_onep
-   integer_each_onep integer_truep
+   integer_each_onep integer_truep integer_nonzerop
    real_zerop real_onep real_minus_onep
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
-   integer_pow2p)
+   integer_pow2p
+   HONOR_NANS)
 
 /* Operator lists.  */
 (define_operator_list tcc_comparison


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]