Skip to content

Dynamic index list

dynamic_index_list

This file contains utility functions to manipulate lists of integers and SSAValues, that are encoded as a dense list of integers attributes and a variadic operand.

For instance, the [1, 2, %3, 4, %5] list is represented as: - static_values = [1, 2, MARKER, 4, MARKER] - dynamic_values = [%3, %5] where MARKER is a special value that indicates that the value at that position is dynamic.

DynamicIndexList dataclass

Bases: CustomDirective

Custom directive for parsing dynamic index list. These contain a mix of indices and (untyped) ssa values.

Source code in xdsl/dialects/utils/dynamic_index_list.py
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
@irdl_custom_directive
class DynamicIndexList(CustomDirective):
    """
    Custom directive for parsing dynamic index list.
    These contain a mix of indices and (untyped) ssa values.
    """

    DYNAMIC_INDEX: ClassVar[int] = -9223372036854775808

    dynamic_position: VariadicOperandVariable
    static_position: AttributeVariable

    def parse(self, parser: Parser, state: ParsingState) -> bool:
        dynamic, static = parse_dynamic_index_list_without_types(
            parser, self.DYNAMIC_INDEX
        )
        self.dynamic_position.set(state, dynamic)
        self.static_position.set(state, DenseArrayBase.from_list(i64, static))
        return True

    def print(self, printer: Printer, state: PrintingState, op: IRDLOperation) -> None:
        state.print_whitespace(printer)

        dynamic = self.dynamic_position.get(op)
        static = self.static_position.get(op)
        assert isa(static, DenseArrayBase[IntegerType])

        print_dynamic_index_list(
            printer, self.DYNAMIC_INDEX, dynamic, static.get_values()
        )

    def set_empty(self, state: ParsingState):
        self.dynamic_position.set(state, [])
        self.static_position.set(state, DenseArrayBase.from_list(i64, []))

    def is_present(self, op: IRDLOperation) -> bool:
        dynamic_empty = not self.dynamic_position.get(op)

        static_vals = self.static_position.get(op)
        assert isa(static_vals, DenseArrayBase[IntegerType])
        static_empty = not static_vals.data.data

        return not (dynamic_empty and static_empty)

    def is_anchorable(self) -> bool:
        return True

DYNAMIC_INDEX: int = -9223372036854775808 class-attribute

dynamic_position: VariadicOperandVariable instance-attribute

static_position: AttributeVariable instance-attribute

parse(parser: Parser, state: ParsingState) -> bool

Source code in xdsl/dialects/utils/dynamic_index_list.py
233
234
235
236
237
238
239
def parse(self, parser: Parser, state: ParsingState) -> bool:
    dynamic, static = parse_dynamic_index_list_without_types(
        parser, self.DYNAMIC_INDEX
    )
    self.dynamic_position.set(state, dynamic)
    self.static_position.set(state, DenseArrayBase.from_list(i64, static))
    return True

print(printer: Printer, state: PrintingState, op: IRDLOperation) -> None

Source code in xdsl/dialects/utils/dynamic_index_list.py
241
242
243
244
245
246
247
248
249
250
def print(self, printer: Printer, state: PrintingState, op: IRDLOperation) -> None:
    state.print_whitespace(printer)

    dynamic = self.dynamic_position.get(op)
    static = self.static_position.get(op)
    assert isa(static, DenseArrayBase[IntegerType])

    print_dynamic_index_list(
        printer, self.DYNAMIC_INDEX, dynamic, static.get_values()
    )

set_empty(state: ParsingState)

Source code in xdsl/dialects/utils/dynamic_index_list.py
252
253
254
def set_empty(self, state: ParsingState):
    self.dynamic_position.set(state, [])
    self.static_position.set(state, DenseArrayBase.from_list(i64, []))

is_present(op: IRDLOperation) -> bool

Source code in xdsl/dialects/utils/dynamic_index_list.py
256
257
258
259
260
261
262
263
def is_present(self, op: IRDLOperation) -> bool:
    dynamic_empty = not self.dynamic_position.get(op)

    static_vals = self.static_position.get(op)
    assert isa(static_vals, DenseArrayBase[IntegerType])
    static_empty = not static_vals.data.data

    return not (dynamic_empty and static_empty)

is_anchorable() -> bool

Source code in xdsl/dialects/utils/dynamic_index_list.py
265
266
def is_anchorable(self) -> bool:
    return True

verify_dynamic_index_list(static_values: Sequence[int], dynamic_values: Sequence[SSAValue], dynamic_index: int, end_message: str = '') -> None

Verify that the static list contains only integers and that the dynamic list contains only SSAValues. The static list should be of the same length as the dynamic list, with the dynamic values replaced by dynamic_index.

