1// RUN: mlir-opt %s --sparse-tensor-conversion --canonicalize --cse | FileCheck %s 2 3#DenseVector = #sparse_tensor.encoding<{ 4 dimLevelType = ["dense"] 5}> 6 7#SparseVector = #sparse_tensor.encoding<{ 8 dimLevelType = ["compressed"] 9}> 10 11#SparseVector64 = #sparse_tensor.encoding<{ 12 dimLevelType = ["compressed"], 13 pointerBitWidth = 64, 14 indexBitWidth = 64 15}> 16 17#SparseVector32 = #sparse_tensor.encoding<{ 18 dimLevelType = ["compressed"], 19 pointerBitWidth = 32, 20 indexBitWidth = 32 21}> 22 23#SparseMatrix = #sparse_tensor.encoding<{ 24 dimLevelType = ["dense", "compressed"] 25}> 26 27#SparseTensor = #sparse_tensor.encoding<{ 28 dimLevelType = ["dense", "compressed", "compressed"], 29 dimOrdering = affine_map<(i,j,k) -> (k,i,j)> 30}> 31 32// CHECK-LABEL: func @sparse_dim1d( 33// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 34// CHECK: %[[C:.*]] = arith.constant 0 : index 35// CHECK: %[[D:.*]] = call @sparseDimSize(%[[A]], %[[C]]) 36// CHECK: return %[[D]] : index 37func @sparse_dim1d(%arg0: tensor<?xf64, #SparseVector>) -> index { 38 %c = arith.constant 0 : index 39 %0 = tensor.dim %arg0, %c : tensor<?xf64, #SparseVector> 40 return %0 : index 41} 42 43// CHECK-LABEL: func @sparse_dim3d( 44// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 45// CHECK: %[[C:.*]] = arith.constant 2 : index 46// CHECK: %[[D:.*]] = call @sparseDimSize(%[[A]], %[[C]]) 47// CHECK: return %[[D]] : index 48func @sparse_dim3d(%arg0: tensor<?x?x?xf64, #SparseTensor>) -> index { 49 // Querying for dimension 1 in the tensor type needs to be 50 // permuted into querying for dimension 2 in the stored sparse 51 // tensor scheme, since the latter honors the dimOrdering. 52 %c = arith.constant 1 : index 53 %0 = tensor.dim %arg0, %c : tensor<?x?x?xf64, #SparseTensor> 54 return %0 : index 55} 56 57// CHECK-LABEL: func @sparse_dim3d_const( 58// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 59// CHECK: %[[C:.*]] = arith.constant 20 : index 60// CHECK: return %[[C]] : index 61func @sparse_dim3d_const(%arg0: tensor<10x20x30xf64, #SparseTensor>) -> index { 62 // Querying for dimension 1 in the tensor type can be directly 63 // folded into the right value (even though it corresponds 64 // to dimension 2 in the stored sparse tensor scheme). 65 %c = arith.constant 1 : index 66 %0 = tensor.dim %arg0, %c : tensor<10x20x30xf64, #SparseTensor> 67 return %0 : index 68} 69 70// CHECK-LABEL: func @sparse_new1d( 71// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 72// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<1xi8> 73// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<1xindex> 74// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<1xindex> 75// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<1xi8> to memref<?xi8> 76// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<1xindex> to memref<?xindex> 77// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<1xindex> to memref<?xindex> 78// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 79// CHECK: return %[[T]] : !llvm.ptr<i8> 80func @sparse_new1d(%arg0: !llvm.ptr<i8>) -> tensor<128xf64, #SparseVector> { 81 %0 = sparse_tensor.new %arg0 : !llvm.ptr<i8> to tensor<128xf64, #SparseVector> 82 return %0 : tensor<128xf64, #SparseVector> 83} 84 85// CHECK-LABEL: func @sparse_new2d( 86// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 87// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 88// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 89// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 90// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 91// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 92// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 93// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 94// CHECK: return %[[T]] : !llvm.ptr<i8> 95func @sparse_new2d(%arg0: !llvm.ptr<i8>) -> tensor<?x?xf32, #SparseMatrix> { 96 %0 = sparse_tensor.new %arg0 : !llvm.ptr<i8> to tensor<?x?xf32, #SparseMatrix> 97 return %0 : tensor<?x?xf32, #SparseMatrix> 98} 99 100// CHECK-LABEL: func @sparse_new3d( 101// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 102// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<3xi8> 103// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<3xindex> 104// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<3xindex> 105// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<3xi8> to memref<?xi8> 106// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<3xindex> to memref<?xindex> 107// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<3xindex> to memref<?xindex> 108// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 109// CHECK: return %[[T]] : !llvm.ptr<i8> 110func @sparse_new3d(%arg0: !llvm.ptr<i8>) -> tensor<?x?x?xf32, #SparseTensor> { 111 %0 = sparse_tensor.new %arg0 : !llvm.ptr<i8> to tensor<?x?x?xf32, #SparseTensor> 112 return %0 : tensor<?x?x?xf32, #SparseTensor> 113} 114 115// CHECK-LABEL: func @sparse_init( 116// CHECK-SAME: %[[I:.*]]: index, 117// CHECK-SAME: %[[J:.*]]: index) -> !llvm.ptr<i8> 118// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 119// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 120// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 121// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 122// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 123// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 124// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 125// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 126// CHECK-DAG: memref.store %[[I]], %[[Q]][%[[C0]]] : memref<2xindex> 127// CHECK-DAG: memref.store %[[J]], %[[Q]][%[[C1]]] : memref<2xindex> 128// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 129// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 130// CHECK: return %[[T]] : !llvm.ptr<i8> 131func @sparse_init(%arg0: index, %arg1: index) -> tensor<?x?xf64, #SparseMatrix> { 132 %0 = sparse_tensor.init [%arg0, %arg1] : tensor<?x?xf64, #SparseMatrix> 133 return %0 : tensor<?x?xf64, #SparseMatrix> 134} 135 136// CHECK-LABEL: func @sparse_release( 137// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 138// CHECK: call @delSparseTensor(%[[A]]) : (!llvm.ptr<i8>) -> () 139// CHECK: return 140func @sparse_release(%arg0: tensor<128xf64, #SparseVector>) { 141 sparse_tensor.release %arg0 : tensor<128xf64, #SparseVector> 142 return 143} 144 145// CHECK-LABEL: func @sparse_nop_convert( 146// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 147// CHECK: return %[[A]] : !llvm.ptr<i8> 148func @sparse_nop_convert(%arg0: tensor<64xf32, #SparseVector>) -> tensor<64xf32, #SparseVector> { 149 %0 = sparse_tensor.convert %arg0 : tensor<64xf32, #SparseVector> to tensor<64xf32, #SparseVector> 150 return %0 : tensor<64xf32, #SparseVector> 151} 152 153// CHECK-LABEL: func @sparse_convert_1d( 154// CHECK-SAME: %[[A:.*]]: tensor<?xi32>) -> !llvm.ptr<i8> 155// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 156// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 157// CHECK-DAG: %[[U:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?xi32> 158// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<1xi8> 159// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<1xindex> 160// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<1xindex> 161// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<1xi8> to memref<?xi8> 162// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<1xindex> to memref<?xindex> 163// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<1xindex> to memref<?xindex> 164// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 165// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 166// CHECK: %[[M:.*]] = memref.alloca() : memref<1xindex> 167// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<1xindex> to memref<?xindex> 168// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U]] step %[[C1]] { 169// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]]] : tensor<?xi32> 170// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<1xindex> 171// CHECK: call @addEltI32(%[[C]], %[[E]], %[[T]], %[[Z]]) 172// CHECK: } 173// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 174// CHECK: return %[[T]] : !llvm.ptr<i8> 175func @sparse_convert_1d(%arg0: tensor<?xi32>) -> tensor<?xi32, #SparseVector> { 176 %0 = sparse_tensor.convert %arg0 : tensor<?xi32> to tensor<?xi32, #SparseVector> 177 return %0 : tensor<?xi32, #SparseVector> 178} 179 180// CHECK-LABEL: func @sparse_convert_1d_ss( 181// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 182// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<1xi8> 183// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<1xindex> 184// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<1xindex> 185// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<1xi8> to memref<?xi8> 186// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<1xindex> to memref<?xindex> 187// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<1xindex> to memref<?xindex> 188// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 189// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 190// CHECK: return %[[T]] : !llvm.ptr<i8> 191func @sparse_convert_1d_ss(%arg0: tensor<?xf32, #SparseVector64>) -> tensor<?xf32, #SparseVector32> { 192 %0 = sparse_tensor.convert %arg0 : tensor<?xf32, #SparseVector64> to tensor<?xf32, #SparseVector32> 193 return %0 : tensor<?xf32, #SparseVector32> 194} 195 196// CHECK-LABEL: func @sparse_convert_2d( 197// CHECK-SAME: %[[A:.*]]: tensor<2x4xf64>) -> !llvm.ptr<i8> 198// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 199// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 200// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 201// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 202// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 203// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 204// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 205// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 206// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 207// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 208// CHECK: %[[M:.*]] = memref.alloca() : memref<2xindex> 209// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<2xindex> to memref<?xindex> 210// CHECK: scf.for %[[I:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 211// CHECK: scf.for %[[J:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 212// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]]] : tensor<2x4xf64> 213// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<2xindex> 214// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<2xindex> 215// CHECK: call @addEltF64(%[[C]], %[[E]], %[[T]], %[[Z]]) 216// CHECK: } 217// CHECK: } 218// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 219// CHECK: return %[[T]] : !llvm.ptr<i8> 220func @sparse_convert_2d(%arg0: tensor<2x4xf64>) -> tensor<2x4xf64, #SparseMatrix> { 221 %0 = sparse_tensor.convert %arg0 : tensor<2x4xf64> to tensor<2x4xf64, #SparseMatrix> 222 return %0 : tensor<2x4xf64, #SparseMatrix> 223} 224 225// CHECK-LABEL: func @sparse_constant() -> !llvm.ptr<i8> { 226// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 227// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 228// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 229// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 230// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 231// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 232// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 233// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 234// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 235// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 236// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 237// CHECK: %[[M:.*]] = memref.alloca() : memref<2xindex> 238// CHECK: %[[N:.*]] = memref.cast %[[M]] : memref<2xindex> to memref<?xindex> 239// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C2]] step %[[C1]] { 240// CHECK: memref.store %{{.*}}, %[[M]][%[[C0]]] : memref<2xindex> 241// CHECK: memref.store %{{.*}}, %[[M]][%[[C1]]] : memref<2xindex> 242// CHECK: %[[V:.*]] = tensor.extract %{{.*}}[%[[I]]] : tensor<2xf32> 243// CHECK: call @addEltF32(%{{.*}}, %[[V]], %[[N]], %{{.*}}) 244// CHECK: } 245// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 246// CHECK: return %[[T]] : !llvm.ptr<i8> 247func @sparse_constant() -> tensor<8x7xf32, #SparseMatrix>{ 248 // Initialize a tensor. 249 %0 = arith.constant sparse<[[0, 0], [1, 6]], [1.0, 5.0]> : tensor<8x7xf32> 250 // Convert the tensor to a sparse tensor. 251 %1 = sparse_tensor.convert %0 : tensor<8x7xf32> to tensor<8x7xf32, #SparseMatrix> 252 return %1 : tensor<8x7xf32, #SparseMatrix> 253} 254 255// CHECK-LABEL: func @sparse_convert_3d( 256// CHECK-SAME: %[[A:.*]]: tensor<?x?x?xf64>) -> !llvm.ptr<i8> 257// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 258// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 259// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 260// CHECK-DAG: %[[U1:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?x?x?xf64> 261// CHECK-DAG: %[[U2:.*]] = tensor.dim %[[A]], %[[C1]] : tensor<?x?x?xf64> 262// CHECK-DAG: %[[U3:.*]] = tensor.dim %[[A]], %[[C2]] : tensor<?x?x?xf64> 263// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<3xi8> 264// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<3xindex> 265// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<3xindex> 266// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<3xi8> to memref<?xi8> 267// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<3xindex> to memref<?xindex> 268// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<3xindex> to memref<?xindex> 269// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 270// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 271// CHECK: %[[M:.*]] = memref.alloca() : memref<3xindex> 272// CHECK: %[[N:.*]] = memref.cast %[[M]] : memref<3xindex> to memref<?xindex> 273// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U1]] step %[[C1]] { 274// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[U2]] step %[[C1]] { 275// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[U3]] step %[[C1]] { 276// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]], %[[K]]] : tensor<?x?x?xf64> 277// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<3xindex> 278// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<3xindex> 279// CHECK: memref.store %[[K]], %[[M]][%[[C2]]] : memref<3xindex> 280// CHECK: call @addEltF64(%[[C]], %[[E]], %[[N]], %[[Z]]) 281// CHECK: } 282// CHECK: } 283// CHECK: } 284// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 285// CHECK: return %[[T]] : !llvm.ptr<i8> 286func @sparse_convert_3d(%arg0: tensor<?x?x?xf64>) -> tensor<?x?x?xf64, #SparseTensor> { 287 %0 = sparse_tensor.convert %arg0 : tensor<?x?x?xf64> to tensor<?x?x?xf64, #SparseTensor> 288 return %0 : tensor<?x?x?xf64, #SparseTensor> 289} 290 291// CHECK-LABEL: func @sparse_pointers( 292// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 293// CHECK: %[[C:.*]] = arith.constant 0 : index 294// CHECK: %[[T:.*]] = call @sparsePointers(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 295// CHECK: return %[[T]] : memref<?xindex> 296func @sparse_pointers(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 297 %c = arith.constant 0 : index 298 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 299 return %0 : memref<?xindex> 300} 301 302// CHECK-LABEL: func @sparse_pointers64( 303// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 304// CHECK: %[[C:.*]] = arith.constant 0 : index 305// CHECK: %[[T:.*]] = call @sparsePointers64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 306// CHECK: return %[[T]] : memref<?xi64> 307func @sparse_pointers64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 308 %c = arith.constant 0 : index 309 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 310 return %0 : memref<?xi64> 311} 312 313// CHECK-LABEL: func @sparse_pointers32( 314// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 315// CHECK: %[[C:.*]] = arith.constant 0 : index 316// CHECK: %[[T:.*]] = call @sparsePointers32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 317// CHECK: return %[[T]] : memref<?xi32> 318func @sparse_pointers32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 319 %c = arith.constant 0 : index 320 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 321 return %0 : memref<?xi32> 322} 323 324// CHECK-LABEL: func @sparse_indices( 325// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 326// CHECK: %[[C:.*]] = arith.constant 0 : index 327// CHECK: %[[T:.*]] = call @sparseIndices(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 328// CHECK: return %[[T]] : memref<?xindex> 329func @sparse_indices(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 330 %c = arith.constant 0 : index 331 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 332 return %0 : memref<?xindex> 333} 334 335// CHECK-LABEL: func @sparse_indices64( 336// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 337// CHECK: %[[C:.*]] = arith.constant 0 : index 338// CHECK: %[[T:.*]] = call @sparseIndices64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 339// CHECK: return %[[T]] : memref<?xi64> 340func @sparse_indices64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 341 %c = arith.constant 0 : index 342 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 343 return %0 : memref<?xi64> 344} 345 346// CHECK-LABEL: func @sparse_indices32( 347// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 348// CHECK: %[[C:.*]] = arith.constant 0 : index 349// CHECK: %[[T:.*]] = call @sparseIndices32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 350// CHECK: return %[[T]] : memref<?xi32> 351func @sparse_indices32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 352 %c = arith.constant 0 : index 353 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 354 return %0 : memref<?xi32> 355} 356 357// CHECK-LABEL: func @sparse_valuesf64( 358// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 359// CHECK: %[[T:.*]] = call @sparseValuesF64(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf64> 360// CHECK: return %[[T]] : memref<?xf64> 361func @sparse_valuesf64(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xf64> { 362 %0 = sparse_tensor.values %arg0 : tensor<128xf64, #SparseVector> to memref<?xf64> 363 return %0 : memref<?xf64> 364} 365 366// CHECK-LABEL: func @sparse_valuesf32( 367// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 368// CHECK: %[[T:.*]] = call @sparseValuesF32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf32> 369// CHECK: return %[[T]] : memref<?xf32> 370func @sparse_valuesf32(%arg0: tensor<128xf32, #SparseVector>) -> memref<?xf32> { 371 %0 = sparse_tensor.values %arg0: tensor<128xf32, #SparseVector> to memref<?xf32> 372 return %0 : memref<?xf32> 373} 374 375// CHECK-LABEL: func @sparse_valuesi32( 376// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 377// CHECK: %[[T:.*]] = call @sparseValuesI32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi32> 378// CHECK: return %[[T]] : memref<?xi32> 379func @sparse_valuesi32(%arg0: tensor<128xi32, #SparseVector>) -> memref<?xi32> { 380 %0 = sparse_tensor.values %arg0: tensor<128xi32, #SparseVector> to memref<?xi32> 381 return %0 : memref<?xi32> 382} 383 384// CHECK-LABEL: func @sparse_valuesi16( 385// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 386// CHECK: %[[T:.*]] = call @sparseValuesI16(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi16> 387// CHECK: return %[[T]] : memref<?xi16> 388func @sparse_valuesi16(%arg0: tensor<128xi16, #SparseVector>) -> memref<?xi16> { 389 %0 = sparse_tensor.values %arg0: tensor<128xi16, #SparseVector> to memref<?xi16> 390 return %0 : memref<?xi16> 391} 392 393// CHECK-LABEL: func @sparse_valuesi8( 394// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 395// CHECK: %[[T:.*]] = call @sparseValuesI8(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi8> 396// CHECK: return %[[T]] : memref<?xi8> 397func @sparse_valuesi8(%arg0: tensor<128xi8, #SparseVector>) -> memref<?xi8> { 398 %0 = sparse_tensor.values %arg0: tensor<128xi8, #SparseVector> to memref<?xi8> 399 return %0 : memref<?xi8> 400} 401 402// CHECK-LABEL: func @sparse_reconstruct_1( 403// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 404// CHECK: return %[[A]] : !llvm.ptr<i8> 405func @sparse_reconstruct_1(%arg0: tensor<128xf32, #DenseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #DenseVector> { 406 %0 = sparse_tensor.values %arg0 : tensor<128xf32, #DenseVector> to memref<?xf32> 407 %1 = sparse_tensor.tensor %0 : memref<?xf32> to tensor<128xf32, #DenseVector> 408 return %1 : tensor<128xf32, #DenseVector> 409} 410 411// CHECK-LABEL: func @sparse_reconstruct_n( 412// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 413// CHECK: return %[[A]] : !llvm.ptr<i8> 414func @sparse_reconstruct_n(%arg0: tensor<128xf32, #SparseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #SparseVector> { 415 %c = arith.constant 0 : index 416 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 417 %1 = sparse_tensor.indices %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 418 %2 = sparse_tensor.values %arg0 : tensor<128xf32, #SparseVector> to memref<?xf32> 419 %3 = sparse_tensor.tensor %0, %1, %2 : memref<?xindex>, memref<?xindex>, memref<?xf32> to tensor<128xf32, #SparseVector> 420 return %3 : tensor<128xf32, #SparseVector> 421} 422