Skip to content

Commit 45eb86a

Browse files
authored
Simplify ovm compilation (#3435)
Including `ElfProgram` in the `OriginalProgram` reduces number and complexity of the functions. Do not merge before powdr-labs/openvm-reth-benchmark#44 is merged and this is updated
1 parent 0491465 commit 45eb86a

File tree

3 files changed

+23
-51
lines changed

3 files changed

+23
-51
lines changed

.github/actions/patch-openvm-reth-benchmark/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ runs:
99
with:
1010
repository: powdr-labs/openvm-reth-benchmark
1111
# Set once here — no inputs required elsewhere
12-
ref: openvm-reth-powdr-2025-11-03
12+
ref: 64cdc9640a563517848814489ea6c63f134e1e85
1313
path: openvm-reth-benchmark
1414

1515
- name: Patch openvm-reth-benchmark to use local powdr

openvm/src/customize_exe.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ use powdr_autoprecompiles::SymbolicBusInteraction;
3535
use powdr_autoprecompiles::VmConfig;
3636
use powdr_autoprecompiles::{Apc, PowdrConfig};
3737
use powdr_number::{BabyBearField, FieldElement, LargeInt};
38-
use powdr_riscv_elf::debug_info::DebugInfo;
3938
use serde::{Deserialize, Serialize};
4039

4140
use crate::bus_interaction_handler::OpenVmBusInteractionHandler;
@@ -141,12 +140,16 @@ impl<'a, F: PrimeField32> Program<Instr<F>> for Prog<'a, F> {
141140
}
142141

143142
pub fn customize<'a, P: PgoAdapter<Adapter = BabyBearOpenVmApcAdapter<'a>>>(
144-
OriginalCompiledProgram { exe, vm_config }: OriginalCompiledProgram,
145-
labels: &BTreeSet<u32>,
146-
debug_info: &DebugInfo,
143+
OriginalCompiledProgram {
144+
exe,
145+
vm_config,
146+
elf,
147+
}: OriginalCompiledProgram,
147148
config: PowdrConfig,
148149
pgo: P,
149150
) -> CompiledProgram {
151+
let labels = elf.text_labels();
152+
let debug_info = elf.debug_info();
150153
let original_config = OriginalVmConfig::new(vm_config.clone());
151154
let airs = original_config.airs(config.degree_bound.identities).expect("Failed to convert the AIR of an OpenVM instruction, even after filtering by the blacklist!");
152155
let bus_map = original_config.bus_map();

openvm/src/lib.rs

Lines changed: 15 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use powdr_autoprecompiles::{execution_profile::execution_profile, PowdrConfig};
4747
use powdr_extension::PowdrExtension;
4848
use powdr_openvm_hints_circuit::{HintsExtension, HintsExtensionExecutor, HintsProverExt};
4949
use powdr_openvm_hints_transpiler::HintsTranspilerExtension;
50+
use powdr_riscv_elf::ElfProgram;
5051
use serde::{Deserialize, Serialize};
5152
use std::cmp::Reverse;
5253
use std::fs::File;
@@ -502,7 +503,7 @@ pub fn compile_openvm(
502503
);
503504

504505
let elf = sdk.build(
505-
guest_opts,
506+
guest_opts.clone(),
506507
target_path,
507508
&Default::default(),
508509
Default::default(),
@@ -511,12 +512,19 @@ pub fn compile_openvm(
511512
// Transpile the ELF into a VmExe.
512513
let exe = sdk.convert_to_exe(elf)?;
513514

515+
let elf_binary_path = build_elf_path(guest_opts.clone(), target_path, &Default::default())?;
516+
let elf = powdr_riscv_elf::load_elf(&elf_binary_path);
517+
514518
let vm_config = ExtendedVmConfig {
515519
sdk: sdk.app_config().app_vm_config.clone(),
516520
hints: HintsExtension,
517521
};
518522

519-
Ok(OriginalCompiledProgram { exe, vm_config })
523+
Ok(OriginalCompiledProgram {
524+
exe,
525+
vm_config,
526+
elf,
527+
})
520528
}
521529

522530
pub fn compile_guest(
@@ -532,7 +540,7 @@ pub fn compile_guest(
532540
tally_opcode_frequency(&pgo_config, &original_program.exe);
533541
}
534542

535-
compile_exe(guest, guest_opts, original_program, config, pgo_config)
543+
compile_exe(original_program, config, pgo_config)
536544
}
537545

538546
fn instruction_index_to_pc(program: &Program<BabyBear>, idx: usize) -> u64 {
@@ -577,39 +585,10 @@ fn tally_opcode_frequency(pgo_config: &PgoConfig, exe: &VmExe<BabyBear>) {
577585
}
578586

579587
pub fn compile_exe(
580-
guest: &str,
581-
guest_opts: GuestOptions,
582588
original_program: OriginalCompiledProgram,
583589
config: PowdrConfig,
584590
pgo_config: PgoConfig,
585591
) -> Result<CompiledProgram, Box<dyn std::error::Error>> {
586-
// Build the ELF with guest options and a target filter.
587-
// We need these extra Rust flags to get the labels.
588-
let guest_opts = guest_opts.with_rustc_flags(vec!["-C", "link-arg=--emit-relocs"]);
589-
590-
// Point to our local guest
591-
use std::path::PathBuf;
592-
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).to_path_buf();
593-
path.push(guest);
594-
let target_path = path.to_str().unwrap();
595-
596-
let elf_binary_path = build_elf_path(guest_opts.clone(), target_path, &Default::default())?;
597-
598-
compile_exe_with_elf(
599-
original_program,
600-
&std::fs::read(elf_binary_path)?,
601-
config,
602-
pgo_config,
603-
)
604-
}
605-
606-
pub fn compile_exe_with_elf(
607-
original_program: OriginalCompiledProgram,
608-
elf: &[u8],
609-
config: PowdrConfig,
610-
pgo_config: PgoConfig,
611-
) -> Result<CompiledProgram, Box<dyn std::error::Error>> {
612-
let elf = powdr_riscv_elf::load_elf_from_buffer(elf);
613592
let compiled = match pgo_config {
614593
PgoConfig::Cell(pgo_data, max_total_columns) => {
615594
let max_total_apc_columns: Option<usize> = max_total_columns.map(|max_total_columns| {
@@ -625,8 +604,6 @@ pub fn compile_exe_with_elf(
625604

626605
customize(
627606
original_program,
628-
elf.text_labels(),
629-
elf.debug_info(),
630607
config,
631608
CellPgo::<_, OpenVmApcCandidate<_, _>>::with_pgo_data_and_max_columns(
632609
pgo_data,
@@ -636,18 +613,10 @@ pub fn compile_exe_with_elf(
636613
}
637614
PgoConfig::Instruction(pgo_data) => customize(
638615
original_program,
639-
elf.text_labels(),
640-
elf.debug_info(),
641616
config,
642617
InstructionPgo::with_pgo_data(pgo_data),
643618
),
644-
PgoConfig::None => customize(
645-
original_program,
646-
elf.text_labels(),
647-
elf.debug_info(),
648-
config,
649-
NonePgo::default(),
650-
),
619+
PgoConfig::None => customize(original_program, config, NonePgo::default()),
651620
};
652621
// Export the compiled program to a PIL file for debugging purposes.
653622
export_pil(
@@ -663,11 +632,11 @@ pub struct CompiledProgram {
663632
pub vm_config: SpecializedConfig,
664633
}
665634

666-
// the original openvm program and config without powdr extension
667-
#[derive(Clone)]
635+
// the original openvm program and config without powdr extension, along with the elf
668636
pub struct OriginalCompiledProgram {
669637
pub exe: Arc<VmExe<BabyBear>>,
670638
pub vm_config: ExtendedVmConfig,
639+
pub elf: ElfProgram,
671640
}
672641

673642
use openvm_circuit_derive::VmConfig;
@@ -994,7 +963,7 @@ pub fn execution_profile_from_guest(
994963
guest_opts: GuestOptions,
995964
inputs: StdIn,
996965
) -> HashMap<u64, u32> {
997-
let OriginalCompiledProgram { exe, vm_config } = compile_openvm(guest, guest_opts).unwrap();
966+
let OriginalCompiledProgram { exe, vm_config, .. } = compile_openvm(guest, guest_opts).unwrap();
998967
let program = Prog::from(&exe.program);
999968

1000969
// Set app configuration

0 commit comments

Comments
 (0)