Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion quil-rs/benches/get_frames_for_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod corpus;
use std::str::FromStr;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use quil_rs::instruction::{DefaultHandler, InstructionHandler as _};

fn benchmark_quil_corpus(c: &mut Criterion) {
corpus::from_corpus().iter().for_each(|cfg| {
Expand All @@ -15,7 +16,7 @@ fn benchmark_quil_corpus(c: &mut Criterion) {
|prog| {
for instruction in prog.body_instructions() {
for _ in 0..50 {
let frames = prog.get_frames_for_instruction(instruction);
let frames = DefaultHandler.matching_frames(&prog, instruction);
black_box(frames);
}
}
Expand Down
14 changes: 4 additions & 10 deletions quil-rs/benches/scheduled_program_from_program.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use quil_rs::{instruction::InstructionHandler, program::scheduling::ScheduledProgram};
use quil_rs::{instruction::DefaultHandler, program::scheduling::ScheduledProgram};
use std::str::FromStr;

mod corpus;
Expand All @@ -12,22 +12,16 @@ fn benchmark_quil_corpus(c: &mut Criterion) {
// Ignore any programs that would fail to schedule
match quil_rs::Program::from_str(&cfg.program) {
Err(_) => false,
Ok(program) => {
ScheduledProgram::from_program(&program, &mut InstructionHandler::default())
.is_ok()
}
Ok(program) => ScheduledProgram::from_program(&program, &DefaultHandler).is_ok(),
}
})
.for_each(|cfg| {
group.bench_function(&cfg.name, |b| {
b.iter_batched(
|| quil_rs::Program::from_str(&cfg.program).unwrap(),
|program| {
let prog = ScheduledProgram::from_program(
&program,
&mut InstructionHandler::default(),
)
.expect("scheduling should not fail");
let prog = ScheduledProgram::from_program(&program, &DefaultHandler)
.expect("scheduling should not fail");
black_box(prog);
},
BatchSize::SmallInput,
Expand Down
22 changes: 22 additions & 0 deletions quil-rs/src/instruction/classical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,28 @@ impl std::hash::Hash for ComparisonOperand {
}
}

pub trait ClassicalOperand: Clone + std::fmt::Debug {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why explicitly have these bounds on the trait?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think because they were in practice true and functionally this is a sealed trait. Plus having a Debug supertrait is always useful for debugging.

fn memory_reference(&self) -> Option<&MemoryReference>;
}

macro_rules! classical_operands {
($($operand:ident),* $(,)?) => {
$(
impl ClassicalOperand for $operand {
fn memory_reference(&self) -> Option<&MemoryReference> {
if let Self::MemoryReference(memory_reference) = self {
Some(memory_reference)
} else {
None
}
}
}
)*
}
}

classical_operands! { ArithmeticOperand, BinaryOperand, ComparisonOperand }

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
#[cfg_attr(
Expand Down
12 changes: 8 additions & 4 deletions quil-rs/src/instruction/extern_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,8 +967,10 @@ impl Call {
}

/// Return the [`MemoryAccesses`] for the [`Call`] instruction given the [`ExternSignatureMap`].
/// This assumes ALL parameters are read, including mutable parameters.
pub(crate) fn get_memory_accesses(
/// If the type of the `EXTERN` has a return type, then the first argument is assumed to be
/// written to and not read from; all other parameters are assumed to be read from, and all
/// other mutable parameters are assumped to be written to as well.
pub(crate) fn default_memory_accesses(
&self,
extern_signatures: &ExternSignatureMap,
) -> Result<MemoryAccesses, CallResolutionError> {
Expand All @@ -979,10 +981,11 @@ impl Call {

let mut reads = HashSet::new();
let mut writes = HashSet::new();

let mut arguments = self.arguments.iter();

if extern_signature.return_type.is_some() {
if let Some(argument) = self.arguments.first() {
arguments.next();
if let Some(argument) = arguments.next() {
match argument {
UnresolvedCallArgument::MemoryReference(memory_reference) => {
reads.insert(memory_reference.name.clone());
Expand All @@ -996,6 +999,7 @@ impl Call {
}
}
}

for (argument, parameter) in std::iter::zip(arguments, extern_signature.parameters.iter()) {
match argument {
UnresolvedCallArgument::MemoryReference(memory_reference) => {
Expand Down
Loading