Every Solana program starts by finding its own inputs. The runtime hands it a pointer to one serialized block of accounts and instruction data, and the program walks it record by record. SIMD-0683, merged on 23 October, hands over three more numbers in three spare registers so that it doesn’t have to.
The proposal and its Agave implementation landed the same morning. We built four small programs that do the same thing, read the last account and the instruction data, in four ways, and counted the instructions each executes in Solana’s VM at 1 to 254 accounts. Today’s entrypoints grow with every account. With the new registers the cost is 8 instructions whatever the count.
What a program gets at its entrypoint today
The VM sets two registers before it calls a program: r1 points to the input region and r2 to the instruction data. r3 to r5, the other argument registers, hold whatever was there. The input region starts with the number of accounts, then one record per account: flags, address, owner, lamports, data length, the data itself, 10 KiB of room to grow and padding. Duplicate accounts get an 8-byte entry instead. Then come the data length, the data and the program id.
Records vary in length with each account’s data, so to find account k, or the instruction data after the last account, a program has to step through every record before it. Entrypoint libraries do that walk for you, and it costs compute on every call.
Two proposals, one after the other
SIMD-0449, which Agave implemented in March, appends an array of pointers after the program id, aligned to 8 bytes, one per account, each to the start of that account’s record; a duplicate points to the original (serialization.rs). Its gate has been active on testnet since 28 June and on devnet since 8 July, but not on mainnet. A program still has to compute where the array starts.
SIMD-0683 removes that step. For every program on the current ABI, the deprecated loader excepted, the VM now also sets (vm.rs):
Agave sets them behind the gate pass_input_metadata_in_vm_r3_r5, and refuses to run a program if the gate is on but the pointer array is missing, since SIMD-0683 depends on SIMD-0449. In Rust the registers are simply the entrypoint’s third to fifth arguments:
#[no_mangle]
pub unsafe extern "C" fn entrypoint(
_input: *mut u8, // r1
data: *const u8, // r2
data_len: u64, // r3
accounts: *const AccountView, // r4: AccountView wraps one pointer
accounts_len: u64, // r5
) -> u64 {
let accounts = core::slice::from_raw_parts(accounts, accounts_len as usize);
let data = core::slice::from_raw_parts(data, data_len as usize);
match process(accounts, data) {
Ok(()) => SUCCESS,
Err(e) => e.into(),
}
}What finding the inputs costs, measured
Each of our four programs reads the last account’s lamports and data length and the first byte of the instruction data. We built them with Pinocchio 0.11.2 and platform-tools v1.57 and ran them in solana-sbpf 0.26.0, the VM version Agave pinned that afternoon, with the input serialized and the registers set the way Agave’s code does. Executed instructions, which equal compute units, for the whole program:
Pinocchio’s standard entrypoint parses every account into an array before the handler runs: about 7.6 instructions per account. Its lazy entrypoint reads accounts on demand, which is cheap for a program that needs only the first few, but it hands out the instruction data only after every account has been read, so a handler that needs its data pays about 19 per account. Both new paths are flat. With one account the four programs cost 19, 34, 14 and 8.
Pinocchio is the low-overhead option today; it is the library behind p-token. We did not measure entrypoints that build heavier account structures.
What the registers add on top of the pointers
Six instructions. Without r3–r5 a program loads the account count from the start of the input and the data length from the 8 bytes before the data, then computes the array’s address: past the data, past the 32-byte program id, rounded up to 8 bytes. That arithmetic is the real cost. It hard-codes the serialization layout into every program, so a program written against SIMD-0449 alone breaks if the layout ever changes. The proposal notes that a future ABI will change it, and the registers carry the same information whatever the layout. Most of the compute saving is SIMD-0449’s; the registers make it portable.
Three registers nobody was supposed to read
Until the gate is active, r3–r5 hold leftover values, and a deployed program that already reads them would see its behaviour change. The proposal scanned deployed programs and found three: one reads all three registers but always fails at its fourth instruction, so it never runs; the other two are false positives, where the analyser assumed that an indirect call used every register. Hence the compatibility note: the change is safe for programs that do not read r3–r5 at their entrypoint.
The reverse case matters to developers: a program written for the new registers and run where the gate is off reads garbage, with nothing to say so. Agave’s own test program compares r5 with the account count stored at the start of the input; a program can do the same as a cheap guard, one load and one comparison.
Where it stands
The proposal is merged with status Review, and Agave’s implementation is merged behind a new gate that no cluster has yet. On mainnet it also waits on SIMD-0449. Pinocchio 0.11.2 has no entrypoint for either; we wrote ours by hand, as Agave’s test program does.
What this does not show
We measured the program side in the VM, with our own serializer written from Agave’s code; the runtime’s own serialization, which SIMD-0449 grows by 8 bytes per account, is not included. The accounts had no data and no duplicates, and the handler was minimal, so real programs add their own work on top. Every program verified it had read the right account and data: we planted a marked account and checked that each returned the expected error for it.
Input Registers: Questions People Actually Ask
What does SIMD-0683 change in Solana programs?
At a program’s entrypoint the VM already sets r1 to the input region and r2 to the instruction data. SIMD-0683 also sets r3 to the instruction data length, r4 to the address of the array of account pointers that SIMD-0449 adds to the input, and r5 to the number of accounts, for every program on the current ABI. Programs can then reach their accounts and data without parsing the input.
How much compute does SIMD-0683 save?
In our measurement inside Solana’s VM, Pinocchio’s standard entrypoint cost 83 compute units with 8 accounts and 1,953 with 254, because it walks every account record. With r3–r5 the same work cost 8 at any account count. Using SIMD-0449’s pointer array without the registers cost 14, so most of the saving comes from SIMD-0449 and the registers remove the last 6 instructions.
What is SIMD-0449?
Direct account pointers in program input: the runtime appends an 8-byte-aligned array of pointers, one per instruction account, to the serialized program input, after the program id. Each points to the account’s record; a duplicate points to the original. Agave added it in March 2026 behind a feature gate, active on testnet since June and devnet since July 2026, and SIMD-0683 depends on it.
Is it safe to read registers r3–r5 at a Solana program entrypoint?
Not before SIMD-0683 is active on the cluster: until then r3–r5 hold uninitialized values. The proposal checked deployed programs for reads of these registers and found one, which always fails a few instructions in, plus two false positives. A program written for the new registers can compare r5 with the account count at the start of the input, as Agave’s own test program does.
Is SIMD-0683 active on mainnet?
No. Agave merged it on 23 October 2026 behind the feature gate pass_input_metadata_in_vm_r3_r5, and it cannot be useful on a cluster before SIMD-0449, whose gate was not active on mainnet either.
The one-line version
SIMD-0683 passes the data length, the account-pointer array and the account count in r3–r5, so a program finds its inputs in 8 instructions instead of walking every account: 83 compute units with Pinocchio at 8 accounts, 1,953 at 254.
Sources: SIMD-0683 at commit a084840a; Agave #16025, merged as ee30f2a1, and #10486 for SIMD-0449; Pinocchio 0.11.2; solana-sbpf 0.26.0. Programs and measurements are our own.