Skip to content

Conversation

@georgwiese
Copy link
Collaborator

@georgwiese georgwiese commented Oct 2, 2025

Following an idea from this doc, checks whether registers (1) written to before being read in a basic block and (2) also written to before read in all possible future basic blocks. If this is the case, the autoprecompile can skip changing their value.

cargo test -r guest_prove_simple -- --nocapture

let opcode = instruction.opcode.as_usize();

if opcode == OPCODE_JALR {
// For JALR, we don't know the target statically.
Copy link
Member

Choose a reason for hiding this comment

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

You can if the previous instruction was AUIPC: https://github.com/powdr-labs/powdr/blob/main/riscv-elf/src/rv64.rs#L211

}

if BRANCH_OPCODES_BIGINT.contains(&opcode) || BRANCH_OPCODES.contains(&opcode) {
// All other branch instructions conditionally add `c` to the current PC,
Copy link
Member

Choose a reason for hiding this comment

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

Other as opposed to JALR?

0 => (vec![], vec![]),
// PHANTOM
1 => {
// TODO: Not sure what should happen here.
Copy link
Member

Choose a reason for hiding this comment

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

https://github.com/powdr-labs/openvm/blob/main/crates/vm/src/arch/segment.rs#L272

Here it doesn't seem to read/write registers. Would need to check other occurrences

.map(|block| (block.start_pc, register_access_types(block)))
.collect::<BTreeMap<_, _>>();
let block_ids = register_access_types.keys().copied().collect::<Vec<_>>();
for i in 0.. {
Copy link
Member

Choose a reason for hiding this comment

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

Intuitively it feels like there's a cubic way of doing the entire search, similar to Floyd-Warshall, but I haven't actually tried to prove that

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Don't remember Floyd-Warshall rn, but noting that this runs 13 times in practice on the simple "guest" example. Worst case, this runs as many times as there are basic blocks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

28 now after 20ee691

for (r, succ) in successor_access_types.iter().enumerate() {
let current = register_access_types.get(block_id).unwrap()[r];
if current == RegisterAccessType::Unused && *succ != RegisterAccessType::Unused {
// Unused becomes whatever the successor is.
Copy link
Member

Choose a reason for hiding this comment

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

Is this true?:
For reg r, if in the current block its state is Write, and in the successor it's Read, we shouldn't change it because we can still use that information to potentially prune searches starting at the predecessors of the current block.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree, but that's what the code does, no? It only updates the current block if the state is Unused.

Copy link
Collaborator Author

@georgwiese georgwiese Oct 3, 2025

Choose a reason for hiding this comment

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

What we want is:

  • Among the successors, read > write > unused
  • The current block is only updated with the succor state if the current state is unused

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Although, actually no! I think this is a bug. we should not set the current block to write if any successor is still unknown!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Haha my first comment "is this true?" was referring to whether my understanding was correcf

Copy link
Member

Choose a reason for hiding this comment

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

Although, actually no! I think this is a bug. we should not set the current block to write if any successor is still unknown!

Yea agree with this, that's what I was trying to figure out

@georgwiese georgwiese force-pushed the tmp-register-analysis branch from 31343bb to 19df4cc Compare October 6, 2025 18:17
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