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_hidden_nop_cast( 154// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 155// CHECK: return %[[A]] : !llvm.ptr<i8> 156func @sparse_hidden_nop_cast(%arg0: tensor<32xf32, #SparseVector>) -> tensor<?xf32, #SparseVector> { 157 %0 = sparse_tensor.convert %arg0 : tensor<32xf32, #SparseVector> to tensor<?xf32, #SparseVector> 158 return %0 : tensor<?xf32, #SparseVector> 159} 160 161// CHECK-LABEL: func @sparse_nop_cast( 162// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) -> !llvm.ptr<i8> 163// CHECK: return %[[A]] : !llvm.ptr<i8> 164func @sparse_nop_cast(%arg0: tensor<64xf32, #SparseVector>) -> tensor<?xf32, #SparseVector> { 165 %0 = tensor.cast %arg0 : tensor<64xf32, #SparseVector> to tensor<?xf32, #SparseVector> 166 return %0 : tensor<?xf32, #SparseVector> 167} 168 169// CHECK-LABEL: func @sparse_convert_1d( 170// CHECK-SAME: %[[A:.*]]: tensor<?xi32>) -> !llvm.ptr<i8> 171// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 172// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 173// CHECK-DAG: %[[U:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?xi32> 174// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<1xi8> 175// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<1xindex> 176// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<1xindex> 177// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<1xi8> to memref<?xi8> 178// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<1xindex> to memref<?xindex> 179// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<1xindex> to memref<?xindex> 180// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 181// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 182// CHECK: %[[M:.*]] = memref.alloca() : memref<1xindex> 183// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<1xindex> to memref<?xindex> 184// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U]] step %[[C1]] { 185// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]]] : tensor<?xi32> 186// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<1xindex> 187// CHECK: call @addEltI32(%[[C]], %[[E]], %[[T]], %[[Z]]) 188// CHECK: } 189// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 190// CHECK: return %[[T]] : !llvm.ptr<i8> 191func @sparse_convert_1d(%arg0: tensor<?xi32>) -> tensor<?xi32, #SparseVector> { 192 %0 = sparse_tensor.convert %arg0 : tensor<?xi32> to tensor<?xi32, #SparseVector> 193 return %0 : tensor<?xi32, #SparseVector> 194} 195 196// CHECK-LABEL: func @sparse_convert_1d_ss( 197// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 198// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<1xi8> 199// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<1xindex> 200// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<1xindex> 201// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<1xi8> to memref<?xi8> 202// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<1xindex> to memref<?xindex> 203// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<1xindex> to memref<?xindex> 204// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 205// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 206// CHECK: return %[[T]] : !llvm.ptr<i8> 207func @sparse_convert_1d_ss(%arg0: tensor<?xf32, #SparseVector64>) -> tensor<?xf32, #SparseVector32> { 208 %0 = sparse_tensor.convert %arg0 : tensor<?xf32, #SparseVector64> to tensor<?xf32, #SparseVector32> 209 return %0 : tensor<?xf32, #SparseVector32> 210} 211 212// CHECK-LABEL: func @sparse_convert_2d( 213// CHECK-SAME: %[[A:.*]]: tensor<2x4xf64>) -> !llvm.ptr<i8> 214// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 215// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 216// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 217// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 218// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 219// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 220// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 221// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 222// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 223// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 224// CHECK: %[[M:.*]] = memref.alloca() : memref<2xindex> 225// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<2xindex> to memref<?xindex> 226// CHECK: scf.for %[[I:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 227// CHECK: scf.for %[[J:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 228// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]]] : tensor<2x4xf64> 229// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<2xindex> 230// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<2xindex> 231// CHECK: call @addEltF64(%[[C]], %[[E]], %[[T]], %[[Z]]) 232// CHECK: } 233// CHECK: } 234// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 235// CHECK: return %[[T]] : !llvm.ptr<i8> 236func @sparse_convert_2d(%arg0: tensor<2x4xf64>) -> tensor<2x4xf64, #SparseMatrix> { 237 %0 = sparse_tensor.convert %arg0 : tensor<2x4xf64> to tensor<2x4xf64, #SparseMatrix> 238 return %0 : tensor<2x4xf64, #SparseMatrix> 239} 240 241// CHECK-LABEL: func @sparse_constant() -> !llvm.ptr<i8> { 242// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 243// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 244// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 245// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<2xi8> 246// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<2xindex> 247// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<2xindex> 248// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<2xi8> to memref<?xi8> 249// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<2xindex> to memref<?xindex> 250// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<2xindex> to memref<?xindex> 251// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 252// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 253// CHECK: %[[M:.*]] = memref.alloca() : memref<2xindex> 254// CHECK: %[[N:.*]] = memref.cast %[[M]] : memref<2xindex> to memref<?xindex> 255// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C2]] step %[[C1]] { 256// CHECK: memref.store %{{.*}}, %[[M]][%[[C0]]] : memref<2xindex> 257// CHECK: memref.store %{{.*}}, %[[M]][%[[C1]]] : memref<2xindex> 258// CHECK: %[[V:.*]] = tensor.extract %{{.*}}[%[[I]]] : tensor<2xf32> 259// CHECK: call @addEltF32(%{{.*}}, %[[V]], %[[N]], %{{.*}}) 260// CHECK: } 261// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 262// CHECK: return %[[T]] : !llvm.ptr<i8> 263func @sparse_constant() -> tensor<8x7xf32, #SparseMatrix>{ 264 // Initialize a tensor. 265 %0 = arith.constant sparse<[[0, 0], [1, 6]], [1.0, 5.0]> : tensor<8x7xf32> 266 // Convert the tensor to a sparse tensor. 267 %1 = sparse_tensor.convert %0 : tensor<8x7xf32> to tensor<8x7xf32, #SparseMatrix> 268 return %1 : tensor<8x7xf32, #SparseMatrix> 269} 270 271// CHECK-LABEL: func @sparse_convert_3d( 272// CHECK-SAME: %[[A:.*]]: tensor<?x?x?xf64>) -> !llvm.ptr<i8> 273// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index 274// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index 275// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index 276// CHECK-DAG: %[[U1:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?x?x?xf64> 277// CHECK-DAG: %[[U2:.*]] = tensor.dim %[[A]], %[[C1]] : tensor<?x?x?xf64> 278// CHECK-DAG: %[[U3:.*]] = tensor.dim %[[A]], %[[C2]] : tensor<?x?x?xf64> 279// CHECK-DAG: %[[P:.*]] = memref.alloca() : memref<3xi8> 280// CHECK-DAG: %[[Q:.*]] = memref.alloca() : memref<3xindex> 281// CHECK-DAG: %[[R:.*]] = memref.alloca() : memref<3xindex> 282// CHECK-DAG: %[[X:.*]] = memref.cast %[[P]] : memref<3xi8> to memref<?xi8> 283// CHECK-DAG: %[[Y:.*]] = memref.cast %[[Q]] : memref<3xindex> to memref<?xindex> 284// CHECK-DAG: %[[Z:.*]] = memref.cast %[[R]] : memref<3xindex> to memref<?xindex> 285// CHECK: %[[NP:.*]] = llvm.mlir.null : !llvm.ptr<i8> 286// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[NP]]) 287// CHECK: %[[M:.*]] = memref.alloca() : memref<3xindex> 288// CHECK: %[[N:.*]] = memref.cast %[[M]] : memref<3xindex> to memref<?xindex> 289// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U1]] step %[[C1]] { 290// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[U2]] step %[[C1]] { 291// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[U3]] step %[[C1]] { 292// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]], %[[K]]] : tensor<?x?x?xf64> 293// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<3xindex> 294// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<3xindex> 295// CHECK: memref.store %[[K]], %[[M]][%[[C2]]] : memref<3xindex> 296// CHECK: call @addEltF64(%[[C]], %[[E]], %[[N]], %[[Z]]) 297// CHECK: } 298// CHECK: } 299// CHECK: } 300// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 301// CHECK: return %[[T]] : !llvm.ptr<i8> 302func @sparse_convert_3d(%arg0: tensor<?x?x?xf64>) -> tensor<?x?x?xf64, #SparseTensor> { 303 %0 = sparse_tensor.convert %arg0 : tensor<?x?x?xf64> to tensor<?x?x?xf64, #SparseTensor> 304 return %0 : tensor<?x?x?xf64, #SparseTensor> 305} 306 307// CHECK-LABEL: func @sparse_pointers( 308// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 309// CHECK: %[[C:.*]] = arith.constant 0 : index 310// CHECK: %[[T:.*]] = call @sparsePointers(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 311// CHECK: return %[[T]] : memref<?xindex> 312func @sparse_pointers(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 313 %c = arith.constant 0 : index 314 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 315 return %0 : memref<?xindex> 316} 317 318// CHECK-LABEL: func @sparse_pointers64( 319// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 320// CHECK: %[[C:.*]] = arith.constant 0 : index 321// CHECK: %[[T:.*]] = call @sparsePointers64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 322// CHECK: return %[[T]] : memref<?xi64> 323func @sparse_pointers64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 324 %c = arith.constant 0 : index 325 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 326 return %0 : memref<?xi64> 327} 328 329// CHECK-LABEL: func @sparse_pointers32( 330// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 331// CHECK: %[[C:.*]] = arith.constant 0 : index 332// CHECK: %[[T:.*]] = call @sparsePointers32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 333// CHECK: return %[[T]] : memref<?xi32> 334func @sparse_pointers32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 335 %c = arith.constant 0 : index 336 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 337 return %0 : memref<?xi32> 338} 339 340// CHECK-LABEL: func @sparse_indices( 341// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 342// CHECK: %[[C:.*]] = arith.constant 0 : index 343// CHECK: %[[T:.*]] = call @sparseIndices(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 344// CHECK: return %[[T]] : memref<?xindex> 345func @sparse_indices(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 346 %c = arith.constant 0 : index 347 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 348 return %0 : memref<?xindex> 349} 350 351// CHECK-LABEL: func @sparse_indices64( 352// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 353// CHECK: %[[C:.*]] = arith.constant 0 : index 354// CHECK: %[[T:.*]] = call @sparseIndices64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 355// CHECK: return %[[T]] : memref<?xi64> 356func @sparse_indices64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 357 %c = arith.constant 0 : index 358 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 359 return %0 : memref<?xi64> 360} 361 362// CHECK-LABEL: func @sparse_indices32( 363// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 364// CHECK: %[[C:.*]] = arith.constant 0 : index 365// CHECK: %[[T:.*]] = call @sparseIndices32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 366// CHECK: return %[[T]] : memref<?xi32> 367func @sparse_indices32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 368 %c = arith.constant 0 : index 369 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 370 return %0 : memref<?xi32> 371} 372 373// CHECK-LABEL: func @sparse_valuesf64( 374// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 375// CHECK: %[[T:.*]] = call @sparseValuesF64(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf64> 376// CHECK: return %[[T]] : memref<?xf64> 377func @sparse_valuesf64(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xf64> { 378 %0 = sparse_tensor.values %arg0 : tensor<128xf64, #SparseVector> to memref<?xf64> 379 return %0 : memref<?xf64> 380} 381 382// CHECK-LABEL: func @sparse_valuesf32( 383// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 384// CHECK: %[[T:.*]] = call @sparseValuesF32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf32> 385// CHECK: return %[[T]] : memref<?xf32> 386func @sparse_valuesf32(%arg0: tensor<128xf32, #SparseVector>) -> memref<?xf32> { 387 %0 = sparse_tensor.values %arg0: tensor<128xf32, #SparseVector> to memref<?xf32> 388 return %0 : memref<?xf32> 389} 390 391// CHECK-LABEL: func @sparse_valuesi32( 392// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 393// CHECK: %[[T:.*]] = call @sparseValuesI32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi32> 394// CHECK: return %[[T]] : memref<?xi32> 395func @sparse_valuesi32(%arg0: tensor<128xi32, #SparseVector>) -> memref<?xi32> { 396 %0 = sparse_tensor.values %arg0: tensor<128xi32, #SparseVector> to memref<?xi32> 397 return %0 : memref<?xi32> 398} 399 400// CHECK-LABEL: func @sparse_valuesi16( 401// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 402// CHECK: %[[T:.*]] = call @sparseValuesI16(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi16> 403// CHECK: return %[[T]] : memref<?xi16> 404func @sparse_valuesi16(%arg0: tensor<128xi16, #SparseVector>) -> memref<?xi16> { 405 %0 = sparse_tensor.values %arg0: tensor<128xi16, #SparseVector> to memref<?xi16> 406 return %0 : memref<?xi16> 407} 408 409// CHECK-LABEL: func @sparse_valuesi8( 410// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 411// CHECK: %[[T:.*]] = call @sparseValuesI8(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi8> 412// CHECK: return %[[T]] : memref<?xi8> 413func @sparse_valuesi8(%arg0: tensor<128xi8, #SparseVector>) -> memref<?xi8> { 414 %0 = sparse_tensor.values %arg0: tensor<128xi8, #SparseVector> to memref<?xi8> 415 return %0 : memref<?xi8> 416} 417 418// CHECK-LABEL: func @sparse_reconstruct_1( 419// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 420// CHECK: return %[[A]] : !llvm.ptr<i8> 421func @sparse_reconstruct_1(%arg0: tensor<128xf32, #DenseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #DenseVector> { 422 %0 = sparse_tensor.values %arg0 : tensor<128xf32, #DenseVector> to memref<?xf32> 423 %1 = sparse_tensor.tensor %0 : memref<?xf32> to tensor<128xf32, #DenseVector> 424 return %1 : tensor<128xf32, #DenseVector> 425} 426 427// CHECK-LABEL: func @sparse_reconstruct_n( 428// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 429// CHECK: return %[[A]] : !llvm.ptr<i8> 430func @sparse_reconstruct_n(%arg0: tensor<128xf32, #SparseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #SparseVector> { 431 %c = arith.constant 0 : index 432 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 433 %1 = sparse_tensor.indices %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 434 %2 = sparse_tensor.values %arg0 : tensor<128xf32, #SparseVector> to memref<?xf32> 435 %3 = sparse_tensor.tensor %0, %1, %2 : memref<?xindex>, memref<?xindex>, memref<?xf32> to tensor<128xf32, #SparseVector> 436 return %3 : tensor<128xf32, #SparseVector> 437} 438