[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[RISC-V] Synthesizing PC-relative pointer constants - #119203

Merged
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers
Dec 1, 2025
Merged

[RISC-V] Synthesizing PC-relative pointer constants#119203
jakobbotsch merged 43 commits into
dotnet:mainfrom
tomeksowi:pc-rel-pointers

Conversation

@tomeksowi

Copy link
Copy Markdown
Member

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

@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Aug 29, 2025
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Aug 29, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@clamp03clamp03 added the arch-riscv Related to the RISC-V architecture label Sep 1, 2025
@tomeksowi

Copy link
Copy Markdown
MemberAuthor

@risc-vv /run

@risc-vv

risc-vv commented Sep 1, 2025

Copy link
Copy Markdown
RISC-V pull_request-CLR-QEMU: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 80h 13min 42s 134ms
REAL time: 1h 18min 35s 828ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-CLR-VF2: 9108 / 9139 (99.66%)
=======================
passed: 9108
failed: 3
skipped: 586
killed: 28
------------------------
TOTAL tests: 9725
VIRTUAL time: 32h 6min 37s 777ms
REAL time: 2h 7min 32s 224ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-QEMU: 0 / 0 (100.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 0
------------------------
TOTAL tests: 14
VIRTUAL time: 0ms
REAL time: 4h 30min 0s 477ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V pull_request-FX-VF2: 0 / 61 (0.00%)
=======================
passed: 0
failed: 0
skipped: 14
killed: 61
------------------------
TOTAL tests: 75
VIRTUAL time: 1min 14s 744ms
REAL time: 13h 0min 6s 48ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: bd0e79cc0470c7eae53ef67028e7c567c9fb9846
CI: 0dd2da79b21e6d27378407c3af1305973fd300aa
REPO: dotnet/runtime
BRANCH: main
CONFIG: Checked
LIB_CONFIG: Release

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

No regressions. Quite a bit of post-bringup cruft went out the window.

Diffs are based on 104,367 contexts (2,270 MinOpts, 102,097 FullOpts).

MISSED contexts: 2 (0.00%)

Overall (-9,469,872 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch71,889,656-9,469,872-7.46%
MinOpts (-2,342,108 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch16,685,964-2,342,108-7.73%
FullOpts (-7,127,764 bytes)
CollectionBase size (bytes)Diff size (bytes)PerfScore in Diffs
linux.riscv64.Checked.3.mch55,203,692-7,127,764-7.45%
Example diffs
linux.riscv64.Checked.3.mch
-48 (-41.38%) : 53568.dasm - Program:Main():int (FullOpts)
@@ -20,35 +20,23 @@ G_M24375_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
mv fp, sp
;; size=16 bbWeight=1 PerfScore 9.00
G_M24375_IG02: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // <unknown method>
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a0, 0xD1FFAB1E(t6)+ auipc a0, 0xD1FFAB1E+ ld a0, 0xD1FFAB1E(a0)
jalr a0 // Test:Ret():int
- ;; size=84 bbWeight=1 PerfScore 30.00+ ;; size=36 bbWeight=1 PerfScore 15.00
G_M24375_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
addi sp, sp, 16
ret ;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 116, prolog size 16, PerfScore 46.50, instruction count 17, allocated bytes for code 116 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)+; Total bytes of code 68, prolog size 16, PerfScore 31.50, instruction count 14, allocated bytes for code 68 (MethodHash=d9b8a0c8) for method Program:Main():int (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +47,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 58 (0x0003a) Actual length = 116 (0x000074)+ Function Length : 34 (0x00022) Actual length = 68 (0x000044)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
-32 (-40.00%) : 54962.dasm - ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
@@ -21,26 +21,18 @@ G_M64910_IG01: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=0 PerfScore 0.00
G_M64910_IG02: ; bbWeight=0, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Capture(System.Exception):System.Runtime.ExceptionServices.ExceptionDispatchInfo
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 12- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 3- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
lw zero, 0xD1FFAB1E(a0)
jalr a1 // System.Runtime.ExceptionServices.ExceptionDispatchInfo:Throw():this
; gcrRegs -[a0]
ebreak
- ;; size=64 bbWeight=0 PerfScore 0.00+ ;; size=32 bbWeight=0 PerfScore 0.00-; Total bytes of code 80, prolog size 16, PerfScore 0.00, instruction count 12, allocated bytes for code 80 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)+; Total bytes of code 48, prolog size 16, PerfScore 0.00, instruction count 10, allocated bytes for code 48 (MethodHash=95e60271) for method ExceptionExtensions:RethrowWithNoStackTraceLoss(System.Exception) (FullOpts)
; ============================================================
Unwind Info:
@@ -51,7 +43,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 40 (0x00028) Actual length = 80 (0x000050)+ Function Length : 24 (0x00018) Actual length = 48 (0x000030)
---- Epilog scopes ----
No epilogs
---- Unwind codes ----
-40 (-38.46%) : 856.dasm - Interop:g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
@@ -22,25 +22,15 @@ G_M36700_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
;; size=16 bbWeight=1 PerfScore 9.00
G_M36700_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 13- addi t6, t6, 0xD1FFAB1E- slli t6, t6, 2- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.PathInternal:TrimEndingDirectorySeparator(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)
jalr a1 // System.IO.Path:GetDirectoryName(System.String):System.String
- lui t6, 0xD1FFAB1E- addiw t6, t6, 0xD1FFAB1E- slli t6, t6, 32- srli t6, t6, 18- ld a1, 0xD1FFAB1E(t6)- ;; size=72 bbWeight=1 PerfScore 25.00+ auipc a1, 0xD1FFAB1E+ ld a1, 0xD1FFAB1E(a1)+ ;; size=32 bbWeight=1 PerfScore 12.00
G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
ld ra, 8(sp)
ld fp, 0(sp)
@@ -48,7 +38,7 @@ G_M36700_IG03: ; bbWeight=1, epilog, nogc, extend
jr a1 // System.IO.Directory:Exists(System.String):bool
;; size=16 bbWeight=1 PerfScore 7.50
-; Total bytes of code 104, prolog size 16, PerfScore 41.50, instruction count 16, allocated bytes for code 104 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)+; Total bytes of code 64, prolog size 16, PerfScore 28.50, instruction count 13, allocated bytes for code 64 (MethodHash=027470a3) for method Interop:<GetExceptionForIoErrno>g__ParentDirectoryExists|7_0(System.String):bool (FullOpts)
; ============================================================
Unwind Info:
@@ -59,7 +49,7 @@ Unwind Info:
E bit : 0
X bit : 0
Vers : 0
- Function Length : 52 (0x00034) Actual length = 104 (0x000068)+ Function Length : 32 (0x00020) Actual length = 64 (0x000040)
---- Epilog scopes ----
---- Scope 0
Epilog Start Offset : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)
+0 (0.00%) : 57024.dasm - UDivConst:U8_Div_3(ulong):ulong (FullOpts)

No diffs found?

+0 (0.00%) : 56976.dasm - SlowPathELTTests.SlowPathELTHelpers:MixedSseStructFunc():SlowPathELTTests.MixedSseStruct (FullOpts)

No diffs found?

Details

Size improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame sizeImprovements (bytes)Regressions (bytes)
linux.riscv64.Checked.3.mch78,13976,85401,285-9,469,872+0

PerfScore improvements/regressions per collection

CollectionContexts with diffsImprovementsRegressionsSame PerfScoreImprovements (PerfScore)Regressions (PerfScore)PerfScore Overall in FullOpts
linux.riscv64.Checked.3.mch78,13957,537020,602-9.99%0.00%-5.6031%

Context information

CollectionDiffed contextsMinOptsFullOptsMissed, baseMissed, diff
linux.riscv64.Checked.3.mch104,3672,270102,0972 (0.00%)2 (0.00%)

jit-analyze output

@tomeksowi

Copy link
Copy Markdown
MemberAuthor
+0 (0.00%) : 104032.dasm - Microsoft.Diagnostics.Tracing.TraceEvent:get_FormattedMessage():System.String:this (FullOpts)
@@ -22,6 +22,7 @@ G_M51530_IG01: ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
G_M51530_IG02: ; bbWeight=1, gcrefRegs=0400 {a0}, byrefRegs=0000 {}, byref
; gcrRegs +[a0]
mv a1, zero
+ ; gcrRegs +[a1]
ld a2, 0xD1FFAB1E(a0)
ld a2, 0xD1FFAB1E(a2)
ld a2, 0xD1FFAB1E(a2)

Looks like a bonus fix. Notice how this code I removed also silently stripped GC flags.

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs.
}

