Skip to content

Stim REPEAT support #630

Open
johnzl-777 wants to merge 68 commits intomainfrom
john/repeat-support
Open

Stim REPEAT support #630
johnzl-777 wants to merge 68 commits intomainfrom
john/repeat-support

Conversation

@johnzl-777
Copy link
Contributor

@johnzl-777 johnzl-777 commented Nov 20, 2025

This PR enables scf.For statements with the proper format to be represented as a Stim REPEAT statement. There can be no dependence on the iterator variable and the number of iterations must be known at the time of the rewrite.

Per feedback I received from the team presentation and some additional help from Phillip I’ve been able to eliminate the dependency on CSE ordering. CSE can now be invoked at any time in the pass with no impact on the correctness of the resulting program.

That being said, there are definitely areas I’d like to work on to expand the the supported semantics for QEC researchers.

  1. There is a limitation on how far back you can index measurements that have occurred. This seems fine for something like a surface code memory experiment (which I have as a unit test) but becomes problematic for something like color code memory experiments where, in initialization, you have two sets of measurements that happen on the same qubits and then outside of the loop, you declare a time-based detector. That detector needs to access measurements that exceed the number of qubits being measured.
REPEAT 2 {
	MR 0 1 2
}
DETECTOR rec[-3] rec[-6] # you wouldn't be able to access this

I imagine if the number of iterations is propagated and perhaps some mechanism to accumulate measurements (say, py.binop.add with ilists) is carefully relaxed on invariance checking this could be supportable.

  1. Potentially premature optimization but it might be more space efficient to have some lattice element that represents a RANGE of record indices. GetItem naturally complicates things but it would encourage a “lazier” growth of the GlobalRecordState than the current structure.

@johnzl-777 johnzl-777 marked this pull request as ready for review January 30, 2026 14:30
@johnzl-777 johnzl-777 marked this pull request as draft January 30, 2026 20:36
@johnzl-777 johnzl-777 marked this pull request as ready for review February 5, 2026 13:46
Copy link
Member

@weinbe58 weinbe58 left a comment

Choose a reason for hiding this comment

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

I have some minor changes but overall it looks good! great job!

Note that it looks like this PR also closes #671

cc: @rafaelha

Comment on lines 31 to 45
new_block = ir.Block()
for stmt in node.body.blocks[0].stmts:
if isinstance(stmt, scf.stmts.Yield):
continue
stmt.detach()
new_block.stmts.append(stmt)

new_region = ir.Region(new_block)

# Create the REPEAT statement
repeat_stmt = cf.stmts.REPEAT(
count=const_repeat_num.result,
body=new_region,
)
node.replace_by(repeat_stmt)
Copy link
Member

Choose a reason for hiding this comment

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

you should not need to copy the statements over you can first check that all uses of the body's block arguments are the Yield statement, if not you can give up on the rewrite, otherwise you can delete the yield statement then delete the block arguments in-place safely after.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wait, I don't think this can be the case though there's definitely uses of the block args beyond just the resulting yield.

The simplest counter example I can give is the repetition code structure test in test_scf_for_to_repeat.py, your block args get touched by other statements in the body (such as measure) and THEN get yielded.

Comment on lines 47 to 48
# coordinates can be a py.Constant with an ilist or a raw ilist
if not isinstance(node.coordinates.owner, (ilist.New, py.Constant)):
Copy link
Member

Choose a reason for hiding this comment

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

This is OK for now but I think it would make sense to add more to the MeasureIDAnalysis to capture coordinates as well. That way we can just pull all this data from the analysis results instead of going through the IR and capturing the values manually from the IR which is more error prone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants