1// RUN: mlir-opt %s -sparsification="parallelization-strategy=0" | \
2// RUN:   FileCheck %s --check-prefix=CHECK-PAR0
3// RUN: mlir-opt %s -sparsification="parallelization-strategy=1" | \
4// RUN:   FileCheck %s --check-prefix=CHECK-PAR1
5// RUN: mlir-opt %s -sparsification="parallelization-strategy=2" | \
6// RUN:   FileCheck %s --check-prefix=CHECK-PAR2
7// RUN: mlir-opt %s -sparsification="parallelization-strategy=3" | \
8// RUN:   FileCheck %s --check-prefix=CHECK-PAR3
9// RUN: mlir-opt %s -sparsification="parallelization-strategy=4" | \
10// RUN:   FileCheck %s --check-prefix=CHECK-PAR4
11
12#SparseMatrix = #sparse_tensor.encoding<{
13  dimLevelType = [ "compressed", "compressed" ]
14}>
15
16#CSR = #sparse_tensor.encoding<{
17  dimLevelType = [ "dense", "compressed" ]
18}>
19
20#trait_dd = {
21  indexing_maps = [
22    affine_map<(i,j) -> (i,j)>,  // A
23    affine_map<(i,j) -> (i,j)>   // X (out)
24  ],
25  iterator_types = ["parallel", "parallel"],
26  doc = "X(i,j) = A(i,j) * SCALE"
27}
28
29//
30// CHECK-PAR0-LABEL: func @scale_dd
31// CHECK-PAR0:         scf.for
32// CHECK-PAR0:           scf.for
33// CHECK-PAR0:         return
34//
35// CHECK-PAR1-LABEL: func @scale_dd
36// CHECK-PAR1:         scf.parallel
37// CHECK-PAR1:           scf.for
38// CHECK-PAR1:         return
39//
40// CHECK-PAR2-LABEL: func @scale_dd
41// CHECK-PAR2:         scf.parallel
42// CHECK-PAR2:           scf.for
43// CHECK-PAR2:         return
44//
45// CHECK-PAR3-LABEL: func @scale_dd
46// CHECK-PAR3:         scf.parallel
47// CHECK-PAR3:           scf.parallel
48// CHECK-PAR3:         return
49//
50// CHECK-PAR4-LABEL: func @scale_dd
51// CHECK-PAR4:         scf.parallel
52// CHECK-PAR4:           scf.parallel
53// CHECK-PAR4:         return
54//
55func @scale_dd(%scale: f32, %arga: tensor<?x?xf32>, %argx: tensor<?x?xf32>) -> tensor<?x?xf32> {
56  %0 = linalg.generic #trait_dd
57     ins(%arga: tensor<?x?xf32>)
58    outs(%argx: tensor<?x?xf32>) {
59      ^bb(%a: f32, %x: f32):
60        %0 = mulf %a, %scale : f32
61        linalg.yield %0 : f32
62  } -> tensor<?x?xf32>
63  return %0 : tensor<?x?xf32>
64}
65
66#trait_ss = {
67  indexing_maps = [
68    affine_map<(i,j) -> (i,j)>,  // A
69    affine_map<(i,j) -> (i,j)>   // X (out)
70  ],
71  iterator_types = ["parallel", "parallel"],
72  doc = "X(i,j) = A(i,j) * SCALE"
73}
74
75//
76// CHECK-PAR0-LABEL: func @scale_ss
77// CHECK-PAR0:         scf.for
78// CHECK-PAR0:           scf.for
79// CHECK-PAR0:         return
80//
81// CHECK-PAR1-LABEL: func @scale_ss
82// CHECK-PAR1:         scf.for
83// CHECK-PAR1:           scf.for
84// CHECK-PAR1:         return
85//
86// CHECK-PAR2-LABEL: func @scale_ss
87// CHECK-PAR2:         scf.parallel
88// CHECK-PAR2:           scf.for
89// CHECK-PAR2:         return
90//
91// CHECK-PAR3-LABEL: func @scale_ss
92// CHECK-PAR3:         scf.for
93// CHECK-PAR3:           scf.for
94// CHECK-PAR3:         return
95//
96// CHECK-PAR4-LABEL: func @scale_ss
97// CHECK-PAR4:         scf.parallel
98// CHECK-PAR4:           scf.parallel
99// CHECK-PAR4:         return
100//
101func @scale_ss(%scale: f32, %arga: tensor<?x?xf32, #SparseMatrix>, %argx: tensor<?x?xf32>) -> tensor<?x?xf32> {
102  %0 = linalg.generic #trait_ss
103     ins(%arga: tensor<?x?xf32, #SparseMatrix>)
104    outs(%argx: tensor<?x?xf32>) {
105      ^bb(%a: f32, %x: f32):
106        %0 = mulf %a, %scale : f32
107        linalg.yield %0 : f32
108  } -> tensor<?x?xf32>
109  return %0 : tensor<?x?xf32>
110}
111
112#trait_matvec = {
113  indexing_maps = [
114    affine_map<(i,j) -> (i,j)>,  // A
115    affine_map<(i,j) -> (j)>,    // b
116    affine_map<(i,j) -> (i)>     // x (out)
117  ],
118  iterator_types = ["parallel", "reduction"],
119  doc = "x(i) += A(i,j) * b(j)"
120}
121
122//
123// CHECK-PAR0-LABEL: func @matvec
124// CHECK-PAR0:         scf.for
125// CHECK-PAR0:           scf.for
126// CHECK-PAR0:         return
127//
128// CHECK-PAR1-LABEL: func @matvec
129// CHECK-PAR1:         scf.parallel
130// CHECK-PAR1:           scf.for
131// CHECK-PAR1:         return
132//
133// CHECK-PAR2-LABEL: func @matvec
134// CHECK-PAR2:         scf.parallel
135// CHECK-PAR2:           scf.for
136// CHECK-PAR2:         return
137//
138// CHECK-PAR3-LABEL: func @matvec
139// CHECK-PAR3:         scf.parallel
140// CHECK-PAR3:           scf.for
141// CHECK-PAR3:         return
142//
143// CHECK-PAR4-LABEL: func @matvec
144// CHECK-PAR4:         scf.parallel
145// CHECK-PAR4:           scf.for
146// CHECK-PAR4:         return
147//
148func @matvec(%argA: tensor<16x32xf32, #CSR>, %argb: tensor<32xf32>, %argx: tensor<16xf32>) -> tensor<16xf32> {
149  %0 = linalg.generic #trait_matvec
150      ins(%argA, %argb : tensor<16x32xf32, #CSR>, tensor<32xf32>)
151     outs(%argx: tensor<16xf32>) {
152    ^bb(%A: f32, %b: f32, %x: f32):
153      %0 = mulf %A, %b : f32
154      %1 = addf %0, %x : f32
155      linalg.yield %1 : f32
156  } -> tensor<16xf32>
157  return %0 : tensor<16xf32>
158}
159