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

--- Comment #14 from Richard Earnshaw <rearnsha at gcc dot gnu.org> ---
(In reply to Tom Lane from comment #13)
> After further experimentation, it seems to me that:
> 
> * There was a behavioral change between gcc 9.3.1 and the later releases I
> tested.  Specifically, in 9.3.1 a -march switch does not override the
> platform-selected default -mfpu, whereas in later releases the default -mfpu
> is ignored if there's -march on the command line.  I don't know if this was
> intentional.  I can work with it, but:
> 

The changes were made in gcc-8, it was announced in the release notes. They
were necessary because the Arm architecture has evolved in a way that makes the
-mfpu option non-viable for some branches of the architecture.

In the old system, there was -march (or -mcpu) and -mfpu.  The problems with
this were that:
- Users had to know which FPU model went with which architecture (it was
common-place to see combinations like -march=armv8-a -mfpu=neon, with users not
realising that this did not enable all the available neon functionality in
armv8-a).
- It was possible to create Franken architectures that did not exist, such as
Armv4 with floating point or armv8-m with neon.  This makes testing a bigger
problem.
- The scheme really does not work for the M-profile MVE extension where this
feature extends both the integer, FP and simd instruction sets.

To address this, I implemented a new methodology for specifying the
architecture and the extensions supported.  The scheme uses '+<feature>' on the
architecture spec, which can be validated against the supported extensions. 
For -march extensions are additive (we start with the base architecture, then
add features that are needed to create a complete architecture specification);
for -mcpu, however, the features are subtractive (we start with the most
capable CPU, but then allow users to disable some extensions that they don't
want.  This is designed to fit the model where most vendors will want to
specify a base architecture that they intend their tools to support, but most
users will want to specify a specific CPU that they intend to target.

To maintain backwards compatibility the new way of specifying SIMD/FPU-related
features is disabled unless -mfpu=auto is specified.  But...

Some options are set to defaults when the compiler is configured by the vendor
(or whoever builds the compiler itself).  The default behaviour is to pick
'auto' as the FPU, thus enabling the new model, but if --with-fpu=<something>
is used, then this disables the auto feature and it falls back to the old way. 
Users can still manually specify -mfpu=auto to force the new behaviour, or (at
present) can use -mfpu= to force the old behaviour.

The problem you are running into is, I think, that your compiler is configured
for auto FPU and hard-float, but you then you then try to change the
architecture without specifying the fp/simd extension you desire. This leads to
an impossible architecture because you end up with the hard float ABI, but the
compiler has no idea which floating-point instructions (or registers) exist.

The final thing that I want to mention is the FP/SIMD options.  These
extensions build on each other - there's the base FP extension, introduced in
Armv5, and then AdvancedSIMD (aka Neon) in Armv7.  Neon extends the floating
point instruction set and while the v7 Arm ARM theoretically permits Neon
without FP, no product ever implemented this.  V8 wend in the other direction
and made Neon mandatory when floating-point was present.  So GCC implements the
following extensions for the v7 architecture:

+fp - add floating point (as defined by the base architecture)
+simd - add floating point and Neon (as defined by the base architecture)

However, in Armv8, +fp isn't a permitted implementation, so this isn't
available, leaving just +simd, which enables both FP and Neon.

For v7 CPUs, the opposite of these exist:
+nosimd - removes SIMD instructions (but leaves the floating point).
+nofp - removes both SIMD and floating point.

For v8 CPUs, because the two are combined, we again end up with just the
extreme:
+nofp - removes both SIMD and floating point.

Reply via email to