Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutable variables in dynamic branches prevent full constant folding in partial evaluation #2087

Open
idavis opened this issue Jan 2, 2025 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@idavis
Copy link
Collaborator

idavis commented Jan 2, 2025

Given a mutable variable used in a quantum condition block, partial eval can't track that despite value being in a dynamic condition, it is statically constant.

@EntryPoint()
operation Test() : Unit {
    mutable value = 0;
    use q = Qubit();
    let cond = MResetZ(q);
    if cond == Zero {
        value -= 1 ;
    } else {
        value += 1;
    }
}

This leads to a variable being used in the CFG for the else block, which is converted into a constant during SSA transformation. This leaves SSA instructions performing mathematical computation on constant values.

This currently causes a panic in the compiler which assumes all constant operations were resolved during partial evaluation.

Actual:

Blocks:
Block 0:Block:
    Variable(0, Integer) = Store Integer(0)
    Call id(1), args( Qubit(0), Result(0), )
    Variable(1, Boolean) = Call id(2), args( Result(0), )
    Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(false)
    Branch Variable(2, Boolean), 2, 3
Block 1:Block:
    Call id(3), args( Integer(0), Pointer, )
    Return
Block 2:Block:
    Variable(0, Integer) = Store Integer(-1)
    Jump(1)
Block 3:Block:
    Variable(3, Integer) = Add Variable(0, Integer), Integer(1)
    Variable(0, Integer) = Store Variable(3, Integer)
    Jump(1)

In SSA processing:

Variable(3, Integer) = Add Variable(0, Integer), Integer(1)
Variable(0, Integer) = Store Variable(3, Integer)

Is turned into:

Variable(0, Integer) = Add Integer(0), Integer(1)

Which causes the panic. Given that partial evaluation can't fully perform constant folding, we most likely need to implement more SSA passes for constant folding, dead code elimination, at a minimum.

Workaround:
Save off the current mut value and use it on the rhs of the expressions in the conditional blocks:

operation Workaround() : Unit {
    mutable value = 0;
    use q = Qubit();
    let cond = MResetZ(q);
    let orig = value;
    if cond == Zero {
        value = orig - 1 ;
    } else {
        value = orig + 1;
    }
}
@idavis idavis added bug Something isn't working needs triage labels Jan 2, 2025
@swernli swernli self-assigned this Jan 4, 2025
swernli added a commit that referenced this issue Jan 4, 2025
…n partial evaluation

This fixes the bug by having partial evaluation more explicitly track different variable mappings to literals across branches and recombining those mappings that match (ie: are constant) when all branches are done. This also includes partial eval and RIR SSA pass fixes to correctly support immutable and mutable copies of dynamic variables. New test cases for several combinations of constant folding at partial eval are included, as well as a new test case confirming RIR SSA fix.

Fixes #2087
swernli added a commit that referenced this issue Jan 4, 2025
…n partial evaluation

This fixes the bug by having partial evaluation more explicitly track different variable mappings to literals across branches and recombining those mappings that match (ie: are constant) when all branches are done. This also includes partial eval and RIR SSA pass fixes to correctly support immutable and mutable copies of dynamic variables. New test cases for several combinations of constant folding at partial eval are included, as well as a new test case confirming RIR SSA fix.

Fixes #2087
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants