Skip to content

Riscv scf for infer constant step

riscv_scf_for_infer_constant_step

This pass converts a statically-known step value into a constant attribute in riscv_scf loops when it fits into the bitwidth of the immediate in the addi operation. The rationale is to use one fewer register in the loop body. The lower bound and upper bound don't benefit from the same transformation, as the former is only used to initialise the induction variable, and the step is used in a comparison which always takes two registers.

InferConstantStep

Bases: RewritePattern

Source code in xdsl/transforms/riscv_scf_for_infer_constant_step.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class InferConstantStep(RewritePattern):
    @op_type_rewrite_pattern
    def match_and_rewrite(
        self, op: riscv_scf.ForOp | riscv_scf.RofOp, rewriter: PatternRewriter
    ) -> None:
        if (sv := op.step_val) is None:
            # Nothing to be done
            return

        if not isinstance(owner := sv.owner, rv32.LiOp):
            # Only support rv32.LiOp for now
            return

        if isinstance(imm := owner.immediate, riscv.LabelAttr):
            # Cannot support labels for now
            return

        try:
            step_attr = IntegerAttr(imm.value.data, si12)
        except VerifyException:
            # RV32 I-type addi immediates (12-bit signed). This is only valid until we
            # add support for rv64, revisit then.
            return

        new_op = type(op)(
            op.lb,
            op.ub,
            step_attr,
            op.iter_args,
            rewriter.move_region_contents_to_new_regions(op.body),
        )
        rewriter.replace_op(op, new_op, new_op.results)

match_and_rewrite(op: riscv_scf.ForOp | riscv_scf.RofOp, rewriter: PatternRewriter) -> None

Source code in xdsl/transforms/riscv_scf_for_infer_constant_step.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@op_type_rewrite_pattern
def match_and_rewrite(
    self, op: riscv_scf.ForOp | riscv_scf.RofOp, rewriter: PatternRewriter
) -> None:
    if (sv := op.step_val) is None:
        # Nothing to be done
        return

    if not isinstance(owner := sv.owner, rv32.LiOp):
        # Only support rv32.LiOp for now
        return

    if isinstance(imm := owner.immediate, riscv.LabelAttr):
        # Cannot support labels for now
        return

    try:
        step_attr = IntegerAttr(imm.value.data, si12)
    except VerifyException:
        # RV32 I-type addi immediates (12-bit signed). This is only valid until we
        # add support for rv64, revisit then.
        return

    new_op = type(op)(
        op.lb,
        op.ub,
        step_attr,
        op.iter_args,
        rewriter.move_region_contents_to_new_regions(op.body),
    )
    rewriter.replace_op(op, new_op, new_op.results)

RiscvScfForInferConstantStepPass dataclass

Bases: ModulePass

Source code in xdsl/transforms/riscv_scf_for_infer_constant_step.py
59
60
61
62
63
class RiscvScfForInferConstantStepPass(ModulePass):
    name = "riscv-scf-for-infer-constant-step"

    def apply(self, ctx: Context, op: builtin.ModuleOp) -> None:
        PatternRewriteWalker(InferConstantStep()).rewrite_module(op)

name = 'riscv-scf-for-infer-constant-step' class-attribute instance-attribute

apply(ctx: Context, op: builtin.ModuleOp) -> None

Source code in xdsl/transforms/riscv_scf_for_infer_constant_step.py
62
63
def apply(self, ctx: Context, op: builtin.ModuleOp) -> None:
    PatternRewriteWalker(InferConstantStep()).rewrite_module(op)