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:.*]] = 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 = 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:.*]] = 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 = 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:.*]] = 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 = 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: %[[U:.*]] = constant dense<1> : tensor<1xi8> 73// CHECK-DAG: %[[V:.*]] = constant dense<128> : tensor<1xi64> 74// CHECK-DAG: %[[W:.*]] = constant dense<0> : tensor<1xi64> 75// CHECK-DAG: %[[X:.*]] = tensor.cast %[[U]] : tensor<1xi8> to tensor<?xi8> 76// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[V]] : tensor<1xi64> to tensor<?xi64> 77// CHECK-DAG: %[[Z:.*]] = tensor.cast %[[W]] : tensor<1xi64> to tensor<?xi64> 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: %[[U:.*]] = constant dense<[0, 1]> : tensor<2xi8> 88// CHECK-DAG: %[[V:.*]] = constant dense<0> : tensor<2xi64> 89// CHECK-DAG: %[[W:.*]] = constant dense<[0, 1]> : tensor<2xi64> 90// CHECK-DAG: %[[X:.*]] = tensor.cast %[[U]] : tensor<2xi8> to tensor<?xi8> 91// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[V]] : tensor<2xi64> to tensor<?xi64> 92// CHECK-DAG: %[[Z:.*]] = tensor.cast %[[W]] : tensor<2xi64> to tensor<?xi64> 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: %[[U:.*]] = constant dense<[0, 1, 1]> : tensor<3xi8> 103// CHECK-DAG: %[[V:.*]] = constant dense<0> : tensor<3xi64> 104// CHECK-DAG: %[[W:.*]] = constant dense<[1, 2, 0]> : tensor<3xi64> 105// CHECK-DAG: %[[X:.*]] = tensor.cast %[[U]] : tensor<3xi8> to tensor<?xi8> 106// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[V]] : tensor<3xi64> to tensor<?xi64> 107// CHECK-DAG: %[[Z:.*]] = tensor.cast %[[W]] : tensor<3xi64> to tensor<?xi64> 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_convert_1d( 116// CHECK-SAME: %[[A:.*]]: tensor<?xi32>) -> !llvm.ptr<i8> 117// CHECK-DAG: %[[C0:.*]] = constant 0 : index 118// CHECK-DAG: %[[C1:.*]] = constant 1 : index 119// CHECK-DAG: %[[D0:.*]] = constant dense<0> : tensor<1xi64> 120// CHECK-DAG: %[[D1:.*]] = constant dense<1> : tensor<1xi8> 121// CHECK-DAG: %[[X:.*]] = tensor.cast %[[D1]] : tensor<1xi8> to tensor<?xi8> 122// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[D0]] : tensor<1xi64> to tensor<?xi64> 123// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Y]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.}}) 124// CHECK: %[[M:.*]] = memref.alloca() : memref<1xindex> 125// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<1xindex> to memref<?xindex> 126// CHECK: %[[U:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?xi32> 127// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U]] step %[[C1]] { 128// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]]] : tensor<?xi32> 129// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<1xindex> 130// CHECK: call @addEltI32(%[[C]], %[[E]], %[[T]], %[[Y]]) 131// CHECK: } 132// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Y]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 133// CHECK: return %[[T]] : !llvm.ptr<i8> 134func @sparse_convert_1d(%arg0: tensor<?xi32>) -> tensor<?xi32, #SparseVector> { 135 %0 = sparse_tensor.convert %arg0 : tensor<?xi32> to tensor<?xi32, #SparseVector> 136 return %0 : tensor<?xi32, #SparseVector> 137} 138 139// CHECK-LABEL: func @sparse_convert_1d_ss( 140// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 141// CHECK: %[[C:.*]] = call @newSparseTensor(%{{.}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[A]]) 142// CHECK: %[[T:.*]] = call @newSparseTensor(%{{.}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 143// CHECK: return %[[T]] : !llvm.ptr<i8> 144func @sparse_convert_1d_ss(%arg0: tensor<?xf32, #SparseVector64>) -> tensor<?xf32, #SparseVector32> { 145 %0 = sparse_tensor.convert %arg0 : tensor<?xf32, #SparseVector64> to tensor<?xf32, #SparseVector32> 146 return %0 : tensor<?xf32, #SparseVector32> 147} 148 149// CHECK-LABEL: func @sparse_convert_2d( 150// CHECK-SAME: %[[A:.*]]: tensor<2x4xf64>) -> !llvm.ptr<i8> 151// CHECK-DAG: %[[C0:.*]] = constant 0 : index 152// CHECK-DAG: %[[C1:.*]] = constant 1 : index 153// CHECK-DAG: %[[U:.*]] = constant dense<[0, 1]> : tensor<2xi8> 154// CHECK-DAG: %[[V:.*]] = constant dense<[2, 4]> : tensor<2xi64> 155// CHECK-DAG: %[[W:.*]] = constant dense<[0, 1]> : tensor<2xi64> 156// CHECK-DAG: %[[X:.*]] = tensor.cast %[[U]] : tensor<2xi8> to tensor<?xi8> 157// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[V]] : tensor<2xi64> to tensor<?xi64> 158// CHECK-DAG: %[[Z:.*]] = tensor.cast %[[W]] : tensor<2xi64> to tensor<?xi64> 159// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.}}) 160// CHECK: %[[M:.*]] = memref.alloca() : memref<2xindex> 161// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<2xindex> to memref<?xindex> 162// CHECK: scf.for %[[I:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 163// CHECK: scf.for %[[J:.*]] = %[[C0]] to %{{.*}} step %[[C1]] { 164// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]]] : tensor<2x4xf64> 165// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<2xindex> 166// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<2xindex> 167// CHECK: call @addEltF64(%[[C]], %[[E]], %[[T]], %[[Z]]) 168// CHECK: } 169// CHECK: } 170// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 171// CHECK: return %[[T]] : !llvm.ptr<i8> 172func @sparse_convert_2d(%arg0: tensor<2x4xf64>) -> tensor<2x4xf64, #SparseMatrix> { 173 %0 = sparse_tensor.convert %arg0 : tensor<2x4xf64> to tensor<2x4xf64, #SparseMatrix> 174 return %0 : tensor<2x4xf64, #SparseMatrix> 175} 176 177// CHECK-LABEL: func @sparse_convert_3d( 178// CHECK-SAME: %[[A:.*]]: tensor<?x?x?xf64>) -> !llvm.ptr<i8> 179// CHECK-DAG: %[[C0:.*]] = constant 0 : index 180// CHECK-DAG: %[[C1:.*]] = constant 1 : index 181// CHECK-DAG: %[[C2:.*]] = constant 2 : index 182// CHECK-DAG: %[[U:.*]] = constant dense<[0, 1, 1]> : tensor<3xi8> 183// CHECK-DAG: %[[V:.*]] = constant dense<0> : tensor<3xi64> 184// CHECK-DAG: %[[W:.*]] = constant dense<[1, 2, 0]> : tensor<3xi64> 185// CHECK-DAG: %[[X:.*]] = tensor.cast %[[U]] : tensor<3xi8> to tensor<?xi8> 186// CHECK-DAG: %[[Y:.*]] = tensor.cast %[[V]] : tensor<3xi64> to tensor<?xi64> 187// CHECK-DAG: %[[Z:.*]] = tensor.cast %[[W]] : tensor<3xi64> to tensor<?xi64> 188// CHECK: %[[C:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.}}) 189// CHECK: %[[M:.*]] = memref.alloca() : memref<3xindex> 190// CHECK: %[[T:.*]] = memref.cast %[[M]] : memref<3xindex> to memref<?xindex> 191// CHECK: %[[U1:.*]] = tensor.dim %[[A]], %[[C0]] : tensor<?x?x?xf64> 192// CHECK: %[[U2:.*]] = tensor.dim %[[A]], %[[C1]] : tensor<?x?x?xf64> 193// CHECK: %[[U3:.*]] = tensor.dim %[[A]], %[[C2]] : tensor<?x?x?xf64> 194// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[U1]] step %[[C1]] { 195// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[U2]] step %[[C1]] { 196// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[U3]] step %[[C1]] { 197// CHECK: %[[E:.*]] = tensor.extract %[[A]][%[[I]], %[[J]], %[[K]]] : tensor<?x?x?xf64> 198// CHECK: memref.store %[[I]], %[[M]][%[[C0]]] : memref<3xindex> 199// CHECK: memref.store %[[J]], %[[M]][%[[C1]]] : memref<3xindex> 200// CHECK: memref.store %[[K]], %[[M]][%[[C2]]] : memref<3xindex> 201// CHECK: call @addEltF64(%[[C]], %[[E]], %[[T]], %[[Z]]) 202// CHECK: } 203// CHECK: } 204// CHECK: } 205// CHECK: %[[T:.*]] = call @newSparseTensor(%[[X]], %[[Y]], %[[Z]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %[[C]]) 206// CHECK: return %[[T]] : !llvm.ptr<i8> 207func @sparse_convert_3d(%arg0: tensor<?x?x?xf64>) -> tensor<?x?x?xf64, #SparseTensor> { 208 %0 = sparse_tensor.convert %arg0 : tensor<?x?x?xf64> to tensor<?x?x?xf64, #SparseTensor> 209 return %0 : tensor<?x?x?xf64, #SparseTensor> 210} 211 212// CHECK-LABEL: func @sparse_pointers( 213// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 214// CHECK: %[[C:.*]] = constant 0 : index 215// CHECK: %[[T:.*]] = call @sparsePointers(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 216// CHECK: return %[[T]] : memref<?xindex> 217func @sparse_pointers(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 218 %c = constant 0 : index 219 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 220 return %0 : memref<?xindex> 221} 222 223// CHECK-LABEL: func @sparse_pointers64( 224// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 225// CHECK: %[[C:.*]] = constant 0 : index 226// CHECK: %[[T:.*]] = call @sparsePointers64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 227// CHECK: return %[[T]] : memref<?xi64> 228func @sparse_pointers64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 229 %c = constant 0 : index 230 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 231 return %0 : memref<?xi64> 232} 233 234// CHECK-LABEL: func @sparse_pointers32( 235// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 236// CHECK: %[[C:.*]] = constant 0 : index 237// CHECK: %[[T:.*]] = call @sparsePointers32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 238// CHECK: return %[[T]] : memref<?xi32> 239func @sparse_pointers32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 240 %c = constant 0 : index 241 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 242 return %0 : memref<?xi32> 243} 244 245// CHECK-LABEL: func @sparse_indices( 246// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 247// CHECK: %[[C:.*]] = constant 0 : index 248// CHECK: %[[T:.*]] = call @sparseIndices(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xindex> 249// CHECK: return %[[T]] : memref<?xindex> 250func @sparse_indices(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xindex> { 251 %c = constant 0 : index 252 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector> to memref<?xindex> 253 return %0 : memref<?xindex> 254} 255 256// CHECK-LABEL: func @sparse_indices64( 257// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 258// CHECK: %[[C:.*]] = constant 0 : index 259// CHECK: %[[T:.*]] = call @sparseIndices64(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi64> 260// CHECK: return %[[T]] : memref<?xi64> 261func @sparse_indices64(%arg0: tensor<128xf64, #SparseVector64>) -> memref<?xi64> { 262 %c = constant 0 : index 263 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector64> to memref<?xi64> 264 return %0 : memref<?xi64> 265} 266 267// CHECK-LABEL: func @sparse_indices32( 268// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 269// CHECK: %[[C:.*]] = constant 0 : index 270// CHECK: %[[T:.*]] = call @sparseIndices32(%[[A]], %[[C]]) : (!llvm.ptr<i8>, index) -> memref<?xi32> 271// CHECK: return %[[T]] : memref<?xi32> 272func @sparse_indices32(%arg0: tensor<128xf64, #SparseVector32>) -> memref<?xi32> { 273 %c = constant 0 : index 274 %0 = sparse_tensor.indices %arg0, %c : tensor<128xf64, #SparseVector32> to memref<?xi32> 275 return %0 : memref<?xi32> 276} 277 278// CHECK-LABEL: func @sparse_valuesf64( 279// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 280// CHECK: %[[T:.*]] = call @sparseValuesF64(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf64> 281// CHECK: return %[[T]] : memref<?xf64> 282func @sparse_valuesf64(%arg0: tensor<128xf64, #SparseVector>) -> memref<?xf64> { 283 %0 = sparse_tensor.values %arg0 : tensor<128xf64, #SparseVector> to memref<?xf64> 284 return %0 : memref<?xf64> 285} 286 287// CHECK-LABEL: func @sparse_valuesf32( 288// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 289// CHECK: %[[T:.*]] = call @sparseValuesF32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xf32> 290// CHECK: return %[[T]] : memref<?xf32> 291func @sparse_valuesf32(%arg0: tensor<128xf32, #SparseVector>) -> memref<?xf32> { 292 %0 = sparse_tensor.values %arg0: tensor<128xf32, #SparseVector> to memref<?xf32> 293 return %0 : memref<?xf32> 294} 295 296// CHECK-LABEL: func @sparse_valuesi32( 297// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 298// CHECK: %[[T:.*]] = call @sparseValuesI32(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi32> 299// CHECK: return %[[T]] : memref<?xi32> 300func @sparse_valuesi32(%arg0: tensor<128xi32, #SparseVector>) -> memref<?xi32> { 301 %0 = sparse_tensor.values %arg0: tensor<128xi32, #SparseVector> to memref<?xi32> 302 return %0 : memref<?xi32> 303} 304 305// CHECK-LABEL: func @sparse_valuesi16( 306// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 307// CHECK: %[[T:.*]] = call @sparseValuesI16(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi16> 308// CHECK: return %[[T]] : memref<?xi16> 309func @sparse_valuesi16(%arg0: tensor<128xi16, #SparseVector>) -> memref<?xi16> { 310 %0 = sparse_tensor.values %arg0: tensor<128xi16, #SparseVector> to memref<?xi16> 311 return %0 : memref<?xi16> 312} 313 314// CHECK-LABEL: func @sparse_valuesi8( 315// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8>) 316// CHECK: %[[T:.*]] = call @sparseValuesI8(%[[A]]) : (!llvm.ptr<i8>) -> memref<?xi8> 317// CHECK: return %[[T]] : memref<?xi8> 318func @sparse_valuesi8(%arg0: tensor<128xi8, #SparseVector>) -> memref<?xi8> { 319 %0 = sparse_tensor.values %arg0: tensor<128xi8, #SparseVector> to memref<?xi8> 320 return %0 : memref<?xi8> 321} 322 323// CHECK-LABEL: func @sparse_reconstruct_1( 324// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 325// CHECK: return %[[A]] : !llvm.ptr<i8> 326func @sparse_reconstruct_1(%arg0: tensor<128xf32, #DenseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #DenseVector> { 327 %0 = sparse_tensor.values %arg0 : tensor<128xf32, #DenseVector> to memref<?xf32> 328 %1 = sparse_tensor.tensor %0 : memref<?xf32> to tensor<128xf32, #DenseVector> 329 return %1 : tensor<128xf32, #DenseVector> 330} 331 332// CHECK-LABEL: func @sparse_reconstruct_n( 333// CHECK-SAME: %[[A:.*]]: !llvm.ptr<i8> 334// CHECK: return %[[A]] : !llvm.ptr<i8> 335func @sparse_reconstruct_n(%arg0: tensor<128xf32, #SparseVector> {linalg.inplaceable = true}) -> tensor<128xf32, #SparseVector> { 336 %c = constant 0 : index 337 %0 = sparse_tensor.pointers %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 338 %1 = sparse_tensor.indices %arg0, %c : tensor<128xf32, #SparseVector> to memref<?xindex> 339 %2 = sparse_tensor.values %arg0 : tensor<128xf32, #SparseVector> to memref<?xf32> 340 %3 = sparse_tensor.tensor %0, %1, %2 : memref<?xindex>, memref<?xindex>, memref<?xf32> to tensor<128xf32, #SparseVector> 341 return %3 : tensor<128xf32, #SparseVector> 342} 343