@tomeksowi
tomeksowi marked this pull request as ready for review September 2, 2025 06:23
@JulieLeeMSFT

Copy link
Copy Markdown
Member

We will review .NET 11 PRs when we are done with .NET 10 last minute works and less busy. Please give us a few more weeks.
CC @jakobbotsch.

@steveisoksteveisok added this to the 11.0.0 milestone Oct 6, 2025
@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

if (!compiler->opts.compReloc)
{
size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
}

For address 0 it is clearly not a problem -- would it be a problem for frozen objects?

@jakobbotsch

Copy link
Copy Markdown
Member

If an address can be synthesized as PC-relative (2 instructions: auipc + ld/addi), do so.

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

@tomeksowi

Copy link
Copy Markdown
MemberAuthor

Note that it's generally impossible to know where the code will be located, so you can only do this heuristically. How do you recover when you get it wrong?

For x64 we recover the situation by disabling rip-relative addressing globally the first time it happens, and then designing things so that it very rarely happens. Look for m_fAllowRel32.

I don't recover, the address of a handle with function address was always within range, but you're right, IsIconHandle(GTF_ICON_FTN_ADDR) is just a heuristic. I remember looking at m_fAllowRel32 briefly but abandoned it because it seemed linked to jump stubs which RISC-V doesn't use (and aren't applicable here since we're doing loads for the handles).

