-
Notifications
You must be signed in to change notification settings - Fork 716
Jump-and-link instruction #630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
cc @vaivaswatha can you comment on the impact of this change? Ie. any concerns regarding register allocation for nested sub-routines? |
Today this is how we compile the following fn main() -> u64 {
1337
}
This is the function ASM (not super optimized to avoid inlining):
This is the ASM calling the
With this new instruction, we could call
and the
Which means we can save 3 instructions when calling We could save extra 4 instructions per function definition, by using |
There shouldn't be any problem. When we enter a function, we save all (used) registers and pop them all back at the end. So register allocation shouldn't be affected. I don't see any downsides, and the upside is as elaborated by @xunilrj . |
I'm not sure how that would work? The immediate part here is at most 12 bits long, and the VM has 48 user-writable registers. Unless we special-case some of these registers, of course, but that seems unwise. I'm noticing that the function calls could be optimized a lot further with smarter register allocation. For instance...
|
I was imagining one bit per push/pop. So from the 12bits not being used, 4 would allow jump and push, or jump and pop all registers. |
I don't think push/pop all registers are sensible operations. At least you'd like to keep the return value and address as-is. |
Some benchmarks with a sway compiler modified to use this instruction: build command
|
Closes #627. VM issue: FuelLabs/fuel-vm#857. VM PR: FuelLabs/fuel-vm#925.
The design is quite similar of the RISC-V of the same name.
JAL $ra $rb imm
stores the address of the next instruction to$ra
, so that register can be used as a return address from the subroutine. Ifra
is$zero
, the value is discarded instead, so this can be used as a jump without having to trash a register. After storing the return address, it jumps to instruction at memory address$rb + imm * 4
.The main purpose of this instruction is efficient subroutine-calling and returning.
JAL $ret_addr $subroutine_addr 0
is used to perform the call, andJAL $zero $ret_addr 0
returns from it. For nexted function calls, the callee is responsible for storing the$ret_addr
.The following snippet shows a minimal program using the functionality:
Fibonacci example
To show off how compact code this makes, I wrote a small fibonacci function using it. The function here uses the following register-based ABI:
$fnarg
in0x10
$return_addr
in0x11
Also the code uses the following locals:
$local1: 0x12, $local2: 0x13, $local3: 0x14
(named forpshl/popl
)Before requesting review