Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 1 addition & 4 deletions source/compiler/qsc/src/codegen/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5779,10 +5779,7 @@ fn foreign_table_lookup_callable_generates_qir() {
use address = Qubit[1];
use output = Qubit[1];
Std.TableLookup.Select([[false], [true]], address, output);

// Adjoint of Select does not work until support for static sized, dynamic content arrays is added.
// See related issue: https://github.com/microsoft/qdk/issues/3388
// Adjoint Std.TableLookup.Select([[false], [true]], address, output);
Adjoint Std.TableLookup.Select([[false], [true]], address, output);
}
"#};
for profile in [Profile::AdaptiveRI, Profile::AdaptiveRIF, Profile::Adaptive] {
Expand Down
1 change: 1 addition & 0 deletions source/compiler/qsc_circuit/src/rir_to_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ fn process_variables(
store_expr_in_variable(&mut state.variables, *variable, expr)?;
}
instruction @ (Instruction::Store(..)
| Instruction::StoreArray(..)
| Instruction::BitwiseNot(..)
| Instruction::Alloca(..)
| Instruction::Load(..)
Expand Down
4 changes: 3 additions & 1 deletion source/compiler/qsc_codegen/src/qir/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ impl ToQir<String> for rir::Instruction {
rir::Instruction::Srem(lhs, rhs, variable) => {
binop_to_qir("srem", lhs, rhs, *variable, program)
}
rir::Instruction::Store(_, _) => unimplemented!("store should be removed by pass"),
rir::Instruction::Store(_, _) | rir::Instruction::StoreArray(_, _) => {
unimplemented!("store should be removed by pass")
}
rir::Instruction::Sub(lhs, rhs, variable) => {
binop_to_qir("sub", lhs, rhs, *variable, program)
}
Expand Down
34 changes: 34 additions & 0 deletions source/compiler/qsc_codegen/src/qir/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ impl ToQir<String> for rir::Instruction {
rir::Instruction::Store(operand, variable) => {
store_to_qir(*operand, *variable, program)
}
rir::Instruction::StoreArray(operands, variable) => {
store_array_to_qir(operands, *variable, program)
}
rir::Instruction::Sub(lhs, rhs, variable) => {
binop_to_qir("sub", lhs, rhs, *variable, program)
}
Expand Down Expand Up @@ -291,6 +294,37 @@ fn store_to_qir(operand: rir::Operand, variable: rir::Variable, program: &rir::P
)
}

fn store_array_to_qir(
operands: &[rir::Operand],
variable: rir::Variable,
program: &rir::Program,
) -> String {
// Since SSA variables cannot be used in array literals, we cannot store the whole
// array into the alloca'ed space in one instruction. Instead, iterate through the array
// and create temporary variables for each memory location via getelementptr, then store
// the corresponding value into the array.
// This expands the single `StoreArray` instruction into 2N instructions, where N is the
// number of elements in the array.
let var_ty = get_variable_ty(variable);
let mut qir = String::new();
let var_str = ToQir::<String>::to_qir(&variable.variable_id, program);
for (i, operand) in operands.iter().enumerate() {
let temp_var = format!("{var_str}_{i}");
writeln!(
qir,
" {temp_var} = getelementptr {var_ty}, ptr {var_str}, i64 0, i64 {i}"
)
.expect("writing to string should succeed");
write!(
qir,
" store {}, ptr {temp_var}",
ToQir::<String>::to_qir(operand, program)
)
.expect("writing to string should succeed");
}
qir
}

fn load_to_qir(var_from: rir::Variable, var_to: rir::Variable, program: &rir::Program) -> String {
let var_to_ty = get_variable_ty(var_to);
format!(
Expand Down
9 changes: 7 additions & 2 deletions source/compiler/qsc_partial_eval/src/evaluation_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use qsc_fir::fir::{LocalItemId, LocalVarId, PackageId};
use qsc_rca::{ComputeKind, RuntimeFeatureFlags, ValueKind};
use qsc_rir::rir::{BlockId, Literal, VariableId};
use rustc_hash::FxHashMap;
use std::collections::hash_map::Entry;
use std::{collections::hash_map::Entry, rc::Rc};

use crate::{ScopeDbgContext, is_static_value};

Expand All @@ -24,7 +24,7 @@ pub struct EvaluationContext {
impl EvaluationContext {
/// Creates a new evaluation context.
pub fn new(package_id: PackageId, initial_block: BlockId) -> Self {
let entry_callable_scope = Scope::new(package_id, None, Vec::new(), None);
let entry_callable_scope = Scope::new(package_id, None, Vec::new(), None, Vec::new());
Self {
active_blocks: vec![BlockNode {
id: initial_block,
Expand Down Expand Up @@ -118,6 +118,9 @@ pub struct Scope {
active_block_count: usize,
/// Debug context, used for generating debug metadata.
pub(crate) dbg_context: ScopeDbgContext,
/// Any locally constant arrays associated with this scope, along with the variable ID
/// they are assigned (which happens after the scope is created).
pub(crate) arrays: Vec<(Rc<Vec<Value>>, Option<VariableId>)>,
}

impl Scope {
Expand All @@ -127,6 +130,7 @@ impl Scope {
callable: Option<(LocalItemId, FunctorApp)>,
args: Vec<Arg>,
ctls_arg: Option<Arg>,
arrays: Vec<Rc<Vec<Value>>>,
) -> Self {
// Create the environment for the classical evaluator.
// A default classical evaluator environment is created with one scope. However, we need to push an additional
Expand Down Expand Up @@ -184,6 +188,7 @@ impl Scope {
hybrid_vars,
static_vars: FxHashMap::default(),
dbg_context: ScopeDbgContext::default(),
arrays: arrays.into_iter().map(|array| (array, None)).collect(),
}
}

Expand Down
Loading