I'll try to use it, maybe communicating failure with m_fJumpStubOverflow = TRUE to reuse existing codepaths, then eeGetRelocTypeHint on the handle value should tell me which way to go.

@jakobbotsch

Copy link
Copy Markdown
Member

For x64 there is a contract between the JIT and VM about when and how relative addressing is used: for data addresses PC-relative addressing can only be used based on getRelocTypeHint. For code addresses PC-relative addressing can always be used, and the VM will create jump stubs if necessary.

If you are using PC-relative addressing for data addresses then I expect you need to build a similar system. If you are only using it for code addresses, then I expect you need to support some form of jump stubs.

@jakobbotsch

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

@EgorBo

Copy link
Copy Markdown
Member

@EgorBo Do we need a fix for arm64 version of the code @tomeksowi points at above?

Do you mean it may strip the GC related flags for frozen objects? I think we don't report them to GC anyway, do we?

Yes, that's what I meant. I was not sure if they GC refs to frozen objects need to be reported or not. If not then it seems ok.

I think in fact we do report them today, but don't have to

@am11am11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For linux-musl-riscv64

Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp Outdated
tomeksowiand others added 2 commits November 19, 2025 20:16
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/inc/utilcode.h Outdated
Comment threadsrc/coreclr/tools/Common/Compiler/ObjectWriter/ElfObjectWriter.cs Outdated
Comment threadsrc/coreclr/vm/jitinterface.cpp Outdated
@tomeksowi
tomeksowi marked this pull request as ready for review November 25, 2025 10:42
Conflicts:
src/coreclr/inc/corinfo.h
src/coreclr/jit/emitriscv64.cpp
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
src/coreclr/vm/jitinterface.cpp
@jkotas

Copy link
Copy Markdown
Member

VM side LGTM.

@dotnet/jit-contrib Could you please review the JIT side?

@jkotas
jkotas requested a review from a teamNovember 27, 2025 15:16
@jakobbotsch
jakobbotsch merged commit f50a572 into dotnet:mainDec 1, 2025
110 of 112 checks passed
jkotas pushed a commit that referenced this pull request Dec 15, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jan 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

arch-riscvRelated to the RISC-V architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants

@tomeksowi@risc-vv@JulieLeeMSFT@jakobbotsch@EgorBo@jkotas@kg@am11@steveisok@clamp03