xref: /llvm-project/mlir/test/python/ir/array_attributes.py (revision 5d3ae5161210c068d01ffba36c8e0761e9971179)
1# RUN: %PYTHON %s | FileCheck %s
2# Note that this is separate from ir_attributes.py since it depends on numpy,
3# and we may want to disable if not available.
4
5import gc
6from mlir.ir import *
7import numpy as np
8import weakref
9
10
11def run(f):
12    print("\nTEST:", f.__name__)
13    f()
14    gc.collect()
15    assert Context._get_live_count() == 0
16    return f
17
18
19################################################################################
20# Tests of the array/buffer .get() factory method on unsupported dtype.
21################################################################################
22
23
24@run
25def testGetDenseElementsUnsupported():
26    with Context():
27        array = np.array([["hello", "goodbye"]])
28        try:
29            attr = DenseElementsAttr.get(array)
30        except ValueError as e:
31            # CHECK: unimplemented array format conversion from format:
32            print(e)
33
34# CHECK-LABEL: TEST: testGetDenseElementsUnSupportedTypeOkIfExplicitTypeProvided
35@run
36def testGetDenseElementsUnSupportedTypeOkIfExplicitTypeProvided():
37    with Context():
38        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)
39        # datetime64 specifically isn't important: it's just a 64-bit type that
40        # doesn't have a format under the Python buffer protocol. A more
41        # realistic example would be a NumPy extension type like the bfloat16
42        # type from the ml_dtypes package, which isn't a dependency of this
43        # test.
44        attr = DenseElementsAttr.get(array.view(np.datetime64),
45                                     type=IntegerType.get_signless(64))
46        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi64>
47        print(attr)
48        # CHECK: {{\[}}[1 2 3]
49        # CHECK: {{\[}}4 5 6]]
50        print(np.array(attr))
51
52
53################################################################################
54# Tests of the list of attributes .get() factory method
55################################################################################
56
57
58# CHECK-LABEL: TEST: testGetDenseElementsFromList
59@run
60def testGetDenseElementsFromList():
61    with Context(), Location.unknown():
62        attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)]
63        attr = DenseElementsAttr.get(attrs)
64
65        # CHECK: dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
66        print(attr)
67
68
69# CHECK-LABEL: TEST: testGetDenseElementsFromListWithExplicitType
70@run
71def testGetDenseElementsFromListWithExplicitType():
72    with Context(), Location.unknown():
73        attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)]
74        shaped_type = ShapedType(Type.parse("tensor<2xf64>"))
75        attr = DenseElementsAttr.get(attrs, shaped_type)
76
77        # CHECK: dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64>
78        print(attr)
79
80
81# CHECK-LABEL: TEST: testGetDenseElementsFromListEmptyList
82@run
83def testGetDenseElementsFromListEmptyList():
84    with Context(), Location.unknown():
85        attrs = []
86
87        try:
88            attr = DenseElementsAttr.get(attrs)
89        except ValueError as e:
90            # CHECK: Attributes list must be non-empty
91            print(e)
92
93
94# CHECK-LABEL: TEST: testGetDenseElementsFromListNonAttributeType
95@run
96def testGetDenseElementsFromListNonAttributeType():
97    with Context(), Location.unknown():
98        attrs = [1.0]
99
100        try:
101            attr = DenseElementsAttr.get(attrs)
102        except RuntimeError as e:
103            # CHECK: Invalid attribute when attempting to create an ArrayAttribute
104            print(e)
105
106
107# CHECK-LABEL: TEST: testGetDenseElementsFromListMismatchedType
108@run
109def testGetDenseElementsFromListMismatchedType():
110    with Context(), Location.unknown():
111        attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F64Type.get(), 2.0)]
112        shaped_type = ShapedType(Type.parse("tensor<2xf32>"))
113
114        try:
115            attr = DenseElementsAttr.get(attrs, shaped_type)
116        except ValueError as e:
117            # CHECK: All attributes must be of the same type and match the type parameter
118            print(e)
119
120
121# CHECK-LABEL: TEST: testGetDenseElementsFromListMixedTypes
122@run
123def testGetDenseElementsFromListMixedTypes():
124    with Context(), Location.unknown():
125        attrs = [FloatAttr.get(F64Type.get(), 1.0), FloatAttr.get(F32Type.get(), 2.0)]
126
127        try:
128            attr = DenseElementsAttr.get(attrs)
129        except ValueError as e:
130            # CHECK: All attributes must be of the same type and match the type parameter
131            print(e)
132
133
134################################################################################
135# Splats.
136################################################################################
137
138# CHECK-LABEL: TEST: testGetDenseElementsSplatInt
139@run
140def testGetDenseElementsSplatInt():
141    with Context(), Location.unknown():
142        t = IntegerType.get_signless(32)
143        element = IntegerAttr.get(t, 555)
144        shaped_type = RankedTensorType.get((2, 3, 4), t)
145        attr = DenseElementsAttr.get_splat(shaped_type, element)
146        # CHECK: dense<555> : tensor<2x3x4xi32>
147        print(attr)
148        # CHECK: is_splat: True
149        print("is_splat:", attr.is_splat)
150
151        # CHECK: splat_value: IntegerAttr(555 : i32)
152        splat_value = attr.get_splat_value()
153        print("splat_value:", repr(splat_value))
154        assert splat_value == element
155
156
157# CHECK-LABEL: TEST: testGetDenseElementsSplatFloat
158@run
159def testGetDenseElementsSplatFloat():
160    with Context(), Location.unknown():
161        t = F32Type.get()
162        element = FloatAttr.get(t, 1.2)
163        shaped_type = RankedTensorType.get((2, 3, 4), t)
164        attr = DenseElementsAttr.get_splat(shaped_type, element)
165        # CHECK: dense<1.200000e+00> : tensor<2x3x4xf32>
166        print(attr)
167        assert attr.get_splat_value() == element
168
169
170# CHECK-LABEL: TEST: testGetDenseElementsSplatErrors
171@run
172def testGetDenseElementsSplatErrors():
173    with Context(), Location.unknown():
174        t = F32Type.get()
175        other_t = F64Type.get()
176        element = FloatAttr.get(t, 1.2)
177        other_element = FloatAttr.get(other_t, 1.2)
178        shaped_type = RankedTensorType.get((2, 3, 4), t)
179        dynamic_shaped_type = UnrankedTensorType.get(t)
180        non_shaped_type = t
181
182        try:
183            attr = DenseElementsAttr.get_splat(non_shaped_type, element)
184        except ValueError as e:
185            # CHECK: Expected a static ShapedType for the shaped_type parameter: Type(f32)
186            print(e)
187
188        try:
189            attr = DenseElementsAttr.get_splat(dynamic_shaped_type, element)
190        except ValueError as e:
191            # CHECK: Expected a static ShapedType for the shaped_type parameter: Type(tensor<*xf32>)
192            print(e)
193
194        try:
195            attr = DenseElementsAttr.get_splat(shaped_type, other_element)
196        except ValueError as e:
197            # CHECK: Shaped element type and attribute type must be equal: shaped=Type(tensor<2x3x4xf32>), element=Attribute(1.200000e+00 : f64)
198            print(e)
199
200
201# CHECK-LABEL: TEST: testRepeatedValuesSplat
202@run
203def testRepeatedValuesSplat():
204    with Context():
205        array = np.array([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]], dtype=np.float32)
206        attr = DenseElementsAttr.get(array)
207        # CHECK: dense<1.000000e+00> : tensor<2x3xf32>
208        print(attr)
209        # CHECK: is_splat: True
210        print("is_splat:", attr.is_splat)
211        # CHECK{LITERAL}: [[1. 1. 1.]
212        # CHECK{LITERAL}:  [1. 1. 1.]]
213        print(np.array(attr))
214
215
216# CHECK-LABEL: TEST: testNonSplat
217@run
218def testNonSplat():
219    with Context():
220        array = np.array([2.0, 1.0, 1.0], dtype=np.float32)
221        attr = DenseElementsAttr.get(array)
222        # CHECK: is_splat: False
223        print("is_splat:", attr.is_splat)
224
225
226################################################################################
227# Tests of the array/buffer .get() factory method, in all of its permutations.
228################################################################################
229
230### explicitly provided types
231
232
233@run
234def testGetDenseElementsBF16():
235    with Context():
236        array = np.array([[2, 4, 8], [16, 32, 64]], dtype=np.uint16)
237        attr = DenseElementsAttr.get(array, type=BF16Type.get())
238        # Note: These values don't mean much since just bit-casting. But they
239        # shouldn't change.
240        # CHECK: dense<{{\[}}[1.836710e-40, 3.673420e-40, 7.346840e-40], [1.469370e-39, 2.938740e-39, 5.877470e-39]]> : tensor<2x3xbf16>
241        print(attr)
242
243
244@run
245def testGetDenseElementsInteger4():
246    with Context():
247        array = np.array([[2, 4, 7], [-2, -4, -8]], dtype=np.int8)
248        attr = DenseElementsAttr.get(array, type=IntegerType.get_signless(4))
249        # Note: These values don't mean much since just bit-casting. But they
250        # shouldn't change.
251        # CHECK: dense<{{\[}}[2, 4, 7], [-2, -4, -8]]> : tensor<2x3xi4>
252        print(attr)
253
254
255@run
256def testGetDenseElementsBool():
257    with Context():
258        bool_array = np.array([[1, 0, 1], [0, 1, 0]], dtype=np.bool_)
259        array = np.packbits(bool_array, axis=None, bitorder="little")
260        attr = DenseElementsAttr.get(
261            array, type=IntegerType.get_signless(1), shape=bool_array.shape
262        )
263        # CHECK: dense<{{\[}}[true, false, true], [false, true, false]]> : tensor<2x3xi1>
264        print(attr)
265
266
267@run
268def testGetDenseElementsBoolSplat():
269    with Context():
270        zero = np.array(0, dtype=np.uint8)
271        one = np.array(255, dtype=np.uint8)
272        print(one)
273        # CHECK: dense<false> : tensor<4x2x5xi1>
274        print(
275            DenseElementsAttr.get(
276                zero, type=IntegerType.get_signless(1), shape=(4, 2, 5)
277            )
278        )
279        # CHECK: dense<true> : tensor<4x2x5xi1>
280        print(
281            DenseElementsAttr.get(
282                one, type=IntegerType.get_signless(1), shape=(4, 2, 5)
283            )
284        )
285
286
287### float and double arrays.
288
289
290# CHECK-LABEL: TEST: testGetDenseElementsF16
291@run
292def testGetDenseElementsF16():
293    with Context():
294        array = np.array([[2.0, 4.0, 8.0], [16.0, 32.0, 64.0]], dtype=np.float16)
295        attr = DenseElementsAttr.get(array)
296        # CHECK: dense<{{\[}}[2.000000e+00, 4.000000e+00, 8.000000e+00], [1.600000e+01, 3.200000e+01, 6.400000e+01]]> : tensor<2x3xf16>
297        print(attr)
298        # CHECK: {{\[}}[ 2. 4. 8.]
299        # CHECK: {{\[}}16. 32. 64.]]
300        print(np.array(attr))
301
302
303# CHECK-LABEL: TEST: testGetDenseElementsF32
304@run
305def testGetDenseElementsF32():
306    with Context():
307        array = np.array([[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]], dtype=np.float32)
308        attr = DenseElementsAttr.get(array)
309        # CHECK: dense<{{\[}}[1.100000e+00, 2.200000e+00, 3.300000e+00], [4.400000e+00, 5.500000e+00, 6.600000e+00]]> : tensor<2x3xf32>
310        print(attr)
311        # CHECK: {{\[}}[1.1 2.2 3.3]
312        # CHECK: {{\[}}4.4 5.5 6.6]]
313        print(np.array(attr))
314
315
316# CHECK-LABEL: TEST: testGetDenseElementsF64
317@run
318def testGetDenseElementsF64():
319    with Context():
320        array = np.array([[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]], dtype=np.float64)
321        attr = DenseElementsAttr.get(array)
322        # CHECK: dense<{{\[}}[1.100000e+00, 2.200000e+00, 3.300000e+00], [4.400000e+00, 5.500000e+00, 6.600000e+00]]> : tensor<2x3xf64>
323        print(attr)
324        # CHECK: {{\[}}[1.1 2.2 3.3]
325        # CHECK: {{\[}}4.4 5.5 6.6]]
326        print(np.array(attr))
327
328
329### 1 bit/boolean integer arrays
330# CHECK-LABEL: TEST: testGetDenseElementsI1Signless
331@run
332def testGetDenseElementsI1Signless():
333    with Context():
334        array = np.array([True], dtype=np.bool_)
335        attr = DenseElementsAttr.get(array)
336        # CHECK: dense<true> : tensor<1xi1>
337        print(attr)
338        # CHECK{LITERAL}: [ True]
339        print(np.array(attr))
340
341        array = np.array([[True, False, True], [True, True, False]], dtype=np.bool_)
342        attr = DenseElementsAttr.get(array)
343        # CHECK{LITERAL}: dense<[[true, false, true], [true, true, false]]> : tensor<2x3xi1>
344        print(attr)
345        # CHECK{LITERAL}: [[ True False True]
346        # CHECK{LITERAL}:  [ True True False]]
347        print(np.array(attr))
348
349        array = np.array(
350            [[True, True, False, False], [True, False, True, False]], dtype=np.bool_
351        )
352        attr = DenseElementsAttr.get(array)
353        # CHECK{LITERAL}: dense<[[true, true, false, false], [true, false, true, false]]> : tensor<2x4xi1>
354        print(attr)
355        # CHECK{LITERAL}: [[ True True False False]
356        # CHECK{LITERAL}:  [ True False True False]]
357        print(np.array(attr))
358
359        array = np.array(
360            [
361                [True, True, False, False],
362                [True, False, True, False],
363                [False, False, False, False],
364                [True, True, True, True],
365                [True, False, False, True],
366            ],
367            dtype=np.bool_,
368        )
369        attr = DenseElementsAttr.get(array)
370        # CHECK{LITERAL}: dense<[[true, true, false, false], [true, false, true, false], [false, false, false, false], [true, true, true, true], [true, false, false, true]]> : tensor<5x4xi1>
371        print(attr)
372        # CHECK{LITERAL}: [[ True True False False]
373        # CHECK{LITERAL}:  [ True False True False]
374        # CHECK{LITERAL}:  [False False False False]
375        # CHECK{LITERAL}:  [ True True True True]
376        # CHECK{LITERAL}:  [ True False False True]]
377        print(np.array(attr))
378
379        array = np.array(
380            [
381                [True, True, False, False, True, True, False, False, False],
382                [False, False, False, True, False, True, True, False, True],
383            ],
384            dtype=np.bool_,
385        )
386        attr = DenseElementsAttr.get(array)
387        # CHECK{LITERAL}: dense<[[true, true, false, false, true, true, false, false, false], [false, false, false, true, false, true, true, false, true]]> : tensor<2x9xi1>
388        print(attr)
389        # CHECK{LITERAL}: [[ True True False False True True False False False]
390        # CHECK{LITERAL}:  [False False False True False True True False True]]
391        print(np.array(attr))
392
393        array = np.array([], dtype=np.bool_)
394        attr = DenseElementsAttr.get(array)
395        # CHECK: dense<> : tensor<0xi1>
396        print(attr)
397        # CHECK{LITERAL}: []
398        print(np.array(attr))
399
400
401### 16 bit integer arrays
402# CHECK-LABEL: TEST: testGetDenseElementsI16Signless
403@run
404def testGetDenseElementsI16Signless():
405    with Context():
406        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int16)
407        attr = DenseElementsAttr.get(array)
408        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi16>
409        print(attr)
410        # CHECK: {{\[}}[1 2 3]
411        # CHECK: {{\[}}4 5 6]]
412        print(np.array(attr))
413
414
415# CHECK-LABEL: TEST: testGetDenseElementsUI16Signless
416@run
417def testGetDenseElementsUI16Signless():
418    with Context():
419        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint16)
420        attr = DenseElementsAttr.get(array)
421        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi16>
422        print(attr)
423        # CHECK: {{\[}}[1 2 3]
424        # CHECK: {{\[}}4 5 6]]
425        print(np.array(attr))
426
427
428# CHECK-LABEL: TEST: testGetDenseElementsI16
429@run
430def testGetDenseElementsI16():
431    with Context():
432        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int16)
433        attr = DenseElementsAttr.get(array, signless=False)
434        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xsi16>
435        print(attr)
436        # CHECK: {{\[}}[1 2 3]
437        # CHECK: {{\[}}4 5 6]]
438        print(np.array(attr))
439
440
441# CHECK-LABEL: TEST: testGetDenseElementsUI16
442@run
443def testGetDenseElementsUI16():
444    with Context():
445        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint16)
446        attr = DenseElementsAttr.get(array, signless=False)
447        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xui16>
448        print(attr)
449        # CHECK: {{\[}}[1 2 3]
450        # CHECK: {{\[}}4 5 6]]
451        print(np.array(attr))
452
453
454### 32 bit integer arrays
455# CHECK-LABEL: TEST: testGetDenseElementsI32Signless
456@run
457def testGetDenseElementsI32Signless():
458    with Context():
459        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)
460        attr = DenseElementsAttr.get(array)
461        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
462        print(attr)
463        # CHECK: {{\[}}[1 2 3]
464        # CHECK: {{\[}}4 5 6]]
465        print(np.array(attr))
466
467
468# CHECK-LABEL: TEST: testGetDenseElementsUI32Signless
469@run
470def testGetDenseElementsUI32Signless():
471    with Context():
472        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint32)
473        attr = DenseElementsAttr.get(array)
474        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
475        print(attr)
476        # CHECK: {{\[}}[1 2 3]
477        # CHECK: {{\[}}4 5 6]]
478        print(np.array(attr))
479
480
481# CHECK-LABEL: TEST: testGetDenseElementsI32
482@run
483def testGetDenseElementsI32():
484    with Context():
485        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)
486        attr = DenseElementsAttr.get(array, signless=False)
487        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xsi32>
488        print(attr)
489        # CHECK: {{\[}}[1 2 3]
490        # CHECK: {{\[}}4 5 6]]
491        print(np.array(attr))
492
493
494# CHECK-LABEL: TEST: testGetDenseElementsUI32
495@run
496def testGetDenseElementsUI32():
497    with Context():
498        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint32)
499        attr = DenseElementsAttr.get(array, signless=False)
500        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xui32>
501        print(attr)
502        # CHECK: {{\[}}[1 2 3]
503        # CHECK: {{\[}}4 5 6]]
504        print(np.array(attr))
505
506
507## 64bit integer arrays
508# CHECK-LABEL: TEST: testGetDenseElementsI64Signless
509@run
510def testGetDenseElementsI64Signless():
511    with Context():
512        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)
513        attr = DenseElementsAttr.get(array)
514        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi64>
515        print(attr)
516        # CHECK: {{\[}}[1 2 3]
517        # CHECK: {{\[}}4 5 6]]
518        print(np.array(attr))
519
520
521# CHECK-LABEL: TEST: testGetDenseElementsUI64Signless
522@run
523def testGetDenseElementsUI64Signless():
524    with Context():
525        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint64)
526        attr = DenseElementsAttr.get(array)
527        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi64>
528        print(attr)
529        # CHECK: {{\[}}[1 2 3]
530        # CHECK: {{\[}}4 5 6]]
531        print(np.array(attr))
532
533
534# CHECK-LABEL: TEST: testGetDenseElementsI64
535@run
536def testGetDenseElementsI64():
537    with Context():
538        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)
539        attr = DenseElementsAttr.get(array, signless=False)
540        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xsi64>
541        print(attr)
542        # CHECK: {{\[}}[1 2 3]
543        # CHECK: {{\[}}4 5 6]]
544        print(np.array(attr))
545
546
547# CHECK-LABEL: TEST: testGetDenseElementsUI64
548@run
549def testGetDenseElementsUI64():
550    with Context():
551        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint64)
552        attr = DenseElementsAttr.get(array, signless=False)
553        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xui64>
554        print(attr)
555        # CHECK: {{\[}}[1 2 3]
556        # CHECK: {{\[}}4 5 6]]
557        print(np.array(attr))
558
559
560# CHECK-LABEL: TEST: testGetDenseElementsIndex
561@run
562def testGetDenseElementsIndex():
563    with Context(), Location.unknown():
564        idx_type = IndexType.get()
565        array = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64)
566        attr = DenseElementsAttr.get(array, type=idx_type)
567        # CHECK: dense<{{\[}}[1, 2, 3], [4, 5, 6]]> : tensor<2x3xindex>
568        print(attr)
569        arr = np.array(attr)
570        # CHECK: {{\[}}[1 2 3]
571        # CHECK: {{\[}}4 5 6]]
572        print(arr)
573        # CHECK: True
574        print(arr.dtype == np.int64)
575        array = np.array([1, 2, 3], dtype=np.int64)
576        attr = DenseIntElementsAttr.get(array, type=VectorType.get([3], idx_type))
577        # CHECK: [1, 2, 3]
578        print(list(DenseIntElementsAttr(attr)))
579
580
581# CHECK-LABEL: TEST: testGetDenseResourceElementsAttr
582@run
583def testGetDenseResourceElementsAttr():
584    def on_delete(_):
585        print("BACKING MEMORY DELETED")
586
587    context = Context()
588    mview = memoryview(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32))
589    ref = weakref.ref(mview, on_delete)
590
591    def test_attribute(context, mview):
592        with context, Location.unknown():
593            element_type = IntegerType.get_signless(32)
594            tensor_type = RankedTensorType.get((2, 3), element_type)
595            resource = DenseResourceElementsAttr.get_from_buffer(
596                mview, "from_py", tensor_type
597            )
598            module = Module.parse("module {}")
599            module.operation.attributes["test.resource"] = resource
600            # CHECK: test.resource = dense_resource<from_py> : tensor<2x3xi32>
601            # CHECK: from_py: "0x04000000010000000200000003000000040000000500000006000000"
602            print(module)
603
604            # Verifies type casting.
605            # CHECK: dense_resource<from_py> : tensor<2x3xi32>
606            print(
607                DenseResourceElementsAttr(module.operation.attributes["test.resource"])
608            )
609
610    test_attribute(context, mview)
611    mview = None
612    gc.collect()
613    # CHECK: FREEING CONTEXT
614    print("FREEING CONTEXT")
615    context = None
616    gc.collect()
617    # CHECK: BACKING MEMORY DELETED
618    # CHECK: EXIT FUNCTION
619    print("EXIT FUNCTION")
620