Skip to content

RISC-V JIT Support#932

Merged
guillep merged 10 commits intopharo-project:pharo-12from
QDucasse:feature/riscv-jit
Mar 31, 2025
Merged

RISC-V JIT Support#932
guillep merged 10 commits intopharo-project:pharo-12from
QDucasse:feature/riscv-jit

Conversation

@QDucasse
Copy link
Contributor

@QDucasse QDucasse commented Mar 19, 2025

Hello, this PR (finally 😅) proposes the RISC-V JIT port.

Description:

The two main added files are the CogRiscV64Compiler and corresponding CogRiscVOutOfLineLiteralsCompiler, adding the support for instructions, concretizations, and rewriting necessary to the JIT compiler. Code in these two classes might be tagged with CLEANUP. If it is, it means it either was used in a previous attempt to emulate flag registers, or defines instructions that were not used in the end.

Since RISC-V, like MIPS does not provide flag registers, it uses the same tricks as the MIPS backend in the opensmalltalk-vm. To this end, every conditional branch is notified and uses its previous instruction to combine into a single compare-and-branch instruction as available on this architecture. You can see this in action in the CogRiscV64Compiler >> noteFollowingConditionalBranch: method.

Changes in existing files:

  • CogAbstractInstruction and CogObjectRepresentationFor64BitSpur: Add support for different disalignment with nops between the checkEntry and noCheckEntry.
  • Cogit: Add support for conditional branch notifications in FP jumps

Note: RISC-V does not support (yet) vector instructions and is separated from the corresponding tests.

  • VMSimpleStackBasedCogitAbstractTest: Add riscv64 as a parameter for tests, redefined another category to hold SIMD/vector operations named wordSize64SIMDParameters
  • VMJitSimdBytecode, VMJitMethodTest, VMJitVectorMethodTest: Add word64SIMDParameters to the corresponding SIMD tests, split JitMethod into vectorized and non-vectorized tests
  • Unicorn: Add support for RISC-V registers, redefine the ABI correctly on RISC-V side
  • VMTrampolineTest: A register mask was used in the tests, made up for register 1 and 2. These registers are the link register and stack pointer on RISC-V and break the tests. A solution using an offset from cResultRegister is implemented.
  • VMMachineSimulatorTest: The mapping IR/machine code is not 1-to-1 on RISC-V and breaks the Unicorn count testing. A simple instruction count is added using the size of the generated machine code.

Where we are:

All tests passing from a fresh Pharo12 image:
Screenshot 2025-03-19 at 14 53 21

The code has been fully generated without errors using:

PharoVMMaker generate: CoInterpreter name 
    outputDirectory: '...'.

Next steps:

I am currently trying the to build directly (to avoid cross-compilation for now) on the RISC-V Beagle-V Ahead board and will provide a different pull request adding build instructions and support in the C code for the RISC-V backend.

@QDucasse QDucasse force-pushed the feature/riscv-jit branch from 91a98f1 to 3a0d9a6 Compare March 20, 2025 12:52
@QDucasse
Copy link
Contributor Author

Update:
Last three commits add C utilities and missing methods that would fail compilation. The CI seems to work but breaks on JUnit archives!

@QDucasse QDucasse changed the base branch from pharo-10 to pharo-12 March 24, 2025 09:02
Copy link
Contributor Author

@QDucasse QDucasse left a comment

Choose a reason for hiding this comment

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

Fix merge conflicts

@QDucasse QDucasse force-pushed the feature/riscv-jit branch from 3a0d9a6 to 40d9835 Compare March 24, 2025 12:18
@iglosiggio
Copy link
Collaborator

I think the alignment requirements for {check,noCheck}Entry are not needed anymore. If I recall correctly these were used as a way to know if a given monomorphically linked call was a regular message send of a super one. We eventually changed it so now they are distinguished by different annotations.

This also means we can probably remove those pesky nops from the other backends too 😅

@guillep
Copy link
Member

guillep commented Mar 25, 2025

