Skip to content

Riscv cf

riscv_cf

RISCV_Cf = Dialect('riscv_cf', [JOp, BranchOp, BeqOp, BneOp, BltOp, BgeOp, BltuOp, BgeuOp, BnezOp]) module-attribute

ConditionalBranchOperation

Bases: RISCVInstruction, HasCanonicalizationPatternsInterface, ABC

A base class for RISC-V branch operations. Lowers to RsRsOffOperation.

Source code in xdsl/dialects/riscv_cf.py
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
class ConditionalBranchOperation(
    RISCVInstruction, HasCanonicalizationPatternsInterface, ABC
):
    """
    A base class for RISC-V branch operations. Lowers to RsRsOffOperation.
    """

    rs1 = operand_def(IntRegisterType)
    rs2 = operand_def(IntRegisterType)

    then_arguments = var_operand_def(RISCVRegisterType)
    else_arguments = var_operand_def(RISCVRegisterType)

    irdl_options = (AttrSizedOperandSegments(),)

    then_block = successor_def()
    else_block = successor_def()

    traits = traits_def(IsTerminator())

    def __init__(
        self,
        rs1: Operation | SSAValue,
        rs2: Operation | SSAValue,
        then_arguments: Sequence[SSAValue],
        else_arguments: Sequence[SSAValue],
        then_block: Successor,
        else_block: Successor,
        *,
        comment: str | StringAttr | None = None,
    ):
        if isinstance(comment, str):
            comment = StringAttr(comment)

        super().__init__(
            operands=[rs1, rs2, then_arguments, else_arguments],
            attributes={
                "comment": comment,
            },
            successors=(then_block, else_block),
        )

    def verify_(self) -> None:
        # The then block must start with a label op

        then_block_first_op = self.then_block.first_op

        if not isinstance(then_block_first_op, riscv.LabelOp):
            raise VerifyException(
                "riscv_cf branch op then block first op must be a label"
            )

        # Types of arguments must match arg types of blocks
        for op_arg, block_arg in zip(self.then_arguments, self.then_block.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        for op_arg, block_arg in zip(self.else_arguments, self.else_block.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        # The else block must be the one immediately following this one

        parent_block = self.parent
        if parent_block is None:
            return

        parent_region = parent_block.parent
        if parent_region is None:
            return

        if parent_block.next_block is not self.else_block:
            raise VerifyException(
                "riscv_cf branch op else block must be immediately after op"
            )

    def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
        then_label = self.then_block.first_op
        assert isinstance(then_label, riscv.LabelOp)
        return self.rs1, self.rs2, then_label.label

    def print(self, printer: Printer) -> None:
        printer.print_string(" ")
        _print_type_pair(printer, self.rs1)
        printer.print_string(", ")
        _print_type_pair(printer, self.rs2)
        printer.print_string(", ")
        printer.print_block_name(self.then_block)
        printer.print_string("(")
        printer.print_list(
            self.then_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string("), ")
        printer.print_block_name(self.else_block)
        printer.print_string("(")
        printer.print_list(
            self.else_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string(")")
        if self.attributes:
            printer.print_op_attributes(
                self.attributes,
                reserved_attr_names="operandSegmentSizes",
                print_keyword=True,
            )

    @classmethod
    def parse(cls, parser: Parser) -> Self:
        rs1 = _parse_type_pair(parser)
        parser.parse_punctuation(",")
        rs2 = _parse_type_pair(parser)
        parser.parse_punctuation(",")
        then_block = parser.parse_successor()
        then_args = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        parser.parse_punctuation(",")
        else_block = parser.parse_successor()
        else_args = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        attrs = parser.parse_optional_attr_dict_with_keyword()
        op = cls(rs1, rs2, then_args, else_args, then_block, else_block)
        if attrs is not None:
            op.attributes |= attrs.data
        return op

    @abstractmethod
    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        pass

    @classmethod
    def get_canonicalization_patterns(cls) -> tuple[RewritePattern, ...]:
        from xdsl.transforms.canonicalization_patterns.riscv_cf import (
            ElideConstantBranches,
        )

        return (ElideConstantBranches(),)

rs1 = operand_def(IntRegisterType) class-attribute instance-attribute

rs2 = operand_def(IntRegisterType) class-attribute instance-attribute

then_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

else_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

irdl_options = (AttrSizedOperandSegments(),) class-attribute instance-attribute

then_block = successor_def() class-attribute instance-attribute

else_block = successor_def() class-attribute instance-attribute

traits = traits_def(IsTerminator()) class-attribute instance-attribute

__init__(rs1: Operation | SSAValue, rs2: Operation | SSAValue, then_arguments: Sequence[SSAValue], else_arguments: Sequence[SSAValue], then_block: Successor, else_block: Successor, *, comment: str | StringAttr | None = None)

Source code in xdsl/dialects/riscv_cf.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def __init__(
    self,
    rs1: Operation | SSAValue,
    rs2: Operation | SSAValue,
    then_arguments: Sequence[SSAValue],
    else_arguments: Sequence[SSAValue],
    then_block: Successor,
    else_block: Successor,
    *,
    comment: str | StringAttr | None = None,
):
    if isinstance(comment, str):
        comment = StringAttr(comment)

    super().__init__(
        operands=[rs1, rs2, then_arguments, else_arguments],
        attributes={
            "comment": comment,
        },
        successors=(then_block, else_block),
    )

verify_() -> None

Source code in xdsl/dialects/riscv_cf.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def verify_(self) -> None:
    # The then block must start with a label op

    then_block_first_op = self.then_block.first_op

    if not isinstance(then_block_first_op, riscv.LabelOp):
        raise VerifyException(
            "riscv_cf branch op then block first op must be a label"
        )

    # Types of arguments must match arg types of blocks
    for op_arg, block_arg in zip(self.then_arguments, self.then_block.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    for op_arg, block_arg in zip(self.else_arguments, self.else_block.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    # The else block must be the one immediately following this one

    parent_block = self.parent
    if parent_block is None:
        return

    parent_region = parent_block.parent
    if parent_region is None:
        return

    if parent_block.next_block is not self.else_block:
        raise VerifyException(
            "riscv_cf branch op else block must be immediately after op"
        )

assembly_line_args() -> tuple[AssemblyInstructionArg, ...]

Source code in xdsl/dialects/riscv_cf.py
127
128
129
130
def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
    then_label = self.then_block.first_op
    assert isinstance(then_label, riscv.LabelOp)
    return self.rs1, self.rs2, then_label.label

print(printer: Printer) -> None

Source code in xdsl/dialects/riscv_cf.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def print(self, printer: Printer) -> None:
    printer.print_string(" ")
    _print_type_pair(printer, self.rs1)
    printer.print_string(", ")
    _print_type_pair(printer, self.rs2)
    printer.print_string(", ")
    printer.print_block_name(self.then_block)
    printer.print_string("(")
    printer.print_list(
        self.then_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string("), ")
    printer.print_block_name(self.else_block)
    printer.print_string("(")
    printer.print_list(
        self.else_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string(")")
    if self.attributes:
        printer.print_op_attributes(
            self.attributes,
            reserved_attr_names="operandSegmentSizes",
            print_keyword=True,
        )

parse(parser: Parser) -> Self classmethod

Source code in xdsl/dialects/riscv_cf.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
@classmethod
def parse(cls, parser: Parser) -> Self:
    rs1 = _parse_type_pair(parser)
    parser.parse_punctuation(",")
    rs2 = _parse_type_pair(parser)
    parser.parse_punctuation(",")
    then_block = parser.parse_successor()
    then_args = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    parser.parse_punctuation(",")
    else_block = parser.parse_successor()
    else_args = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    attrs = parser.parse_optional_attr_dict_with_keyword()
    op = cls(rs1, rs2, then_args, else_args, then_block, else_block)
    if attrs is not None:
        op.attributes |= attrs.data
    return op

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool abstractmethod

Source code in xdsl/dialects/riscv_cf.py
178
179
180
@abstractmethod
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    pass

get_canonicalization_patterns() -> tuple[RewritePattern, ...] classmethod

Source code in xdsl/dialects/riscv_cf.py
182
183
184
185
186
187
188
@classmethod
def get_canonicalization_patterns(cls) -> tuple[RewritePattern, ...]:
    from xdsl.transforms.canonicalization_patterns.riscv_cf import (
        ElideConstantBranches,
    )

    return (ElideConstantBranches(),)

BeqOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 and rs2 are equal.

if (x[rs1] == x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
@irdl_op_definition
class BeqOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 and rs2 are equal.

    if (x[rs1] == x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#beq).
    """

    name = "riscv_cf.beq"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_unsigned(rs1, bitwidth)
        rhs = to_unsigned(rs2, bitwidth)
        return lhs == rhs

name = 'riscv_cf.beq' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
203
204
205
206
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_unsigned(rs1, bitwidth)
    rhs = to_unsigned(rs2, bitwidth)
    return lhs == rhs

BneOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 and rs2 are not equal.

if (x[rs1] != x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
@irdl_op_definition
class BneOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 and rs2 are not equal.

    if (x[rs1] != x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#bne).
    """

    name = "riscv_cf.bne"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_unsigned(rs1, bitwidth)
        rhs = to_unsigned(rs2, bitwidth)
        return lhs != rhs

name = 'riscv_cf.bne' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
221
222
223
224
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_unsigned(rs1, bitwidth)
    rhs = to_unsigned(rs2, bitwidth)
    return lhs != rhs

BltOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 is less than rs2, using signed comparison.

if (x[rs1] <s x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
@irdl_op_definition
class BltOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 is less than rs2, using signed comparison.

    if (x[rs1] <s x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#blt).
    """

    name = "riscv_cf.blt"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_signed(rs1, bitwidth)
        rhs = to_signed(rs2, bitwidth)
        return lhs < rhs

name = 'riscv_cf.blt' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
239
240
241
242
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_signed(rs1, bitwidth)
    rhs = to_signed(rs2, bitwidth)
    return lhs < rhs

BgeOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 is greater than or equal to rs2, using signed comparison.

if (x[rs1] >=s x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
@irdl_op_definition
class BgeOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 is greater than or equal to rs2, using signed comparison.

    if (x[rs1] >=s x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#bge).
    """

    name = "riscv_cf.bge"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_signed(rs1, bitwidth)
        rhs = to_signed(rs2, bitwidth)
        return lhs >= rhs

name = 'riscv_cf.bge' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
257
258
259
260
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_signed(rs1, bitwidth)
    rhs = to_signed(rs2, bitwidth)
    return lhs >= rhs

BltuOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 is less than rs2, using unsigned comparison.

if (x[rs1] <u x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
@irdl_op_definition
class BltuOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 is less than rs2, using unsigned comparison.

    if (x[rs1] <u x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#bltu).
    """

    name = "riscv_cf.bltu"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_unsigned(rs1, bitwidth)
        rhs = to_unsigned(rs2, bitwidth)
        return lhs < rhs

name = 'riscv_cf.bltu' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
275
276
277
278
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_unsigned(rs1, bitwidth)
    rhs = to_unsigned(rs2, bitwidth)
    return lhs < rhs

BgeuOp dataclass

Bases: ConditionalBranchOperation

Take the branch if registers rs1 is greater than or equal to rs2, using unsigned comparison.

if (x[rs1] >=u x[rs2]) pc += sext(offset)

See external documentation.

Source code in xdsl/dialects/riscv_cf.py
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
@irdl_op_definition
class BgeuOp(ConditionalBranchOperation):
    """
    Take the branch if registers rs1 is greater than or equal to rs2, using unsigned comparison.

    if (x[rs1] >=u x[rs2]) pc += sext(offset)

    See external [documentation](https://msyksphinz-self.github.io/riscv-isadoc/html/rvi.html#bgeu).
    """

    name = "riscv_cf.bgeu"

    def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
        lhs = to_unsigned(rs1, bitwidth)
        rhs = to_unsigned(rs2, bitwidth)
        return lhs >= rhs

name = 'riscv_cf.bgeu' class-attribute instance-attribute

const_evaluate(rs1: int, rs2: int, bitwidth: int) -> bool

Source code in xdsl/dialects/riscv_cf.py
293
294
295
296
def const_evaluate(self, rs1: int, rs2: int, bitwidth: int) -> bool:
    lhs = to_unsigned(rs1, bitwidth)
    rhs = to_unsigned(rs2, bitwidth)
    return lhs >= rhs

BranchOp

Bases: RISCVAsmOperation

Branches to a different block, which must follow this operation's block in the parent region. Is not printed in assembly.

Source code in xdsl/dialects/riscv_cf.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
@irdl_op_definition
class BranchOp(riscv.RISCVAsmOperation):
    """
    Branches to a different block, which must follow this operation's block in the parent
    region. Is not printed in assembly.
    """

    name = "riscv_cf.branch"

    block_arguments = var_operand_def(RISCVRegisterType)
    successor = successor_def()
    comment = opt_attr_def(StringAttr)
    """
    An optional comment that will be printed along with the instruction.
    """

    traits = traits_def(IsTerminator())

    def __init__(
        self,
        block_arguments: Sequence[SSAValue],
        successor: Successor,
        *,
        comment: str | StringAttr | None = None,
    ):
        if isinstance(comment, str):
            comment = StringAttr(comment)

        super().__init__(
            operands=[block_arguments],
            attributes={
                "comment": comment,
            },
            successors=(successor,),
        )

    def verify_(self) -> None:
        # Types of arguments must match arg types of blocks
        for op_arg, block_arg in zip(self.block_arguments, self.successor.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        # The successor must immediately follow the parent block.
        if (parent_block := self.parent) is None or (
            parent_region := parent_block.parent
        ) is None:
            return

        parent_index = parent_region.get_block_index(parent_block)
        successor_index = parent_region.get_block_index(self.successor)

        if parent_index + 1 != successor_index:
            raise VerifyException(
                "Successor block must be immediately after parent block in the parent "
                "region."
            )

    def print(self, printer: Printer) -> None:
        printer.print_string(" ")
        printer.print_block_name(self.successor)
        printer.print_string("(")
        printer.print_list(
            self.block_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string(")")
        if self.attributes:
            printer.print_op_attributes(self.attributes, print_keyword=True)

    @classmethod
    def parse(cls, parser: Parser) -> Self:
        successor = parser.parse_successor()
        block_arguments = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        attrs = parser.parse_optional_attr_dict_with_keyword()
        op = cls(block_arguments, successor)
        if attrs is not None:
            op.attributes |= attrs.data
        return op

    def assembly_line(self) -> str | None:
        if self.comment is None:
            return None

        return f"    # {self.comment.data}"

name = 'riscv_cf.branch' class-attribute instance-attribute

block_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

successor = successor_def() class-attribute instance-attribute

comment = opt_attr_def(StringAttr) class-attribute instance-attribute

An optional comment that will be printed along with the instruction.

traits = traits_def(IsTerminator()) class-attribute instance-attribute

__init__(block_arguments: Sequence[SSAValue], successor: Successor, *, comment: str | StringAttr | None = None)

Source code in xdsl/dialects/riscv_cf.py
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
def __init__(
    self,
    block_arguments: Sequence[SSAValue],
    successor: Successor,
    *,
    comment: str | StringAttr | None = None,
):
    if isinstance(comment, str):
        comment = StringAttr(comment)

    super().__init__(
        operands=[block_arguments],
        attributes={
            "comment": comment,
        },
        successors=(successor,),
    )

verify_() -> None

Source code in xdsl/dialects/riscv_cf.py
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
def verify_(self) -> None:
    # Types of arguments must match arg types of blocks
    for op_arg, block_arg in zip(self.block_arguments, self.successor.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    # The successor must immediately follow the parent block.
    if (parent_block := self.parent) is None or (
        parent_region := parent_block.parent
    ) is None:
        return

    parent_index = parent_region.get_block_index(parent_block)
    successor_index = parent_region.get_block_index(self.successor)

    if parent_index + 1 != successor_index:
        raise VerifyException(
            "Successor block must be immediately after parent block in the parent "
            "region."
        )

print(printer: Printer) -> None

Source code in xdsl/dialects/riscv_cf.py
358
359
360
361
362
363
364
365
366
367
def print(self, printer: Printer) -> None:
    printer.print_string(" ")
    printer.print_block_name(self.successor)
    printer.print_string("(")
    printer.print_list(
        self.block_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string(")")
    if self.attributes:
        printer.print_op_attributes(self.attributes, print_keyword=True)

parse(parser: Parser) -> Self classmethod

Source code in xdsl/dialects/riscv_cf.py
369
370
371
372
373
374
375
376
377
378
379
@classmethod
def parse(cls, parser: Parser) -> Self:
    successor = parser.parse_successor()
    block_arguments = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    attrs = parser.parse_optional_attr_dict_with_keyword()
    op = cls(block_arguments, successor)
    if attrs is not None:
        op.attributes |= attrs.data
    return op

assembly_line() -> str | None

Source code in xdsl/dialects/riscv_cf.py
381
382
383
384
385
def assembly_line(self) -> str | None:
    if self.comment is None:
        return None

    return f"    # {self.comment.data}"

JOp

Bases: RISCVInstruction

A pseudo-instruction, for unconditional jumps you don't expect to return from. Is equivalent to JalOp with rd = x0. Used to be a part of the spec, removed in 2.0.

Source code in xdsl/dialects/riscv_cf.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
@irdl_op_definition
class JOp(RISCVInstruction):
    """
    A pseudo-instruction, for unconditional jumps you don't expect to return from.
    Is equivalent to JalOp with `rd` = `x0`.
    Used to be a part of the spec, removed in 2.0.
    """

    name = "riscv_cf.j"

    block_arguments = var_operand_def(RISCVRegisterType)

    successor = successor_def()

    traits = traits_def(IsTerminator())

    def __init__(
        self,
        block_arguments: Sequence[SSAValue],
        successor: Successor,
        *,
        comment: str | StringAttr | None = None,
    ):
        if isinstance(comment, str):
            comment = StringAttr(comment)

        super().__init__(
            operands=[block_arguments],
            attributes={
                "comment": comment,
            },
            successors=(successor,),
        )

    def verify_(self) -> None:
        # Types of arguments must match arg types of blocks

        for op_arg, block_arg in zip(self.block_arguments, self.successor.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        if not isinstance(self.successor.first_op, riscv.LabelOp):
            raise VerifyException(
                "riscv_cf.j operation successor must have a riscv.label operation as a "
                f"first argument, found {self.successor.first_op}"
            )

    def print(self, printer: Printer) -> None:
        printer.print_string(" ")
        printer.print_block_name(self.successor)
        printer.print_string("(")
        printer.print_list(
            self.block_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string(")")
        if self.attributes:
            printer.print_op_attributes(self.attributes, print_keyword=True)

    @classmethod
    def parse(cls, parser: Parser) -> Self:
        successor = parser.parse_successor()
        block_arguments = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        attrs = parser.parse_optional_attr_dict_with_keyword()
        op = cls(block_arguments, successor)
        if attrs is not None:
            op.attributes |= attrs.data
        return op

    def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
        dest_label = self.successor.first_op
        assert isinstance(dest_label, riscv.LabelOp)
        return (dest_label.label,)

name = 'riscv_cf.j' class-attribute instance-attribute

block_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

successor = successor_def() class-attribute instance-attribute

traits = traits_def(IsTerminator()) class-attribute instance-attribute

__init__(block_arguments: Sequence[SSAValue], successor: Successor, *, comment: str | StringAttr | None = None)

Source code in xdsl/dialects/riscv_cf.py
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
def __init__(
    self,
    block_arguments: Sequence[SSAValue],
    successor: Successor,
    *,
    comment: str | StringAttr | None = None,
):
    if isinstance(comment, str):
        comment = StringAttr(comment)

    super().__init__(
        operands=[block_arguments],
        attributes={
            "comment": comment,
        },
        successors=(successor,),
    )

verify_() -> None

Source code in xdsl/dialects/riscv_cf.py
422
423
424
425
426
427
428
429
430
431
432
433
434
435
def verify_(self) -> None:
    # Types of arguments must match arg types of blocks

    for op_arg, block_arg in zip(self.block_arguments, self.successor.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    if not isinstance(self.successor.first_op, riscv.LabelOp):
        raise VerifyException(
            "riscv_cf.j operation successor must have a riscv.label operation as a "
            f"first argument, found {self.successor.first_op}"
        )

print(printer: Printer) -> None

Source code in xdsl/dialects/riscv_cf.py
437
438
439
440
441
442
443
444
445
446
def print(self, printer: Printer) -> None:
    printer.print_string(" ")
    printer.print_block_name(self.successor)
    printer.print_string("(")
    printer.print_list(
        self.block_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string(")")
    if self.attributes:
        printer.print_op_attributes(self.attributes, print_keyword=True)

parse(parser: Parser) -> Self classmethod

Source code in xdsl/dialects/riscv_cf.py
448
449
450
451
452
453
454
455
456
457
458
@classmethod
def parse(cls, parser: Parser) -> Self:
    successor = parser.parse_successor()
    block_arguments = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    attrs = parser.parse_optional_attr_dict_with_keyword()
    op = cls(block_arguments, successor)
    if attrs is not None:
        op.attributes |= attrs.data
    return op

assembly_line_args() -> tuple[AssemblyInstructionArg, ...]

Source code in xdsl/dialects/riscv_cf.py
460
461
462
463
def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
    dest_label = self.successor.first_op
    assert isinstance(dest_label, riscv.LabelOp)
    return (dest_label.label,)

BnezOp

Bases: RISCVInstruction

A pseudo-instruction that branches if register rs is not equal to zero. Equivalent to BneOp with rs2 = x0.

if (x[rs] != 0) pc += sext(offset)

Source code in xdsl/dialects/riscv_cf.py
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
@irdl_op_definition
class BnezOp(RISCVInstruction):
    """
    A pseudo-instruction that branches if register rs is not equal to zero.
    Equivalent to BneOp with rs2 = x0.

    if (x[rs] != 0) pc += sext(offset)
    """

    name = "riscv_cf.bnez"

    rs = operand_def(IntRegisterType)

    then_arguments = var_operand_def(RISCVRegisterType)
    else_arguments = var_operand_def(RISCVRegisterType)

    irdl_options = (AttrSizedOperandSegments(),)

    then_block = successor_def()
    else_block = successor_def()

    traits = traits_def(IsTerminator())

    def __init__(
        self,
        rs: Operation | SSAValue,
        then_arguments: Sequence[SSAValue],
        else_arguments: Sequence[SSAValue],
        then_block: Successor,
        else_block: Successor,
        *,
        comment: str | StringAttr | None = None,
    ):
        if isinstance(comment, str):
            comment = StringAttr(comment)

        super().__init__(
            operands=[rs, then_arguments, else_arguments],
            attributes={
                "comment": comment,
            },
            successors=(then_block, else_block),
        )

    def verify_(self) -> None:
        if not isinstance(self.then_block.first_op, riscv.LabelOp):
            raise VerifyException(
                "riscv_cf.bnez operation then block must have a riscv.label operation as a "
                f"first argument, found {self.then_block.first_op}"
            )

        for op_arg, block_arg in zip(self.then_arguments, self.then_block.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        for op_arg, block_arg in zip(self.else_arguments, self.else_block.args):
            if op_arg.type != block_arg.type:
                raise VerifyException(
                    f"Block arg types must match {op_arg.type} {block_arg.type}"
                )

        parent_block = self.parent
        if parent_block is None:
            return

        parent_region = parent_block.parent
        if parent_region is None:
            return

        if parent_block.next_block is not self.else_block:
            raise VerifyException(
                "riscv_cf.bnez operation else block must be immediately after op"
            )

    def print(self, printer: Printer) -> None:
        printer.print_string(" ")
        _print_type_pair(printer, self.rs)
        printer.print_string(", ")
        printer.print_block_name(self.then_block)
        printer.print_string("(")
        printer.print_list(
            self.then_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string("), ")
        printer.print_block_name(self.else_block)
        printer.print_string("(")
        printer.print_list(
            self.else_arguments, lambda val: _print_type_pair(printer, val)
        )
        printer.print_string(")")
        if self.attributes:
            printer.print_op_attributes(
                self.attributes,
                reserved_attr_names="operandSegmentSizes",
                print_keyword=True,
            )

    @classmethod
    def parse(cls, parser: Parser) -> Self:
        rs = _parse_type_pair(parser)
        parser.parse_punctuation(",")
        then_block = parser.parse_successor()
        then_args = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        parser.parse_punctuation(",")
        else_block = parser.parse_successor()
        else_args = parser.parse_comma_separated_list(
            parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
        )
        attrs = parser.parse_optional_attr_dict_with_keyword()
        op = cls(rs, then_args, else_args, then_block, else_block)
        if attrs is not None:
            op.attributes |= attrs.data
        return op

    def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
        then_label = self.then_block.first_op
        assert isinstance(then_label, riscv.LabelOp)
        return (self.rs, then_label.label)

name = 'riscv_cf.bnez' class-attribute instance-attribute

rs = operand_def(IntRegisterType) class-attribute instance-attribute

then_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

else_arguments = var_operand_def(RISCVRegisterType) class-attribute instance-attribute

irdl_options = (AttrSizedOperandSegments(),) class-attribute instance-attribute

then_block = successor_def() class-attribute instance-attribute

else_block = successor_def() class-attribute instance-attribute

traits = traits_def(IsTerminator()) class-attribute instance-attribute

__init__(rs: Operation | SSAValue, then_arguments: Sequence[SSAValue], else_arguments: Sequence[SSAValue], then_block: Successor, else_block: Successor, *, comment: str | StringAttr | None = None)

Source code in xdsl/dialects/riscv_cf.py
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
def __init__(
    self,
    rs: Operation | SSAValue,
    then_arguments: Sequence[SSAValue],
    else_arguments: Sequence[SSAValue],
    then_block: Successor,
    else_block: Successor,
    *,
    comment: str | StringAttr | None = None,
):
    if isinstance(comment, str):
        comment = StringAttr(comment)

    super().__init__(
        operands=[rs, then_arguments, else_arguments],
        attributes={
            "comment": comment,
        },
        successors=(then_block, else_block),
    )

verify_() -> None

Source code in xdsl/dialects/riscv_cf.py
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
def verify_(self) -> None:
    if not isinstance(self.then_block.first_op, riscv.LabelOp):
        raise VerifyException(
            "riscv_cf.bnez operation then block must have a riscv.label operation as a "
            f"first argument, found {self.then_block.first_op}"
        )

    for op_arg, block_arg in zip(self.then_arguments, self.then_block.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    for op_arg, block_arg in zip(self.else_arguments, self.else_block.args):
        if op_arg.type != block_arg.type:
            raise VerifyException(
                f"Block arg types must match {op_arg.type} {block_arg.type}"
            )

    parent_block = self.parent
    if parent_block is None:
        return

    parent_region = parent_block.parent
    if parent_region is None:
        return

    if parent_block.next_block is not self.else_block:
        raise VerifyException(
            "riscv_cf.bnez operation else block must be immediately after op"
        )

print(printer: Printer) -> None

Source code in xdsl/dialects/riscv_cf.py
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
def print(self, printer: Printer) -> None:
    printer.print_string(" ")
    _print_type_pair(printer, self.rs)
    printer.print_string(", ")
    printer.print_block_name(self.then_block)
    printer.print_string("(")
    printer.print_list(
        self.then_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string("), ")
    printer.print_block_name(self.else_block)
    printer.print_string("(")
    printer.print_list(
        self.else_arguments, lambda val: _print_type_pair(printer, val)
    )
    printer.print_string(")")
    if self.attributes:
        printer.print_op_attributes(
            self.attributes,
            reserved_attr_names="operandSegmentSizes",
            print_keyword=True,
        )

parse(parser: Parser) -> Self classmethod

Source code in xdsl/dialects/riscv_cf.py
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
@classmethod
def parse(cls, parser: Parser) -> Self:
    rs = _parse_type_pair(parser)
    parser.parse_punctuation(",")
    then_block = parser.parse_successor()
    then_args = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    parser.parse_punctuation(",")
    else_block = parser.parse_successor()
    else_args = parser.parse_comma_separated_list(
        parser.Delimiter.PAREN, lambda: _parse_type_pair(parser)
    )
    attrs = parser.parse_optional_attr_dict_with_keyword()
    op = cls(rs, then_args, else_args, then_block, else_block)
    if attrs is not None:
        op.attributes |= attrs.data
    return op

assembly_line_args() -> tuple[AssemblyInstructionArg, ...]

Source code in xdsl/dialects/riscv_cf.py
584
585
586
587
def assembly_line_args(self) -> tuple[AssemblyInstructionArg, ...]:
    then_label = self.then_block.first_op
    assert isinstance(then_label, riscv.LabelOp)
    return (self.rs, then_label.label)