Skip to content

Commit

Permalink
feat: executor optimizations (#1692)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctian1 authored Oct 29, 2024
2 parents a2dfd90 + 2af8d07 commit 209d2e2
Show file tree
Hide file tree
Showing 40 changed files with 923 additions and 935 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,10 @@ debug-assertions = true
[workspace.dependencies]
# sp1
sp1-build = { path = "crates/build", version = "3.0.0" }
sp1-cli = { path = "crates/cli", version = "3.0.0", default-features = false }
sp1-core-machine = { path = "crates/core/machine", version = "3.0.0" }
sp1-core-executor = { path = "crates/core/executor", version = "3.0.0" }
sp1-curves = { path = "crates/curves", version = "3.0.0" }
sp1-derive = { path = "crates/derive", version = "3.0.0" }
sp1-eval = { path = "crates/eval", version = "3.0.0" }
sp1-helper = { path = "crates/helper", version = "3.0.0", default-features = false }
sp1-primitives = { path = "crates/primitives", version = "3.0.0" }
sp1-prover = { path = "crates/prover", version = "3.0.0" }
sp1-recursion-compiler = { path = "crates/recursion/compiler", version = "3.0.0" }
Expand All @@ -80,11 +77,8 @@ p3-util = "0.1.4-succinct"
p3-challenger = "0.1.4-succinct"
p3-dft = "0.1.4-succinct"
p3-fri = "0.1.4-succinct"
p3-goldilocks = "0.1.4-succinct"
p3-keccak = "0.1.4-succinct"
p3-keccak-air = "0.1.4-succinct"
p3-blake3 = "0.1.4-succinct"
p3-mds = "0.1.4-succinct"
p3-merkle-tree = "0.1.4-succinct"
p3-poseidon2 = "0.1.4-succinct"
p3-symmetric = "0.1.4-succinct"
Expand Down
119 changes: 62 additions & 57 deletions crates/core/executor/src/dependencies.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::{
events::{create_alu_lookups, AluEvent, CpuEvent},
events::AluEvent,
utils::{get_msb, get_quotient_and_remainder, is_signed_operation},
Executor, Opcode,
};

/// Emits the dependencies for division and remainder operations.
#[allow(clippy::too_many_lines)]
pub fn emit_divrem_dependencies(executor: &mut Executor, event: AluEvent) {
let shard = executor.shard();
let (quotient, remainder) = get_quotient_and_remainder(event.b, event.c, event.opcode);
let c_msb = get_msb(event.c);
let rem_msb = get_msb(remainder);
Expand All @@ -19,27 +20,29 @@ pub fn emit_divrem_dependencies(executor: &mut Executor, event: AluEvent) {
}

if c_neg == 1 {
let ids = executor.record.create_lookup_ids();
executor.record.add_events.push(AluEvent {
lookup_id: event.sub_lookups[4],
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: 0,
b: event.c,
c: (event.c as i32).unsigned_abs(),
sub_lookups: create_alu_lookups(),
sub_lookups: ids,
});
}
if rem_neg == 1 {
let ids = executor.record.create_lookup_ids();
executor.record.add_events.push(AluEvent {
lookup_id: event.sub_lookups[5],
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: 0,
b: remainder,
c: (remainder as i32).unsigned_abs(),
sub_lookups: create_alu_lookups(),
sub_lookups: ids,
});
}

Expand All @@ -55,19 +58,19 @@ pub fn emit_divrem_dependencies(executor: &mut Executor, event: AluEvent) {

let lower_multiplication = AluEvent {
lookup_id: event.sub_lookups[0],
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::MUL,
a: lower_word,
c: event.c,
b: quotient,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.mul_events.push(lower_multiplication);

let upper_multiplication = AluEvent {
lookup_id: event.sub_lookups[1],
shard: event.shard,
shard,
clk: event.clk,
opcode: {
if is_signed_operation {
Expand All @@ -79,31 +82,31 @@ pub fn emit_divrem_dependencies(executor: &mut Executor, event: AluEvent) {
a: upper_word,
c: event.c,
b: quotient,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.mul_events.push(upper_multiplication);

let lt_event = if is_signed_operation {
AluEvent {
lookup_id: event.sub_lookups[2],
shard: event.shard,
shard,
opcode: Opcode::SLTU,
a: 1,
b: (remainder as i32).unsigned_abs(),
c: u32::max(1, (event.c as i32).unsigned_abs()),
clk: event.clk,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
}
} else {
AluEvent {
lookup_id: event.sub_lookups[3],
shard: event.shard,
shard,
opcode: Opcode::SLTU,
a: 1,
b: remainder,
c: u32::max(1, event.c),
clk: event.clk,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
}
};

Expand All @@ -114,9 +117,12 @@ pub fn emit_divrem_dependencies(executor: &mut Executor, event: AluEvent) {

/// Emit the dependencies for CPU events.
#[allow(clippy::too_many_lines)]
pub fn emit_cpu_dependencies(executor: &mut Executor, event: &CpuEvent) {
pub fn emit_cpu_dependencies(executor: &mut Executor, index: usize) {
let event = executor.record.cpu_events[index];
let shard = executor.shard();
let instruction = &executor.program.fetch(event.pc);
if matches!(
event.instruction.opcode,
instruction.opcode,
Opcode::LB
| Opcode::LH
| Opcode::LW
Expand All @@ -130,58 +136,57 @@ pub fn emit_cpu_dependencies(executor: &mut Executor, event: &CpuEvent) {
// Add event to ALU check to check that addr == b + c
let add_event = AluEvent {
lookup_id: event.memory_add_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: memory_addr,
b: event.b,
c: event.c,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(add_event);
let addr_offset = (memory_addr % 4_u32) as u8;
let mem_value = event.memory_record.unwrap().value();

if matches!(event.instruction.opcode, Opcode::LB | Opcode::LH) {
let (unsigned_mem_val, most_sig_mem_value_byte, sign_value) =
match event.instruction.opcode {
Opcode::LB => {
let most_sig_mem_value_byte = mem_value.to_le_bytes()[addr_offset as usize];
let sign_value = 256;
(most_sig_mem_value_byte as u32, most_sig_mem_value_byte, sign_value)
}
Opcode::LH => {
let sign_value = 65536;
let unsigned_mem_val = match (addr_offset >> 1) % 2 {
0 => mem_value & 0x0000FFFF,
1 => (mem_value & 0xFFFF0000) >> 16,
_ => unreachable!(),
};
let most_sig_mem_value_byte = unsigned_mem_val.to_le_bytes()[1];
(unsigned_mem_val, most_sig_mem_value_byte, sign_value)
}
_ => unreachable!(),
};
if matches!(instruction.opcode, Opcode::LB | Opcode::LH) {
let (unsigned_mem_val, most_sig_mem_value_byte, sign_value) = match instruction.opcode {
Opcode::LB => {
let most_sig_mem_value_byte = mem_value.to_le_bytes()[addr_offset as usize];
let sign_value = 256;
(most_sig_mem_value_byte as u32, most_sig_mem_value_byte, sign_value)
}
Opcode::LH => {
let sign_value = 65536;
let unsigned_mem_val = match (addr_offset >> 1) % 2 {
0 => mem_value & 0x0000FFFF,
1 => (mem_value & 0xFFFF0000) >> 16,
_ => unreachable!(),
};
let most_sig_mem_value_byte = unsigned_mem_val.to_le_bytes()[1];
(unsigned_mem_val, most_sig_mem_value_byte, sign_value)
}
_ => unreachable!(),
};

if most_sig_mem_value_byte >> 7 & 0x01 == 1 {
let sub_event = AluEvent {
lookup_id: event.memory_sub_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::SUB,
a: event.a,
b: unsigned_mem_val,
c: sign_value,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(sub_event);
}
}
}

if event.instruction.is_branch_instruction() {
if instruction.is_branch_instruction() {
let a_eq_b = event.a == event.b;
let use_signed_comparison = matches!(event.instruction.opcode, Opcode::BLT | Opcode::BGE);
let use_signed_comparison = matches!(instruction.opcode, Opcode::BLT | Opcode::BGE);
let a_lt_b = if use_signed_comparison {
(event.a as i32) < (event.b as i32)
} else {
Expand All @@ -197,27 +202,27 @@ pub fn emit_cpu_dependencies(executor: &mut Executor, event: &CpuEvent) {
// Add the ALU events for the comparisons
let lt_comp_event = AluEvent {
lookup_id: event.branch_lt_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: alu_op_code,
a: a_lt_b as u32,
b: event.a,
c: event.b,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
let gt_comp_event = AluEvent {
lookup_id: event.branch_gt_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: alu_op_code,
a: a_gt_b as u32,
b: event.b,
c: event.a,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.lt_events.push(lt_comp_event);
executor.record.lt_events.push(gt_comp_event);
let branching = match event.instruction.opcode {
let branching = match instruction.opcode {
Opcode::BEQ => a_eq_b,
Opcode::BNE => !a_eq_b,
Opcode::BLT | Opcode::BLTU => a_lt_b,
Expand All @@ -228,62 +233,62 @@ pub fn emit_cpu_dependencies(executor: &mut Executor, event: &CpuEvent) {
let next_pc = event.pc.wrapping_add(event.c);
let add_event = AluEvent {
lookup_id: event.branch_add_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: next_pc,
b: event.pc,
c: event.c,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(add_event);
}
}

if event.instruction.is_jump_instruction() {
match event.instruction.opcode {
if instruction.is_jump_instruction() {
match instruction.opcode {
Opcode::JAL => {
let next_pc = event.pc.wrapping_add(event.b);
let add_event = AluEvent {
lookup_id: event.jump_jal_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: next_pc,
b: event.pc,
c: event.b,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(add_event);
}
Opcode::JALR => {
let next_pc = event.b.wrapping_add(event.c);
let add_event = AluEvent {
lookup_id: event.jump_jalr_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: next_pc,
b: event.b,
c: event.c,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(add_event);
}
_ => unreachable!(),
}
}

if matches!(event.instruction.opcode, Opcode::AUIPC) {
if matches!(instruction.opcode, Opcode::AUIPC) {
let add_event = AluEvent {
lookup_id: event.auipc_lookup_id,
shard: event.shard,
shard,
clk: event.clk,
opcode: Opcode::ADD,
a: event.a,
b: event.pc,
c: event.b,
sub_lookups: create_alu_lookups(),
sub_lookups: executor.record.create_lookup_ids(),
};
executor.record.add_events.push(add_event);
}
Expand Down
Loading

0 comments on commit 209d2e2

Please sign in to comment.