public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Function multiversioning ABI issues
@ 2023-10-10 17:35 Andrew Carlotti
  2023-10-11  8:59 ` Florian Weimer
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Carlotti @ 2023-10-10 17:35 UTC (permalink / raw)
  To: gcc; +Cc: daniel.kiss, pavel.iliin

Hi,

I've been looking into existing function multiversioning implementations (while
working to add support for fmv in GCC on aarch64).  It seems there are various
inconsistencies among current implementations, and it's unclear to me which (if
any) of these differences could be problematic.  There's a list of observations
of current behaviour at the end of the email.

I've also seen the GCC documentation for the ifunc attribute [1].  This states
that "the indirect function needs to be defined in the same translation unit as
the resolver function".  This is not how function multiversioning is currently
implemented.  Instead, the resolver functions are added to the translation
units of every caller.  What is the reason for the restriction specified in the
documentation?  Does this mean that current function multiversioning
implementations are subtly broken when used across different translation units?

On a related point - how important is the mangling of the symbols involved (for
the function implementations, the resolver, and the symbol that will be
resolved at load time)?  We're not consistent about how we mangle these on any
target - even the explicit mangling requirements in the aarch64 Beta
specification [2] apply only to the function implementations, and make no
mention of how the other symbols should be mangled.

It seems to me that things would have been much simpler if the resolver were
always in the same translation unit as the implementations, and the symbol that
is resolved at run time used the original function symbol name.  This would
allow the mangling of the function versions and the resolver function to be a
hidden implementation detail, with no need to specify it as part of an explicit
or implicit ABI.  It would add an explicit restriction that all function
implementations must be in the same translation unit, but it seems that might
be required for absolute correctness anyway.

So, how much of this stuff matters?  Is some of this stuff actually broken?
Will we have horrible compatibility issues if we try to fix some of it?

Thanks,
Andrew

(cc'd to Daniel Kiss and Pavel Iliin, who have been working on the aarch64
function multiversioning specification and LLVM implementation respectively.)

---
Current behaviour:


For all combinations of the following, I checked to see whether the compiler
would emit a resolver function:
a) GCC / Clang
b) aarch64 / rs6000 / i386
c) target_clones attribute / target (or target_version) attribute
d) function is fully implemented / function is just declared
e) function is referenced / function is unreferenced

Function multiversioning is not supported for rs6000 (power) in Clang.  For
aarch64, I used my WIP implementation in GCC.

If the function was referenced, then the compiler always emitted a resolver.
However, when the function is declared but not implemented, then GCC for rs6000
would emit a resolver that always used the default version.

If the function was not referenced, then the compiler usually did not emit a
resolver.  The exceptions to this were both in GCC, with resolvers being
emitted both for rs6000 when using an implemented function with target_clones,
and for aarch64 (with my WIP patch) when using an implementations with
target_version.


There are also many discrepancies in the mangling used in the various symbol
names:

For the symbol that will be resolved at load time, Clang always uses the
original name and append ".ifunc".  GCC leaves the symbol name unchanged when
using target_clones, but adds a second layer of C++ mangling when using target
attribute versions.

For the resolver function, the symbol name is always generated by appending
".resolver" to the original mangled function name.

For the individual versions, the following changes are made:
- Clang for i386 numbers the versions when using target_clones (by appending
  ".0", ".1", etc.).  GCC used to share this behaviour, but the numbering was
removed for GCC 12 (commit bfc9250e).
- GCC for i386, when using target_clones, will substitute any non-alphanumeric
  character with "_" when formign the suffix.  E.g, an "sse4.2" version of foo
has a symbol name of "_Z3foov.sse4.2" using target attributes, but
"_Z3foov.sse4_2" using target_clones.
- GCC for rs6000 has no target-defined mangling for versions using the "target"
  attribute, so the compiler output will fail to assemble due to duplicate
symbol names.  However, there seem to be no errors or warnings to detect this
at an earlier stage.

(Incidentally, is there any specific documentation for rs6000 function
multiversioning? I was surprised to discover during testing that the resolver
was ignoring some of my function clones, until I found the list of supported
multiversioning targets in rs6000_clone_map.)

---

[1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Common-Function-Attributes.html#index-ifunc-function-attribute

[2] https://github.com/ARM-software/acle/blob/main/main/acle.md#function-multi-versioning

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Function multiversioning ABI issues
  2023-10-10 17:35 Function multiversioning ABI issues Andrew Carlotti
@ 2023-10-11  8:59 ` Florian Weimer
  2023-10-11  9:17   ` Andrew Carlotti
  0 siblings, 1 reply; 3+ messages in thread
From: Florian Weimer @ 2023-10-11  8:59 UTC (permalink / raw)
  To: Andrew Carlotti via Gcc; +Cc: Andrew Carlotti, daniel.kiss, pavel.iliin

* Andrew Carlotti via Gcc:

> I've also seen the GCC documentation for the ifunc attribute [1].
> This states that "the indirect function needs to be defined in the
> same translation unit as the resolver function".  This is not how
> function multiversioning is currently implemented.  Instead, the
> resolver functions are added to the translation units of every caller.

I don't see how this can happen.  Do you have a declaration of the
resolver function in a shared header, by chance?

Thanks,
Florian


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Function multiversioning ABI issues
  2023-10-11  8:59 ` Florian Weimer
@ 2023-10-11  9:17   ` Andrew Carlotti
  0 siblings, 0 replies; 3+ messages in thread
From: Andrew Carlotti @ 2023-10-11  9:17 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Andrew Carlotti via Gcc, daniel.kiss, pavel.iliin

On Wed, Oct 11, 2023 at 10:59:10AM +0200, Florian Weimer wrote:
> * Andrew Carlotti via Gcc:
> 
> > I've also seen the GCC documentation for the ifunc attribute [1].
> > This states that "the indirect function needs to be defined in the
> > same translation unit as the resolver function".  This is not how
> > function multiversioning is currently implemented.  Instead, the
> > resolver functions are added to the translation units of every caller.
> 
> I don't see how this can happen.  Do you have a declaration of the
> resolver function in a shared header, by chance?
> 
> Thanks,
> Florian

I haven't explicity declared a separate function. I just included the normal
function multiversioning attributes on the function declarations.

If you don't include the attributes on the declarations, then you will get one
of two issues:

- For target_clones, you would need to ensure that the mutiversioned function
  has a caller in the same translation unit as the implementations. If you 
  don't do this, then no resolver will be generated, with all of the callers
  referencing a non-existent symbol.

- For target versions, any caller that cannot see the function multiversioning
  attributes will only ever use the default version of the function. This also
  applies to the current aarch64 specification for target_clones and
  target_version.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-10-11  9:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-10 17:35 Function multiversioning ABI issues Andrew Carlotti
2023-10-11  8:59 ` Florian Weimer
2023-10-11  9:17   ` Andrew Carlotti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).