Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FMV] Add Priority syntax for version selection order #85

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
45 changes: 38 additions & 7 deletions riscv-c-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,12 @@ Each `TARGET-CLONES-ATTR-STRING` defines a distinguished version of the function
The syntax of `<TARGET-CLONES-ATTR-STRING>` describes below:

```
TARGET-CLONES-ATTR-STRING := 'arch=' EXTENSIONS
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you may have re-odered the BPF. Please undo this as it makes the diff really hard to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it look better now?

| 'default'
TARGET-CLONES-ATTR-STRING := ATTR-STRING
| ';' TARGET-VERSION-ATTR-STRING
BeMg marked this conversation as resolved.
Show resolved Hide resolved

ATTR-STRING := 'arch=' EXTENSIONS
| 'default'
| 'priority=' DIGIT

EXTENSIONS := <EXTENSION> ',' <EXTENSIONS>
| <EXTENSION>
Expand All @@ -313,13 +317,15 @@ VERSION := [0-9]+ 'p' [0-9]+
| [1-9][0-9]*
|

DIGIT := [0-9]+

EXTENSION-NAME := Naming rule is defined in RISC-V ISA manual
```

For example, the following `foo` function will have three versions but share the same function signature.

```c
__attribute__((target_clones("arch=+v", "default", "arch=+zbb")))
__attribute__((target_clones("arch=+v;priority=2", "default", "arch=+zbb;priority=1")))
int foo(int a)
{
return a + 5;
Expand All @@ -331,6 +337,8 @@ int bar() {
}
```

The `priority` accepts a digit as the version priority during [Version Selection](#version-selection). If `priority` doesn't exist, then the priority of version defaults to zero.
BeMg marked this conversation as resolved.
Show resolved Hide resolved

It makes the compiler trigger the [function multi-version](#function-multi-version) when there exist more than one version for the same function signature.

### `__attribute__((target_version("<TARGET-VERSION-ATTR-STRING>")))`
Expand All @@ -342,8 +350,13 @@ Each `TARGET-VERSION-ATTR-STRING` defines a distinguished version of the functio
The syntax of `<TARGET-VERSION-ATTR-STRING>` describes below:

```
TARGET-VERSION-ATTR-STRING := 'arch=' EXTENSIONS
| 'default'

TARGET-VERSION-ATTR-STRING := ATTR-STRING
| ';' TARGET-VERSION-ATTR-STRING

ATTR-STRING := 'arch=' EXTENSIONS
| 'default'
| 'priority=' DIGIT

EXTENSIONS := <EXTENSION> ',' <EXTENSIONS>
| <EXTENSION>
Expand All @@ -356,19 +369,21 @@ VERSION := [0-9]+ 'p' [0-9]+
| [1-9][0-9]*
|

DIGIT := [0-9]+

EXTENSION-NAME := Naming rule is defined in RISC-V ISA manual
```

For example, the following foo function has three versions.

```c
__attribute__((target_version("arch=+v")))
__attribute__((target_version("arch=+v;priority=1")))
int foo(int a)
{
return a + 5;
}

__attribute__((target_version("arch=+zbb")))
__attribute__((target_version("arch=+zbb;priority=2")))
int foo(int a)
{
return a + 5;
Expand All @@ -386,6 +401,8 @@ int bar() {
}
```

The `priority` accepts a digit as the version priority during [Version Selection](#version-selection). If `priority` doesn't exist, then the priority of version defaults to zero.
BeMg marked this conversation as resolved.
Show resolved Hide resolved

It makes the compiler trigger the [function multi-version](#function-multi-version) when there exist more than one version for the same function signature.

### riscv_vector_cc
Expand Down Expand Up @@ -708,3 +725,17 @@ statements, including both RISC-V specific and common operand modifiers.
Function multi-versioning(FMV) provides an approach to selecting the appropriate function according to the runtime environment. The final binary may contain all versions of the function, with the compiler generating all supported versions and the runtime selecting the appropriate one.

This feature is triggered by `target_version/target_clones` function attribute.

### Version Selection

The process of selecting the appropriate function version during function multi-versioning follows these guidelines:

1. The implementation of the selection algorithm is platform-specific.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change "platform-specific" to "implementation-specific". This allows e.g. different toolchains to have different tie breakers while still following the priority rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

2. Once a version is selected, it remains in use for the entire duration of the process.
3. Only versions whose required features are all available in the runtime environment are eligible for selection.

The version selection process applies the following rules in order:

1. Among the eligible versions, select the one with the highest priority.
2. If multiple versions have equal priority, select the one that was declared first.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to mandate (2)? We can leave ourselves more flexibility by saying "select one based on an implementation defined heuristic".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a good idea to maintain more flexibility. Updated. Thanks!

3. If no other suitable versions are found, fall back to the "default" version.