Skip to content

Commit

Permalink
Fix to partial evaluation generating branch instructions on constant …
Browse files Browse the repository at this point in the history
…conditions (#1963)

RCA can categorize an expression as dynamic even if it is in fact purely
classical. This can happen in cases where a data structure such an
array, tuple or UDT contains a mix of static and dynamic values. In such
instances, RCA identifies all the contents of the data structure as
dynamic even if some values are static. This causes partial evaluation
to generate branch instructions on constant conditions under certain
circumstances. This change fixes this issue.

---------

Co-authored-by: Stefan J. Wernli <swernli@microsoft.com>
  • Loading branch information
cesarzc and swernli authored Oct 15, 2024
1 parent 0d05c9f commit d14d6c2
Show file tree
Hide file tree
Showing 2 changed files with 773 additions and 0 deletions.
22 changes: 22 additions & 0 deletions compiler/qsc_partial_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,28 @@ impl<'a> PartialEvaluator<'a> {
panic!("expected result value from RHS expression");
};

// Even though to get to this path, an expression would have to be categorized as hybrid by RCA, it is
// possible that the expression is in fact purely classical.
// This can happen in cases where a data structure such an array, tuple or UDT contains a mix of static and
// dynamic values. In such instances, RCA identifies all the contents of the data structure as dynamic even if
// some values are static.
// Here we handle this case and if both operands are purely classical we evaluate them.
if let (val::Result::Val(lhs_result_value), val::Result::Val(rhs_result_value)) =
(lhs_result, rhs_result)
{
let bool_value = match bin_op {
BinOp::Eq => lhs_result_value == rhs_result_value,
BinOp::Neq => lhs_result_value != rhs_result_value,
_ => {
return Err(Error::Unexpected(
format!("invalid binary operator for Result operands: {bin_op:?})"),
bin_op_expr_span,
))
}
};
return Ok(EvalControlFlow::Continue(Value::Bool(bool_value)));
}

// Get the operands to use when generating the binary operation instruction.
let lhs_operand = self.eval_result_as_bool_operand(lhs_result);
let rhs_operand = self.eval_result_as_bool_operand(rhs_result);
Expand Down
Loading

0 comments on commit d14d6c2

Please sign in to comment.