Gimple FE support for internal functions
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 17 May 2018 10:52:58 +0000 (10:52 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 17 May 2018 10:52:58 +0000 (10:52 +0000)
This patch gets the gimple FE to parse calls to internal functions.
The only non-obvious thing was how the functions should be written
to avoid clashes with real function names.  One option would be to
go the magic number of underscores route, but we already do that for
built-in functions, and it would be good to keep them visually
distinct.  In the end I borrowed the local/internal label convention
from asm and used:

  x = .SQRT (y);

2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* internal-fn.h (lookup_internal_fn): Declare
* internal-fn.c (lookup_internal_fn): New function.
* gimple.c (gimple_build_call_from_tree): Handle calls to
internal functions.
* gimple-pretty-print.c (dump_gimple_call): Print "." before
internal function names.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree-ssa-scopedtables.c (expr_hash_elt::print): Likewise.

gcc/c/
* gimple-parser.c: Include internal-fn.h.
(c_parser_gimple_statement): Treat a leading CPP_DOT as a call.
(c_parser_gimple_call_internal): New function.
(c_parser_gimple_postfix_expression): Use it to handle CPP_DOT.
Fix typos in comment.

gcc/testsuite/
* gcc.dg/gimplefe-28.c: New test.
* gcc.dg/asan/use-after-scope-9.c: Adjust expected output for
internal function calls.
* gcc.dg/goacc/loop-processing-1.c: Likewise.

From-SVN: r260316

13 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/gimple-parser.c
gcc/gimple-pretty-print.c
gcc/gimple.c
gcc/internal-fn.c
gcc/internal-fn.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
gcc/testsuite/gcc.dg/gimplefe-28.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/goacc/loop-processing-1.c
gcc/tree-pretty-print.c
gcc/tree-ssa-scopedtables.c

index 2f8fd3c277be9086001e85a29708b7479b8d4c70..9e22926fba7d9b1765865f79f319da9926952e24 100644 (file)
@@ -1,3 +1,14 @@
+2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * internal-fn.h (lookup_internal_fn): Declare
+       * internal-fn.c (lookup_internal_fn): New function.
+       * gimple.c (gimple_build_call_from_tree): Handle calls to
+       internal functions.
+       * gimple-pretty-print.c (dump_gimple_call): Print "." before
+       internal function names.
+       * tree-pretty-print.c (dump_generic_node): Likewise.
+       * tree-ssa-scopedtables.c (expr_hash_elt::print): Likewise.
+
 2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * gimple-fold.h (gimple_build): Make the function forms take
index a8e21284deb03ee8745355df6d3bcef5e686b270..f31c86fbf958f9a65a2991135037d570cdbdeb95 100644 (file)
@@ -1,3 +1,11 @@
+2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * gimple-parser.c: Include internal-fn.h.
+       (c_parser_gimple_statement): Treat a leading CPP_DOT as a call.
+       (c_parser_gimple_call_internal): New function.
+       (c_parser_gimple_postfix_expression): Use it to handle CPP_DOT.
+       Fix typos in comment.
+
 2018-05-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/85662
index 32513f1227777a2d0eb43976c73707963c1328e2..c9abe24bfe619fb6e0b513abb2e10d60ba7220dd 100644 (file)
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssanames.h"
 #include "gimple-ssa.h"
 #include "tree-dfa.h"
+#include "internal-fn.h"
 
 
 /* Gimple parsing functions.  */
@@ -400,9 +401,10 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
     }
 
   /* GIMPLE call with lhs.  */
