Skip to content

Add new relocation type for global array accesses with non-constant indices.#489

Open
LiqinWeng wants to merge 2 commits intoriscv-non-isa:masterfrom
LiqinWeng:add-new-rel
Open

Add new relocation type for global array accesses with non-constant indices.#489
LiqinWeng wants to merge 2 commits intoriscv-non-isa:masterfrom
LiqinWeng:add-new-rel

Conversation

@LiqinWeng
Copy link

Relocation Type Includes: R_RISCV_REGREL_ADD/R_RISCV_REGREL_SHXADD/R_RISCV_REGREL_LO12_I/R_RISCV_REGREL_LO12_S

The RISC-V architecture addresses non-constant subscript elements using lui + addi + add + ld/st. The low-address calculation process of addi instruction is offloaded th the ld/st, thereby eliminating low-address calculation and reducing addressing instructions.

The scenario is as follows: same as sh1add/sh2add/sh3add

lui     vr1, %hi(sym)
addi    vr1, vr1, %lo(sym)
add     vr2, vrx, vr1
lbu     vr3, off(vr2)

After Compiler Transformation

lui     vr1, %hi(sym+off)
add     vr2, vrx, vr1, %regrel_add(sym+off)
lbu     vr3, %regrel_lo(sym+off)(vr2)

After Linker Relaxation:

add vr2, vrx, gp
lbu vr3, <gp-relative-offset>(vr2)

Need update the ld/st's offset and add/sh1add/sh2add/sh3add's src2 be replace by gp, so need add new relocation deal with this scenario.

…ndices.

Relocation Type: R_RISCV_REGREL_ADD/R_RISCV_REGREL_SHXADD/R_RISCV_REGREL_LO12_I/R_RISCV_REGREL_LO12_S

The RISC-V architecture addresses non-constant subscript elements using lui + addi + add + ld/st. The low-address calculation process of addi instruction is offloaded th the ld/st, thereby eliminating low-address calculation and reducing addressing instructions.

The scenario is as follows: same as sh1add/sh2add/sh3add
```
lui     vr1, %hi(sym)
addi    vr1, vr1, %lo(sym)
add     vr2, vrx, vr1
lbu     vr3, off(vr2)
```
 After Compiler Transformation
```
lui     vr1, %hi(sym+off)
add     vr2, vrx, vr1, %regrel_add(sym+off)
lbu     vr3, %regrel_lo(sym+off)(vr2)
```
After Linker Relaxation:
```
add vr2, vrx, gp
lbu vr3, <gp-relative-offset>(vr2)
```
Need update the ld/st's offset and add/sh1add/sh2add/sh3add's src2 be replace by gp, so need add new relocation deal with this scenario.
@LiqinWeng
Copy link
Author

cc @lenary

Copy link
Contributor

@lenary lenary left a comment

Choose a reason for hiding this comment

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

Initial comments, to facilitate reviews.

These seem reasonable improvements to me, if we're continuing down the route of adding more relaxations and are willing to do marker relocations.

I think it is reasonable that the REGREL_* relocations take the global symbol they relate to, but this does prevent them being implicitly relax (as we want to use the symbol in R_RISCV_RELAX for an arch string), which will cause a blow-up in the static relocation tables. That's the price of more linker relaxations, I feel.

riscv-elf.adoc Outdated
Comment on lines +591 to +599
.2+| 67 .2+| REGREL_LO12_I .2+| Static | _I-Type_ .2+| Low 12 bits of 32-bit Global Array Offset, `%regrel_lo(symbol)`
<|
.2+| 68 .2+| REGREL_LO12_S .2+| Static | _S-Type_ .2+| Low 12 bits of 32-bit Global Array Offset, `%regrel_lo(symbol)`
<|
.2+| 69 .2+| REGREL_ADD .2+| Static | .2+| Global Array usage, `%regrel_add(symbol)`
<|
.2+| 70 .2+| REGREL_SHXADD .2+| Static | .2+| Global Array usage, `%regrel_shxadd(symbol)`
<|
.2+| 71-76 .2+| *Reserved* .2+| - | .2+| Reserved for Y base ISA
Copy link
Contributor

Choose a reason for hiding this comment

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

67-76 are reserved for a specific use - these relocations do not relate to Y base ISA. Please use values from 77 onwards.

Copy link
Author

Choose a reason for hiding this comment

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

done~

riscv-elf.adoc Outdated
[,asm]
----
add tY, tY, gp
lw t1, <address-of-symbol>(tY)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
lw t1, <address-of-symbol>(tY)
lw t1, <gp-offset-for-symbol>(tY)

