Re: Ping: Add a simulate_builin_function_decl langhook

2019-10-18 Thread Richard Sandiford
Here's a version rebased on top of Nathan's C++ patch yesterday.
This actually makes the patch simpler; the changes to the frontends
are now pure additions, so no existing frontend code should be affected.

FWIW, this patch and the enum one:

  https://gcc.gnu.org/ml/gcc-patches/2019-09/msg01523.html
  pinged with more rationale here:
  https://gcc.gnu.org/ml/gcc-patches/2019-10/msg01003.html

are the only remaining prerequisites we need before adding (fixed-length
support for) the SVE intrinsics and calling conventions.

Thanks,
Richard

Richard Sandiford  writes:
> Ping
>
> See also https://gcc.gnu.org/ml/gcc-patches/2019-10/msg00413.html
> for more details about why this seemed like a good idea.  A shorter
> version of that message (well, it started out that way :-)) is that
> it lets us use:
>
>   #ifndef _ARM_SVE_H_
>   #define _ARM_SVE_H_
>
>   #include 
>
>   typedef __fp16 float16_t;
>   typedef float float32_t;
>   typedef double float64_t;
>
>   #pragma GCC aarch64 "arm_sve.h"
>
>   #endif
>
> as the full intrinsics header file.  Rather than have GCC call:
>
>   add_builtin_function ("__builtin_aarch64_svarsd_s16_n_x",
> fntype, code, BUILT_IN_MD, NULL, attrs);
>
> at start-up and having the header file provide an inline wrapper like:
>
>   __extension__ extern __inline svint8_t
>   __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
>   svasrd_n_s16_x (svbool_t __a, svint8_t __b, int64_t __c)
>   {
> return __builtin_aarch64_svasrd_n_s16_x (__a, __b, __c);
>   }
>
> we can just have GCC call:
>
>   simulate_builtin_function_decl (input_location, "svasrd_n_s16_x",
>   fntype, code, NULL, attrs);
>
> when the header pragma is invoked.
>
> When repeated for thousands of functions, this significantly reduces
> the amount of code needed.  It also gives quicker start-up times
> (because functions are only registered when they're needed) and makes
> arm_sve.h compile more quickly (because there's less code to parse).
>
> Another benefit is that inline wrappers don't show up in error messages.
> E.g.:
>
>   #include 
>   int8x8_t foo (int16x8_t x, int y)
>   { return vqrshrn_n_s16 (x, y); }
>
> gives:
>
>   In file included from foo.c:3:10:
>   In function 'vqrshrn_n_s16',
>   inlined from 'foo' at foo.c:2:
>   include/arm_neon.h:24419:10: error: argument 2 must be a constant immediate
>   24419 |   return (int8x8_t) __builtin_aarch64_sqrshrn_nv8hi (__a, __b);
> |  ^
>
> where the quoted line is the inline wrapper in arm_neon.h rather than
> the user's code.  An SVE example like:
>
>   #include 
>   svint16_t foo (svbool_t pg, svint16_t x, int y)
>   { return svasrd_x (pg, x, y); }
>
> instead gives:
>
>   foo.c: In function 'foo':
>   foo.c:3:10: error: argument 3 of 'svasrd_x' must be an integer constant 
> expression
>   3 | { return svasrd_x (pg, x, y); }
> |  ^~~~
>
> which seems more user-friendly.
>
> Thanks,
> Richard
>
> Richard Sandiford  writes:
>> Although it's possible to define the SVE intrinsics in a normal header
>> file, it's much more convenient to define them directly in the compiler.
>> This also speeds up compilation and gives better error messages.
>>
>> The idea is therefore for arm_sve.h (the main intrinsics header file)
>> to have the pragma:
>>
>> #pragma GCC aarch64 "arm_sve.h"
>>
>> telling GCC to define (almost) everything arm_sve.h needs to define.
>> The target then needs a way of injecting new built-in function
>> declarations during compilation.
>>
>> The main hook for defining built-in functions is add_builtin_function.
>> This is designed for use at start-up, and so has various features that
>> are correct in that context but not for the pragma above:
>>
>>   (1) the location is always BUILTINS_LOCATION, whereas for arm_sve.h
>>   it ought to be the location of the pragma.
>>
>>   (2) the function is only immediately visible if it's in the implementation
>>   namespace, whereas the pragma is deliberately injecting functions
>>   into the general namespace.
>>
>>   (3) there's no attempt to emulate a normal function declaration in
>>   C or C++, whereas functions declared by the pragma should be
>>   checked in the same way as an open-coded declaration would be.
>>   E.g. we should get an error if there was a previous incompatible
>>   declaration.
>>
>>   (4) in C++, the function is treated as extern "C" and so can't be
>>   overloaded, whereas SVE intrinsics do use function overloading.
>>
>> This patch therefore adds a hook that targets can use to inject
>> the equivalent of a source-level function declaration, but bound
>> to a BUILT_IN_MD function.
>>
>> The main SVE intrinsic patch has tests to make sure that we report an
>> error for conflicting definitions that appear either before or after
>> including arm_sve.h.
>>
>> Tested on aarch64-linux-gnu and 

Ping: Add a simulate_builin_function_decl langhook

2019-10-14 Thread Richard Sandiford
Ping

See also https://gcc.gnu.org/ml/gcc-patches/2019-10/msg00413.html
for more details about why this seemed like a good idea.  A shorter
version of that message (well, it started out that way :-)) is that
it lets us use:

  #ifndef _ARM_SVE_H_
  #define _ARM_SVE_H_

  #include 

  typedef __fp16 float16_t;
  typedef float float32_t;
  typedef double float64_t;

  #pragma GCC aarch64 "arm_sve.h"

  #endif

as the full intrinsics header file.  Rather than have GCC call:

  add_builtin_function ("__builtin_aarch64_svarsd_s16_n_x",
fntype, code, BUILT_IN_MD, NULL, attrs);

at start-up and having the header file provide an inline wrapper like:

  __extension__ extern __inline svint8_t
  __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
  svasrd_n_s16_x (svbool_t __a, svint8_t __b, int64_t __c)
  {
return __builtin_aarch64_svasrd_n_s16_x (__a, __b, __c);
  }

we can just have GCC call:

  simulate_builtin_function_decl (input_location, "svasrd_n_s16_x",
  fntype, code, NULL, attrs);

when the header pragma is invoked.

When repeated for thousands of functions, this significantly reduces
the amount of code needed.  It also gives quicker start-up times
(because functions are only registered when they're needed) and makes
arm_sve.h compile more quickly (because there's less code to parse).

Another benefit is that inline wrappers don't show up in error messages.
E.g.:

  #include 
  int8x8_t foo (int16x8_t x, int y)
  { return vqrshrn_n_s16 (x, y); }

gives:

  In file included from foo.c:3:10:
  In function 'vqrshrn_n_s16',
  inlined from 'foo' at foo.c:2:
  include/arm_neon.h:24419:10: error: argument 2 must be a constant immediate
  24419 |   return (int8x8_t) __builtin_aarch64_sqrshrn_nv8hi (__a, __b);
|  ^

where the quoted line is the inline wrapper in arm_neon.h rather than
the user's code.  An SVE example like:

  #include 
  svint16_t foo (svbool_t pg, svint16_t x, int y)
  { return svasrd_x (pg, x, y); }

instead gives:

  foo.c: In function 'foo':
  foo.c:3:10: error: argument 3 of 'svasrd_x' must be an integer constant 
expression
  3 | { return svasrd_x (pg, x, y); }
|  ^~~~

which seems more user-friendly.

Thanks,
Richard

Richard Sandiford  writes:
> Although it's possible to define the SVE intrinsics in a normal header
> file, it's much more convenient to define them directly in the compiler.
> This also speeds up compilation and gives better error messages.
>
> The idea is therefore for arm_sve.h (the main intrinsics header file)
> to have the pragma:
>
> #pragma GCC aarch64 "arm_sve.h"
>
> telling GCC to define (almost) everything arm_sve.h needs to define.
> The target then needs a way of injecting new built-in function
> declarations during compilation.
>
> The main hook for defining built-in functions is add_builtin_function.
> This is designed for use at start-up, and so has various features that
> are correct in that context but not for the pragma above:
>
>   (1) the location is always BUILTINS_LOCATION, whereas for arm_sve.h
>   it ought to be the location of the pragma.
>
>   (2) the function is only immediately visible if it's in the implementation
>   namespace, whereas the pragma is deliberately injecting functions
>   into the general namespace.
>
>   (3) there's no attempt to emulate a normal function declaration in
>   C or C++, whereas functions declared by the pragma should be
>   checked in the same way as an open-coded declaration would be.
>   E.g. we should get an error if there was a previous incompatible
>   declaration.
>
>   (4) in C++, the function is treated as extern "C" and so can't be
>   overloaded, whereas SVE intrinsics do use function overloading.
>
> This patch therefore adds a hook that targets can use to inject
> the equivalent of a source-level function declaration, but bound
> to a BUILT_IN_MD function.
>
> The main SVE intrinsic patch has tests to make sure that we report an
> error for conflicting definitions that appear either before or after
> including arm_sve.h.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?
>
> Richard


2019-09-26  Richard Sandiford  

gcc/
* langhooks.h (lang_hooks::simulate_builtin_function_decl): New hook.
(simulate_builtin_function_decl): Declare.
* langhooks-def.h (LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL): Define.
(LANG_HOOKS_INITIALIZER): Include it.
* langhooks.c (add_builtin_function_common): Rename to...
(build_builtin_function): ...this.  Add a location parameter and use
it instead of BUILTINS_LOCATION.  Remove the hook parameter and return
the decl instead.
(add_builtin_function): Update accordingly, passing the returned
decl to the lang hook.
(add_builtin_function_ext_scope): Likewise