https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93370

            Bug ID: 93370
           Summary: Aarch64 accepts but ignores target("+sm4") unless
                    ARMv8.2-A is enabled
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lloyd at randombit dot net
  Target Milestone: ---

Aarch64 8.2-A has an optional extension for SM4. This is a Chinese
cryptographic algorithm analogous to AES. GCC supports these via intrinsic.

The confusion came about because GCC accepts `__attribute__((target("+sm4")))`
but unless ARMv8.2-A is also enabled (eg via -march=armv8.2-a command line
flag) then it complains about a target specific option mismatch, which is the
usual error when trying to use an intrinsic for an extension that is not
enabled when compiling that function or file. In contrast if you pass something
GCC doesn't know about to target() then it errors with a clear message "pragma
or attribute 'target("+foo")' is not valid".

Example:

$ aarch64-linux-gnu-gcc -v                                       
Using built-in specs.
COLLECT_GCC=aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/aarch64-linux-gnu/9.2.0/lto-wrapper
Target: aarch64-linux-gnu
Configured with: /build/aarch64-linux-gnu-gcc/src/gcc-9.2.0/configure
--prefix=/usr --program-prefix=aarch64-linux-gnu-
--with-local-prefix=/usr/aarch64-linux-gnu
--with-sysroot=/usr/aarch64-linux-gnu
--with-build-sysroot=/usr/aarch64-linux-gnu
--with-native-system-header-dir=/include --libdir=/usr/lib
--libexecdir=/usr/lib --target=aarch64-linux-gnu --host=x86_64-pc-linux-gnu
--build=x86_64-pc-linux-gnu --disable-nls --enable-languages=c,c++,fortran
--enable-shared --enable-threads=posix --with-system-zlib --with-isl
--enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu
--disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object
--enable-linker-build-id --enable-lto --enable-plugin
--enable-install-libiberty --with-linker-hash-style=gnu
--enable-gnu-indirect-function --disable-multilib --disable-werror
--enable-checking=release
Thread model: posix
gcc version 9.2.0 (GCC)
$ cat sm4.c
#include <arm_neon.h>

#if WORKS
 #define TARGET "arch=armv8.2-a+sm4"
#else
 #define TARGET "+sm4"
#endif

void __attribute__((target(TARGET))) enc(uint32_t b[4])
   {
   uint32x4_t B = vld1q_u32(b);
   vsm4eq_u32(B, B); // from SM4 extension
   vst1q_u32(b, B);
   }
$ aarch64-linux-gnu-gcc -DWORKS=1 -Wall -Wextra -c sm4.c -o sm4.o
$ aarch64-linux-gnu-gcc -DWORKS=0 -march=armv8.2-a -Wall -Wextra -c sm4.c -o
sm4.o
$ aarch64-linux-gnu-gcc -DWORKS=0 -Wall -Wextra -c sm4.c -o sm4.o               
In file included from sm4.c:1:
/usr/lib/gcc/aarch64-linux-gnu/9.2.0/include/arm_neon.h: In function 'void
enc(uint32_t*)':
/usr/lib/gcc/aarch64-linux-gnu/9.2.0/include/arm_neon.h:33125:1: error:
inlining failed in call to always_inline 'uint32x4_t vsm4eq_u32(uint32x4_t,
uint32x4_t)': target specific option mismatch
33125 | vsm4eq_u32 (uint32x4_t __a, uint32x4_t __b)
      | ^~~~~~~~~~
sm4.c:12:14: note: called from here
   12 |    vsm4eq_u32(B, B);
      |    ~~~~~~~~~~^~~~~~
In file included from sm4.c:1:
/usr/lib/gcc/aarch64-linux-gnu/9.2.0/include/arm_neon.h:33125:1: error:
inlining failed in call to always_inline 'uint32x4_t vsm4eq_u32(uint32x4_t,
uint32x4_t)': target specific option mismatch
33125 | vsm4eq_u32 (uint32x4_t __a, uint32x4_t __b)
      | ^~~~~~~~~~
sm4.c:12:14: note: called from here
   12 |    vsm4eq_u32(B, B);
      |    ~~~~~~~~~~^~~~~~

This is not a huge bug but it would be nice if GCC gave a more obvious error to
hint at the problem, since it accepts +sm4 but does not actually respect it
unless ARMv8.2-A is separately enabled. I imagine this situation holds true for
some of the other Aarch64 extensions but have not checked this.

Reply via email to