1
- // RUN: iree-opt --pass-pipeline="builtin.module(func.func(iree-codegen-propagate-reshapes-by-expansion))" --split-input-file %s | FileCheck %s
1
+ // RUN: iree-opt --pass-pipeline="builtin.module(func.func(iree-codegen-propagate-reshapes-by-expansion))" --split-input-file %s --mlir-print-local-scope | FileCheck %s
2
2
3
3
func.func @reshape_and_lowering_config (%src: tensor <3 x4 xf16 >, %dest: tensor <12 xf16 >, %dest2: tensor <12 xf16 >) -> tensor <12 xf16 > {
4
4
%collapse = tensor.collapse_shape %src [[0 , 1 ]] : tensor <3 x4 xf16 > into tensor <12 xf16 >
@@ -14,3 +14,75 @@ func.func @reshape_and_lowering_config(%src: tensor<3x4xf16>, %dest: tensor<12xf
14
14
// CHECK: linalg.copy
15
15
// CHECK-SAME: lowering_config = #iree_gpu.derived_thread_config
16
16
// CHECK-SAME: ins(%[[COLLAPSE]]
17
+
18
+ // -----
19
+
20
+ #pipeline_layout = #hal.pipeline.layout <constants = 1 , bindings = [
21
+ #hal.pipeline.binding <storage_buffer , " ReadOnly|Indirect" >], flags = Indirect >
22
+ func.func @fold_collapse_into_loads_dynamic () -> tensor <?x32 xf32 > {
23
+ %c0 = arith.constant 0 : index
24
+ %0 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (0 ) : index
25
+ %1 = hal.interface.binding.subspan layout (#pipeline_layout ) binding (0 ) alignment (64 ) offset (%c0 )
26
+ flags (" ReadOnly|Indirect" ) : !flow.dispatch.tensor <readonly :tensor <2 x?x32 xf32 >>{%0 }
27
+ %2 = flow.dispatch.tensor.load %1 , offsets = [0 , 0 , 0 ], sizes = [2 , %0 , 32 ], strides = [1 , 1 , 1 ]
28
+ : !flow.dispatch.tensor <readonly :tensor <2 x?x32 xf32 >>{%0 } -> tensor <2 x?x32 xf32 >
29
+ %3 = tensor.collapse_shape %2 [[0 , 1 ], [2 ]] : tensor <2 x?x32 xf32 > into tensor <?x32 xf32 >
30
+ return %3 : tensor <?x32 xf32 >
31
+ }
32
+ // CHECK-LABEL: func @fold_collapse_into_loads_dynamic()
33
+ // CHECK: %[[CONST:.+]] = hal.interface.constant.load
34
+ // CHECK: %[[SHAPE:.+]] = affine.apply affine_map<()[s0] -> (s0 * 2)>()[%[[CONST]]]
35
+ // CHECK: %[[SUBSPAN:.+]] = hal.interface.binding.subspan
36
+ // CHECK-SAME: !flow.dispatch.tensor<readonly:tensor<?x32xf32>>{%[[SHAPE]]}
37
+ // CHECK: %[[LOAD:.+]] = flow.dispatch.tensor.load %[[SUBSPAN]]
38
+ // CHECK-SAME: offsets = [0, 0], sizes = [%[[SHAPE]], 32], strides = [1, 1]
39
+ // CHECK-SAME: !flow.dispatch.tensor<readonly:tensor<?x32xf32>>{%[[SHAPE]]}
40
+
41
+ // -----
42
+
43
+ #pipeline_layout = #hal.pipeline.layout <constants = 2 , bindings = [
44
+ #hal.pipeline.binding <storage_buffer , " ReadOnly|Indirect" >], flags = Indirect >
45
+ func.func @fold_expand_into_loads_dynamic () -> tensor <2 x?x16 x32 xf32 > {
46
+ %c0 = arith.constant 0 : index
47
+ %0 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (0 ) : index
48
+ %1 = hal.interface.binding.subspan layout (#pipeline_layout ) binding (0 ) alignment (64 ) offset (%c0 )
49
+ flags (" ReadOnly|Indirect" ) : !flow.dispatch.tensor <readonly :tensor <2 x?x32 xf32 >>{%0 }
50
+ %2 = flow.dispatch.tensor.load %1 , offsets = [0 , 0 , 0 ], sizes = [2 , %0 , 32 ], strides = [1 , 1 , 1 ]
51
+ : !flow.dispatch.tensor <readonly :tensor <2 x?x32 xf32 >>{%0 } -> tensor <2 x?x32 xf32 >
52
+ %3 = affine.apply affine_map <()[s0 ] -> (s0 floordiv 2 )>()[%0 ]
53
+ %4 = tensor.expand_shape %2 [[0 ], [1 , 2 ], [3 ]] output_shape [2 , %3 , 16 , 32 ] : tensor <2 x?x32 xf32 > into tensor <2 x?x16 x32 xf32 >
54
+ return %4 : tensor <2 x?x16 x32 xf32 >
55
+ }
56
+ // CHECK-LABEL: func @fold_expand_into_loads_dynamic()
57
+ // CHECK-DAG: %[[C16:.+]] = arith.constant 16 : index
58
+ // CHECK-DAG: %[[CONST:.+]] = hal.interface.constant.load
59
+ // CHECK: %[[SHAPE:.+]] = arith.divui %[[CONST]], %[[C16]]
60
+ // CHECK: %[[SUBSPAN:.+]] = hal.interface.binding.subspan
61
+ // CHECK-SAME: !flow.dispatch.tensor<readonly:tensor<2x?x16x32xf32>>{%[[SHAPE]]}
62
+ // CHECK: %[[LOAD:.+]] = flow.dispatch.tensor.load %[[SUBSPAN]]
63
+ // CHECK-SAME: offsets = [0, 0, 0, 0], sizes = [2, %[[SHAPE]], 16, 32], strides = [1, 1, 1, 1]
64
+ // CHECK-SAME: !flow.dispatch.tensor<readonly:tensor<2x?x16x32xf32>>{%[[SHAPE]]}
65
+
66
+ // -----
67
+
68
+ #pipeline_layout = #hal.pipeline.layout <constants = 1 , bindings = [
69
+ #hal.pipeline.binding <storage_buffer , Indirect >], flags = Indirect >
70
+ func.func @fold_collapse_into_stores_dynamic (%arg0 : tensor <2 x?x32 xf32 >) {
71
+ %c0 = arith.constant 0 : index
72
+ %0 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (0 ) : index
73
+ %1 = hal.interface.binding.subspan layout (#pipeline_layout ) binding (0 ) alignment (64 ) offset (%c0 )
74
+ flags (" ReadOnly|Indirect" ) : !flow.dispatch.tensor <writeonly :tensor <?x32 xf32 >>{%0 }
75
+ %2 = tensor.collapse_shape %arg0 [[0 , 1 ], [2 ]] : tensor <2 x?x32 xf32 > into tensor <?x32 xf32 >
76
+ flow.dispatch.tensor.store %2 , %1 , offsets = [0 , 0 ], sizes = [%0 , 32 ], strides = [1 , 1 ]
77
+ : tensor <?x32 xf32 > -> !flow.dispatch.tensor <writeonly :tensor <?x32 xf32 >>{%0 }
78
+ return
79
+ }
80
+ // CHECK-LABEL: func @fold_collapse_into_stores_dynamic(
81
+ // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index
82
+ // CHECK: %[[CONST:.+]] = hal.interface.constant.load
83
+ // CHECK: %[[SHAPE:.+]] = arith.divui %[[CONST]], %[[C2]]
84
+ // CHECK: %[[SUBSPAN:.+]] = hal.interface.binding.subspan
85
+ // CHECK-SAME: !flow.dispatch.tensor<writeonly:tensor<2x?x32xf32>>{%[[SHAPE]]}
86
+ // CHECK: flow.dispatch.tensor.store %{{.+}}, %[[SUBSPAN]]
87
+ // CHECK-SAME: offsets = [0, 0, 0], sizes = [2, %[[SHAPE]], 32], strides = [1, 1, 1]
88
+ // CHECK-SAME: !flow.dispatch.tensor<writeonly:tensor<2x?x32xf32>>{%[[SHAPE]]}
0 commit comments