--- /dev/null
+// RUN: mlir-opt %s -canonicalize | FileCheck %s
+
+// CHECK-DAG: #[[SUB:.*]] = ()[s0, s1] -> (s0 - s1)
+
+func @fold_constants(%arg0: !linalg.buffer<?xf32>) -> (index, index, index, index, index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %c2 = constant 2 : index
+ %c3 = constant 3 : index
+ %c4 = constant 4 : index
+ %c5 = constant 5 : index
+ %R02 = linalg.range %c0:%c2:%c1 : !linalg.range
+ %R03 = linalg.range %c0:%c3:%c1 : !linalg.range
+ %R04 = linalg.range %c0:%c4:%c1 : !linalg.range
+ %R12 = linalg.range %c1:%c2:%c1 : !linalg.range
+ %R13 = linalg.range %c1:%c3:%c1 : !linalg.range
+ %R14 = linalg.range %c1:%c4:%c1 : !linalg.range
+
+ %v = linalg.view %arg0[%R02, %R14] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ // Expected 2.
+ %v0 = linalg.dim %v, 0 : !linalg.view<?x?xf32>
+ // Expected 3.
+ %v1 = linalg.dim %v, 1 : !linalg.view<?x?xf32>
+
+ %s = linalg.slice %v[%c1, %R12] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
+ // Expected 1.
+ %s0 = linalg.dim %s, 0 : !linalg.view<?xf32>
+
+ %sv = linalg.subview %v[%v0, %v1, %c1, %c2, %c4, %c1] : !linalg.view<?x?xf32>
+ // Expected 1.
+ %sv0 = linalg.dim %sv, 0 : !linalg.view<?x?xf32>
+ // Expected 2.
+ %sv1 = linalg.dim %sv, 1 : !linalg.view<?x?xf32>
+
+ return %v0, %v1, %s0, %sv0, %sv1 : index, index, index, index, index
+}
+
+// CHECK-LABEL: fold_constants
+// CHECK-DAG: %[[c1:.*]] = constant 1 : index
+// CHECK-DAG: %[[c2:.*]] = constant 2 : index
+// CHECK-DAG: %[[c3:.*]] = constant 3 : index
+// CHECK: return %[[c2]], %[[c3]], %[[c1]], %[[c1]], %[[c2]]
+
+
+func @fold_indices(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) -> (index, index, index, index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %R = linalg.range %arg1:%arg3:%c1 : !linalg.range
+
+ %v = linalg.view %arg0[%R, %R] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ // Expected %arg3 - %arg1.
+ %v0 = linalg.dim %v, 0 : !linalg.view<?x?xf32>
+ // Expected %arg3 - %arg1.
+ %v1 = linalg.dim %v, 1 : !linalg.view<?x?xf32>
+
+ %arg1_p_arg2 = addi %arg1, %arg2: index
+ %arg1_p_arg2_affine = affine.apply (i, j) -> (i + j) (%arg1, %arg2)
+ %sv = linalg.subview %v[%arg1, %arg1_p_arg2, %c1, %arg1, %arg1_p_arg2_affine, %c1] : !linalg.view<?x?xf32>
+ // Expected %arg2 but can't fold affine.apply with addi.
+ %sv0 = linalg.dim %sv, 0 : !linalg.view<?x?xf32>
+ // Expected %arg2.
+ %sv1 = linalg.dim %sv, 1 : !linalg.view<?x?xf32>
+
+ return %v0, %v1, %sv0, %sv1 : index, index, index, index
+}
+
+// CHECK-LABEL: fold_indices
+// CHECK: (%[[arg0:.*]]: !linalg.buffer<?xf32>, %[[arg1:.*]]: index, %[[arg2:.*]]: index, %[[arg3:.*]]: index
+// CHECK: %[[r0:.*]] = affine.apply #[[SUB]]()[%[[arg3]], %[[arg1]]]
+// CHECK: %[[r1:.*]] = affine.apply #[[SUB]]()[%[[arg3]], %[[arg1]]]
+// CHECK: %[[add:.*]] = addi %[[arg1]], %[[arg2]] : index
+// CHECK: %[[aff:.*]] = affine.apply #[[SUB]]()[%[[add]], %[[arg1]]]
+// CHECK: return %[[r0]], %[[r1]], %[[aff]], %[[arg2]]
\ No newline at end of file
--- /dev/null
+// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=16 -cse | mlir-opt -linalg-fusion -linalg-fusion-tile-sizes=8 | FileCheck %s
+
+func @f1(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// CHECK-LABEL: func @f1
+// CHECK-DAG: %[[c8:.*]] = constant 8
+// CHECK-DAG: %[[c16:.*]] = constant 16
+// CHECK: loop.for %{{.*}} step %[[c16]] {
+// CHECK: loop.for %{{.*}} %[[c8]] {
+// CHECK: linalg.matmul
+// CHECK: linalg.matmul
\ No newline at end of file
--- /dev/null
+// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=0,0,0 | FileCheck %s -check-prefix=FUSE-0
+// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2 | FileCheck %s -check-prefix=FUSE-2
+// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2,3 | FileCheck %s -check-prefix=FUSE-23
+// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2,3,4 | FileCheck %s -check-prefix=FUSE-234
+
+func @f1(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// No RAW dependences, the pass does not fuse RAR atm.
+// FUSE-0-LABEL: func @f1
+// FUSE-0-NOT: loop.for
+// FUSE-2-LABEL: func @f1
+// FUSE-2-NOT: loop.for
+// FUSE-23-LABEL: func @f1
+// FUSE-23-NOT: loop.for
+// FUSE-234-LABEL: func @f1
+// FUSE-234-NOT: loop.for
+
+func @f2(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f2
+// FUSE-0-NOT: loop.for
+//
+// FUSE-2-LABEL: func @f2
+// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-2: linalg.matmul
+// FUSE-2: linalg.matmul
+//
+// FUSE-23-LABEL: func @f2
+// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
+// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+//
+// FUSE-234-LABEL: func @f2
+// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
+// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+
+func @f3(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%D, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f3
+// FUSE-0-NOT: loop.for
+//
+// Read to %C does not get tiled along 1st dimension => no fusion
+// FUSE-2-LABEL: func @f3
+// FUSE-2-NOT: loop.for
+//
+// FUSE-23-LABEL: func @f3
+// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
+// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+//
+// FUSE-234-LABEL: func @f3
+// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
+// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+
+func @f4(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f4
+// FUSE-0-NOT: loop.for
+//
+// Read to %D does not get tiled along 1st dimension => no fusion
+// FUSE-2-LABEL: func @f4
+// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-2: linalg.matmul
+// FUSE-2: linalg.matmul
+//
+// FUSE-23-LABEL: func @f4
+// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
+// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+//
+// FUSE-234-LABEL: func @f4
+// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
+// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+
+func @f5(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %B, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%D, %B, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f5
+// FUSE-0-NOT: loop.for
+//
+// FUSE-2-LABEL: func @f5
+// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-2: %[[D_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-2: linalg.matmul
+// FUSE-2: linalg.matmul
+//
+// FUSE-23-LABEL: func @f5
+// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
+// FUSE-23: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+//
+// FUSE-234-LABEL: func @f5
+// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
+// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
+// FUSE-234: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+
+func @f6(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %C, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// Write to %C can not be fused because the 2 RAW are not compatible.
+// The current algorithm just bails out on fusion in the case of any write-based
+// interleaved dependence.
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f6
+// FUSE-0-NOT: loop.for
+//
+// Read to D is not tiled along 1st dimension => no fusion
+// FUSE-2-LABEL: func @f6
+// FUSE-2-NOT: loop.for
+//
+// FUSE-23-LABEL: func @f6
+//
+// FUSE-234-LABEL: func @f6
+
+func @f7(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// The only fusion that respects dependences is the write to %C into the
+// immediately following read.
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f7
+// FUSE-0-NOT: loop.for
+//
+// Read to %C (in 3rd matmul) is not tiled along 1st dimension => no fusion
+// FUSE-2-LABEL: func @f7
+// FUSE-2-NOT: loop.for
+//
+// FUSE-23-LABEL: func @f7
+// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-23: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
+// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
+// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul
+// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+//
+// FUSE-234-LABEL: func @f7
+// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+// FUSE-234: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
+// FUSE-234: %[[A_1:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
+// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
+// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_1]] step %{{.*}} {
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul
+// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
+
+func @f8(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
+ linalg.matmul(%A, %C, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matmul(%A, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return %E : !linalg.view<?x?xf32>
+}
+// In this example, %D can never be fused because the WAR on %C would be violated
+// No tiling => no fusion
+// FUSE-0-LABEL: func @f8
+// FUSE-0-NOT: loop.for
+//
+// FUSE-2-LABEL: func @f8
+// FUSE-2-NOT: loop.for
+//
+// FUSE-23-LABEL: func @f8
+// FUSE-23-NOT: loop.for
+//
+// FUSE-234-LABEL: func @f8
+// FUSE-234-NOT: loop.for
+
+#id_2d = (i, j) -> (i, j)
+#pointwise_2d_trait = {
+ indexing_maps = [#id_2d, #id_2d, #id_2d],
+ n_loop_types = [2, 0, 0],
+ n_views = [2, 1]
+}
+
+func @pointwise(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>,
+ %arg2: !linalg.view<?x?xf32>, %arg3: !linalg.view<?x?xf32>) {
+ linalg.generic #pointwise_2d_trait %arg0, %arg0, %arg1 {
+ ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
+ %4 = addf %arg4, %arg5 : f32
+ linalg.yield %4 : f32
+ }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.generic #pointwise_2d_trait %arg1, %arg2, %arg3 {
+ ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
+ %4 = mulf %arg4, %arg5 : f32
+ linalg.yield %4 : f32
+ }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return
+}
+// No tiling => no fusion
+// FUSE-0-LABEL: func @pointwise
+// FUSE-0-NOT: loop.for
+// FUSE-0: linalg.generic
+// FUSE-0: addf
+// FUSE-0: linalg.generic
+// FUSE-0: mulf
+//
+// FUSE-2-LABEL: func @pointwise
+// FUSE-2: loop.for
+// FUSE-2-NOT: loop.for
+// FUSE-2: linalg.generic
+// FUSE-2: addf
+// FUSE-2: linalg.generic
+// FUSE-2: mulf
+//
+// FUSE-23-LABEL: func @pointwise
+// FUSE-23: loop.for
+// FUSE-23: loop.for
+// FUSE-23-NOT: loop.for
+// FUSE-23: linalg.generic
+// FUSE-23: addf
+// FUSE-23: linalg.generic
+// FUSE-23: mulf
+//
+// FUSE-234-LABEL: func @pointwise
+// FUSE-234: loop.for
+// FUSE-234: loop.for
+// FUSE-234-NOT: loop.for
+// FUSE-234: linalg.generic
+// FUSE-234: addf
+// FUSE-234: linalg.generic
+// FUSE-234: mulf
--- /dev/null
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+// -----
+
+func @buffer_alloc_single_index() {
+ // expected-error @+1 {{expected one index operand}}
+ %0 = linalg.buffer_alloc : !linalg.buffer<?xf32>
+}
+
+// -----
+
+func @buffer_alloc_unexpected_index(%s : index) {
+ // expected-error @+1 {{expected zero operand}}
+ %0 = linalg.buffer_alloc %s : !linalg.buffer<32xf32>
+}
+
+// -----
+
+func @buffer_alloc_nonegative_size() {
+ // expected-error @+1 {{expected nonnegative static buffer size}}
+ %0 = linalg.buffer_alloc : !linalg.buffer<0xf32>
+}
+
+// -----
+
+func @buffer_alloc_nonegative_alignment(%arg0: index) {
+ // expected-error @+1 {{expected positive alignment}}
+ %0 = linalg.buffer_alloc %arg0 {alignment = -123}: !linalg.buffer<?xf32>
+}
+
+// -----
+
+func @buffer_alloc_powerof2_alignment(%arg0: index) {
+ // expected-error @+1 {{expected power of 2 alignment}}
+ %0 = linalg.buffer_alloc %arg0 {alignment = 123}: !linalg.buffer<?xf32>
+}
+
+// -----
+
+func @buffer_valid_element_type() {
+ // expected-error @+1 {{expected valid buffer element type}}
+ %0 = linalg.buffer_alloc : !linalg.buffer<4xindex>
+}
+
+// -----
+
+func @load_number_of_indices(%v : !linalg.view<f32>) {
+ // expected-error @+2 {{expected 0 indices, got 1}}
+ %c0 = constant 0 : index
+ linalg.load %v[%c0] : !linalg.view<f32>
+}
+
+// -----
+
+func @slice_number_of_indexings(%arg0: !linalg.view<?x?xf32>) {
+ // expected-error @+2 {{expected 2 indexings, got 1}}
+ %c0 = constant 0: index
+ %0 = linalg.slice %arg0[%c0] : !linalg.view<?x?xf32>, index, !linalg.view<?x?xf32>
+}
+
+// -----
+
+func @slice_rank_vs_range_indices(%arg0: !linalg.view<?x?xf32>) {
+ // expected-error @+2 {{op expected rank of the view(1) to be the number of ranges(0)}}
+ %c0 = constant 0: index
+ %0 = linalg.slice %arg0[%c0, %c0] : !linalg.view<?x?xf32>, index, index, !linalg.view<?xf32>
+}
+
+// -----
+
+func @store_number_of_indices(%v : !linalg.view<f32>) {
+ // expected-error @+3 {{expected 0 indices, got 1}}
+ %c0 = constant 0 : index
+ %f0 = constant 0.0 : f32
+ linalg.store %f0, %v[%c0] : !linalg.view<f32>
+}
+
+// -----
+
+func @subview_number_of_indices(%v : !linalg.view<?x?xf32>) {
+ // expected-error @+2 {{expected a view followed by 6 indices specifying a range for each dimension}}
+ %c0 = constant 0 : index
+ linalg.subview %v[%c0, %c0] : !linalg.view<?x?xf32>
+}
+
+// -----
+
+func @transpose_not_permutation(%v : !linalg.view<?x?xf32>) {
+ // expected-error @+1 {{expected a permutation map}}
+ linalg.transpose %v (i, j) -> (i, i) : !linalg.view<?x?xf32>
+}
+
+// -----
+
+func @transpose_bad_rank(%v : !linalg.view<?x?xf32>) {
+ // expected-error @+1 {{expected a permutation map of same rank as the view}}
+ linalg.transpose %v (i) -> (i) : !linalg.view<?x?xf32>
+}
+
+// -----
+
+func @view_type(%buf: !linalg.buffer<?xf32>, %min: index, %max: index, %step: index) {
+ // expected-error @+2 {{expected view type}}
+ %r = linalg.range %min:%max:%step : !linalg.range
+ %0 = linalg.view %buf[%r]: !linalg.buffer<?xf32> -> index
+}
+
+// -----
+
+func @view_num_ranges(%buf: !linalg.buffer<?xf32>, %min: index, %max: index, %step: index) {
+ // expected-error @+2 {{expected 2 ranges}}
+ %r = linalg.range %min:%max:%step : !linalg.range
+ %0 = linalg.view %buf[%r]: !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+}
+
+// -----
+
+func @yield_parent(%arg0: !linalg.view<?xf32>) {
+ // expected-error @+1 {{op expected 'linalg.generic' parent op}}
+ linalg.yield %arg0: !linalg.view<?xf32>
+}
+
+// -----
+
+func @generic_at_least_2_operands(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected 2 or more operands}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [1, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @generic_exactly_2_views(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected exactly 2 view operands}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [1, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0, %arg0, %arg0: !linalg.view<f32>, !linalg.view<f32>, !linalg.view<f32>
+}
+
+// -----
+
+func @generic_undefined_fun(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected fun attribute to refer to a defined symbol}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [1, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0, %arg0: !linalg.view<f32>, !linalg.view<f32>
+}
+
+// -----
+
+func @foo() { return }
+
+func @generic_mismatched_num_arguments(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected fun arguments to match number of views}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @foo(%0: i32) { return }
+
+func @generic_mismatched_num_returns(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected fun results to match number of output views}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @foo(%0: i32) -> i32 { return %0: i32 }
+
+func @generic_symbol_in_map(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected indexing_map #0 to have no symbols}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ ()[N] -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [1, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @foo(%0: i32) -> i32 { return %0: i32 }
+
+func @generic_wrong_dim_in_map(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected indexing_map #0 to have 1 dim(s) to match the number of loops}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [1, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @foo(%0: i32) -> i32 { return %0: i32 }
+
+func @generic_zero_d_view(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected indexing_map #0 to be 0 to match 0-D view: '!linalg.view<f32>'}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (1) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<f32>
+}
+
+// -----
+
+func @foo(%0: f32) -> f32 { return %0: f32 }
+
+func @generic_one_d_view(%arg0: !linalg.view<?xf32>) {
+ // expected-error @+1 {{op expected indexing_map #0 results to match view rank: '!linalg.view<?xf32>'}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0, 0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<?xf32>
+}
+
+// -----
+
+func @foo(%0: i32) -> f32 {
+ %1 = constant 0.0: f32
+ return %1: f32
+}
+
+func @generic_fun_arg_0_element_type(%arg0: !linalg.view<?xf32>) {
+ // expected-error @+1 {{op expected fun argument 0 to match view element type: 'f32'}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<?xf32>
+}
+
+// -----
+
+func @foo(%0: f32) -> i4 {
+ %1 = constant 1: i4
+ return %1: i4
+}
+
+func @generic_fun_result_0_element_type(%arg0: !linalg.view<?xf32>) {
+ // expected-error @+1 {{op expected fun result 0 to match output view element type: 'f32'}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0: !linalg.view<?xf32>
+}
+
+// -----
+
+func @foo(%0: f32, %1: f32) -> f32 { return %1: f32 }
+
+func @generic_singular_maps(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
+ // expected-error @+1 {{op expected the concatenation of maps in indexing_map to be invertible}}
+ linalg.generic {
+ fun = @foo,
+ indexing_maps = [
+ (i, j) -> (i + j) ,
+ (i, j) -> (i + j)
+ ],
+ n_views = [1, 1],
+ n_loop_types = [2, 0, 0]
+ } %arg0, %arg1: !linalg.view<?xf32>, !linalg.view<?xf32>
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// Region tests /////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+// -----
+
+func @generic_empty_region(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected region with 1 block}}
+ linalg.generic {
+ indexing_maps = [ () -> (0) ],
+ n_views = [1, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0, %arg0 {
+ ^bb1:
+ ^bb2:
+ }: !linalg.view<f32>, !linalg.view<f32>
+}
+
+// -----
+
+func @generic_mismatched_num_arguments(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected number of block arguments to match number of views}}
+ linalg.generic {
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0 {
+ ^bb:
+ }: !linalg.view<f32>
+}
+
+// -----
+
+func @generic_block_arg_type(%arg0: !linalg.view<f32>) {
+ // expected-error @+1 {{op expected block argument 0 of the same type as elemental type of output view: '!linalg.view<f32>'}}
+ linalg.generic {
+ indexing_maps = [ () -> (0) ],
+ n_views = [0, 1],
+ n_loop_types = [0, 0, 0]
+ } %arg0 {
+ ^bb(%i: i1):
+ }: !linalg.view<f32>
+}
+
+// -----
+
+func @generic_fun_result_0_element_type(%arg0: !linalg.view<?xf32>) {
+ // expected-error @+8 {{type of return operand 0 ('i1') doesn't match view element type ('f32')}}
+ linalg.generic {
+ indexing_maps = [ (i) -> (i) ],
+ n_views = [0, 1],
+ n_loop_types = [1, 0, 0]
+ } %arg0 {
+ ^bb(%i: f32):
+ %0 = constant 0: i1
+ linalg.yield %0: i1
+ }: !linalg.view<?xf32>
+}
--- /dev/null
+// RUN: mlir-opt %s -linalg-lower-to-llvm-dialect | FileCheck %s
+
+func @buffer_size(%arg0: !linalg.buffer<?xf32>) {
+ %c1 = constant 1 : index
+ %s = linalg.buffer_size %arg0 : !linalg.buffer<?xf32>
+ %t = addi %s, %c1 : index
+ return
+}
+// CHECK-LABEL: func @buffer_size
+// CHECK: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i8*, float*, i64 }">
+// CHECK-NEXT: llvm.add {{.*}}, {{.*}} : !llvm.i64
+
+func @buffer_alloc_aligned(%arg0: index) {
+ %s = linalg.buffer_alloc %arg0 {alignment=16} : !linalg.buffer<?xf32>
+ return
+}
+// CHECK-LABEL: func @buffer_alloc_aligned
+// CHECK: %[[c4:.*]] = llvm.mlir.constant(4 : index) : !llvm.i64
+// CHECK: %[[m:.*]] = llvm.mul %arg0, %[[c4]] : !llvm.i64
+// CHECK: %[[c1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK: %[[c16:.*]] = llvm.mlir.constant(16 : index) : !llvm.i64
+// CHECK: %[[a:.*]] = llvm.add %[[m]], %[[c16]] : !llvm.i64
+// CHECK: %[[s:.*]] = llvm.sub %[[a]], %[[c1]] : !llvm.i64
+// CHECK: %[[alloc:.*]] = llvm.call @malloc(%[[s]]) : (!llvm.i64) -> !llvm<"i8*">
+// aligning `ptr` on `align` is done computing the address `ptr + (align - ptr % align) % align`.
+// CHECK: %[[cast:.*]] = llvm.ptrtoint %[[alloc]] : !llvm<"i8*"> to !llvm.i64
+// CHECK: %[[rem:.*]] = llvm.urem %[[cast]], %[[c16]] : !llvm.i64
+// CHECK: %[[drem:.*]] = llvm.sub %[[c16]], %[[rem]] : !llvm.i64
+// CHECK: %[[off:.*]] = llvm.urem %[[drem]], %[[c16]] : !llvm.i64
+// CHECK: llvm.getelementptr %{{.*}}[%[[off]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
+
+func @range(%arg0: index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %R = linalg.range %c0:%arg0:%c1 : !linalg.range
+ return
+}
+// CHECK-LABEL: func @range(%{{.*}}: !llvm.i64) {
+// CHECK: llvm.mlir.constant(0 : index) : !llvm.i64
+// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK-NEXT: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
+
+func @view(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range) {
+ %0 = linalg.view %arg0[%arg1] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ return
+}
+// CHECK-LABEL: func @view
+// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK-NEXT: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [1 x i64], [1 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, float*, i64 }">
+// CHECK-NEXT: llvm.bitcast {{.*}} : !llvm<"float*"> to !llvm<"float*">
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.mlir.constant(0 : index) : !llvm.i64
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK: llvm.store %{{.*}}, %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// CHECK-NEXT: llvm.return
+
+func @view3d(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range, %arg2: !linalg.range, %arg3: !linalg.range) {
+ %0 = linalg.view %arg0[%arg1, %arg2, %arg3] : !linalg.buffer<?xf32> -> !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @view3d
+// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
+// CHECK-NEXT: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [3 x i64], [3 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+// CHECK-NEXT: llvm.load {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+// CHECK: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
+// CHECK: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+
+func @slice(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range) {
+ %0 = linalg.view %arg0[%arg1] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ %1 = linalg.slice %0[%arg1] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
+ return
+}
+// CHECK-LABEL: func @slice
+// 1st load from view_op
+// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// 2nd load from reloading the view descriptor pointer
+// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// 3rd load from slice_op
+// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
+// insert data ptr
+// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.add %{{.*}}, %{{.*}} : !llvm.i64
+// insert offset
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
+// get size[0] from parent view
+// CHECK-NEXT: llvm.extractvalue %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// compute size[0] bounded by parent view's size[0]
+// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
+// bound below by 0
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// compute stride[0] using bounded size
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+// insert size and stride
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
+
+func @dot(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
+ linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+ return
+}
+// CHECK-LABEL: func @dot(%{{.*}}: !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, %{{.*}}: !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, %{{.*}}: !llvm<"{ float*, i64, [0 x i64], [0 x i64] }*">) {
+// CHECK: llvm.call @linalg_dot_viewxf32_viewxf32_viewf32(%{{.*}}, %{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, !llvm<"{ float*, i64, [0 x i64], [0 x i64] }*">) -> ()
+
+func @dim(%arg0: !linalg.view<?x?xf32>) {
+ %0 = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
+ return
+}
+// CHECK-LABEL: func @dim(%{{.*}}: !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">) {
+// CHECK: llvm.extractvalue %{{.*}}[2, 1] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
+
+func @subview(%arg0: !linalg.view<?x?xf32>) {
+ %c0 = constant 0 : index
+ %0 = linalg.subview %arg0[%c0, %c0, %c0, %c0, %c0, %c0] : !linalg.view<?x?xf32>
+ return
+}
+// CHECK-LABEL: func @subview
+//
+// Subview lowers to range + slice op
+// CHECK: llvm.alloca %{{.*}} x !llvm<"{ float*, i64, [2 x i64], [2 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">
+// CHECK: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
+// CHECK: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
+// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">
+//
+// Select occurs in slice op lowering
+// CHECK: llvm.extractvalue %{{.*}}[2, 0] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+//
+// CHECK: llvm.extractvalue %{{.*}}[2, 1] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
+// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
+// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
+
+func @view_with_range_and_index(%arg0: !linalg.view<?x?xf64>) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %R = linalg.range %c0:%c1:%c1 : !linalg.range
+ loop.for %i0 = %c0 to %c1 step %c1 {
+ %1 = linalg.slice %arg0[%i0, %R] : !linalg.view<?x?xf64>, index, !linalg.range, !linalg.view<?xf64>
+ }
+ return
+}
+// CHECK-LABEL: func @view_with_range_and_index
+// top of the function alloca + load.
+// CHECK: llvm.alloca %{{.*}} x !llvm<"{ double*, i64, [1 x i64], [1 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ double*, i64, [1 x i64], [1 x i64] }*">
+// CHECK: llvm.load %{{.*}} : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }*">
+// loop-body load from descriptor ptr.
+// CHECK: llvm.load %{{.*}} : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }*">
+// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
+// CHECK: llvm.extractvalue %{{.*}}[3, 0] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
+// CHECK: llvm.extractvalue %{{.*}}[3, 1] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
+// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
+// CHECK: llvm.insertvalue %{{.*}}[1] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
+// CHECK: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
+// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
+// CHECK: llvm.insertvalue %{{.*}}[2, 0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
+// CHECK: llvm.insertvalue %{{.*}}[3, 0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
+
+func @copy(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.copy(%arg0, %arg1) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @copy
+// CHECK: llvm.call @linalg_copy_viewxxxf32_viewxxxf32(%{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">, !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">) -> ()
+
+func @transpose(%arg0: !linalg.view<?x?x?xf32>) {
+ %0 = linalg.transpose %arg0 (i, j, k) -> (k, i, j) : !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @transpose
+// CHECK: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [3 x i64], [3 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+
+func @copy_transpose(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
+ outputPermutation = (i, j, k) -> (k, j, i)}
+ : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @copy
+// Tranpose input
+// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+// Transpose output
+// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
+// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
+// Call external copy
+// CHECK: llvm.call @linalg_copy_viewxxxf32_viewxxxf32(%{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">, !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">) -> ()
--- /dev/null
+// RUN: mlir-opt %s -linalg-lower-to-loops | FileCheck %s
+
+// CHECK-DAG: #[[S2D1:.*]] = (d0, d1) -> (d0 * 2 + d1)
+// CHECK-DAG: #[[S2D3:.*]] = (d0, d1) -> (d0 * 2 + d1 * 4)
+// CHECK-DAG: #[[S3D2:.*]] = (d0, d1) -> (d0 * 3 + d1 * 5)
+
+func @matmul(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %I = linalg.range %c0:%arg1:%c1 : !linalg.range
+ %J = linalg.range %c0:%arg2:%c1 : !linalg.range
+ %K = linalg.range %c0:%arg3:%c1 : !linalg.range
+ %A = linalg.view %arg0[%I, %K] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %B = linalg.view %arg0[%K, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %C = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return
+}
+// CHECK-LABEL: func @matmul(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+// CHECK: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
+// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
+// CHECK: %[[N:.*]] = linalg.dim %[[B]], 1 : !linalg.view<?x?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
+// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
+// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
+// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
+// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
+// CHECK: linalg.store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
+
+func @matvec(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %I = linalg.range %c0:%arg1:%c1 : !linalg.range
+ %J = linalg.range %c0:%arg2:%c1 : !linalg.range
+ %2 = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %3 = linalg.view %arg0[%J] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ %4 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ linalg.matvec(%2, %3, %4) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+ return
+}
+// CHECK-LABEL: func @matvec(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+// CHECK: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
+// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
+// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
+// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
+// CHECK: linalg.store %[[res]], %[[C]][%{{.*}}] : !linalg.view<?xf32>
+
+func @dot(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %I = linalg.range %c0:%arg1:%c1 : !linalg.range
+ %1 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ %2 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+ %3 = linalg.view %arg0[] : !linalg.buffer<?xf32> -> !linalg.view<f32>
+ linalg.dot(%1, %2, %3) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+ return
+}
+// CHECK-LABEL: func @dot(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
+// CHECK: %[[C:.*]] = linalg.view %arg0[] : !linalg.buffer<?xf32> -> !linalg.view<f32>
+// CHECK: %[[K:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
+// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][] : !linalg.view<f32>
+// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
+// CHECK: linalg.store %[[res]], %[[C]][] : !linalg.view<f32>
+
+func @dot_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
+ linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+ return
+}
+// CHECK-LABEL: func @dot_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// CHECK: %[[K:.*]] = linalg.dim %arg0, 0 : !linalg.view<?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK-DAG: %[[a:.*]] = linalg.load %arg0[%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[b:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
+// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
+// CHECK-DAG: %[[c:.*]] = linalg.load %{{.*}}[] : !linalg.view<f32>
+// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
+// CHECK: linalg.store %[[res]], %{{.*}}[] : !linalg.view<f32>
+
+func @fill_view(%arg0: !linalg.view<?xf32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<?xf32>, f32
+ return
+}
+// CHECK-LABEL: func @fill_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: f32) {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
+
+func @fill_view0(%arg0: !linalg.view<f32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<f32>, f32
+ return
+}
+// CHECK-LABEL: func @fill_view0(%{{.*}}: !linalg.view<f32>, %{{.*}}: f32) {
+// CHECK: linalg.store %{{.*}}, %{{.*}}[] : !linalg.view<f32>
+
+func @fill_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<?x?x?xf32>, f32
+ return
+}
+// CHECK-LABEL: func @fill_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: f32) {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+
+func @copy_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
+ linalg.copy(%arg0, %arg1) : !linalg.view<?xf32>, !linalg.view<?xf32>
+ return
+}
+// CHECK-LABEL: func @copy_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
+// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
+
+func @copy_view0(%arg0: !linalg.view<f32>, %arg1: !linalg.view<f32>) {
+ linalg.copy(%arg0, %arg1) : !linalg.view<f32>, !linalg.view<f32>
+ return
+}
+// CHECK-LABEL: func @copy_view0(%{{.*}}: !linalg.view<f32>, %{{.*}}: !linalg.view<f32>) {
+// CHECK: %{{.*}} = linalg.load %{{.*}}[] : !linalg.view<f32>
+// CHECK: linalg.store %{{.*}}, %{{.*}}[] : !linalg.view<f32>
+
+func @copy_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
+ outputPermutation = (i, j, k) -> (k, j, i)} :
+ !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @copy_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+
+func @conv_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
+ linalg.conv(%arg0, %arg1, %arg2) {strides = [2]}: !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @conv_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
+// CHECK: %[[Z0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?x?xf32>
+// CHECK: %[[Q:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?x?xf32>
+// CHECK: %[[K:.*]] = linalg.dim %arg0, 2 : !linalg.view<?x?x?xf32>
+// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?xf32>
+// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
+// CHECK: %[[SUM:.*]] = affine.apply #[[S2D1]](%{{.*}}, %{{.*}})
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM]], %{{.*}}] : !linalg.view<?x?x?xf32>
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+// CHECK: %{{.*}} = mulf %{{.*}}, %{{.*}} : f32
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+// CHECK: %{{.*}} = addf %{{.*}}, %{{.*}} : f32
+// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
+
+func @conv_view4(%arg0: !linalg.view<?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?xf32>) {
+ linalg.conv(%arg0, %arg1, %arg2) {dilations = [4, 5], strides = [2, 3]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @conv_view4(%{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>) {
+// CHECK: %[[Z0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[Z1:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[Q:.*]] = linalg.dim %arg0, 2 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[K:.*]] = linalg.dim %arg0, 3 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?x?xf32>
+// CHECK: %[[X1:.*]] = linalg.dim %arg2, 2 : !linalg.view<?x?x?x?xf32>
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X1]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
+// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z1]] step %{{.*}} {
+// CHECK: %[[SUM0:.*]] = affine.apply #map1(%{{.*}}, %{{.*}})
+// CHECK: %[[SUM1:.*]] = affine.apply #map2(%{{.*}}, %{{.*}})
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM0]], %[[SUM1]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
+// CHECK: %{{.*}} = mulf %{{.*}}, %{{.*}} : f32
+// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
+// CHECK: %{{.*}} = addf %{{.*}}, %{{.*}} : f32
+// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
+
+func @foo(%0: f32, %1: f32, %2: f32) -> (f32, f32) {
+ %f0 = constant 0.0 : f32
+ return %f0, %f0 : f32, f32
+}
+#accesses = [
+ (i, j, k) -> (i, j),
+ (i, j, k) -> (i, j, k),
+ (i, j, k) -> (i, k, j)
+]
+#trait = {
+ n_views = [1, 2],
+ n_loop_types = [3, 0, 0],
+ indexing_maps = #accesses,
+ fun = @foo,
+ library_call = "external_function_name",
+ doc = "B(i,j,k), C(i,k,j) = foo(A(i, j), B(i,j,k), C(i,k,j))"
+}
+func @generic_function(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
+ linalg.generic #trait %arg0, %arg1, %arg2:
+ !linalg.view<?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: @foo
+// CHECK-LABEL: @generic_function
+// CHECK: loop.for %[[i:.*]] = {{.*}}
+// CHECK: loop.for %[[j:.*]] = {{.*}}
+// CHECK: loop.for %[[k:.*]] = {{.*}}
+// CHECK: %[[a:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]]] : !linalg.view<?x?xf32>
+// CHECK: %[[b:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
+// CHECK: %[[c:.*]] = linalg.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
+// CHECK: %[[res:.*]]:2 = call @foo(%[[a]], %[[b]], %[[c]]) : (f32, f32, f32) -> (f32, f32)
+// CHECK: linalg.store %[[res]]#0, %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
+// CHECK: linalg.store %[[res]]#1, %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
+
+#trait2 = {
+ n_views = [1, 2],
+ n_loop_types = [3, 0, 0],
+ indexing_maps = #accesses,
+ library_call = "external_function_name",
+ doc = "B(i,j,k), C(i,k,j) = foo(A(i, j), B(i,j,k), C(i,k,j))"
+}
+func @generic_region(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
+ linalg.generic #trait2 %arg0, %arg1, %arg2 {
+ ^bb0(%a: f32, %b: f32, %c: f32):
+ %d = mulf %a, %b : f32
+ %e = addf %c, %d : f32
+ linalg.yield %d, %e : f32, f32
+ }: !linalg.view<?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: @generic_region
+// CHECK: loop.for %[[i:.*]] = {{.*}}
+// CHECK: loop.for %[[j:.*]] = {{.*}}
+// CHECK: loop.for %[[k:.*]] = {{.*}}
+// CHECK: %[[a:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]]] : !linalg.view<?x?xf32>
+// CHECK: %[[b:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
+// CHECK: %[[c:.*]] = linalg.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
+// CHECK: %[[d:.*]] = mulf %[[a]], %[[b]] : f32
+// CHECK: %[[e:.*]] = addf %[[c]], %[[d]] : f32
+// CHECK: linalg.store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
+// CHECK: linalg.store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
--- /dev/null
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,4 -linalg-tile-promote-full-tile-views=true | FileCheck %s -check-prefix=TILE-1D
+
+func @matmul(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
+ %c0 = constant 0 : index
+ %c1 = constant 1 : index
+ %I = linalg.range %c0:%arg1:%c1 : !linalg.range
+ %J = linalg.range %c0:%arg2:%c1 : !linalg.range
+ %K = linalg.range %c0:%arg3:%c1 : !linalg.range
+ %A = linalg.view %arg0[%I, %K] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %B = linalg.view %arg0[%K, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %C = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return
+}
+// TILE-1D-LABEL: func @matmul(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
+// TILE-1D: %[[vA:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
+// TILE-1D: %[[vB:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
+// TILE-1D: %[[vC:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
+///
+// TILE-1D: %[[tmpA:.*]] = linalg.buffer_alloc : !linalg.buffer<8xf32>
+// TILE-1D: %[[fullA:.*]] = linalg.view %[[tmpA]][{{.*}}] : !linalg.buffer<8xf32> -> !linalg.view<?x?xf32>
+// TILE-1D: %[[partialA:.*]] = linalg.slice %[[fullA]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
+///
+// TILE-1D: %[[tmpB:.*]] = linalg.buffer_alloc : !linalg.buffer<12xf32>
+// TILE-1D: %[[fullB:.*]] = linalg.view %[[tmpB]][{{.*}}] : !linalg.buffer<12xf32> -> !linalg.view<?x?xf32>
+// TILE-1D: %[[partialB:.*]] = linalg.slice %[[fullB]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
+///
+// TILE-1D: %[[tmpC:.*]] = linalg.buffer_alloc : !linalg.buffer<6xf32>
+// TILE-1D: %[[fullC:.*]] = linalg.view %[[tmpC]][{{.*}}] : !linalg.buffer<6xf32> -> !linalg.view<?x?xf32>
+// TILE-1D: %[[partialC:.*]] = linalg.slice %[[fullC]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
+
+// TILE-1D: linalg.fill(%[[fullA]], {{.*}}) : !linalg.view<?x?xf32>, f32
+// TILE-1D: linalg.fill(%[[fullB]], {{.*}}) : !linalg.view<?x?xf32>, f32
+// TILE-1D: linalg.fill(%[[fullC]], {{.*}}) : !linalg.view<?x?xf32>, f32
+// TILE-1D: linalg.copy(%[[vA]], %[[partialA]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+// TILE-1D: linalg.copy(%[[vB]], %[[partialB]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+// TILE-1D: linalg.copy(%[[vC]], %[[partialC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+//
+// TILE-1D: linalg.matmul(%[[fullA]], %[[fullB]], %[[fullC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+//
+// TILE-1D: linalg.copy(%[[partialC]], %[[vC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+//
+// TILE-1D: linalg.buffer_dealloc %[[tmpA]] : !linalg.buffer<8xf32>
+// TILE-1D: linalg.buffer_dealloc %[[tmpB]] : !linalg.buffer<12xf32>
+// TILE-1D: linalg.buffer_dealloc %[[tmpC]] : !linalg.buffer<6xf32>
--- /dev/null
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
+
+// CHECK-DAG: #[[map0:.*]] = (d0, d1, d2) -> (d0, d2, d1)
+// CHECK-DAG: #[[map1:.*]] = (d0, d1, d2) -> (d2, d1, d0)
+
+func @range(%arg0: index, %arg1: index, %arg2: index) {
+ %0 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
+ return
+}
+// CHECK-LABEL: func @range(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK-NEXT: linalg.range %{{.*}}:%{{.*}}:%{{.*}} : !linalg.range
+
+func @buffer_size(%arg0: !linalg.buffer<?xf32>) -> index {
+ %0 = linalg.buffer_size %arg0 : !linalg.buffer<?xf32>
+ return %0 : index
+}
+// CHECK-LABEL: func @buffer_size
+// CHECK: linalg.buffer_size {{.*}} : !linalg.buffer<?xf32>
+
+func @buffer(%arg0: index, %arg1: index) {
+ %0 = muli %arg0, %arg0 : index
+ %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xvector<4xi8>>
+ %2 = linalg.buffer_alloc %0 {alignment = 16} : !linalg.buffer<?xvector<4xi8>>
+ %3 = linalg.buffer_alloc : !linalg.buffer<17xvector<4xi8>>
+ %4 = linalg.buffer_alloc {alignment = 32} : !linalg.buffer<17xvector<4xi8>>
+ linalg.buffer_dealloc %4 : !linalg.buffer<17xvector<4xi8>>
+ linalg.buffer_dealloc %3 : !linalg.buffer<17xvector<4xi8>>
+ linalg.buffer_dealloc %2 : !linalg.buffer<?xvector<4xi8>>
+ linalg.buffer_dealloc %1 : !linalg.buffer<?xvector<4xi8>>
+ return
+}
+// CHECK-LABEL: func @buffer(%{{.*}}: index, %{{.*}}: index) {
+// CHECK-NEXT: muli %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_alloc %{{.*}} {alignment = 16 : i64} : !linalg.buffer<?xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_alloc : !linalg.buffer<17xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_alloc {alignment = 32 : i64} : !linalg.buffer<17xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<17xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<17xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
+
+func @view_fun(%arg0: !linalg.view<?x?xvector<3x4xi4>>) {
+ return
+}
+// CHECK-LABEL: func @view_fun(%{{.*}}: !linalg.view<?x?xvector<3x4xi4>>) {
+
+func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) {
+ %0 = muli %arg0, %arg0 : index
+ %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xf32>
+ %2 = linalg.range %arg2:%arg3:%arg4 : !linalg.range
+ %3 = linalg.view %1[%2, %2] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+ %4 = linalg.slice %3[%2, %2] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
+ %5 = linalg.slice %3[%2, %arg2] : !linalg.view<?x?xf32>, !linalg.range, index, !linalg.view<?xf32>
+ %6 = linalg.slice %3[%arg2, %2] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
+ %7 = linalg.slice %3[%arg2, %arg3] : !linalg.view<?x?xf32>, index, index, !linalg.view<f32>
+ %8 = linalg.view %1[%2, %2] : !linalg.buffer<?xf32> -> !linalg.view<?x?xvector<4x4xf32>>
+ linalg.buffer_dealloc %1 : !linalg.buffer<?xf32>
+ return
+}
+// CHECK-LABEL: func @views(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK-NEXT: muli %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xf32>
+// CHECK-NEXT: linalg.range %{{.*}}:%{{.*}}:%{{.*}} : !linalg.range
+// CHECK-NEXT: linalg.view %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
+// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
+// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, index, !linalg.view<?xf32>
+// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
+// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, index, index, !linalg.view<f32>
+// CHECK-NEXT: linalg.view %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xvector<4x4xf32>>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xf32>
+
+func @ops(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<?xf32>, %arg3: !linalg.view<f32>) {
+ linalg.matmul(%arg0, %arg0, %arg0) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ linalg.matvec(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+ linalg.dot(%arg1, %arg2, %arg3) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+ return
+}
+// CHECK-LABEL: func @ops(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// CHECK-NEXT: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+// CHECK-NEXT: linalg.matvec(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+// CHECK-NEXT: linalg.dot(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+
+func @dim(%arg0: !linalg.view<?x?xf32>) {
+ %0 = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
+ %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xf32>
+ linalg.buffer_dealloc %1 : !linalg.buffer<?xf32>
+ return
+}
+// CHECK-LABEL: func @dim(%{{.*}}: !linalg.view<?x?xf32>) {
+// CHECK-NEXT: linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xf32>
+// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xf32>
+
+func @linalg_for(%arg0 : index, %arg1 : index, %arg2 : index) {
+ loop.for %i0 = %arg0 to %arg1 step %arg2 {
+ loop.for %i1 = %arg0 to %arg1 step %arg2 {
+ %min_cmp = cmpi "slt", %i0, %i1 : index
+ %min = select %min_cmp, %i0, %i1 : index
+ %max_cmp = cmpi "sge", %i0, %i1 : index
+ %max = select %max_cmp, %i0, %i1 : index
+ loop.for %i2 = %min to %max step %i1 {
+ }
+ }
+ }
+ return
+}
+// CHECK-LABEL: func @linalg_for(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
+// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
+// CHECK-NEXT: cmpi "slt", %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: select %{{.*}}, %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: cmpi "sge", %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: select %{{.*}}, %{{.*}}, %{{.*}} : index
+// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
+
+func @fill_view(%arg0: !linalg.view<?xf32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<?xf32>, f32
+ return
+}
+// CHECK-LABEL: func @fill_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: f32) {
+// CHECK: linalg.fill(%{{.*}}, %{{.*}}) : !linalg.view<?xf32>, f32
+
+func @transpose(%arg0: !linalg.view<?x?x?xf32>) {
+ %0 = linalg.transpose %arg0 (i, j, k) -> (k, j, i) : !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @transpose
+// CHECK: linalg.transpose %{{.*}} ([[i:.*]], [[j:.*]], [[k:.*]]) -> ([[k]], [[j]], [[i]]) : !linalg.view<?x?x?xf32>
+
+func @fill_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<?x?x?xf32>, f32
+ return
+}
+// CHECK-LABEL: func @fill_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: f32) {
+// CHECK: linalg.fill(%{{.*}}, %{{.*}}) : !linalg.view<?x?x?xf32>, f32
+
+func @copy_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
+ linalg.copy(%arg0, %arg1) : !linalg.view<?xf32>, !linalg.view<?xf32>
+ return
+}
+// CHECK-LABEL: func @copy_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// CHECK: linalg.copy(%{{.*}}, %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>
+
+func @copy_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
+ outputPermutation = (i, j, k) -> (k, j, i)} :
+ !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @copy_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
+// CHECK: linalg.copy(%{{.*}}, %{{.*}}) {inputPermutation = #[[map0]], outputPermutation = #[[map1]]} : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+
+func @conv_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
+ linalg.conv(%arg0, %arg1, %arg2) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @conv_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
+// CHECK: linalg.conv(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
+
+func @conv_view6(%arg0: !linalg.view<?x?x?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?x?x?xf32>) {
+ linalg.conv(%arg0, %arg1, %arg2) {dilations = [4, 4, 5, 5], strides = [2, 2, 3, 3]} : !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @conv_view6(%{{.*}}: !linalg.view<?x?x?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?x?x?xf32>) {
+// CHECK: linalg.conv(%{{.*}}, %{{.*}}, %{{.*}}) {dilations = [4, 4, 5, 5], strides = [2, 2, 3, 3]} : !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>
+
+func @subview(%arg0: !linalg.view<?x?xvector<3x4xi4>>) {
+ %c0 = constant 0 : index
+ %0 = linalg.subview %arg0[%c0, %c0, %c0, %c0, %c0, %c0] : !linalg.view<?x?xvector<3x4xi4>>
+ return
+}
+// CHECK-LABEL: func @subview(%{{.*}}: !linalg.view<?x?xvector<3x4xi4>>) {
+// CHECK: constant 0 : index
+// CHECK: linalg.subview %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?xvector<3x4xi4>>
+
+func @const_buffer_view(%arg0: index, %arg1: index, %arg2: index) {
+ %c0 = linalg.buffer_alloc : !linalg.buffer<17xf32>
+ %c1 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
+ %c2 = linalg.view %c0[%c1] : !linalg.buffer<17xf32> -> !linalg.view<?xf32>
+ return
+}
+
+#accesses = [
+ (i, j, k) -> (j, i),
+ (i, j, k) -> (i, k, i + j)
+]
+#trait = {
+ indexing_maps = #accesses,
+ n_views = [1, 1],
+ n_loop_types = [3, 0, 0],
+ fun = @foo,
+ library_call = "external_function_name"
+}
+func @foo(%0: vector<3x4xi4>, %1: f32) -> f32 {
+ %f0 = constant 0.0 : f32
+ return %f0 : f32
+}
+func @generic(%arg0: !linalg.view<?x?xvector<3x4xi4>>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.generic #trait %arg0, %arg1 {foo = 1} : !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @foo
+// CHECK-LABEL: func @generic
+// CHECK: linalg.generic {fun = @foo, indexing_maps = [#map2, #map3], library_call = "external_function_name", n_loop_types = [3, 0, 0], n_views = [1, 1]} %{{.*}}, %{{.*}} {foo = 1 : i64}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
+
+#trait2 = {
+ indexing_maps = #accesses,
+ n_views = [1, 1],
+ n_loop_types = [3, 0, 0],
+ library_call = "external_function_name"
+}
+func @generic_region(%arg0: !linalg.view<?x?xvector<3x4xi4>>, %arg1: !linalg.view<?x?x?xf32>) {
+ linalg.generic #trait2 %arg0, %arg1 {
+ ^bb(%a: vector<3x4xi4>, %b: f32) :
+ linalg.yield %b : f32
+ } {foo = 1}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
+ return
+}
+// CHECK-LABEL: func @generic_region
+// CHECK: linalg.generic {indexing_maps = [#map2, #map3], library_call = "external_function_name", n_loop_types = [3, 0, 0], n_views = [1, 1]} %{{.*}}, %{{.*}} {
+// CHECK: ^{{.*}}(%{{.*}}: vector<3x4xi4>, %{{.*}}: f32): // no predecessors
+// CHECK: linalg.yield %{{.*}} : f32
+// CHECK: } {foo = 1 : i64}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
\ No newline at end of file
--- /dev/null
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2 | FileCheck %s -check-prefix=TILE-2
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=0,2 | FileCheck %s -check-prefix=TILE-02
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=0,0,2 | FileCheck %s -check-prefix=TILE-002
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,4 | FileCheck %s -check-prefix=TILE-234
+
+// TILE-2-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
+// TILE-02-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
+// TILE-002-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
+// TILE-234-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
+// TILE-234-DAG: #[[UB1:.*]] = (d0) -> (d0 + 3)
+// TILE-234-DAG: #[[UB2:.*]] = (d0) -> (d0 + 4)
+
+func @matmul(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>, %arg2: !linalg.view<?x?xf32>) {
+ linalg.matmul(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return
+}
+// TILE-2-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
+// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[K]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-2: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-2: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[c]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-2: linalg.matmul(%[[sAi]], %{{.*}}, %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+
+// TILE-02-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
+// TILE-02: %[[N:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
+// TILE-02: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
+// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-02: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-02: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[K]], %{{.*}}, %{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-02: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-02: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-02: %[[sCj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[c]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-02: linalg.matmul(%{{.*}}, %[[sBj]], %[[sCj]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+
+// TILE-002-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
+// TILE-002: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-002: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-002: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-002: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-002: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-002: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-002: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-002: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-002: linalg.matmul(%[[sAj]], %[[sBj]], %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+
+// TILE-234-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
+// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-234: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[N]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[ak:.*]] = affine.apply #[[UB2]](%{{.*}})
+// TILE-234: %[[sAik:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[ak]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-234: %[[bk:.*]] = affine.apply #[[UB2]](%{{.*}})
+// TILE-234: %[[bj:.*]] = affine.apply #[[UB1]](%{{.*}})
+// TILE-234: %[[sBkj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[bk]], %{{.*}}, %{{.*}}, %[[bj]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-234: %[[ci:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[cj:.*]] = affine.apply #[[UB1]](%{{.*}})
+// TILE-234: %[[sCij:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ci]], %{{.*}}, %{{.*}}, %[[cj]], %{{.*}}] : !linalg.view<?x?xf32>
+//
+// TILE-234: linalg.matmul(%[[sAik]], %[[sBkj]], %[[sCij]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+
+func @matvec(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<?xf32>) {
+ linalg.matvec(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+ return
+}
+// TILE-2-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-2: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[c]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-2: linalg.matvec(%[[sAi]], %{{.*}}, %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+
+// TILE-02-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-02: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-02: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-02: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-02: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-02: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-02: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-02: linalg.matvec(%[[sAj]], %[[sBj]], %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+
+// TILE-002-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// TILE-002-NOT: loop.for
+
+// TILE-234-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
+// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
+// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[aj:.*]] = affine.apply #[[UB1]](%{{.*}})
+// TILE-234: %[[sAij:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[aj]], %{{.*}}] : !linalg.view<?x?xf32>
+// TILE-234: %[[bj:.*]] = affine.apply #[[UB1]](%{{.*}})
+// TILE-234: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[bj]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-234: %[[ci:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ci]], %{{.*}}] : !linalg.view<?xf32>
+//
+// TILE-234: linalg.matvec(%[[sAij]], %[[sBj]], %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
+
+func @dot(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
+ linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+ return
+}
+// TILE-2-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
+// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
+// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-2: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-2: %[[sBi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-2: linalg.dot(%[[sAi]], %[[sBi]], {{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+
+// TILE-02-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// TILE-02-NOT: loop.for
+
+// TILE-002-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// TILE-002-NOT: loop.for
+
+// TILE-234-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
+// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
+// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
+// TILE-234: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-234: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-234: %[[sBi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
+// TILE-234: linalg.dot(%[[sAi]], %[[sBi]], %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
+
+func @fill(%arg0: !linalg.view<?x?xf32>, %arg1: f32) {
+ linalg.fill(%arg0, %arg1) : !linalg.view<?x?xf32>, f32
+ return
+}
+// TILE-2-LABEL: func @fill
+// TILE-2: for
+// TILE-2-NOT: for
+// TILE-2: fill{{.*}} f32
+
+// TILE-02-LABEL: func @fill
+// TILE-02: for
+// TILE-02-NOT: for
+// TILE-02: fill{{.*}} f32
+
+// TILE-002-LABEL: func @fill
+// TILE-002-NOT: for
+// TILE-002: fill{{.*}} f32
+
+// TILE-234-LABEL: func @fill
+// TILE-234: for
+// TILE-234: for
+// TILE-234-NOT: for
+// TILE-234: fill{{.*}} f32
+
+#id_2d = (i, j) -> (i, j)
+#pointwise_2d_trait = {
+ indexing_maps = [#id_2d, #id_2d, #id_2d],
+ n_loop_types = [2, 0, 0],
+ n_views = [2, 1]
+}
+
+func @pointwise(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>,
+ %arg2: !linalg.view<?x?xf32>) {
+ linalg.generic #pointwise_2d_trait %arg0, %arg1, %arg2 {
+ ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
+ %4 = addf %arg4, %arg5 : f32
+ linalg.yield %4 : f32
+ }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
+ return
+}
+// TILE-2-LABEL: func @pointwise
+// TILE-2: for
+// TILE-2-NOT: for
+// TILE-2: linalg.generic
+
+// TILE-02-LABEL: func @pointwise
+// TILE-02: for
+// TILE-02-NOT: for
+// TILE-02: linalg.generic
+
+// TILE-002-LABEL: func @pointwise
+// TILE-002-NOT: for
+// TILE-002: linalg.generic
+
+// TILE-234-LABEL: func @pointwise
+// TILE-234: for
+// TILE-234: for
+// TILE-234-NOT: for
+// TILE-234: linalg.generic
--- /dev/null
+// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,0,0,4 | FileCheck %s -check-prefix=TILE-23004
+
+// TILE-23004-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
+// TILE-23004-DAG: #[[UB1:.*]] = (d0) -> (d0 + 3)
+// TILE-23004-DAG: #[[UB2:.*]] = (d0) -> (d0 + 4)
+// TILE-23004-DAG: #[[D0x30pS0x10:.*]] = (d0) -> (d0 * 30)
+// TILE-23004-DAG: #[[D0x30pS0x10p90:.*]] = (d0)[s0] -> (d0 * 30 + s0 * 10 + 90)
+func @conv(%arg0: !linalg.view<?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?xf32>) {
+ linalg.conv(%arg0, %arg1, %arg2) {dilations = [10, 20], strides = [30, 40]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>
+ return
+}
+// TILE-23004-LABEL: func @conv(%{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>) {
+// TILE-23004: %[[Q:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[B:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[PaddedInput0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[X0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
+// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
+// TILE-23004: %[[Z0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[Z1:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[I2p4:.*]] = affine.apply #[[UB2]](%{{.*}})
+// TILE-23004: %[[K:.*]] = linalg.dim %{{.*}}, 3 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[FilterView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[Z0]], %{{.*}}, %{{.*}}, %[[Z1]], %{{.*}}, %{{.*}}, %[[I2p4]], %{{.*}}, %{{.*}}, %[[K]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
+//
+// TILE-23004: %[[I0p3:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-23004: %[[I1:.*]] = affine.apply #[[D0x30pS0x10]](%{{.*}})
+// TILE-23004: %[[I1pStep:.*]] = affine.apply #[[D0x30pS0x10p90]](%{{.*}})[%[[PaddedInput0]]]
+// TILE-23004: %[[SZ2:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[I2p2:.*]] = affine.apply #[[UB2]](%{{.*}})
+// TILE-23004: %[[InputView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[I0p3]], %{{.*}}, %[[I1]], %[[I1pStep]], %{{.*}}, %{{.*}}, %[[SZ2]], %{{.*}}, %{{.*}}, %[[I2p2]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
+//
+// TILE-23004: %[[B:.*]] = affine.apply #[[UB0]](%{{.*}})
+// TILE-23004: %[[I1p3:.*]] = affine.apply #[[UB1]](%{{.*}})
+// TILE-23004: %[[X0:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[X1:.*]] = linalg.dim %{{.*}}, 3 : !linalg.view<?x?x?x?xf32>
+// TILE-23004: %[[OutputView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[B]], %{{.*}}, %{{.*}}, %[[I1p3]], %{{.*}}, %{{.*}}, %[[X0]], %{{.*}}, %{{.*}}, %[[X1]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
+//
+// TILE-23004: linalg.conv(%[[FilterView]], %[[InputView]], %[[OutputView]]) {dilations = [10, 20], strides = [30, 40]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>
+++ /dev/null
-// RUN: mlir-opt %s -canonicalize | FileCheck %s
-
-// CHECK-DAG: #[[SUB:.*]] = ()[s0, s1] -> (s0 - s1)
-
-func @fold_constants(%arg0: !linalg.buffer<?xf32>) -> (index, index, index, index, index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %c2 = constant 2 : index
- %c3 = constant 3 : index
- %c4 = constant 4 : index
- %c5 = constant 5 : index
- %R02 = linalg.range %c0:%c2:%c1 : !linalg.range
- %R03 = linalg.range %c0:%c3:%c1 : !linalg.range
- %R04 = linalg.range %c0:%c4:%c1 : !linalg.range
- %R12 = linalg.range %c1:%c2:%c1 : !linalg.range
- %R13 = linalg.range %c1:%c3:%c1 : !linalg.range
- %R14 = linalg.range %c1:%c4:%c1 : !linalg.range
-
- %v = linalg.view %arg0[%R02, %R14] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- // Expected 2.
- %v0 = linalg.dim %v, 0 : !linalg.view<?x?xf32>
- // Expected 3.
- %v1 = linalg.dim %v, 1 : !linalg.view<?x?xf32>
-
- %s = linalg.slice %v[%c1, %R12] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
- // Expected 1.
- %s0 = linalg.dim %s, 0 : !linalg.view<?xf32>
-
- %sv = linalg.subview %v[%v0, %v1, %c1, %c2, %c4, %c1] : !linalg.view<?x?xf32>
- // Expected 1.
- %sv0 = linalg.dim %sv, 0 : !linalg.view<?x?xf32>
- // Expected 2.
- %sv1 = linalg.dim %sv, 1 : !linalg.view<?x?xf32>
-
- return %v0, %v1, %s0, %sv0, %sv1 : index, index, index, index, index
-}
-
-// CHECK-LABEL: fold_constants
-// CHECK-DAG: %[[c1:.*]] = constant 1 : index
-// CHECK-DAG: %[[c2:.*]] = constant 2 : index
-// CHECK-DAG: %[[c3:.*]] = constant 3 : index
-// CHECK: return %[[c2]], %[[c3]], %[[c1]], %[[c1]], %[[c2]]
-
-
-func @fold_indices(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) -> (index, index, index, index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %R = linalg.range %arg1:%arg3:%c1 : !linalg.range
-
- %v = linalg.view %arg0[%R, %R] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- // Expected %arg3 - %arg1.
- %v0 = linalg.dim %v, 0 : !linalg.view<?x?xf32>
- // Expected %arg3 - %arg1.
- %v1 = linalg.dim %v, 1 : !linalg.view<?x?xf32>
-
- %arg1_p_arg2 = addi %arg1, %arg2: index
- %arg1_p_arg2_affine = affine.apply (i, j) -> (i + j) (%arg1, %arg2)
- %sv = linalg.subview %v[%arg1, %arg1_p_arg2, %c1, %arg1, %arg1_p_arg2_affine, %c1] : !linalg.view<?x?xf32>
- // Expected %arg2 but can't fold affine.apply with addi.
- %sv0 = linalg.dim %sv, 0 : !linalg.view<?x?xf32>
- // Expected %arg2.
- %sv1 = linalg.dim %sv, 1 : !linalg.view<?x?xf32>
-
- return %v0, %v1, %sv0, %sv1 : index, index, index, index
-}
-
-// CHECK-LABEL: fold_indices
-// CHECK: (%[[arg0:.*]]: !linalg.buffer<?xf32>, %[[arg1:.*]]: index, %[[arg2:.*]]: index, %[[arg3:.*]]: index
-// CHECK: %[[r0:.*]] = affine.apply #[[SUB]]()[%[[arg3]], %[[arg1]]]
-// CHECK: %[[r1:.*]] = affine.apply #[[SUB]]()[%[[arg3]], %[[arg1]]]
-// CHECK: %[[add:.*]] = addi %[[arg1]], %[[arg2]] : index
-// CHECK: %[[aff:.*]] = affine.apply #[[SUB]]()[%[[add]], %[[arg1]]]
-// CHECK: return %[[r0]], %[[r1]], %[[aff]], %[[arg2]]
\ No newline at end of file
+++ /dev/null
-// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=16 -cse | mlir-opt -linalg-fusion -linalg-fusion-tile-sizes=8 | FileCheck %s
-
-func @f1(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// CHECK-LABEL: func @f1
-// CHECK-DAG: %[[c8:.*]] = constant 8
-// CHECK-DAG: %[[c16:.*]] = constant 16
-// CHECK: loop.for %{{.*}} step %[[c16]] {
-// CHECK: loop.for %{{.*}} %[[c8]] {
-// CHECK: linalg.matmul
-// CHECK: linalg.matmul
\ No newline at end of file
+++ /dev/null
-// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=0,0,0 | FileCheck %s -check-prefix=FUSE-0
-// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2 | FileCheck %s -check-prefix=FUSE-2
-// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2,3 | FileCheck %s -check-prefix=FUSE-23
-// RUN: mlir-opt %s -linalg-fusion -linalg-fusion-tile-sizes=2,3,4 | FileCheck %s -check-prefix=FUSE-234
-
-func @f1(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// No RAW dependences, the pass does not fuse RAR atm.
-// FUSE-0-LABEL: func @f1
-// FUSE-0-NOT: loop.for
-// FUSE-2-LABEL: func @f1
-// FUSE-2-NOT: loop.for
-// FUSE-23-LABEL: func @f1
-// FUSE-23-NOT: loop.for
-// FUSE-234-LABEL: func @f1
-// FUSE-234-NOT: loop.for
-
-func @f2(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f2
-// FUSE-0-NOT: loop.for
-//
-// FUSE-2-LABEL: func @f2
-// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-2: linalg.matmul
-// FUSE-2: linalg.matmul
-//
-// FUSE-23-LABEL: func @f2
-// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
-// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-//
-// FUSE-234-LABEL: func @f2
-// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
-// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-
-func @f3(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%D, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f3
-// FUSE-0-NOT: loop.for
-//
-// Read to %C does not get tiled along 1st dimension => no fusion
-// FUSE-2-LABEL: func @f3
-// FUSE-2-NOT: loop.for
-//
-// FUSE-23-LABEL: func @f3
-// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
-// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-//
-// FUSE-234-LABEL: func @f3
-// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
-// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-
-func @f4(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f4
-// FUSE-0-NOT: loop.for
-//
-// Read to %D does not get tiled along 1st dimension => no fusion
-// FUSE-2-LABEL: func @f4
-// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-2: %[[C_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-2: linalg.matmul
-// FUSE-2: linalg.matmul
-//
-// FUSE-23-LABEL: func @f4
-// FUSE-23: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
-// FUSE-23: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-//
-// FUSE-234-LABEL: func @f4
-// FUSE-234: %[[C_0:.*]] = linalg.dim %arg2, 0 : !linalg.view<?x?xf32>
-// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-
-func @f5(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %B, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%D, %B, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f5
-// FUSE-0-NOT: loop.for
-//
-// FUSE-2-LABEL: func @f5
-// FUSE-2: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-2: %[[D_0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// FUSE-2: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-2: linalg.matmul
-// FUSE-2: linalg.matmul
-//
-// FUSE-23-LABEL: func @f5
-// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-23: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
-// FUSE-23: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-//
-// FUSE-234-LABEL: func @f5
-// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-234: %[[D_0:.*]] = linalg.dim %arg3, 0 : !linalg.view<?x?xf32>
-// FUSE-234: %[[D_1:.*]] = linalg.dim %arg3, 1 : !linalg.view<?x?xf32>
-// FUSE-234: %[[B_1:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[B_1]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-
-func @f6(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %C, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// Write to %C can not be fused because the 2 RAW are not compatible.
-// The current algorithm just bails out on fusion in the case of any write-based
-// interleaved dependence.
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f6
-// FUSE-0-NOT: loop.for
-//
-// Read to D is not tiled along 1st dimension => no fusion
-// FUSE-2-LABEL: func @f6
-// FUSE-2-NOT: loop.for
-//
-// FUSE-23-LABEL: func @f6
-//
-// FUSE-234-LABEL: func @f6
-
-func @f7(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %C, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%C, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// The only fusion that respects dependences is the write to %C into the
-// immediately following read.
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f7
-// FUSE-0-NOT: loop.for
-//
-// Read to %C (in 3rd matmul) is not tiled along 1st dimension => no fusion
-// FUSE-2-LABEL: func @f7
-// FUSE-2-NOT: loop.for
-//
-// FUSE-23-LABEL: func @f7
-// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-23: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
-// FUSE-23: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
-// FUSE-23: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul
-// FUSE-23: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-//
-// FUSE-234-LABEL: func @f7
-// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-// FUSE-234: %[[A_0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?xf32>
-// FUSE-234: %[[A_1:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
-// FUSE-234: %[[C_1:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?xf32>
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
-// FUSE-234: loop.for %{{.*}} = %{{.*}} to %[[A_1]] step %{{.*}} {
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul
-// FUSE-234: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}})
-
-func @f8(%A: !linalg.view<?x?xf32>, %B: !linalg.view<?x?xf32>, %C: !linalg.view<?x?xf32>, %D: !linalg.view<?x?xf32>, %E: !linalg.view<?x?xf32>) -> !linalg.view<?x?xf32> {
- linalg.matmul(%A, %C, %D) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matmul(%A, %D, %E) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return %E : !linalg.view<?x?xf32>
-}
-// In this example, %D can never be fused because the WAR on %C would be violated
-// No tiling => no fusion
-// FUSE-0-LABEL: func @f8
-// FUSE-0-NOT: loop.for
-//
-// FUSE-2-LABEL: func @f8
-// FUSE-2-NOT: loop.for
-//
-// FUSE-23-LABEL: func @f8
-// FUSE-23-NOT: loop.for
-//
-// FUSE-234-LABEL: func @f8
-// FUSE-234-NOT: loop.for
-
-#id_2d = (i, j) -> (i, j)
-#pointwise_2d_trait = {
- indexing_maps = [#id_2d, #id_2d, #id_2d],
- n_loop_types = [2, 0, 0],
- n_views = [2, 1]
-}
-
-func @pointwise(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>,
- %arg2: !linalg.view<?x?xf32>, %arg3: !linalg.view<?x?xf32>) {
- linalg.generic #pointwise_2d_trait %arg0, %arg0, %arg1 {
- ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
- %4 = addf %arg4, %arg5 : f32
- linalg.yield %4 : f32
- }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.generic #pointwise_2d_trait %arg1, %arg2, %arg3 {
- ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
- %4 = mulf %arg4, %arg5 : f32
- linalg.yield %4 : f32
- }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return
-}
-// No tiling => no fusion
-// FUSE-0-LABEL: func @pointwise
-// FUSE-0-NOT: loop.for
-// FUSE-0: linalg.generic
-// FUSE-0: addf
-// FUSE-0: linalg.generic
-// FUSE-0: mulf
-//
-// FUSE-2-LABEL: func @pointwise
-// FUSE-2: loop.for
-// FUSE-2-NOT: loop.for
-// FUSE-2: linalg.generic
-// FUSE-2: addf
-// FUSE-2: linalg.generic
-// FUSE-2: mulf
-//
-// FUSE-23-LABEL: func @pointwise
-// FUSE-23: loop.for
-// FUSE-23: loop.for
-// FUSE-23-NOT: loop.for
-// FUSE-23: linalg.generic
-// FUSE-23: addf
-// FUSE-23: linalg.generic
-// FUSE-23: mulf
-//
-// FUSE-234-LABEL: func @pointwise
-// FUSE-234: loop.for
-// FUSE-234: loop.for
-// FUSE-234-NOT: loop.for
-// FUSE-234: linalg.generic
-// FUSE-234: addf
-// FUSE-234: linalg.generic
-// FUSE-234: mulf
+++ /dev/null
-// RUN: mlir-opt %s -split-input-file -verify-diagnostics
-
-// -----
-
-func @buffer_alloc_single_index() {
- // expected-error @+1 {{expected one index operand}}
- %0 = linalg.buffer_alloc : !linalg.buffer<?xf32>
-}
-
-// -----
-
-func @buffer_alloc_unexpected_index(%s : index) {
- // expected-error @+1 {{expected zero operand}}
- %0 = linalg.buffer_alloc %s : !linalg.buffer<32xf32>
-}
-
-// -----
-
-func @buffer_alloc_nonegative_size() {
- // expected-error @+1 {{expected nonnegative static buffer size}}
- %0 = linalg.buffer_alloc : !linalg.buffer<0xf32>
-}
-
-// -----
-
-func @buffer_alloc_nonegative_alignment(%arg0: index) {
- // expected-error @+1 {{expected positive alignment}}
- %0 = linalg.buffer_alloc %arg0 {alignment = -123}: !linalg.buffer<?xf32>
-}
-
-// -----
-
-func @buffer_alloc_powerof2_alignment(%arg0: index) {
- // expected-error @+1 {{expected power of 2 alignment}}
- %0 = linalg.buffer_alloc %arg0 {alignment = 123}: !linalg.buffer<?xf32>
-}
-
-// -----
-
-func @buffer_valid_element_type() {
- // expected-error @+1 {{expected valid buffer element type}}
- %0 = linalg.buffer_alloc : !linalg.buffer<4xindex>
-}
-
-// -----
-
-func @load_number_of_indices(%v : !linalg.view<f32>) {
- // expected-error @+2 {{expected 0 indices, got 1}}
- %c0 = constant 0 : index
- linalg.load %v[%c0] : !linalg.view<f32>
-}
-
-// -----
-
-func @slice_number_of_indexings(%arg0: !linalg.view<?x?xf32>) {
- // expected-error @+2 {{expected 2 indexings, got 1}}
- %c0 = constant 0: index
- %0 = linalg.slice %arg0[%c0] : !linalg.view<?x?xf32>, index, !linalg.view<?x?xf32>
-}
-
-// -----
-
-func @slice_rank_vs_range_indices(%arg0: !linalg.view<?x?xf32>) {
- // expected-error @+2 {{op expected rank of the view(1) to be the number of ranges(0)}}
- %c0 = constant 0: index
- %0 = linalg.slice %arg0[%c0, %c0] : !linalg.view<?x?xf32>, index, index, !linalg.view<?xf32>
-}
-
-// -----
-
-func @store_number_of_indices(%v : !linalg.view<f32>) {
- // expected-error @+3 {{expected 0 indices, got 1}}
- %c0 = constant 0 : index
- %f0 = constant 0.0 : f32
- linalg.store %f0, %v[%c0] : !linalg.view<f32>
-}
-
-// -----
-
-func @subview_number_of_indices(%v : !linalg.view<?x?xf32>) {
- // expected-error @+2 {{expected a view followed by 6 indices specifying a range for each dimension}}
- %c0 = constant 0 : index
- linalg.subview %v[%c0, %c0] : !linalg.view<?x?xf32>
-}
-
-// -----
-
-func @transpose_not_permutation(%v : !linalg.view<?x?xf32>) {
- // expected-error @+1 {{expected a permutation map}}
- linalg.transpose %v (i, j) -> (i, i) : !linalg.view<?x?xf32>
-}
-
-// -----
-
-func @transpose_bad_rank(%v : !linalg.view<?x?xf32>) {
- // expected-error @+1 {{expected a permutation map of same rank as the view}}
- linalg.transpose %v (i) -> (i) : !linalg.view<?x?xf32>
-}
-
-// -----
-
-func @view_type(%buf: !linalg.buffer<?xf32>, %min: index, %max: index, %step: index) {
- // expected-error @+2 {{expected view type}}
- %r = linalg.range %min:%max:%step : !linalg.range
- %0 = linalg.view %buf[%r]: !linalg.buffer<?xf32> -> index
-}
-
-// -----
-
-func @view_num_ranges(%buf: !linalg.buffer<?xf32>, %min: index, %max: index, %step: index) {
- // expected-error @+2 {{expected 2 ranges}}
- %r = linalg.range %min:%max:%step : !linalg.range
- %0 = linalg.view %buf[%r]: !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-}
-
-// -----
-
-func @yield_parent(%arg0: !linalg.view<?xf32>) {
- // expected-error @+1 {{op expected 'linalg.generic' parent op}}
- linalg.yield %arg0: !linalg.view<?xf32>
-}
-
-// -----
-
-func @generic_at_least_2_operands(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected 2 or more operands}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [1, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @generic_exactly_2_views(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected exactly 2 view operands}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [1, 1],
- n_loop_types = [0, 0, 0]
- } %arg0, %arg0, %arg0: !linalg.view<f32>, !linalg.view<f32>, !linalg.view<f32>
-}
-
-// -----
-
-func @generic_undefined_fun(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected fun attribute to refer to a defined symbol}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [1, 1],
- n_loop_types = [0, 0, 0]
- } %arg0, %arg0: !linalg.view<f32>, !linalg.view<f32>
-}
-
-// -----
-
-func @foo() { return }
-
-func @generic_mismatched_num_arguments(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected fun arguments to match number of views}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @foo(%0: i32) { return }
-
-func @generic_mismatched_num_returns(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected fun results to match number of output views}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @foo(%0: i32) -> i32 { return %0: i32 }
-
-func @generic_symbol_in_map(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected indexing_map #0 to have no symbols}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ ()[N] -> (0) ],
- n_views = [0, 1],
- n_loop_types = [1, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @foo(%0: i32) -> i32 { return %0: i32 }
-
-func @generic_wrong_dim_in_map(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected indexing_map #0 to have 1 dim(s) to match the number of loops}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [1, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @foo(%0: i32) -> i32 { return %0: i32 }
-
-func @generic_zero_d_view(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected indexing_map #0 to be 0 to match 0-D view: '!linalg.view<f32>'}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (1) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<f32>
-}
-
-// -----
-
-func @foo(%0: f32) -> f32 { return %0: f32 }
-
-func @generic_one_d_view(%arg0: !linalg.view<?xf32>) {
- // expected-error @+1 {{op expected indexing_map #0 results to match view rank: '!linalg.view<?xf32>'}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0, 0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<?xf32>
-}
-
-// -----
-
-func @foo(%0: i32) -> f32 {
- %1 = constant 0.0: f32
- return %1: f32
-}
-
-func @generic_fun_arg_0_element_type(%arg0: !linalg.view<?xf32>) {
- // expected-error @+1 {{op expected fun argument 0 to match view element type: 'f32'}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<?xf32>
-}
-
-// -----
-
-func @foo(%0: f32) -> i4 {
- %1 = constant 1: i4
- return %1: i4
-}
-
-func @generic_fun_result_0_element_type(%arg0: !linalg.view<?xf32>) {
- // expected-error @+1 {{op expected fun result 0 to match output view element type: 'f32'}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0: !linalg.view<?xf32>
-}
-
-// -----
-
-func @foo(%0: f32, %1: f32) -> f32 { return %1: f32 }
-
-func @generic_singular_maps(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
- // expected-error @+1 {{op expected the concatenation of maps in indexing_map to be invertible}}
- linalg.generic {
- fun = @foo,
- indexing_maps = [
- (i, j) -> (i + j) ,
- (i, j) -> (i + j)
- ],
- n_views = [1, 1],
- n_loop_types = [2, 0, 0]
- } %arg0, %arg1: !linalg.view<?xf32>, !linalg.view<?xf32>
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///////////////////////////// Region tests /////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-// -----
-
-func @generic_empty_region(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected region with 1 block}}
- linalg.generic {
- indexing_maps = [ () -> (0) ],
- n_views = [1, 1],
- n_loop_types = [0, 0, 0]
- } %arg0, %arg0 {
- ^bb1:
- ^bb2:
- }: !linalg.view<f32>, !linalg.view<f32>
-}
-
-// -----
-
-func @generic_mismatched_num_arguments(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected number of block arguments to match number of views}}
- linalg.generic {
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0 {
- ^bb:
- }: !linalg.view<f32>
-}
-
-// -----
-
-func @generic_block_arg_type(%arg0: !linalg.view<f32>) {
- // expected-error @+1 {{op expected block argument 0 of the same type as elemental type of output view: '!linalg.view<f32>'}}
- linalg.generic {
- indexing_maps = [ () -> (0) ],
- n_views = [0, 1],
- n_loop_types = [0, 0, 0]
- } %arg0 {
- ^bb(%i: i1):
- }: !linalg.view<f32>
-}
-
-// -----
-
-func @generic_fun_result_0_element_type(%arg0: !linalg.view<?xf32>) {
- // expected-error @+8 {{type of return operand 0 ('i1') doesn't match view element type ('f32')}}
- linalg.generic {
- indexing_maps = [ (i) -> (i) ],
- n_views = [0, 1],
- n_loop_types = [1, 0, 0]
- } %arg0 {
- ^bb(%i: f32):
- %0 = constant 0: i1
- linalg.yield %0: i1
- }: !linalg.view<?xf32>
-}
+++ /dev/null
-// RUN: mlir-opt %s -linalg-lower-to-llvm-dialect | FileCheck %s
-
-func @buffer_size(%arg0: !linalg.buffer<?xf32>) {
- %c1 = constant 1 : index
- %s = linalg.buffer_size %arg0 : !linalg.buffer<?xf32>
- %t = addi %s, %c1 : index
- return
-}
-// CHECK-LABEL: func @buffer_size
-// CHECK: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i8*, float*, i64 }">
-// CHECK-NEXT: llvm.add {{.*}}, {{.*}} : !llvm.i64
-
-func @buffer_alloc_aligned(%arg0: index) {
- %s = linalg.buffer_alloc %arg0 {alignment=16} : !linalg.buffer<?xf32>
- return
-}
-// CHECK-LABEL: func @buffer_alloc_aligned
-// CHECK: %[[c4:.*]] = llvm.mlir.constant(4 : index) : !llvm.i64
-// CHECK: %[[m:.*]] = llvm.mul %arg0, %[[c4]] : !llvm.i64
-// CHECK: %[[c1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK: %[[c16:.*]] = llvm.mlir.constant(16 : index) : !llvm.i64
-// CHECK: %[[a:.*]] = llvm.add %[[m]], %[[c16]] : !llvm.i64
-// CHECK: %[[s:.*]] = llvm.sub %[[a]], %[[c1]] : !llvm.i64
-// CHECK: %[[alloc:.*]] = llvm.call @malloc(%[[s]]) : (!llvm.i64) -> !llvm<"i8*">
-// aligning `ptr` on `align` is done computing the address `ptr + (align - ptr % align) % align`.
-// CHECK: %[[cast:.*]] = llvm.ptrtoint %[[alloc]] : !llvm<"i8*"> to !llvm.i64
-// CHECK: %[[rem:.*]] = llvm.urem %[[cast]], %[[c16]] : !llvm.i64
-// CHECK: %[[drem:.*]] = llvm.sub %[[c16]], %[[rem]] : !llvm.i64
-// CHECK: %[[off:.*]] = llvm.urem %[[drem]], %[[c16]] : !llvm.i64
-// CHECK: llvm.getelementptr %{{.*}}[%[[off]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
-
-func @range(%arg0: index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %R = linalg.range %c0:%arg0:%c1 : !linalg.range
- return
-}
-// CHECK-LABEL: func @range(%{{.*}}: !llvm.i64) {
-// CHECK: llvm.mlir.constant(0 : index) : !llvm.i64
-// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK-NEXT: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
-
-func @view(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range) {
- %0 = linalg.view %arg0[%arg1] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- return
-}
-// CHECK-LABEL: func @view
-// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK-NEXT: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [1 x i64], [1 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i8*, float*, i64 }">
-// CHECK-NEXT: llvm.bitcast {{.*}} : !llvm<"float*"> to !llvm<"float*">
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.mlir.constant(0 : index) : !llvm.i64
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK: llvm.store %{{.*}}, %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// CHECK-NEXT: llvm.return
-
-func @view3d(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range, %arg2: !linalg.range, %arg3: !linalg.range) {
- %0 = linalg.view %arg0[%arg1, %arg2, %arg3] : !linalg.buffer<?xf32> -> !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @view3d
-// CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64
-// CHECK-NEXT: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [3 x i64], [3 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-// CHECK-NEXT: llvm.load {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-// CHECK: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
-// CHECK: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-
-func @slice(%arg0: !linalg.buffer<?xf32>, %arg1: !linalg.range) {
- %0 = linalg.view %arg0[%arg1] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- %1 = linalg.slice %0[%arg1] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
- return
-}
-// CHECK-LABEL: func @slice
-// 1st load from view_op
-// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// 2nd load from reloading the view descriptor pointer
-// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// 3rd load from slice_op
-// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">
-// insert data ptr
-// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.add %{{.*}}, %{{.*}} : !llvm.i64
-// insert offset
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[2] : !llvm<"{ i64, i64, i64 }">
-// get size[0] from parent view
-// CHECK-NEXT: llvm.extractvalue %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// compute size[0] bounded by parent view's size[0]
-// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
-// bound below by 0
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// compute stride[0] using bounded size
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-// insert size and stride
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[2, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-// CHECK-NEXT: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm<"{ float*, i64, [1 x i64], [1 x i64] }">
-
-func @dot(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
- linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
- return
-}
-// CHECK-LABEL: func @dot(%{{.*}}: !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, %{{.*}}: !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, %{{.*}}: !llvm<"{ float*, i64, [0 x i64], [0 x i64] }*">) {
-// CHECK: llvm.call @linalg_dot_viewxf32_viewxf32_viewf32(%{{.*}}, %{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, !llvm<"{ float*, i64, [1 x i64], [1 x i64] }*">, !llvm<"{ float*, i64, [0 x i64], [0 x i64] }*">) -> ()
-
-func @dim(%arg0: !linalg.view<?x?xf32>) {
- %0 = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
- return
-}
-// CHECK-LABEL: func @dim(%{{.*}}: !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">) {
-// CHECK: llvm.extractvalue %{{.*}}[2, 1] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
-
-func @subview(%arg0: !linalg.view<?x?xf32>) {
- %c0 = constant 0 : index
- %0 = linalg.subview %arg0[%c0, %c0, %c0, %c0, %c0, %c0] : !linalg.view<?x?xf32>
- return
-}
-// CHECK-LABEL: func @subview
-//
-// Subview lowers to range + slice op
-// CHECK: llvm.alloca %{{.*}} x !llvm<"{ float*, i64, [2 x i64], [2 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">
-// CHECK: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
-// CHECK: llvm.mlir.undef : !llvm<"{ i64, i64, i64 }">
-// CHECK: llvm.load %{{.*}} : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }*">
-//
-// Select occurs in slice op lowering
-// CHECK: llvm.extractvalue %{{.*}}[2, 0] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-//
-// CHECK: llvm.extractvalue %{{.*}}[2, 1] : !llvm<"{ float*, i64, [2 x i64], [2 x i64] }">
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// CHECK-NEXT: llvm.sub %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.icmp "slt" %{{.*}}, %{{.*}} : !llvm.i64
-// CHECK-NEXT: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : !llvm.i1, !llvm.i64
-// CHECK-NEXT: llvm.mul %{{.*}}, %{{.*}} : !llvm.i64
-
-func @view_with_range_and_index(%arg0: !linalg.view<?x?xf64>) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %R = linalg.range %c0:%c1:%c1 : !linalg.range
- loop.for %i0 = %c0 to %c1 step %c1 {
- %1 = linalg.slice %arg0[%i0, %R] : !linalg.view<?x?xf64>, index, !linalg.range, !linalg.view<?xf64>
- }
- return
-}
-// CHECK-LABEL: func @view_with_range_and_index
-// top of the function alloca + load.
-// CHECK: llvm.alloca %{{.*}} x !llvm<"{ double*, i64, [1 x i64], [1 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ double*, i64, [1 x i64], [1 x i64] }*">
-// CHECK: llvm.load %{{.*}} : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }*">
-// loop-body load from descriptor ptr.
-// CHECK: llvm.load %{{.*}} : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }*">
-// CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
-// CHECK: llvm.extractvalue %{{.*}}[3, 0] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
-// CHECK: llvm.extractvalue %{{.*}}[3, 1] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
-// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ double*, i64, [2 x i64], [2 x i64] }">
-// CHECK: llvm.insertvalue %{{.*}}[1] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
-// CHECK: llvm.extractvalue %{{.*}}[0] : !llvm<"{ i64, i64, i64 }">
-// CHECK: llvm.extractvalue %{{.*}}[1] : !llvm<"{ i64, i64, i64 }">
-// CHECK: llvm.insertvalue %{{.*}}[2, 0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
-// CHECK: llvm.insertvalue %{{.*}}[3, 0] : !llvm<"{ double*, i64, [1 x i64], [1 x i64] }">
-
-func @copy(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.copy(%arg0, %arg1) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @copy
-// CHECK: llvm.call @linalg_copy_viewxxxf32_viewxxxf32(%{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">, !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">) -> ()
-
-func @transpose(%arg0: !linalg.view<?x?x?xf32>) {
- %0 = linalg.transpose %arg0 (i, j, k) -> (k, i, j) : !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @transpose
-// CHECK: llvm.alloca {{.*}} x !llvm<"{ float*, i64, [3 x i64], [3 x i64] }"> {alignment = 8 : i64} : (!llvm.i64) -> !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-
-func @copy_transpose(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
- outputPermutation = (i, j, k) -> (k, j, i)}
- : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @copy
-// Tranpose input
-// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-// Transpose output
-// CHECK: llvm.insertvalue {{.*}}[0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 1] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.extractvalue {{.*}}[2, 2] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.insertvalue {{.*}}[2, 0] : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }">
-// CHECK: llvm.store {{.*}} : !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">
-// Call external copy
-// CHECK: llvm.call @linalg_copy_viewxxxf32_viewxxxf32(%{{.*}}, %{{.*}}) : (!llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">, !llvm<"{ float*, i64, [3 x i64], [3 x i64] }*">) -> ()
+++ /dev/null
-// RUN: mlir-opt %s -linalg-lower-to-loops | FileCheck %s
-
-// CHECK-DAG: #[[S2D1:.*]] = (d0, d1) -> (d0 * 2 + d1)
-// CHECK-DAG: #[[S2D3:.*]] = (d0, d1) -> (d0 * 2 + d1 * 4)
-// CHECK-DAG: #[[S3D2:.*]] = (d0, d1) -> (d0 * 3 + d1 * 5)
-
-func @matmul(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %I = linalg.range %c0:%arg1:%c1 : !linalg.range
- %J = linalg.range %c0:%arg2:%c1 : !linalg.range
- %K = linalg.range %c0:%arg3:%c1 : !linalg.range
- %A = linalg.view %arg0[%I, %K] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %B = linalg.view %arg0[%K, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %C = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return
-}
-// CHECK-LABEL: func @matmul(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-// CHECK: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
-// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
-// CHECK: %[[N:.*]] = linalg.dim %[[B]], 1 : !linalg.view<?x?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
-// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
-// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
-// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
-// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
-// CHECK: linalg.store %[[res]], %[[C]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
-
-func @matvec(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %I = linalg.range %c0:%arg1:%c1 : !linalg.range
- %J = linalg.range %c0:%arg2:%c1 : !linalg.range
- %2 = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %3 = linalg.view %arg0[%J] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- %4 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- linalg.matvec(%2, %3, %4) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
- return
-}
-// CHECK-LABEL: func @matvec(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
-// CHECK: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
-// CHECK: %[[M:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?x?xf32>
-// CHECK: %[[K:.*]] = linalg.dim %[[A]], 1 : !linalg.view<?x?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[M]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>
-// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
-// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
-// CHECK: linalg.store %[[res]], %[[C]][%{{.*}}] : !linalg.view<?xf32>
-
-func @dot(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %I = linalg.range %c0:%arg1:%c1 : !linalg.range
- %1 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- %2 = linalg.view %arg0[%I] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
- %3 = linalg.view %arg0[] : !linalg.buffer<?xf32> -> !linalg.view<f32>
- linalg.dot(%1, %2, %3) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
- return
-}
-// CHECK-LABEL: func @dot(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK: %[[A:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
-// CHECK: %[[B:.*]] = linalg.view %arg0[{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?xf32>
-// CHECK: %[[C:.*]] = linalg.view %arg0[] : !linalg.buffer<?xf32> -> !linalg.view<f32>
-// CHECK: %[[K:.*]] = linalg.dim %[[A]], 0 : !linalg.view<?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK-DAG: %[[a:.*]] = linalg.load %[[A]][%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[b:.*]] = linalg.load %[[B]][%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
-// CHECK-DAG: %[[c:.*]] = linalg.load %[[C]][] : !linalg.view<f32>
-// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
-// CHECK: linalg.store %[[res]], %[[C]][] : !linalg.view<f32>
-
-func @dot_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
- linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
- return
-}
-// CHECK-LABEL: func @dot_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// CHECK: %[[K:.*]] = linalg.dim %arg0, 0 : !linalg.view<?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK-DAG: %[[a:.*]] = linalg.load %arg0[%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[b:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
-// CHECK-DAG: %[[inc:.*]] = mulf %[[a]], %[[b]] : f32
-// CHECK-DAG: %[[c:.*]] = linalg.load %{{.*}}[] : !linalg.view<f32>
-// CHECK-DAG: %[[res:.*]] = addf %[[c]], %[[inc]] : f32
-// CHECK: linalg.store %[[res]], %{{.*}}[] : !linalg.view<f32>
-
-func @fill_view(%arg0: !linalg.view<?xf32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<?xf32>, f32
- return
-}
-// CHECK-LABEL: func @fill_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: f32) {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
-
-func @fill_view0(%arg0: !linalg.view<f32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<f32>, f32
- return
-}
-// CHECK-LABEL: func @fill_view0(%{{.*}}: !linalg.view<f32>, %{{.*}}: f32) {
-// CHECK: linalg.store %{{.*}}, %{{.*}}[] : !linalg.view<f32>
-
-func @fill_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<?x?x?xf32>, f32
- return
-}
-// CHECK-LABEL: func @fill_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: f32) {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-
-func @copy_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
- linalg.copy(%arg0, %arg1) : !linalg.view<?xf32>, !linalg.view<?xf32>
- return
-}
-// CHECK-LABEL: func @copy_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
-// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}] : !linalg.view<?xf32>
-
-func @copy_view0(%arg0: !linalg.view<f32>, %arg1: !linalg.view<f32>) {
- linalg.copy(%arg0, %arg1) : !linalg.view<f32>, !linalg.view<f32>
- return
-}
-// CHECK-LABEL: func @copy_view0(%{{.*}}: !linalg.view<f32>, %{{.*}}: !linalg.view<f32>) {
-// CHECK: %{{.*}} = linalg.load %{{.*}}[] : !linalg.view<f32>
-// CHECK: linalg.store %{{.*}}, %{{.*}}[] : !linalg.view<f32>
-
-func @copy_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
- outputPermutation = (i, j, k) -> (k, j, i)} :
- !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @copy_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK: %[[L:.*]] = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-// CHECK: linalg.store %[[L]], %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-
-func @conv_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
- linalg.conv(%arg0, %arg1, %arg2) {strides = [2]}: !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @conv_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
-// CHECK: %[[Z0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?x?xf32>
-// CHECK: %[[Q:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?x?xf32>
-// CHECK: %[[K:.*]] = linalg.dim %arg0, 2 : !linalg.view<?x?x?xf32>
-// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?xf32>
-// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
-// CHECK: %[[SUM:.*]] = affine.apply #[[S2D1]](%{{.*}}, %{{.*}})
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM]], %{{.*}}] : !linalg.view<?x?x?xf32>
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-// CHECK: %{{.*}} = mulf %{{.*}}, %{{.*}} : f32
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-// CHECK: %{{.*}} = addf %{{.*}}, %{{.*}} : f32
-// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?xf32>
-
-func @conv_view4(%arg0: !linalg.view<?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?xf32>) {
- linalg.conv(%arg0, %arg1, %arg2) {dilations = [4, 5], strides = [2, 3]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @conv_view4(%{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>) {
-// CHECK: %[[Z0:.*]] = linalg.dim %arg0, 0 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[Z1:.*]] = linalg.dim %arg0, 1 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[Q:.*]] = linalg.dim %arg0, 2 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[K:.*]] = linalg.dim %arg0, 3 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[B:.*]] = linalg.dim %arg1, 0 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[X0:.*]] = linalg.dim %arg2, 1 : !linalg.view<?x?x?x?xf32>
-// CHECK: %[[X1:.*]] = linalg.dim %arg2, 2 : !linalg.view<?x?x?x?xf32>
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[X1]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[K]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z0]] step %{{.*}} {
-// CHECK: loop.for %{{.*}} = %{{.*}} to %[[Z1]] step %{{.*}} {
-// CHECK: %[[SUM0:.*]] = affine.apply #map1(%{{.*}}, %{{.*}})
-// CHECK: %[[SUM1:.*]] = affine.apply #map2(%{{.*}}, %{{.*}})
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %[[SUM0]], %[[SUM1]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
-// CHECK: %{{.*}} = mulf %{{.*}}, %{{.*}} : f32
-// CHECK: %{{.*}} = linalg.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
-// CHECK: %{{.*}} = addf %{{.*}}, %{{.*}} : f32
-// CHECK: linalg.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?x?x?xf32>
-
-func @foo(%0: f32, %1: f32, %2: f32) -> (f32, f32) {
- %f0 = constant 0.0 : f32
- return %f0, %f0 : f32, f32
-}
-#accesses = [
- (i, j, k) -> (i, j),
- (i, j, k) -> (i, j, k),
- (i, j, k) -> (i, k, j)
-]
-#trait = {
- n_views = [1, 2],
- n_loop_types = [3, 0, 0],
- indexing_maps = #accesses,
- fun = @foo,
- library_call = "external_function_name",
- doc = "B(i,j,k), C(i,k,j) = foo(A(i, j), B(i,j,k), C(i,k,j))"
-}
-func @generic_function(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
- linalg.generic #trait %arg0, %arg1, %arg2:
- !linalg.view<?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: @foo
-// CHECK-LABEL: @generic_function
-// CHECK: loop.for %[[i:.*]] = {{.*}}
-// CHECK: loop.for %[[j:.*]] = {{.*}}
-// CHECK: loop.for %[[k:.*]] = {{.*}}
-// CHECK: %[[a:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]]] : !linalg.view<?x?xf32>
-// CHECK: %[[b:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
-// CHECK: %[[c:.*]] = linalg.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
-// CHECK: %[[res:.*]]:2 = call @foo(%[[a]], %[[b]], %[[c]]) : (f32, f32, f32) -> (f32, f32)
-// CHECK: linalg.store %[[res]]#0, %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
-// CHECK: linalg.store %[[res]]#1, %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
-
-#trait2 = {
- n_views = [1, 2],
- n_loop_types = [3, 0, 0],
- indexing_maps = #accesses,
- library_call = "external_function_name",
- doc = "B(i,j,k), C(i,k,j) = foo(A(i, j), B(i,j,k), C(i,k,j))"
-}
-func @generic_region(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
- linalg.generic #trait2 %arg0, %arg1, %arg2 {
- ^bb0(%a: f32, %b: f32, %c: f32):
- %d = mulf %a, %b : f32
- %e = addf %c, %d : f32
- linalg.yield %d, %e : f32, f32
- }: !linalg.view<?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: @generic_region
-// CHECK: loop.for %[[i:.*]] = {{.*}}
-// CHECK: loop.for %[[j:.*]] = {{.*}}
-// CHECK: loop.for %[[k:.*]] = {{.*}}
-// CHECK: %[[a:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]]] : !linalg.view<?x?xf32>
-// CHECK: %[[b:.*]] = linalg.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
-// CHECK: %[[c:.*]] = linalg.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
-// CHECK: %[[d:.*]] = mulf %[[a]], %[[b]] : f32
-// CHECK: %[[e:.*]] = addf %[[c]], %[[d]] : f32
-// CHECK: linalg.store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : !linalg.view<?x?x?xf32>
-// CHECK: linalg.store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : !linalg.view<?x?x?xf32>
+++ /dev/null
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,4 -linalg-tile-promote-full-tile-views=true | FileCheck %s -check-prefix=TILE-1D
-
-func @matmul(%arg0: !linalg.buffer<?xf32>, %arg1: index, %arg2: index, %arg3: index) {
- %c0 = constant 0 : index
- %c1 = constant 1 : index
- %I = linalg.range %c0:%arg1:%c1 : !linalg.range
- %J = linalg.range %c0:%arg2:%c1 : !linalg.range
- %K = linalg.range %c0:%arg3:%c1 : !linalg.range
- %A = linalg.view %arg0[%I, %K] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %B = linalg.view %arg0[%K, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %C = linalg.view %arg0[%I, %J] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- linalg.matmul(%A, %B, %C) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return
-}
-// TILE-1D-LABEL: func @matmul(%{{.*}}: !linalg.buffer<?xf32>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// TILE-1D: loop.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} {
-// TILE-1D: %[[vA:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
-// TILE-1D: %[[vB:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
-// TILE-1D: %[[vC:.*]] = linalg.subview {{.*}} : !linalg.view<?x?xf32>
-///
-// TILE-1D: %[[tmpA:.*]] = linalg.buffer_alloc : !linalg.buffer<8xf32>
-// TILE-1D: %[[fullA:.*]] = linalg.view %[[tmpA]][{{.*}}] : !linalg.buffer<8xf32> -> !linalg.view<?x?xf32>
-// TILE-1D: %[[partialA:.*]] = linalg.slice %[[fullA]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
-///
-// TILE-1D: %[[tmpB:.*]] = linalg.buffer_alloc : !linalg.buffer<12xf32>
-// TILE-1D: %[[fullB:.*]] = linalg.view %[[tmpB]][{{.*}}] : !linalg.buffer<12xf32> -> !linalg.view<?x?xf32>
-// TILE-1D: %[[partialB:.*]] = linalg.slice %[[fullB]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
-///
-// TILE-1D: %[[tmpC:.*]] = linalg.buffer_alloc : !linalg.buffer<6xf32>
-// TILE-1D: %[[fullC:.*]] = linalg.view %[[tmpC]][{{.*}}] : !linalg.buffer<6xf32> -> !linalg.view<?x?xf32>
-// TILE-1D: %[[partialC:.*]] = linalg.slice %[[fullC]][%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
-
-// TILE-1D: linalg.fill(%[[fullA]], {{.*}}) : !linalg.view<?x?xf32>, f32
-// TILE-1D: linalg.fill(%[[fullB]], {{.*}}) : !linalg.view<?x?xf32>, f32
-// TILE-1D: linalg.fill(%[[fullC]], {{.*}}) : !linalg.view<?x?xf32>, f32
-// TILE-1D: linalg.copy(%[[vA]], %[[partialA]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-// TILE-1D: linalg.copy(%[[vB]], %[[partialB]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-// TILE-1D: linalg.copy(%[[vC]], %[[partialC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-//
-// TILE-1D: linalg.matmul(%[[fullA]], %[[fullB]], %[[fullC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-//
-// TILE-1D: linalg.copy(%[[partialC]], %[[vC]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-//
-// TILE-1D: linalg.buffer_dealloc %[[tmpA]] : !linalg.buffer<8xf32>
-// TILE-1D: linalg.buffer_dealloc %[[tmpB]] : !linalg.buffer<12xf32>
-// TILE-1D: linalg.buffer_dealloc %[[tmpC]] : !linalg.buffer<6xf32>
+++ /dev/null
-// RUN: mlir-opt %s | mlir-opt | FileCheck %s
-
-// CHECK-DAG: #[[map0:.*]] = (d0, d1, d2) -> (d0, d2, d1)
-// CHECK-DAG: #[[map1:.*]] = (d0, d1, d2) -> (d2, d1, d0)
-
-func @range(%arg0: index, %arg1: index, %arg2: index) {
- %0 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
- return
-}
-// CHECK-LABEL: func @range(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK-NEXT: linalg.range %{{.*}}:%{{.*}}:%{{.*}} : !linalg.range
-
-func @buffer_size(%arg0: !linalg.buffer<?xf32>) -> index {
- %0 = linalg.buffer_size %arg0 : !linalg.buffer<?xf32>
- return %0 : index
-}
-// CHECK-LABEL: func @buffer_size
-// CHECK: linalg.buffer_size {{.*}} : !linalg.buffer<?xf32>
-
-func @buffer(%arg0: index, %arg1: index) {
- %0 = muli %arg0, %arg0 : index
- %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xvector<4xi8>>
- %2 = linalg.buffer_alloc %0 {alignment = 16} : !linalg.buffer<?xvector<4xi8>>
- %3 = linalg.buffer_alloc : !linalg.buffer<17xvector<4xi8>>
- %4 = linalg.buffer_alloc {alignment = 32} : !linalg.buffer<17xvector<4xi8>>
- linalg.buffer_dealloc %4 : !linalg.buffer<17xvector<4xi8>>
- linalg.buffer_dealloc %3 : !linalg.buffer<17xvector<4xi8>>
- linalg.buffer_dealloc %2 : !linalg.buffer<?xvector<4xi8>>
- linalg.buffer_dealloc %1 : !linalg.buffer<?xvector<4xi8>>
- return
-}
-// CHECK-LABEL: func @buffer(%{{.*}}: index, %{{.*}}: index) {
-// CHECK-NEXT: muli %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_alloc %{{.*}} {alignment = 16 : i64} : !linalg.buffer<?xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_alloc : !linalg.buffer<17xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_alloc {alignment = 32 : i64} : !linalg.buffer<17xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<17xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<17xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xvector<4xi8>>
-
-func @view_fun(%arg0: !linalg.view<?x?xvector<3x4xi4>>) {
- return
-}
-// CHECK-LABEL: func @view_fun(%{{.*}}: !linalg.view<?x?xvector<3x4xi4>>) {
-
-func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) {
- %0 = muli %arg0, %arg0 : index
- %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xf32>
- %2 = linalg.range %arg2:%arg3:%arg4 : !linalg.range
- %3 = linalg.view %1[%2, %2] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
- %4 = linalg.slice %3[%2, %2] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
- %5 = linalg.slice %3[%2, %arg2] : !linalg.view<?x?xf32>, !linalg.range, index, !linalg.view<?xf32>
- %6 = linalg.slice %3[%arg2, %2] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
- %7 = linalg.slice %3[%arg2, %arg3] : !linalg.view<?x?xf32>, index, index, !linalg.view<f32>
- %8 = linalg.view %1[%2, %2] : !linalg.buffer<?xf32> -> !linalg.view<?x?xvector<4x4xf32>>
- linalg.buffer_dealloc %1 : !linalg.buffer<?xf32>
- return
-}
-// CHECK-LABEL: func @views(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK-NEXT: muli %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xf32>
-// CHECK-NEXT: linalg.range %{{.*}}:%{{.*}}:%{{.*}} : !linalg.range
-// CHECK-NEXT: linalg.view %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xf32>
-// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
-// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, index, !linalg.view<?xf32>
-// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, index, !linalg.range, !linalg.view<?xf32>
-// CHECK-NEXT: linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.view<?x?xf32>, index, index, !linalg.view<f32>
-// CHECK-NEXT: linalg.view %{{.*}}[%{{.*}}, %{{.*}}] : !linalg.buffer<?xf32> -> !linalg.view<?x?xvector<4x4xf32>>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xf32>
-
-func @ops(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<?xf32>, %arg3: !linalg.view<f32>) {
- linalg.matmul(%arg0, %arg0, %arg0) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- linalg.matvec(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
- linalg.dot(%arg1, %arg2, %arg3) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
- return
-}
-// CHECK-LABEL: func @ops(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// CHECK-NEXT: linalg.matmul(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-// CHECK-NEXT: linalg.matvec(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
-// CHECK-NEXT: linalg.dot(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
-
-func @dim(%arg0: !linalg.view<?x?xf32>) {
- %0 = linalg.dim %arg0, 1 : !linalg.view<?x?xf32>
- %1 = linalg.buffer_alloc %0 : !linalg.buffer<?xf32>
- linalg.buffer_dealloc %1 : !linalg.buffer<?xf32>
- return
-}
-// CHECK-LABEL: func @dim(%{{.*}}: !linalg.view<?x?xf32>) {
-// CHECK-NEXT: linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// CHECK-NEXT: linalg.buffer_alloc %{{.*}} : !linalg.buffer<?xf32>
-// CHECK-NEXT: linalg.buffer_dealloc %{{.*}} : !linalg.buffer<?xf32>
-
-func @linalg_for(%arg0 : index, %arg1 : index, %arg2 : index) {
- loop.for %i0 = %arg0 to %arg1 step %arg2 {
- loop.for %i1 = %arg0 to %arg1 step %arg2 {
- %min_cmp = cmpi "slt", %i0, %i1 : index
- %min = select %min_cmp, %i0, %i1 : index
- %max_cmp = cmpi "sge", %i0, %i1 : index
- %max = select %max_cmp, %i0, %i1 : index
- loop.for %i2 = %min to %max step %i1 {
- }
- }
- }
- return
-}
-// CHECK-LABEL: func @linalg_for(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
-// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
-// CHECK-NEXT: cmpi "slt", %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: select %{{.*}}, %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: cmpi "sge", %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: select %{{.*}}, %{{.*}}, %{{.*}} : index
-// CHECK-NEXT: loop.for %{{.*}} to %{{.*}} step %{{.*}} {
-
-func @fill_view(%arg0: !linalg.view<?xf32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<?xf32>, f32
- return
-}
-// CHECK-LABEL: func @fill_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: f32) {
-// CHECK: linalg.fill(%{{.*}}, %{{.*}}) : !linalg.view<?xf32>, f32
-
-func @transpose(%arg0: !linalg.view<?x?x?xf32>) {
- %0 = linalg.transpose %arg0 (i, j, k) -> (k, j, i) : !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @transpose
-// CHECK: linalg.transpose %{{.*}} ([[i:.*]], [[j:.*]], [[k:.*]]) -> ([[k]], [[j]], [[i]]) : !linalg.view<?x?x?xf32>
-
-func @fill_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<?x?x?xf32>, f32
- return
-}
-// CHECK-LABEL: func @fill_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: f32) {
-// CHECK: linalg.fill(%{{.*}}, %{{.*}}) : !linalg.view<?x?x?xf32>, f32
-
-func @copy_view(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>) {
- linalg.copy(%arg0, %arg1) : !linalg.view<?xf32>, !linalg.view<?xf32>
- return
-}
-// CHECK-LABEL: func @copy_view(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// CHECK: linalg.copy(%{{.*}}, %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>
-
-func @copy_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.copy(%arg0, %arg1) {inputPermutation = (i, j, k) -> (i, k, j),
- outputPermutation = (i, j, k) -> (k, j, i)} :
- !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @copy_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
-// CHECK: linalg.copy(%{{.*}}, %{{.*}}) {inputPermutation = #[[map0]], outputPermutation = #[[map1]]} : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
-
-func @conv_view3(%arg0: !linalg.view<?x?x?xf32>, %arg1: !linalg.view<?x?x?xf32>, %arg2: !linalg.view<?x?x?xf32>) {
- linalg.conv(%arg0, %arg1, %arg2) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @conv_view3(%{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?xf32>) {
-// CHECK: linalg.conv(%{{.*}}, %{{.*}}, %{{.*}}) : !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>, !linalg.view<?x?x?xf32>
-
-func @conv_view6(%arg0: !linalg.view<?x?x?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?x?x?xf32>) {
- linalg.conv(%arg0, %arg1, %arg2) {dilations = [4, 4, 5, 5], strides = [2, 2, 3, 3]} : !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @conv_view6(%{{.*}}: !linalg.view<?x?x?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?x?x?xf32>) {
-// CHECK: linalg.conv(%{{.*}}, %{{.*}}, %{{.*}}) {dilations = [4, 4, 5, 5], strides = [2, 2, 3, 3]} : !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>, !linalg.view<?x?x?x?x?x?xf32>
-
-func @subview(%arg0: !linalg.view<?x?xvector<3x4xi4>>) {
- %c0 = constant 0 : index
- %0 = linalg.subview %arg0[%c0, %c0, %c0, %c0, %c0, %c0] : !linalg.view<?x?xvector<3x4xi4>>
- return
-}
-// CHECK-LABEL: func @subview(%{{.*}}: !linalg.view<?x?xvector<3x4xi4>>) {
-// CHECK: constant 0 : index
-// CHECK: linalg.subview %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : !linalg.view<?x?xvector<3x4xi4>>
-
-func @const_buffer_view(%arg0: index, %arg1: index, %arg2: index) {
- %c0 = linalg.buffer_alloc : !linalg.buffer<17xf32>
- %c1 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
- %c2 = linalg.view %c0[%c1] : !linalg.buffer<17xf32> -> !linalg.view<?xf32>
- return
-}
-
-#accesses = [
- (i, j, k) -> (j, i),
- (i, j, k) -> (i, k, i + j)
-]
-#trait = {
- indexing_maps = #accesses,
- n_views = [1, 1],
- n_loop_types = [3, 0, 0],
- fun = @foo,
- library_call = "external_function_name"
-}
-func @foo(%0: vector<3x4xi4>, %1: f32) -> f32 {
- %f0 = constant 0.0 : f32
- return %f0 : f32
-}
-func @generic(%arg0: !linalg.view<?x?xvector<3x4xi4>>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.generic #trait %arg0, %arg1 {foo = 1} : !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @foo
-// CHECK-LABEL: func @generic
-// CHECK: linalg.generic {fun = @foo, indexing_maps = [#map2, #map3], library_call = "external_function_name", n_loop_types = [3, 0, 0], n_views = [1, 1]} %{{.*}}, %{{.*}} {foo = 1 : i64}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
-
-#trait2 = {
- indexing_maps = #accesses,
- n_views = [1, 1],
- n_loop_types = [3, 0, 0],
- library_call = "external_function_name"
-}
-func @generic_region(%arg0: !linalg.view<?x?xvector<3x4xi4>>, %arg1: !linalg.view<?x?x?xf32>) {
- linalg.generic #trait2 %arg0, %arg1 {
- ^bb(%a: vector<3x4xi4>, %b: f32) :
- linalg.yield %b : f32
- } {foo = 1}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
- return
-}
-// CHECK-LABEL: func @generic_region
-// CHECK: linalg.generic {indexing_maps = [#map2, #map3], library_call = "external_function_name", n_loop_types = [3, 0, 0], n_views = [1, 1]} %{{.*}}, %{{.*}} {
-// CHECK: ^{{.*}}(%{{.*}}: vector<3x4xi4>, %{{.*}}: f32): // no predecessors
-// CHECK: linalg.yield %{{.*}} : f32
-// CHECK: } {foo = 1 : i64}: !linalg.view<?x?xvector<3x4xi4>>, !linalg.view<?x?x?xf32>
\ No newline at end of file
+++ /dev/null
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2 | FileCheck %s -check-prefix=TILE-2
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=0,2 | FileCheck %s -check-prefix=TILE-02
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=0,0,2 | FileCheck %s -check-prefix=TILE-002
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,4 | FileCheck %s -check-prefix=TILE-234
-
-// TILE-2-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
-// TILE-02-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
-// TILE-002-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
-// TILE-234-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
-// TILE-234-DAG: #[[UB1:.*]] = (d0) -> (d0 + 3)
-// TILE-234-DAG: #[[UB2:.*]] = (d0) -> (d0 + 4)
-
-func @matmul(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>, %arg2: !linalg.view<?x?xf32>) {
- linalg.matmul(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return
-}
-// TILE-2-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
-// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[K]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-2: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-2: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[c]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-2: linalg.matmul(%[[sAi]], %{{.*}}, %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-
-// TILE-02-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
-// TILE-02: %[[N:.*]] = linalg.dim %arg1, 1 : !linalg.view<?x?xf32>
-// TILE-02: loop.for %{{.*}} = %{{.*}} to %[[N]] step %{{.*}} {
-// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-02: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-02: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[K]], %{{.*}}, %{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-02: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-02: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-02: %[[sCj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[c]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-02: linalg.matmul(%{{.*}}, %[[sBj]], %[[sCj]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-
-// TILE-002-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
-// TILE-002: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-002: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-// TILE-002: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-002: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-002: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-002: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-002: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-002: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-002: linalg.matmul(%[[sAj]], %[[sBj]], %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-
-// TILE-234-LABEL: func @matmul(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?x?xf32>) {
-// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-234: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[N]] step %{{.*}} {
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[ak:.*]] = affine.apply #[[UB2]](%{{.*}})
-// TILE-234: %[[sAik:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[ak]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-234: %[[bk:.*]] = affine.apply #[[UB2]](%{{.*}})
-// TILE-234: %[[bj:.*]] = affine.apply #[[UB1]](%{{.*}})
-// TILE-234: %[[sBkj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[bk]], %{{.*}}, %{{.*}}, %[[bj]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-234: %[[ci:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[cj:.*]] = affine.apply #[[UB1]](%{{.*}})
-// TILE-234: %[[sCij:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ci]], %{{.*}}, %{{.*}}, %[[cj]], %{{.*}}] : !linalg.view<?x?xf32>
-//
-// TILE-234: linalg.matmul(%[[sAik]], %[[sBkj]], %[[sCij]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
-
-func @matvec(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<?xf32>) {
- linalg.matvec(%arg0, %arg1, %arg2) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
- return
-}
-// TILE-2-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[N:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}, %{{.*}}, %[[N]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-2: %[[c:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[c]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-2: linalg.matvec(%[[sAi]], %{{.*}}, %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
-
-// TILE-02-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// TILE-02: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-02: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-// TILE-02: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-02: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-02: %[[sAj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[M]], %{{.*}}, %{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-02: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-02: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-02: linalg.matvec(%[[sAj]], %[[sBj]], %{{.*}}) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
-
-// TILE-002-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// TILE-002-NOT: loop.for
-
-// TILE-234-LABEL: func @matvec(%{{.*}}: !linalg.view<?x?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>) {
-// TILE-234: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?xf32>
-// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?xf32>
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-// TILE-234: %[[ai:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[aj:.*]] = affine.apply #[[UB1]](%{{.*}})
-// TILE-234: %[[sAij:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ai]], %{{.*}}, %{{.*}}, %[[aj]], %{{.*}}] : !linalg.view<?x?xf32>
-// TILE-234: %[[bj:.*]] = affine.apply #[[UB1]](%{{.*}})
-// TILE-234: %[[sBj:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[bj]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-234: %[[ci:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[sCi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[ci]], %{{.*}}] : !linalg.view<?xf32>
-//
-// TILE-234: linalg.matvec(%[[sAij]], %[[sBj]], %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
-
-func @dot(%arg0: !linalg.view<?xf32>, %arg1: !linalg.view<?xf32>, %arg2: !linalg.view<f32>) {
- linalg.dot(%arg0, %arg1, %arg2) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
- return
-}
-// TILE-2-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-2: %[[M:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
-// TILE-2: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
-// TILE-2: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-2: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-2: %[[sBi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-2: linalg.dot(%[[sAi]], %[[sBi]], {{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
-
-// TILE-02-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-02-NOT: loop.for
-
-// TILE-002-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-002-NOT: loop.for
-
-// TILE-234-LABEL: func @dot(%{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<?xf32>, %{{.*}}: !linalg.view<f32>) {
-// TILE-234: %[[K:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?xf32>
-// TILE-234: loop.for %{{.*}} = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-// TILE-234: %[[a:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[sAi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[a]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-234: %[[b:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-234: %[[sBi:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[b]], %{{.*}}] : !linalg.view<?xf32>
-// TILE-234: linalg.dot(%[[sAi]], %[[sBi]], %{{.*}}) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
-
-func @fill(%arg0: !linalg.view<?x?xf32>, %arg1: f32) {
- linalg.fill(%arg0, %arg1) : !linalg.view<?x?xf32>, f32
- return
-}
-// TILE-2-LABEL: func @fill
-// TILE-2: for
-// TILE-2-NOT: for
-// TILE-2: fill{{.*}} f32
-
-// TILE-02-LABEL: func @fill
-// TILE-02: for
-// TILE-02-NOT: for
-// TILE-02: fill{{.*}} f32
-
-// TILE-002-LABEL: func @fill
-// TILE-002-NOT: for
-// TILE-002: fill{{.*}} f32
-
-// TILE-234-LABEL: func @fill
-// TILE-234: for
-// TILE-234: for
-// TILE-234-NOT: for
-// TILE-234: fill{{.*}} f32
-
-#id_2d = (i, j) -> (i, j)
-#pointwise_2d_trait = {
- indexing_maps = [#id_2d, #id_2d, #id_2d],
- n_loop_types = [2, 0, 0],
- n_views = [2, 1]
-}
-
-func @pointwise(%arg0: !linalg.view<?x?xf32>, %arg1: !linalg.view<?x?xf32>,
- %arg2: !linalg.view<?x?xf32>) {
- linalg.generic #pointwise_2d_trait %arg0, %arg1, %arg2 {
- ^bb0(%arg4: f32, %arg5: f32, %arg6: f32): // no predecessors
- %4 = addf %arg4, %arg5 : f32
- linalg.yield %4 : f32
- }: !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
- return
-}
-// TILE-2-LABEL: func @pointwise
-// TILE-2: for
-// TILE-2-NOT: for
-// TILE-2: linalg.generic
-
-// TILE-02-LABEL: func @pointwise
-// TILE-02: for
-// TILE-02-NOT: for
-// TILE-02: linalg.generic
-
-// TILE-002-LABEL: func @pointwise
-// TILE-002-NOT: for
-// TILE-002: linalg.generic
-
-// TILE-234-LABEL: func @pointwise
-// TILE-234: for
-// TILE-234: for
-// TILE-234-NOT: for
-// TILE-234: linalg.generic
+++ /dev/null
-// RUN: mlir-opt %s -linalg-tile -linalg-tile-sizes=2,3,0,0,4 | FileCheck %s -check-prefix=TILE-23004
-
-// TILE-23004-DAG: #[[UB0:.*]] = (d0) -> (d0 + 2)
-// TILE-23004-DAG: #[[UB1:.*]] = (d0) -> (d0 + 3)
-// TILE-23004-DAG: #[[UB2:.*]] = (d0) -> (d0 + 4)
-// TILE-23004-DAG: #[[D0x30pS0x10:.*]] = (d0) -> (d0 * 30)
-// TILE-23004-DAG: #[[D0x30pS0x10p90:.*]] = (d0)[s0] -> (d0 * 30 + s0 * 10 + 90)
-func @conv(%arg0: !linalg.view<?x?x?x?xf32>, %arg1: !linalg.view<?x?x?x?xf32>, %arg2: !linalg.view<?x?x?x?xf32>) {
- linalg.conv(%arg0, %arg1, %arg2) {dilations = [10, 20], strides = [30, 40]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>
- return
-}
-// TILE-23004-LABEL: func @conv(%{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>, %{{.*}}: !linalg.view<?x?x?x?xf32>) {
-// TILE-23004: %[[Q:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[B:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[PaddedInput0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[X0:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[B]] step %{{.*}} {
-// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[X0]] step %{{.*}} {
-// TILE-23004: loop.for %{{.*}} = %{{.*}} to %[[Q]] step %{{.*}} {
-// TILE-23004: %[[Z0:.*]] = linalg.dim %{{.*}}, 0 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[Z1:.*]] = linalg.dim %{{.*}}, 1 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[I2p4:.*]] = affine.apply #[[UB2]](%{{.*}})
-// TILE-23004: %[[K:.*]] = linalg.dim %{{.*}}, 3 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[FilterView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[Z0]], %{{.*}}, %{{.*}}, %[[Z1]], %{{.*}}, %{{.*}}, %[[I2p4]], %{{.*}}, %{{.*}}, %[[K]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
-//
-// TILE-23004: %[[I0p3:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-23004: %[[I1:.*]] = affine.apply #[[D0x30pS0x10]](%{{.*}})
-// TILE-23004: %[[I1pStep:.*]] = affine.apply #[[D0x30pS0x10p90]](%{{.*}})[%[[PaddedInput0]]]
-// TILE-23004: %[[SZ2:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[I2p2:.*]] = affine.apply #[[UB2]](%{{.*}})
-// TILE-23004: %[[InputView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[I0p3]], %{{.*}}, %[[I1]], %[[I1pStep]], %{{.*}}, %{{.*}}, %[[SZ2]], %{{.*}}, %{{.*}}, %[[I2p2]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
-//
-// TILE-23004: %[[B:.*]] = affine.apply #[[UB0]](%{{.*}})
-// TILE-23004: %[[I1p3:.*]] = affine.apply #[[UB1]](%{{.*}})
-// TILE-23004: %[[X0:.*]] = linalg.dim %{{.*}}, 2 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[X1:.*]] = linalg.dim %{{.*}}, 3 : !linalg.view<?x?x?x?xf32>
-// TILE-23004: %[[OutputView:.*]] = linalg.subview %{{.*}}[%{{.*}}, %[[B]], %{{.*}}, %{{.*}}, %[[I1p3]], %{{.*}}, %{{.*}}, %[[X0]], %{{.*}}, %{{.*}}, %[[X1]], %{{.*}}] : !linalg.view<?x?x?x?xf32>
-//
-// TILE-23004: linalg.conv(%[[FilterView]], %[[InputView]], %[[OutputView]]) {dilations = [10, 20], strides = [30, 40]} : !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>, !linalg.view<?x?x?x?xf32>