1// RUN: mlir-opt %s -sparsification --canonicalize | FileCheck %s --check-prefix=CHECK-HIR
2//
3// RUN: mlir-opt %s -sparsification --sparse-tensor-conversion --canonicalize | \
4// RUN: FileCheck %s --check-prefix=CHECK-MIR
5
6#X = #sparse_tensor.encoding<{
7 dimLevelType = [ "dense", "dense", "dense" ],
8 dimOrdering = affine_map<(i,j,k) -> (k,i,j)>
9}>
10
11#trait = {
12  indexing_maps = [
13    affine_map<(i,j,k) -> (k,i,j)>,  // A (in)
14    affine_map<(i,j,k) -> ()>        // X (out)
15  ],
16  iterator_types = ["reduction", "reduction", "reduction"]
17}
18
19// CHECK-HIR-LABEL:   func @sparse_dynamic_dims(
20// CHECK-HIR-SAME:                                      %[[VAL_0:.*]]: tensor<?x?x?xf32,  #sparse_tensor.encoding<{{{.*}}}>>,
21// CHECK-HIR-SAME:                                      %[[VAL_1:.*]]: tensor<f32>) -> tensor<f32> {
22// CHECK-HIR-DAG:       %[[C0:.*]] = constant 0 : index
23// CHECK-HIR-DAG:       %[[C1:.*]] = constant 1 : index
24// CHECK-HIR-DAG:       %[[C2:.*]] = constant 2 : index
25// CHECK-HIR:           %[[VAL_5:.*]] = tensor.dim %[[VAL_0]], %[[C2]] : tensor<?x?x?xf32,  #sparse_tensor.encoding<{{{.*}}}>>
26// CHECK-HIR:           %[[VAL_6:.*]] = tensor.dim %[[VAL_0]], %[[C0]] : tensor<?x?x?xf32,  #sparse_tensor.encoding<{{{.*}}}>>
27// CHECK-HIR:           %[[VAL_7:.*]] = tensor.dim %[[VAL_0]], %[[C1]] : tensor<?x?x?xf32,  #sparse_tensor.encoding<{{{.*}}}>>
28// CHECK-HIR:           %[[VAL_8:.*]] = sparse_tensor.values %[[VAL_0]] : tensor<?x?x?xf32,  #sparse_tensor.encoding<{{{.*}}}>>
29// CHECK-HIR:           %[[VAL_9:.*]] = memref.buffer_cast %[[VAL_1]] : memref<f32>
30// CHECK-HIR:           %[[VAL_10:.*]] = memref.alloc() : memref<f32>
31// CHECK-HIR:           memref.copy %[[VAL_9]], %[[VAL_10]] : memref<f32> to memref<f32>
32// CHECK-HIR:           scf.for %[[VAL_11:.*]] = %[[C0]] to %[[VAL_5]] step %[[C1]] {
33// CHECK-HIR:             scf.for %[[VAL_12:.*]] = %[[C0]] to %[[VAL_6]] step %[[C1]] {
34// CHECK-HIR:               %[[VAL_13:.*]] = muli %[[VAL_6]], %[[VAL_11]] : index
35// CHECK-HIR:               %[[VAL_14:.*]] = addi %[[VAL_13]], %[[VAL_12]] : index
36// CHECK-HIR:               %[[VAL_15:.*]] = memref.load %[[VAL_10]][] : memref<f32>
37// CHECK-HIR:               %[[VAL_16:.*]] = scf.for %[[VAL_17:.*]] = %[[C0]] to %[[VAL_7]] step %[[C1]] iter_args(%[[VAL_18:.*]] = %[[VAL_15]]) -> (f32) {
38// CHECK-HIR:                 %[[VAL_19:.*]] = muli %[[VAL_7]], %[[VAL_14]] : index
39// CHECK-HIR:                 %[[VAL_20:.*]] = addi %[[VAL_19]], %[[VAL_17]] : index
40// CHECK-HIR:                 %[[VAL_21:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_20]]] : memref<?xf32>
41// CHECK-HIR:                 %[[VAL_22:.*]] = addf %[[VAL_18]], %[[VAL_21]] : f32
42// CHECK-HIR:                 scf.yield %[[VAL_22]] : f32
43// CHECK-HIR:               }
44// CHECK-HIR:               memref.store %[[VAL_23:.*]], %[[VAL_10]][] : memref<f32>
45// CHECK-HIR:             }
46// CHECK-HIR:           }
47// CHECK-HIR:           %[[VAL_24:.*]] = memref.tensor_load %[[VAL_10]] : memref<f32>
48// CHECK-HIR:           return %[[VAL_24]] : tensor<f32>
49// CHECK-HIR:         }
50//
51// CHECK-MIR-LABEL:   func @sparse_dynamic_dims(
52// CHECK-MIR-SAME:                                      %[[VAL_0:.*]]: !llvm.ptr<i8>,
53// CHECK-MIR-SAME:                                      %[[VAL_1:.*]]: tensor<f32>) -> tensor<f32> {
54// CHECK-MIR-DAG:       %[[C0:.*]] = constant 0 : index
55// CHECK-MIR-DAG:       %[[C1:.*]] = constant 1 : index
56// CHECK-MIR-DAG:       %[[C2:.*]] = constant 2 : index
57// CHECK-MIR:           %[[VAL_5:.*]] = call @sparseDimSize(%[[VAL_0]], %[[C0]]) : (!llvm.ptr<i8>, index) -> index
58// CHECK-MIR:           %[[VAL_6:.*]] = call @sparseDimSize(%[[VAL_0]], %[[C1]]) : (!llvm.ptr<i8>, index) -> index
59// CHECK-MIR:           %[[VAL_7:.*]] = call @sparseDimSize(%[[VAL_0]], %[[C2]]) : (!llvm.ptr<i8>, index) -> index
60// CHECK-MIR:           %[[VAL_8:.*]] = call @sparseValuesF32(%[[VAL_0]]) : (!llvm.ptr<i8>) -> memref<?xf32>
61// CHECK-MIR:           %[[VAL_9:.*]] = memref.buffer_cast %[[VAL_1]] : memref<f32>
62// CHECK-MIR:           %[[VAL_10:.*]] = memref.alloc() : memref<f32>
63// CHECK-MIR:           memref.copy %[[VAL_9]], %[[VAL_10]] : memref<f32> to memref<f32>
64// CHECK-MIR:           scf.for %[[VAL_11:.*]] = %[[C0]] to %[[VAL_5]] step %[[C1]] {
65// CHECK-MIR:             scf.for %[[VAL_12:.*]] = %[[C0]] to %[[VAL_6]] step %[[C1]] {
66// CHECK-MIR:               %[[VAL_13:.*]] = muli %[[VAL_6]], %[[VAL_11]] : index
67// CHECK-MIR:               %[[VAL_14:.*]] = addi %[[VAL_13]], %[[VAL_12]] : index
68// CHECK-MIR:               %[[VAL_15:.*]] = memref.load %[[VAL_10]][] : memref<f32>
69// CHECK-MIR:               %[[VAL_16:.*]] = scf.for %[[VAL_17:.*]] = %[[C0]] to %[[VAL_7]] step %[[C1]] iter_args(%[[VAL_18:.*]] = %[[VAL_15]]) -> (f32) {
70// CHECK-MIR:                 %[[VAL_19:.*]] = muli %[[VAL_7]], %[[VAL_14]] : index
71// CHECK-MIR:                 %[[VAL_20:.*]] = addi %[[VAL_19]], %[[VAL_17]] : index
72// CHECK-MIR:                 %[[VAL_21:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_20]]] : memref<?xf32>
73// CHECK-MIR:                 %[[VAL_22:.*]] = addf %[[VAL_18]], %[[VAL_21]] : f32
74// CHECK-MIR:                 scf.yield %[[VAL_22]] : f32
75// CHECK-MIR:               }
76// CHECK-MIR:               memref.store %[[VAL_23:.*]], %[[VAL_10]][] : memref<f32>
77// CHECK-MIR:             }
78// CHECK-MIR:           }
79// CHECK-MIR:           %[[VAL_24:.*]] = memref.tensor_load %[[VAL_10]] : memref<f32>
80// CHECK-MIR:           return %[[VAL_24]] : tensor<f32>
81// CHECK-MIR:         }
82func @sparse_dynamic_dims(%arga: tensor<?x?x?xf32, #X>,
83                          %argx: tensor<f32>) -> tensor<f32> {
84  %0 = linalg.generic #trait
85    ins(%arga: tensor<?x?x?xf32, #X>)
86    outs(%argx: tensor<f32>) {
87      ^bb(%a : f32, %x: f32):
88        %0 = addf %x, %a : f32
89        linalg.yield %0 : f32
90  } -> tensor<f32>
91  return %0 : tensor<f32>
92}
93