brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.2 KiB · efdceed Raw
789 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(affine-loop-unroll{unroll-factor=-1}))" | FileCheck %s --check-prefix UNROLL-FULL2// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(affine-loop-unroll{unroll-factor=-1 unroll-full-threshold=2}))" | FileCheck %s --check-prefix SHORT3// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(affine-loop-unroll{unroll-factor=4}))" | FileCheck %s --check-prefix UNROLL-BY-44// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(affine-loop-unroll{unroll-factor=1}))" | FileCheck %s --check-prefix UNROLL-BY-15// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(affine-loop-unroll{unroll-factor=5 cleanup-unroll=true}))" | FileCheck %s --check-prefix UNROLL-CLEANUP-LOOP6// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(gpu.module(gpu.func(affine-loop-unroll{unroll-factor=-1})))" | FileCheck %s --check-prefix GPU-UNROLL-FULL7 8// UNROLL-FULL-DAG: [[$MAP0:#map[0-9]*]] = affine_map<(d0) -> (d0 + 1)>9// UNROLL-FULL-DAG: [[$MAP1:#map[0-9]*]] = affine_map<(d0) -> (d0 + 2)>10// UNROLL-FULL-DAG: [[$MAP2:#map[0-9]*]] = affine_map<(d0) -> (d0 + 3)>11// UNROLL-FULL-DAG: [[$MAP3:#map[0-9]*]] = affine_map<(d0) -> (d0 + 4)>12// UNROLL-FULL-DAG: [[$MAP4:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 + 1)>13// UNROLL-FULL-DAG: [[$MAP5:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 + 3)>14// UNROLL-FULL-DAG: [[$MAP6:#map[0-9]*]] = affine_map<(d0)[s0] -> (d0 + s0 + 1)>15 16// SHORT-DAG: [[$MAP0:#map[0-9]*]] = affine_map<(d0) -> (d0 + 1)>17 18// UNROLL-BY-4-DAG: [[$MAP0:#map[0-9]*]] = affine_map<(d0) -> (d0 + 1)>19// UNROLL-BY-4-DAG: [[$MAP1:#map[0-9]*]] = affine_map<(d0) -> (d0 + 2)>20// UNROLL-BY-4-DAG: [[$MAP2:#map[0-9]*]] = affine_map<(d0) -> (d0 + 3)>21// UNROLL-BY-4-DAG: [[$MAP3:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 + 1)>22// UNROLL-BY-4-DAG: [[$MAP4:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 + 3)>23// UNROLL-BY-4-DAG: [[$MAP5:#map[0-9]*]] = affine_map<(d0)[s0] -> (d0 + s0 + 1)>24// UNROLL-BY-4-DAG: [[$MAP6:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 * 16 + d1)>25// UNROLL-BY-4-DAG: [[$MAP11:#map[0-9]*]] = affine_map<(d0) -> (d0)>26 27// UNROLL-FULL-LABEL: func @loop_nest_simplest() {28func.func @loop_nest_simplest() {29  // UNROLL-FULL: affine.for %arg0 = 0 to 100 step 2 {30  affine.for %i = 0 to 100 step 2 {31    // UNROLL-FULL: %c1_i32 = arith.constant 1 : i3232    // UNROLL-FULL-NEXT: %c1_i32_0 = arith.constant 1 : i3233    // UNROLL-FULL-NEXT: %c1_i32_1 = arith.constant 1 : i3234    // UNROLL-FULL-NEXT: %c1_i32_2 = arith.constant 1 : i3235    affine.for %j = 0 to 4 {36      %x = arith.constant 1 : i3237    }38  }       // UNROLL-FULL:  }39  return  // UNROLL-FULL:  return40}         // UNROLL-FULL }41 42// UNROLL-FULL-LABEL: func @loop_nest_simple_iv_use() {43func.func @loop_nest_simple_iv_use() {44  // UNROLL-FULL: %c0 = arith.constant 0 : index45  // UNROLL-FULL-NEXT: affine.for %arg0 = 0 to 100 step 2 {46  affine.for %i = 0 to 100 step 2 {47    // UNROLL-FULL: %0 = "addi32"(%c0, %c0) : (index, index) -> i3248    // UNROLL-FULL: %1 = affine.apply [[$MAP0]](%c0)49    // UNROLL-FULL-NEXT:  %2 = "addi32"(%1, %1) : (index, index) -> i3250    // UNROLL-FULL: %3 = affine.apply [[$MAP1]](%c0)51    // UNROLL-FULL-NEXT:  %4 = "addi32"(%3, %3) : (index, index) -> i3252    // UNROLL-FULL: %5 = affine.apply [[$MAP2]](%c0)53    // UNROLL-FULL-NEXT:  %6 = "addi32"(%5, %5) : (index, index) -> i3254    affine.for %j = 0 to 4 {55      %x = "addi32"(%j, %j) : (index, index) -> i3256    }57  }       // UNROLL-FULL:  }58  return  // UNROLL-FULL:  return59}         // UNROLL-FULL }60 61// Operations in the loop body have results that are used therein.62// UNROLL-FULL-LABEL: func @loop_nest_body_def_use() {63func.func @loop_nest_body_def_use() {64  // UNROLL-FULL: %c0 = arith.constant 0 : index65  // UNROLL-FULL-NEXT: affine.for %arg0 = 0 to 100 step 2 {66  affine.for %i = 0 to 100 step 2 {67    // UNROLL-FULL: %c0_0 = arith.constant 0 : index68    %c0 = arith.constant 0 : index69    // UNROLL-FULL:      %0 = affine.apply [[$MAP0]](%c0)70    // UNROLL-FULL-NEXT: %1 = "addi32"(%0, %c0_0) : (index, index) -> index71    // UNROLL-FULL-NEXT: %2 = affine.apply [[$MAP0]](%c0)72    // UNROLL-FULL-NEXT: %3 = affine.apply [[$MAP0]](%2)73    // UNROLL-FULL-NEXT: %4 = "addi32"(%3, %c0_0) : (index, index) -> index74    // UNROLL-FULL-NEXT: %5 = affine.apply [[$MAP1]](%c0)75    // UNROLL-FULL-NEXT: %6 = affine.apply [[$MAP0]](%5)76    // UNROLL-FULL-NEXT: %7 = "addi32"(%6, %c0_0) : (index, index) -> index77    // UNROLL-FULL-NEXT: %8 = affine.apply [[$MAP2]](%c0)78    // UNROLL-FULL-NEXT: %9 = affine.apply [[$MAP0]](%8)79    // UNROLL-FULL-NEXT: %10 = "addi32"(%9, %c0_0) : (index, index) -> index80    affine.for %j = 0 to 4 {81      %x = "affine.apply" (%j) { map = affine_map<(d0) -> (d0 + 1)> } :82        (index) -> (index)83      %y = "addi32"(%x, %c0) : (index, index) -> index84    }85  }       // UNROLL-FULL:  }86  return  // UNROLL-FULL:  return87}         // UNROLL-FULL }88 89// UNROLL-FULL-LABEL: func @loop_nest_strided() {90func.func @loop_nest_strided() {91  // UNROLL-FULL: %c2 = arith.constant 2 : index92  // UNROLL-FULL-NEXT: %c2_0 = arith.constant 2 : index93  // UNROLL-FULL-NEXT: affine.for %arg0 = 0 to 100 {94  affine.for %i = 0 to 100 {95    // UNROLL-FULL:      %0 = affine.apply [[$MAP0]](%c2_0)96    // UNROLL-FULL-NEXT: %1 = "addi32"(%0, %0) : (index, index) -> index97    // UNROLL-FULL-NEXT: %2 = affine.apply [[$MAP1]](%c2_0)98    // UNROLL-FULL-NEXT: %3 = affine.apply [[$MAP0]](%2)99    // UNROLL-FULL-NEXT: %4 = "addi32"(%3, %3) : (index, index) -> index100    affine.for %j = 2 to 6 step 2 {101      %x = "affine.apply" (%j) { map = affine_map<(d0) -> (d0 + 1)> } :102        (index) -> (index)103      %y = "addi32"(%x, %x) : (index, index) -> index104    }105    // UNROLL-FULL:      %5 = affine.apply [[$MAP0]](%c2)106    // UNROLL-FULL-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> index107    // UNROLL-FULL-NEXT: %7 = affine.apply [[$MAP1]](%c2)108    // UNROLL-FULL-NEXT: %8 = affine.apply [[$MAP0]](%7)109    // UNROLL-FULL-NEXT: %9 = "addi32"(%8, %8) : (index, index) -> index110    // UNROLL-FULL-NEXT: %10 = affine.apply [[$MAP3]](%c2)111    // UNROLL-FULL-NEXT: %11 = affine.apply [[$MAP0]](%10)112    // UNROLL-FULL-NEXT: %12 = "addi32"(%11, %11) : (index, index) -> index113    affine.for %k = 2 to 7 step 2 {114      %z = "affine.apply" (%k) { map = affine_map<(d0) -> (d0 + 1)> } :115        (index) -> (index)116      %w = "addi32"(%z, %z) : (index, index) -> index117    }118  }       // UNROLL-FULL:  }119  return  // UNROLL-FULL:  return120}         // UNROLL-FULL }121 122// UNROLL-FULL-LABEL: func @loop_nest_multiple_results() {123func.func @loop_nest_multiple_results() {124  // UNROLL-FULL: %c0 = arith.constant 0 : index125  // UNROLL-FULL-NEXT: affine.for %arg0 = 0 to 100 {126  affine.for %i = 0 to 100 {127    // UNROLL-FULL: %0 = affine.apply [[$MAP4]](%arg0, %c0)128    // UNROLL-FULL-NEXT: %1 = "addi32"(%0, %0) : (index, index) -> index129    // UNROLL-FULL-NEXT: %2 = affine.apply #map{{.*}}(%arg0, %c0)130    // UNROLL-FULL-NEXT: %3:2 = "fma"(%2, %0, %0) : (index, index, index) -> (index, index)131    // UNROLL-FULL-NEXT: %4 = affine.apply #map{{.*}}(%c0)132    // UNROLL-FULL-NEXT: %5 = affine.apply #map{{.*}}(%arg0, %4)133    // UNROLL-FULL-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> index134    // UNROLL-FULL-NEXT: %7 = affine.apply #map{{.*}}(%arg0, %4)135    // UNROLL-FULL-NEXT: %8:2 = "fma"(%7, %5, %5) : (index, index, index) -> (index, index)136    affine.for %j = 0 to 2 step 1 {137      %x = affine.apply affine_map<(d0, d1) -> (d0 + 1)> (%i, %j)138      %y = "addi32"(%x, %x) : (index, index) -> index139      %z = affine.apply affine_map<(d0, d1) -> (d0 + 3)> (%i, %j)140      %w:2 = "fma"(%z, %x, %x) : (index, index, index) -> (index, index)141    }142  }       // UNROLL-FULL:  }143  return  // UNROLL-FULL:  return144}         // UNROLL-FULL }145 146 147// Imperfect loop nest. Unrolling innermost here yields a perfect nest.148// UNROLL-FULL-LABEL: func @loop_nest_seq_imperfect(%arg0: memref<128x128xf32>) {149func.func @loop_nest_seq_imperfect(%a : memref<128x128xf32>) {150  // UNROLL-FULL: %c0 = arith.constant 0 : index151  // UNROLL-FULL-NEXT: %c128 = arith.constant 128 : index152  %c128 = arith.constant 128 : index153  // UNROLL-FULL: affine.for %arg1 = 0 to 100 {154  affine.for %i = 0 to 100 {155    // UNROLL-FULL: %0 = "vld"(%arg1) : (index) -> i32156    %ld = "vld"(%i) : (index) -> i32157    // UNROLL-FULL: %1 = affine.apply [[$MAP0]](%c0)158    // UNROLL-FULL-NEXT: %2 = "vmulf"(%c0, %1) : (index, index) -> index159    // UNROLL-FULL-NEXT: %3 = "vaddf"(%2, %2) : (index, index) -> index160    // UNROLL-FULL-NEXT: %4 = affine.apply [[$MAP0]](%c0)161    // UNROLL-FULL-NEXT: %5 = affine.apply [[$MAP0]](%4)162    // UNROLL-FULL-NEXT: %6 = "vmulf"(%4, %5) : (index, index) -> index163    // UNROLL-FULL-NEXT: %7 = "vaddf"(%6, %6) : (index, index) -> index164    // UNROLL-FULL-NEXT: %8 = affine.apply [[$MAP1]](%c0)165    // UNROLL-FULL-NEXT: %9 = affine.apply [[$MAP0]](%8)166    // UNROLL-FULL-NEXT: %10 = "vmulf"(%8, %9) : (index, index) -> index167    // UNROLL-FULL-NEXT: %11 = "vaddf"(%10, %10) : (index, index) -> index168    // UNROLL-FULL-NEXT: %12 = affine.apply [[$MAP2]](%c0)169    // UNROLL-FULL-NEXT: %13 = affine.apply [[$MAP0]](%12)170    // UNROLL-FULL-NEXT: %14 = "vmulf"(%12, %13) : (index, index) -> index171    // UNROLL-FULL-NEXT: %15 = "vaddf"(%14, %14) : (index, index) -> index172    affine.for %j = 0 to 4 {173      %x = "affine.apply" (%j) { map = affine_map<(d0) -> (d0 + 1)> } :174        (index) -> (index)175       %y = "vmulf"(%j, %x) : (index, index) -> index176       %z = "vaddf"(%y, %y) : (index, index) -> index177    }178    // UNROLL-FULL: %16 = "scale"(%c128, %arg1) : (index, index) -> index179    %addr = "scale"(%c128, %i) : (index, index) -> index180    // UNROLL-FULL: "vst"(%16, %arg1) : (index, index) -> ()181    "vst"(%addr, %i) : (index, index) -> ()182  }       // UNROLL-FULL }183  return  // UNROLL-FULL:  return184}185 186// UNROLL-FULL-LABEL: func @loop_nest_seq_multiple() {187func.func @loop_nest_seq_multiple() {188  // UNROLL-FULL: c0 = arith.constant 0 : index189  // UNROLL-FULL-NEXT: %c0_0 = arith.constant 0 : index190  // UNROLL-FULL-NEXT: %0 = affine.apply [[$MAP0]](%c0_0)191  // UNROLL-FULL-NEXT: "mul"(%0, %0) : (index, index) -> ()192  // UNROLL-FULL-NEXT: %1 = affine.apply [[$MAP0]](%c0_0)193  // UNROLL-FULL-NEXT: %2 = affine.apply [[$MAP0]](%1)194  // UNROLL-FULL-NEXT: "mul"(%2, %2) : (index, index) -> ()195  // UNROLL-FULL-NEXT: %3 = affine.apply [[$MAP1]](%c0_0)196  // UNROLL-FULL-NEXT: %4 = affine.apply [[$MAP0]](%3)197  // UNROLL-FULL-NEXT: "mul"(%4, %4) : (index, index) -> ()198  // UNROLL-FULL-NEXT: %5 = affine.apply [[$MAP2]](%c0_0)199  // UNROLL-FULL-NEXT: %6 = affine.apply [[$MAP0]](%5)200  // UNROLL-FULL-NEXT: "mul"(%6, %6) : (index, index) -> ()201  affine.for %j = 0 to 4 {202    %x = "affine.apply" (%j) { map = affine_map<(d0) -> (d0 + 1)> } :203      (index) -> (index)204    "mul"(%x, %x) : (index, index) -> ()205  }206 207  // UNROLL-FULL: %c99 = arith.constant 99 : index208  %k = arith.constant 99 : index209  // UNROLL-FULL: affine.for %arg0 = 0 to 100 step 2 {210  affine.for %m = 0 to 100 step 2 {211    // UNROLL-FULL: %7 = affine.apply [[$MAP0]](%c0)212    // UNROLL-FULL-NEXT: %8 = affine.apply [[$MAP6]](%c0)[%c99]213    // UNROLL-FULL-NEXT: %9 = affine.apply [[$MAP0]](%c0)214    // UNROLL-FULL-NEXT: %10 = affine.apply [[$MAP0]](%9)215    // UNROLL-FULL-NEXT: %11 = affine.apply [[$MAP6]](%9)[%c99]216    // UNROLL-FULL-NEXT: %12 = affine.apply [[$MAP1]](%c0)217    // UNROLL-FULL-NEXT: %13 = affine.apply [[$MAP0]](%12)218    // UNROLL-FULL-NEXT: %14 = affine.apply [[$MAP6]](%12)[%c99]219    // UNROLL-FULL-NEXT: %15 = affine.apply [[$MAP2]](%c0)220    // UNROLL-FULL-NEXT: %16 = affine.apply [[$MAP0]](%15)221    // UNROLL-FULL-NEXT: %17 = affine.apply [[$MAP6]](%15)[%c99]222    affine.for %n = 0 to 4 {223      %y = "affine.apply" (%n) { map = affine_map<(d0) -> (d0 + 1)> } :224        (index) -> (index)225      %z = "affine.apply" (%n, %k) { map = affine_map<(d0) [s0] -> (d0 + s0 + 1)> } :226        (index, index) -> (index)227    }     // UNROLL-FULL }228  }       // UNROLL-FULL }229  return  // UNROLL-FULL:  return230}         // UNROLL-FULL }231 232// UNROLL-FULL-LABEL: func @loop_nest_unroll_full() {233func.func @loop_nest_unroll_full() {234  // UNROLL-FULL-NEXT: %0 = "foo"() : () -> i32235  // UNROLL-FULL-NEXT: %1 = "bar"() : () -> i32236  // UNROLL-FULL-NEXT:  return237  affine.for %i = 0 to 1 {238    %x = "foo"() : () -> i32239    %y = "bar"() : () -> i32240  }241  return242} // UNROLL-FULL }243 244gpu.module @unroll_full {245  // GPU-UNROLL-FULL-LABEL: func @gpu_loop_nest_simplest() {246  gpu.func @gpu_loop_nest_simplest() {247    // GPU-UNROLL-FULL: affine.for %arg0 = 0 to 100 step 2 {248    affine.for %i = 0 to 100 step 2 {249      // GPU-UNROLL-FULL: %c1_i32 = arith.constant 1 : i32250      // GPU-UNROLL-FULL-NEXT: %c1_i32_0 = arith.constant 1 : i32251      // GPU-UNROLL-FULL-NEXT: %c1_i32_1 = arith.constant 1 : i32252      // GPU-UNROLL-FULL-NEXT: %c1_i32_2 = arith.constant 1 : i32253      affine.for %j = 0 to 4 {254        %x = arith.constant 1 : i32255      }256    }           // GPU-UNROLL-FULL:  }257    gpu.return  // GPU-UNROLL-FULL:  return258  }259}260 261// SHORT-LABEL: func @loop_nest_outer_unroll() {262func.func @loop_nest_outer_unroll() {263  // SHORT:      affine.for %arg0 = 0 to 4 {264  // SHORT-NEXT:   %0 = affine.apply [[$MAP0]](%arg0)265  // SHORT-NEXT:   %1 = "addi32"(%0, %0) : (index, index) -> index266  // SHORT-NEXT: }267  // SHORT-NEXT: affine.for %arg0 = 0 to 4 {268  // SHORT-NEXT:   %0 = affine.apply [[$MAP0]](%arg0)269  // SHORT-NEXT:   %1 = "addi32"(%0, %0) : (index, index) -> index270  // SHORT-NEXT: }271  affine.for %i = 0 to 2 {272    affine.for %j = 0 to 4 {273      %x = "affine.apply" (%j) { map = affine_map<(d0) -> (d0 + 1)> } :274        (index) -> (index)275      %y = "addi32"(%x, %x) : (index, index) -> index276    }277  }278  return  // SHORT:  return279}         // SHORT }280 281// We are doing a minimal FileCheck here. We just need this test case to282// successfully run. Both %x and %y will get unrolled here as the min trip283// count threshold set to 2.284// SHORT-LABEL: func @loop_nest_seq_long() -> i32 {285func.func @loop_nest_seq_long() -> i32 {286  %A = memref.alloc() : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>287  %B = memref.alloc() : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>288  %C = memref.alloc() : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>289 290  %zero = arith.constant 0 : i32291  %one = arith.constant 1 : i32292  %two = arith.constant 2 : i32293 294  %zero_idx = arith.constant 0 : index295 296  // CHECK: affine.for %arg0 = 0 to 512297  affine.for %n0 = 0 to 512 {298    // CHECK: affine.for %arg1 = 0 to 8299    affine.for %n1 = 0 to 8 {300      memref.store %one,  %A[%n0, %n1] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>301      memref.store %two,  %B[%n0, %n1] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>302      memref.store %zero, %C[%n0, %n1] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>303    }304  }305 306  affine.for %x = 0 to 2 {307    affine.for %y = 0 to 2 {308      // CHECK: affine.for309      affine.for %arg2 = 0 to 8 {310        // CHECK-NOT: affine.for311        // CHECK: %{{[0-9]+}} = affine.apply312        %b2 = "affine.apply" (%y, %arg2) {map = affine_map<(d0, d1) -> (16*d0 + d1)>} : (index, index) -> index313        %z = memref.load %B[%x, %b2] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>314        "op1"(%z) : (i32) -> ()315      }316      affine.for %j1 = 0 to 8 {317        affine.for %j2 = 0 to 8 {318          %a2 = "affine.apply" (%y, %j2) {map = affine_map<(d0, d1) -> (16*d0 + d1)>} : (index, index) -> index319          %v203 = memref.load %A[%j1, %a2] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>320          "op2"(%v203) : (i32) -> ()321        }322        affine.for %k2 = 0 to 8 {323          %s0 = "op3"() : () -> i32324          %c2 = "affine.apply" (%x, %k2) {map = affine_map<(d0, d1) -> (16*d0 + d1)>} : (index, index) -> index325          %s1 =  memref.load %C[%j1, %c2] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>326          %s2 = "addi32"(%s0, %s1) : (i32, i32) -> i32327          memref.store %s2, %C[%j1, %c2] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>328        }329      }330      "op4"() : () -> ()331    }332  }333  %ret = memref.load %C[%zero_idx, %zero_idx] : memref<512 x 512 x i32, affine_map<(d0, d1) -> (d0, d1)>, 2>334  return %ret : i32335}336 337// UNROLL-BY-4-LABEL: func @unroll_unit_stride_no_cleanup() {338func.func @unroll_unit_stride_no_cleanup() {339  // UNROLL-BY-4: affine.for %arg0 = 0 to 100 {340  affine.for %i = 0 to 100 {341    // UNROLL-BY-4: for [[L1:%arg[0-9]+]] = 0 to 8 step 4 {342    // UNROLL-BY-4-NEXT: %0 = "addi32"([[L1]], [[L1]]) : (index, index) -> i32343    // UNROLL-BY-4-NEXT: %1 = "addi32"(%0, %0) : (i32, i32) -> i32344    // UNROLL-BY-4-NEXT: %2 = affine.apply #map{{[0-9]*}}([[L1]])345    // UNROLL-BY-4-NEXT: %3 = "addi32"(%2, %2) : (index, index) -> i32346    // UNROLL-BY-4-NEXT: %4 = "addi32"(%3, %3) : (i32, i32) -> i32347    // UNROLL-BY-4-NEXT: %5 = affine.apply #map{{[0-9]*}}([[L1]])348    // UNROLL-BY-4-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> i32349    // UNROLL-BY-4-NEXT: %7 = "addi32"(%6, %6) : (i32, i32) -> i32350    // UNROLL-BY-4-NEXT: %8 = affine.apply #map{{[0-9]*}}([[L1]])351    // UNROLL-BY-4-NEXT: %9 = "addi32"(%8, %8) : (index, index) -> i32352    // UNROLL-BY-4-NEXT: %10 = "addi32"(%9, %9) : (i32, i32) -> i32353    // UNROLL-BY-4-NEXT: }354    affine.for %j = 0 to 8 {355      %x = "addi32"(%j, %j) : (index, index) -> i32356      %y = "addi32"(%x, %x) : (i32, i32) -> i32357    }358    // empty loop359    // UNROLL-BY-4: affine.for %arg1 = 0 to 8 {360    affine.for %k = 0 to 8 {361    }362  }363  return364}365 366// UNROLL-BY-4-LABEL: func @unroll_unit_stride_cleanup() {367func.func @unroll_unit_stride_cleanup() {368  // UNROLL-BY-4: affine.for %arg0 = 0 to 100 {369  affine.for %i = 0 to 100 {370    // UNROLL-BY-4: for [[L1:%arg[0-9]+]] = 0 to 8 step 4 {371    // UNROLL-BY-4-NEXT:   %0 = "addi32"([[L1]], [[L1]]) : (index, index) -> i32372    // UNROLL-BY-4-NEXT:   %1 = "addi32"(%0, %0) : (i32, i32) -> i32373    // UNROLL-BY-4-NEXT:   %2 = affine.apply #map{{[0-9]*}}([[L1]])374    // UNROLL-BY-4-NEXT:   %3 = "addi32"(%2, %2) : (index, index) -> i32375    // UNROLL-BY-4-NEXT:   %4 = "addi32"(%3, %3) : (i32, i32) -> i32376    // UNROLL-BY-4-NEXT:   %5 = affine.apply #map{{[0-9]*}}([[L1]])377    // UNROLL-BY-4-NEXT:   %6 = "addi32"(%5, %5) : (index, index) -> i32378    // UNROLL-BY-4-NEXT:   %7 = "addi32"(%6, %6) : (i32, i32) -> i32379    // UNROLL-BY-4-NEXT:   %8 = affine.apply #map{{[0-9]*}}([[L1]])380    // UNROLL-BY-4-NEXT:   %9 = "addi32"(%8, %8) : (index, index) -> i32381    // UNROLL-BY-4-NEXT:   %10 = "addi32"(%9, %9) : (i32, i32) -> i32382    // UNROLL-BY-4-NEXT: }383    // UNROLL-BY-4-NEXT: for [[L2:%arg[0-9]+]] = 8 to 10 {384    // UNROLL-BY-4-NEXT:   %0 = "addi32"([[L2]], [[L2]]) : (index, index) -> i32385    // UNROLL-BY-4-NEXT:   %1 = "addi32"(%0, %0) : (i32, i32) -> i32386    // UNROLL-BY-4-NEXT: }387    affine.for %j = 0 to 10 {388      %x = "addi32"(%j, %j) : (index, index) -> i32389      %y = "addi32"(%x, %x) : (i32, i32) -> i32390    }391  }392  return393}394 395// UNROLL-BY-4-LABEL: func @unroll_non_unit_stride_cleanup() {396func.func @unroll_non_unit_stride_cleanup() {397  // UNROLL-BY-4: affine.for %arg0 = 0 to 100 {398  affine.for %i = 0 to 100 {399    // UNROLL-BY-4: for [[L1:%arg[0-9]+]] = 2 to 42 step 20 {400    // UNROLL-BY-4-NEXT: %0 = "addi32"([[L1]], [[L1]]) : (index, index) -> i32401    // UNROLL-BY-4-NEXT: %1 = "addi32"(%0, %0) : (i32, i32) -> i32402    // UNROLL-BY-4-NEXT: %2 = affine.apply #map{{[0-9]*}}([[L1]])403    // UNROLL-BY-4-NEXT: %3 = "addi32"(%2, %2) : (index, index) -> i32404    // UNROLL-BY-4-NEXT: %4 = "addi32"(%3, %3) : (i32, i32) -> i32405    // UNROLL-BY-4-NEXT: %5 = affine.apply #map{{[0-9]*}}([[L1]])406    // UNROLL-BY-4-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> i32407    // UNROLL-BY-4-NEXT: %7 = "addi32"(%6, %6) : (i32, i32) -> i32408    // UNROLL-BY-4-NEXT: %8 = affine.apply #map{{[0-9]*}}([[L1]])409    // UNROLL-BY-4-NEXT: %9 = "addi32"(%8, %8) : (index, index) -> i32410    // UNROLL-BY-4-NEXT: %10 = "addi32"(%9, %9) : (i32, i32) -> i32411    // UNROLL-BY-4-NEXT: }412    // UNROLL-BY-4-NEXT: for [[L2:%arg[0-9]+]] = 42 to 48 step 5 {413    // UNROLL-BY-4-NEXT: %0 = "addi32"([[L2]], [[L2]]) : (index, index) -> i32414    // UNROLL-BY-4-NEXT: %1 = "addi32"(%0, %0) : (i32, i32) -> i32415    // UNROLL-BY-4-NEXT: }416    affine.for %j = 2 to 48 step 5 {417      %x = "addi32"(%j, %j) : (index, index) -> i32418      %y = "addi32"(%x, %x) : (i32, i32) -> i32419    }420  }421  return422}423 424// Both the unrolled loop and the cleanup loop are single iteration loops.425// UNROLL-BY-4-LABEL: func @loop_nest_single_iteration_after_unroll426func.func @loop_nest_single_iteration_after_unroll(%N: index) {427  // UNROLL-BY-4: %c0 = arith.constant 0 : index428  // UNROLL-BY-4: %c4 = arith.constant 4 : index429  // UNROLL-BY-4: affine.for %arg1 = 0 to %arg0 {430  affine.for %i = 0 to %N {431    // UNROLL-BY-4: %0 = "addi32"(%c0, %c0) : (index, index) -> i32432    // UNROLL-BY-4-NEXT: %1 = affine.apply [[$MAP0]](%c0)433    // UNROLL-BY-4-NEXT: %2 = "addi32"(%1, %1) : (index, index) -> i32434    // UNROLL-BY-4-NEXT: %3 = affine.apply [[$MAP1]](%c0)435    // UNROLL-BY-4-NEXT: %4 = "addi32"(%3, %3) : (index, index) -> i32436    // UNROLL-BY-4-NEXT: %5 = affine.apply [[$MAP2]](%c0)437    // UNROLL-BY-4-NEXT: %6 = "addi32"(%5, %5) : (index, index) -> i32438    // UNROLL-BY-4-NEXT: %7 = "addi32"(%c4, %c4) : (index, index) -> i32439    // UNROLL-BY-4-NOT: for440    affine.for %j = 0 to 5 {441      %x = "addi32"(%j, %j) : (index, index) -> i32442    } // UNROLL-BY-4-NOT: }443  } // UNROLL-BY-4:  }444  return445}446 447// Test cases with loop bound operands.448 449// No cleanup will be generated here.450// UNROLL-BY-4-LABEL: func @loop_nest_operand1() {451func.func @loop_nest_operand1() {452// UNROLL-BY-4:      affine.for %arg0 = 0 to 100 step 2 {453// UNROLL-BY-4-NEXT:   affine.for %arg1 = 0 to #map{{[0-9]*}}(%arg0) step 4454// UNROLL-BY-4-NEXT:      %0 = "foo"() : () -> i32455// UNROLL-BY-4-NEXT:      %1 = "foo"() : () -> i32456// UNROLL-BY-4-NEXT:      %2 = "foo"() : () -> i32457// UNROLL-BY-4-NEXT:      %3 = "foo"() : () -> i32458// UNROLL-BY-4-NEXT:   }459// UNROLL-BY-4-NEXT: }460// UNROLL-BY-4-NEXT: return461  affine.for %i = 0 to 100 step 2 {462    affine.for %j = 0 to affine_map<(d0) -> (d0 - d0 mod 4)> (%i) {463      %x = "foo"() : () -> i32464    }465  }466  return467}468 469// No cleanup will be generated here.470// UNROLL-BY-4-LABEL: func @loop_nest_operand2() {471func.func @loop_nest_operand2() {472// UNROLL-BY-4:      affine.for %arg0 = 0 to 100 step 2 {473// UNROLL-BY-4-NEXT:   affine.for %arg1 = [[$MAP11]](%arg0) to #map{{[0-9]*}}(%arg0) step 4 {474// UNROLL-BY-4-NEXT:     %0 = "foo"() : () -> i32475// UNROLL-BY-4-NEXT:     %1 = "foo"() : () -> i32476// UNROLL-BY-4-NEXT:     %2 = "foo"() : () -> i32477// UNROLL-BY-4-NEXT:     %3 = "foo"() : () -> i32478// UNROLL-BY-4-NEXT:   }479// UNROLL-BY-4-NEXT: }480// UNROLL-BY-4-NEXT: return481  affine.for %i = 0 to 100 step 2 {482    affine.for %j = affine_map<(d0) -> (d0)> (%i) to affine_map<(d0) -> (5*d0 + 4)> (%i) {483      %x = "foo"() : () -> i32484    }485  }486  return487}488 489// UNROLL-BY-4-LABEL: func @floordiv_mod_ub490func.func @floordiv_mod_ub(%M : index, %N : index) {491  affine.for %i = 0 to %N step 4 {492    // A cleanup should be generated here.493    affine.for %j = 0 to min affine_map<(d0)[s0] -> ((16 * d0) floordiv (4 * s0))>(%i)[%N] {494      "test.foo"() : () -> ()495    }496  }497  // UNROLL-BY-4-NEXT: affine.for498  // UNROLL-BY-4-NEXT:   affine.for %{{.*}} = 0 to {{.*}} step 4499  // UNROLL-BY-4:      affine.for500  affine.for %i = 0 to %N step 4 {501    // No cleanup needed here.502    affine.for %j = 0 to min affine_map<(d0)[s0] -> ((16 * d0) mod (4 * s0))>(%i)[%N] {503      "test.foo"() : () -> ()504    }505  }506  // UNROLL-BY-4:       affine.for507  // UNROLL-BY-4-NEXT:    affine.for %{{.*}} = 0 to {{.*}} step 4508  // UNROLL-BY-4-NOT:     affine.for509  // UNROLL-BY-4:       return510    return511}512 513// Difference between loop bounds is constant, but not a multiple of unroll514// factor. The cleanup loop happens to be a single iteration one and is promoted.515// UNROLL-BY-4-LABEL: func @loop_nest_operand3() {516func.func @loop_nest_operand3() {517  // UNROLL-BY-4: affine.for %arg0 = 0 to 100 step 2 {518  affine.for %i = 0 to 100 step 2 {519    // UNROLL-BY-4: affine.for %arg1 = [[$MAP11]](%arg0) to #map{{[0-9]*}}(%arg0) step 4 {520    // UNROLL-BY-4-NEXT: %1 = "foo"() : () -> i32521    // UNROLL-BY-4-NEXT: %2 = "foo"() : () -> i32522    // UNROLL-BY-4-NEXT: %3 = "foo"() : () -> i32523    // UNROLL-BY-4-NEXT: %4 = "foo"() : () -> i32524    // UNROLL-BY-4-NEXT: }525    // UNROLL-BY-4-NEXT: %0 = "foo"() : () -> i32526    affine.for %j = affine_map<(d0) -> (d0)> (%i) to affine_map<(d0) -> (d0 + 9)> (%i) {527      %x = "foo"() : () -> i32528    }529  } // UNROLL-BY-4: }530  return531}532 533// UNROLL-BY-4-LABEL: func @loop_nest_symbolic_bound(%arg0: index) {534func.func @loop_nest_symbolic_bound(%N : index) {535  // UNROLL-BY-4: affine.for %arg1 = 0 to 100 {536  affine.for %i = 0 to 100 {537    // UNROLL-BY-4: affine.for %arg2 = 0 to #map{{[0-9]*}}()[%arg0] step 4 {538    // UNROLL-BY-4: %0 = "foo"() : () -> i32539    // UNROLL-BY-4-NEXT: %1 = "foo"() : () -> i32540    // UNROLL-BY-4-NEXT: %2 = "foo"() : () -> i32541    // UNROLL-BY-4-NEXT: %3 = "foo"() : () -> i32542    // UNROLL-BY-4-NEXT: }543    // A cleanup loop will be generated here.544    // UNROLL-BY-4-NEXT: affine.for %arg2 = #map{{[0-9]*}}()[%arg0] to %arg0 {545    // UNROLL-BY-4-NEXT: %0 = "foo"() : () -> i32546    // UNROLL-BY-4-NEXT: }547    affine.for %j = 0 to %N {548      %x = "foo"() : () -> i32549    }550  }551  return552}553 554// UNROLL-BY-4-LABEL: func @loop_nest_symbolic_bound_with_step555// UNROLL-BY-4-SAME: %[[N:.*]]: index556func.func @loop_nest_symbolic_bound_with_step(%N : index) {557  // UNROLL-BY-4: affine.for %arg1 = 0 to 100 {558  affine.for %i = 0 to 100 {559    affine.for %j = 0 to %N step 3 {560      %x = "foo"() : () -> i32561    }562// UNROLL-BY-4:      affine.for %{{.*}} = 0 to #map{{[0-9]*}}()[%[[N]]] step 12 {563// UNROLL-BY-4:        "foo"()564// UNROLL-BY-4-NEXT:   "foo"()565// UNROLL-BY-4-NEXT:   "foo"()566// UNROLL-BY-4-NEXT:   "foo"()567// UNROLL-BY-4-NEXT: }568// A cleanup loop will be be generated here.569// UNROLL-BY-4-NEXT: affine.for %{{.*}} = #map{{[0-9]*}}()[%[[N]]] to %[[N]] step 3 {570// UNROLL-BY-4-NEXT:   "foo"()571// UNROLL-BY-4-NEXT: }572  }573  return574}575 576// UNROLL-BY-4-LABEL: func @loop_nest_symbolic_and_min_upper_bound577func.func @loop_nest_symbolic_and_min_upper_bound(%M : index, %N : index, %K : index) {578  affine.for %i = %M to min affine_map<()[s0, s1] -> (s0, s1, 1024)>()[%N, %K] {579    "test.foo"() : () -> ()580  }581  return582}583// No unrolling here.584// UNROLL-BY-4:      affine.for %{{.*}} = %{{.*}} to min #map{{.*}}()[%{{.*}}, %{{.*}}] {585// UNROLL-BY-4-NEXT:   "test.foo"() : () -> ()586// UNROLL-BY-4-NEXT: }587// UNROLL-BY-4-NEXT: return588 589// The trip count here is a multiple of four, but this can be inferred only590// through composition. Check for no cleanup scf.591// UNROLL-BY-4-LABEL: func @loop_nest_non_trivial_multiple_upper_bound592func.func @loop_nest_non_trivial_multiple_upper_bound(%M : index, %N : index) {593  %T = affine.apply affine_map<(d0) -> (4*d0 + 1)>(%M)594  %K = affine.apply affine_map<(d0) -> (d0 - 1)> (%T)595  affine.for %i = 0 to min affine_map<(d0, d1) -> (4 * d0, d1, 1024)>(%N, %K) {596    "foo"() : () -> ()597  }598  return599}600// UNROLL-BY-4: affine.for %arg2 = 0 to min601// UNROLL-BY-4-NOT: for602// UNROLL-BY-4: return603 604// UNROLL-BY-4-LABEL: func @multi_upper_bound605func.func @multi_upper_bound(%arg0: index) {606  affine.for %i = 0 to min affine_map<()[s0] -> (8 * s0, 12 * s0)>()[%arg0] {607    "test.foo"() : () -> ()608  }609  // No unrolling possible here.610  // UNROLL-BY-4: affine.for %{{.*}} = 0 to min #map{{.*}}()[%{{.*}}]611  return612}613 614// UNROLL-BY-4-LABEL: func @multi_lower_bound615func.func @multi_lower_bound(%arg0: index) {616  affine.for %i = max affine_map<()[s0] -> (8 * s0, 12 * s0)>()[%arg0] to 100 {617    "test.foo"() : () -> ()618  }619  // TODO: Extend getTripCountMapAndOperands to handle multi-result lower bound620  // maps.621  // UNROLL-BY-4: affine.for %{{.*}} = max #map{{.*}}()[%{{.*}}] to 100622  // UNROLL-BY-4-NOT: affine.for623  return624}625 626// UNROLL-BY-4-LABEL: func @loop_nest_non_trivial_multiple_upper_bound_alt627func.func @loop_nest_non_trivial_multiple_upper_bound_alt(%M : index, %N : index) {628  %K = affine.apply affine_map<(d0) -> (4*d0)> (%M)629  affine.for %i = 0 to min affine_map<()[s0, s1] -> (4 * s0, s1, 1024)>()[%N, %K] {630    "foo"() : () -> ()631  }632  // UNROLL-BY-4: affine.for %arg2 = 0 to min633  // UNROLL-BY-4-NEXT: "foo"634  // UNROLL-BY-4-NEXT: "foo"635  // UNROLL-BY-4-NEXT: "foo"636  // UNROLL-BY-4-NEXT: "foo"637  // UNROLL-BY-4-NOT: for638  // UNROLL-BY-4: return639  return640}641 642// UNROLL-BY-1-LABEL: func @unroll_by_one_should_promote_single_iteration_loop()643func.func @unroll_by_one_should_promote_single_iteration_loop() {644  affine.for %i = 0 to 1 {645    %x = "foo"(%i) : (index) -> i32646  }647  return648// UNROLL-BY-1-NEXT: %c0 = arith.constant 0 : index649// UNROLL-BY-1-NEXT: %0 = "foo"(%c0) : (index) -> i32650// UNROLL-BY-1-NEXT: return651}652 653// Test unrolling with affine.for iter_args.654 655// UNROLL-BY-4-LABEL: loop_unroll_with_iter_args_and_cleanup656func.func @loop_unroll_with_iter_args_and_cleanup(%arg0 : f32, %arg1 : f32, %n : index) -> (f32,f32) {657  %cf1 = arith.constant 1.0 : f32658  %cf2 = arith.constant 2.0 : f32659  %sum:2 = affine.for %iv = 0 to 10 iter_args(%i0 = %arg0, %i1 = %arg1) -> (f32, f32) {660    %sum0 = arith.addf %i0, %cf1 : f32661    %sum1 = arith.addf %i1, %cf2 : f32662    affine.yield %sum0, %sum1 : f32, f32663  }664  return %sum#0, %sum#1 : f32, f32665  // UNROLL-BY-4:      %[[SUM:.*]]:2 = affine.for {{.*}} = 0 to 8 step 4 iter_args666  // UNROLL-BY-4-NEXT:   arith.addf667  // UNROLL-BY-4-NEXT:   arith.addf668  // UNROLL-BY-4-NEXT:   arith.addf669  // UNROLL-BY-4-NEXT:   arith.addf670  // UNROLL-BY-4-NEXT:   arith.addf671  // UNROLL-BY-4-NEXT:   arith.addf672  // UNROLL-BY-4-NEXT:   %[[Y1:.*]] = arith.addf673  // UNROLL-BY-4-NEXT:   %[[Y2:.*]] = arith.addf674  // UNROLL-BY-4-NEXT:   affine.yield %[[Y1]], %[[Y2]]675  // UNROLL-BY-4-NEXT: }676  // UNROLL-BY-4-NEXT: %[[SUM1:.*]]:2 = affine.for {{.*}} = 8 to 10 iter_args(%[[V1:.*]] = %[[SUM]]#0, %[[V2:.*]] = %[[SUM]]#1)677  // UNROLL-BY-4:      }678  // UNROLL-BY-4-NEXT: return %[[SUM1]]#0, %[[SUM1]]#1679}680 681// The epilogue being a single iteration loop gets promoted here.682 683// UNROLL-BY-4-LABEL: unroll_with_iter_args_and_promotion684func.func @unroll_with_iter_args_and_promotion(%arg0 : f32, %arg1 : f32) -> f32 {685  %from = arith.constant 0 : index686  %to = arith.constant 10 : index687  %step = arith.constant 1 : index688  %sum = affine.for %iv = 0 to 9 iter_args(%sum_iter = %arg0) -> (f32) {689    %next = arith.addf %sum_iter, %arg1 : f32690    affine.yield %next : f32691  }692  // UNROLL-BY-4:      %[[SUM:.*]] = affine.for %{{.*}} = 0 to 8 step 4 iter_args(%[[V0:.*]] =693  // UNROLL-BY-4-NEXT:   %[[V1:.*]] = arith.addf %[[V0]]694  // UNROLL-BY-4-NEXT:   %[[V2:.*]] = arith.addf %[[V1]]695  // UNROLL-BY-4-NEXT:   %[[V3:.*]] = arith.addf %[[V2]]696  // UNROLL-BY-4-NEXT:   %[[V4:.*]] = arith.addf %[[V3]]697  // UNROLL-BY-4-NEXT:   affine.yield %[[V4]]698  // UNROLL-BY-4-NEXT: }699  // UNROLL-BY-4-NEXT: %[[RES:.*]] = arith.addf %[[SUM]],700  // UNROLL-BY-4-NEXT: return %[[RES]]701  return %sum : f32702}703 704// UNROLL-FULL: func @unroll_zero_trip_count_case705func.func @unroll_zero_trip_count_case() {706  // CHECK-NEXT: affine.for %{{.*}} = 0 to 0707  affine.for %i = 0 to 0 {708  }709  return710}711 712// UNROLL-CLEANUP-LOOP-LABEL: func @unroll_cleanup_loop_with_larger_unroll_factor()713func.func @unroll_cleanup_loop_with_larger_unroll_factor() {714  affine.for %i = 0 to 3 {715    %x = "foo"(%i) : (index) -> i32716  }717  return718// UNROLL-CLEANUP-LOOP-NEXT: %[[C0:.*]] = arith.constant 0 : index719// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[C0]]) : (index) -> i32720// UNROLL-CLEANUP-LOOP-NEXT: %[[V1:.*]] = affine.apply {{.*}}721// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V1]]) : (index) -> i32722// UNROLL-CLEANUP-LOOP-NEXT: %[[V2:.*]] = affine.apply {{.*}}723// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V2]]) : (index) -> i32724// UNROLL-CLEANUP-LOOP-NEXT: return725}726 727// UNROLL-CLEANUP-LOOP-LABEL: func @unroll_cleanup_loop_with_smaller_unroll_factor()728func.func @unroll_cleanup_loop_with_smaller_unroll_factor() {729  affine.for %i = 0 to 7 {730    %x = "foo"(%i) : (index) -> i32731  }732  return733// UNROLL-CLEANUP-LOOP-NEXT: %[[C0:.*]] = arith.constant 0 : index734// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[C0]]) : (index) -> i32735// UNROLL-CLEANUP-LOOP-NEXT: %[[V1:.*]] = affine.apply {{.*}}736// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V1]]) : (index) -> i32737// UNROLL-CLEANUP-LOOP-NEXT: %[[V2:.*]] = affine.apply {{.*}}738// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V2]]) : (index) -> i32739// UNROLL-CLEANUP-LOOP-NEXT: %[[V3:.*]] = affine.apply {{.*}}740// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V3]]) : (index) -> i32741// UNROLL-CLEANUP-LOOP-NEXT: %[[V4:.*]] = affine.apply {{.*}}742// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V4]]) : (index) -> i32743// UNROLL-CLEANUP-LOOP-NEXT: %[[V5:.*]] = affine.apply {{.*}}744// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V5]]) : (index) -> i32745// UNROLL-CLEANUP-LOOP-NEXT: %[[V6:.*]] = affine.apply {{.*}}746// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V6]]) : (index) -> i32747// UNROLL-CLEANUP-LOOP-NEXT: return748}749 750// UNROLL-CLEANUP-LOOP-LABEL: func @unroll_cleanup_loop_with_identical_unroll_factor()751func.func @unroll_cleanup_loop_with_identical_unroll_factor() {752  affine.for %i = 0 to 5 {753    %x = "foo"(%i) : (index) -> i32754  }755  return756// UNROLL-CLEANUP-LOOP-NEXT: %[[C0:.*]] = arith.constant 0 : index757// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[C0]]) : (index) -> i32758// UNROLL-CLEANUP-LOOP-NEXT: %[[V1:.*]] = affine.apply {{.*}}759// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V1]]) : (index) -> i32760// UNROLL-CLEANUP-LOOP-NEXT: %[[V2:.*]] = affine.apply {{.*}}761// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V2]]) : (index) -> i32762// UNROLL-CLEANUP-LOOP-NEXT: %[[V3:.*]] = affine.apply {{.*}}763// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V3]]) : (index) -> i32764// UNROLL-CLEANUP-LOOP-NEXT: %[[V4:.*]] = affine.apply {{.*}}765// UNROLL-CLEANUP-LOOP-NEXT: {{.*}} = "foo"(%[[V4]]) : (index) -> i32766// UNROLL-CLEANUP-LOOP-NEXT: return767}768 769// UNROLL-BY-4-LABEL: func @known_multiple_ceildiv770func.func @known_multiple_ceildiv(%N: index, %S: index) {771  %cst = arith.constant 0.0 : f32772  %m = memref.alloc(%S) : memref<?xf32>773  // This exercises affine expr getLargestKnownDivisor for the ceildiv case.774  affine.for %i = 0 to affine_map<(d0) -> (32 * d0 + 64)>(%N) step 8 {775    affine.store %cst, %m[%i] : memref<?xf32>776  }777  // UNROLL-BY-4:     affine.for %{{.*}} = 0 to {{.*}} step 32778  // UNROLL-BY-4-NOT: affine.for779 780  // This exercises affine expr getLargestKnownDivisor for floordiv.781  affine.for %i = 0 to affine_map<(d0) -> ((32 * d0 + 64) floordiv 8)>(%N) {782    affine.store %cst, %m[%i] : memref<?xf32>783  }784  // UNROLL-BY-4:     affine.for %{{.*}} = 0 to {{.*}} step 4785  // UNROLL-BY-4-NOT: affine.for786  // UNROLL-BY-4:     return787  return788}789