blob: b872cb687fc722d6368c8aa15598ee439a8414de [file] [log] [blame]
// RUN: mlir-opt %s -loop-unroll-jam -unroll-jam-factor=2 | FileCheck %s
// CHECK-DAG: [[MAP_PLUS_1:#map[0-9]+]] = (d0) -> (d0 + 1)
// CHECK-DAG: [[M1:#map[0-9]+]] = ()[s0] -> (s0 + 8)
// CHECK-DAG: [[MAP_DIV_OFFSET:#map[0-9]+]] = ()[s0] -> (((s0 - 1) floordiv 2) * 2 + 1)
// CHECK-DAG: [[MAP_MULTI_RES:#map[0-9]+]] = ()[s0, s1] -> ((s0 floordiv 2) * 2, (s1 floordiv 2) * 2, 1024)
// CHECK-LABEL: func @unroll_jam_imperfect_nest() {
func @unroll_jam_imperfect_nest() {
// CHECK: %c100 = constant 100 : index
// CHECK-NEXT: for %i0 = 0 to 100 step 2 {
for %i = 0 to 101 {
// CHECK: %0 = "addi32"(%i0, %i0) : (index, index) -> i32
// CHECK-NEXT: %1 = affine.apply [[MAP_PLUS_1]](%i0)
// CHECK-NEXT: %2 = "addi32"(%1, %1) : (index, index) -> i32
%x = "addi32"(%i, %i) : (index, index) -> i32
for %j = 0 to 17 {
// CHECK: %3 = "addi32"(%i0, %i0) : (index, index) -> i32
// CHECK-NEXT: %4 = "addi32"(%3, %3) : (i32, i32) -> i32
// CHECK-NEXT: %5 = affine.apply [[MAP_PLUS_1]](%i0)
// CHECK-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> i32
// CHECK-NEXT: %7 = "addi32"(%6, %6) : (i32, i32) -> i32
%y = "addi32"(%i, %i) : (index, index) -> i32
%z = "addi32"(%y, %y) : (i32, i32) -> i32
}
// CHECK: %8 = "addi32"(%i0, %i0) : (index, index) -> i32
// CHECK-NEXT: %9 = affine.apply [[MAP_PLUS_1]](%i0)
// CHECK-NEXT: %10 = "addi32"(%9, %9) : (index, index) -> i32
%w = "addi32"(%i, %i) : (index, index) -> i32
} // CHECK }
// cleanup loop (single iteration)
// CHECK: %11 = "addi32"(%c100, %c100) : (index, index) -> i32
// CHECK-NEXT: for %i2 = 0 to 17 {
// CHECK-NEXT: %12 = "addi32"(%c100, %c100) : (index, index) -> i32
// CHECK-NEXT: %13 = "addi32"(%12, %12) : (i32, i32) -> i32
// CHECK-NEXT: }
// CHECK-NEXT: %14 = "addi32"(%c100, %c100) : (index, index) -> i32
return
}
// CHECK-LABEL: func @loop_nest_unknown_count_1(%arg0: index) {
func @loop_nest_unknown_count_1(%N : index) {
// CHECK-NEXT: for %i0 = 1 to [[MAP_DIV_OFFSET]]()[%arg0] step 2 {
// CHECK-NEXT: for %i1 = 1 to 100 {
// CHECK-NEXT: %0 = "foo"() : () -> i32
// CHECK-NEXT: %1 = "foo"() : () -> i32
// CHECK-NEXT: }
// CHECK-NEXT: }
// A cleanup loop should be generated here.
// CHECK-NEXT: for %i2 = [[MAP_DIV_OFFSET]]()[%arg0] to %arg0 {
// CHECK-NEXT: for %i3 = 1 to 100 {
// CHECK-NEXT: %2 = "foo"() : () -> i32
// CHECK_NEXT: }
// CHECK_NEXT: }
for %i = 1 to %N {
for %j = 1 to 100 {
%x = "foo"() : () -> i32
}
}
return
}
// CHECK-LABEL: func @loop_nest_unknown_count_2(%arg0: index) {
func @loop_nest_unknown_count_2(%arg : index) {
// CHECK-NEXT: for %i0 = %arg0 to [[M1]]()[%arg0] step 2 {
// CHECK-NEXT: for %i1 = 1 to 100 {
// CHECK-NEXT: %0 = "foo"(%i0) : (index) -> i32
// CHECK-NEXT: %1 = affine.apply #map{{[0-9]+}}(%i0)
// CHECK-NEXT: %2 = "foo"(%1) : (index) -> i32
// CHECK-NEXT: }
// CHECK-NEXT: }
// The cleanup loop is a single iteration one and is promoted.
// CHECK-NEXT: %3 = affine.apply [[M1]]()[%arg0]
// CHECK-NEXT: for %i2 = 1 to 100 {
// CHECK-NEXT: %4 = "foo"(%3) : (index) -> i32
// CHECK_NEXT: }
for %i = %arg to ()[s0] -> (s0+9) ()[%arg] {
for %j = 1 to 100 {
%x = "foo"(%i) : (index) -> i32
}
}
return
}
// CHECK-LABEL: func @loop_nest_symbolic_and_min_upper_bound
func @loop_nest_symbolic_and_min_upper_bound(%M : index, %N : index, %K : index) {
for %i = 0 to min ()[s0, s1] -> (s0, s1, 1024)()[%M, %N] {
for %j = 0 to %K {
"foo"(%i, %j) : (index, index) -> ()
}
}
return
}
// CHECK-NEXT: for %i0 = 0 to min [[MAP_MULTI_RES]]()[%arg0, %arg1] step 2 {
// CHECK-NEXT: for %i1 = 0 to %arg2 {
// CHECK-NEXT: "foo"(%i0, %i1) : (index, index) -> ()
// CHECK-NEXT: %0 = affine.apply #map2(%i0)
// CHECK-NEXT: "foo"(%0, %i1) : (index, index) -> ()
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: for %i2 = max [[MAP_MULTI_RES]]()[%arg0, %arg1] to min #map9()[%arg0, %arg1] {
// CHECK-NEXT: for %i3 = 0 to %arg2 {
// CHECK-NEXT: "foo"(%i2, %i3) : (index, index) -> ()
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: return