https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123206
Bug ID: 123206
Summary: aarch64: Wrong gating of fp8 intrinsics in
aarch64-simd-pragma-builtins.def
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: acoplan at gcc dot gnu.org
Target Milestone: ---
gcc/config/aarch64/aarch64-simd-pragma-builtins.def has several entries of the
form:
#define REQUIRED_EXTENSIONS nonstreaming_only (TARGET_SIMD)
[...]
#undef REQUIRED_EXTENSIONS
e.g.:
// bsl
#define REQUIRED_EXTENSIONS nonstreaming_only (TARGET_SIMD)
ENTRY_TERNARY (vbsl_mf8, mf8, u8, mf8, mf8, UNSPEC_BSL, QUIET)
ENTRY_TERNARY (vbslq_mf8, mf8q, u8q, mf8q, mf8q, UNSPEC_BSL, QUIET)
#undef REQUIRED_EXTENSIONS
the problem is that nonstreaming_only expects an aarch64_feature_flags
instance, which describes (statically) which feature flags are required in this
context. TARGET_SIMD, on the other hand, doesn't give a set of feature flags,
but computes a boolean which says whether the SIMD feature is currently
enabled, according to global_options.
This manifests as an ICE when +nosimd is given in -march:
$ cat small.i
#pragma GCC aarch64 "arm_neon.h"
typedef __Mfloat8x8_t mfloat8x8_t;
typedef __Uint8x8_t uint8x8_t;
mfloat8x8_t foo(uint8x8_t a, mfloat8x8_t b, mfloat8x8_t c)
{
return vbsl_mf8(a,b,c);
}
$ ./xgcc -B . -c small.i -O2 -S -o /dev/null -march=armv8-a+nosimd
small.i: In function ‘foo’:
small.i:8:1: error: unrecognizable insn:
8 | }
| ^
(insn 8 5 12 2 (set (reg:V8QI 101 [ <retval> ])
(xor:V8QI (and:V8QI (xor:V8QI (reg/v:V8QI 104 [ c ])
(reg/v:V8QI 103 [ b ]))
(reg/v:V8QI 102 [ a ]))
(reg/v:V8QI 104 [ c ]))) "small.i":7:10 -1
(nil))
during RTL pass: vregs
small.i:8:1: internal compiler error: in extract_insn, at recog.cc:2888
0x38b692e internal_error(char const*, ...)
/fast/trunk/src/gcc/gcc/diagnostic-global-context.cc:787
0x38c65b4 fancy_abort(char const*, int, char const*)
/fast/trunk/src/gcc/gcc/diagnostics/context.cc:1805
0x1a35428 _fatal_insn(char const*, rtx_def const*, char const*, int, char
const*)
/fast/trunk/src/gcc/gcc/rtl-error.cc:108
0x1a3546d _fatal_insn_not_found(rtx_def const*, char const*, int, char const*)
/fast/trunk/src/gcc/gcc/rtl-error.cc:116
0x19e1a2c extract_insn(rtx_insn*)
/fast/trunk/src/gcc/gcc/recog.cc:2888
0x1507fec instantiate_virtual_regs_in_insn
/fast/trunk/src/gcc/gcc/function.cc:1609
0x1509668 instantiate_virtual_regs
/fast/trunk/src/gcc/gcc/function.cc:1985
0x150974c execute
/fast/trunk/src/gcc/gcc/function.cc:2032
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
This is because +nosimd (correctly) disables the pattern but the frontend (via
the .def file) incorrectly accepts the intrinsic.
The fix should be straightforward (s/TARGET_SIMD/AARCH64_FL_SIMD/ in that
file), but I think we should take at least one of the additional hardening
steps to avoid this happening again in the future:
1. Make aarch64-builtins.cc:aarch64_pragma_builtins declared constexpr. This
would prevent uses of global_options via TARGET_* macros.
2. Make the ctor of aarch64_feature_flags (i.e. bbitmap) declared explicit.
This would prevent implicit conversions to aarch64_feature_flags from int/bool.
This has the slight downside of not allowing bare uses of 0 in an
aarch64_feature_flags context, but I think avoiding this sort of thing in the
future is probably worth it (though I would appreciate an opinion from Alice on
that).