On 17 May 2018 at 10:25, Richard Sandiford <richard.sandif...@linaro.org> wrote:
> 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);
>
> I don't think even C++ has found a meaning for a leading dot yet.
>
> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> and x86_64-linux-gnu.  OK to install?
>
> Richard
>
>
> 2018-05-17  Richard Sandiford  <richard.sandif...@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.

Hi Richard,

I've noticed that this new test fails on arm-none-linux-gnueabi and
arm-none-eabi:
during RTL pass: expand
/gcc/testsuite/gcc.dg/gimplefe-28.c: In function 'f1':
/gcc/testsuite/gcc.dg/gimplefe-28.c:5:1: internal compiler error: in
maybe_gen_insn, at optabs.c:7240
0xa9157a maybe_gen_insn(insn_code, unsigned int, expand_operand*)
        /gcc/optabs.c:7240
0xa91658 maybe_expand_insn(insn_code, unsigned int, expand_operand*)
        /gcc/optabs.c:7284
0xa91688 expand_insn(insn_code, unsigned int, expand_operand*)
        /gcc/optabs.c:7315
0x94242d expand_direct_optab_fn
        /gcc/internal-fn.c:2918
0x6c5d14 expand_call_stmt
        /gcc/cfgexpand.c:2598
0x6c6fd4 expand_gimple_stmt_1
        /gcc/cfgexpand.c:3644
0x6c6fd4 expand_gimple_stmt
        /gcc/cfgexpand.c:3810
0x6c7ab4 expand_gimple_tailcall
        /gcc/cfgexpand.c:3856
0x6c9183 expand_gimple_basic_block
        /gcc/cfgexpand.c:5816
0x6cbf26 execute
        /gcc/cfgexpand.c:6445

It passes on arm-none-linux-gnueabihf and armeb-none-linux-gnueabihf.

Christophe


>         * gcc.dg/asan/use-after-scope-9.c: Adjust expected output for
>         internal function calls.
>         * gcc.dg/goacc/loop-processing-1.c: Likewise.
>
> Index: gcc/internal-fn.h
> ===================================================================
> --- gcc/internal-fn.h   2018-05-16 12:48:59.194282896 +0100
> +++ gcc/internal-fn.h   2018-05-17 09:17:58.757608747 +0100
> @@ -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: gcc/internal-fn.c
> ===================================================================
> --- gcc/internal-fn.c   2018-05-16 12:48:59.410941892 +0100
> +++ gcc/internal-fn.c   2018-05-17 09:22:49.808912358 +0100
> @@ -64,6 +64,26 @@ #define DEF_INTERNAL_FN(CODE, FLAGS, FNS
>    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: gcc/gimple.c
> ===================================================================
> --- gcc/gimple.c        2018-05-16 12:48:59.410941892 +0100
> +++ gcc/gimple.c        2018-05-17 09:22:49.808912358 +0100
> @@ -350,12 +350,19 @@ gimple_build_call_from_tree (tree t, tre
>  {
>    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: gcc/gimple-pretty-print.c
> ===================================================================
> --- gcc/gimple-pretty-print.c   2018-05-16 12:48:59.410941892 +0100
> +++ gcc/gimple-pretty-print.c   2018-05-17 09:22:49.808912358 +0100
> @@ -874,7 +874,7 @@ dump_gimple_call (pretty_printer *buffer
>    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
>           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: gcc/tree-pretty-print.c
> ===================================================================
> --- gcc/tree-pretty-print.c     2018-05-16 12:48:59.410941892 +0100
> +++ gcc/tree-pretty-print.c     2018-05-17 09:22:49.808912358 +0100
> @@ -2262,7 +2262,10 @@ dump_generic_node (pretty_printer *pp, t
>        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: gcc/tree-ssa-scopedtables.c
> ===================================================================
> --- gcc/tree-ssa-scopedtables.c 2018-02-08 13:34:20.649280969 +0000
> +++ gcc/tree-ssa-scopedtables.c 2018-05-17 09:17:58.758608713 +0100
> @@ -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, " (");
> Index: gcc/c/gimple-parser.c
> ===================================================================
> --- gcc/c/gimple-parser.c       2018-05-16 12:48:59.410941892 +0100
> +++ gcc/c/gimple-parser.c       2018-05-17 09:22:49.808912358 +0100
> @@ -53,6 +53,7 @@ Software Foundation; either version 3, o
>  #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 *par
>      }
>
>    /* 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 *parse
>    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 *parse
>       identifier
>       constant
>       string-literal
> +     gimple-call-internal
>
>  */
>
> @@ -779,6 +825,9 @@ c_parser_gimple_postfix_expression (c_pa
>        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: gcc/testsuite/gcc.dg/gimplefe-28.c
> ===================================================================
> --- /dev/null   2018-04-20 16:19:46.369131350 +0100
> +++ gcc/testsuite/gcc.dg/gimplefe-28.c  2018-05-17 09:17:58.757608747 +0100
> @@ -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: gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/asan/use-after-scope-9.c       2017-02-23 
> 19:54:08.000000000 +0000
> +++ gcc/testsuite/gcc.dg/asan/use-after-scope-9.c       2018-05-17 
> 09:17:58.757608747 +0100
> @@ -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.*" }
> Index: gcc/testsuite/gcc.dg/goacc/loop-processing-1.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/goacc/loop-processing-1.c      2017-02-23 
> 19:54:08.000000000 +0000
> +++ gcc/testsuite/gcc.dg/goacc/loop-processing-1.c      2018-05-17 
> 09:17:58.757608747 +0100
> @@ -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" } } */

Reply via email to