Source code in xdsl/dialects/utils/dynamic_index_list.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def verify_dynamic_index_list(
    static_values: Sequence[int],
    dynamic_values: Sequence[SSAValue],
    dynamic_index: int,
    end_message: str = "",
) -> None:
    """
    Verify that the static list contains only integers and that the dynamic list
    contains only SSAValues. The static list should be of the same length as the
    dynamic list, with the dynamic values replaced by `dynamic_index`.
    """
    num_dyn_indices = tuple(static_values).count(dynamic_index)
    if num_dyn_indices != len(dynamic_values):
        raise VerifyException(
            "The number of dynamic positions passed as values "
            f"({len(dynamic_values)}) does not match "
            "the number of dynamic position markers "
            f"({num_dyn_indices}){end_message}."
        )

get_dynamic_index_list(static_values: Sequence[int], dynamic_values: Sequence[SSAValue], dynamic_index: int) -> list[SSAValue | int]

Get a mixed list of SSAValues and integers from the static and dynamic lists. The static list contains integers, where the ones marked with dynamic_index are to be replaced with the SSAValues from the dynamic list.

For instance, given the static list [1, 2, MARKER, 4, MARKER] and the dynamic list [%3, %5], the result will be [1, 2, %3, 4, %5].

Source code in xdsl/dialects/utils/dynamic_index_list.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
def get_dynamic_index_list(
    static_values: Sequence[int],
    dynamic_values: Sequence[SSAValue],
    dynamic_index: int,
) -> list[SSAValue | int]:
    """
    Get a mixed list of SSAValues and integers from the static and dynamic
    lists. The static list contains integers, where the ones marked with
    `dynamic_index` are to be replaced with the SSAValues from the dynamic list.

    For instance, given the static list `[1, 2, MARKER, 4, MARKER]` and the
    dynamic list `[%3, %5]`, the result will be `[1, 2, %3, 4, %5]`.
    """
    next_dynamic_index = 0
    result: list[SSAValue | int] = []
    for pos in static_values:
        assert isinstance(pos, int)
        if pos == dynamic_index:
            result.append(dynamic_values[next_dynamic_index])
            next_dynamic_index += 1
            continue
        result.append(pos)
    return result

split_dynamic_index_list(values: Sequence[SSAValue | int], dynamic_index: int) -> tuple[list[int], list[SSAValue]]

Split a mixed list of SSAValues and integers into static and dynamic lists. The static list contains integers, where the ones marked with dynamic_index are to be replaced with the SSAValues from the dynamic list.

For instance, given the list [1, 2, %3, 4, %5], the result will be: - static: [1, 2, MARKER, 4, MARKER] - dynamic: [%3, %5]

Source code in xdsl/dialects/utils/dynamic_index_list.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def split_dynamic_index_list(
    values: Sequence[SSAValue | int],
    dynamic_index: int,
) -> tuple[list[int], list[SSAValue]]:
    """
    Split a mixed list of SSAValues and integers into static and dynamic lists.
    The static list contains integers, where the ones marked with `dynamic_index`
    are to be replaced with the SSAValues from the dynamic list.

    For instance, given the list `[1, 2, %3, 4, %5]`, the result will be:
    - static: `[1, 2, MARKER, 4, MARKER]`
    - dynamic: [%3, %5]
    """
    static_values = [
        value if isinstance(value, int) else dynamic_index for value in values
    ]
    dynamic_values = [value for value in values if isinstance(value, SSAValue)]
    return static_values, dynamic_values

print_dynamic_index_list(printer: Printer, dynamic_index: int, values: Sequence[SSAValue], integers: Iterable[int], value_types: Sequence[Attribute] = (), *, delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE)

Prints a list with either 1) the static integer value in integers is ShapedType.DYNAMIC or 2) the next value otherwise. If value_types is non-empty, it is expected to contain as many elements as values indicating their types. This allows idiomatic printing of mixed value and integer attributes in a list. E.g. [%arg0 : index, 7, 42, %arg42 : i32]. The dynamic_index parameter specifies the sentinel value to use to print an ssa value instead of a constant.

Source code in xdsl/dialects/utils/dynamic_index_list.py
 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
def print_dynamic_index_list(
    printer: Printer,
    dynamic_index: int,
    values: Sequence[SSAValue],
    integers: Iterable[int],
    value_types: Sequence[Attribute] = (),
    *,
    delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE,
):
    """
    Prints a list with either
      1) the static integer value in `integers` is `ShapedType.DYNAMIC` or
      2) the next value otherwise.
    If `value_types` is non-empty, it is expected to contain as many elements as `values`
    indicating their types. This allows idiomatic printing of mixed value and
    integer attributes in a list. E.g.
    `[%arg0 : index, 7, 42, %arg42 : i32]`.
    The `dynamic_index` parameter specifies the sentinel value to use to print an ssa
    value instead of a constant.
    """
    if delimiter.value is not None:
        printer.print_string(delimiter.value[0])
    value_index = 0
    for integer_index, integer in enumerate(integers):
        if integer_index:
            printer.print_string(", ")
        if integer == dynamic_index:
            printer.print_ssa_value(values[value_index])
            if value_types:
                printer.print_string(" : ")
                printer.print_attribute(value_types[value_index])
            value_index += 1
        else:
            printer.print_string(f"{integer}")
    if delimiter.value is not None:
        printer.print_string(delimiter.value[1])

parse_dynamic_index_with_type(parser: Parser) -> int | SSAValue

Parses an element in an index list, either an index or an ssa value with a type: e.g. 42 or %val : i32.

Source code in xdsl/dialects/utils/dynamic_index_list.py
137
138
139
140
141
142
143
144
145
146
147
148
def parse_dynamic_index_with_type(parser: Parser) -> int | SSAValue:
    """
    Parses an element in an index list, either an index or an ssa value with a type:
    e.g. `42` or `%val : i32`.
    """
    value = parser.parse_optional_unresolved_operand()
    if value is None:
        return parser.parse_integer(allow_boolean=False, allow_negative=False)
    else:
        parser.parse_punctuation(":")
        value_type = parser.parse_attribute()
        return parser.resolve_operand(value, value_type)

parse_dynamic_index_without_type(parser: Parser) -> int | UnresolvedOperand

Parses an element in an index list, either an index or an ssa value without a type: e.g. 42 or %val.

Source code in xdsl/dialects/utils/dynamic_index_list.py
151
152
153
154
155
156
157
158
159
160
def parse_dynamic_index_without_type(parser: Parser) -> int | UnresolvedOperand:
    """
    Parses an element in an index list, either an index or an ssa value without a type:
    e.g. `42` or `%val`.
    """
    value = parser.parse_optional_unresolved_operand()
    if value is None:
        return parser.parse_integer(allow_boolean=False)
    else:
        return value

parse_dynamic_index_list_with_types(parser: Parser, dynamic_index: int, *, delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE) -> tuple[Sequence[SSAValue], Sequence[int]]

Parses an in index list, composed of a mix of indices and ssa values with types: e.g. [1, 2, 3, %val : i32, 5]. The dynamic_index parameter specifies the sentinel value to use to print an ssa value instead of a constant.

Source code in xdsl/dialects/utils/dynamic_index_list.py
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
189
def parse_dynamic_index_list_with_types(
    parser: Parser,
    dynamic_index: int,
    *,
    delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE,
) -> tuple[Sequence[SSAValue], Sequence[int]]:
    """
    Parses an in index list, composed of a mix of indices and ssa values with types:
    e.g. `[1, 2, 3, %val : i32, 5]`.
    The `dynamic_index` parameter specifies the sentinel value to use to print an ssa
    value instead of a constant.
    """
    mixed_values = parser.parse_comma_separated_list(
        delimiter, lambda: parse_dynamic_index_with_type(parser)
    )

    values: list[SSAValue] = []
    indices: list[int] = []

    for value_or_index in mixed_values:
        if isinstance(value_or_index, int):
            indices.append(value_or_index)
        else:
            indices.append(dynamic_index)
            values.append(value_or_index)

    return values, indices

parse_dynamic_index_list_without_types(parser: Parser, dynamic_index: int, *, delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE) -> tuple[Sequence[UnresolvedOperand], Sequence[int]]

Parses an in index list, composed of a mix of indices and ssa values without types: e.g. [1, 2, 3, %val, 5]. The dynamic_index parameter specifies the sentinel value to use to print an ssa value instead of a constant.

Source code in xdsl/dialects/utils/dynamic_index_list.py
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
def parse_dynamic_index_list_without_types(
    parser: Parser,
    dynamic_index: int,
    *,
    delimiter: Parser.Delimiter = Parser.Delimiter.SQUARE,
) -> tuple[Sequence[UnresolvedOperand], Sequence[int]]:
    """
    Parses an in index list, composed of a mix of indices and ssa values without types:
    e.g. `[1, 2, 3, %val, 5]`.
    The `dynamic_index` parameter specifies the sentinel value to use to print an ssa
    value instead of a constant.
    """
    mixed_values = parser.parse_comma_separated_list(
        delimiter, lambda: parse_dynamic_index_without_type(parser)
    )

    values: list[UnresolvedOperand] = []
    indices: list[int] = []

    for value_or_index in mixed_values:
        if isinstance(value_or_index, int):
            indices.append(value_or_index)
        else:
            indices.append(dynamic_index)
            values.append(value_or_index)

    return values, indices