]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/genmatch.c
PR tree-optimization/90626 - fold strcmp(a, b) == 0 to zero when one string length...
[thirdparty/gcc.git] / gcc / genmatch.c
index 5715dd16f550733882c2bdc203d9d07000c68a6a..7b9b09c7d8bbceb06410b91312d0695874cad96c 100644 (file)
@@ -1,7 +1,7 @@
 /* Generate pattern matching and transform code shared between
    GENERIC and GIMPLE folding code from match-and-simplify description.
 
-   Copyright (C) 2014-2018 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
    Contributed by Richard Biener <rguenther@suse.de>
    and Prathamesh Kulkarni  <bilbotheelffriend@gmail.com>
 
@@ -53,7 +53,7 @@ unsigned verbose;
 static struct line_maps *line_table;
 
 /* The rich_location class within libcpp requires a way to expand
-   source_location instances, and relies on the client code
+   location_t instances, and relies on the client code
    providing a symbol named
      linemap_client_expand_location_to_spelling_point
    to do this.
@@ -61,7 +61,7 @@ static struct line_maps *line_table;
    This is the implementation for genmatch.  */
 
 expanded_location
-linemap_client_expand_location_to_spelling_point (source_location loc,
+linemap_client_expand_location_to_spelling_point (location_t loc,
                                                  enum location_aspect)
 {
   const struct line_map_ordinary *map;
@@ -73,11 +73,12 @@ static bool
 #if GCC_VERSION >= 4001
 __attribute__((format (printf, 5, 0)))
 #endif
-error_cb (cpp_reader *, int errtype, int, rich_location *richloc,
-         const char *msg, va_list *ap)
+diagnostic_cb (cpp_reader *, enum cpp_diagnostic_level errtype,
+              enum cpp_warning_reason, rich_location *richloc,
+              const char *msg, va_list *ap)
 {
   const line_map_ordinary *map;
-  source_location location = richloc->get_loc ();
+  location_t location = richloc->get_loc ();
   linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map);
   expanded_location loc = linemap_expand_location (line_table, map, location);
   fprintf (stderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column,
@@ -122,7 +123,7 @@ fatal_at (const cpp_token *tk, const char *msg, ...)
   rich_location richloc (line_table, tk->src_loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
+  diagnostic_cb (NULL, CPP_DL_FATAL, CPP_W_NONE, &richloc, msg, &ap);
   va_end (ap);
 }
 
@@ -130,12 +131,12 @@ static void
 #if GCC_VERSION >= 4001
 __attribute__((format (printf, 2, 3)))
 #endif
-fatal_at (source_location loc, const char *msg, ...)
+fatal_at (location_t loc, const char *msg, ...)
 {
   rich_location richloc (line_table, loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
+  diagnostic_cb (NULL, CPP_DL_FATAL, CPP_W_NONE, &richloc, msg, &ap);
   va_end (ap);
 }
 
@@ -148,7 +149,7 @@ warning_at (const cpp_token *tk, const char *msg, ...)
   rich_location richloc (line_table, tk->src_loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
+  diagnostic_cb (NULL, CPP_DL_WARNING, CPP_W_NONE, &richloc, msg, &ap);
   va_end (ap);
 }
 
@@ -156,12 +157,12 @@ static void
 #if GCC_VERSION >= 4001
 __attribute__((format (printf, 2, 3)))
 #endif
-warning_at (source_location loc, const char *msg, ...)
+warning_at (location_t loc, const char *msg, ...)
 {
   rich_location richloc (line_table, loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
+  diagnostic_cb (NULL, CPP_DL_WARNING, CPP_W_NONE, &richloc, msg, &ap);
   va_end (ap);
 }
 
@@ -183,8 +184,8 @@ fprintf_indent (FILE *f, unsigned int indent, const char *format, ...)
 }
 
 static void
-output_line_directive (FILE *f, source_location location,
-                      bool dumpfile = false)
+output_line_directive (FILE *f, location_t location,
+                      bool dumpfile = false, bool fnargs = false)
 {
   const line_map_ordinary *map;
   linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map);
@@ -202,7 +203,11 @@ output_line_directive (FILE *f, source_location location,
        file = loc.file;
       else
        ++file;
-      fprintf (f, "%s:%d", file, loc.line);
+
+      if (fnargs)
+       fprintf (f, "\"%s\", %d", file, loc.line);
+      else
+       fprintf (f, "%s:%d", file, loc.line);
     }
   else
     /* Other gen programs really output line directives here, at least for
@@ -662,10 +667,10 @@ struct capture_info;
 
 struct operand {
   enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR, OP_IF, OP_WITH };
-  operand (enum op_type type_, source_location loc_)
+  operand (enum op_type type_, location_t loc_)
     : type (type_), location (loc_) {}
   enum op_type type;
-  source_location location;
+  location_t location;
   virtual void gen_transform (FILE *, int, const char *, bool, int,
                              const char *, capture_info *,
                              dt_operand ** = 0,
@@ -677,7 +682,7 @@ struct operand {
 
 struct predicate : public operand
 {
-  predicate (predicate_id *p_, source_location loc)
+  predicate (predicate_id *p_, location_t loc)
     : operand (OP_PREDICATE, loc), p (p_) {}
   predicate_id *p;
 };
@@ -687,7 +692,7 @@ struct predicate : public operand
 
 struct expr : public operand
 {
-  expr (id_base *operation_, source_location loc, bool is_commutative_ = false)
+  expr (id_base *operation_, location_t loc, bool is_commutative_ = false)
     : operand (OP_EXPR, loc), operation (operation_),
       ops (vNULL), expr_type (NULL), is_commutative (is_commutative_),
       is_generic (false), force_single_use (false) {}
@@ -728,7 +733,7 @@ struct c_expr : public operand
     id_tab (const char *id_, const char *oper_): id (id_), oper (oper_) {}
   };
 
-  c_expr (cpp_reader *r_, source_location loc,
+  c_expr (cpp_reader *r_, location_t loc,
          vec<cpp_token> code_, unsigned nr_stmts_,
          vec<id_tab> ids_, cid_map_t *capture_ids_)
     : operand (OP_C_EXPR, loc), r (r_), code (code_),
@@ -750,7 +755,7 @@ struct c_expr : public operand
 
 struct capture : public operand
 {
-  capture (source_location loc, unsigned where_, operand *what_, bool value_)
+  capture (location_t loc, unsigned where_, operand *what_, bool value_)
       : operand (OP_CAPTURE, loc), where (where_), value_match (value_),
         what (what_) {}
   /* Identifier index for the value.  */
@@ -770,7 +775,7 @@ struct capture : public operand
 
 struct if_expr : public operand
 {
-  if_expr (source_location loc)
+  if_expr (location_t loc)
     : operand (OP_IF, loc), cond (NULL), trueexpr (NULL), falseexpr (NULL) {}
   c_expr *cond;
   operand *trueexpr;
@@ -781,7 +786,7 @@ struct if_expr : public operand
 
 struct with_expr : public operand
 {
-  with_expr (source_location loc)
+  with_expr (location_t loc)
     : operand (OP_WITH, loc), with (NULL), subexpr (NULL) {}
   c_expr *with;
   operand *subexpr;
@@ -1792,13 +1797,13 @@ decision_tree::find_node (vec<dt_node *>& ops, dt_node *p)
            {
              if (verbose >= 1)
                {
-                 source_location p_loc = 0;
+                 location_t p_loc = 0;
                  if (p->type == dt_node::DT_OPERAND)
                    p_loc = as_a <dt_operand *> (p)->op->location;
-                 source_location op_loc = 0;
+                 location_t op_loc = 0;
                  if (ops[i]->type == dt_node::DT_OPERAND)
                    op_loc = as_a <dt_operand *> (ops[i])->op->location;
-                 source_location true_loc = 0;
+                 location_t true_loc = 0;
                  true_loc = true_node->op->location;
                  warning_at (p_loc,
                              "failed to merge decision tree node");
@@ -2370,6 +2375,18 @@ get_operand_type (id_base *op, unsigned pos,
   else if (*op == COND_EXPR
           && pos == 0)
     return "boolean_type_node";
+  else if (strncmp (op->id, "CFN_COND_", 9) == 0)
+    {
+      /* IFN_COND_* operands 1 and later by default have the same type
+        as the result.  The type of operand 0 needs to be specified
+        explicitly.  */
+      if (pos > 0 && expr_type)
+       return expr_type;
+      else if (pos > 0 && in_type)
+       return in_type;
+      else
+       return NULL;
+    }
   else
     {
       /* Otherwise all types should match - choose one in order of
@@ -2429,7 +2446,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
       in_type = NULL;
     }
   else if (*opr == COND_EXPR
-          || *opr == VEC_COND_EXPR)
+          || *opr == VEC_COND_EXPR
+          || strncmp (opr->id, "CFN_COND_", 9) == 0)
     {
       /* Conditions are of the same type as their first alternative.  */
       sprintf (optype, "TREE_TYPE (ops%d[1])", depth);
@@ -2484,8 +2502,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
       /* ???  Building a stmt can fail for various reasons here, seq being
          NULL or the stmt referencing SSA names occuring in abnormal PHIs.
         So if we fail here we should continue matching other patterns.  */
-      fprintf_indent (f, indent, "gimple_match_op tem_op (%s, %s",
-                     opr_name, type);
+      fprintf_indent (f, indent, "gimple_match_op tem_op "
+                     "(res_op->cond.any_else (), %s, %s", opr_name, type);
       for (unsigned i = 0; i < ops.length (); ++i)
        fprintf (f, ", ops%d[%u]", depth, i);
       fprintf (f, ");\n");
@@ -2735,12 +2753,14 @@ dt_operand::gen_match_op (FILE *f, int indent, const char *opname, bool)
   char match_opname[20];
   match_dop->get_name (match_opname);
   if (value_match)
-    fprintf_indent (f, indent, "if (%s == %s || operand_equal_p (%s, %s, 0))\n",
-                   opname, match_opname, opname, match_opname);
+    fprintf_indent (f, indent, "if ((%s == %s && ! TREE_SIDE_EFFECTS (%s)) "
+                   "|| operand_equal_p (%s, %s, 0))\n",
+                   opname, match_opname, opname, opname, match_opname);
   else
-    fprintf_indent (f, indent, "if (%s == %s || (operand_equal_p (%s, %s, 0) "
+    fprintf_indent (f, indent, "if ((%s == %s && ! TREE_SIDE_EFFECTS (%s)) "
+                   "|| (operand_equal_p (%s, %s, 0) "
                    "&& types_match (%s, %s)))\n",
-                   opname, match_opname, opname, match_opname,
+                   opname, match_opname, opname, opname, match_opname,
                    opname, match_opname);
   fprintf_indent (f, indent + 2, "{\n");
   return 1;
@@ -3290,11 +3310,15 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
        }
     }
 
-  fprintf_indent (f, indent, "if (dump_file && (dump_flags & TDF_FOLDING)) "
-          "fprintf (dump_file, \"Applying pattern ");
+  fprintf_indent (f, indent, "if (__builtin_expect (dump_file && (dump_flags & TDF_FOLDING), 0)) "
+          "fprintf (dump_file, \"%s ",
+          s->kind == simplify::SIMPLIFY
+          ? "Applying pattern" : "Matching expression");
+  fprintf (f, "%%s:%%d, %%s:%%d\\n\", ");
   output_line_directive (f,
-                        result ? result->location : s->match->location, true);
-  fprintf (f, ", %%s:%%d\\n\", __FILE__, __LINE__);\n");
+                        result ? result->location : s->match->location, true,
+                        true);
+  fprintf (f, ", __FILE__, __LINE__);\n");
 
   if (!result)
     {
@@ -3737,7 +3761,7 @@ decision_tree::gen (FILE *f, bool gimple)
     }
   fprintf (stderr, "removed %u duplicate tails\n", rcnt);
 
-  for (unsigned n = 1; n <= 3; ++n)
+  for (unsigned n = 1; n <= 5; ++n)
     {
       /* First generate split-out functions.  */
       for (unsigned i = 0; i < root->kids.length (); i++)
@@ -3903,7 +3927,7 @@ private:
   c_expr *parse_c_expr (cpp_ttype);
   operand *parse_op ();
 
-  void record_operlist (source_location, user_id *);
+  void record_operlist (location_t, user_id *);
 
   void parse_pattern ();
   operand *parse_result (operand *, predicate_id *);
@@ -3911,10 +3935,10 @@ private:
                      vec<simplify *>&, operand *, operand *);
   void parse_simplify (simplify::simplify_kind,
                       vec<simplify *>&, predicate_id *, operand *);
-  void parse_for (source_location);
-  void parse_if (source_location);
-  void parse_predicates (source_location);
-  void parse_operator_list (source_location);
+  void parse_for (location_t);
+  void parse_if (location_t);
+  void parse_predicates (location_t);
+  void parse_operator_list (location_t);
 
   void finish_match_operand (operand *);
 
@@ -4072,7 +4096,7 @@ parser::get_internal_capture_id ()
 /* Record an operator-list use for transparent for handling.  */
 
 void
-parser::record_operlist (source_location loc, user_id *p)
+parser::record_operlist (location_t loc, user_id *p)
 {
   if (!oper_lists_set->add (p))
     {
@@ -4135,7 +4159,7 @@ parser::parse_operation ()
       if (active_fors.length() == 0)
        record_operlist (id_tok->src_loc, p);
       else
-       fatal_at (id_tok, "operator-list %s cannot be exapnded inside 'for'", id);
+       fatal_at (id_tok, "operator-list %s cannot be expanded inside 'for'", id);
     }
   return op;
 }
@@ -4146,7 +4170,7 @@ parser::parse_operation ()
 struct operand *
 parser::parse_capture (operand *op, bool require_existing)
 {
-  source_location src_loc = eat_token (CPP_ATSIGN)->src_loc;
+  location_t src_loc = eat_token (CPP_ATSIGN)->src_loc;
   const cpp_token *token = peek ();
   const char *id = NULL;
   bool value_match = false;
@@ -4302,7 +4326,7 @@ parser::parse_c_expr (cpp_ttype start)
   unsigned opencnt;
   vec<cpp_token> code = vNULL;
   unsigned nr_stmts = 0;
-  source_location loc = eat_token (start)->src_loc;
+  location_t loc = eat_token (start)->src_loc;
   if (start == CPP_OPEN_PAREN)
     end = CPP_CLOSE_PAREN;
   else if (start == CPP_OPEN_BRACE)
@@ -4491,7 +4515,7 @@ parser::parse_result (operand *result, predicate_id *matcher)
   else if (peek_ident ("switch"))
     {
       token = eat_ident ("switch");
-      source_location ifloc = eat_token (CPP_OPEN_PAREN)->src_loc;
+      location_t ifloc = eat_token (CPP_OPEN_PAREN)->src_loc;
       eat_ident ("if");
       if_expr *ife = new if_expr (ifloc);
       operand *res = ife;
@@ -4630,7 +4654,7 @@ parser::parse_simplify (simplify::simplify_kind kind,
      subst = <ident> '(' <ident>... ')'  */
 
 void
-parser::parse_for (source_location)
+parser::parse_for (location_t)
 {
   auto_vec<const cpp_token *> user_id_tokens;
   vec<user_id *> user_ids = vNULL;
@@ -4744,7 +4768,7 @@ parser::parse_for (source_location)
      oprs = '(' 'define_operator_list' <ident> <ident>... ')'  */
 
 void
-parser::parse_operator_list (source_location)
+parser::parse_operator_list (location_t)
 {
   const cpp_token *token = peek (); 
   const char *id = get_ident ();
@@ -4796,7 +4820,7 @@ parser::parse_operator_list (source_location)
      if = '(' 'if' '(' <c-expr> ')' <pattern> ')'  */
 
 void
-parser::parse_if (source_location)
+parser::parse_if (location_t)
 {
   c_expr *ifexpr = parse_c_expr (CPP_OPEN_PAREN);
 
@@ -4820,7 +4844,7 @@ parser::parse_if (source_location)
      preds = '(' 'define_predicates' <ident>... ')'  */
 
 void
-parser::parse_predicates (source_location)
+parser::parse_predicates (location_t)
 {
   do
     {
@@ -4851,7 +4875,7 @@ parser::parse_pattern ()
   else if (strcmp (id, "match") == 0)
     {
       bool with_args = false;
-      source_location e_loc = peek ()->src_loc;
+      location_t e_loc = peek ()->src_loc;
       if (peek ()->type == CPP_OPEN_PAREN)
        {
          eat_token (CPP_OPEN_PAREN);
@@ -5050,7 +5074,7 @@ main (int argc, char **argv)
 
   r = cpp_create_reader (CLK_GNUC99, NULL, line_table);
   cpp_callbacks *cb = cpp_get_callbacks (r);
-  cb->error = error_cb;
+  cb->diagnostic = diagnostic_cb;
 
   /* Add the build directory to the #include "" search path.  */
   cpp_dir *dir = XCNEW (cpp_dir);