Skip to content

Commit afd6b56

Browse files
Minor modification to FMV rules for scope and signatures (#363)
Hi all, While attempting to implement FMV in the GCC front-end some questions were raised that I think are worth clarifying here. This PR changes the rules to use the default function to determine the signature and scope of the versioned function set. This clears up some cases such as: ```C int fn (int c = 1); int __attribute__((target_version("sve"))) fn (int c = 2); int bar() { return fn(); } ``` Where there are conflicting signatures and which default should be used is not clear at the moment. ```C int fn (int c[]); int __attribute__((target_version("default"))) fn (int c[1]) { } int __attribute__((target_version("sve"))) fn (int c[2]) { } ``` Where if this should be considered a conflicting signature is not clear. ```C int __attribute__((target_version("default"))) fn (int x) { return 1; } void bar () { int __attribute__((target_version("sve2"))) fn (int); fn(1); } ``` Where the scope of multi-versioned functions differs. And ```C // TU 1 #import TU2 int fn (int c = 1); int bar() { return fn(); } // TU 2 int __attribute__((target_version("sve"))) fn (int c = 2); int __attribute__((target_version("sve2"))) fn (int c = 2); int bar() { return fn(); } ``` Where it is possible calls in different TU's could use different default argument values.
1 parent 80b917a commit afd6b56

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

Diff for: main/acle.md

+37-8
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ Armv8.4-A [[ARMARMv84]](#ARMARMv84). Support is added for the Dot Product intrin
433433
than the [NEON-SVE bridge](#neon-sve-bridge) intrinsics.
434434
* Removed extraneous `const` from SVE2.1 store intrinsics.
435435
* Added [`__arm_agnostic`](#arm_agnostic) keyword attribute.
436+
* Refined function versioning scope and signature rules to use the default
437+
version scope and signature.
436438

437439
### References
438440

@@ -2675,10 +2677,12 @@ The following attributes trigger the multi version code generation:
26752677
`__attribute__((target_version("name")))` and
26762678
`__attribute__((target_clones("name",...)))`.
26772679

2680+
* Functions are allowed to have the same name and signature when
2681+
annotated with these attributes.
26782682
* These attributes can be mixed with each other.
2683+
* `name` is the dependent features from the tables below.
26792684
* The `default` version means the version of the function that would
26802685
be generated without these attributes.
2681-
* `name` is the dependent features from the tables below.
26822686
* The dependent features could be joined by the `+` sign.
26832687
* None of these attributes will enable the corresponding ACLE feature(s)
26842688
associated to the `name` expressed in the attribute.
@@ -2687,21 +2691,46 @@ The following attributes trigger the multi version code generation:
26872691
* If only the `default` version exist it should be linked directly.
26882692
* FMV may be disabled in compile time by a compiler flag. In this
26892693
case the `default` version shall be used.
2694+
* All function versions must be declared at the same scope level.
2695+
* The default version signature is the signature for calling
2696+
the multiversioned functions. Therefore, a versioned function
2697+
cannot be called unless the declaration of the default version
2698+
is visible in the scope of the call site.
2699+
* Non-default versions shall have a type that is convertible to the
2700+
type of the default version.
2701+
* All the function versions must be declared at the translation
2702+
unit in which the definition of the default version resides.
26902703

26912704
The attribute `__attribute__((target_version("name")))` expresses the
26922705
following:
26932706

2694-
* when applied to a function it becomes one of the versions. Function
2695-
with the same name may exist with multiple versions in the same
2696-
or in different translation units.
2707+
* When applied to a function it becomes one of the versions.
2708+
* Multiple function versions may exist in the same or in different
2709+
translation units.
26972710
* One `default` version of the function is required to be provided
26982711
in one of the translation units.
26992712
* Implicitly, without this attribute,
27002713
* or explicitly providing the `default` in the attribute.
2701-
* All instances of the versions shall share the same function
2702-
signature and calling convention.
2703-
* All the function versions must be declared at the translation
2704-
unit in which the definition of the default version resides.
2714+
2715+
For example, the below is valid and 2 is used as the default
2716+
value for `c` when calling the multiversioned function `f`.
2717+
2718+
```cpp
2719+
int __attribute__((target_version("simd"))) f (int c = 1);
2720+
int __attribute__((target_version("default"))) f (int c = 2);
2721+
int __attribute__((target_version("sve"))) f (int c = 3);
2722+
2723+
int g() { return f(); }
2724+
```
2725+
2726+
Additionally, the below is not valid as the two statements declare
2727+
the same entity (the `default` version of `f`) with conflicting
2728+
signatures.
2729+
2730+
```cpp
2731+
int f (int c = 1);
2732+
int __attribute__((target_version("default"))) f (int c = 2);
2733+
```
27052734

27062735
The attribute `__attribute__((target_clones("name",...)))` expresses the
27072736
following:

0 commit comments

Comments
 (0)