Skip to content

Text format #16

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion proposals/compilation-hints/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The following contains a list of hints to be included in the first version of th
The section `metadata.code.compilation_order` contains the order in which functions should be compiled in order to minimize wait times until the compilation is completed. This is especially relevant during instantiation and startup but might also be relevant later.
* *byte offset* |U32| with value 0 (function level only)
* *hint length* |U32| in bytes
* *compilation order* |U32| starting at 0 (functions with the same order value will be compiled in an arbitrary order but before functions with a higher order value)
* *compilation priority* |U32| starting at 0 (functions with the same order value will be compiled in an arbitrary order but before functions with a higher order value)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* *compilation priority* |U32| starting at 0 (functions with the same order value will be compiled in an arbitrary order but before functions with a higher order value)
* *compilation priority* |U32| starting at 0 (functions with the same priority value will be compiled in an arbitrary order but before functions with a higher priority value)

Should the hint itself be renamed to metadata.code.compilation_priority?

* *hotness* |U32| defining how often this function is called

If a length of larger than required to store 2 values is present, only the first two values of the following hint data is evalued while the rest is ignored. This leaves space for future extensions, e.g. grouping functions. Similarly, the *hotness* can be dropped if a length corresponds to only 1 value is given.
Expand All @@ -49,6 +49,22 @@ It is expected and even desired that not all functions are annotated to keep thi
*Note: This should be moved to `metadata.function.compilation_order` without the byte offset if such a namespace will be supported by custom annotations.*


#### Text format

Instead of a binary string representation, these hints can also be provided using a more human readable notation in text format:
```
@metadata.code.compilation_order(
(priority 1)
(hotness 100)
)
Copy link
Member

Choose a reason for hiding this comment

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

Looks like the current branch hints have this form:

(@metadata.code.branch_hint "\01")
(..instruction attached to..)

Perhaps we can follow that? That is,

Suggested change
@metadata.code.compilation_order(
(priority 1)
(hotness 100)
)
(@metadata.code.compilation_order
(priority 1)
(hotness 100)
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, of course. I misremembered the syntax.

```
The above example is equivalent to
```
@metadata.code.compilation_order("\01\64")
```
and tools can produce one or the other.


### Instruction frequencies

Instruction frequencies might be useful to guide optimizations like inlining, loop unrolling, block deferrals, etc. Within a function, these frequencies inform which blocks lie on the hot path and deserve more expensive optimizations, as well as which are on the cold path and might even allow very expensive steps to even execute the code within (e.g. outlining or de-optimization). An engine can take those decisisions based on the instruction frequency observed, but cannot assume that any part of the code is unreachable based on the instruction frequency.
Expand Down Expand Up @@ -88,6 +104,23 @@ Special values of 0 and 127 indicate that a function should never or always be i
| 127| |*always optimize* |


#### Text format

The alternative text format representation for such a section would look as follows
```
@metadata.code.instr_freq(
(freq 123.45)
)
```
The given frequency $\frac{n}{N}$ is then converted into the equivalent binary representation
```
@metadata.code.instr_freq("\26")
```
according to the formula above.

Alternatively to `freq` followed by a numeric value, one can provide `never_opt` and `always_opt` with binary representations of `"\00"` and `"\7f"` respectively.
Copy link
Member

Choose a reason for hiding this comment

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

Just to bikeshed a bit, what do you think about never and always instead of never_opt and always_opt?



### Call targets

When dealing with `call_indirect` or `call_ref`, often inefficient code is generated, because the call target is unknown. With code that e.g. uses virtual function calls, there are often very few commonly called targets which a compiler could optimize for. It still needs to have the ability to handle other call targets, but that can then happen at a much lower performance in favor of optimizing for the more commonly called target.
Expand All @@ -104,3 +137,19 @@ The `metadata.code.call_targets` section contains instruction level annotations
The accumulated call frequency must add up to 100 or less. If it is less than 100, then other call targets that are not listed are responsible for the missing calls. Together with the inline hints on call frequency, this can information can be used to inline function calls as well. The effective call frequency for each call target is then the inlining call frequency multiplied by the fractional call frequency encoded in this section.

Similarly to the compilation order section, not all call sites need to be annotated and not all call targets be listed. However, if other call targets are known but not emitted, then the frequency must be below 100 to inform the engine of the missing information.


#### Text format

The text representation allows for multiple targets
```
@metadata.code.call_targets(
(target $func1 0.73)
(target $func2 0.21)
)
```
which would be converted into binary format as
```
@metadata.code.call_targets("\01\49\02\15)
```
under the assumption that `$func1` and `$func2` have function indices 1 and 2 respectively.