-  if (c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
-      && lookup_name (c_parser_peek_token (parser)->value))
+  if (c_parser_next_token_is (parser, CPP_DOT)
+      || (c_parser_next_token_is (parser, CPP_NAME)
+         && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
+         && lookup_name (c_parser_peek_token (parser)->value)))
     {
       rhs = c_parser_gimple_unary_expression (parser);
       if (rhs.value != error_mark_node)
@@ -726,14 +728,57 @@ c_parser_parse_ssa_name (c_parser *parser,
   return name;
 }
 
+/* Parse a gimple call to an internal function.
+
+   gimple-call-internal:
+     . identifier ( gimple-argument-expression-list[opt] )  */
+
+static struct c_expr
+c_parser_gimple_call_internal (c_parser *parser)
+{
+  struct c_expr expr;
+  expr.set_error ();
+
+  gcc_assert (c_parser_next_token_is (parser, CPP_DOT));
+  c_parser_consume_token (parser);
+  location_t loc = c_parser_peek_token (parser)->location;
+  if (!c_parser_next_token_is (parser, CPP_NAME)
+      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+    {
+      c_parser_error (parser, "expecting internal function name");
+      return expr;
+    }
+  tree id = c_parser_peek_token (parser)->value;
+  internal_fn ifn = lookup_internal_fn (IDENTIFIER_POINTER (id));
+  c_parser_consume_token (parser);
+  if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    {
+      auto_vec<tree> exprlist;
+      if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+       c_parser_gimple_expr_list (parser, &exprlist);
+      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+      if (ifn == IFN_LAST)
+       error_at (loc, "unknown internal function %qE", id);
+      else
+       {
+         expr.value = build_call_expr_internal_loc_array
+           (loc, ifn, void_type_node, exprlist.length (),
+            exprlist.address ());
+         expr.original_code = ERROR_MARK;
+         expr.original_type = NULL;
+       }
+    }
+  return expr;
+}
+
 /* Parse gimple postfix expression.
 
    gimple-postfix-expression:
      gimple-primary-expression
-     gimple-primary-xpression [ gimple-primary-expression ]
+     gimple-primary-expression [ gimple-primary-expression ]
      gimple-primary-expression ( gimple-argument-expression-list[opt] )
-     postfix-expression . identifier
-     postfix-expression -> identifier
+     gimple-postfix-expression . identifier
+     gimple-postfix-expression -> identifier
 
    gimple-argument-expression-list:
      gimple-unary-expression
@@ -743,6 +788,7 @@ c_parser_parse_ssa_name (c_parser *parser,
      identifier
      constant
      string-literal
+     gimple-call-internal
 
 */
 
@@ -779,6 +825,9 @@ c_parser_gimple_postfix_expression (c_parser *parser)
       expr.original_code = STRING_CST;
       c_parser_consume_token (parser);
       break;
+    case CPP_DOT:
+      expr = c_parser_gimple_call_internal (parser);
+      break;
     case CPP_NAME:
       if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
        {
index 6695526f3702dbf7aa286b430e7042de6b159133..afe01471a45cb0d73de270540dcb69982659c3f4 100644 (file)
@@ -874,7 +874,7 @@ dump_gimple_call (pretty_printer *buffer, gcall *gs, int spc,
   if (flags & TDF_RAW)
     {
       if (gimple_call_internal_p (gs))
-       dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
+       dump_gimple_fmt (buffer, spc, flags, "%G <.%s, %T", gs,
                         internal_fn_name (gimple_call_internal_fn (gs)), lhs);
       else
        dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", gs, fn, lhs);
@@ -898,7 +898,10 @@ dump_gimple_call (pretty_printer *buffer, gcall *gs, int spc,
          pp_space (buffer);
         }
       if (gimple_call_internal_p (gs))
-       pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
+       {
+         pp_dot (buffer);
+         pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
+       }
       else
        print_call_name (buffer, fn, flags);
       pp_string (buffer, " (");
index 9dc4911a36e04c99102961a1d410de6d3cd0e816..745cdf33586ab588af6e40744a853fbde9347fc3 100644 (file)
@@ -350,12 +350,19 @@ gimple_build_call_from_tree (tree t, tree fnptrtype)
 {
   unsigned i, nargs;
   gcall *call;
-  tree fndecl = get_callee_fndecl (t);
 
   gcc_assert (TREE_CODE (t) == CALL_EXPR);
 
   nargs = call_expr_nargs (t);
-  call = gimple_build_call_1 (fndecl ? fndecl : CALL_EXPR_FN (t), nargs);
+
+  tree fndecl = NULL_TREE;
+  if (CALL_EXPR_FN (t) == NULL_TREE)
+    call = gimple_build_call_internal_1 (CALL_EXPR_IFN (t), nargs);
+  else
+    {
+      fndecl = get_callee_fndecl (t);
+      call = gimple_build_call_1 (fndecl ? fndecl : CALL_EXPR_FN (t), nargs);
+    }
 
   for (i = 0; i < nargs; i++)
     gimple_call_set_arg (call, i, CALL_EXPR_ARG (t, i));
index da205c9d68a16217f9e8e575206fec5d3456934e..ba94a61cf11197d6a7e50b14794eb2ae64098f2b 100644 (file)
@@ -64,6 +64,26 @@ const int internal_fn_flags_array[] = {
   0
 };
 
+/* Return the internal function called NAME, or IFN_LAST if there's
+   no such function.  */
+
+internal_fn
+lookup_internal_fn (const char *name)
+{
+  typedef hash_map<nofree_string_hash, internal_fn> name_to_fn_map_type;
+  static name_to_fn_map_type *name_to_fn_map;
+
+  if (!name_to_fn_map)
+    {
+      name_to_fn_map = new name_to_fn_map_type (IFN_LAST);
+      for (unsigned int i = 0; i < IFN_LAST; ++i)
+       name_to_fn_map->put (internal_fn_name (internal_fn (i)),
+                            internal_fn (i));
+    }
+  internal_fn *entry = name_to_fn_map->get (name);
+  return entry ? *entry : IFN_LAST;
+}
+
 /* Fnspec of each internal function, indexed by function number.  */
 const_tree internal_fn_fnspec_array[IFN_LAST + 1];
 
index 67102fdad76d7301cc959c0043b712f01d524219..34ea8c67a4ee807df92d3e950ec94ffe2d8966ef 100644 (file)
@@ -107,6 +107,8 @@ internal_fn_name (enum internal_fn fn)
   return internal_fn_name_array[(int) fn];
 }
 
+extern internal_fn lookup_internal_fn (const char *);
+
 /* Return the ECF_* flags for function FN.  */
 
 extern const int internal_fn_flags_array[];
index f02fa93ad3f84df2ddf44075c83d07551335e06a..c20e717ed97e38ced7ea1f7490612e02b406a889 100644 (file)
@@ -1,3 +1,10 @@
+2018-05-17  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * gcc.dg/gimplefe-28.c: New test.
+       * gcc.dg/asan/use-after-scope-9.c: Adjust expected output for
+       internal function calls.
+       * gcc.dg/goacc/loop-processing-1.c: Likewise.
+
 2018-05-17  Martin Liska  <mliska@suse.cz>
 
        * gcc.dg/plugin/ggcplug.c (plugin_init): Do not use
index edc1ab21f884100fb5cf0e00edcfb1dd790b8bcc..c3e4da55aade001b6cc880057a3225347f8021ef 100644 (file)
@@ -17,7 +17,7 @@ main (int argc, char **argv)
   return *ptr;
 }
 
-// { dg-final { scan-tree-dump-times "= ASAN_POISON \\(\\)" 1 "asan1" } }
+// { dg-final { scan-tree-dump-times {= \.ASAN_POISON \(\)} 1 "asan1" } }
 // { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
 // { dg-output "READ of size .*" }
 // { dg-output ".*'a' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/gimplefe-28.c b/gcc/testsuite/gcc.dg/gimplefe-28.c
new file mode 100644 (file)
index 0000000..467172d
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile { target sqrt_insn } } */
+/* { dg-options "-fgimple -O2" } */
+
+double __GIMPLE
+f1 (double x)
+{
+  double res;
+  res = .SQRT (x);
+  return res;
+}
+
+void __GIMPLE
+f2 (double x)
+{
+  .SQRT (x); // Dead code
+}
index 07f56a25329cf1619c3cdc37975761c69bb550e7..bd4c07e7d81cf4334912bea1711a983b32a811e2 100644 (file)
@@ -15,4 +15,4 @@ void vector_1 (int *ary, int size)
   }
 }
 
-/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 24\(1\).*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*Head-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccdevlow" } } */
+/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 24\(1\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccdevlow" } } */
index 276ad00a7b2f58394bf2900f58a111d69dfb0915..bc36c28643b8b420dc47b538c11667d22593c200 100644 (file)
@@ -2262,7 +2262,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
       if (CALL_EXPR_FN (node) != NULL_TREE)
        print_call_name (pp, CALL_EXPR_FN (node), flags);
       else
-       pp_string (pp, internal_fn_name (CALL_EXPR_IFN (node)));
+       {
+         pp_dot (pp);
+         pp_string (pp, internal_fn_name (CALL_EXPR_IFN (node)));
+       }
 
       /* Print parameters.  */
       pp_space (pp);
index 2a40fdae0a27b78d84e9f989ef181bb5a89022b5..9e751a2715262a687e396830711a471220f3b9ff 100644 (file)
@@ -906,8 +906,8 @@ expr_hash_elt::print (FILE *stream)
 
           fn_from = m_expr.ops.call.fn_from;
           if (gimple_call_internal_p (fn_from))
-            fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
-                   stream);
+           fprintf (stream, ".%s",
+                    internal_fn_name (gimple_call_internal_fn (fn_from)));
           else
            print_generic_expr (stream, gimple_call_fn (fn_from));
           fprintf (stream, " (");