blob: ec9b60649191076d45d16537354b76deed2f24e7 [file] [log] [blame] [edit]
// RUN: mlir-opt -transform-interpreter -split-input-file -canonicalize -cse %s | FileCheck %s
func.func @gemm(%arg0 : memref<?x?xf32>, %arg1 : memref<?x?xf32>,
%arg2 : memref<?x?xf32>) {
linalg.matmul ins(%arg0, %arg1 : memref<?x?xf32>, memref<?x?xf32>)
outs(%arg2 : memref<?x?xf32>)
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%matmul = transform.structured.match ops{["linalg.matmul"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %matmul
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func @gemm
// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
// CHECK-DAG: %[[M:.+]] = memref.dim %[[ARG0]], %[[C0]]
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[K:.+]] = memref.dim %[[ARG0]], %[[C1]]
// CHECK-DAG: %[[N:.+]] = memref.dim %[[ARG1]], %[[C1]]
// CHECK: scf.for %[[IV0:[a-zA-Z0-9]+]] = %[[C0]] to %[[M]] step %[[C1]]
// CHECK: scf.for %[[IV1:[a-zA-Z0-9]+]] = %[[C0]] to %[[N]] step %[[C1]]
// CHECK: scf.for %[[IV2:[a-zA-Z0-9]+]] = %[[C0]] to %[[K]] step %[[C1]]
// CHECK-DAG: %[[LHS:.+]] = memref.load %[[ARG0]][%[[IV0]], %[[IV2]]]
// CHECK-DAG: %[[RHS:.+]] = memref.load %[[ARG1]][%[[IV2]], %[[IV1]]]
// CHECK-DAG: %[[OUT:.+]] = memref.load %[[ARG2]][%[[IV0]], %[[IV1]]]
// CHECK: %[[MULF:.+]] = arith.mulf %[[LHS]], %[[RHS]]
// CHECK: %[[ADDF:.+]] = arith.addf %[[OUT]], %[[MULF]]
// CHECK: memref.store %[[ADDF]], %[[ARG2]][%[[IV0]], %[[IV1]]]
// CHECK-NOT: linalg.matmul ins(%arg0, %arg1 : memref<?x?xf32>, memref<?x?xf32>)
// -----
func.func @gemm(%arg0 : memref<?x?xf32>, %arg1 : memref<?x?xf32>,
%arg2 : memref<?x?xf32>, %arg3 : memref<?xf32>, %arg4 : memref<?xf32>) {
linalg.matmul ins(%arg0, %arg1 : memref<?x?xf32>, memref<?x?xf32>)
outs(%arg2 : memref<?x?xf32>)
linalg.matvec ins(%arg0, %arg3 : memref<?x?xf32>, memref<?xf32>)
outs(%arg4 : memref<?xf32>)
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%linalg_ops = transform.structured.match interface{TilingInterface} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %linalg_ops
: (!transform.any_op) -> (!transform.any_op)
%1:5 = transform.split_handle %0
: (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func @gemm
// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: memref<?xf32>
// CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: memref<?xf32>
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
// CHECK-DAG: %[[M:.+]] = memref.dim %[[ARG0]], %[[C0]]
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[K:.+]] = memref.dim %[[ARG0]], %[[C1]]
// CHECK-DAG: %[[N:.+]] = memref.dim %[[ARG1]], %[[C1]]
// CHECK: scf.for %[[IV0:[a-zA-Z0-9]+]] = %[[C0]] to %[[M]] step %[[C1]]
// CHECK: scf.for %[[IV1:[a-zA-Z0-9]+]] = %[[C0]] to %[[N]] step %[[C1]]
// CHECK: scf.for %[[IV2:[a-zA-Z0-9]+]] = %[[C0]] to %[[K]] step %[[C1]]
// CHECK-DAG: %[[LHS:.+]] = memref.load %[[ARG0]][%[[IV0]], %[[IV2]]]
// CHECK-DAG: %[[RHS:.+]] = memref.load %[[ARG1]][%[[IV2]], %[[IV1]]]
// CHECK-DAG: %[[OUT:.+]] = memref.load %[[ARG2]][%[[IV0]], %[[IV1]]]
// CHECK: %[[MULF:.+]] = arith.mulf %[[LHS]], %[[RHS]]
// CHECK: %[[ADDF:.+]] = arith.addf %[[OUT]], %[[MULF]]
// CHECK: memref.store %[[ADDF]], %[[ARG2]][%[[IV0]], %[[IV1]]]
// CHECK: scf.for %[[IV3:[a-zA-Z0-9]+]] = %[[C0]] to %[[M]] step %[[C1]]
// CHECK: scf.for %[[IV4:[a-zA-Z0-9]+]] = %[[C0]] to %[[K]] step %[[C1]]
// CHECK-DAG: %[[LHS:.+]] = memref.load %[[ARG0]][%[[IV3]], %[[IV4]]]
// CHECK-DAG: %[[RHS:.+]] = memref.load %[[ARG3]][%[[IV4]]]
// CHECK-DAG: %[[OUT:.+]] = memref.load %[[ARG4]][%[[IV3]]]
// CHECK: %[[MULF:.+]] = arith.mulf %[[LHS]], %[[RHS]]
// CHECK: %[[ADDF:.+]] = arith.addf %[[OUT]], %[[MULF]]
// CHECK: memref.store %[[ADDF]], %[[ARG4]][%[[IV3]]]
// -----
func.func @indexed_generic(%arg0 : memref<200x300xi32>, %arg1 : memref<300xi16>,
%arg2 : memref<200xi8>, %arg3 : memref<300x200xi64>) {
linalg.generic {
indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d1)>,
affine_map<(d0, d1) -> (d0)>, affine_map<(d0, d1) -> (d1, d0)>],
iterator_types = ["parallel", "parallel"]}
ins(%arg0, %arg1, %arg2 : memref<200x300xi32>, memref<300xi16>, memref<200xi8>)
outs(%arg3 : memref<300x200xi64>) {
^bb0(%b0 : i32, %b1 : i16, %b2 : i8, %b3 : i64):
%0 = linalg.index 0 : index
%1 = arith.index_cast %0 : index to i16
%2 = arith.muli %b1, %1 : i16
%3 = linalg.index 1 : index
%4 = arith.index_cast %3 : index to i8
%5 = arith.muli %b2, %4 : i8
%6 = arith.extsi %2 : i16 to i32
%7 = arith.extsi %5 : i8 to i32
%8 = arith.addi %6, %7 : i32
%9 = arith.addi %8, %b0 : i32
%10 = arith.extsi %9 : i32 to i64
linalg.yield %10 : i64
}
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%generic = transform.structured.match ops{["linalg.generic"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %generic
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func @indexed_generic
// CHECK-SAME: %[[ARG0:.+]]: memref<200x300xi32>
// CHECK-SAME: %[[ARG1:.+]]: memref<300xi16>
// CHECK-SAME: %[[ARG2:.+]]: memref<200xi8>
// CHECK-SAME: %[[ARG3:.+]]: memref<300x200xi64>
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[C200:.+]] = arith.constant 200 : index
// CHECK-DAG: %[[C300:.+]] = arith.constant 300 : index
// CHECK: scf.for %[[IV0:[a-zA-Z0-9]+]] = %[[C0]] to %[[C200]] step %[[C1]]
// CHECK: scf.for %[[IV1:[a-zA-Z0-9]+]] = %[[C0]] to %[[C300]] step %[[C1]]
// CHECK-DAG: %[[B0:.+]] = memref.load %[[ARG0]][%[[IV0]], %[[IV1]]]
// CHECK-DAG: %[[B1:.+]] = memref.load %[[ARG1]][%[[IV1]]]
// CHECK-DAG: %[[B2:.+]] = memref.load %[[ARG2]][%[[IV0]]]
// CHECK: %[[T1:.+]] = arith.index_cast %[[IV0]]
// CHECK: %[[T2:.+]] = arith.muli %[[B1]], %[[T1]]
// CHECK: %[[T4:.+]] = arith.index_cast %[[IV1]]
// CHECK: %[[T5:.+]] = arith.muli %[[B2]], %[[T4]]
// CHECK: %[[T6:.+]] = arith.extsi %[[T2]]
// CHECK: %[[T7:.+]] = arith.extsi %[[T5]]
// CHECK: %[[T8:.+]] = arith.addi %[[T6]], %[[T7]]
// CHECK: %[[T9:.+]] = arith.addi %[[T8]], %[[B0]]
// CHECK: %[[T10:.+]] = arith.extsi %[[T9]]
// CHECK: memref.store %[[T10]], %[[ARG3]][%[[IV1]], %[[IV0]]]
// -----
func.func @conv_strides_and_dilation(%arg0 : memref<?x?x?x?xf32>, %arg1 : memref<?x?x?x?xf32>,
%arg2 : memref<?x?x?x?xf32>) {
linalg.conv_2d_nhwc_hwcf {
strides = dense<[1, 2]> : tensor<2xi64>,
dilations = dense<[3, 4]> : tensor<2xi64>}
ins(%arg0, %arg1 : memref<?x?x?x?xf32>, memref<?x?x?x?xf32>)
outs(%arg2 : memref<?x?x?x?xf32>)
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%conv = transform.structured.match ops{["linalg.conv_2d_nhwc_hwcf"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %conv
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0 + d1 * 3)>
// CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0 * 2 + d1 * 4)>
// CHECK: func @conv_strides_and_dilation(
// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index
// CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index
// CHECK-DAG: %[[N:.+]] = memref.dim %[[ARG0]], %[[C0]]
// CHECK-DAG: %[[C:.+]] = memref.dim %[[ARG0]], %[[C3]]
// CHECK-DAG: %[[H:.+]] = memref.dim %[[ARG1]], %[[C0]]
// CHECK-DAG: %[[W:.+]] = memref.dim %[[ARG1]], %[[C1]]
// CHECK-DAG: %[[F:.+]] = memref.dim %[[ARG1]], %[[C3]]
// CHECK-DAG: %[[P:.+]] = memref.dim %[[ARG2]], %[[C1]]
// CHECK-DAG: %[[Q:.+]] = memref.dim %[[ARG2]], %[[C2]]
// CHECK: scf.for %[[IV0:[a-zA-Z0-9]+]] = %[[C0]] to %[[N]] step %[[C1]]
// CHECK: scf.for %[[IV1:[a-zA-Z0-9]+]] = %[[C0]] to %[[P]] step %[[C1]]
// CHECK: scf.for %[[IV2:[a-zA-Z0-9]+]] = %[[C0]] to %[[Q]] step %[[C1]]
// CHECK: scf.for %[[IV3:[a-zA-Z0-9]+]] = %[[C0]] to %[[F]] step %[[C1]]
// CHECK: scf.for %[[IV4:[a-zA-Z0-9]+]] = %[[C0]] to %[[H]] step %[[C1]]
// CHECK: scf.for %[[IV5:[a-zA-Z0-9]+]] = %[[C0]] to %[[W]] step %[[C1]]
// CHECK: scf.for %[[IV6:[a-zA-Z0-9]+]] = %[[C0]] to %[[C]] step %[[C1]]
// CHECK-DAG: %[[I:.+]] = affine.apply #[[MAP0]](%[[IV1]], %[[IV4]])
// CHECK-DAG: %[[J:.+]] = affine.apply #[[MAP1]](%[[IV2]], %[[IV5]])
// CHECK-DAG: %[[T9:.+]] = memref.load %[[ARG0]][%[[IV0]], %[[I]], %[[J]], %[[IV6]]]
// CHECK-DAG: %[[T10:.+]] = memref.load %[[ARG1]][%[[IV4]], %[[IV5]], %[[IV6]], %[[IV3]]]
// CHECK-DAG: %[[T11:.+]] = memref.load %[[ARG2]][%[[IV0]], %[[IV1]], %[[IV2]], %[[IV3]]]
// CHECK: %[[T12:.+]] = arith.mulf %[[T9]], %[[T10]]
// CHECK: %[[T13:.+]] = arith.addf %[[T11]], %[[T12]]
// CHECK: memref.store %[[T13]], %[[ARG2]][%[[IV0]], %[[IV1]], %[[IV2]], %[[IV3]]]
// -----
func.func @pool_strides_and_dilation(%arg0 : memref<?x?x?x?xf32>, %arg1 : memref<?x?xf32>,
%arg2 : memref<?x?x?x?xf32>) {
linalg.pooling_nhwc_max {
strides = dense<[1, 2]> : tensor<2xi64>,
dilations = dense<[3, 4]> : tensor<2xi64>}
ins(%arg0, %arg1 : memref<?x?x?x?xf32>, memref<?x?xf32>)
outs(%arg2 : memref<?x?x?x?xf32>)
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%pool = transform.structured.match ops{["linalg.pooling_nhwc_max"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %pool
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0 + d1 * 3)>
// CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0 * 2 + d1 * 4)>
// CHECK: func @pool_strides_and_dilation
// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: memref<?x?xf32>
// CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index
// CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index
// CHECK-DAG: %[[N:.+]] = memref.dim %[[ARG0]], %[[C0]]
// CHECK-DAG: %[[C:.+]] = memref.dim %[[ARG0]], %[[C3]]
// CHECK-DAG: %[[H:.+]] = memref.dim %[[ARG1]], %[[C0]]
// CHECK-DAG: %[[W:.+]] = memref.dim %[[ARG1]], %[[C1]]
// CHECK-DAG: %[[P:.+]] = memref.dim %[[ARG2]], %[[C1]]
// CHECK-DAG: %[[Q:.+]] = memref.dim %[[ARG2]], %[[C2]]
// CHECK: scf.for %[[IV0:[a-zA-Z0-9]+]] = %[[C0]] to %[[N]] step %[[C1]]
// CHECK: scf.for %[[IV1:[a-zA-Z0-9]+]] = %[[C0]] to %[[P]] step %[[C1]]
// CHECK: scf.for %[[IV2:[a-zA-Z0-9]+]] = %[[C0]] to %[[Q]] step %[[C1]]
// CHECK: scf.for %[[IV3:[a-zA-Z0-9]+]] = %[[C0]] to %[[C]] step %[[C1]]
// CHECK: scf.for %[[IV4:[a-zA-Z0-9]+]] = %[[C0]] to %[[H]] step %[[C1]]
// CHECK: scf.for %[[IV5:[a-zA-Z0-9]+]] = %[[C0]] to %[[W]] step %[[C1]]
// CHECK-DAG: %[[I:.+]] = affine.apply #[[MAP0]](%[[IV1]], %[[IV4]])
// CHECK-DAG: %[[J:.+]] = affine.apply #[[MAP1]](%[[IV2]], %[[IV5]])
// CHECK-DAG: %[[T8:.+]] = memref.load %[[ARG0]][%[[IV0]], %[[I]], %[[J]], %[[IV3]]]
// CHECK-DAG: %[[T9:.+]] = memref.load %[[ARG2]][%[[IV0]], %[[IV1]], %[[IV2]], %[[IV3]]]
// CHECK: %[[T10:.+]] = arith.maximumf %[[T9]], %[[T8]]
// CHECK: memref.store %[[T10]], %[[ARG2]][%[[IV0]], %[[IV1]], %[[IV2]], %[[IV3]]]
// -----
func.func @map(%lhs: memref<64xf32>,
%rhs: memref<64xf32>, %init: memref<64xf32>) {
linalg.map ins(%lhs, %rhs : memref<64xf32>, memref<64xf32>)
outs(%init : memref<64xf32>)
(%in: f32, %in_0: f32, %out: f32) {
%0 = arith.addf %in, %in_0 : f32
linalg.yield %0 : f32
}
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%map = transform.structured.match ops{["linalg.map"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %map
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func.func @map(
// CHECK-SAME: %[[LHS:[a-zA-Z0-9]+]]: memref<64xf32>,
// CHECK-SAME: %[[RHS:[a-zA-Z0-9]+]]: memref<64xf32>,
// CHECK-SAME: %[[OUT:[a-zA-Z0-9]+]]: memref<64xf32>) {
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C64:.*]] = arith.constant 64 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C64]] step %[[C1]] {
// CHECK: %[[LHS_ELEM:.*]] = memref.load %[[LHS]][%[[I]]]
// CHECK: %[[RHS_ELEM:.*]] = memref.load %[[RHS]][%[[I]]]
// CHECK: %[[ADD:.*]] = arith.addf %[[LHS_ELEM]], %[[RHS_ELEM]]
// CHECK: memref.store %[[ADD]], %[[OUT]][%[[I]]]
// -----
func.func @transpose(%arg0: memref<16x32x64xf32>,
%arg1: memref<32x64x16xf32>) {
linalg.transpose ins(%arg0 : memref<16x32x64xf32>)
outs(%arg1 : memref<32x64x16xf32>) permutation = [1, 2, 0]
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%transpose = transform.structured.match ops{["linalg.transpose"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %transpose
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func.func @transpose(
// CHECK-SAME: %[[IN:[a-zA-Z0-9]+]]: memref<16x32x64xf32>,
// CHECK-SAME: %[[OUT:[a-zA-Z0-9]+]]: memref<32x64x16xf32>)
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C16:.*]] = arith.constant 16 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK-DAG: %[[C64:.*]] = arith.constant 64 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C64]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C16]] step %[[C1]] {
// CHECK: %[[ELEM:.*]] = memref.load %[[IN]][%[[K]], %[[I]], %[[J]]]
// CHECK: memref.store %[[ELEM]], %[[OUT]][%[[I]], %[[J]], %[[K]]]
// -----
func.func @reduce(%arg0: memref<16x32x64xf32>,
%arg1: memref<16x64xf32>) {
linalg.reduce ins(%arg0 : memref<16x32x64xf32>)
outs(%arg1 : memref<16x64xf32>) dimensions = [1]
(%in: f32, %init: f32) {
%0 = arith.addf %in, %init : f32
linalg.yield %0 : f32
}
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%reduce = transform.structured.match ops{["linalg.reduce"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %reduce
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func.func @reduce(
// CHECK-SAME: %[[IN:[a-zA-Z0-9]+]]: memref<16x32x64xf32>,
// CHECK-SAME: %[[OUT:[a-zA-Z0-9]+]]: memref<16x64xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C16:.*]] = arith.constant 16 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK-DAG: %[[C64:.*]] = arith.constant 64 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C16]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C64]] step %[[C1]] {
// CHECK: %[[IN_ELEM:.*]] = memref.load %[[IN]][%[[I]], %[[J]], %[[K]]]
// CHECK: %[[OUT_ELEM:.*]] = memref.load %[[OUT]][%[[I]], %[[K]]]
// CHECK: %[[ADD:.*]] = arith.addf %[[IN_ELEM]], %[[OUT_ELEM]]
// CHECK: memref.store %[[ADD]], %[[OUT]][%[[I]], %[[K]]]
// -----
func.func @broadcast(%input: memref<8x32xf32>,
%init: memref<8x16x32xf32>) {
linalg.broadcast
ins(%input:memref<8x32xf32>)
outs(%init:memref<8x16x32xf32>)
dimensions = [1]
func.return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%broadcast = transform.structured.match ops{["linalg.broadcast"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %broadcast
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-LABEL: func.func @broadcast(
// CHECK-SAME: %[[IN:[a-zA-Z0-9]+]]: memref<8x32xf32>,
// CHECK-SAME: %[[OUT:[a-zA-Z0-9]+]]: memref<8x16x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index
// CHECK-DAG: %[[C16:.*]] = arith.constant 16 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C16]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: %[[ELEM:.*]] = memref.load %[[IN]][%[[I]], %[[K]]]
// CHECK: memref.store %[[ELEM]], %[[OUT]][%[[I]], %[[J]], %[[K]]]
// -----
func.func @NC_to_NCnc(%arg0: memref<128x256xf32>, %arg1: memref<4x8x32x32xf32>) {
linalg.pack %arg0 inner_dims_pos = [0, 1] inner_tiles = [32, 32] into %arg1
: memref<128x256xf32> -> memref<4x8x32x32xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%pack = transform.structured.match ops{["linalg.pack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %pack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK: #[[$MAP:.*]] = affine_map<(d0, d1) -> (d0 * 32 + d1)>
// CHECK-LABEL: func @NC_to_NCnc(
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<4x8x32x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index
// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C4]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[L:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK-DAG: %[[SRC_I:.*]] = affine.apply #[[$MAP]](%[[I]], %[[K]])
// CHECK-DAG: %[[SRC_J:.*]] = affine.apply #[[$MAP]](%[[J]], %[[L]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[SRC_I]], %[[SRC_J]]] : memref<128x256xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]], %[[K]], %[[L]]] : memref<4x8x32x32xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: }
// -----
func.func @NC_to_NCnc_pad(%arg0: memref<13x15xf32>, %arg1: memref<2x8x8x2xf32>, %arg2: f32) {
linalg.pack %arg0 padding_value(%arg2 : f32) inner_dims_pos = [0, 1] inner_tiles = [8, 2]
into %arg1 : memref<13x15xf32> -> memref<2x8x8x2xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%pack = transform.structured.match ops{["linalg.pack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %pack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1) -> (d0 * 8 + d1)>
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1) -> (d0 * 2 + d1)>
// CHECK-LABEL: func @NC_to_NCnc_pad(
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<13x15xf32>
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<2x8x8x2xf32>
// CHECK-SAME: %[[PAD:[a-zA-Z0-9]+]]: f32
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index
// CHECK-DAG: %[[C13:.*]] = arith.constant 13 : index
// CHECK-DAG: %[[C15:.*]] = arith.constant 15 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C2]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK: scf.for %[[L:.*]] = %[[C0]] to %[[C2]] step %[[C1]] {
// CHECK-DAG: %[[SRC_I:.*]] = affine.apply #[[$MAP0]](%[[I]], %[[K]])
// CHECK-DAG: %[[SRC_J:.*]] = affine.apply #[[$MAP1]](%[[J]], %[[L]])
// CHECK: %[[BOUND_I:.*]] = arith.cmpi slt, %[[SRC_I]], %[[C13]] : index
// CHECK: %[[BOUND_J:.*]] = arith.cmpi slt, %[[SRC_J]], %[[C15]] : index
// CHECK: %[[IN_BOUNDS:.*]] = arith.andi %[[BOUND_I]], %[[BOUND_J]] : i1
// CHECK: %[[VAL:.*]] = scf.if %[[IN_BOUNDS]] -> (f32) {
// CHECK: %[[LOAD:.*]] = memref.load %[[SRC]][%[[SRC_I]], %[[SRC_J]]] : memref<13x15xf32>
// CHECK: scf.yield %[[LOAD]]
// CHECK: } else {
// CHECK: scf.yield %[[PAD]]
// CHECK: }
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]], %[[K]], %[[L]]] : memref<2x8x8x2xf32>
// -----
func.func @KC_to_KCck(%arg0: memref<128x256xf32>, %arg1: memref<4x8x32x32xf32>) {
linalg.pack %arg0 inner_dims_pos = [1, 0] inner_tiles = [32, 32] into %arg1
: memref<128x256xf32> -> memref<4x8x32x32xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%pack = transform.structured.match ops{["linalg.pack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %pack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK: #[[$MAP:.*]] = affine_map<(d0, d1) -> (d0 * 32 + d1)>
// CHECK-LABEL: func @KC_to_KCck(
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<4x8x32x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index
// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C4]] step %[[C1]] {
// CHECK: scf.for %[[C:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK: scf.for %[[c:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[k:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK-DAG: %[[SRC_C:.*]] = affine.apply #[[$MAP]](%[[C]], %[[c]])
// CHECK-DAG: %[[SRC_K:.*]] = affine.apply #[[$MAP]](%[[K]], %[[k]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[SRC_K]], %[[SRC_C]]] : memref<128x256xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[K]], %[[C]], %[[c]], %[[k]]] : memref<4x8x32x32xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: }
// -----
func.func @NCnc_to_NC(%arg0: memref<128x256xf32>, %arg1: memref<4x8x32x32xf32>) {
linalg.unpack %arg1 inner_dims_pos = [0, 1] inner_tiles = [32, 32] into %arg0
: memref<4x8x32x32xf32> -> memref<128x256xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP_FLOOR:.*]] = affine_map<(d0) -> (d0 floordiv 32)>
// CHECK-DAG: #[[$MAP_MOD:.*]] = affine_map<(d0) -> (d0 mod 32)>
// CHECK-LABEL: func @NCnc_to_NC(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<4x8x32x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C128:.*]] = arith.constant 128 : index
// CHECK-DAG: %[[C256:.*]] = arith.constant 256 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C128]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C256]] step %[[C1]] {
// CHECK-DAG: %[[FLOOR_I:.*]] = affine.apply #[[$MAP_FLOOR]](%[[I]])
// CHECK-DAG: %[[FLOOR_J:.*]] = affine.apply #[[$MAP_FLOOR]](%[[J]])
// CHECK-DAG: %[[MOD_I:.*]] = affine.apply #[[$MAP_MOD]](%[[I]])
// CHECK-DAG: %[[MOD_J:.*]] = affine.apply #[[$MAP_MOD]](%[[J]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[FLOOR_I]], %[[FLOOR_J]], %[[MOD_I]], %[[MOD_J]]] : memref<4x8x32x32xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]]] : memref<128x256xf32>
// CHECK: }
// CHECK: }
// -----
func.func @KCck_to_KC(%arg0: memref<128x256xf32>, %arg1: memref<4x8x32x32xf32>) {
linalg.unpack %arg1 inner_dims_pos = [1, 0] inner_tiles = [32, 32] into %arg0
: memref<4x8x32x32xf32> -> memref<128x256xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP_FLOOR:.*]] = affine_map<(d0) -> (d0 floordiv 32)>
// CHECK-DAG: #[[$MAP_MOD:.*]] = affine_map<(d0) -> (d0 mod 32)>
// CHECK-LABEL: func @KCck_to_KC(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<4x8x32x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C128:.*]] = arith.constant 128 : index
// CHECK-DAG: %[[C256:.*]] = arith.constant 256 : index
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[C128]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[C256]] step %[[C1]] {
// CHECK-DAG: %[[FLOOR_I:.*]] = affine.apply #[[$MAP_FLOOR]](%[[I]])
// CHECK-DAG: %[[FLOOR_J:.*]] = affine.apply #[[$MAP_FLOOR]](%[[J]])
// CHECK-DAG: %[[MOD_I:.*]] = affine.apply #[[$MAP_MOD]](%[[I]])
// CHECK-DAG: %[[MOD_J:.*]] = affine.apply #[[$MAP_MOD]](%[[J]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[FLOOR_I]], %[[FLOOR_J]], %[[MOD_J]], %[[MOD_I]]] : memref<4x8x32x32xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]]] : memref<128x256xf32>
// CHECK: }
// CHECK: }
// -----
func.func @KC_to_CKkc(%arg0: memref<128x256xf32>, %arg1: memref<32x4x32x8xf32>) {
linalg.pack %arg0 outer_dims_perm = [1, 0] inner_dims_pos = [0, 1] inner_tiles = [32, 8]
into %arg1 : memref<128x256xf32> -> memref<32x4x32x8xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%pack = transform.structured.match ops{["linalg.pack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %pack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1) -> (d0 * 32 + d1)>
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1) -> (d0 * 8 + d1)>
// CHECK-LABEL: func @KC_to_CKkc(
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<32x4x32x8xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index
// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index
// CHECK-DAG: %[[C32:.*]] = arith.constant 32 : index
// CHECK: scf.for %[[C:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C4]] step %[[C1]] {
// CHECK: scf.for %[[k:.*]] = %[[C0]] to %[[C32]] step %[[C1]] {
// CHECK: scf.for %[[c:.*]] = %[[C0]] to %[[C8]] step %[[C1]] {
// CHECK-DAG: %[[SRC_K:.*]] = affine.apply #[[$MAP0]](%[[K]], %[[k]])
// CHECK-DAG: %[[SRC_C:.*]] = affine.apply #[[$MAP1]](%[[C]], %[[c]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[SRC_K]], %[[SRC_C]]] : memref<128x256xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[C]], %[[K]], %[[k]], %[[c]]] : memref<32x4x32x8xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: }
// -----
func.func @CKkc_to_KC(%arg0: memref<128x256xf32>, %arg1: memref<32x4x32x8xf32>) {
linalg.unpack %arg1 outer_dims_perm = [1, 0] inner_dims_pos = [0, 1] inner_tiles = [32, 8]
into %arg0 : memref<32x4x32x8xf32> -> memref<128x256xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0) -> (d0 floordiv 32)>
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0) -> (d0 mod 32)>
// CHECK-DAG: #[[$MAP2:.*]] = affine_map<(d0) -> (d0 floordiv 8)>
// CHECK-DAG: #[[$MAP3:.*]] = affine_map<(d0) -> (d0 mod 8)>
// CHECK-LABEL: func @CKkc_to_KC(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<128x256xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<32x4x32x8xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C128:.*]] = arith.constant 128 : index
// CHECK-DAG: %[[C256:.*]] = arith.constant 256 : index
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C128]] step %[[C1]] {
// CHECK: scf.for %[[C:.*]] = %[[C0]] to %[[C256]] step %[[C1]] {
// CHECK-DAG: %[[FLOOR_K:.*]] = affine.apply #[[$MAP0]](%[[K]])
// CHECK-DAG: %[[MOD_K:.*]] = affine.apply #[[$MAP1]](%[[K]])
// CHECK-DAG: %[[FLOOR_C:.*]] = affine.apply #[[$MAP2]](%[[C]])
// CHECK-DAG: %[[MOD_C:.*]] = affine.apply #[[$MAP3]](%[[C]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[FLOOR_C]], %[[FLOOR_K]], %[[MOD_K]], %[[MOD_C]]] : memref<32x4x32x8xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[K]], %[[C]]] : memref<128x256xf32>
// CHECK: }
// CHECK: }
// -----
func.func @KCRSsr_to_KCRS_static(%arg0: memref<1x1x128x64xf32>, %arg1: memref<1x1x4x8x8x32xf32>) {
linalg.unpack %arg1 inner_dims_pos = [3, 2] inner_tiles = [8, 32] into %arg0
: memref<1x1x4x8x8x32xf32> -> memref<1x1x128x64xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP_FLOORK:.*]] = affine_map<(d0) -> (d0 floordiv 32)>
// CHECK-DAG: #[[$MAP_MODK:.*]] = affine_map<(d0) -> (d0 mod 32)>
// CHECK-DAG: #[[$MAP_FLOORL:.*]] = affine_map<(d0) -> (d0 floordiv 8)>
// CHECK-DAG: #[[$MAP_MODL:.*]] = affine_map<(d0) -> (d0 mod 8)>
// CHECK-LABEL: func @KCRSsr_to_KCRS_static(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<1x1x128x64xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<1x1x4x8x8x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C64:.*]] = arith.constant 64 : index
// CHECK-DAG: %[[C128:.*]] = arith.constant 128 : index
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[C128]] step %[[C1]] {
// CHECK: scf.for %[[L:.*]] = %[[C0]] to %[[C64]] step %[[C1]] {
// CHECK-DAG: %[[FLOORK:.*]] = affine.apply #[[$MAP_FLOORK]](%[[K]])
// CHECK-DAG: %[[FLOORL:.*]] = affine.apply #[[$MAP_FLOORL]](%[[L]])
// CHECK-DAG: %[[MODK:.*]] = affine.apply #[[$MAP_MODK]](%[[K]])
// CHECK-DAG: %[[MODL:.*]] = affine.apply #[[$MAP_MODL]](%[[L]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[C0]], %[[C0]], %[[FLOORK]], %[[FLOORL]], %[[MODL]], %[[MODK]]] : memref<1x1x4x8x8x32xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[C0]], %[[C0]], %[[K]], %[[L]]] : memref<1x1x128x64xf32>
// CHECK: }
// CHECK: }
// -----
func.func @KCRSsr_to_KCRS_dynamic_with_static_inner_tiles(%arg0: memref<?x?x?x?xf32>, %arg1: memref<?x?x?x?x8x32xf32>) {
linalg.unpack %arg1 inner_dims_pos = [3, 2] inner_tiles = [8, 32] into %arg0
: memref<?x?x?x?x8x32xf32> -> memref<?x?x?x?xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP_FLOORK:.*]] = affine_map<(d0) -> (d0 floordiv 32)>
// CHECK-DAG: #[[$MAP_MODK:.*]] = affine_map<(d0) -> (d0 mod 32)>
// CHECK-DAG: #[[$MAP_FLOORL:.*]] = affine_map<(d0) -> (d0 floordiv 8)>
// CHECK-DAG: #[[$MAP_MODL:.*]] = affine_map<(d0) -> (d0 mod 8)>
// CHECK-LABEL: func @KCRSsr_to_KCRS_dynamic_with_static_inner_tiles(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<?x?x?x?x8x32xf32>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
// CHECK-DAG: %[[C3:.*]] = arith.constant 3 : index
// CHECK-DAG: %[[UBI:.*]] = memref.dim %[[DEST]], %[[C0]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBJ:.*]] = memref.dim %[[DEST]], %[[C1]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBK:.*]] = memref.dim %[[DEST]], %[[C2]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBL:.*]] = memref.dim %[[DEST]], %[[C3]] : memref<?x?x?x?xf32>
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[UBI]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[UBJ]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[UBK]] step %[[C1]] {
// CHECK: scf.for %[[L:.*]] = %[[C0]] to %[[UBL]] step %[[C1]] {
// CHECK-DAG: %[[FLOORK:.*]] = affine.apply #[[$MAP_FLOORK]](%[[K]])
// CHECK-DAG: %[[FLOORL:.*]] = affine.apply #[[$MAP_FLOORL]](%[[L]])
// CHECK-DAG: %[[MODK:.*]] = affine.apply #[[$MAP_MODK]](%[[K]])
// CHECK-DAG: %[[MODL:.*]] = affine.apply #[[$MAP_MODL]](%[[L]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[I]], %[[J]], %[[FLOORK]], %[[FLOORL]], %[[MODL]], %[[MODK]]] : memref<?x?x?x?x8x32xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]], %[[K]], %[[L]]] : memref<?x?x?x?xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: }
// -----
func.func @KCRSsr_to_KCRS_dynamic_with_dynamic_inner_tiles(%arg0: memref<?x?x?x?xf32>, %arg1: memref<?x?x?x?x8x?xf32>, %block : index) {
linalg.unpack %arg1 inner_dims_pos = [3, 2] inner_tiles = [8, %block] into %arg0
: memref<?x?x?x?x8x?xf32> -> memref<?x?x?x?xf32>
return
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg1 : !transform.any_op {transform.readonly}) {
%unpack = transform.structured.match ops{["linalg.unpack"]} in %arg1
: (!transform.any_op) -> !transform.any_op
%0 = transform.structured.convert_to_loops %unpack
: (!transform.any_op) -> (!transform.any_op)
transform.yield
}
}
// CHECK-DAG: #[[$MAP_FLOORK:.*]] = affine_map<(d0)[s0] -> (d0 floordiv s0)>
// CHECK-DAG: #[[$MAP_MODK:.*]] = affine_map<(d0)[s0] -> (d0 mod s0)>
// CHECK-DAG: #[[$MAP_FLOORL:.*]] = affine_map<(d0) -> (d0 floordiv 8)>
// CHECK-DAG: #[[$MAP_MODL:.*]] = affine_map<(d0) -> (d0 mod 8)>
// CHECK-LABEL: func @KCRSsr_to_KCRS_dynamic_with_dynamic_inner_tiles(
// CHECK-SAME: %[[DEST:[a-zA-Z0-9]+]]: memref<?x?x?x?xf32>
// CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]]: memref<?x?x?x?x8x?xf32>
// CHECK-SAME: %[[TILE:[a-zA-Z0-9]+]]: index
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index
// CHECK-DAG: %[[C3:.*]] = arith.constant 3 : index
// CHECK-DAG: %[[UBI:.*]] = memref.dim %[[DEST]], %[[C0]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBJ:.*]] = memref.dim %[[DEST]], %[[C1]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBK:.*]] = memref.dim %[[DEST]], %[[C2]] : memref<?x?x?x?xf32>
// CHECK-DAG: %[[UBL:.*]] = memref.dim %[[DEST]], %[[C3]] : memref<?x?x?x?xf32>
// CHECK: scf.for %[[I:.*]] = %[[C0]] to %[[UBI]] step %[[C1]] {
// CHECK: scf.for %[[J:.*]] = %[[C0]] to %[[UBJ]] step %[[C1]] {
// CHECK: scf.for %[[K:.*]] = %[[C0]] to %[[UBK]] step %[[C1]] {
// CHECK: scf.for %[[L:.*]] = %[[C0]] to %[[UBL]] step %[[C1]] {
// CHECK-DAG: %[[FLOORK:.*]] = affine.apply #[[$MAP_FLOORK]](%[[K]])[%[[TILE]]]
// CHECK-DAG: %[[FLOORL:.*]] = affine.apply #[[$MAP_FLOORL]](%[[L]])
// CHECK-DAG: %[[MODK:.*]] = affine.apply #[[$MAP_MODK]](%[[K]])[%[[TILE]]]
// CHECK-DAG: %[[MODL:.*]] = affine.apply #[[$MAP_MODL]](%[[L]])
// CHECK: %[[VAL:.*]] = memref.load %[[SRC]][%[[I]], %[[J]], %[[FLOORK]], %[[FLOORL]], %[[MODL]], %[[MODK]]] : memref<?x?x?x?x8x?xf32>
// CHECK: memref.store %[[VAL]], %[[DEST]][%[[I]], %[[J]], %[[K]], %[[L]]] : memref<?x?x?x?xf32>
// CHECK: }
// CHECK: }
// CHECK: }
// CHECK: }