-
Notifications
You must be signed in to change notification settings - Fork 250
Proposal: Exact Mode (Compression and Relaxation Control) #122
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
base: main
Are you sure you want to change the base?
Changes from all commits
a5c2ea9
ea694f4
834bfa3
52eaf1f
cb73122
7e7825f
0c76925
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -370,6 +370,75 @@ NOTE: `.option arch, +<ext>, -<ext>` is accepted and will result in enabling the | |
| extensions that depend on `ext`, e.g. `rv32i` + `.option arch, +v, -v` will result | ||
| `rv32ifd_zve32x_zve32f_zve64x_zve64f_zve64d_zvl32b_zvl64b_zvl128b`. | ||
|
|
||
| === `exact`/`noexact` | ||
|
|
||
| In RISC-V, the assembler and linker can do several things to change the code | ||
| that a user writes into a different sequence of instructions. There are features | ||
| which help static code size in the final executable: | ||
|
|
||
| - Compression turns longer instructions into shorter, equivalent instructions. | ||
| For example the assembler might turn `lw a0, 16(a1)` into `c.lw a0, 16(a1)` | ||
| when the C or Zca extensions are enabled. | ||
| - Linker Relaxation causes the linker to replace long symbol references with | ||
| shorter code sequences that can reference the same symbol (documented more | ||
| fully in the psABI document). | ||
|
|
||
| And also a feature which allows users to write a sequence of code which doesn't | ||
| match what appears in the final executable, but avoids assembler errors in some | ||
| cases: | ||
|
|
||
| - Branch Relaxation turns short branches of too long or unknown range into code | ||
| sequences with a longer range. For example `beq a0, a1, sym` will be turned | ||
| into `bne a0, a1, 4; j sym` because `j` has a longer range than `beq`. | ||
|
|
||
| The aim of `.option exact` is to prevent the assembler and linker from modifying | ||
| the written instruction sequence into a different instruction sequence. This | ||
| primarily affects assembler behaviour, but the assembler also should not emit | ||
| `R_RISCV_RELAX` relocations for affected instructions, which prevents the linker | ||
| relaxing the instruction sequence too. | ||
|
|
||
| `.option exact` can be seen as a version of `.option norelax` which also affects | ||
| the modifications made by the assembler as well as those made by the linker. | ||
|
|
||
| Without this option, compression is only controllable with `.option norvc` -- | ||
| which turns off the C extension, so also prevents users from writing the shorter | ||
| instructions directly. There is no similar mechanism for preventing longer | ||
| instructions being compressed into 32-bit instructions from the base ISA, as the | ||
| base ISA cannot be turned off. | ||
|
|
||
| This option does not change the currently enabled extensions, which allows | ||
| instructions of different lengths to still be used without error. | ||
|
|
||
| For example: | ||
|
|
||
| [source,asm] | ||
| ---- | ||
| .option arch, +zca | ||
|
|
||
| lw a0, 0(a0) # assembled as 'c.lw a0, 0(a0)' (2 bytes) | ||
| c.lw a0, 0(a0) # not changed | ||
|
|
||
| .option exact | ||
|
|
||
| lw a0, 0(a0) # not changed | ||
| c.lw a0, 0(a0) # not changed, no error | ||
|
|
||
| .option noexact | ||
|
|
||
| lw a0, 0(a0) # assembled as 'c.lw a0, 0(a0)' (2 bytes) | ||
| c.lw a0, 0(a0) # not changed | ||
| ---- | ||
|
|
||
| The default behaviour is `.option noexact`. | ||
|
|
||
| Enabling `.option exact` implies `.option norelax` from that point onwards, so | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'd better adding an example or a clarification (relation/interactions between For instance, LLVM seems to enable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For example, (if we prefer current LLVM semantics), adding the fact that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The semantics here are a bit dicey. Linker relaxations:
Exact:
I would follow LLVM (because both enabling it, and not enabling it again are equally confusing), but/and our docs should also encourage people towards push/pop. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lenary FYI, I decided to warn in the documentation about flaky interactions between
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @a4lg just to circle back on this, I'm finding that for testing the linker, the combination There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lenary I understand the value of testing the linker but this reason alone is unconvincing for me. Rather (on the patch set for GNU Binutils), I thought it would be better to endorse regular users from using both If there's a note which indicates that |
||
| this should be used with `.option push; .option exact; ... ; .option pop` to be | ||
| clear about when to re-enable relaxation. | ||
|
|
||
| The default behaviour of some disassemblers is to reverse this process and show | ||
| `lw a0, 0(a0)` when `c.lw a0, 0(a0)` is in the binary. This can be disabled in | ||
| objdump-compatible disassemblers using the options `-M no-aliases`. | ||
|
|
||
| === `pic`/`nopic` | ||
|
|
||
| Set the code model to PIC (position independent code) or non-PIC. This will | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel that the text is overly verbose. Grok suggests a concise one:
In RISC-V, the assembler and linker may modify user code to optimize the final executable:
Programmers may want unmodified assembly, but only linker relaxation can be disabled with .option norelax. Compression requires disabling extensions like .option norvc, which restricts smaller instructions and affects larger ones.
The .option exact prevents assembler or linker modifications, controlling both without altering enabled extensions, allowing flexible instruction lengths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if RISC-V International takes a view at the moment on using LLM-derived content in its specifications. Probably best not to get into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the bullet points from Sam's version are clear enough. Maybe Sam can rework / reduce a bit the 4 paragraphs that follow the bullet points with a bullet point for the limitations of no-relax and norvc options and the flexibility introduced with the exact option, to address Maskray's concern.