qat.experimental.dialect.q1_scf.transforms.lower_to_cf module

Lower structured q1_scf regions to a q1_cf block CFG.

q1_scf expresses control flow with structured containers: an if conditional and while/for loops whose bodies are regions terminated by condition and yield. q1_cf is the layer below, an unstructured CFG of basic blocks wired by branch terminators. This pass expands each container into blocks and selects the matching q1_cf terminator, carrying the source predicate across unchanged.

Each construct is lowered by splitting its parent block into the ops preceding it and a continuation holding the ops that follow. The container regions inline between the two, and the branch terminators thread live values as successor block arguments:

  1. q1_scf.if becomes a conditional branch into then/else blocks, both rejoining the continuation. Region yield operands become the continuation’s block arguments, which stand in for the conditional’s results.

  2. q1_scf.while becomes a header block that tests the condition and branches to the body or the exit, with the body’s yield forming the back-edge to the header.

  3. q1_scf.for becomes a self-looping body whose terminator is q1_cf.loop_branch, the native decrement-and-branch. The induction counter, its back-edge argument, and the loop-branch counter operand are one value, decremented in place each iteration.

The lowering is register-neutral. It introduces no new register values: every value a branch forwards already exists as an SSA value at the q1_scf level. Conditions carry a predicate over q1.reg operands rather than a boolean, so predicate selection is a direct match with no value to materialise. Whether a pre-allocation body still needs relocation is left to register allocation.

A q1_cf conditional branch falls through to its else successor, which its verifier requires to be the branch block’s layout neighbour. The lowering honours this by placing the else block, or a forwarding stub for edges that leave through the continuation, immediately after the branch.

Reference: https://docs.qblox.com/en/main/products/qblox_instruments/q1/index.html

class ForLowering

Bases: RewritePattern

Lower q1_scf.for to a self-looping body terminated by loop_branch.

The counted loop maps onto the native decrement-and-branch. The body runs at least once, so a well-formed q1_scf.for has a positive iteration count; a zero-trip loop is not expressible on the hardware and is expected to be removed upstream.

match_and_rewrite(op: Operation, rewriter: PatternRewriter) None

Match an operation, and optionally perform a rewrite using the rewriter.

Return type:

None

class IfLowering

Bases: RewritePattern

Lower q1_scf.if to a conditional branch over then/else blocks.

match_and_rewrite(op: Operation, rewriter: PatternRewriter) None

Match an operation, and optionally perform a rewrite using the rewriter.

Return type:

None

class LowerQ1ScfToQ1CfPass

Bases: ModulePass

Lower every q1_scf container in the module to a q1_cf block CFG.

apply(ctx, op)

Run lowering in a fixed inside-out order across structured forms.

Rewrites run as if -> while -> for in one greedy walk so nested containers dissolve from the smallest structured region toward enclosing loop forms.

Return type:

None

name: ClassVar[str] = 'lower-q1-scf-to-q1-cf'
class WhileLowering

Bases: RewritePattern

Lower q1_scf.while to a header, body, and exit CFG with the back-edge.

match_and_rewrite(op: Operation, rewriter: PatternRewriter) None

Match an operation, and optionally perform a rewrite using the rewriter.

Return type:

None