brintos

brintos / llvm-project-archived public Read only

0
0
Text · 41.2 KiB · 550ea71 Raw
930 lines · plain
1// RUN: mlir-opt -lower-affine %s | FileCheck %s2 3// CHECK-LABEL: func @empty() {4func.func @empty() {5  return     // CHECK:  return6}            // CHECK: }7 8func.func private @body(index) -> ()9 10// Simple loops are properly converted.11// CHECK-LABEL: func @simple_loop12// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index13// CHECK-NEXT:   %[[c42:.*]] = arith.constant 42 : index14// CHECK-NEXT:   %[[c1_0:.*]] = arith.constant 1 : index15// CHECK-NEXT:   for %{{.*}} = %[[c1]] to %[[c42]] step %[[c1_0]] {16// CHECK-NEXT:     call @body(%{{.*}}) : (index) -> ()17// CHECK-NEXT:   }18// CHECK-NEXT:   return19// CHECK-NEXT: }20func.func @simple_loop() {21  affine.for %i = 1 to 42 {22    func.call @body(%i) : (index) -> ()23  }24  return25}26 27/////////////////////////////////////////////////////////////////////28 29func.func @for_with_yield(%buffer: memref<1024xf32>) -> (f32) {30  %sum_0 = arith.constant 0.0 : f3231  %sum = affine.for %i = 0 to 10 step 2 iter_args(%sum_iter = %sum_0) -> (f32) {32    %t = affine.load %buffer[%i] : memref<1024xf32>33    %sum_next = arith.addf %sum_iter, %t : f3234    affine.yield %sum_next : f3235  }36  return %sum : f3237}38 39// CHECK-LABEL: func @for_with_yield40// CHECK:         %[[INIT_SUM:.*]] = arith.constant 0.000000e+00 : f3241// CHECK-NEXT:    %[[LOWER:.*]] = arith.constant 0 : index42// CHECK-NEXT:    %[[UPPER:.*]] = arith.constant 10 : index43// CHECK-NEXT:    %[[STEP:.*]] = arith.constant 2 : index44// CHECK-NEXT:    %[[SUM:.*]] = scf.for %[[IV:.*]] = %[[LOWER]] to %[[UPPER]] step %[[STEP]] iter_args(%[[SUM_ITER:.*]] = %[[INIT_SUM]]) -> (f32) {45// CHECK-NEXT:      memref.load46// CHECK-NEXT:      %[[SUM_NEXT:.*]] = arith.addf47// CHECK-NEXT:      scf.yield %[[SUM_NEXT]] : f3248// CHECK-NEXT:    }49// CHECK-NEXT:    return %[[SUM]] : f3250 51/////////////////////////////////////////////////////////////////////52 53func.func private @pre(index) -> ()54func.func private @body2(index, index) -> ()55func.func private @post(index) -> ()56 57// CHECK-LABEL: func @imperfectly_nested_loops58// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index59// CHECK-NEXT:   %[[c42:.*]] = arith.constant 42 : index60// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index61// CHECK-NEXT:   for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] {62// CHECK-NEXT:     call @pre(%{{.*}}) : (index) -> ()63// CHECK-NEXT:     %[[c7:.*]] = arith.constant 7 : index64// CHECK-NEXT:     %[[c56:.*]] = arith.constant 56 : index65// CHECK-NEXT:     %[[c2:.*]] = arith.constant 2 : index66// CHECK-NEXT:     for %{{.*}} = %[[c7]] to %[[c56]] step %[[c2]] {67// CHECK-NEXT:       call @body2(%{{.*}}, %{{.*}}) : (index, index) -> ()68// CHECK-NEXT:     }69// CHECK-NEXT:     call @post(%{{.*}}) : (index) -> ()70// CHECK-NEXT:   }71// CHECK-NEXT:   return72// CHECK-NEXT: }73func.func @imperfectly_nested_loops() {74  affine.for %i = 0 to 42 {75    func.call @pre(%i) : (index) -> ()76    affine.for %j = 7 to 56 step 2 {77      func.call @body2(%i, %j) : (index, index) -> ()78    }79    func.call @post(%i) : (index) -> ()80  }81  return82}83 84/////////////////////////////////////////////////////////////////////85 86func.func private @mid(index) -> ()87func.func private @body3(index, index) -> ()88 89// CHECK-LABEL: func @more_imperfectly_nested_loops90// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index91// CHECK-NEXT:   %[[c42:.*]] = arith.constant 42 : index92// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index93// CHECK-NEXT:   for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] {94// CHECK-NEXT:     call @pre(%{{.*}}) : (index) -> ()95// CHECK-NEXT:     %[[c7:.*]] = arith.constant 7 : index96// CHECK-NEXT:     %[[c56:.*]] = arith.constant 56 : index97// CHECK-NEXT:     %[[c2:.*]] = arith.constant 2 : index98// CHECK-NEXT:     for %{{.*}} = %[[c7]] to %[[c56]] step %[[c2]] {99// CHECK-NEXT:       call @body2(%{{.*}}, %{{.*}}) : (index, index) -> ()100// CHECK-NEXT:     }101// CHECK-NEXT:     call @mid(%{{.*}}) : (index) -> ()102// CHECK-NEXT:     %[[c18:.*]] = arith.constant 18 : index103// CHECK-NEXT:     %[[c37:.*]] = arith.constant 37 : index104// CHECK-NEXT:     %[[c3:.*]] = arith.constant 3 : index105// CHECK-NEXT:     for %{{.*}} = %[[c18]] to %[[c37]] step %[[c3]] {106// CHECK-NEXT:       call @body3(%{{.*}}, %{{.*}}) : (index, index) -> ()107// CHECK-NEXT:     }108// CHECK-NEXT:     call @post(%{{.*}}) : (index) -> ()109// CHECK-NEXT:   }110// CHECK-NEXT:   return111// CHECK-NEXT: }112func.func @more_imperfectly_nested_loops() {113  affine.for %i = 0 to 42 {114    func.call @pre(%i) : (index) -> ()115    affine.for %j = 7 to 56 step 2 {116      func.call @body2(%i, %j) : (index, index) -> ()117    }118    func.call @mid(%i) : (index) -> ()119    affine.for %k = 18 to 37 step 3 {120      func.call @body3(%i, %k) : (index, index) -> ()121    }122    func.call @post(%i) : (index) -> ()123  }124  return125}126 127// CHECK-LABEL: func @affine_apply_loops_shorthand128// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index129// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index130// CHECK-NEXT:   for %{{.*}} = %[[c0]] to %{{.*}} step %[[c1]] {131// CHECK-NEXT:     %[[c42:.*]] = arith.constant 42 : index132// CHECK-NEXT:     %[[c1_0:.*]] = arith.constant 1 : index133// CHECK-NEXT:     for %{{.*}} = %{{.*}} to %[[c42]] step %[[c1_0]] {134// CHECK-NEXT:       call @body2(%{{.*}}, %{{.*}}) : (index, index) -> ()135// CHECK-NEXT:     }136// CHECK-NEXT:   }137// CHECK-NEXT:   return138// CHECK-NEXT: }139func.func @affine_apply_loops_shorthand(%N : index) {140  affine.for %i = 0 to %N {141    affine.for %j = affine_map<(d0)[]->(d0)>(%i)[] to 42 {142      func.call @body2(%i, %j) : (index, index) -> ()143    }144  }145  return146}147 148/////////////////////////////////////////////////////////////////////149 150func.func private @get_idx() -> (index)151 152#set1 = affine_set<(d0) : (20 - d0 >= 0)>153#set2 = affine_set<(d0) : (d0 - 10 >= 0)>154 155// CHECK-LABEL: func @if_only156// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index157// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index158// CHECK-NEXT:   %[[cm1:.*]] = arith.constant -1 : index159// CHECK-NEXT:   %[[v1:.*]] = arith.muli %[[v0]], %[[cm1]] overflow<nsw> : index160// CHECK-NEXT:   %[[c20:.*]] = arith.constant 20 : index161// CHECK-NEXT:   %[[v2:.*]] = arith.addi %[[v1]], %[[c20]] : index162// CHECK-NEXT:   %[[v3:.*]] = arith.cmpi sge, %[[v2]], %[[c0]] : index163// CHECK-NEXT:   if %[[v3]] {164// CHECK-NEXT:     call @body(%[[v0:.*]]) : (index) -> ()165// CHECK-NEXT:   }166// CHECK-NEXT:   return167// CHECK-NEXT: }168func.func @if_only() {169  %i = call @get_idx() : () -> (index)170  affine.if #set1(%i) {171    func.call @body(%i) : (index) -> ()172  }173  return174}175 176// CHECK-LABEL: func @if_else177// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index178// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index179// CHECK-NEXT:   %[[cm1:.*]] = arith.constant -1 : index180// CHECK-NEXT:   %[[v1:.*]] = arith.muli %[[v0]], %[[cm1]] overflow<nsw> : index181// CHECK-NEXT:   %[[c20:.*]] = arith.constant 20 : index182// CHECK-NEXT:   %[[v2:.*]] = arith.addi %[[v1]], %[[c20]] : index183// CHECK-NEXT:   %[[v3:.*]] = arith.cmpi sge, %[[v2]], %[[c0]] : index184// CHECK-NEXT:   if %[[v3]] {185// CHECK-NEXT:     call @body(%[[v0:.*]]) : (index) -> ()186// CHECK-NEXT:   } else {187// CHECK-NEXT:     call @mid(%[[v0:.*]]) : (index) -> ()188// CHECK-NEXT:   }189// CHECK-NEXT:   return190// CHECK-NEXT: }191func.func @if_else() {192  %i = call @get_idx() : () -> (index)193  affine.if #set1(%i) {194    func.call @body(%i) : (index) -> ()195  } else {196    func.call @mid(%i) : (index) -> ()197  }198  return199}200 201// CHECK-LABEL: func @nested_ifs202// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index203// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index204// CHECK-NEXT:   %[[cm1:.*]] = arith.constant -1 : index205// CHECK-NEXT:   %[[v1:.*]] = arith.muli %[[v0]], %[[cm1]] overflow<nsw> : index206// CHECK-NEXT:   %[[c20:.*]] = arith.constant 20 : index207// CHECK-NEXT:   %[[v2:.*]] = arith.addi %[[v1]], %[[c20]] : index208// CHECK-NEXT:   %[[v3:.*]] = arith.cmpi sge, %[[v2]], %[[c0]] : index209// CHECK-NEXT:   if %[[v3]] {210// CHECK-NEXT:     %[[c0_0:.*]] = arith.constant 0 : index211// CHECK-NEXT:     %[[cm10:.*]] = arith.constant -10 : index212// CHECK-NEXT:     %[[v4:.*]] = arith.addi %[[v0]], %[[cm10]] : index213// CHECK-NEXT:     %[[v5:.*]] = arith.cmpi sge, %[[v4]], %[[c0_0]] : index214// CHECK-NEXT:     if %[[v5]] {215// CHECK-NEXT:       call @body(%[[v0:.*]]) : (index) -> ()216// CHECK-NEXT:     }217// CHECK-NEXT:   } else {218// CHECK-NEXT:     %[[c0_0:.*]] = arith.constant 0 : index219// CHECK-NEXT:     %[[cm10:.*]] = arith.constant -10 : index220// CHECK-NEXT:     %{{.*}} = arith.addi %[[v0]], %[[cm10]] : index221// CHECK-NEXT:     %{{.*}} = arith.cmpi sge, %{{.*}}, %[[c0_0]] : index222// CHECK-NEXT:     if %{{.*}} {223// CHECK-NEXT:       call @mid(%[[v0:.*]]) : (index) -> ()224// CHECK-NEXT:     }225// CHECK-NEXT:   }226// CHECK-NEXT:   return227// CHECK-NEXT: }228func.func @nested_ifs() {229  %i = call @get_idx() : () -> (index)230  affine.if #set1(%i) {231    affine.if #set2(%i) {232      func.call @body(%i) : (index) -> ()233    }234  } else {235    affine.if #set2(%i) {236      func.call @mid(%i) : (index) -> ()237    }238  }239  return240}241 242// CHECK-LABEL: func @if_with_yield243// CHECK-NEXT:   %[[c0_i64:.*]] = arith.constant 0 : i64244// CHECK-NEXT:   %[[c1_i64:.*]] = arith.constant 1 : i64245// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index246// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index247// CHECK-NEXT:   %[[cm10:.*]] = arith.constant -10 : index248// CHECK-NEXT:   %[[v1:.*]] = arith.addi %[[v0]], %[[cm10]] : index249// CHECK-NEXT:   %[[v2:.*]] = arith.cmpi sge, %[[v1]], %[[c0]] : index250// CHECK-NEXT:   %[[v3:.*]] = scf.if %[[v2]] -> (i64) {251// CHECK-NEXT:     scf.yield %[[c0_i64]] : i64252// CHECK-NEXT:   } else {253// CHECK-NEXT:     scf.yield %[[c1_i64]] : i64254// CHECK-NEXT:   }255// CHECK-NEXT:   return %[[v3]] : i64256// CHECK-NEXT: }257func.func @if_with_yield() -> (i64) {258  %cst0 = arith.constant 0 : i64259  %cst1 = arith.constant 1 : i64260  %i = call @get_idx() : () -> (index)261  %1 = affine.if #set2(%i) -> (i64) {262      affine.yield %cst0 : i64263  } else {264      affine.yield %cst1 : i64265  }266  return %1 : i64267}268 269#setN = affine_set<(d0)[N,M,K,L] : (N - d0 + 1 >= 0, N - 1 >= 0, M - 1 >= 0, K - 1 >= 0, L - 42 == 0)>270 271// CHECK-LABEL: func @multi_cond272// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index273// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index274// CHECK-NEXT:   %[[cm1:.*]] = arith.constant -1 : index275// CHECK-NEXT:   %[[v1:.*]] = arith.muli %[[v0]], %[[cm1]] overflow<nsw> : index276// CHECK-NEXT:   %[[v2:.*]] = arith.addi %[[v1]], %{{.*}} : index277// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index278// CHECK-NEXT:   %[[v3:.*]] = arith.addi %[[v2]], %[[c1]] : index279// CHECK-NEXT:   %[[v4:.*]] = arith.cmpi sge, %[[v3]], %[[c0]] : index280// CHECK-NEXT:   %[[cm1_0:.*]] = arith.constant -1 : index281// CHECK-NEXT:   %[[v5:.*]] = arith.addi %{{.*}}, %[[cm1_0]] : index282// CHECK-NEXT:   %[[v6:.*]] = arith.cmpi sge, %[[v5]], %[[c0]] : index283// CHECK-NEXT:   %[[v7:.*]] = arith.andi %[[v4]], %[[v6]] : i1284// CHECK-NEXT:   %[[cm1_1:.*]] = arith.constant -1 : index285// CHECK-NEXT:   %[[v8:.*]] = arith.addi %{{.*}}, %[[cm1_1]] : index286// CHECK-NEXT:   %[[v9:.*]] = arith.cmpi sge, %[[v8]], %[[c0]] : index287// CHECK-NEXT:   %[[v10:.*]] = arith.andi %[[v7]], %[[v9]] : i1288// CHECK-NEXT:   %[[cm1_2:.*]] = arith.constant -1 : index289// CHECK-NEXT:   %[[v11:.*]] = arith.addi %{{.*}}, %[[cm1_2]] : index290// CHECK-NEXT:   %[[v12:.*]] = arith.cmpi sge, %[[v11]], %[[c0]] : index291// CHECK-NEXT:   %[[v13:.*]] = arith.andi %[[v10]], %[[v12]] : i1292// CHECK-NEXT:   %[[cm42:.*]] = arith.constant -42 : index293// CHECK-NEXT:   %[[v14:.*]] = arith.addi %{{.*}}, %[[cm42]] : index294// CHECK-NEXT:   %[[v15:.*]] = arith.cmpi eq, %[[v14]], %[[c0]] : index295// CHECK-NEXT:   %[[v16:.*]] = arith.andi %[[v13]], %[[v15]] : i1296// CHECK-NEXT:   if %[[v16]] {297// CHECK-NEXT:     call @body(%[[v0:.*]]) : (index) -> ()298// CHECK-NEXT:   } else {299// CHECK-NEXT:     call @mid(%[[v0:.*]]) : (index) -> ()300// CHECK-NEXT:   }301// CHECK-NEXT:   return302// CHECK-NEXT: }303func.func @multi_cond(%N : index, %M : index, %K : index, %L : index) {304  %i = call @get_idx() : () -> (index)305  affine.if #setN(%i)[%N,%M,%K,%L] {306    func.call @body(%i) : (index) -> ()307  } else {308    func.call @mid(%i) : (index) -> ()309  }310  return311}312 313// CHECK-LABEL: func @if_for314func.func @if_for() {315// CHECK-NEXT:   %[[v0:.*]] = call @get_idx() : () -> index316  %i = call @get_idx() : () -> (index)317// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index318// CHECK-NEXT:   %[[cm1:.*]] = arith.constant -1 : index319// CHECK-NEXT:   %[[v1:.*]] = arith.muli %[[v0]], %[[cm1]] overflow<nsw> : index320// CHECK-NEXT:   %[[c20:.*]] = arith.constant 20 : index321// CHECK-NEXT:   %[[v2:.*]] = arith.addi %[[v1]], %[[c20]] : index322// CHECK-NEXT:   %[[v3:.*]] = arith.cmpi sge, %[[v2]], %[[c0]] : index323// CHECK-NEXT:   if %[[v3]] {324// CHECK-NEXT:     %[[c0:.*]]{{.*}} = arith.constant 0 : index325// CHECK-NEXT:     %[[c42:.*]]{{.*}} = arith.constant 42 : index326// CHECK-NEXT:     %[[c1:.*]]{{.*}} = arith.constant 1 : index327// CHECK-NEXT:     for %{{.*}} = %[[c0:.*]]{{.*}} to %[[c42:.*]]{{.*}} step %[[c1:.*]]{{.*}} {328// CHECK-NEXT:       %[[c0_:.*]]{{.*}} = arith.constant 0 : index329// CHECK-NEXT:       %[[cm10:.*]] = arith.constant -10 : index330// CHECK-NEXT:       %[[v4:.*]] = arith.addi %{{.*}}, %[[cm10]] : index331// CHECK-NEXT:       %[[v5:.*]] = arith.cmpi sge, %[[v4]], %[[c0_:.*]]{{.*}} : index332// CHECK-NEXT:       if %[[v5]] {333// CHECK-NEXT:         call @body2(%[[v0]], %{{.*}}) : (index, index) -> ()334  affine.if #set1(%i) {335    affine.for %j = 0 to 42 {336      affine.if #set2(%j) {337        func.call @body2(%i, %j) : (index, index) -> ()338      }339    }340  }341//      CHECK:   %[[c0:.*]]{{.*}} = arith.constant 0 : index342// CHECK-NEXT:   %[[c42:.*]]{{.*}} = arith.constant 42 : index343// CHECK-NEXT:   %[[c1:.*]]{{.*}} = arith.constant 1 : index344// CHECK-NEXT:   for %{{.*}} = %[[c0:.*]]{{.*}} to %[[c42:.*]]{{.*}} step %[[c1:.*]]{{.*}} {345// CHECK-NEXT:     %[[c0:.*]]{{.*}} = arith.constant 0 : index346// CHECK-NEXT:     %[[cm10:.*]]{{.*}} = arith.constant -10 : index347// CHECK-NEXT:     %{{.*}} = arith.addi %{{.*}}, %[[cm10:.*]]{{.*}} : index348// CHECK-NEXT:     %{{.*}} = arith.cmpi sge, %{{.*}}, %[[c0:.*]]{{.*}} : index349// CHECK-NEXT:     if %{{.*}} {350// CHECK-NEXT:       %[[c0_:.*]]{{.*}} = arith.constant 0 : index351// CHECK-NEXT:       %[[c42_:.*]]{{.*}} = arith.constant 42 : index352// CHECK-NEXT:       %[[c1_:.*]]{{.*}} = arith.constant 1 : index353// CHECK-NEXT:       for %{{.*}} = %[[c0_:.*]]{{.*}} to %[[c42_:.*]]{{.*}} step %[[c1_:.*]]{{.*}} {354  affine.for %k = 0 to 42 {355    affine.if #set2(%k) {356      affine.for %l = 0 to 42 {357        func.call @body3(%k, %l) : (index, index) -> ()358      }359    }360  }361//      CHECK:   return362  return363}364 365#lbMultiMap = affine_map<(d0)[s0] -> (d0, s0 - d0)>366#ubMultiMap = affine_map<(d0)[s0] -> (s0, d0 + 10)>367 368// CHECK-LABEL: func @loop_min_max369// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index370// CHECK-NEXT:   %[[c42:.*]] = arith.constant 42 : index371// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index372// CHECK-NEXT:   for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] {373// CHECK-NEXT:     %[[cm1:.*]] = arith.constant -1 : index374// CHECK-NEXT:     %[[mul0:.*]] = arith.muli %{{.*}}, %[[cm1]] overflow<nsw> : index375// CHECK-NEXT:     %[[add0:.*]] = arith.addi %[[mul0]], %{{.*}} : index376// CHECK-NEXT:     %[[max:.*]] = arith.maxsi %{{.*}}, %[[add0]] : index377// CHECK-NEXT:     %[[c10:.*]] = arith.constant 10 : index378// CHECK-NEXT:     %[[add1:.*]] = arith.addi %{{.*}}, %[[c10]] : index379// CHECK-NEXT:     %[[min:.*]] = arith.minsi %{{.*}}, %[[add1]] : index380// CHECK-NEXT:     %[[c1_0:.*]] = arith.constant 1 : index381// CHECK-NEXT:     for %{{.*}} = %[[max]] to %[[min]] step %[[c1_0]] {382// CHECK-NEXT:       call @body2(%{{.*}}, %{{.*}}) : (index, index) -> ()383// CHECK-NEXT:     }384// CHECK-NEXT:   }385// CHECK-NEXT:   return386// CHECK-NEXT: }387func.func @loop_min_max(%N : index) {388  affine.for %i = 0 to 42 {389    affine.for %j = max #lbMultiMap(%i)[%N] to min #ubMultiMap(%i)[%N] {390      func.call @body2(%i, %j) : (index, index) -> ()391    }392  }393  return394}395 396#map_7_values = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d0, d1, d2, d3, d4, d5, d6)>397 398// Check that the "min" reduction sequence is emitted399// correctly for an affine map with 7 results.400 401// CHECK-LABEL: func @min_reduction_tree402// CHECK-NEXT:   %[[c0:.*]] = arith.constant 0 : index403// CHECK-NEXT:   %[[min:.+]] = arith.minsi %{{.*}}, %{{.*}} : index404// CHECK-NEXT:   %[[min_0:.+]] = arith.minsi %[[min]], %{{.*}} : index405// CHECK-NEXT:   %[[min_1:.+]] = arith.minsi %[[min_0]], %{{.*}} : index406// CHECK-NEXT:   %[[min_2:.+]] = arith.minsi %[[min_1]], %{{.*}} : index407// CHECK-NEXT:   %[[min_3:.+]] = arith.minsi %[[min_2]], %{{.*}} : index408// CHECK-NEXT:   %[[min_4:.+]] = arith.minsi %[[min_3]], %{{.*}} : index409// CHECK-NEXT:   %[[c1:.*]] = arith.constant 1 : index410// CHECK-NEXT:   for %{{.*}} = %[[c0]] to %[[min_4]] step %[[c1]] {411// CHECK-NEXT:     call @body(%{{.*}}) : (index) -> ()412// CHECK-NEXT:   }413// CHECK-NEXT:   return414// CHECK-NEXT: }415func.func @min_reduction_tree(%v1 : index, %v2 : index, %v3 : index, %v4 : index, %v5 : index, %v6 : index, %v7 : index) {416  affine.for %i = 0 to min #map_7_values(%v1, %v2, %v3, %v4, %v5, %v6, %v7)[] {417    func.call @body(%i) : (index) -> ()418  }419  return420}421 422/////////////////////////////////////////////////////////////////////423 424#map0 = affine_map<() -> (0)>425#map1 = affine_map<()[s0] -> (s0)>426#map2 = affine_map<(d0) -> (d0)>427#map3 = affine_map<(d0)[s0] -> (d0 + s0 + 1)>428#map4 = affine_map<(d0,d1,d2,d3)[s0,s1,s2] -> (d0 + 2*d1 + 3*d2 + 4*d3 + 5*s0 + 6*s1 + 7*s2)>429#map5 = affine_map<(d0,d1,d2) -> (d0,d1,d2)>430#map6 = affine_map<(d0,d1,d2) -> (d0 + d1 + d2)>431 432// CHECK-LABEL: func @affine_applies(433func.func @affine_applies(%arg0 : index) {434// CHECK: %[[c0:.*]] = arith.constant 0 : index435  %zero = affine.apply #map0()436 437// Identity maps are just discarded.438// CHECK-NEXT: %[[c101:.*]] = arith.constant 101 : index439  %101 = arith.constant 101 : index440  %symbZero = affine.apply #map1()[%zero]441// CHECK-NEXT: %[[c102:.*]] = arith.constant 102 : index442  %102 = arith.constant 102 : index443  %copy = affine.apply #map2(%zero)444 445// CHECK-NEXT: %[[v0:.*]] = arith.addi %[[c0]], %[[c0]] : index446// CHECK-NEXT: %[[c1:.*]] = arith.constant 1 : index447// CHECK-NEXT: %[[v1:.*]] = arith.addi %[[v0]], %[[c1]] : index448  %one = affine.apply #map3(%symbZero)[%zero]449 450// CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index451// CHECK-NEXT: %[[v2:.*]] = arith.muli %arg0, %[[c2]] overflow<nsw> : index452// CHECK-NEXT: %[[v3:.*]] = arith.addi %arg0, %[[v2]] : index453// CHECK-NEXT: %[[c3:.*]] = arith.constant 3 : index454// CHECK-NEXT: %[[v4:.*]] = arith.muli %arg0, %[[c3]] overflow<nsw> : index455// CHECK-NEXT: %[[v5:.*]] = arith.addi %[[v3]], %[[v4]] : index456// CHECK-NEXT: %[[c4:.*]] = arith.constant 4 : index457// CHECK-NEXT: %[[v6:.*]] = arith.muli %arg0, %[[c4]] overflow<nsw> : index458// CHECK-NEXT: %[[v7:.*]] = arith.addi %[[v5]], %[[v6]] : index459// CHECK-NEXT: %[[c5:.*]] = arith.constant 5 : index460// CHECK-NEXT: %[[v8:.*]] = arith.muli %arg0, %[[c5]] overflow<nsw> : index461// CHECK-NEXT: %[[v9:.*]] = arith.addi %[[v7]], %[[v8]] : index462// CHECK-NEXT: %[[c6:.*]] = arith.constant 6 : index463// CHECK-NEXT: %[[v10:.*]] = arith.muli %arg0, %[[c6]] overflow<nsw> : index464// CHECK-NEXT: %[[v11:.*]] = arith.addi %[[v9]], %[[v10]] : index465// CHECK-NEXT: %[[c7:.*]] = arith.constant 7 : index466// CHECK-NEXT: %[[v12:.*]] = arith.muli %arg0, %[[c7]] overflow<nsw> : index467// CHECK-NEXT: %[[v13:.*]] = arith.addi %[[v11]], %[[v12]] : index468  %four = affine.apply #map4(%arg0, %arg0, %arg0, %arg0)[%arg0, %arg0, %arg0]469  return470}471 472// CHECK-LABEL: func @args_ret_affine_apply(473func.func @args_ret_affine_apply(index, index) -> (index, index) {474^bb0(%0 : index, %1 : index):475// CHECK-NEXT: return %{{.*}}, %{{.*}} : index, index476  %00 = affine.apply #map2 (%0)477  %11 = affine.apply #map1 ()[%1]478  return %00, %11 : index, index479}480 481//===---------------------------------------------------------------------===//482// Test lowering of Euclidean (floor) division, ceil division and modulo483// operation used in affine expressions.  In addition to testing the484// operation-level output, check that the obtained results are correct by485// applying constant folding transformation after affine lowering.486//===---------------------------------------------------------------------===//487 488// --------------------------------------------------------------------------//489// IMPORTANT NOTE: if you change this test, also change the @lowered_affine_mod490// test in the "canonicalize.mlir" test to reflect the expected output of491// affine.apply lowering.492// --------------------------------------------------------------------------//493 494#map_mod = affine_map<(i) -> (i mod 42)>495// CHECK-LABEL: func @affine_apply_mod496func.func @affine_apply_mod(%arg0 : index) -> (index) {497// CHECK-NEXT: %[[c42:.*]] = arith.constant 42 : index498// CHECK-NEXT: %[[v0:.*]] = arith.remsi %{{.*}}, %[[c42]] : index499// CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : index500// CHECK-NEXT: %[[v1:.*]] = arith.cmpi slt, %[[v0]], %[[c0]] : index501// CHECK-NEXT: %[[v2:.*]] = arith.addi %[[v0]], %[[c42]] : index502// CHECK-NEXT: %[[v3:.*]] = arith.select %[[v1]], %[[v2]], %[[v0]] : index503  %0 = affine.apply #map_mod (%arg0)504  return %0 : index505}506#map_mod_dynamic_divisor = affine_map<(i)[s] -> (i mod s)>507// CHECK-LABEL: func @affine_apply_mod_dynamic_divisor508func.func @affine_apply_mod_dynamic_divisor(%arg0 : index, %arg1 : index) -> (index) {509// CHECK-NEXT: %[[v0:.*]] = arith.remsi %{{.*}}, %arg1 : index510// CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : index511// CHECK-NEXT: %[[v1:.*]] = arith.cmpi slt, %[[v0]], %[[c0]] : index512// CHECK-NEXT: %[[v2:.*]] = arith.addi %[[v0]], %arg1 : index513// CHECK-NEXT: %[[v3:.*]] = arith.select %[[v1]], %[[v2]], %[[v0]] : index514  %0 = affine.apply #map_mod_dynamic_divisor (%arg0)[%arg1]515  return %0 : index516}517 518// --------------------------------------------------------------------------//519// IMPORTANT NOTE: if you change this test, also change the @lowered_affine_floordiv520// test in the "canonicalize.mlir" test to reflect the expected output of521// affine.apply lowering.522// --------------------------------------------------------------------------//523#map_floordiv = affine_map<(i) -> (i floordiv 42)>524// CHECK-LABEL: func @affine_apply_floordiv525func.func @affine_apply_floordiv(%arg0 : index) -> (index) {526// CHECK-NEXT: %[[c42:.*]] = arith.constant 42 : index527// CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : index528// CHECK-NEXT: %[[cm1:.*]] = arith.constant -1 : index529// CHECK-NEXT: %[[v0:.*]] = arith.cmpi slt, %{{.*}}, %[[c0]] : index530// CHECK-NEXT: %[[v1:.*]] = arith.subi %[[cm1]], %{{.*}} : index531// CHECK-NEXT: %[[v2:.*]] = arith.select %[[v0]], %[[v1]], %{{.*}} : index532// CHECK-NEXT: %[[v3:.*]] = arith.divsi %[[v2]], %[[c42]] : index533// CHECK-NEXT: %[[v4:.*]] = arith.subi %[[cm1]], %[[v3]] : index534// CHECK-NEXT: %[[v5:.*]] = arith.select %[[v0]], %[[v4]], %[[v3]] : index535  %0 = affine.apply #map_floordiv (%arg0)536  return %0 : index537}538#map_floordiv_dynamic_divisor = affine_map<(i)[s] -> (i floordiv s)>539// CHECK-LABEL: func @affine_apply_floordiv_dynamic_divisor540func.func @affine_apply_floordiv_dynamic_divisor(%arg0 : index, %arg1 : index) -> (index) {541// CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : index542// CHECK-NEXT: %[[cm1:.*]] = arith.constant -1 : index543// CHECK-NEXT: %[[v0:.*]] = arith.cmpi slt, %{{.*}}, %[[c0]] : index544// CHECK-NEXT: %[[v1:.*]] = arith.subi %[[cm1]], %{{.*}} : index545// CHECK-NEXT: %[[v2:.*]] = arith.select %[[v0]], %[[v1]], %{{.*}} : index546// CHECK-NEXT: %[[v3:.*]] = arith.divsi %[[v2]], %arg1 : index547// CHECK-NEXT: %[[v4:.*]] = arith.subi %[[cm1]], %[[v3]] : index548// CHECK-NEXT: %[[v5:.*]] = arith.select %[[v0]], %[[v4]], %[[v3]] : index549  %0 = affine.apply #map_floordiv_dynamic_divisor (%arg0)[%arg1]550  return %0 : index551}552 553// --------------------------------------------------------------------------//554// IMPORTANT NOTE: if you change this test, also change the @lowered_affine_ceildiv555// test in the "canonicalize.mlir" test to reflect the expected output of556// affine.apply lowering.557// --------------------------------------------------------------------------//558#map_ceildiv = affine_map<(i) -> (i ceildiv 42)>559// CHECK-LABEL: func @affine_apply_ceildiv560func.func @affine_apply_ceildiv(%arg0 : index) -> (index) {561// CHECK-NEXT:  %[[c42:.*]] = arith.constant 42 : index562// CHECK-NEXT:  %[[c0:.*]] = arith.constant 0 : index563// CHECK-NEXT:  %[[c1:.*]] = arith.constant 1 : index564// CHECK-NEXT:  %[[v0:.*]] = arith.cmpi sle, %{{.*}}, %[[c0]] : index565// CHECK-NEXT:  %[[v1:.*]] = arith.subi %[[c0]], %{{.*}} : index566// CHECK-NEXT:  %[[v2:.*]] = arith.subi %{{.*}}, %[[c1]] : index567// CHECK-NEXT:  %[[v3:.*]] = arith.select %[[v0]], %[[v1]], %[[v2]] : index568// CHECK-NEXT:  %[[v4:.*]] = arith.divsi %[[v3]], %[[c42]] : index569// CHECK-NEXT:  %[[v5:.*]] = arith.subi %[[c0]], %[[v4]] : index570// CHECK-NEXT:  %[[v6:.*]] = arith.addi %[[v4]], %[[c1]] : index571// CHECK-NEXT:  %[[v7:.*]] = arith.select %[[v0]], %[[v5]], %[[v6]] : index572  %0 = affine.apply #map_ceildiv (%arg0)573  return %0 : index574}575#map_ceildiv_dynamic_divisor = affine_map<(i)[s] -> (i ceildiv s)>576// CHECK-LABEL: func @affine_apply_ceildiv_dynamic_divisor577func.func @affine_apply_ceildiv_dynamic_divisor(%arg0 : index, %arg1 : index) -> (index) {578// CHECK-NEXT:  %[[c0:.*]] = arith.constant 0 : index579// CHECK-NEXT:  %[[c1:.*]] = arith.constant 1 : index580// CHECK-NEXT:  %[[v0:.*]] = arith.cmpi sle, %{{.*}}, %[[c0]] : index581// CHECK-NEXT:  %[[v1:.*]] = arith.subi %[[c0]], %{{.*}} : index582// CHECK-NEXT:  %[[v2:.*]] = arith.subi %{{.*}}, %[[c1]] : index583// CHECK-NEXT:  %[[v3:.*]] = arith.select %[[v0]], %[[v1]], %[[v2]] : index584// CHECK-NEXT:  %[[v4:.*]] = arith.divsi %[[v3]], %arg1 : index585// CHECK-NEXT:  %[[v5:.*]] = arith.subi %[[c0]], %[[v4]] : index586// CHECK-NEXT:  %[[v6:.*]] = arith.addi %[[v4]], %[[c1]] : index587// CHECK-NEXT:  %[[v7:.*]] = arith.select %[[v0]], %[[v5]], %[[v6]] : index588  %0 = affine.apply #map_ceildiv_dynamic_divisor (%arg0)[%arg1]589  return %0 : index590}591 592// CHECK-LABEL: func @affine_load593func.func @affine_load(%arg0 : index) {594  %0 = memref.alloc() : memref<10xf32>595  affine.for %i0 = 0 to 10 {596    %1 = affine.load %0[%i0 + symbol(%arg0) + 7] : memref<10xf32>597  }598// CHECK:       %[[a:.*]] = arith.addi %{{.*}}, %{{.*}} : index599// CHECK-NEXT:  %[[c7:.*]] = arith.constant 7 : index600// CHECK-NEXT:  %[[b:.*]] = arith.addi %[[a]], %[[c7]] : index601// CHECK-NEXT:  %{{.*}} = memref.load %[[v0:.*]][%[[b]]] : memref<10xf32>602  return603}604 605// CHECK-LABEL: func @affine_store606func.func @affine_store(%arg0 : index) {607  %0 = memref.alloc() : memref<10xf32>608  %1 = arith.constant 11.0 : f32609  affine.for %i0 = 0 to 10 {610    affine.store %1, %0[%i0 - symbol(%arg0) + 7] : memref<10xf32>611  }612// CHECK:       %[[cm1:.*]] = arith.constant -1 : index613// CHECK-NEXT:  %[[a:.*]] = arith.muli %{{.*}}, %[[cm1]] overflow<nsw> : index614// CHECK-NEXT:  %[[b:.*]] = arith.addi %{{.*}}, %[[a]] : index615// CHECK-NEXT:  %[[c7:.*]] = arith.constant 7 : index616// CHECK-NEXT:  %[[c:.*]] = arith.addi %[[b]], %[[c7]] : index617// CHECK-NEXT:  store %{{.*}}, %{{.*}}[%[[c]]] : memref<10xf32>618  return619}620 621// CHECK-LABEL: func @affine_load_store_zero_dim622func.func @affine_load_store_zero_dim(%arg0 : memref<i32>, %arg1 : memref<i32>) {623  %0 = affine.load %arg0[] : memref<i32>624  affine.store %0, %arg1[] : memref<i32>625// CHECK: %[[x:.*]] = memref.load %arg0[] : memref<i32>626// CHECK: store %[[x]], %arg1[] : memref<i32>627  return628}629 630// CHECK-LABEL: func @affine_prefetch631func.func @affine_prefetch(%arg0 : index) {632  %0 = memref.alloc() : memref<10xf32>633  affine.for %i0 = 0 to 10 {634    affine.prefetch %0[%i0 + symbol(%arg0) + 7], read, locality<3>, data : memref<10xf32>635  }636// CHECK:       %[[a:.*]] = arith.addi %{{.*}}, %{{.*}} : index637// CHECK-NEXT:  %[[c7:.*]] = arith.constant 7 : index638// CHECK-NEXT:  %[[b:.*]] = arith.addi %[[a]], %[[c7]] : index639// CHECK-NEXT:  memref.prefetch %[[v0:.*]][%[[b]]], read, locality<3>, data : memref<10xf32>640  return641}642 643// CHECK-LABEL: func @affine_dma_start644func.func @affine_dma_start(%arg0 : index) {645  %0 = memref.alloc() : memref<100xf32>646  %1 = memref.alloc() : memref<100xf32, 2>647  %2 = memref.alloc() : memref<1xi32>648  %c0 = arith.constant 0 : index649  %c64 = arith.constant 64 : index650  affine.for %i0 = 0 to 10 {651    affine.dma_start %0[%i0 + 7], %1[%arg0 + 11], %2[%c0], %c64652        : memref<100xf32>, memref<100xf32, 2>, memref<1xi32>653  }654// CHECK:       %[[c7:.*]] = arith.constant 7 : index655// CHECK-NEXT:  %[[a:.*]] = arith.addi %{{.*}}, %[[c7]] : index656// CHECK-NEXT:  %[[c11:.*]] = arith.constant 11 : index657// CHECK-NEXT:  %[[b:.*]] = arith.addi %{{.*}}, %[[c11]] : index658// CHECK-NEXT:  dma_start %{{.*}}[%[[a]]], %{{.*}}[%[[b]]], %{{.*}}, %{{.*}}[%{{.*}}] : memref<100xf32>, memref<100xf32, 2>, memref<1xi32>659  return660}661 662// CHECK-LABEL: func @affine_dma_wait663func.func @affine_dma_wait(%arg0 : index) {664  %2 = memref.alloc() : memref<1xi32>665  %c64 = arith.constant 64 : index666  affine.for %i0 = 0 to 10 {667    affine.dma_wait %2[%i0 + %arg0 + 17], %c64 : memref<1xi32>668  }669// CHECK:       %[[a:.*]] = arith.addi %{{.*}}, %arg0 : index670// CHECK-NEXT:  %[[c17:.*]] = arith.constant 17 : index671// CHECK-NEXT:  %[[b:.*]] = arith.addi %[[a]], %[[c17]] : index672// CHECK-NEXT:  dma_wait %{{.*}}[%[[b]]], %{{.*}} : memref<1xi32>673  return674}675 676// CHECK-LABEL: func @affine_min677// CHECK-SAME: %[[ARG0:.*]]: index, %[[ARG1:.*]]: index678func.func @affine_min(%arg0: index, %arg1: index) -> index{679  // CHECK: %[[Cm1:.*]] = arith.constant -1680  // CHECK: %[[neg1:.*]] = arith.muli %[[ARG1]], %[[Cm1:.*]]681  // CHECK: %[[first:.*]] = arith.addi %[[ARG0]], %[[neg1]]682  // CHECK: %[[Cm2:.*]] = arith.constant -1683  // CHECK: %[[neg2:.*]] = arith.muli %[[ARG0]], %[[Cm2:.*]]684  // CHECK: %[[second:.*]] = arith.addi %[[ARG1]], %[[neg2]]685  // CHECK: arith.minsi %[[first]], %[[second]]686  %0 = affine.min affine_map<(d0,d1) -> (d0 - d1, d1 - d0)>(%arg0, %arg1)687  return %0 : index688}689 690// CHECK-LABEL: func @affine_max691// CHECK-SAME: %[[ARG0:.*]]: index, %[[ARG1:.*]]: index692func.func @affine_max(%arg0: index, %arg1: index) -> index{693  // CHECK: %[[Cm1:.*]] = arith.constant -1694  // CHECK: %[[neg1:.*]] = arith.muli %[[ARG1]], %[[Cm1:.*]]695  // CHECK: %[[first:.*]] = arith.addi %[[ARG0]], %[[neg1]]696  // CHECK: %[[Cm2:.*]] = arith.constant -1697  // CHECK: %[[neg2:.*]] = arith.muli %[[ARG0]], %[[Cm2:.*]]698  // CHECK: %[[second:.*]] = arith.addi %[[ARG1]], %[[neg2]]699  // CHECK: arith.maxsi %[[first]], %[[second]]700  %0 = affine.max affine_map<(d0,d1) -> (d0 - d1, d1 - d0)>(%arg0, %arg1)701  return %0 : index702}703 704// CHECK-LABEL: func @affine_parallel(705// CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>) {706func.func @affine_parallel(%o: memref<100x100xf32>, %a: memref<100x100xf32>) {707  affine.parallel (%i, %j) = (0, 0) to (100, 100) {708  }709  return710}711 712// CHECK-DAG:    %[[C100:.*]] = arith.constant 100713// CHECK-DAG:    %[[C100_1:.*]] = arith.constant 100714// CHECK-DAG:    %[[C0:.*]] = arith.constant 0715// CHECK-DAG:    %[[C0_1:.*]] = arith.constant 0716// CHECK-DAG:    %[[C1:.*]] = arith.constant 1717// CHECK-DAG:    %[[C1_1:.*]] = arith.constant 1718// CHECK-DAG:    scf.parallel (%arg2, %arg3) = (%[[C0]], %[[C0_1]]) to (%[[C100]], %[[C100_1]]) step (%[[C1]], %[[C1_1]]) {719 720// CHECK-LABEL: func @affine_parallel_tiled(721// CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>, %[[ARG2:.*]]: memref<100x100xf32>) {722func.func @affine_parallel_tiled(%o: memref<100x100xf32>, %a: memref<100x100xf32>, %b: memref<100x100xf32>) {723  affine.parallel (%i0, %j0, %k0) = (0, 0, 0) to (100, 100, 100) step (10, 10, 10) {724    affine.parallel (%i1, %j1, %k1) = (%i0, %j0, %k0) to (%i0 + 10, %j0 + 10, %k0 + 10) {725      %0 = affine.load %a[%i1, %k1] : memref<100x100xf32>726      %1 = affine.load %b[%k1, %j1] : memref<100x100xf32>727      %2 = arith.mulf %0, %1 : f32728    }729  }730  return731}732 733// CHECK-DAG:     %[[C100:.*]] = arith.constant 100734// CHECK-DAG:     %[[C100_0:.*]] = arith.constant 100735// CHECK-DAG:     %[[C100_1:.*]] = arith.constant 100736// CHECK-DAG:     %[[C0:.*]] = arith.constant 0737// CHECK-DAG:     %[[C0_2:.*]] = arith.constant 0738// CHECK-DAG:     %[[C0_3:.*]] = arith.constant 0739// CHECK-DAG:     %[[C10:.*]] = arith.constant 10740// CHECK-DAG:     %[[C10_4:.*]] = arith.constant 10741// CHECK-DAG:     %[[C10_5:.*]] = arith.constant 10742// CHECK:         scf.parallel (%[[arg3:.*]], %[[arg4:.*]], %[[arg5:.*]]) = (%[[C0]], %[[C0_2]], %[[C0_3]]) to (%[[C100]], %[[C100_0]], %[[C100_1]]) step (%[[C10]], %[[C10_4]], %[[C10_5]]) {743// CHECK-DAG:       %[[C10_6:.*]] = arith.constant 10744// CHECK-DAG:       %[[A0:.*]] = arith.addi %[[arg3]], %[[C10_6]]745// CHECK-DAG:       %[[C10_7:.*]] = arith.constant 10746// CHECK-DAG:       %[[A1:.*]] = arith.addi %[[arg4]], %[[C10_7]]747// CHECK-DAG:       %[[C10_8:.*]] = arith.constant 10748// CHECK-DAG:       %[[A2:.*]] = arith.addi %[[arg5]], %[[C10_8]]749// CHECK-DAG:       %[[C1:.*]] = arith.constant 1750// CHECK-DAG:       %[[C1_9:.*]] = arith.constant 1751// CHECK-DAG:       %[[C1_10:.*]] = arith.constant 1752// CHECK:           scf.parallel (%[[arg6:.*]], %[[arg7:.*]], %[[arg8:.*]]) = (%[[arg3]], %[[arg4]], %[[arg5]]) to (%[[A0]], %[[A1]], %[[A2]]) step (%[[C1]], %[[C1_9]], %[[C1_10]]) {753// CHECK:             %[[A3:.*]] = memref.load %[[ARG1]][%[[arg6]], %[[arg8]]] : memref<100x100xf32>754// CHECK:             %[[A4:.*]] = memref.load %[[ARG2]][%[[arg8]], %[[arg7]]] : memref<100x100xf32>755// CHECK:             arith.mulf %[[A3]], %[[A4]] : f32756// CHECK:             scf.reduce757 758/////////////////////////////////////////////////////////////////////759 760func.func @affine_parallel_simple(%arg0: memref<3x3xf32>, %arg1: memref<3x3xf32>) -> (memref<3x3xf32>) {761  %O = memref.alloc() : memref<3x3xf32>762  affine.parallel (%kx, %ky) = (0, 0) to (2, 2) {763      %1 = affine.load %arg0[%kx, %ky] : memref<3x3xf32>764      %2 = affine.load %arg1[%kx, %ky] : memref<3x3xf32>765      %3 = arith.mulf %1, %2 : f32766      affine.store %3, %O[%kx, %ky] : memref<3x3xf32>767  }768  return %O : memref<3x3xf32>769}770// CHECK-LABEL: func @affine_parallel_simple771// CHECK:         %[[LOWER_1:.*]] = arith.constant 0 : index772// CHECK-NEXT:    %[[UPPER_1:.*]] = arith.constant 2 : index773// CHECK-NEXT:    %[[LOWER_2:.*]] = arith.constant 0 : index774// CHECK-NEXT:    %[[UPPER_2:.*]] = arith.constant 2 : index775// CHECK-NEXT:    %[[STEP_1:.*]] = arith.constant 1 : index776// CHECK-NEXT:    %[[STEP_2:.*]] = arith.constant 1 : index777// CHECK-NEXT:    scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[LOWER_1]], %[[LOWER_2]]) to (%[[UPPER_1]], %[[UPPER_2]]) step (%[[STEP_1]], %[[STEP_2]]) {778// CHECK-NEXT:      %[[VAL_1:.*]] = memref.load779// CHECK-NEXT:      %[[VAL_2:.*]] = memref.load780// CHECK-NEXT:      %[[PRODUCT:.*]] = arith.mulf781// CHECK-NEXT:      store782// CHECK-NEXT:      scf.reduce783// CHECK-NEXT:    }784// CHECK-NEXT:    return785// CHECK-NEXT:  }786 787/////////////////////////////////////////////////////////////////////788 789func.func @affine_parallel_simple_dynamic_bounds(%arg0: memref<?x?xf32>, %arg1: memref<?x?xf32>, %arg2: memref<?x?xf32>) {790  %c_0 = arith.constant 0 : index791  %output_dim = memref.dim %arg0, %c_0 : memref<?x?xf32>792  affine.parallel (%kx, %ky) = (%c_0, %c_0) to (%output_dim, %output_dim) {793      %1 = affine.load %arg0[%kx, %ky] : memref<?x?xf32>794      %2 = affine.load %arg1[%kx, %ky] : memref<?x?xf32>795      %3 = arith.mulf %1, %2 : f32796      affine.store %3, %arg2[%kx, %ky] : memref<?x?xf32>797  }798  return799}800// CHECK-LABEL: func @affine_parallel_simple_dynamic_bounds801// CHECK-SAME:  %[[ARG_0:.*]]: memref<?x?xf32>, %[[ARG_1:.*]]: memref<?x?xf32>, %[[ARG_2:.*]]: memref<?x?xf32>802// CHECK:         %[[DIM_INDEX:.*]] = arith.constant 0 : index803// CHECK-NEXT:    %[[UPPER:.*]] = memref.dim %[[ARG_0]], %[[DIM_INDEX]] : memref<?x?xf32>804// CHECK-NEXT:    %[[LOWER_1:.*]] = arith.constant 0 : index805// CHECK-NEXT:    %[[LOWER_2:.*]] = arith.constant 0 : index806// CHECK-NEXT:    %[[STEP_1:.*]] = arith.constant 1 : index807// CHECK-NEXT:    %[[STEP_2:.*]] = arith.constant 1 : index808// CHECK-NEXT:    scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[LOWER_1]], %[[LOWER_2]]) to (%[[UPPER]], %[[UPPER]]) step (%[[STEP_1]], %[[STEP_2]]) {809// CHECK-NEXT:      %[[VAL_1:.*]] = memref.load810// CHECK-NEXT:      %[[VAL_2:.*]] = memref.load811// CHECK-NEXT:      %[[PRODUCT:.*]] = arith.mulf812// CHECK-NEXT:      store813// CHECK-NEXT:      scf.reduce814// CHECK-NEXT:    }815// CHECK-NEXT:    return816// CHECK-NEXT:  }817 818/////////////////////////////////////////////////////////////////////819 820func.func @affine_parallel_with_reductions(%arg0: memref<3x3xf32>, %arg1: memref<3x3xf32>) -> (f32, f32) {821  %0:2 = affine.parallel (%kx, %ky) = (0, 0) to (2, 2) reduce ("addf", "mulf") -> (f32, f32) {822            %1 = affine.load %arg0[%kx, %ky] : memref<3x3xf32>823            %2 = affine.load %arg1[%kx, %ky] : memref<3x3xf32>824            %3 = arith.mulf %1, %2 : f32825            %4 = arith.addf %1, %2 : f32826            affine.yield %3, %4 : f32, f32827          }828  return %0#0, %0#1 : f32, f32829}830// CHECK-LABEL: func @affine_parallel_with_reductions831// CHECK:         %[[LOWER_1:.*]] = arith.constant 0 : index832// CHECK-NEXT:    %[[UPPER_1:.*]] = arith.constant 2 : index833// CHECK-NEXT:    %[[LOWER_2:.*]] = arith.constant 0 : index834// CHECK-NEXT:    %[[UPPER_2:.*]] = arith.constant 2 : index835// CHECK-NEXT:    %[[STEP_1:.*]] = arith.constant 1 : index836// CHECK-NEXT:    %[[STEP_2:.*]] = arith.constant 1 : index837// CHECK-NEXT:    %[[INIT_1:.*]] = arith.constant 0.000000e+00 : f32838// CHECK-NEXT:    %[[INIT_2:.*]] = arith.constant 1.000000e+00 : f32839// CHECK-NEXT:    %[[RES:.*]] = scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[LOWER_1]], %[[LOWER_2]]) to (%[[UPPER_1]], %[[UPPER_2]]) step (%[[STEP_1]], %[[STEP_2]]) init (%[[INIT_1]], %[[INIT_2]]) -> (f32, f32) {840// CHECK-NEXT:      %[[VAL_1:.*]] = memref.load841// CHECK-NEXT:      %[[VAL_2:.*]] = memref.load842// CHECK-NEXT:      %[[PRODUCT:.*]] = arith.mulf843// CHECK-NEXT:      %[[SUM:.*]] = arith.addf844// CHECK-NEXT:      scf.reduce(%[[PRODUCT]], %[[SUM]] : f32, f32) {845// CHECK-NEXT:      ^bb0(%[[LHS:.*]]: f32, %[[RHS:.*]]: f32):846// CHECK-NEXT:        %[[RES:.*]] = arith.addf847// CHECK-NEXT:        scf.reduce.return %[[RES]] : f32848// CHECK-NEXT:      }, {849// CHECK-NEXT:      ^bb0(%[[LHS:.*]]: f32, %[[RHS:.*]]: f32):850// CHECK-NEXT:        %[[RES:.*]] = arith.mulf851// CHECK-NEXT:        scf.reduce.return %[[RES]] : f32852// CHECK-NEXT:      }853// CHECK-NEXT:    }854// CHECK-NEXT:    return855// CHECK-NEXT:  }856 857/////////////////////////////////////////////////////////////////////858 859func.func @affine_parallel_with_reductions_f64(%arg0: memref<3x3xf64>, %arg1: memref<3x3xf64>) -> (f64, f64) {860  %0:2 = affine.parallel (%kx, %ky) = (0, 0) to (2, 2) reduce ("addf", "mulf") -> (f64, f64) {861            %1 = affine.load %arg0[%kx, %ky] : memref<3x3xf64>862            %2 = affine.load %arg1[%kx, %ky] : memref<3x3xf64>863            %3 = arith.mulf %1, %2 : f64864            %4 = arith.addf %1, %2 : f64865            affine.yield %3, %4 : f64, f64866          }867  return %0#0, %0#1 : f64, f64868}869// CHECK-LABEL: @affine_parallel_with_reductions_f64870// CHECK:  %[[LOWER_1:.*]] = arith.constant 0 : index871// CHECK:  %[[UPPER_1:.*]] = arith.constant 2 : index872// CHECK:  %[[LOWER_2:.*]] = arith.constant 0 : index873// CHECK:  %[[UPPER_2:.*]] = arith.constant 2 : index874// CHECK:  %[[STEP_1:.*]] = arith.constant 1 : index875// CHECK:  %[[STEP_2:.*]] = arith.constant 1 : index876// CHECK:  %[[INIT_1:.*]] = arith.constant 0.000000e+00 : f64877// CHECK:  %[[INIT_2:.*]] = arith.constant 1.000000e+00 : f64878// CHECK:  %[[RES:.*]] = scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[LOWER_1]], %[[LOWER_2]]) to (%[[UPPER_1]], %[[UPPER_2]]) step (%[[STEP_1]], %[[STEP_2]]) init (%[[INIT_1]], %[[INIT_2]]) -> (f64, f64) {879// CHECK:    %[[VAL_1:.*]] = memref.load880// CHECK:    %[[VAL_2:.*]] = memref.load881// CHECK:    %[[PRODUCT:.*]] = arith.mulf882// CHECK:    %[[SUM:.*]] = arith.addf883// CHECK:    scf.reduce(%[[PRODUCT]], %[[SUM]] : f64, f64) {884// CHECK:    ^bb0(%[[LHS:.*]]: f64, %[[RHS:.*]]: f64):885// CHECK:      %[[RES:.*]] = arith.addf886// CHECK:      scf.reduce.return %[[RES]] : f64887// CHECK:    }, {888// CHECK:    ^bb0(%[[LHS:.*]]: f64, %[[RHS:.*]]: f64):889// CHECK:      %[[RES:.*]] = arith.mulf890// CHECK:      scf.reduce.return %[[RES]] : f64891// CHECK:    }892// CHECK:  }893 894/////////////////////////////////////////////////////////////////////895 896func.func @affine_parallel_with_reductions_i64(%arg0: memref<3x3xi64>, %arg1: memref<3x3xi64>) -> (i64, i64) {897  %0:2 = affine.parallel (%kx, %ky) = (0, 0) to (2, 2) reduce ("addi", "muli") -> (i64, i64) {898            %1 = affine.load %arg0[%kx, %ky] : memref<3x3xi64>899            %2 = affine.load %arg1[%kx, %ky] : memref<3x3xi64>900            %3 = arith.muli %1, %2 : i64901            %4 = arith.addi %1, %2 : i64902            affine.yield %3, %4 : i64, i64903          }904  return %0#0, %0#1 : i64, i64905}906// CHECK-LABEL: @affine_parallel_with_reductions_i64907// CHECK:  %[[LOWER_1:.*]] = arith.constant 0 : index908// CHECK:  %[[UPPER_1:.*]] = arith.constant 2 : index909// CHECK:  %[[LOWER_2:.*]] = arith.constant 0 : index910// CHECK:  %[[UPPER_2:.*]] = arith.constant 2 : index911// CHECK:  %[[STEP_1:.*]] = arith.constant 1 : index912// CHECK:  %[[STEP_2:.*]] = arith.constant 1 : index913// CHECK:  %[[INIT_1:.*]] = arith.constant 0 : i64914// CHECK:  %[[INIT_2:.*]] = arith.constant 1 : i64915// CHECK:  %[[RES:.*]] = scf.parallel (%[[I:.*]], %[[J:.*]]) = (%[[LOWER_1]], %[[LOWER_2]]) to (%[[UPPER_1]], %[[UPPER_2]]) step (%[[STEP_1]], %[[STEP_2]]) init (%[[INIT_1]], %[[INIT_2]]) -> (i64, i64) {916// CHECK:    %[[VAL_1:.*]] = memref.load917// CHECK:    %[[VAL_2:.*]] = memref.load918// CHECK:    %[[PRODUCT:.*]] = arith.muli919// CHECK:    %[[SUM:.*]] = arith.addi920// CHECK:    scf.reduce(%[[PRODUCT]], %[[SUM]] : i64, i64) {921// CHECK:    ^bb0(%[[LHS:.*]]: i64, %[[RHS:.*]]: i64):922// CHECK:      %[[RES:.*]] = arith.addi923// CHECK:      scf.reduce.return %[[RES]] : i64924// CHECK:    }, {925// CHECK:    ^bb0(%[[LHS:.*]]: i64, %[[RHS:.*]]: i64):926// CHECK:      %[[RES:.*]] = arith.muli927// CHECK:      scf.reduce.return %[[RES]] : i64928// CHECK:    }929// CHECK:  }930