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