536 lines · plain
1// RUN: mlir-opt %s --sparse-reinterpret-map -sparsification -cse -sparse-vectorization="vl=8" -cse -split-input-file | \2// RUN: FileCheck %s --check-prefix=CHECK-ON3// RUN: mlir-opt %s --sparse-reinterpret-map -sparsification -cse -split-input-file | \4// RUN: FileCheck %s --check-prefix=CHECK-OFF5 6// -----7 8// Check that we vectorize reductions with ori.9 10// CHECK-ON-LABEL: func.func @sparse_reduction_ori(11// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<i13>,12// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xi13, #sparse{{[0-9]*}}>) -> tensor<i13> {13// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index14// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<8xi13>15// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index16// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index17// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xindex>18// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xi13>19// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i13> to memref<i13>20// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<i13>21// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>22// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>23// CHECK-ON: %[[VAL_12:.*]] = vector.broadcast %[[VAL_9]] : i13 to vector<8xi13>24// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xi13>) {25// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]26// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>27// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xi13>, vector<8xi1>, vector<8xi13> into vector<8xi13>28// CHECK-ON: %[[VAL_19:.*]] = arith.ori %[[VAL_15]], %[[VAL_18]] : vector<8xi13>29// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xi13>30// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xi13>31// CHECK-ON: } {"Emitted from" = "linalg.generic"}32// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <or>, %[[VAL_22:.*]] : vector<8xi13> into i1333// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<i13>34// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<i13>35// CHECK-ON: return %[[VAL_23]] : tensor<i13>36// CHECK-ON: }37//38// CHECK-OFF-LABEL: func.func @sparse_reduction_ori(39// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<i13>,40// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xi13, #sparse{{[0-9]*}}>) -> tensor<i13> {41// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index42// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index43// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xindex>44// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xi13>45// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i13> to memref<i13>46// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<i13>47// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>48// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>49// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (i13) {50// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xi13>51// CHECK-OFF: %[[VAL_14:.*]] = arith.ori %[[VAL_12]], %[[VAL_13]] : i1352// CHECK-OFF: scf.yield %[[VAL_14]] : i1353// CHECK-OFF: } {"Emitted from" = "linalg.generic"}54// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<i13>55// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<i13>56// CHECK-OFF: return %[[VAL_16]] : tensor<i13>57// CHECK-OFF: }58#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>59 60#trait = {61 indexing_maps = [62 affine_map<(i) -> (i)>, // a (in)63 affine_map<(i) -> ()> // x (out)64 ],65 iterator_types = ["reduction"]66}67 68func.func @sparse_reduction_ori(%argx: tensor<i13>,69 %arga: tensor<?xi13, #SparseVector>)70 -> tensor<i13> {71 %0 = linalg.generic #trait72 ins(%arga: tensor<?xi13, #SparseVector>)73 outs(%argx: tensor<i13>) {74 ^bb(%a: i13, %x: i13):75 %t = arith.ori %x, %a: i1376 linalg.yield %t : i1377 } -> tensor<i13>78 return %0 : tensor<i13>79}80 81// -----82 83// Same test as sparse_reduction_ori except that the accumulator is on the84// rhs of the operation. This checks that we can recognize a reduction85// irrespective to where the accumulator appears on commutative operations.86 87// CHECK-ON-LABEL: func.func @sparse_reduction_ori_accumulator_on_rhs(88// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<i13>,89// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xi13, #sparse{{[0-9]*}}>) -> tensor<i13> {90// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index91// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<8xi13>92// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index93// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index94// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xindex>95// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xi13>96// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i13> to memref<i13>97// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<i13>98// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>99// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>100// CHECK-ON: %[[VAL_12:.*]] = vector.broadcast %[[VAL_9]] : i13 to vector<8xi13>101// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xi13>) {102// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]103// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>104// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xi13>, vector<8xi1>, vector<8xi13> into vector<8xi13>105// CHECK-ON: %[[VAL_19:.*]] = arith.ori %[[VAL_18]], %[[VAL_15]] : vector<8xi13>106// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xi13>107// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xi13>108// CHECK-ON: } {"Emitted from" = "linalg.generic"}109// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <or>, %[[VAL_22:.*]] : vector<8xi13> into i13110// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<i13>111// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<i13>112// CHECK-ON: return %[[VAL_23]] : tensor<i13>113// CHECK-ON: }114//115// CHECK-OFF-LABEL: func.func @sparse_reduction_ori_accumulator_on_rhs(116// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<i13>,117// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xi13, #sparse{{[0-9]*}}>) -> tensor<i13> {118// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index119// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index120// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xindex>121// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi13, #sparse{{[0-9]*}}> to memref<?xi13>122// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i13> to memref<i13>123// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<i13>124// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>125// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>126// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (i13) {127// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xi13>128// CHECK-OFF: %[[VAL_14:.*]] = arith.ori %[[VAL_13]], %[[VAL_12]] : i13129// CHECK-OFF: scf.yield %[[VAL_14]] : i13130// CHECK-OFF: } {"Emitted from" = "linalg.generic"}131// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<i13>132// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<i13>133// CHECK-OFF: return %[[VAL_16]] : tensor<i13>134// CHECK-OFF: }135#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>136 137#trait = {138 indexing_maps = [139 affine_map<(i) -> (i)>, // a (in)140 affine_map<(i) -> ()> // x (out)141 ],142 iterator_types = ["reduction"]143}144 145func.func @sparse_reduction_ori_accumulator_on_rhs(%argx: tensor<i13>,146 %arga: tensor<?xi13, #SparseVector>)147 -> tensor<i13> {148 %0 = linalg.generic #trait149 ins(%arga: tensor<?xi13, #SparseVector>)150 outs(%argx: tensor<i13>) {151 ^bb(%a: i13, %x: i13):152 %t = arith.ori %a, %x: i13153 linalg.yield %t : i13154 } -> tensor<i13>155 return %0 : tensor<i13>156}157 158// -----159 160// Check that we vectorize reductions with subi.161//162// CHECK-ON-LABEL: func.func @sparse_reduction_subi(163// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<i32>,164// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {165// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index166// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant 0 : index167// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant dense<0> : vector<8xi32>168// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index169// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>170// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>171// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>172// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<i32>173// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_3]]] : memref<?xindex>174// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>175// CHECK-ON: %[[VAL_12:.*]] = vector.insert %[[VAL_9]], %[[VAL_4]] [0] : i32 into vector<8xi32>176// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xi32>) {177// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]178// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>179// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_4]] : memref<?xi32>, vector<8xi1>, vector<8xi32> into vector<8xi32>180// CHECK-ON: %[[VAL_19:.*]] = arith.subi %[[VAL_15]], %[[VAL_18]] : vector<8xi32>181// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xi32>182// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xi32>183// CHECK-ON: } {"Emitted from" = "linalg.generic"}184// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <add>, %[[VAL_22:.*]] : vector<8xi32> into i32185// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<i32>186// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<i32>187// CHECK-ON: return %[[VAL_23]] : tensor<i32>188// CHECK-ON: }189//190// CHECK-OFF-LABEL: func.func @sparse_reduction_subi(191// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<i32>,192// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {193// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index194// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index195// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>196// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>197// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>198// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<i32>199// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>200// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>201// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (i32) {202// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xi32>203// CHECK-OFF: %[[VAL_14:.*]] = arith.subi %[[VAL_12]], %[[VAL_13]] : i32204// CHECK-OFF: scf.yield %[[VAL_14]] : i32205// CHECK-OFF: } {"Emitted from" = "linalg.generic"}206// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<i32>207// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<i32>208// CHECK-OFF: return %[[VAL_16]] : tensor<i32>209// CHECK-OFF: }210#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>211 212#trait = {213 indexing_maps = [214 affine_map<(i) -> (i)>, // a (in)215 affine_map<(i) -> ()> // x (out)216 ],217 iterator_types = ["reduction"]218}219 220func.func @sparse_reduction_subi(%argx: tensor<i32>,221 %arga: tensor<?xi32, #SparseVector>)222 -> tensor<i32> {223 %0 = linalg.generic #trait224 ins(%arga: tensor<?xi32, #SparseVector>)225 outs(%argx: tensor<i32>) {226 ^bb(%a: i32, %x: i32):227 %t = arith.subi %x, %a: i32228 linalg.yield %t : i32229 } -> tensor<i32>230 return %0 : tensor<i32>231}232 233// -----234 235// Check that we vectorize reductions with xor.236 237// CHECK-ON-LABEL: func.func @sparse_reduction_xor(238// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<i32>,239// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {240// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index241// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<8xi32>242// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index243// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index244// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>245// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>246// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>247// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<i32>248// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>249// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>250// CHECK-ON: %[[VAL_12:.*]] = vector.insert %[[VAL_9]], %[[VAL_3]] [0] : i32 into vector<8xi32>251// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xi32>) {252// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]253// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>254// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xi32>, vector<8xi1>, vector<8xi32> into vector<8xi32>255// CHECK-ON: %[[VAL_19:.*]] = arith.xori %[[VAL_15]], %[[VAL_18]] : vector<8xi32>256// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xi32>257// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xi32>258// CHECK-ON: } {"Emitted from" = "linalg.generic"}259// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <xor>, %[[VAL_22:.*]] : vector<8xi32> into i32260// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<i32>261// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<i32>262// CHECK-ON: return %[[VAL_23]] : tensor<i32>263// CHECK-ON: }264//265// CHECK-OFF-LABEL: func.func @sparse_reduction_xor(266// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<i32>,267// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {268// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index269// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index270// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>271// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>272// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>273// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<i32>274// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>275// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>276// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (i32) {277// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xi32>278// CHECK-OFF: %[[VAL_14:.*]] = arith.xori %[[VAL_12]], %[[VAL_13]] : i32279// CHECK-OFF: scf.yield %[[VAL_14]] : i32280// CHECK-OFF: } {"Emitted from" = "linalg.generic"}281// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<i32>282// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<i32>283// CHECK-OFF: return %[[VAL_16]] : tensor<i32>284// CHECK-OFF: }285 286#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>287 288#trait = {289 indexing_maps = [290 affine_map<(i) -> (i)>, // a (in)291 affine_map<(i) -> ()> // x (out)292 ],293 iterator_types = ["reduction"]294}295 296func.func @sparse_reduction_xor(%argx: tensor<i32>,297 %arga: tensor<?xi32, #SparseVector>)298 -> tensor<i32> {299 %0 = linalg.generic #trait300 ins(%arga: tensor<?xi32, #SparseVector>)301 outs(%argx: tensor<i32>) {302 ^bb(%a: i32, %x: i32):303 %t = arith.xori %x, %a: i32304 linalg.yield %t : i32305 } -> tensor<i32>306 return %0 : tensor<i32>307}308 309// -----310 311// Check that we vectorize reductions with addi.312 313// CHECK-ON-LABEL: func.func @sparse_reduction_addi(314// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<i32>,315// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {316// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index317// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<8xi32>318// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index319// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index320// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>321// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>322// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>323// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<i32>324// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>325// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>326// CHECK-ON: %[[VAL_12:.*]] = vector.insert %[[VAL_9]], %[[VAL_3]] [0] : i32 into vector<8xi32>327// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xi32>) {328// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]329// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>330// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xi32>, vector<8xi1>, vector<8xi32> into vector<8xi32>331// CHECK-ON: %[[VAL_19:.*]] = arith.addi %[[VAL_15]], %[[VAL_18]] : vector<8xi32>332// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xi32>333// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xi32>334// CHECK-ON: } {"Emitted from" = "linalg.generic"}335// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <add>, %[[VAL_22:.*]] : vector<8xi32> into i32336// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<i32>337// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<i32>338// CHECK-ON: return %[[VAL_23]] : tensor<i32>339// CHECK-ON: }340//341// CHECK-OFF-LABEL: func.func @sparse_reduction_addi(342// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<i32>,343// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xi32, #sparse{{[0-9]*}}>) -> tensor<i32> {344// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index345// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index346// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xindex>347// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xi32, #sparse{{[0-9]*}}> to memref<?xi32>348// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<i32> to memref<i32>349// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<i32>350// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>351// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>352// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (i32) {353// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xi32>354// CHECK-OFF: %[[VAL_14:.*]] = arith.addi %[[VAL_12]], %[[VAL_13]] : i32355// CHECK-OFF: scf.yield %[[VAL_14]] : i32356// CHECK-OFF: } {"Emitted from" = "linalg.generic"}357// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<i32>358// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<i32>359// CHECK-OFF: return %[[VAL_16]] : tensor<i32>360// CHECK-OFF: }361 362#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>363 364#trait = {365 indexing_maps = [366 affine_map<(i) -> (i)>, // a (in)367 affine_map<(i) -> ()> // x (out)368 ],369 iterator_types = ["reduction"]370}371 372func.func @sparse_reduction_addi(%argx: tensor<i32>,373 %arga: tensor<?xi32, #SparseVector>)374 -> tensor<i32> {375 %0 = linalg.generic #trait376 ins(%arga: tensor<?xi32, #SparseVector>)377 outs(%argx: tensor<i32>) {378 ^bb(%a: i32, %x: i32):379 %t = arith.addi %x, %a: i32380 linalg.yield %t : i32381 } -> tensor<i32>382 return %0 : tensor<i32>383}384 385// -----386 387// Check that we vectorize reductions with subf.388 389// CHECK-ON-LABEL: func.func @sparse_reduction_subf(390// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<f32>,391// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xf32, #sparse{{[0-9]*}}>) -> tensor<f32> {392// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index393// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0.000000e+00> : vector<8xf32>394// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index395// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index396// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xindex>397// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xf32>398// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<f32> to memref<f32>399// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<f32>400// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>401// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>402// CHECK-ON: %[[VAL_12:.*]] = vector.insert %[[VAL_9]], %[[VAL_3]] [0] : f32 into vector<8xf32>403// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xf32>) {404// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]405// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>406// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xf32>, vector<8xi1>, vector<8xf32> into vector<8xf32>407// CHECK-ON: %[[VAL_19:.*]] = arith.subf %[[VAL_15]], %[[VAL_18]] : vector<8xf32>408// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xf32>409// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xf32>410// CHECK-ON: } {"Emitted from" = "linalg.generic"}411// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <add>, %[[VAL_22:.*]] : vector<8xf32> into f32412// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<f32>413// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<f32>414// CHECK-ON: return %[[VAL_23]] : tensor<f32>415// CHECK-ON: }416//417// CHECK-OFF-LABEL: func.func @sparse_reduction_subf(418// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<f32>,419// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xf32, #sparse{{[0-9]*}}>) -> tensor<f32> {420// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index421// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index422// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xindex>423// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xf32>424// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<f32> to memref<f32>425// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<f32>426// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>427// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>428// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (f32) {429// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xf32>430// CHECK-OFF: %[[VAL_14:.*]] = arith.subf %[[VAL_12]], %[[VAL_13]] : f32431// CHECK-OFF: scf.yield %[[VAL_14]] : f32432// CHECK-OFF: } {"Emitted from" = "linalg.generic"}433// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<f32>434// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<f32>435// CHECK-OFF: return %[[VAL_16]] : tensor<f32>436// CHECK-OFF: }437 438#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>439 440#trait = {441 indexing_maps = [442 affine_map<(i) -> (i)>, // a (in)443 affine_map<(i) -> ()> // x (out)444 ],445 iterator_types = ["reduction"]446}447 448func.func @sparse_reduction_subf(%argx: tensor<f32>,449 %arga: tensor<?xf32, #SparseVector>)450 -> tensor<f32> {451 %0 = linalg.generic #trait452 ins(%arga: tensor<?xf32, #SparseVector>)453 outs(%argx: tensor<f32>) {454 ^bb(%a: f32, %x: f32):455 %t = arith.subf %x, %a: f32456 linalg.yield %t : f32457 } -> tensor<f32>458 return %0 : tensor<f32>459}460 461// -----462 463// Check that we vectorize reductions with addf.464 465// CHECK-ON-LABEL: func.func @sparse_reduction_addf(466// CHECK-ON-SAME: %[[VAL_0:.*]]: tensor<f32>,467// CHECK-ON-SAME: %[[VAL_1:.*]]: tensor<?xf32, #sparse{{[0-9]*}}>) -> tensor<f32> {468// CHECK-ON-DAG: %[[VAL_2:.*]] = arith.constant 8 : index469// CHECK-ON-DAG: %[[VAL_3:.*]] = arith.constant dense<0.000000e+00> : vector<8xf32>470// CHECK-ON-DAG: %[[VAL_4:.*]] = arith.constant 0 : index471// CHECK-ON-DAG: %[[VAL_5:.*]] = arith.constant 1 : index472// CHECK-ON-DAG: %[[VAL_6:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xindex>473// CHECK-ON-DAG: %[[VAL_7:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xf32>474// CHECK-ON-DAG: %[[VAL_8:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<f32> to memref<f32>475// CHECK-ON: %[[VAL_9:.*]] = memref.load %[[VAL_8]][] : memref<f32>476// CHECK-ON: %[[VAL_10:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_4]]] : memref<?xindex>477// CHECK-ON: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_5]]] : memref<?xindex>478// CHECK-ON: %[[VAL_12:.*]] = vector.insert %[[VAL_9]], %[[VAL_3]] [0] : f32 into vector<8xf32>479// CHECK-ON: %[[VAL_13:.*]] = scf.for %[[VAL_14:.*]] = %[[VAL_10]] to %[[VAL_11]] step %[[VAL_2]] iter_args(%[[VAL_15:.*]] = %[[VAL_12]]) -> (vector<8xf32>) {480// CHECK-ON: %[[VAL_16:.*]] = affine.min #map(%[[VAL_11]], %[[VAL_14]]){{\[}}%[[VAL_2]]]481// CHECK-ON: %[[VAL_17:.*]] = vector.create_mask %[[VAL_16]] : vector<8xi1>482// CHECK-ON: %[[VAL_18:.*]] = vector.maskedload %[[VAL_7]]{{\[}}%[[VAL_14]]], %[[VAL_17]], %[[VAL_3]] : memref<?xf32>, vector<8xi1>, vector<8xf32> into vector<8xf32>483// CHECK-ON: %[[VAL_19:.*]] = arith.addf %[[VAL_15]], %[[VAL_18]] : vector<8xf32>484// CHECK-ON: %[[VAL_20:.*]] = arith.select %[[VAL_17]], %[[VAL_19]], %[[VAL_15]] : vector<8xi1>, vector<8xf32>485// CHECK-ON: scf.yield %[[VAL_20]] : vector<8xf32>486// CHECK-ON: } {"Emitted from" = "linalg.generic"}487// CHECK-ON: %[[VAL_21:.*]] = vector.reduction <add>, %[[VAL_22:.*]] : vector<8xf32> into f32488// CHECK-ON: memref.store %[[VAL_21]], %[[VAL_8]][] : memref<f32>489// CHECK-ON: %[[VAL_23:.*]] = bufferization.to_tensor %[[VAL_8]] : memref<f32>490// CHECK-ON: return %[[VAL_23]] : tensor<f32>491// CHECK-ON: }492//493// CHECK-OFF-LABEL: func.func @sparse_reduction_addf(494// CHECK-OFF-SAME: %[[VAL_0:.*]]: tensor<f32>,495// CHECK-OFF-SAME: %[[VAL_1:.*]]: tensor<?xf32, #sparse{{[0-9]*}}>) -> tensor<f32> {496// CHECK-OFF-DAG: %[[VAL_2:.*]] = arith.constant 0 : index497// CHECK-OFF-DAG: %[[VAL_3:.*]] = arith.constant 1 : index498// CHECK-OFF-DAG: %[[VAL_4:.*]] = sparse_tensor.positions %[[VAL_1]] {level = 0 : index} : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xindex>499// CHECK-OFF-DAG: %[[VAL_5:.*]] = sparse_tensor.values %[[VAL_1]] : tensor<?xf32, #sparse{{[0-9]*}}> to memref<?xf32>500// CHECK-OFF-DAG: %[[VAL_6:.*]] = bufferization.to_buffer %[[VAL_0]] : tensor<f32> to memref<f32>501// CHECK-OFF: %[[VAL_7:.*]] = memref.load %[[VAL_6]][] : memref<f32>502// CHECK-OFF: %[[VAL_8:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_2]]] : memref<?xindex>503// CHECK-OFF: %[[VAL_9:.*]] = memref.load %[[VAL_4]]{{\[}}%[[VAL_3]]] : memref<?xindex>504// CHECK-OFF: %[[VAL_10:.*]] = scf.for %[[VAL_11:.*]] = %[[VAL_8]] to %[[VAL_9]] step %[[VAL_3]] iter_args(%[[VAL_12:.*]] = %[[VAL_7]]) -> (f32) {505// CHECK-OFF: %[[VAL_13:.*]] = memref.load %[[VAL_5]]{{\[}}%[[VAL_11]]] : memref<?xf32>506// CHECK-OFF: %[[VAL_14:.*]] = arith.addf %[[VAL_12]], %[[VAL_13]] : f32507// CHECK-OFF: scf.yield %[[VAL_14]] : f32508// CHECK-OFF: } {"Emitted from" = "linalg.generic"}509// CHECK-OFF: memref.store %[[VAL_15:.*]], %[[VAL_6]][] : memref<f32>510// CHECK-OFF: %[[VAL_16:.*]] = bufferization.to_tensor %[[VAL_6]] : memref<f32>511// CHECK-OFF: return %[[VAL_16]] : tensor<f32>512// CHECK-OFF: }513 514#SparseVector = #sparse_tensor.encoding<{map = (d0) -> (d0 : compressed)}>515 516#trait = {517 indexing_maps = [518 affine_map<(i) -> (i)>, // a (in)519 affine_map<(i) -> ()> // x (out)520 ],521 iterator_types = ["reduction"]522}523 524func.func @sparse_reduction_addf(%argx: tensor<f32>,525 %arga: tensor<?xf32, #SparseVector>)526 -> tensor<f32> {527 %0 = linalg.generic #trait528 ins(%arga: tensor<?xf32, #SparseVector>)529 outs(%argx: tensor<f32>) {530 ^bb(%a: f32, %x: f32):531 %t = arith.addf %x, %a: f32532 linalg.yield %t : f32533 } -> tensor<f32>534 return %0 : tensor<f32>535}536