I think the alignment requirements for {check,noCheck}Entry are not needed anymore. If I recall correctly these were used as a way to know if a given monomorphically linked call was a regular message send of a super one. We eventually changed it so now they are distinguished by different annotations.

This also means we can probably remove those pesky nops from the other backends too 😅

Isn't that in your branch that is not integrated yet?

@iglosiggio
Copy link
Collaborator

I think the alignment requirements for {check,noCheck}Entry are not needed anymore. If I recall correctly these were used as a way to know if a given monomorphically linked call was a regular message send of a super one. We eventually changed it so now they are distinguished by different annotations.
This also means we can probably remove those pesky nops from the other backends too 😅

Isn't that in your branch that is not integrated yet?

Yes but my branch has a lot of other changes so maybe two wrongs made a right there. I'll do a small PoC from the pharo-12 branch now and report later :)

@iglosiggio
Copy link
Collaborator

iglosiggio commented Mar 25, 2025

Yes but my branch has a lot of other changes so maybe two wrongs made a right there. I'll do a small PoC from the pharo-12 branch now and report later :)

Okay so.... the current user of the alignment thing is Cogit>>#entryPointTagIsSelector: This is something that is not available on my branch because the cache tags work differently there >_<"

Will look around to see if there's an easy fix.

EDIT: Looks like there's one :)
EDIT2: #934

@guillep
Copy link
Member

guillep commented Mar 27, 2025

@QDucasse I just integrated this PR that produced a (single to fix?) conflict, sorry!

@QDucasse QDucasse force-pushed the feature/riscv-jit branch from 40d9835 to 0fac6dd Compare March 27, 2025 12:05
@QDucasse
Copy link
Contributor Author

I removed the conflict and disalignment generation for RISC-V, it is still missing the double dispatch for the JumpFP failing x86/64 tests, I will work on that soon!

@QDucasse QDucasse force-pushed the feature/riscv-jit branch from 0fac6dd to 859675e Compare March 27, 2025 12:14
@QDucasse
Copy link
Contributor Author

Hmmm this broke ~120 tests though...

@QDucasse QDucasse force-pushed the feature/riscv-jit branch 6 times, most recently from b7945ac to 781cd67 Compare March 31, 2025 09:25
@QDucasse
Copy link
Contributor Author

Updated to the latest pharo-12 commit, fixed the last issue with previous FP jumps, CI seems to pass!

…e no senders either because they are artifacts from the time we used diy flag registers to hangle CogIR or additional RISC-V instructions. It uses out-of-line literals, using dependent. This also adds support for rewriting literals or their references. This part is mostly based on the ARMv8 backend. A placeholder abstract compiler class is added for future expansions and to support isAbstract

Note: vector concretization and missing methods (even unused) are added to silence compilation errors of translated code.

Note 2: Add alignment nop check, needed in expectedClosedPICPrototype: as an OutOfLineLiteralsManager may add nops between the closedPICEnd and the start of the literals dump
…on flag registers (e.g. RISC-V or MIPS). see noteFollowingConditionalBranch:.
…the ABI of Smalltalk argument and result registers for the RISC-V backend
…rameter set for SIMD or vector operation. Split the VMJitMethodTest tests into the base one (staying in the class) and vectorized ones in VMJitVectorMethodTest
…rs number 1 and 2. While this corresponds to general registers in x86, x64, ARMv5, ARMv8 and MIPS, RISC-V defines register number 1 as the link register, register number 2 as the stack pointer. For a more robust encoding, the mask is built starting from the cResultRegister as defined in the backend
…expects all conditional branches to be preceeded by an instruction from which it can extracts the operand to fuse them into one compare and branch instruction, the Stop IR inclusion was preventing this mechanism. The test is slightly modified to keep the original usage.

The count number is not a 1-to-1 mapping on RISC-V and breaks the corresponding test. Using the machineCodeSize, the number of instruction is inferred and used as a count for the final test.
@QDucasse QDucasse force-pushed the feature/riscv-jit branch from 781cd67 to a6609c0 Compare March 31, 2025 12:21
@guillep guillep merged commit 63d8c3e into pharo-project:pharo-12 Mar 31, 2025
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments