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
220
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
@irdl_custom_directive
class DynamicIndexList(CustomDirective):
    """
    Custom directive for parsing dynamic index list.
    These contain a mix of indices and (untyped) ssa values.
    """

    dynamic_position: VariadicOperandVariable
    static_position: AttributeVariable

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

    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, 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_position: VariadicOperandVariable instance-attribute

static_position: AttributeVariable instance-attribute

parse(parser: Parser, state: ParsingState)

Source code in xdsl/dialects/utils/dynamic_index_list.py
230
231
232
233
def parse(self, parser: Parser, state: ParsingState):
    dynamic, static = parse_dynamic_index_list_without_types(parser, DYNAMIC_INDEX)
    self.dynamic_position.set(state, dynamic)
    self.static_position.set(state, DenseArrayBase.from_list(i64, static))

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

Source code in xdsl/dialects/utils/dynamic_index_list.py
235
236
237
238
239
240
241
242
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, DYNAMIC_INDEX, dynamic, static.get_values())

set_empty(state: ParsingState)

Source code in xdsl/dialects/utils/dynamic_index_list.py
244
245
246
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
248
249
250
251
252
253
254
255
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
257
258
def is_anchorable(self) -> bool:
    return True

ScalableDynamicIndexList dataclass

Bases: CustomDirective

Custom directive for parsing a dynamic index list where each element may additionally be marked as scalable by wrapping it in square brackets, e.g. [4, [8], %v]. Port of upstream custom<DynamicIndexList> with scalable flags.

Source code in xdsl/dialects/utils/dynamic_index_list.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
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
@irdl_custom_directive
class ScalableDynamicIndexList(CustomDirective):
    """
    Custom directive for parsing a dynamic index list where each element may
    additionally be marked as scalable by wrapping it in square brackets,
    e.g. `[4, [8], %v]`.
    Port of upstream `custom<DynamicIndexList>` with scalable flags.
    """

    dynamic_values: VariadicOperandVariable
    static_values: AttributeVariable
    scalable_flags: AttributeVariable

    @staticmethod
    def _parse_element(
        parser: Parser,
        dynamic: list[UnresolvedOperand],
        static: list[int],
        scalable: list[int],
    ) -> None:
        is_scalable = parser.parse_optional_punctuation("[") is not None
        value = parse_dynamic_index_without_type(parser)
        if is_scalable:
            parser.parse_punctuation("]")
        if isinstance(value, int):
            static.append(value)
        else:
            static.append(DYNAMIC_INDEX)
            dynamic.append(value)
        scalable.append(int(is_scalable))

    def parse(self, parser: Parser, state: ParsingState):
        dynamic: list[UnresolvedOperand] = []
        static: list[int] = []
        scalable: list[int] = []
        parser.parse_comma_separated_list(
            Parser.Delimiter.SQUARE,
            lambda: self._parse_element(parser, dynamic, static, scalable),
        )
        self.dynamic_values.set(state, dynamic)
        self.static_values.set(state, DenseArrayBase.from_list(i64, static))
        self.scalable_flags.set(state, DenseArrayBase.from_list(i1, scalable))

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

        dynamic = self.dynamic_values.get(op)
        static = self.static_values.get(op)
        scalable = self.scalable_flags.get(op)
        static_values = ()
        if static is not None:
            assert isa(static, DenseArrayBase[IntegerType])
            static_values = static.get_values()
        scalable_values: Sequence[int] = ()
        if scalable is not None:
            assert isa(scalable, DenseArrayBase[IntegerType])
            scalable_values = scalable.get_values()

        printer.print_string("[")
        dynamic_index = 0
        for i, value in enumerate(static_values):
            if i:
                printer.print_string(", ")
            is_scalable = i < len(scalable_values) and scalable_values[i]
            if is_scalable:
                printer.print_string("[")
            if value == DYNAMIC_INDEX:
                printer.print_ssa_value(dynamic[dynamic_index])
                dynamic_index += 1
            else:
                printer.print_string(f"{value}")
            if is_scalable:
                printer.print_string("]")
        printer.print_string("]")

dynamic_values: VariadicOperandVariable instance-attribute

static_values: AttributeVariable instance-attribute

scalable_flags: AttributeVariable instance-attribute

parse(parser: Parser, state: ParsingState)

Source code in xdsl/dialects/utils/dynamic_index_list.py
292
293
294
295
296
297
298
299
300
301
302
def parse(self, parser: Parser, state: ParsingState):
    dynamic: list[UnresolvedOperand] = []
    static: list[int] = []
    scalable: list[int] = []
    parser.parse_comma_separated_list(
        Parser.Delimiter.SQUARE,
        lambda: self._parse_element(parser, dynamic, static, scalable),
    )
    self.dynamic_values.set(state, dynamic)
    self.static_values.set(state, DenseArrayBase.from_list(i64, static))
    self.scalable_flags.set(state, DenseArrayBase.from_list(i1, scalable))

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

Source code in xdsl/dialects/utils/dynamic_index_list.py
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
def print(self, printer: Printer, state: PrintingState, op: IRDLOperation) -> None:
    state.print_whitespace(printer)

    dynamic = self.dynamic_values.get(op)
    static = self.static_values.get(op)
    scalable = self.scalable_flags.get(op)
    static_values = ()
    if static is not None:
        assert isa(static, DenseArrayBase[IntegerType])
        static_values = static.get_values()
    scalable_values: Sequence[int] = ()
    if scalable is not None:
        assert isa(scalable, DenseArrayBase[IntegerType])
        scalable_values = scalable.get_values()

    printer.print_string("[")
    dynamic_index = 0
    for i, value in enumerate(static_values):
        if i:
            printer.print_string(", ")
        is_scalable = i < len(scalable_values) and scalable_values[i]
        if is_scalable:
            printer.print_string("[")
        if value == DYNAMIC_INDEX:
            printer.print_ssa_value(dynamic[dynamic_index])
            dynamic_index += 1
        else:
            printer.print_string(f"{value}")
        if is_scalable:
            printer.print_string("]")
    printer.print_string("]")

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
 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
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
136
137
138
139
140
141
142
143
144
145
146
147
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
150
151
152
153
154
155
156
157
158
159
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
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
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
191
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
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