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 4 5// CHECK-LABEL: func @mixed_alloc( 6// CHECK: %[[Marg:.*]]: index, %[[Narg:.*]]: index) 7func.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> 31} 32 33// ----- 34 35// CHECK-LABEL: func @mixed_dealloc 36func.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 41} 42 43// ----- 44 45// CHECK-LABEL: func @unranked_dealloc 46func.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 52} 53 54// ----- 55 56// CHECK-LABEL: func @dynamic_alloc( 57// CHECK: %[[Marg:.*]]: index, %[[Narg:.*]]: index) 58func.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> 78} 79 80// ----- 81 82// CHECK-LABEL: func @dynamic_alloca 83// CHECK: %[[Marg:.*]]: index, %[[Narg:.*]]: index) 84func.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> 100 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> 110} 111 112// ----- 113 114// CHECK-LABEL: func @dynamic_dealloc 115func.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 120} 121 122// ----- 123 124// CHECK-LABEL: func @stdlib_aligned_alloc({{.*}}) 125// ALIGNED-ALLOC-LABEL: func @stdlib_aligned_alloc({{.*}}) 126func.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> 141 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> 167} 168 169// ----- 170 171// CHECK-LABEL: func @mixed_load( 172// CHECK: %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index) 173func.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 184} 185 186// ----- 187 188// CHECK-LABEL: func @dynamic_load( 189// CHECK: %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index) 190func.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 201} 202 203// ----- 204 205// CHECK-LABEL: func @prefetch 206// CHECK: %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index) 207func.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 222} 223 224// ----- 225 226// CHECK-LABEL: func @dynamic_store 227// CHECK: %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index 228func.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 239} 240 241// ----- 242 243// CHECK-LABEL: func @mixed_store 244// CHECK: %{{.*}}, %[[Iarg:.*]]: index, %[[Jarg:.*]]: index 245func.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 256} 257 258// ----- 259 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. 263module 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 } 271} 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)> 277 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] 290 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 300 301// Memcpy remaining values 302 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}> 308 309// ----- 310 311// CHECK-LABEL: func @memref_cast_static_to_dynamic 312func.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 316} 317 318// ----- 319 320// CHECK-LABEL: func @memref_cast_static_to_mixed 321func.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 325} 326 327// ----- 328 329// CHECK-LABEL: func @memref_cast_dynamic_to_static 330func.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 334} 335 336// ----- 337 338// CHECK-LABEL: func @memref_cast_dynamic_to_mixed 339func.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 343} 344 345// ----- 346 347// CHECK-LABEL: func @memref_cast_mixed_to_dynamic 348func.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 352} 353 354// ----- 355 356// CHECK-LABEL: func @memref_cast_mixed_to_static 357func.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 361} 362 363// ----- 364 365// CHECK-LABEL: func @memref_cast_mixed_to_mixed 366func.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 370} 371 372// ----- 373 374// CHECK-LABEL: func @memref_cast_ranked_to_unranked 375// CHECK32-LABEL: func @memref_cast_ranked_to_unranked 376func.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 393} 394 395// ----- 396 397// CHECK-LABEL: func @memref_cast_unranked_to_ranked 398func.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 402} 403 404// ----- 405 406// CHECK-LABEL: func @mixed_memref_dim 407func.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 424} 425 426// ----- 427 428// CHECK-LABEL: @memref_dim_with_dyn_index 429// CHECK: %{{.*}}, %[[IDXarg:.*]]: index 430func.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 440} 441 442// ----- 443 444// CHECK-LABEL: @memref_reinterpret_cast_ranked_to_static_shape 445func.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 450} 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]] 468 469// ----- 470 471// CHECK-LABEL: @memref_reinterpret_cast_unranked_to_dynamic_shape 472func.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 483} 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]] 506 507// ----- 508 509// CHECK-LABEL: @memref_reshape( 510// CHECK-SAME: %[[ARG0:.*]]: memref<2x3xf32>, %[[ARG1:.*]]: memref<?xindex>) 511func.func @memref_reshape(%input : memref<2x3xf32>, %shape : memref<?xindex>) { 512 %output = memref.reshape %input(%shape) 513 : (memref<2x3xf32>, memref<?xindex>) -> memref<*xf32> 514 return 515} 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)> 521 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] 531 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 541 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) 549 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 554 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) 565 566// CHECK: ^bb3: 567// CHECK: return 568 569// ----- 570 571// ALIGNED-ALLOC-LABEL: @memref_of_memref 572func.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 577 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) 581 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 588} 589 590// ----- 591 592module 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 599 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) 603 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 } 611} 612 613 614// ----- 615 616// ALIGNED-ALLOC-LABEL: @memref_of_memref_of_memref 617func.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 622 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 629} 630 631// ----- 632 633// ALIGNED-ALLOC-LABEL: @ranked_unranked 634func.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 639 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 647} 648