@@ -47,6 +47,54 @@ func.func @fold_expand_into_loads_dynamic() -> tensor<2x?x16x32xf32> {
4747// CHECK-SAME: offsets = [0, 0, 0, 0], sizes = [2, %[[SHAPE]], 16, 32], strides = [1, 1, 1, 1]
4848// CHECK-SAME: !iree_tensor_ext.dispatch.tensor<readonly:tensor<2x?x16x32xf32>>{%[[SHAPE]]}
4949
50+ // -----
51+
52+ #pipeline_layout = #hal.pipeline.layout <constants = 3 , bindings = [
53+ #hal.pipeline.binding <storage_buffer , " ReadOnly|Indirect" >], flags = Indirect >
54+ func.func @fold_expand_into_loads_fully_dynamic () -> tensor <?x?xf32 > {
55+ %c0 = arith.constant 0 : index
56+ %0 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (0 ) : index
57+ %1 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (1 ) : index
58+ %2 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (2 ) : index
59+ %3 = hal.interface.binding.subspan layout (#pipeline_layout ) binding (0 ) alignment (64 ) offset (%c0 )
60+ flags (" ReadOnly|Indirect" ) : !iree_tensor_ext.dispatch.tensor <readonly :tensor <?xf32 >>{%0 }
61+ %4 = iree_tensor_ext.dispatch.tensor.load %3 , offsets = [0 ], sizes = [%0 ], strides = [1 ]
62+ : !iree_tensor_ext.dispatch.tensor <readonly :tensor <?xf32 >>{%0 } -> tensor <?xf32 >
63+ %5 = tensor.expand_shape %4 [[0 , 1 ]] output_shape [%1 , %2 ] : tensor <?xf32 > into tensor <?x?xf32 >
64+ return %5 : tensor <?x?xf32 >
65+ }
66+ // CHECK-LABEL: func @fold_expand_into_loads_fully_dynamic()
67+ // CHECK-DAG: %[[CONST0:.+]] = hal.interface.constant.load {{.*}} ordinal(1)
68+ // CHECK-DAG: %[[CONST1:.+]] = hal.interface.constant.load {{.*}} ordinal(2)
69+ // CHECK: %[[SUBSPAN:.+]] = hal.interface.binding.subspan
70+ // CHECK-SAME: !iree_tensor_ext.dispatch.tensor<readonly:tensor<?x?xf32>>{%[[CONST0]], %[[CONST1]]}
71+ // CHECK: %[[LOAD:.+]] = iree_tensor_ext.dispatch.tensor.load %[[SUBSPAN]]
72+ // CHECK-SAME: offsets = [0, 0], sizes = [%[[CONST0]], %[[CONST1]]]
73+ // CHECK-SAME: !iree_tensor_ext.dispatch.tensor<readonly:tensor<?x?xf32>>{%[[CONST0]], %[[CONST1]]}
74+
75+ // -----
76+
77+ #pipeline_layout = #hal.pipeline.layout <constants = 2 , bindings = [
78+ #hal.pipeline.binding <storage_buffer , " ReadOnly|Indirect" >], flags = Indirect >
79+ func.func @no_fold_expand_into_loads_fully_dynamic () -> tensor <?x?xindex > {
80+ %c0 = arith.constant 0 : index
81+ %0 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (0 ) : index
82+ %1 = hal.interface.constant.load layout (#pipeline_layout ) ordinal (1 ) : index
83+ %2 = hal.interface.binding.subspan layout (#pipeline_layout ) binding (0 ) alignment (64 ) offset (%c0 )
84+ flags (" ReadOnly|Indirect" ) : !iree_tensor_ext.dispatch.tensor <readonly :tensor <?xindex >>{%0 }
85+ %3 = iree_tensor_ext.dispatch.tensor.load %2 , offsets = [0 ], sizes = [%0 ], strides = [1 ]
86+ : !iree_tensor_ext.dispatch.tensor <readonly :tensor <?xindex >>{%0 } -> tensor <?xindex >
87+ %4 = tensor.extract %3 [%c0 ] : tensor <?xindex >
88+ %5 = tensor.expand_shape %3 [[0 , 1 ]] output_shape [%1 , %4 ] : tensor <?xindex > into tensor <?x?xindex >
89+ return %5 : tensor <?x?xindex >
90+ }
91+ // This case cannot be folded because expanded sizes depend on the tensor itself.
92+ // So, the size cannot be known before the load.
93+
94+ // CHECK-LABEL: func @no_fold_expand_into_loads_fully_dynamic()
95+ // CHECK: tensor.expand_shape
96+
97+
5098// -----
5199
52100#pipeline_layout = #hal.pipeline.layout <constants = 1 , bindings = [
0 commit comments