• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// RUN: mlir-opt -convert-std-to-llvm %s | FileCheck %s
2// RUN: mlir-opt -convert-std-to-llvm='use-aligned-alloc=1' %s | FileCheck %s --check-prefix=ALIGNED-ALLOC
3
4// CHECK-LABEL: func @check_strided_memref_arguments(
5// CHECK-COUNT-2: !llvm.ptr<float>
6// CHECK-COUNT-5: !llvm.i64
7// CHECK-COUNT-2: !llvm.ptr<float>
8// CHECK-COUNT-5: !llvm.i64
9// CHECK-COUNT-2: !llvm.ptr<float>
10// CHECK-COUNT-5: !llvm.i64
11func @check_strided_memref_arguments(%static: memref<10x20xf32, affine_map<(i,j)->(20 * i + j + 1)>>,
12                                     %dynamic : memref<?x?xf32, affine_map<(i,j)[M]->(M * i + j + 1)>>,
13                                     %mixed : memref<10x?xf32, affine_map<(i,j)[M]->(M * i + j + 1)>>) {
14  return
15}
16
17// CHECK-LABEL: func @check_arguments
18// CHECK-COUNT-2: !llvm.ptr<float>
19// CHECK-COUNT-5: !llvm.i64
20// CHECK-COUNT-2: !llvm.ptr<float>
21// CHECK-COUNT-5: !llvm.i64
22// CHECK-COUNT-2: !llvm.ptr<float>
23// CHECK-COUNT-5: !llvm.i64
24func @check_arguments(%static: memref<10x20xf32>, %dynamic : memref<?x?xf32>, %mixed : memref<10x?xf32>) {
25  return
26}
27
28// CHECK-LABEL: func @mixed_alloc(
29//       CHECK:   %[[M:.*]]: !llvm.i64, %[[N:.*]]: !llvm.i64) -> !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)> {
30func @mixed_alloc(%arg0: index, %arg1: index) -> memref<?x42x?xf32> {
31//       CHECK:  %[[c42:.*]] = llvm.mlir.constant(42 : index) : !llvm.i64
32//  CHECK-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
33//  CHECK-NEXT:  %[[st0:.*]] = llvm.mul %[[N]], %[[c42]] : !llvm.i64
34//  CHECK-NEXT:  %[[sz:.*]] = llvm.mul %[[st0]], %[[M]] : !llvm.i64
35//  CHECK-NEXT:  %[[null:.*]] = llvm.mlir.null : !llvm.ptr<float>
36//  CHECK-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[sz]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
37//  CHECK-NEXT:  %[[sz_bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr<float> to !llvm.i64
38//  CHECK-NEXT:  llvm.call @malloc(%[[sz_bytes]]) : (!llvm.i64) -> !llvm.ptr<i8>
39//  CHECK-NEXT:  llvm.bitcast %{{.*}} : !llvm.ptr<i8> to !llvm.ptr<float>
40//  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
41//  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
42//  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
43//  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
44//  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
45//  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
46//  CHECK-NEXT:  llvm.insertvalue %[[c42]], %{{.*}}[3, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
47//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
48//  CHECK-NEXT:  llvm.insertvalue %[[st0]], %{{.*}}[4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
49//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
50//  CHECK-NEXT:  llvm.insertvalue %[[one]], %{{.*}}[4, 2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
51  %0 = alloc(%arg0, %arg1) : memref<?x42x?xf32>
52//  CHECK-NEXT:  llvm.return %{{.*}} : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
53  return %0 : memref<?x42x?xf32>
54}
55
56// CHECK-LABEL: func @mixed_dealloc
57func @mixed_dealloc(%arg0: memref<?x42x?xf32>) {
58//      CHECK:  %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>
59// CHECK-NEXT:  %[[ptri8:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr<float> to !llvm.ptr<i8>
60// CHECK-NEXT:  llvm.call @free(%[[ptri8]]) : (!llvm.ptr<i8>) -> ()
61  dealloc %arg0 : memref<?x42x?xf32>
62// CHECK-NEXT:  llvm.return
63  return
64}
65
66// CHECK-LABEL: func @dynamic_alloc(
67//       CHECK:   %[[M:.*]]: !llvm.i64, %[[N:.*]]: !llvm.i64) -> !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)> {
68func @dynamic_alloc(%arg0: index, %arg1: index) -> memref<?x?xf32> {
69//  CHECK-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
70//  CHECK-NEXT:  %[[sz:.*]] = llvm.mul %[[N]], %[[M]] : !llvm.i64
71//  CHECK-NEXT:  %[[null:.*]] = llvm.mlir.null : !llvm.ptr<float>
72//  CHECK-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[sz]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
73//  CHECK-NEXT:  %[[sz_bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr<float> to !llvm.i64
74//  CHECK-NEXT:  llvm.call @malloc(%[[sz_bytes]]) : (!llvm.i64) -> !llvm.ptr<i8>
75//  CHECK-NEXT:  llvm.bitcast %{{.*}} : !llvm.ptr<i8> to !llvm.ptr<float>
76//  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
77//  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
78//  CHECK-NEXT:  llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
79//  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
80//  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
81//  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
82//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
83//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
84//  CHECK-NEXT:  llvm.insertvalue %[[one]], %{{.*}}[4, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
85  %0 = alloc(%arg0, %arg1) : memref<?x?xf32>
86//  CHECK-NEXT:  llvm.return %{{.*}} : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
87  return %0 : memref<?x?xf32>
88}
89
90// -----
91
92// CHECK-LABEL: func @dynamic_alloca
93// CHECK: %[[M:.*]]: !llvm.i64, %[[N:.*]]: !llvm.i64) -> !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)> {
94func @dynamic_alloca(%arg0: index, %arg1: index) -> memref<?x?xf32> {
95//  CHECK-NEXT:  %[[st1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
96//  CHECK-NEXT:  %[[num_elems:.*]] = llvm.mul %[[N]], %[[M]] : !llvm.i64
97//  CHECK-NEXT:  %[[null:.*]] = llvm.mlir.null : !llvm.ptr<float>
98//  CHECK-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[num_elems]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
99//  CHECK-NEXT:  %[[sz_bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr<float> to !llvm.i64
100//  CHECK-NEXT:  %[[allocated:.*]] = llvm.alloca %[[sz_bytes]] x !llvm.float : (!llvm.i64) -> !llvm.ptr<float>
101//  CHECK-NEXT:  llvm.mlir.undef : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
102//  CHECK-NEXT:  llvm.insertvalue %[[allocated]], %{{.*}}[0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
103//  CHECK-NEXT:  llvm.insertvalue %[[allocated]], %{{.*}}[1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
104//  CHECK-NEXT:  %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
105//  CHECK-NEXT:  llvm.insertvalue %[[off]], %{{.*}}[2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
106//  CHECK-NEXT:  llvm.insertvalue %[[M]], %{{.*}}[3, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
107//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[3, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
108//  CHECK-NEXT:  llvm.insertvalue %[[N]], %{{.*}}[4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
109//  CHECK-NEXT:  llvm.insertvalue %[[st1]], %{{.*}}[4, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
110  %0 = alloca(%arg0, %arg1) : memref<?x?xf32>
111
112// Test with explicitly specified alignment. llvm.alloca takes care of the
113// alignment. The same pointer is thus used for allocation and aligned
114// accesses.
115// CHECK: %[[alloca_aligned:.*]] = llvm.alloca %{{.*}} x !llvm.float {alignment = 32 : i64} : (!llvm.i64) -> !llvm.ptr<float>
116// CHECK: %[[desc:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
117// CHECK: %[[desc1:.*]] = llvm.insertvalue %[[alloca_aligned]], %[[desc]][0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
118// CHECK: llvm.insertvalue %[[alloca_aligned]], %[[desc1]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
119  alloca(%arg0, %arg1) {alignment = 32} : memref<?x?xf32>
120  return %0 : memref<?x?xf32>
121}
122
123// CHECK-LABEL: func @dynamic_dealloc
124func @dynamic_dealloc(%arg0: memref<?x?xf32>) {
125//      CHECK:  %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
126// CHECK-NEXT:  %[[ptri8:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr<float> to !llvm.ptr<i8>
127// CHECK-NEXT:  llvm.call @free(%[[ptri8]]) : (!llvm.ptr<i8>) -> ()
128  dealloc %arg0 : memref<?x?xf32>
129  return
130}
131
132// CHECK-LABEL: func @stdlib_aligned_alloc({{.*}}) -> !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)> {
133// ALIGNED-ALLOC-LABEL: func @stdlib_aligned_alloc({{.*}}) -> !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)> {
134func @stdlib_aligned_alloc(%N : index) -> memref<32x18xf32> {
135// ALIGNED-ALLOC-NEXT:  %[[sz1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64
136// ALIGNED-ALLOC-NEXT:  %[[sz2:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64
137// ALIGNED-ALLOC-NEXT:  %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
138// ALIGNED-ALLOC-NEXT:  %[[num_elems:.*]] = llvm.mlir.constant(576 : index) : !llvm.i64
139// ALIGNED-ALLOC-NEXT:  %[[null:.*]] = llvm.mlir.null : !llvm.ptr<float>
140// ALIGNED-ALLOC-NEXT:  %[[gep:.*]] = llvm.getelementptr %[[null]][%[[num_elems]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
141// ALIGNED-ALLOC-NEXT:  %[[bytes:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr<float> to !llvm.i64
142// ALIGNED-ALLOC-NEXT:  %[[alignment:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64
143// ALIGNED-ALLOC-NEXT:  %[[allocated:.*]] = llvm.call @aligned_alloc(%[[alignment]], %[[bytes]]) : (!llvm.i64, !llvm.i64) -> !llvm.ptr<i8>
144// ALIGNED-ALLOC-NEXT:  llvm.bitcast %[[allocated]] : !llvm.ptr<i8> to !llvm.ptr<float>
145  %0 = alloc() {alignment = 32} : memref<32x18xf32>
146  // Do another alloc just to test that we have a unique declaration for
147  // aligned_alloc.
148  // ALIGNED-ALLOC:  llvm.call @aligned_alloc
149  %1 = alloc() {alignment = 64} : memref<4096xf32>
150
151  // Alignment is to element type boundaries (minimum 16 bytes).
152  // ALIGNED-ALLOC:  %[[c32:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64
153  // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c32]]
154  %2 = alloc() : memref<4096xvector<8xf32>>
155  // The minimum alignment is 16 bytes unless explicitly specified.
156  // ALIGNED-ALLOC:  %[[c16:.*]] = llvm.mlir.constant(16 : index) : !llvm.i64
157  // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c16]],
158  %3 = alloc() : memref<4096xvector<2xf32>>
159  // ALIGNED-ALLOC:  %[[c8:.*]] = llvm.mlir.constant(8 : index) : !llvm.i64
160  // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c8]],
161  %4 = alloc() {alignment = 8} : memref<1024xvector<4xf32>>
162  // Bump the memref allocation size if its size is not a multiple of alignment.
163  // ALIGNED-ALLOC:       %[[c32:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64
164  // ALIGNED-ALLOC-NEXT:  llvm.mlir.constant(1 : index) : !llvm.i64
165  // ALIGNED-ALLOC-NEXT:  llvm.sub
166  // ALIGNED-ALLOC-NEXT:  llvm.add
167  // ALIGNED-ALLOC-NEXT:  llvm.urem
168  // ALIGNED-ALLOC-NEXT:  %[[SIZE_ALIGNED:.*]] = llvm.sub
169  // ALIGNED-ALLOC-NEXT:  llvm.call @aligned_alloc(%[[c32]], %[[SIZE_ALIGNED]])
170  %5 = alloc() {alignment = 32} : memref<100xf32>
171  // Bump alignment to the next power of two if it isn't.
172  // ALIGNED-ALLOC:  %[[c128:.*]] = llvm.mlir.constant(128 : index) : !llvm.i64
173  // ALIGNED-ALLOC:  llvm.call @aligned_alloc(%[[c128]]
174  %6 = alloc(%N) : memref<?xvector<18xf32>>
175  return %0 : memref<32x18xf32>
176}
177
178// CHECK-LABEL: func @mixed_load(
179// CHECK-COUNT-2: !llvm.ptr<float>,
180// CHECK-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i64
181// CHECK:         %[[I:.*]]: !llvm.i64,
182// CHECK:         %[[J:.*]]: !llvm.i64)
183func @mixed_load(%mixed : memref<42x?xf32>, %i : index, %j : index) {
184//       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
185//  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
186//  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64
187//  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : !llvm.i64
188//  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
189//  CHECK-NEXT:  llvm.load %[[addr]] : !llvm.ptr<float>
190  %0 = load %mixed[%i, %j] : memref<42x?xf32>
191  return
192}
193
194// CHECK-LABEL: func @dynamic_load(
195// CHECK-SAME:         %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr<float>
196// CHECK-SAME:         %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr<float>
197// CHECK-SAME:         %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64
198// CHECK-SAME:         %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64
199// CHECK-SAME:         %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64
200// CHECK-SAME:         %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64
201// CHECK-SAME:         %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64
202// CHECK-SAME:         %[[I:[a-zA-Z0-9]*]]: !llvm.i64
203// CHECK-SAME:         %[[J:[a-zA-Z0-9]*]]: !llvm.i64
204func @dynamic_load(%dynamic : memref<?x?xf32>, %i : index, %j : index) {
205//       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
206//  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
207//  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64
208//  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : !llvm.i64
209//  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
210//  CHECK-NEXT:  llvm.load %[[addr]] : !llvm.ptr<float>
211  %0 = load %dynamic[%i, %j] : memref<?x?xf32>
212  return
213}
214
215// CHECK-LABEL: func @prefetch
216// CHECK-SAME:         %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr<float>
217// CHECK-SAME:         %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr<float>
218// CHECK-SAME:         %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64
219// CHECK-SAME:         %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64
220// CHECK-SAME:         %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64
221// CHECK-SAME:         %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64
222// CHECK-SAME:         %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64
223// CHECK-SAME:         %[[I:[a-zA-Z0-9]*]]: !llvm.i64
224// CHECK-SAME:         %[[J:[a-zA-Z0-9]*]]: !llvm.i64
225func @prefetch(%A : memref<?x?xf32>, %i : index, %j : index) {
226//      CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
227// CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
228// CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64
229// CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : !llvm.i64
230// CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
231// CHECK-NEXT:  [[C1:%.*]] = llvm.mlir.constant(1 : i32) : !llvm.i32
232// CHECK-NEXT:  [[C3:%.*]] = llvm.mlir.constant(3 : i32) : !llvm.i32
233// CHECK-NEXT:  [[C1_1:%.*]] = llvm.mlir.constant(1 : i32) : !llvm.i32
234// CHECK-NEXT:  "llvm.intr.prefetch"(%[[addr]], [[C1]], [[C3]], [[C1_1]]) : (!llvm.ptr<float>, !llvm.i32, !llvm.i32, !llvm.i32) -> ()
235  prefetch %A[%i, %j], write, locality<3>, data : memref<?x?xf32>
236// CHECK:  [[C0:%.*]] = llvm.mlir.constant(0 : i32) : !llvm.i32
237// CHECK:  [[C0_1:%.*]] = llvm.mlir.constant(0 : i32) : !llvm.i32
238// CHECK:  [[C1_2:%.*]] = llvm.mlir.constant(1 : i32) : !llvm.i32
239// CHECK:  "llvm.intr.prefetch"(%{{.*}}, [[C0]], [[C0_1]], [[C1_2]]) : (!llvm.ptr<float>, !llvm.i32, !llvm.i32, !llvm.i32) -> ()
240  prefetch %A[%i, %j], read, locality<0>, data : memref<?x?xf32>
241// CHECK:  [[C0_2:%.*]] = llvm.mlir.constant(0 : i32) : !llvm.i32
242// CHECK:  [[C2:%.*]] = llvm.mlir.constant(2 : i32) : !llvm.i32
243// CHECK:  [[C0_3:%.*]] = llvm.mlir.constant(0 : i32) : !llvm.i32
244// CHECK:  "llvm.intr.prefetch"(%{{.*}}, [[C0_2]], [[C2]], [[C0_3]]) : (!llvm.ptr<float>, !llvm.i32, !llvm.i32, !llvm.i32) -> ()
245  prefetch %A[%i, %j], read, locality<2>, instr : memref<?x?xf32>
246  return
247}
248
249// CHECK-LABEL: func @dynamic_store
250// CHECK-SAME:         %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr<float>
251// CHECK-SAME:         %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr<float>
252// CHECK-SAME:         %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64
253// CHECK-SAME:         %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64
254// CHECK-SAME:         %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64
255// CHECK-SAME:         %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64
256// CHECK-SAME:         %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64
257// CHECK-SAME:         %[[I:[a-zA-Z0-9]*]]: !llvm.i64
258// CHECK-SAME:         %[[J:[a-zA-Z0-9]*]]: !llvm.i64
259func @dynamic_store(%dynamic : memref<?x?xf32>, %i : index, %j : index, %val : f32) {
260//       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
261//  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
262//  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64
263//  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : !llvm.i64
264//  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
265//  CHECK-NEXT:  llvm.store %{{.*}}, %[[addr]] : !llvm.ptr<float>
266  store %val, %dynamic[%i, %j] : memref<?x?xf32>
267  return
268}
269
270// CHECK-LABEL: func @mixed_store
271// CHECK-SAME:         %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr<float>
272// CHECK-SAME:         %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr<float>
273// CHECK-SAME:         %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64
274// CHECK-SAME:         %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64
275// CHECK-SAME:         %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64
276// CHECK-SAME:         %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64
277// CHECK-SAME:         %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64
278// CHECK-SAME:         %[[I:[a-zA-Z0-9]*]]: !llvm.i64
279// CHECK-SAME:         %[[J:[a-zA-Z0-9]*]]: !llvm.i64
280func @mixed_store(%mixed : memref<42x?xf32>, %i : index, %j : index, %val : f32) {
281//       CHECK:  %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
282//  CHECK-NEXT:  %[[st0:.*]] = llvm.extractvalue %[[ld]][4, 0] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>)>
283//  CHECK-NEXT:  %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64
284//  CHECK-NEXT:  %[[off1:.*]] = llvm.add %[[offI]], %[[J]] : !llvm.i64
285//  CHECK-NEXT:  %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr<float>, !llvm.i64) -> !llvm.ptr<float>
286//  CHECK-NEXT:  llvm.store %{{.*}}, %[[addr]] : !llvm.ptr<float>
287  store %val, %mixed[%i, %j] : memref<42x?xf32>
288  return
289}
290
291// CHECK-LABEL: func @memref_cast_static_to_dynamic
292func @memref_cast_static_to_dynamic(%static : memref<10x42xf32>) {
293// CHECK-NOT: llvm.bitcast
294  %0 = memref_cast %static : memref<10x42xf32> to memref<?x?xf32>
295  return
296}
297
298// CHECK-LABEL: func @memref_cast_static_to_mixed
299func @memref_cast_static_to_mixed(%static : memref<10x42xf32>) {
300// CHECK-NOT: llvm.bitcast
301  %0 = memref_cast %static : memref<10x42xf32> to memref<?x42xf32>
302  return
303}
304
305// CHECK-LABEL: func @memref_cast_dynamic_to_static
306func @memref_cast_dynamic_to_static(%dynamic : memref<?x?xf32>) {
307// CHECK-NOT: llvm.bitcast
308  %0 = memref_cast %dynamic : memref<?x?xf32> to memref<10x12xf32>
309  return
310}
311
312// CHECK-LABEL: func @memref_cast_dynamic_to_mixed
313func @memref_cast_dynamic_to_mixed(%dynamic : memref<?x?xf32>) {
314// CHECK-NOT: llvm.bitcast
315  %0 = memref_cast %dynamic : memref<?x?xf32> to memref<?x12xf32>
316  return
317}
318
319// CHECK-LABEL: func @memref_cast_mixed_to_dynamic
320func @memref_cast_mixed_to_dynamic(%mixed : memref<42x?xf32>) {
321// CHECK-NOT: llvm.bitcast
322  %0 = memref_cast %mixed : memref<42x?xf32> to memref<?x?xf32>
323  return
324}
325
326// CHECK-LABEL: func @memref_cast_mixed_to_static
327func @memref_cast_mixed_to_static(%mixed : memref<42x?xf32>) {
328// CHECK-NOT: llvm.bitcast
329  %0 = memref_cast %mixed : memref<42x?xf32> to memref<42x1xf32>
330  return
331}
332
333// CHECK-LABEL: func @memref_cast_mixed_to_mixed
334func @memref_cast_mixed_to_mixed(%mixed : memref<42x?xf32>) {
335// CHECK-NOT: llvm.bitcast
336  %0 = memref_cast %mixed : memref<42x?xf32> to memref<?x1xf32>
337  return
338}
339
340// CHECK-LABEL: func @memref_cast_ranked_to_unranked
341func @memref_cast_ranked_to_unranked(%arg : memref<42x2x?xf32>) {
342// CHECK-DAG:  %[[c:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
343// CHECK-DAG:  %[[p:.*]] = llvm.alloca %[[c]] x !llvm.struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)> : (!llvm.i64) -> !llvm.ptr<struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>>
344// CHECK-DAG:  llvm.store %{{.*}}, %[[p]] : !llvm.ptr<struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>>
345// CHECK-DAG:  %[[p2:.*]] = llvm.bitcast %[[p]] : !llvm.ptr<struct<(ptr<float>, ptr<float>, i64, array<3 x i64>, array<3 x i64>)>> to !llvm.ptr<i8>
346// CHECK-DAG:  %[[r:.*]] = llvm.mlir.constant(3 : i64) : !llvm.i64
347// CHECK    :  llvm.mlir.undef : !llvm.struct<(i64, ptr<i8>)>
348// CHECK-DAG:  llvm.insertvalue %[[r]], %{{.*}}[0] : !llvm.struct<(i64, ptr<i8>)>
349// CHECK-DAG:  llvm.insertvalue %[[p2]], %{{.*}}[1] : !llvm.struct<(i64, ptr<i8>)>
350  %0 = memref_cast %arg : memref<42x2x?xf32> to memref<*xf32>
351  return
352}
353
354// CHECK-LABEL: func @memref_cast_unranked_to_ranked
355func @memref_cast_unranked_to_ranked(%arg : memref<*xf32>) {
356//      CHECK: %[[p:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(i64, ptr<i8>)>
357// CHECK-NEXT: llvm.bitcast %[[p]] : !llvm.ptr<i8> to !llvm.ptr<struct<(ptr<float>, ptr<float>, i64, array<4 x i64>, array<4 x i64>)>>
358  %0 = memref_cast %arg : memref<*xf32> to memref<?x?x10x2xf32>
359  return
360}
361
362// CHECK-LABEL: func @mixed_memref_dim
363func @mixed_memref_dim(%mixed : memref<42x?x?x13x?xf32>) {
364// CHECK: llvm.mlir.constant(42 : index) : !llvm.i64
365  %c0 = constant 0 : index
366  %0 = dim %mixed, %c0 : memref<42x?x?x13x?xf32>
367// CHECK: llvm.extractvalue %[[ld:.*]][3, 1] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<5 x i64>, array<5 x i64>)>
368  %c1 = constant 1 : index
369  %1 = dim %mixed, %c1 : memref<42x?x?x13x?xf32>
370// CHECK: llvm.extractvalue %[[ld]][3, 2] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<5 x i64>, array<5 x i64>)>
371  %c2 = constant 2 : index
372  %2 = dim %mixed, %c2 : memref<42x?x?x13x?xf32>
373// CHECK: llvm.mlir.constant(13 : index) : !llvm.i64
374  %c3 = constant 3 : index
375  %3 = dim %mixed, %c3 : memref<42x?x?x13x?xf32>
376// CHECK: llvm.extractvalue %[[ld]][3, 4] : !llvm.struct<(ptr<float>, ptr<float>, i64, array<5 x i64>, array<5 x i64>)>
377  %c4 = constant 4 : index
378  %4 = dim %mixed, %c4 : memref<42x?x?x13x?xf32>
379  return
380}
381
382// CHECK-LABEL: @memref_dim_with_dyn_index
383// CHECK-SAME: %[[ALLOC_PTR:.*]]: !llvm.ptr<float>, %[[ALIGN_PTR:.*]]: !llvm.ptr<float>, %[[OFFSET:.*]]: !llvm.i64, %[[SIZE0:.*]]: !llvm.i64, %[[SIZE1:.*]]: !llvm.i64, %[[STRIDE0:.*]]: !llvm.i64, %[[STRIDE1:.*]]: !llvm.i64, %[[IDX:.*]]: !llvm.i64) -> !llvm.i64
384func @memref_dim_with_dyn_index(%arg : memref<3x?xf32>, %idx : index) -> index {
385  // CHECK-NEXT: %[[DESCR0:.*]] = llvm.mlir.undef : [[DESCR_TY:!llvm.struct<\(ptr<float>, ptr<float>, i64, array<2 x i64>, array<2 x i64>\)>]]
386  // CHECK-NEXT: %[[DESCR1:.*]] = llvm.insertvalue %[[ALLOC_PTR]], %[[DESCR0]][0] : [[DESCR_TY]]
387  // CHECK-NEXT: %[[DESCR2:.*]] = llvm.insertvalue %[[ALIGN_PTR]], %[[DESCR1]][1] : [[DESCR_TY]]
388  // CHECK-NEXT: %[[DESCR3:.*]] = llvm.insertvalue %[[OFFSET]],    %[[DESCR2]][2] : [[DESCR_TY]]
389  // CHECK-NEXT: %[[DESCR4:.*]] = llvm.insertvalue %[[SIZE0]],     %[[DESCR3]][3, 0] : [[DESCR_TY]]
390  // CHECK-NEXT: %[[DESCR5:.*]] = llvm.insertvalue %[[STRIDE0]],   %[[DESCR4]][4, 0] : [[DESCR_TY]]
391  // CHECK-NEXT: %[[DESCR6:.*]] = llvm.insertvalue %[[SIZE1]],     %[[DESCR5]][3, 1] : [[DESCR_TY]]
392  // CHECK-NEXT: %[[DESCR7:.*]] = llvm.insertvalue %[[STRIDE1]],   %[[DESCR6]][4, 1] : [[DESCR_TY]]
393  // CHECK-DAG: %[[C0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
394  // CHECK-DAG: %[[C1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
395  // CHECK-DAG: %[[SIZES:.*]] = llvm.extractvalue %[[DESCR7]][3] : [[DESCR_TY]]
396  // CHECK-DAG: %[[SIZES_PTR:.*]] = llvm.alloca %[[C1]] x !llvm.array<2 x i64> : (!llvm.i64) -> !llvm.ptr<array<2 x i64>>
397  // CHECK-DAG: llvm.store %[[SIZES]], %[[SIZES_PTR]] : !llvm.ptr<array<2 x i64>>
398  // CHECK-DAG: %[[RESULT_PTR:.*]] = llvm.getelementptr %[[SIZES_PTR]][%[[C0]], %[[IDX]]] : (!llvm.ptr<array<2 x i64>>, !llvm.i64, !llvm.i64) -> !llvm.ptr<i64>
399  // CHECK-DAG: %[[RESULT:.*]] = llvm.load %[[RESULT_PTR]] : !llvm.ptr<i64>
400  // CHECK-DAG: llvm.return %[[RESULT]] : !llvm.i64
401  %result = dim %arg, %idx : memref<3x?xf32>
402  return %result : index
403}
404
405// CHECK-LABEL: @memref_reinterpret_cast_ranked_to_static_shape
406func @memref_reinterpret_cast_ranked_to_static_shape(%input : memref<2x3xf32>) {
407  %output = memref_reinterpret_cast %input to
408           offset: [0], sizes: [6, 1], strides: [1, 1]
409           : memref<2x3xf32> to memref<6x1xf32>
410  return
411}
412// CHECK: [[INPUT:%.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : [[TY:!.*]]
413// CHECK: [[OUT_0:%.*]] = llvm.mlir.undef : [[TY]]
414// CHECK: [[BASE_PTR:%.*]] = llvm.extractvalue [[INPUT]][0] : [[TY]]
415// CHECK: [[ALIGNED_PTR:%.*]] = llvm.extractvalue [[INPUT]][1] : [[TY]]
416// CHECK: [[OUT_1:%.*]] = llvm.insertvalue [[BASE_PTR]], [[OUT_0]][0] : [[TY]]
417// CHECK: [[OUT_2:%.*]] = llvm.insertvalue [[ALIGNED_PTR]], [[OUT_1]][1] : [[TY]]
418// CHECK: [[OFFSET:%.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
419// CHECK: [[OUT_3:%.*]] = llvm.insertvalue [[OFFSET]], [[OUT_2]][2] : [[TY]]
420// CHECK: [[SIZE_0:%.*]] = llvm.mlir.constant(6 : index) : !llvm.i64
421// CHECK: [[OUT_4:%.*]] = llvm.insertvalue [[SIZE_0]], [[OUT_3]][3, 0] : [[TY]]
422// CHECK: [[SIZE_1:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
423// CHECK: [[OUT_5:%.*]] = llvm.insertvalue [[SIZE_1]], [[OUT_4]][4, 0] : [[TY]]
424// CHECK: [[STRIDE_0:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
425// CHECK: [[OUT_6:%.*]] = llvm.insertvalue [[STRIDE_0]], [[OUT_5]][3, 1] : [[TY]]
426// CHECK: [[STRIDE_1:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
427// CHECK: [[OUT_7:%.*]] = llvm.insertvalue [[STRIDE_1]], [[OUT_6]][4, 1] : [[TY]]
428
429// CHECK-LABEL: @memref_reinterpret_cast_unranked_to_dynamic_shape
430func @memref_reinterpret_cast_unranked_to_dynamic_shape(%offset: index,
431                                                        %size_0 : index,
432                                                        %size_1 : index,
433                                                        %stride_0 : index,
434                                                        %stride_1 : index,
435                                                        %input : memref<*xf32>) {
436  %output = memref_reinterpret_cast %input to
437           offset: [%offset], sizes: [%size_0, %size_1],
438           strides: [%stride_0, %stride_1]
439           : memref<*xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
440  return
441}
442// CHECK-SAME: ([[OFFSET:%[a-z,0-9]+]]: !llvm.i64,
443// CHECK-SAME: [[SIZE_0:%[a-z,0-9]+]]: !llvm.i64, [[SIZE_1:%[a-z,0-9]+]]: !llvm.i64,
444// CHECK-SAME: [[STRIDE_0:%[a-z,0-9]+]]: !llvm.i64, [[STRIDE_1:%[a-z,0-9]+]]: !llvm.i64,
445// CHECK: [[INPUT:%.*]] = llvm.insertvalue {{.*}}[1] : !llvm.struct<(i64, ptr<i8>)>
446// CHECK: [[OUT_0:%.*]] = llvm.mlir.undef : [[TY:!.*]]
447// CHECK: [[DESCRIPTOR:%.*]] = llvm.extractvalue [[INPUT]][1] : !llvm.struct<(i64, ptr<i8>)>
448// CHECK: [[BASE_PTR_PTR:%.*]] = llvm.bitcast [[DESCRIPTOR]] : !llvm.ptr<i8> to !llvm.ptr<ptr<float>>
449// CHECK: [[BASE_PTR:%.*]] = llvm.load [[BASE_PTR_PTR]] : !llvm.ptr<ptr<float>>
450// CHECK: [[BASE_PTR_PTR_:%.*]] = llvm.bitcast [[DESCRIPTOR]] : !llvm.ptr<i8> to !llvm.ptr<ptr<float>>
451// CHECK: [[C1:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
452// CHECK: [[ALIGNED_PTR_PTR:%.*]] = llvm.getelementptr [[BASE_PTR_PTR_]]{{\[}}[[C1]]]
453// CHECK-SAME: : (!llvm.ptr<ptr<float>>, !llvm.i64) -> !llvm.ptr<ptr<float>>
454// CHECK: [[ALIGNED_PTR:%.*]] = llvm.load [[ALIGNED_PTR_PTR]] : !llvm.ptr<ptr<float>>
455// CHECK: [[OUT_1:%.*]] = llvm.insertvalue [[BASE_PTR]], [[OUT_0]][0] : [[TY]]
456// CHECK: [[OUT_2:%.*]] = llvm.insertvalue [[ALIGNED_PTR]], [[OUT_1]][1] : [[TY]]
457// CHECK: [[OUT_3:%.*]] = llvm.insertvalue [[OFFSET]], [[OUT_2]][2] : [[TY]]
458// CHECK: [[OUT_4:%.*]] = llvm.insertvalue [[SIZE_0]], [[OUT_3]][3, 0] : [[TY]]
459// CHECK: [[OUT_5:%.*]] = llvm.insertvalue [[STRIDE_0]], [[OUT_4]][4, 0] : [[TY]]
460// CHECK: [[OUT_6:%.*]] = llvm.insertvalue [[SIZE_1]], [[OUT_5]][3, 1] : [[TY]]
461// CHECK: [[OUT_7:%.*]] = llvm.insertvalue [[STRIDE_1]], [[OUT_6]][4, 1] : [[TY]]
462
463// CHECK-LABEL: @memref_reshape
464func @memref_reshape(%input : memref<2x3xf32>, %shape : memref<?xindex>) {
465  %output = memref_reshape %input(%shape)
466                : (memref<2x3xf32>, memref<?xindex>) -> memref<*xf32>
467  return
468}
469// CHECK: [[INPUT:%.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : [[INPUT_TY:!.*]]
470// CHECK: [[SHAPE:%.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : [[SHAPE_TY:!.*]]
471// CHECK: [[RANK:%.*]] = llvm.extractvalue [[SHAPE]][3, 0] : [[SHAPE_TY]]
472// CHECK: [[UNRANKED_OUT_O:%.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr<i8>)>
473// CHECK: [[UNRANKED_OUT_1:%.*]] = llvm.insertvalue [[RANK]], [[UNRANKED_OUT_O]][0] : !llvm.struct<(i64, ptr<i8>)>
474
475// Compute size in bytes to allocate result ranked descriptor
476// CHECK: [[C1:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
477// CHECK: [[C2:%.*]] = llvm.mlir.constant(2 : index) : !llvm.i64
478// CHECK: [[PTR_SIZE:%.*]] = llvm.mlir.constant(8 : index) : !llvm.i64
479// CHECK: [[INDEX_SIZE:%.*]] = llvm.mlir.constant(8 : index) : !llvm.i64
480// CHECK: [[DOUBLE_PTR_SIZE:%.*]] = llvm.mul [[C2]], [[PTR_SIZE]] : !llvm.i64
481// CHECK: [[DESC_ALLOC_SIZE:%.*]] = llvm.add [[DOUBLE_PTR_SIZE]], %{{.*}}
482// CHECK: [[UNDERLYING_DESC:%.*]] = llvm.alloca [[DESC_ALLOC_SIZE]] x !llvm.i8
483// CHECK: llvm.insertvalue [[UNDERLYING_DESC]], [[UNRANKED_OUT_1]][1]
484
485// Set allocated, aligned pointers and offset.
486// CHECK: [[ALLOC_PTR:%.*]] = llvm.extractvalue [[INPUT]][0] : [[INPUT_TY]]
487// CHECK: [[ALIGN_PTR:%.*]] = llvm.extractvalue [[INPUT]][1] : [[INPUT_TY]]
488// CHECK: [[OFFSET:%.*]] = llvm.extractvalue [[INPUT]][2] : [[INPUT_TY]]
489// CHECK: [[BASE_PTR_PTR:%.*]] = llvm.bitcast [[UNDERLYING_DESC]]
490// CHECK-SAME:                     !llvm.ptr<i8> to !llvm.ptr<ptr<float>>
491// CHECK: llvm.store [[ALLOC_PTR]], [[BASE_PTR_PTR]] : !llvm.ptr<ptr<float>>
492// CHECK: [[BASE_PTR_PTR_:%.*]] = llvm.bitcast [[UNDERLYING_DESC]] : !llvm.ptr<i8> to !llvm.ptr<ptr<float>>
493// CHECK: [[C1:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
494// CHECK: [[ALIGNED_PTR_PTR:%.*]] = llvm.getelementptr [[BASE_PTR_PTR_]]{{\[}}[[C1]]]
495// CHECK: llvm.store [[ALIGN_PTR]], [[ALIGNED_PTR_PTR]] : !llvm.ptr<ptr<float>>
496// CHECK: [[BASE_PTR_PTR__:%.*]] = llvm.bitcast [[UNDERLYING_DESC]] : !llvm.ptr<i8> to !llvm.ptr<ptr<float>>
497// CHECK: [[C2:%.*]] = llvm.mlir.constant(2 : index) : !llvm.i64
498// CHECK: [[OFFSET_PTR_:%.*]] = llvm.getelementptr [[BASE_PTR_PTR__]]{{\[}}[[C2]]]
499// CHECK: [[OFFSET_PTR:%.*]] = llvm.bitcast [[OFFSET_PTR_]]
500// CHECK: llvm.store [[OFFSET]], [[OFFSET_PTR]] : !llvm.ptr<i64>
501
502// Iterate over shape operand in reverse order and set sizes and strides.
503// CHECK: [[STRUCT_PTR:%.*]] = llvm.bitcast [[UNDERLYING_DESC]]
504// CHECK-SAME: !llvm.ptr<i8> to !llvm.ptr<struct<(ptr<float>, ptr<float>, i64, i64)>>
505// CHECK: [[C0:%.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
506// CHECK: [[C3_I32:%.*]] = llvm.mlir.constant(3 : i32) : !llvm.i32
507// CHECK: [[SIZES_PTR:%.*]] = llvm.getelementptr [[STRUCT_PTR]]{{\[}}[[C0]], [[C3_I32]]]
508// CHECK: [[STRIDES_PTR:%.*]] = llvm.getelementptr [[SIZES_PTR]]{{\[}}[[RANK]]]
509// CHECK: [[SHAPE_IN_PTR:%.*]] = llvm.extractvalue [[SHAPE]][1] : [[SHAPE_TY]]
510// CHECK: [[C1_:%.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
511// CHECK: [[RANK_MIN_1:%.*]] = llvm.sub [[RANK]], [[C1_]] : !llvm.i64
512// CHECK: llvm.br ^bb1([[RANK_MIN_1]], [[C1_]] : !llvm.i64, !llvm.i64)
513
514// CHECK: ^bb1([[DIM:%.*]]: !llvm.i64, [[CUR_STRIDE:%.*]]: !llvm.i64):
515// CHECK:   [[C0_:%.*]] = llvm.mlir.constant(0 : index) : !llvm.i64
516// CHECK:   [[COND:%.*]] = llvm.icmp "sge" [[DIM]], [[C0_]] : !llvm.i64
517// CHECK:   llvm.cond_br [[COND]], ^bb2, ^bb3
518
519// CHECK: ^bb2:
520// CHECK:   [[SIZE_PTR:%.*]] = llvm.getelementptr [[SHAPE_IN_PTR]]{{\[}}[[DIM]]]
521// CHECK:   [[SIZE:%.*]] = llvm.load [[SIZE_PTR]] : !llvm.ptr<i64>
522// CHECK:   [[TARGET_SIZE_PTR:%.*]] = llvm.getelementptr [[SIZES_PTR]]{{\[}}[[DIM]]]
523// CHECK:   llvm.store [[SIZE]], [[TARGET_SIZE_PTR]] : !llvm.ptr<i64>
524// CHECK:   [[TARGET_STRIDE_PTR:%.*]] = llvm.getelementptr [[STRIDES_PTR]]{{\[}}[[DIM]]]
525// CHECK:   llvm.store [[CUR_STRIDE]], [[TARGET_STRIDE_PTR]] : !llvm.ptr<i64>
526// CHECK:   [[UPDATE_STRIDE:%.*]] = llvm.mul [[CUR_STRIDE]], [[SIZE]] : !llvm.i64
527// CHECK:   [[STRIDE_COND:%.*]] = llvm.sub [[DIM]], [[C1_]] : !llvm.i64
528// CHECK:   llvm.br ^bb1([[STRIDE_COND]], [[UPDATE_STRIDE]] : !llvm.i64, !llvm.i64)
529
530// CHECK: ^bb3:
531// CHECK:   llvm.return
532