Copy link
Author

Choose a reason for hiding this comment

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

Could you take a look : llvm/llvm-project#185586 (comment) like to know if adding the handling logic for the inst scenarios below introduces any potential , as: add.uw/sh1add.uw/sh2add.uw/sh3add.uw

Comment on lines +1893 to +1894
Target Relocation:: R_RISCV_HI20, R_RISCV_REGREL_LO12_I, R_RISCV_REGREL_LO12_S,
R_RISCV_REGREL_ADD, R_RISCV_REGREL_SHXADD
Copy link
Contributor

Choose a reason for hiding this comment

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

Please split off the R_RISCV_REGREL_SHXADD relaxation into a separate description, or add a shxadd example below (either way, an example is needed, as that relaxation is more complex).

Copy link
Author

Choose a reason for hiding this comment

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

done~

@LiqinWeng
Copy link
Author

LiqinWeng commented Mar 20, 2026

cc @topperc @MaskRay

@kito-cheng
Copy link
Collaborator

Hi @LiqinWeng, thanks for this proposal!

There is few review comment:

I think REGREL_ADD and REGREL_SHXADD can be merged into one relocation. Both add and shXadd just rewrite rs2 to gp. The linker can check the instruction encoding to know whether it is add or shXadd if needed, so there is no need to use different relocation types for them.

Also, I suggest adding a set of PCREL_REGREL_* relocations for medany code model support. The current REGREL_* only works with medlow (using lui). With PCREL_REGREL_*, medany (using auipc) can also benefit from this indexed array access relaxation. I was think we could reuse the same relocations for both models — the difference is just whether the relocation points to a symbol or a local label — but that would make the linker implementation more complex. Using separate relocation types is simpler and makes the semantics clearer.

@jrtc27
Copy link
Collaborator

jrtc27 commented Mar 20, 2026

REGREL is a bit of a strange name. I imagine you've done it because of TPREL, but that's a bit different. With TPREL for TLS, TP is a pointer, and you materialise the offset of the TLS symbol within the static TLS block in a register that you add to TP (and since that's an offset not an address, you're always using lui+addi, never auipc+addi). With your proposed REGREL, the GPR in question isn't a pointer, it's some additional offset, and it's the lui+addi that's the pointer (and hence why auipc+addi would be needed for medany/PIE/PIC). This naming therefore seems backwards.

@lenary
Copy link
Contributor

lenary commented Mar 20, 2026

I think REGREL_ADD and REGREL_SHXADD can be merged into one relocation. Both add and shXadd just rewrite rs2 to gp. The linker can check the instruction encoding to know whether it is add or shXadd if needed, so there is no need to use different relocation types for them.

One question for the case of add is whether we also want to support rewriting rs1 instead (we cannot for the shxadd). Maybe this is something we derive from the encoding though.

@kito-cheng
Copy link
Collaborator

I think REGREL_ADD and REGREL_SHXADD can be merged into one relocation. Both add and shXadd just rewrite rs2 to gp. The linker can check the instruction encoding to know whether it is add or shXadd if needed, so there is no need to use different relocation types for them.

One question for the case of add is whether we also want to support rewriting rs1 instead (we cannot for the shxadd). Maybe this is something we derive from the encoding though.

I'm inclined to require that REGREL_ADD always rewrites rs2 for add. Since add is commutative, the compiler can choose the operand order without cost, so constraining the lui result to rs2 has zero cost on the compiler side. The alternative would be either introducing two relocation types (one for rs1, one for rs2), or having the linker figure out which operand to rewrite — which would require pairing with R_RISCV_HI20 or some register tracking analysis that we don't currently do.

@kito-cheng
Copy link
Collaborator

REGREL is a bit of a strange name. I imagine you've done it because of TPREL, but that's a bit different. With TPREL for TLS, TP is a pointer, and you materialise the offset of the TLS symbol within the static TLS block in a register that you add to TP (and since that's an offset not an address, you're always using lui+addi, never auipc+addi). With your proposed REGREL, the GPR in question isn't a pointer, it's some additional offset, and it's the lui+addi that's the pointer (and hence why auipc+addi would be needed for medany/PIE/PIC). This naming therefore seems backwards.

Yeah, I agree the naming is a bit confusing. I didn't have a good idea when I first replied, but after thinking more, how about R_RISCV_BASE_IDX_ADD and R_RISCV_BASE_IDX_LO12_[I|S]? This better describes what the relocation actually is - a base + index addressing pattern.

I considered GPREL at first, but it would be even more confusing since the pattern has nothing to do with GP when relaxation doesn't happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants