[SandboxVec][BottomUpVec] Fix packing when PHIs are present (#124206)
[llvm-project.git] / mlir / test / Conversion / MemRefToLLVM / convert-dynamic-memref-ops.mlir
blobebfc3b95d6effd38ead556229b7a4188500933f5
1 // RUN: mlir-opt -split-input-file -finalize-memref-to-llvm %s | FileCheck %s
2 // RUN: mlir-opt -split-input-file -finalize-memref-to-llvm='use-aligned-alloc=1' %s | FileCheck %s --check-prefix=ALIGNED-ALLOC
3 // RUN: mlir-opt -split-input-file -finalize-memref-to-llvm='index-bitwidth=32' %s | FileCheck --check-prefix=CHECK32 %s
5 // CHECK-LABEL: func @mixed_alloc(
6 //       CHECK:   %[[Marg:.*]]: index, %[[Narg:.*]]: index)
7 func.func @mixed_alloc(%arg0: index, %arg1: index) -> memref<?x42x?xf32> {
8 //   CHECK-DAG:  %[[M:.*]] = builtin.unrealized_conversion_cast %[[Marg]]
9 //   CHECK-DAG:  %[[N:.*]] = builtin.unrealized_conversion_cast %[[Narg]]
10 //       CHECK:  %[[c42:.*]] = llvm.mlir.constant(42 : index) : i64
11 //  CHECK-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : i64
12 //  CHECK-NEXT:  %[[st0:.*]] = llvm.mul %[[N]], %[[c42]] : i64
13 //  CHECK-NEXT:  %[[sz:.*]] = llvm.mul %[[st0]], %[[M]] : i64
14 //  CHECK-NEXT:  %[[null:.*]] = llvm.mlir.zero : !llvm.ptr
15 //  CHECK-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[sz]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
16 //  CHECK-NEXT:  %[[sz_bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to i64
17 //  CHECK-NEXT:  llvm.call @malloc(%[[sz_bytes]]) : (i64) -> !llvm.ptr
18 //  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
19 //  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
20 //  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
21 //  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : i64
22 //  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
23 //  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
24 //  CHECK-NEXT:  llvm.insertvalue %[[c42]], %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
25 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
26 //  CHECK-NEXT:  llvm.insertvalue %[[st0]], %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
27 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
28 //  CHECK-NEXT:  llvm.insertvalue %[[one]], %{{.*}}[4, 2] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
29   %0 = memref.alloc(%arg0, %arg1) : memref<?x42x?xf32>
30   return %0 : memref<?x42x?xf32>
33 // -----
35 // CHECK-LABEL: func @mixed_dealloc
36 func.func @mixed_dealloc(%arg0: memref<?x42x?xf32>) {
37 //      CHECK:  %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>
38 // CHECK-NEXT:  llvm.call @free(%[[ptr]]) : (!llvm.ptr) -> ()
39   memref.dealloc %arg0 : memref<?x42x?xf32>
40   return
43 // -----
45 // CHECK-LABEL: func @unranked_dealloc
46 func.func @unranked_dealloc(%arg0: memref<*xf32>) {
47 //      CHECK: %[[memref:.*]] = llvm.extractvalue %{{.*}} : !llvm.struct<(i64, ptr)>
48 //      CHECK: %[[ptr:.*]] = llvm.load %[[memref]]
49 // CHECK-NEXT: llvm.call @free(%[[ptr]])
50   memref.dealloc %arg0 : memref<*xf32>
51   return
54 // -----
56 // CHECK-LABEL: func @dynamic_alloc(
57 //       CHECK:   %[[Marg:.*]]: index, %[[Narg:.*]]: index)
58 func.func @dynamic_alloc(%arg0: index, %arg1: index) -> memref<?x?xf32> {
59 //   CHECK-DAG:  %[[M:.*]] = builtin.unrealized_conversion_cast %[[Marg]]
60 //   CHECK-DAG:  %[[N:.*]] = builtin.unrealized_conversion_cast %[[Narg]]
61 //  CHECK-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : i64
62 //  CHECK-NEXT:  %[[sz:.*]] = llvm.mul %[[N]], %[[M]] : i64
63 //  CHECK-NEXT:  %[[null:.*]] = llvm.mlir.zero : !llvm.ptr
64 //  CHECK-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[sz]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
65 //  CHECK-NEXT:  %[[sz_bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to i64
66 //  CHECK-NEXT:  llvm.call @malloc(%[[sz_bytes]]) : (i64) -> !llvm.ptr
67 //  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
68 //  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
69 //  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
70 //  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : i64
71 //  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
72 //  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
73 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
74 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
75 //  CHECK-NEXT:  llvm.insertvalue %[[one]], %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
76   %0 = memref.alloc(%arg0, %arg1) : memref<?x?xf32>
77   return %0 : memref<?x?xf32>
80 // -----
82 // CHECK-LABEL: func @dynamic_alloca
83 // CHECK: %[[Marg:.*]]: index, %[[Narg:.*]]: index)
84 func.func @dynamic_alloca(%arg0: index, %arg1: index) -> memref<?x?xf32> {
85 //   CHECK-DAG:  %[[M:.*]] = builtin.unrealized_conversion_cast %[[Marg]]
86 //   CHECK-DAG:  %[[N:.*]] = builtin.unrealized_conversion_cast %[[Narg]]
87 //  CHECK-NEXT:  %[[st1:.*]] = llvm.mlir.constant(1 : index) : i64
88 //  CHECK-NEXT:  %[[num_elems:.*]] = llvm.mul %[[N]], %[[M]] : i64
89 //  CHECK-NEXT:  %[[allocated:.*]] = llvm.alloca %[[num_elems]] x f32 : (i64) -> !llvm.ptr
90 //  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
91 //  CHECK-NEXT:  llvm.insertvalue %[[allocated]], %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
92 //  CHECK-NEXT:  llvm.insertvalue %[[allocated]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
93 //  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : i64
94 //  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
95 //  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
96 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
97 //  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
98 //  CHECK-NEXT:  llvm.insertvalue %[[st1]], %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
99   %0 = memref.alloca(%arg0, %arg1) : memref<?x?xf32>
101 // Test with explicitly specified alignment. llvm.alloca takes care of the
102 // alignment. The same pointer is thus used for allocation and aligned
103 // accesses.
104 // CHECK: %[[alloca_aligned:.*]] = llvm.alloca %{{.*}} x f32 {alignment = 32 : i64} : (i64) -> !llvm.ptr
105 // CHECK: %[[desc:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
106 // CHECK: %[[desc1:.*]] = llvm.insertvalue %[[alloca_aligned]], %[[desc]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
107 // CHECK: llvm.insertvalue %[[alloca_aligned]], %[[desc1]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
108   memref.alloca(%arg0, %arg1) {alignment = 32} : memref<?x?xf32>
109   return %0 : memref<?x?xf32>
112 // -----
114 // CHECK-LABEL: func @dynamic_dealloc
115 func.func @dynamic_dealloc(%arg0: memref<?x?xf32>) {
116 //      CHECK:  %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
117 // CHECK-NEXT:  llvm.call @free(%[[ptr]]) : (!llvm.ptr) -> ()
118   memref.dealloc %arg0 : memref<?x?xf32>
119   return
122 // -----
124 // CHECK-LABEL: func @stdlib_aligned_alloc({{.*}})
125 // ALIGNED-ALLOC-LABEL: func @stdlib_aligned_alloc({{.*}})
126 func.func @stdlib_aligned_alloc(%N : index) -> memref<32x18xf32> {
127 // ALIGNED-ALLOC:       %[[sz1:.*]] = llvm.mlir.constant(32 : index) : i64
128 // ALIGNED-ALLOC-NEXT:  %[[sz2:.*]] = llvm.mlir.constant(18 : index) : i64
129 // ALIGNED-ALLOC-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : i64
130 // ALIGNED-ALLOC-NEXT:  %[[num_elems:.*]] = llvm.mlir.constant(576 : index) : i64
131 // ALIGNED-ALLOC-NEXT:  %[[null:.*]] = llvm.mlir.zero : !llvm.ptr
132 // ALIGNED-ALLOC-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[num_elems]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
133 // ALIGNED-ALLOC-NEXT:  %[[bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to i64
134 // ALIGNED-ALLOC-NEXT:  %[[alignment:.*]] = llvm.mlir.constant(32 : index) : i64
135 // ALIGNED-ALLOC-NEXT:  %[[allocated:.*]] = llvm.call @aligned_alloc(%[[alignment]], %[[bytes]]) : (i64, i64) -> !llvm.ptr
136   %0 = memref.alloc() {alignment = 32} : memref<32x18xf32>
137   // Do another alloc just to test that we have a unique declaration for
138   // aligned_alloc.
139   // ALIGNED-ALLOC:  llvm.call @aligned_alloc
140   %1 = memref.alloc() {alignment = 64} : memref<4096xf32>
142   // Alignment is to element type boundaries (minimum 16 bytes).
143   // ALIGNED-ALLOC:  %[[c32:.*]] = llvm.mlir.constant(32 : index) : i64
144   // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c32]]
145   %2 = memref.alloc() : memref<4096xvector<8xf32>>
146   // The minimum alignment is 16 bytes unless explicitly specified.
147   // ALIGNED-ALLOC:  %[[c16:.*]] = llvm.mlir.constant(16 : index) : i64
148   // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c16]],
149   %3 = memref.alloc() : memref<4096xvector<2xf32>>
150   // ALIGNED-ALLOC:  %[[c8:.*]] = llvm.mlir.constant(8 : index) : i64
151   // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c8]],
152   %4 = memref.alloc() {alignment = 8} : memref<1024xvector<4xf32>>
153   // Bump the memref allocation size if its size is not a multiple of alignment.
154   // ALIGNED-ALLOC:       %[[c32:.*]] = llvm.mlir.constant(32 : index) : i64
155   // ALIGNED-ALLOC:       llvm.mlir.constant(1 : index) : i64
156   // ALIGNED-ALLOC-NEXT:  llvm.sub
157   // ALIGNED-ALLOC-NEXT:  llvm.add
158   // ALIGNED-ALLOC-NEXT:  llvm.urem
159   // ALIGNED-ALLOC-NEXT:  %[[SIZE_ALIGNED:.*]] = llvm.sub
160   // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c32]], %[[SIZE_ALIGNED]])
161   %5 = memref.alloc() {alignment = 32} : memref<100xf32>
162   // Bump alignment to the next power of two if it isn't.
163   // ALIGNED-ALLOC:  %[[c128:.*]] = llvm.mlir.constant(128 : index) : i64
164   // ALIGNED-ALLOC:  llvm.call @aligned_alloc(%[[c128]]
165   %6 = memref.alloc(%N) : memref<?xvector<18xf32>>
166   return %0 : memref<32x18xf32>
169 // -----
171 // CHECK-LABEL: func @mixed_load(
172 // CHECK:         %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index)
173 func.func @mixed_load(%mixed : memref<42x?xf32>, %i : index, %j : index) {
174 //   CHECK-DAG:  %[[I:.*]] = builtin.unrealized_conversion_cast %[[Iarg]]
175 //   CHECK-DAG:  %[[J:.*]] = builtin.unrealized_conversion_cast %[[Jarg]]
176 //       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
177 //  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
178 //  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : i64
179 //  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : i64
180 //  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
181 //  CHECK-NEXT:  llvm.load %[[addr]] : !llvm.ptr -> f32
182   %0 = memref.load %mixed[%i, %j] : memref<42x?xf32>
183   return
186 // -----
188 // CHECK-LABEL: func @dynamic_load(
189 // CHECK:         %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index)
190 func.func @dynamic_load(%dynamic : memref<?x?xf32>, %i : index, %j : index) {
191 //   CHECK-DAG:  %[[I:.*]] = builtin.unrealized_conversion_cast %[[Iarg]]
192 //   CHECK-DAG:  %[[J:.*]] = builtin.unrealized_conversion_cast %[[Jarg]]
193 //       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
194 //  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
195 //  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : i64
196 //  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : i64
197 //  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
198 //  CHECK-NEXT:  llvm.load %[[addr]] : !llvm.ptr -> f32
199   %0 = memref.load %dynamic[%i, %j] : memref<?x?xf32>
200   return
203 // -----
205 // CHECK-LABEL: func @prefetch
206 // CHECK:         %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index)
207 func.func @prefetch(%A : memref<?x?xf32>, %i : index, %j : index) {
208 //      CHECK-DAG:  %[[I:.*]] = builtin.unrealized_conversion_cast %[[Iarg]]
209 //      CHECK-DAG:  %[[J:.*]] = builtin.unrealized_conversion_cast %[[Jarg]]
210 //      CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
211 // CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
212 // CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : i64
213 // CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : i64
214 // CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
215 // CHECK-NEXT:  "llvm.intr.prefetch"(%[[addr]]) <{cache = 1 : i32, hint = 3 : i32, rw = 1 : i32}> : (!llvm.ptr) -> ()
216   memref.prefetch %A[%i, %j], write, locality<3>, data : memref<?x?xf32>
217 // CHECK:  "llvm.intr.prefetch"(%{{.*}}) <{cache = 1 : i32, hint = 0 : i32, rw = 0 : i32}> : (!llvm.ptr) -> ()
218   memref.prefetch %A[%i, %j], read, locality<0>, data : memref<?x?xf32>
219 // CHECK:  "llvm.intr.prefetch"(%{{.*}}) <{cache = 0 : i32, hint = 2 : i32, rw = 0 : i32}> : (!llvm.ptr) -> ()
220   memref.prefetch %A[%i, %j], read, locality<2>, instr : memref<?x?xf32>
221   return
224 // -----
226 // CHECK-LABEL: func @dynamic_store
227 // CHECK:         %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index
228 func.func @dynamic_store(%dynamic : memref<?x?xf32>, %i : index, %j : index, %val : f32) {
229 //   CHECK-DAG:  %[[I:.*]] = builtin.unrealized_conversion_cast %[[Iarg]]
230 //   CHECK-DAG:  %[[J:.*]] = builtin.unrealized_conversion_cast %[[Jarg]]
231 //       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
232 //  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
233 //  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : i64
234 //  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : i64
235 //  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
236 //  CHECK-NEXT:  llvm.store %{{.*}}, %[[addr]] : f32, !llvm.ptr
237   memref.store %val, %dynamic[%i, %j] : memref<?x?xf32>
238   return
241 // -----
243 // CHECK-LABEL: func @mixed_store
244 // CHECK:         %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index
245 func.func @mixed_store(%mixed : memref<42x?xf32>, %i : index, %j : index, %val : f32) {
246 //   CHECK-DAG:  %[[I:.*]] = builtin.unrealized_conversion_cast %[[Iarg]]
247 //   CHECK-DAG:  %[[J:.*]] = builtin.unrealized_conversion_cast %[[Jarg]]
248 //       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
249 //  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>
250 //  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : i64
251 //  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : i64
252 //  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
253 //  CHECK-NEXT:  llvm.store %{{.*}}, %[[addr]] : f32, !llvm.ptr
254   memref.store %val, %mixed[%i, %j] : memref<42x?xf32>
255   return
258 // -----
260 // FIXME: the *ToLLVM passes don't use information from data layouts
261 // to set address spaces, so the constants below don't reflect the layout
262 // Update this test once that data layout attribute works how we'd expect it to.
263 module attributes { dlti.dl_spec = #dlti.dl_spec<
264   #dlti.dl_entry<!llvm.ptr, dense<[64, 64, 64]> : vector<3xi64>>,
265   #dlti.dl_entry<!llvm.ptr<1>, dense<[32, 32, 32]> : vector<3xi64>>> }  {
266   // CHECK-LABEL: @memref_memory_space_cast
267   func.func @memref_memory_space_cast(%input : memref<*xf32>) -> memref<*xf32, 1> {
268     %cast = memref.memory_space_cast %input : memref<*xf32> to memref<*xf32, 1>
269     return %cast : memref<*xf32, 1>
270   }
272 // CHECK: [[INPUT:%.*]] = builtin.unrealized_conversion_cast %{{.*}} to !llvm.struct<(i64, ptr)>
273 // CHECK: [[RANK:%.*]] = llvm.extractvalue [[INPUT]][0] : !llvm.struct<(i64, ptr)>
274 // CHECK: [[SOURCE_DESC:%.*]] = llvm.extractvalue [[INPUT]][1]
275 // CHECK: [[RESULT_0:%.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)>
276 // CHECK: [[RESULT_1:%.*]] = llvm.insertvalue [[RANK]], [[RESULT_0]][0] : !llvm.struct<(i64, ptr)>
278 // Compute size in bytes to allocate result ranked descriptor
279 // CHECK: [[C1:%.*]] = llvm.mlir.constant(1 : index) : i64
280 // CHECK: [[C2:%.*]] = llvm.mlir.constant(2 : index) : i64
281 // CHECK: [[INDEX_SIZE:%.*]] = llvm.mlir.constant(8 : index) : i64
282 // CHECK: [[PTR_SIZE:%.*]] = llvm.mlir.constant(8 : index) : i64
283 // CHECK: [[DOUBLE_PTR_SIZE:%.*]] = llvm.mul [[C2]], [[PTR_SIZE]]
284 // CHECK: [[DOUBLE_RANK:%.*]] = llvm.mul [[C2]], %{{.*}}
285 // CHECK: [[NUM_INDEX_VALS:%.*]] = llvm.add [[DOUBLE_RANK]], [[C1]]
286 // CHECK: [[INDEX_VALS_SIZE:%.*]] = llvm.mul [[NUM_INDEX_VALS]], [[INDEX_SIZE]]
287 // CHECK: [[DESC_ALLOC_SIZE:%.*]] = llvm.add [[DOUBLE_PTR_SIZE]], [[INDEX_VALS_SIZE]]
288 // CHECK: [[RESULT_DESC:%.*]] = llvm.alloca [[DESC_ALLOC_SIZE]] x i8
289 // CHECK: llvm.insertvalue [[RESULT_DESC]], [[RESULT_1]][1]
291 // Cast pointers
292 // CHECK: [[SOURCE_ALLOC:%.*]] = llvm.load [[SOURCE_DESC]]
293 // CHECK: [[SOURCE_ALIGN_GEP:%.*]] = llvm.getelementptr [[SOURCE_DESC]][1]
294 // CHECK: [[SOURCE_ALIGN:%.*]] = llvm.load [[SOURCE_ALIGN_GEP]] : !llvm.ptr
295 // CHECK: [[RESULT_ALLOC:%.*]] = llvm.addrspacecast [[SOURCE_ALLOC]] : !llvm.ptr to !llvm.ptr<1>
296 // CHECK: [[RESULT_ALIGN:%.*]] = llvm.addrspacecast [[SOURCE_ALIGN]] : !llvm.ptr to !llvm.ptr<1>
297 // CHECK: llvm.store [[RESULT_ALLOC]], [[RESULT_DESC]] : !llvm.ptr
298 // CHECK: [[RESULT_ALIGN_GEP:%.*]] = llvm.getelementptr [[RESULT_DESC]][1]
299 // CHECK: llvm.store [[RESULT_ALIGN]], [[RESULT_ALIGN_GEP]] : !llvm.ptr
301 // Memcpy remaining values
303 // CHECK: [[SOURCE_OFFSET_GEP:%.*]] = llvm.getelementptr [[SOURCE_DESC]][2]
304 // CHECK: [[RESULT_OFFSET_GEP:%.*]] = llvm.getelementptr [[RESULT_DESC]][2]
305 // CHECK: [[SIZEOF_TWO_RESULT_PTRS:%.*]] = llvm.mlir.constant(16 : index) : i64
306 // CHECK: [[COPY_SIZE:%.*]] = llvm.sub [[DESC_ALLOC_SIZE]], [[SIZEOF_TWO_RESULT_PTRS]]
307 // CHECK: "llvm.intr.memcpy"([[RESULT_OFFSET_GEP]], [[SOURCE_OFFSET_GEP]], [[COPY_SIZE]]) <{isVolatile = false}>
309 // -----
311 // CHECK-LABEL: func @memref_cast_static_to_dynamic
312 func.func @memref_cast_static_to_dynamic(%static : memref<10x42xf32>) {
313 // CHECK-NOT: llvm.bitcast
314   %0 = memref.cast %static : memref<10x42xf32> to memref<?x?xf32>
315   return
318 // -----
320 // CHECK-LABEL: func @memref_cast_static_to_mixed
321 func.func @memref_cast_static_to_mixed(%static : memref<10x42xf32>) {
322 // CHECK-NOT: llvm.bitcast
323   %0 = memref.cast %static : memref<10x42xf32> to memref<?x42xf32>
324   return
327 // -----
329 // CHECK-LABEL: func @memref_cast_dynamic_to_static
330 func.func @memref_cast_dynamic_to_static(%dynamic : memref<?x?xf32>) {
331 // CHECK-NOT: llvm.bitcast
332   %0 = memref.cast %dynamic : memref<?x?xf32> to memref<10x12xf32>
333   return
336 // -----
338 // CHECK-LABEL: func @memref_cast_dynamic_to_mixed
339 func.func @memref_cast_dynamic_to_mixed(%dynamic : memref<?x?xf32>) {
340 // CHECK-NOT: llvm.bitcast
341   %0 = memref.cast %dynamic : memref<?x?xf32> to memref<?x12xf32>
342   return
345 // -----
347 // CHECK-LABEL: func @memref_cast_mixed_to_dynamic
348 func.func @memref_cast_mixed_to_dynamic(%mixed : memref<42x?xf32>) {
349 // CHECK-NOT: llvm.bitcast
350   %0 = memref.cast %mixed : memref<42x?xf32> to memref<?x?xf32>
351   return
354 // -----
356 // CHECK-LABEL: func @memref_cast_mixed_to_static
357 func.func @memref_cast_mixed_to_static(%mixed : memref<42x?xf32>) {
358 // CHECK-NOT: llvm.bitcast
359   %0 = memref.cast %mixed : memref<42x?xf32> to memref<42x1xf32>
360   return
363 // -----
365 // CHECK-LABEL: func @memref_cast_mixed_to_mixed
366 func.func @memref_cast_mixed_to_mixed(%mixed : memref<42x?xf32>) {
367 // CHECK-NOT: llvm.bitcast
368   %0 = memref.cast %mixed : memref<42x?xf32> to memref<?x1xf32>
369   return
372 // -----
374 // CHECK-LABEL: func @memref_cast_ranked_to_unranked
375 // CHECK32-LABEL: func @memref_cast_ranked_to_unranked
376 func.func @memref_cast_ranked_to_unranked(%arg : memref<42x2x?xf32>) {
377 // CHECK-DAG:  %[[c:.*]] = llvm.mlir.constant(1 : index) : i64
378 // CHECK-DAG:  %[[p:.*]] = llvm.alloca %[[c]] x !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)> : (i64) -> !llvm.ptr
379 // CHECK-DAG:  llvm.store %{{.*}}, %[[p]] : !llvm.struct<(ptr, ptr, i64, array<3 x i64>, array<3 x i64>)>, !llvm.ptr
380 // CHECK-DAG:  %[[r:.*]] = llvm.mlir.constant(3 : index) : i64
381 //     CHECK:  llvm.mlir.undef : !llvm.struct<(i64, ptr)>
382 // CHECK-DAG:  llvm.insertvalue %[[r]], %{{.*}}[0] : !llvm.struct<(i64, ptr)>
383 // CHECK-DAG:  llvm.insertvalue %[[p]], %{{.*}}[1] : !llvm.struct<(i64, ptr)>
384 // CHECK32-DAG:  %[[c:.*]] = llvm.mlir.constant(1 : index) : i64
385 // CHECK32-DAG:  %[[p:.*]] = llvm.alloca %[[c]] x !llvm.struct<(ptr, ptr, i32, array<3 x i32>, array<3 x i32>)> : (i64) -> !llvm.ptr
386 // CHECK32-DAG:  llvm.store %{{.*}}, %[[p]] : !llvm.struct<(ptr, ptr, i32, array<3 x i32>, array<3 x i32>)>, !llvm.ptr
387 // CHECK32-DAG:  %[[r:.*]] = llvm.mlir.constant(3 : index) : i32
388 //     CHECK32:  llvm.mlir.undef : !llvm.struct<(i32, ptr)>
389 // CHECK32-DAG:  llvm.insertvalue %[[r]], %{{.*}}[0] : !llvm.struct<(i32, ptr)>
390 // CHECK32-DAG:  llvm.insertvalue %[[p]], %{{.*}}[1] : !llvm.struct<(i32, ptr)>
391   %0 = memref.cast %arg : memref<42x2x?xf32> to memref<*xf32>
392   return
395 // -----
397 // CHECK-LABEL: func @memref_cast_unranked_to_ranked
398 func.func @memref_cast_unranked_to_ranked(%arg : memref<*xf32>) {
399 //      CHECK: %[[p:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(i64, ptr)>
400   %0 = memref.cast %arg : memref<*xf32> to memref<?x?x10x2xf32>
401   return
404 // -----
406 // CHECK-LABEL: func @mixed_memref_dim
407 func.func @mixed_memref_dim(%mixed : memref<42x?x?x13x?xf32>) {
408 // CHECK: llvm.mlir.constant(42 : index) : i64
409   %c0 = arith.constant 0 : index
410   %0 = memref.dim %mixed, %c0 : memref<42x?x?x13x?xf32>
411 // CHECK: llvm.extractvalue %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<5 x i64>, array<5 x i64>)>
412   %c1 = arith.constant 1 : index
413   %1 = memref.dim %mixed, %c1 : memref<42x?x?x13x?xf32>
414 // CHECK: llvm.extractvalue %{{.*}}[3, 2] : !llvm.struct<(ptr, ptr, i64, array<5 x i64>, array<5 x i64>)>
415   %c2 = arith.constant 2 : index
416   %2 = memref.dim %mixed, %c2 : memref<42x?x?x13x?xf32>
417 // CHECK: llvm.mlir.constant(13 : index) : i64
418   %c3 = arith.constant 3 : index
419   %3 = memref.dim %mixed, %c3 : memref<42x?x?x13x?xf32>
420 // CHECK: llvm.extractvalue %{{.*}}[3, 4] : !llvm.struct<(ptr, ptr, i64, array<5 x i64>, array<5 x i64>)>
421   %c4 = arith.constant 4 : index
422   %4 = memref.dim %mixed, %c4 : memref<42x?x?x13x?xf32>
423   return
426 // -----
428 // CHECK-LABEL: @memref_dim_with_dyn_index
429 // CHECK: %{{.*}}, %[[IDXarg:.*]]: index
430 func.func @memref_dim_with_dyn_index(%arg : memref<3x?xf32>, %idx : index) -> index {
431   // CHECK-DAG: %[[IDX:.*]] = builtin.unrealized_conversion_cast %[[IDXarg]]
432   // CHECK-DAG: %[[C1:.*]] = llvm.mlir.constant(1 : index) : i64
433   // CHECK-DAG: %[[SIZES:.*]] = llvm.extractvalue %{{.*}}[3] : ![[DESCR_TY:.*]]
434   // CHECK-DAG: %[[SIZES_PTR:.*]] = llvm.alloca %[[C1]] x !llvm.array<2 x i64> : (i64) -> !llvm.ptr
435   // CHECK-DAG: llvm.store %[[SIZES]], %[[SIZES_PTR]] : !llvm.array<2 x i64>, !llvm.ptr
436   // CHECK-DAG: %[[RESULT_PTR:.*]] = llvm.getelementptr %[[SIZES_PTR]][0, %[[IDX]]] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<2 x i64>
437   // CHECK-DAG: %[[RESULT:.*]] = llvm.load %[[RESULT_PTR]] : !llvm.ptr -> i64
438   %result = memref.dim %arg, %idx : memref<3x?xf32>
439   return %result : index
442 // -----
444 // CHECK-LABEL: @memref_reinterpret_cast_ranked_to_static_shape
445 func.func @memref_reinterpret_cast_ranked_to_static_shape(%input : memref<2x3xf32>) {
446   %output = memref.reinterpret_cast %input to
447            offset: [0], sizes: [6, 1], strides: [1, 1]
448            : memref<2x3xf32> to memref<6x1xf32>
449   return
451 // CHECK: [[INPUT:%.*]] = builtin.unrealized_conversion_cast %{{.*}} :
452 // CHECK: to [[TY:!.*]]
453 // CHECK: [[OUT_0:%.*]] = llvm.mlir.undef : [[TY]]
454 // CHECK: [[BASE_PTR:%.*]] = llvm.extractvalue [[INPUT]][0] : [[TY]]
455 // CHECK: [[ALIGNED_PTR:%.*]] = llvm.extractvalue [[INPUT]][1] : [[TY]]
456 // CHECK: [[OUT_1:%.*]] = llvm.insertvalue [[BASE_PTR]], [[OUT_0]][0] : [[TY]]
457 // CHECK: [[OUT_2:%.*]] = llvm.insertvalue [[ALIGNED_PTR]], [[OUT_1]][1] : [[TY]]
458 // CHECK: [[OFFSET:%.*]] = llvm.mlir.constant(0 : index) : i64
459 // CHECK: [[OUT_3:%.*]] = llvm.insertvalue [[OFFSET]], [[OUT_2]][2] : [[TY]]
460 // CHECK: [[SIZE_0:%.*]] = llvm.mlir.constant(6 : index) : i64
461 // CHECK: [[OUT_4:%.*]] = llvm.insertvalue [[SIZE_0]], [[OUT_3]][3, 0] : [[TY]]
462 // CHECK: [[SIZE_1:%.*]] = llvm.mlir.constant(1 : index) : i64
463 // CHECK: [[OUT_5:%.*]] = llvm.insertvalue [[SIZE_1]], [[OUT_4]][4, 0] : [[TY]]
464 // CHECK: [[STRIDE_0:%.*]] = llvm.mlir.constant(1 : index) : i64
465 // CHECK: [[OUT_6:%.*]] = llvm.insertvalue [[STRIDE_0]], [[OUT_5]][3, 1] : [[TY]]
466 // CHECK: [[STRIDE_1:%.*]] = llvm.mlir.constant(1 : index) : i64
467 // CHECK: [[OUT_7:%.*]] = llvm.insertvalue [[STRIDE_1]], [[OUT_6]][4, 1] : [[TY]]
469 // -----
471 // CHECK-LABEL: @memref_reinterpret_cast_unranked_to_dynamic_shape
472 func.func @memref_reinterpret_cast_unranked_to_dynamic_shape(%offset: index,
473                                                         %size_0 : index,
474                                                         %size_1 : index,
475                                                         %stride_0 : index,
476                                                         %stride_1 : index,
477                                                         %input : memref<*xf32>) {
478   %output = memref.reinterpret_cast %input to
479            offset: [%offset], sizes: [%size_0, %size_1],
480            strides: [%stride_0, %stride_1]
481            : memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
482   return
484 // CHECK-SAME: ([[OFFSETarg:%[a-z,0-9]+]]: index,
485 // CHECK-SAME: [[SIZE_0arg:%[a-z,0-9]+]]: index, [[SIZE_1arg:%[a-z,0-9]+]]: index,
486 // CHECK-SAME: [[STRIDE_0arg:%[a-z,0-9]+]]: index, [[STRIDE_1arg:%[a-z,0-9]+]]: index,
487 // CHECK-DAG: [[OFFSET:%.*]] = builtin.unrealized_conversion_cast [[OFFSETarg]]
488 // CHECK-DAG: [[SIZE_0:%.*]] = builtin.unrealized_conversion_cast [[SIZE_0arg]]
489 // CHECK-DAG: [[SIZE_1:%.*]] = builtin.unrealized_conversion_cast [[SIZE_1arg]]
490 // CHECK-DAG: [[STRIDE_0:%.*]] = builtin.unrealized_conversion_cast [[STRIDE_0arg]]
491 // CHECK-DAG: [[STRIDE_1:%.*]] = builtin.unrealized_conversion_cast [[STRIDE_1arg]]
492 // CHECK-DAG: [[INPUT:%.*]] = builtin.unrealized_conversion_cast
493 // CHECK: [[OUT_0:%.*]] = llvm.mlir.undef : [[TY:!.*]]
494 // CHECK: [[DESCRIPTOR:%.*]] = llvm.extractvalue [[INPUT]][1] : !llvm.struct<(i64, ptr)>
495 // CHECK: [[BASE_PTR:%.*]] = llvm.load [[DESCRIPTOR]] : !llvm.ptr -> !llvm.ptr
496 // CHECK: [[ALIGNED_PTR_PTR:%.*]] = llvm.getelementptr [[DESCRIPTOR]]{{\[}}1]
497 // CHECK-SAME: : (!llvm.ptr) -> !llvm.ptr, !llvm.ptr
498 // CHECK: [[ALIGNED_PTR:%.*]] = llvm.load [[ALIGNED_PTR_PTR]] : !llvm.ptr -> !llvm.ptr
499 // CHECK: [[OUT_1:%.*]] = llvm.insertvalue [[BASE_PTR]], [[OUT_0]][0] : [[TY]]
500 // CHECK: [[OUT_2:%.*]] = llvm.insertvalue [[ALIGNED_PTR]], [[OUT_1]][1] : [[TY]]
501 // CHECK: [[OUT_3:%.*]] = llvm.insertvalue [[OFFSET]], [[OUT_2]][2] : [[TY]]
502 // CHECK: [[OUT_4:%.*]] = llvm.insertvalue [[SIZE_0]], [[OUT_3]][3, 0] : [[TY]]
503 // CHECK: [[OUT_5:%.*]] = llvm.insertvalue [[STRIDE_0]], [[OUT_4]][4, 0] : [[TY]]
504 // CHECK: [[OUT_6:%.*]] = llvm.insertvalue [[SIZE_1]], [[OUT_5]][3, 1] : [[TY]]
505 // CHECK: [[OUT_7:%.*]] = llvm.insertvalue [[STRIDE_1]], [[OUT_6]][4, 1] : [[TY]]
507 // -----
509 // CHECK-LABEL: @memref_reshape(
510 //  CHECK-SAME:     %[[ARG0:.*]]: memref<2x3xf32>, %[[ARG1:.*]]: memref<?xindex>)
511 func.func @memref_reshape(%input : memref<2x3xf32>, %shape : memref<?xindex>) {
512   %output = memref.reshape %input(%shape)
513                 : (memref<2x3xf32>, memref<?xindex>) -> memref<*xf32>
514   return
516 // CHECK-DAG: [[INPUT:%.*]] = builtin.unrealized_conversion_cast %[[ARG0]] : {{.*}} to [[INPUT_TY:!.*]]
517 // CHECK-DAG: [[SHAPE:%.*]] = builtin.unrealized_conversion_cast %[[ARG1]] : {{.*}} to [[SHAPE_TY:!.*]]
518 // CHECK: [[RANK:%.*]] = llvm.extractvalue [[SHAPE]][3, 0] : [[SHAPE_TY]]
519 // CHECK: [[UNRANKED_OUT_O:%.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)>
520 // CHECK: [[UNRANKED_OUT_1:%.*]] = llvm.insertvalue [[RANK]], [[UNRANKED_OUT_O]][0] : !llvm.struct<(i64, ptr)>
522 // Compute size in bytes to allocate result ranked descriptor
523 // CHECK: [[C1:%.*]] = llvm.mlir.constant(1 : index) : i64
524 // CHECK: [[C2:%.*]] = llvm.mlir.constant(2 : index) : i64
525 // CHECK: [[INDEX_SIZE:%.*]] = llvm.mlir.constant(8 : index) : i64
526 // CHECK: [[PTR_SIZE:%.*]] = llvm.mlir.constant(8 : index) : i64
527 // CHECK: [[DOUBLE_PTR_SIZE:%.*]] = llvm.mul [[C2]], [[PTR_SIZE]] : i64
528 // CHECK: [[DESC_ALLOC_SIZE:%.*]] = llvm.add [[DOUBLE_PTR_SIZE]], %{{.*}}
529 // CHECK: [[UNDERLYING_DESC:%.*]] = llvm.alloca [[DESC_ALLOC_SIZE]] x i8
530 // CHECK: llvm.insertvalue [[UNDERLYING_DESC]], [[UNRANKED_OUT_1]][1]
532 // Set allocated, aligned pointers and offset.
533 // CHECK: [[ALLOC_PTR:%.*]] = llvm.extractvalue [[INPUT]][0] : [[INPUT_TY]]
534 // CHECK: [[ALIGN_PTR:%.*]] = llvm.extractvalue [[INPUT]][1] : [[INPUT_TY]]
535 // CHECK: [[OFFSET:%.*]] = llvm.extractvalue [[INPUT]][2] : [[INPUT_TY]]
536 // CHECK: llvm.store [[ALLOC_PTR]], [[UNDERLYING_DESC]] : !llvm.ptr, !llvm.ptr
537 // CHECK: [[ALIGNED_PTR_PTR:%.*]] = llvm.getelementptr [[UNDERLYING_DESC]]{{\[}}1]
538 // CHECK: llvm.store [[ALIGN_PTR]], [[ALIGNED_PTR_PTR]] : !llvm.ptr, !llvm.ptr
539 // CHECK: [[OFFSET_PTR:%.*]] = llvm.getelementptr [[UNDERLYING_DESC]]{{\[}}2]
540 // CHECK: llvm.store [[OFFSET]], [[OFFSET_PTR]] : i64, !llvm.ptr
542 // Iterate over shape operand in reverse order and set sizes and strides.
543 // CHECK: [[SIZES_PTR:%.*]] = llvm.getelementptr [[UNDERLYING_DESC]]{{\[}}0, 3]
544 // CHECK: [[STRIDES_PTR:%.*]] = llvm.getelementptr [[SIZES_PTR]]{{\[}}[[RANK]]]
545 // CHECK: [[SHAPE_IN_PTR:%.*]] = llvm.extractvalue [[SHAPE]][1] : [[SHAPE_TY]]
546 // CHECK: [[C1_:%.*]] = llvm.mlir.constant(1 : index) : i64
547 // CHECK: [[RANK_MIN_1:%.*]] = llvm.sub [[RANK]], [[C1_]] : i64
548 // CHECK: llvm.br ^bb1([[RANK_MIN_1]], [[C1_]] : i64, i64)
550 // CHECK: ^bb1([[DIM:%.*]]: i64, [[CUR_STRIDE:%.*]]: i64):
551 // CHECK:   [[C0_:%.*]] = llvm.mlir.constant(0 : index) : i64
552 // CHECK:   [[COND:%.*]] = llvm.icmp "sge" [[DIM]], [[C0_]] : i64
553 // CHECK:   llvm.cond_br [[COND]], ^bb2, ^bb3
555 // CHECK: ^bb2:
556 // CHECK:   [[SIZE_PTR:%.*]] = llvm.getelementptr [[SHAPE_IN_PTR]]{{\[}}[[DIM]]]
557 // CHECK:   [[SIZE:%.*]] = llvm.load [[SIZE_PTR]] : !llvm.ptr -> i64
558 // CHECK:   [[TARGET_SIZE_PTR:%.*]] = llvm.getelementptr [[SIZES_PTR]]{{\[}}[[DIM]]]
559 // CHECK:   llvm.store [[SIZE]], [[TARGET_SIZE_PTR]] : i64, !llvm.ptr
560 // CHECK:   [[TARGET_STRIDE_PTR:%.*]] = llvm.getelementptr [[STRIDES_PTR]]{{\[}}[[DIM]]]
561 // CHECK:   llvm.store [[CUR_STRIDE]], [[TARGET_STRIDE_PTR]] : i64, !llvm.ptr
562 // CHECK:   [[UPDATE_STRIDE:%.*]] = llvm.mul [[CUR_STRIDE]], [[SIZE]] : i64
563 // CHECK:   [[STRIDE_COND:%.*]] = llvm.sub [[DIM]], [[C1_]] : i64
564 // CHECK:   llvm.br ^bb1([[STRIDE_COND]], [[UPDATE_STRIDE]] : i64, i64)
566 // CHECK: ^bb3:
567 // CHECK:   return
569 // -----
571 // ALIGNED-ALLOC-LABEL: @memref_of_memref
572 func.func @memref_of_memref() {
573   // Sizeof computation is as usual.
574   // ALIGNED-ALLOC: %[[NULL:.*]] = llvm.mlir.zero
575   // ALIGNED-ALLOC: %[[PTR:.*]] = llvm.getelementptr
576   // ALIGNED-ALLOC: %[[SIZEOF:.*]] = llvm.ptrtoint
578   // Static alignment should be computed as ceilPowerOf2(2 * sizeof(pointer) +
579   // (1 + 2 * rank) * sizeof(index) = ceilPowerOf2(2 * 8 + 3 * 8) = 64.
580   // ALIGNED-ALLOC: llvm.mlir.constant(64 : index)
582   // Check that the types are converted as expected.
583   // ALIGNED-ALLOC: llvm.call @aligned_alloc
584   // ALIGNED-ALLOC: llvm.mlir.undef
585   // ALIGNED-ALLOC-SAME: !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>
586   %0 = memref.alloc() : memref<1xmemref<1xf32>>
587   return
590 // -----
592 module attributes { dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<index, 32>> } {
593   // ALIGNED-ALLOC-LABEL: @memref_of_memref_32
594   func.func @memref_of_memref_32() {
595     // Sizeof computation is as usual.
596     // ALIGNED-ALLOC: %[[NULL:.*]] = llvm.mlir.zero
597     // ALIGNED-ALLOC: %[[PTR:.*]] = llvm.getelementptr
598     // ALIGNED-ALLOC: %[[SIZEOF:.*]] = llvm.ptrtoint
600     // Static alignment should be computed as ceilPowerOf2(2 * sizeof(pointer) +
601     // (1 + 2 * rank) * sizeof(index) = ceilPowerOf2(2 * 8 + 3 * 4) = 32.
602     // ALIGNED-ALLOC: llvm.mlir.constant(32 : index)
604     // Check that the types are converted as expected.
605     // ALIGNED-ALLOC: llvm.call @aligned_alloc
606     // ALIGNED-ALLOC: llvm.mlir.undef
607     // ALIGNED-ALLOC-SAME: !llvm.struct<(ptr, ptr, i32, array<1 x i32>, array<1 x i32>)>
608     %0 = memref.alloc() : memref<1xmemref<1xf32>>
609     return
610   }
614 // -----
616 // ALIGNED-ALLOC-LABEL: @memref_of_memref_of_memref
617 func.func @memref_of_memref_of_memref() {
618   // Sizeof computation is as usual, also check the type.
619   // ALIGNED-ALLOC: %[[NULL:.*]] = llvm.mlir.zero : !llvm.ptr
620   // ALIGNED-ALLOC: %[[PTR:.*]] = llvm.getelementptr
621   // ALIGNED-ALLOC: %[[SIZEOF:.*]] = llvm.ptrtoint
623   // Static alignment should be computed as ceilPowerOf2(2 * sizeof(pointer) +
624   // (1 + 2 * rank) * sizeof(index) = ceilPowerOf2(2 * 8 + 3 * 8) = 64.
625   // ALIGNED-ALLOC: llvm.mlir.constant(64 : index)
626   // ALIGNED-ALLOC: llvm.call @aligned_alloc
627   %0 = memref.alloc() : memref<1 x memref<2 x memref<3 x f32>>>
628   return
631 // -----
633 // ALIGNED-ALLOC-LABEL: @ranked_unranked
634 func.func @ranked_unranked() {
635   // ALIGNED-ALLOC: llvm.mlir.zero
636   // ALIGNED-ALLOC-SAME: !llvm.ptr
637   // ALIGNED-ALLOC: llvm.getelementptr
638   // ALIGNED-ALLOC: llvm.ptrtoint
640   // Static alignment should be computed as ceilPowerOf2(sizeof(index) +
641   // sizeof(pointer)) = 16.
642   // ALIGNED-ALLOC: llvm.mlir.constant(16 : index)
643   // ALIGNED-ALLOC: llvm.call @aligned_alloc
644   %0 = memref.alloc() : memref<1 x memref<* x f32>>
645   memref.cast %0 : memref<1 x memref<* x f32>> to memref<* x memref<* x f32>>
646   return