Skip to content

Commit f50a572

Browse files
authored
[RISC-V] Synthesizing PC-relative pointer constants (#119203)
RISC-V is ill-equipped to synthesize large >32-bit constants like absolute pointers, it results in a 6-8 instruction sequence. If an address can be synthesized as PC-relative (2 instructions: `auipc + ld/addi`), do so. It also simplifies codegen. Part of #84834, cc @dotnet/samsung
1 parent e4f710e commit f50a572

File tree

22 files changed

+460
-393
lines changed

22 files changed

+460
-393
lines changed

src/coreclr/inc/corinfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,9 @@ enum class CorInfoReloc
902902
LOONGARCH64_JIR, // LoongArch64: pcaddu18i+jirl
903903

904904
// RISCV64 relocs
905-
RISCV64_PC, // RiscV64: auipc
905+
RISCV64_CALL_PLT, // RiscV64: auipc + jalr
906+
RISCV64_PCREL_I, // RiscV64: auipc + I-type
907+
RISCV64_PCREL_S, // RiscV64: auipc + S-type
906908
};
907909

908910
enum CorInfoGCType

src/coreclr/inc/utilcode.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,14 +3236,14 @@ void PutLoongArch64PC12(UINT32 * pCode, INT64 imm);
32363236
void PutLoongArch64JIR(UINT32 * pCode, INT64 imm);
32373237

32383238
//*****************************************************************************
3239-
// Extract the PC-Relative offset from auipc + I-type adder (addi/ld/jalr)
3239+
// Extract the PC-Relative offset from auipc + I-type or S-type adder (addi/load/store/jalr)
32403240
//*****************************************************************************
3241-
INT64 GetRiscV64AuipcItype(UINT32 * pCode);
3241+
INT64 GetRiscV64AuipcCombo(UINT32 * pCode, bool isStype);
32423242

32433243
//*****************************************************************************
3244-
// Deposit the PC-Relative offset into auipc + I-type adder (addi/ld/jalr)
3244+
// Deposit the PC-Relative offset into auipc + I-type or S-type adder (addi/load/store/jalr)
32453245
//*****************************************************************************
3246-
void PutRiscV64AuipcItype(UINT32 * pCode, INT64 offset);
3246+
void PutRiscV64AuipcCombo(UINT32 * pCode, INT64 offset, bool isStype);
32473247

32483248
//*****************************************************************************
32493249
// Returns whether the offset fits into bl instruction
@@ -3285,6 +3285,19 @@ inline bool FitsInRel28(INT64 val64)
32853285
return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
32863286
}
32873287

3288+
//*****************************************************************************
3289+
// Returns whether the offset fits into a RISC-V auipc + I-type or S-type instruction combo
3290+
//*****************************************************************************
3291+
inline bool FitsInRiscV64AuipcCombo(INT64 val64)
3292+
{
3293+
// A PC relative load/store/jalr/addi is 2 instructions, e.g.:
3294+
// auipc reg, offset_hi20 # range: [0x80000000, 0x7FFFF000]
3295+
// ld reg, reg, offset_lo12 # range: [0xFFFFF800, 0x000007FF]
3296+
// Both hi20 and lo12 immediates are sign-extended and combined with a 64-bit adder,
3297+
// which shifts the total 32-bit range into the negative by half of the 12-bit immediate range.
3298+
return (val64 >= -(1ll << 31) - (1ll << 11)) && (val64 < (1ll << 31) - (1ll << 11));
3299+
}
3300+
32883301
//
32893302
// TEB access can be dangerous when using fibers because a fiber may
32903303
// run on multiple threads. If the TEB pointer is retrieved and saved

0 commit comments

Comments
 (0)