qat.experimental.dialect.q1_scf.transforms.lower_scf module
Lower the builtin scf dialect into q1_scf.
This pass converts standard MLIR structured control flow (xdsl.dialects.scf)
into the Q1-sequencer-specific structured control flow dialect q1_scf.
Motivation
The frontend importer produces scf.for loops to represent shot iteration and
similar counted patterns. Before the q1_scf pipeline can lower those loops to
hardware, the generic scf containers must first be mapped onto their Q1
counterparts.
For loops
scf.for %i = %lb to %ub step %step iter_args(%a, ...) { ... scf.yield ... }
maps onto q1_scf.for %n : q1.reg iter_args(%a, ...) { ... q1_scf.yield ... }
where %n is loaded with the iteration count ceil((ub - lb) / step) by a
q1.ir.move instruction inserted immediately before the loop.
The scf induction variable counts up from lb toward ub; the q1_scf
induction counter counts down from n toward zero. When the loop body uses the
induction variable, arithmetic instructions are inserted at the top of the body to
reconstruct the ascending value lb + (count - counter) * step.
Bounds that are not arith.constant integer literals, non-positive step values,
zero-trip counts, and loop-carried values whose type is not q1.reg are also
rejected.
Stubs
scf.if and scf.while are not yet supported. The corresponding rewrite
patterns raise PassFailedException immediately.
Reference: https://docs.qblox.com/en/main/products/qblox_instruments/q1/index.html
- class ForLowering
Bases:
RewritePatternLower
scf.fortoq1_scf.for. The iteration countceil((ub - lb) / step)is materialised as aq1.ir.moveinserted immediately before the loop. The body induction argument is retyped fromindexto!q1.reg, andscf.yieldis replaced byq1_scf.yield. When the body uses the induction variable, arithmetic is inserted at the top of the body block to reconstruct the ascending index from the countdown counter.Example (
lb=0,ub=10,step=2,count=5; body uses%i):// before %lb = arith.constant 0 : index %ub = arith.constant 10 : index %step = arith.constant 2 : index scf.for %i = %lb to %ub step %step { ... uses of %i ... scf.yield } // after %lb = arith.constant 0 : index %ub = arith.constant 10 : index %step = arith.constant 2 : index %n = q1.ir.move () <{imm = #q1.su32_imm<5>}> : () -> !q1.reg q1_scf.for %n : !q1.reg { ^bb0(%counter: !q1.reg): %not_c = q1.rr.not (%counter) : (!q1.reg) -> !q1.reg %diff = q1.rir.add (%not_c) <{imm = #q1.su32_imm<6>}> : (!q1.reg) -> !q1.reg %i = q1.rir.muls16 (%diff) <{imm = #q1.si16_imm<2>}> : (!q1.reg) -> !q1.reg ... uses of %i (now !q1.reg, ascending 0, 2, 4, 6, 8) ... q1_scf.yield }- 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:
RewritePatternStub for
scf.if→q1_scf.iflowering.Not yet implemented.
- match_and_rewrite(op: Operation, rewriter: PatternRewriter) None
Match an operation, and optionally perform a rewrite using the rewriter.
- Return type:
None
- class LowerScfToQ1ScfPass
Bases:
OrderedPass,ModulePassLower every
scfoperation in the module to itsq1_scfequivalent.Currently only
scf.foris fully implemented.scf.ifandscf.whileraisePassFailedExceptionif encountered.- apply(ctx, op)
- Return type:
None
- name: ClassVar[str] = 'lower-scf-to-q1-scf'