2174 lines · plain
1// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{test-convergence}))' -split-input-file | FileCheck %s2 3func.func @single_iteration_some(%A: memref<?x?x?xi32>) {4 %c0 = arith.constant 0 : index5 %c1 = arith.constant 1 : index6 %c2 = arith.constant 2 : index7 %c3 = arith.constant 3 : index8 %c6 = arith.constant 6 : index9 %c7 = arith.constant 7 : index10 %c10 = arith.constant 10 : index11 scf.parallel (%i0, %i1, %i2) = (%c0, %c3, %c7) to (%c1, %c6, %c10) step (%c1, %c2, %c3) {12 %c42 = arith.constant 42 : i3213 memref.store %c42, %A[%i0, %i1, %i2] : memref<?x?x?xi32>14 scf.reduce15 }16 return17}18 19// CHECK-LABEL: func @single_iteration_some(20// CHECK-SAME: [[ARG0:%.*]]: memref<?x?x?xi32>) {21// CHECK-DAG: [[C42:%.*]] = arith.constant 42 : i3222// CHECK-DAG: [[C7:%.*]] = arith.constant 7 : index23// CHECK-DAG: [[C6:%.*]] = arith.constant 6 : index24// CHECK-DAG: [[C3:%.*]] = arith.constant 3 : index25// CHECK-DAG: [[C2:%.*]] = arith.constant 2 : index26// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index27// CHECK: scf.parallel ([[V0:%.*]]) = ([[C3]]) to ([[C6]]) step ([[C2]]) {28// CHECK: memref.store [[C42]], [[ARG0]]{{\[}}[[C0]], [[V0]], [[C7]]] : memref<?x?x?xi32>29// CHECK: scf.reduce30// CHECK: }31// CHECK: return32 33// -----34 35func.func @single_iteration_all(%A: memref<?x?x?xi32>) {36 %c0 = arith.constant 0 : index37 %c1 = arith.constant 1 : index38 %c3 = arith.constant 3 : index39 %c6 = arith.constant 6 : index40 %c7 = arith.constant 7 : index41 %c10 = arith.constant 10 : index42 scf.parallel (%i0, %i1, %i2) = (%c0, %c3, %c7) to (%c1, %c6, %c10) step (%c1, %c3, %c3) {43 %c42 = arith.constant 42 : i3244 memref.store %c42, %A[%i0, %i1, %i2] : memref<?x?x?xi32>45 scf.reduce46 }47 return48}49 50// CHECK-LABEL: func @single_iteration_all(51// CHECK-SAME: [[ARG0:%.*]]: memref<?x?x?xi32>) {52// CHECK-DAG: [[C42:%.*]] = arith.constant 42 : i3253// CHECK-DAG: [[C7:%.*]] = arith.constant 7 : index54// CHECK-DAG: [[C3:%.*]] = arith.constant 3 : index55// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index56// CHECK-NOT: scf.parallel57// CHECK: memref.store [[C42]], [[ARG0]]{{\[}}[[C0]], [[C3]], [[C7]]] : memref<?x?x?xi32>58// CHECK-NOT: scf.reduce59// CHECK: return60 61// -----62 63func.func @single_iteration_reduce(%A: index, %B: index) -> (index, index) {64 %c0 = arith.constant 0 : index65 %c1 = arith.constant 1 : index66 %c2 = arith.constant 2 : index67 %c3 = arith.constant 3 : index68 %c6 = arith.constant 6 : index69 %0:2 = scf.parallel (%i0, %i1) = (%c1, %c3) to (%c2, %c6) step (%c1, %c3) init(%A, %B) -> (index, index) {70 scf.reduce(%i0, %i1 : index, index) {71 ^bb0(%lhs: index, %rhs: index):72 %1 = arith.addi %lhs, %rhs : index73 scf.reduce.return %1 : index74 }, {75 ^bb0(%lhs: index, %rhs: index):76 %2 = arith.muli %lhs, %rhs : index77 scf.reduce.return %2 : index78 }79 }80 return %0#0, %0#1 : index, index81}82 83// CHECK-LABEL: func @single_iteration_reduce(84// CHECK-SAME: [[ARG0:%.*]]: index, [[ARG1:%.*]]: index)85// CHECK-DAG: [[C3:%.*]] = arith.constant 3 : index86// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index87// CHECK-NOT: scf.parallel88// CHECK-NOT: scf.reduce89// CHECK-NOT: scf.reduce.return90// CHECK-NOT: scf.yield91// CHECK: [[V0:%.*]] = arith.addi [[ARG0]], [[C1]]92// CHECK: [[V1:%.*]] = arith.muli [[ARG1]], [[C3]]93// CHECK: return [[V0]], [[V1]]94 95// -----96 97func.func @nested_parallel(%0: memref<?x?x?xf64>) -> memref<?x?x?xf64> {98 %c0 = arith.constant 0 : index99 %c1 = arith.constant 1 : index100 %c2 = arith.constant 2 : index101 %1 = memref.dim %0, %c0 : memref<?x?x?xf64>102 %2 = memref.dim %0, %c1 : memref<?x?x?xf64>103 %3 = memref.dim %0, %c2 : memref<?x?x?xf64>104 %4 = memref.alloc(%1, %2, %3) : memref<?x?x?xf64>105 scf.parallel (%arg1) = (%c0) to (%1) step (%c1) {106 scf.parallel (%arg2) = (%c0) to (%2) step (%c1) {107 scf.parallel (%arg3) = (%c0) to (%3) step (%c1) {108 %5 = memref.load %0[%arg1, %arg2, %arg3] : memref<?x?x?xf64>109 memref.store %5, %4[%arg1, %arg2, %arg3] : memref<?x?x?xf64>110 scf.reduce111 }112 scf.reduce113 }114 scf.reduce115 }116 return %4 : memref<?x?x?xf64>117}118 119// CHECK-LABEL: func @nested_parallel(120// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index121// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index122// CHECK-DAG: [[C2:%.*]] = arith.constant 2 : index123// CHECK: [[B0:%.*]] = memref.dim {{.*}}, [[C0]]124// CHECK: [[B1:%.*]] = memref.dim {{.*}}, [[C1]]125// CHECK: [[B2:%.*]] = memref.dim {{.*}}, [[C2]]126// CHECK: scf.parallel ([[V0:%.*]], [[V1:%.*]], [[V2:%.*]]) = ([[C0]], [[C0]], [[C0]]) to ([[B0]], [[B1]], [[B2]]) step ([[C1]], [[C1]], [[C1]])127// CHECK: memref.load {{.*}}{{\[}}[[V0]], [[V1]], [[V2]]]128// CHECK: memref.store {{.*}}{{\[}}[[V0]], [[V1]], [[V2]]]129 130// -----131 132func.func private @side_effect()133func.func @one_unused(%cond: i1) -> (index) {134 %0, %1 = scf.if %cond -> (index, index) {135 func.call @side_effect() : () -> ()136 %c0 = "test.value0"() : () -> (index)137 %c1 = "test.value1"() : () -> (index)138 scf.yield %c0, %c1 : index, index139 } else {140 %c2 = "test.value2"() : () -> (index)141 %c3 = "test.value3"() : () -> (index)142 scf.yield %c2, %c3 : index, index143 }144 return %1 : index145}146 147// CHECK-LABEL: func @one_unused148// CHECK: [[V0:%.*]] = scf.if %{{.*}} -> (index) {149// CHECK: call @side_effect() : () -> ()150// CHECK: [[C1:%.*]] = "test.value1"151// CHECK: scf.yield [[C1]] : index152// CHECK: } else {153// CHECK: [[C3:%.*]] = "test.value3"154// CHECK: scf.yield [[C3]] : index155// CHECK: }156// CHECK: return [[V0]] : index157 158// -----159 160func.func private @side_effect()161func.func @nested_unused(%cond1: i1, %cond2: i1) -> (index) {162 %0, %1 = scf.if %cond1 -> (index, index) {163 %2, %3 = scf.if %cond2 -> (index, index) {164 func.call @side_effect() : () -> ()165 %c0 = "test.value0"() : () -> (index)166 %c1 = "test.value1"() : () -> (index)167 scf.yield %c0, %c1 : index, index168 } else {169 %c2 = "test.value2"() : () -> (index)170 %c3 = "test.value3"() : () -> (index)171 scf.yield %c2, %c3 : index, index172 }173 scf.yield %2, %3 : index, index174 } else {175 %c0 = "test.value0_2"() : () -> (index)176 %c1 = "test.value1_2"() : () -> (index)177 scf.yield %c0, %c1 : index, index178 }179 return %1 : index180}181 182// CHECK-LABEL: func @nested_unused183// CHECK: [[V0:%.*]] = scf.if {{.*}} -> (index) {184// CHECK: [[V1:%.*]] = scf.if {{.*}} -> (index) {185// CHECK: call @side_effect() : () -> ()186// CHECK: [[C1:%.*]] = "test.value1"187// CHECK: scf.yield [[C1]] : index188// CHECK: } else {189// CHECK: [[C3:%.*]] = "test.value3"190// CHECK: scf.yield [[C3]] : index191// CHECK: }192// CHECK: scf.yield [[V1]] : index193// CHECK: } else {194// CHECK: [[C1_2:%.*]] = "test.value1_2"195// CHECK: scf.yield [[C1_2]] : index196// CHECK: }197// CHECK: return [[V0]] : index198 199// -----200 201func.func private @side_effect()202func.func @all_unused(%cond: i1) {203 %c0 = arith.constant 0 : index204 %c1 = arith.constant 1 : index205 %0, %1 = scf.if %cond -> (index, index) {206 func.call @side_effect() : () -> ()207 scf.yield %c0, %c1 : index, index208 } else {209 func.call @side_effect() : () -> ()210 scf.yield %c0, %c1 : index, index211 }212 return213}214 215// CHECK-LABEL: func @all_unused216// CHECK: scf.if %{{.*}} {217// CHECK: call @side_effect() : () -> ()218// CHECK: } else {219// CHECK: call @side_effect() : () -> ()220// CHECK: }221// CHECK: return222 223// -----224 225func.func @empty_if1(%cond: i1) {226 scf.if %cond {227 scf.yield228 }229 return230}231 232// CHECK-LABEL: func @empty_if1233// CHECK-NOT: scf.if234// CHECK: return235 236// -----237 238func.func @empty_if2(%cond: i1) {239 scf.if %cond {240 scf.yield241 } else {242 scf.yield243 }244 return245}246 247// CHECK-LABEL: func @empty_if2248// CHECK-NOT: scf.if249// CHECK: return250 251// -----252 253func.func @empty_else(%cond: i1, %v : memref<i1>) {254 scf.if %cond {255 memref.store %cond, %v[] : memref<i1>256 } else {257 }258 return259}260 261// CHECK-LABEL: func @empty_else262// CHECK: scf.if263// CHECK-NOT: else264 265// -----266 267func.func @to_select1(%cond: i1) -> index {268 %c0 = arith.constant 0 : index269 %c1 = arith.constant 1 : index270 %0 = scf.if %cond -> index {271 scf.yield %c0 : index272 } else {273 scf.yield %c1 : index274 }275 return %0 : index276}277 278// CHECK-LABEL: func @to_select1279// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index280// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index281// CHECK: [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]282// CHECK: return [[V0]] : index283 284// -----285 286func.func @to_select_same_val(%cond: i1) -> (index, index) {287 %c0 = arith.constant 0 : index288 %c1 = arith.constant 1 : index289 %0, %1 = scf.if %cond -> (index, index) {290 scf.yield %c0, %c1 : index, index291 } else {292 scf.yield %c1, %c1 : index, index293 }294 return %0, %1 : index, index295}296 297// CHECK-LABEL: func @to_select_same_val298// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index299// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index300// CHECK: [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]301// CHECK: return [[V0]], [[C1]] : index, index302 303// -----304 305func.func @to_select_with_body(%cond: i1) -> index {306 %c0 = arith.constant 0 : index307 %c1 = arith.constant 1 : index308 %0 = scf.if %cond -> index {309 "test.op"() : () -> ()310 scf.yield %c0 : index311 } else {312 scf.yield %c1 : index313 }314 return %0 : index315}316 317// CHECK-LABEL: func @to_select_with_body318// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index319// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index320// CHECK: [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C1]]321// CHECK: scf.if {{.*}} {322// CHECK: "test.op"() : () -> ()323// CHECK: }324// CHECK: return [[V0]] : index325 326// -----327 328func.func @to_select2(%cond: i1) -> (index, index) {329 %c0 = arith.constant 0 : index330 %c1 = arith.constant 1 : index331 %c2 = arith.constant 2 : index332 %c3 = arith.constant 3 : index333 %0, %1 = scf.if %cond -> (index, index) {334 scf.yield %c0, %c1 : index, index335 } else {336 scf.yield %c2, %c3 : index, index337 }338 return %0, %1 : index, index339}340 341// CHECK-LABEL: func @to_select2342// CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index343// CHECK-DAG: [[C1:%.*]] = arith.constant 1 : index344// CHECK-DAG: [[C2:%.*]] = arith.constant 2 : index345// CHECK-DAG: [[C3:%.*]] = arith.constant 3 : index346// CHECK: [[V0:%.*]] = arith.select {{.*}}, [[C0]], [[C2]]347// CHECK: [[V1:%.*]] = arith.select {{.*}}, [[C1]], [[C3]]348// CHECK: return [[V0]], [[V1]] : index349 350// -----351 352func.func private @make_i32() -> i32353 354func.func @for_yields_2(%lb : index, %ub : index, %step : index) -> i32 {355 %a = call @make_i32() : () -> (i32)356 %b = scf.for %i = %lb to %ub step %step iter_args(%0 = %a) -> i32 {357 scf.yield %0 : i32358 }359 return %b : i32360}361 362// CHECK-LABEL: func @for_yields_2363// CHECK-NEXT: %[[R:.*]] = call @make_i32() : () -> i32364// CHECK-NEXT: return %[[R]] : i32365 366// -----367 368func.func private @make_i32() -> i32369 370func.func @for_yields_3(%lb : index, %ub : index, %step : index) -> (i32, i32, i32) {371 %a = call @make_i32() : () -> (i32)372 %b = call @make_i32() : () -> (i32)373 %r:3 = scf.for %i = %lb to %ub step %step iter_args(%0 = %a, %1 = %a, %2 = %b) -> (i32, i32, i32) {374 %c = func.call @make_i32() : () -> (i32)375 scf.yield %0, %c, %2 : i32, i32, i32376 } {some_attr}377 return %r#0, %r#1, %r#2 : i32, i32, i32378}379 380// CHECK-LABEL: func @for_yields_3381// CHECK-NEXT: %[[a:.*]] = call @make_i32() : () -> i32382// CHECK-NEXT: %[[b:.*]] = call @make_i32() : () -> i32383// CHECK-NEXT: %[[r1:.*]] = scf.for {{.*}} iter_args(%arg4 = %[[a]]) -> (i32) {384// CHECK-NEXT: %[[c:.*]] = func.call @make_i32() : () -> i32385// CHECK-NEXT: scf.yield %[[c]] : i32386// CHECK-NEXT: } {some_attr}387// CHECK-NEXT: return %[[a]], %[[r1]], %[[b]] : i32, i32, i32388 389// -----390 391// Test that an empty loop which iterates at least once and only returns392// values defined outside of the loop is folded away.393func.func @for_yields_4() -> i32 {394 %c0 = arith.constant 0 : index395 %c1 = arith.constant 1 : index396 %c2 = arith.constant 2 : index397 %a = arith.constant 3 : i32398 %b = arith.constant 4 : i32399 %r = scf.for %i = %c0 to %c2 step %c1 iter_args(%0 = %a) -> i32 {400 scf.yield %b : i32401 }402 return %r : i32403}404 405// CHECK-LABEL: func @for_yields_4406// CHECK-NEXT: %[[b:.*]] = arith.constant 4 : i32407// CHECK-NEXT: return %[[b]] : i32408 409// -----410 411// CHECK-LABEL: @constant_iter_arg412func.func @constant_iter_arg(%arg0: index, %arg1: index, %arg2: index) {413 %c0_i32 = arith.constant 0 : i32414 // CHECK: scf.for %arg3 = %arg0 to %arg1 step %arg2 {415 %0 = scf.for %i = %arg0 to %arg1 step %arg2 iter_args(%arg3 = %c0_i32) -> i32 {416 // CHECK-NEXT: "test.use"(%c0_i32)417 "test.use"(%arg3) : (i32) -> ()418 scf.yield %c0_i32 : i32419 }420 return421}422 423// -----424 425// CHECK-LABEL: @replace_true_if426func.func @replace_true_if() {427 %true = arith.constant true428 // CHECK-NOT: scf.if429 // CHECK: "test.op"430 scf.if %true {431 "test.op"() : () -> ()432 scf.yield433 }434 return435}436 437// -----438 439// CHECK-LABEL: @remove_false_if440func.func @remove_false_if() {441 %false = arith.constant false442 // CHECK-NOT: scf.if443 // CHECK-NOT: "test.op"444 scf.if %false {445 "test.op"() : () -> ()446 scf.yield447 }448 return449}450 451// -----452 453// CHECK-LABEL: @replace_true_if_with_values454func.func @replace_true_if_with_values() {455 %true = arith.constant true456 // CHECK-NOT: scf.if457 // CHECK: %[[VAL:.*]] = "test.op"458 %0 = scf.if %true -> (i32) {459 %1 = "test.op"() : () -> i32460 scf.yield %1 : i32461 } else {462 %2 = "test.other_op"() : () -> i32463 scf.yield %2 : i32464 }465 // CHECK: "test.consume"(%[[VAL]])466 "test.consume"(%0) : (i32) -> ()467 return468}469 470// -----471 472// CHECK-LABEL: @replace_false_if_with_values473func.func @replace_false_if_with_values() {474 %false = arith.constant false475 // CHECK-NOT: scf.if476 // CHECK: %[[VAL:.*]] = "test.other_op"477 %0 = scf.if %false -> (i32) {478 %1 = "test.op"() : () -> i32479 scf.yield %1 : i32480 } else {481 %2 = "test.other_op"() : () -> i32482 scf.yield %2 : i32483 }484 // CHECK: "test.consume"(%[[VAL]])485 "test.consume"(%0) : (i32) -> ()486 return487}488 489// -----490 491// CHECK-LABEL: @merge_nested_if492// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)493func.func @merge_nested_if(%arg0: i1, %arg1: i1) {494// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]495// CHECK: scf.if %[[COND]] {496// CHECK-NEXT: "test.op"()497 scf.if %arg0 {498 scf.if %arg1 {499 "test.op"() : () -> ()500 scf.yield501 }502 scf.yield503 }504 return505}506 507// -----508 509// CHECK-LABEL: @merge_yielding_nested_if510// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)511func.func @merge_yielding_nested_if(%arg0: i1, %arg1: i1) -> (i32, f32, i32, i8) {512// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32513// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> f32514// CHECK: %[[PRE2:.*]] = "test.op2"() : () -> i32515// CHECK: %[[PRE3:.*]] = "test.op3"() : () -> i8516// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]517// CHECK: %[[RES:.*]]:2 = scf.if %[[COND]] -> (f32, i32)518// CHECK: %[[IN0:.*]] = "test.inop"() : () -> i32519// CHECK: %[[IN1:.*]] = "test.inop1"() : () -> f32520// CHECK: scf.yield %[[IN1]], %[[IN0]] : f32, i32521// CHECK: } else {522// CHECK: scf.yield %[[PRE1]], %[[PRE2]] : f32, i32523// CHECK: }524// CHECK: return %[[PRE0]], %[[RES]]#0, %[[RES]]#1, %[[PRE3]] : i32, f32, i32, i8525 %0 = "test.op"() : () -> (i32)526 %1 = "test.op1"() : () -> (f32)527 %2 = "test.op2"() : () -> (i32)528 %3 = "test.op3"() : () -> (i8)529 %r:4 = scf.if %arg0 -> (i32, f32, i32, i8) {530 %a:2 = scf.if %arg1 -> (i32, f32) {531 %i = "test.inop"() : () -> (i32)532 %i1 = "test.inop1"() : () -> (f32)533 scf.yield %i, %i1 : i32, f32534 } else {535 scf.yield %2, %1 : i32, f32536 }537 scf.yield %0, %a#1, %a#0, %3 : i32, f32, i32, i8538 } else {539 scf.yield %0, %1, %2, %3 : i32, f32, i32, i8540 }541 return %r#0, %r#1, %r#2, %r#3 : i32, f32, i32, i8542}543 544// -----545 546// CHECK-LABEL: @merge_yielding_nested_if_nv1547// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)548func.func @merge_yielding_nested_if_nv1(%arg0: i1, %arg1: i1) {549// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32550// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> f32551// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]552// CHECK: scf.if %[[COND]]553// CHECK: %[[IN0:.*]] = "test.inop"() : () -> i32554// CHECK: %[[IN1:.*]] = "test.inop1"() : () -> f32555// CHECK: }556 %0 = "test.op"() : () -> (i32)557 %1 = "test.op1"() : () -> (f32)558 scf.if %arg0 {559 %a:2 = scf.if %arg1 -> (i32, f32) {560 %i = "test.inop"() : () -> (i32)561 %i1 = "test.inop1"() : () -> (f32)562 scf.yield %i, %i1 : i32, f32563 } else {564 scf.yield %0, %1 : i32, f32565 }566 }567 return568}569 570// -----571 572// CHECK-LABEL: @merge_yielding_nested_if_nv2573// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)574func.func @merge_yielding_nested_if_nv2(%arg0: i1, %arg1: i1) -> i32 {575// CHECK: %[[PRE0:.*]] = "test.op"() : () -> i32576// CHECK: %[[PRE1:.*]] = "test.op1"() : () -> i32577// CHECK: %[[COND:.*]] = arith.andi %[[ARG0]], %[[ARG1]]578// CHECK: %[[RES:.*]] = arith.select %[[ARG0]], %[[PRE0]], %[[PRE1]]579// CHECK: scf.if %[[COND]]580// CHECK: "test.run"() : () -> ()581// CHECK: }582// CHECK: return %[[RES]]583 %0 = "test.op"() : () -> (i32)584 %1 = "test.op1"() : () -> (i32)585 %r = scf.if %arg0 -> i32 {586 scf.if %arg1 {587 "test.run"() : () -> ()588 }589 scf.yield %0 : i32590 } else {591 scf.yield %1 : i32592 }593 return %r : i32594}595 596// -----597 598// CHECK-LABEL: @merge_fail_yielding_nested_if599// CHECK-SAME: (%[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1)600func.func @merge_fail_yielding_nested_if(%arg0: i1, %arg1: i1) -> (i32, f32, i32, i8) {601// CHECK-NOT: andi602 %0 = "test.op"() : () -> (i32)603 %1 = "test.op1"() : () -> (f32)604 %2 = "test.op2"() : () -> (i32)605 %3 = "test.op3"() : () -> (i8)606 %r:4 = scf.if %arg0 -> (i32, f32, i32, i8) {607 %a:2 = scf.if %arg1 -> (i32, f32) {608 %i = "test.inop"() : () -> (i32)609 %i1 = "test.inop1"() : () -> (f32)610 scf.yield %i, %i1 : i32, f32611 } else {612 scf.yield %0, %1 : i32, f32613 }614 scf.yield %0, %a#1, %a#0, %3 : i32, f32, i32, i8615 } else {616 scf.yield %0, %1, %2, %3 : i32, f32, i32, i8617 }618 return %r#0, %r#1, %r#2, %r#3 : i32, f32, i32, i8619}620 621// -----622 623// CHECK-LABEL: func @if_condition_swap624// CHECK-NEXT: %{{.*}} = scf.if %arg0 -> (index) {625// CHECK-NEXT: %[[i1:.+]] = "test.origFalse"() : () -> index626// CHECK-NEXT: scf.yield %[[i1]] : index627// CHECK-NEXT: } else {628// CHECK-NEXT: %[[i2:.+]] = "test.origTrue"() : () -> index629// CHECK-NEXT: scf.yield %[[i2]] : index630// CHECK-NEXT: }631func.func @if_condition_swap(%cond: i1) -> index {632 %true = arith.constant true633 %not = arith.xori %cond, %true : i1634 %0 = scf.if %not -> (index) {635 %1 = "test.origTrue"() : () -> index636 scf.yield %1 : index637 } else {638 %1 = "test.origFalse"() : () -> index639 scf.yield %1 : index640 }641 return %0 : index642}643 644// -----645 646// CHECK-LABEL: @remove_zero_iteration_loop647func.func @remove_zero_iteration_loop() {648 %c42 = arith.constant 42 : index649 %c1 = arith.constant 1 : index650 // CHECK: %[[INIT:.*]] = "test.init"651 %init = "test.init"() : () -> i32652 // CHECK-NOT: scf.for653 %0 = scf.for %i = %c42 to %c1 step %c1 iter_args(%arg = %init) -> (i32) {654 %1 = "test.op"(%i, %arg) : (index, i32) -> i32655 scf.yield %1 : i32656 }657 // CHECK: "test.consume"(%[[INIT]])658 "test.consume"(%0) : (i32) -> ()659 return660}661 662// -----663 664// CHECK-LABEL: @remove_zero_iteration_loop_vals665func.func @remove_zero_iteration_loop_vals(%arg0: index) {666 %c2 = arith.constant 2 : index667 // CHECK: %[[INIT:.*]] = "test.init"668 %init = "test.init"() : () -> i32669 // CHECK-NOT: scf.for670 // CHECK-NOT: test.op671 %0 = scf.for %i = %arg0 to %arg0 step %c2 iter_args(%arg = %init) -> (i32) {672 %1 = "test.op"(%i, %arg) : (index, i32) -> i32673 scf.yield %1 : i32674 }675 // CHECK: "test.consume"(%[[INIT]])676 "test.consume"(%0) : (i32) -> ()677 return678}679 680// -----681 682// CHECK-LABEL: @replace_single_iteration_loop_1683func.func @replace_single_iteration_loop_1() {684 // CHECK: %[[LB:.*]] = arith.constant 42685 %c42 = arith.constant 42 : index686 %c43 = arith.constant 43 : index687 %c1 = arith.constant 1 : index688 // CHECK: %[[INIT:.*]] = "test.init"689 %init = "test.init"() : () -> i32690 // CHECK-NOT: scf.for691 // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])692 %0 = scf.for %i = %c42 to %c43 step %c1 iter_args(%arg = %init) -> (i32) {693 %1 = "test.op"(%i, %arg) : (index, i32) -> i32694 scf.yield %1 : i32695 }696 // CHECK: "test.consume"(%[[VAL]])697 "test.consume"(%0) : (i32) -> ()698 return699}700 701// -----702 703// CHECK-LABEL: @replace_single_iteration_loop_2704func.func @replace_single_iteration_loop_2() {705 // CHECK: %[[LB:.*]] = arith.constant 5706 %c5 = arith.constant 5 : index707 %c6 = arith.constant 6 : index708 %c11 = arith.constant 11 : index709 // CHECK: %[[INIT:.*]] = "test.init"710 %init = "test.init"() : () -> i32711 // CHECK-NOT: scf.for712 // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])713 %0 = scf.for %i = %c5 to %c11 step %c6 iter_args(%arg = %init) -> (i32) {714 %1 = "test.op"(%i, %arg) : (index, i32) -> i32715 scf.yield %1 : i32716 }717 // CHECK: "test.consume"(%[[VAL]])718 "test.consume"(%0) : (i32) -> ()719 return720}721 722// -----723 724// CHECK-LABEL: @replace_single_iteration_loop_non_unit_step725func.func @replace_single_iteration_loop_non_unit_step() {726 // CHECK: %[[LB:.*]] = arith.constant 42727 %c42 = arith.constant 42 : index728 %c47 = arith.constant 47 : index729 %c5 = arith.constant 5 : index730 // CHECK: %[[INIT:.*]] = "test.init"731 %init = "test.init"() : () -> i32732 // CHECK-NOT: scf.for733 // CHECK: %[[VAL:.*]] = "test.op"(%[[LB]], %[[INIT]])734 %0 = scf.for %i = %c42 to %c47 step %c5 iter_args(%arg = %init) -> (i32) {735 %1 = "test.op"(%i, %arg) : (index, i32) -> i32736 scf.yield %1 : i32737 }738 // CHECK: "test.consume"(%[[VAL]])739 "test.consume"(%0) : (i32) -> ()740 return741}742 743 744// -----745 746// CHECK-LABEL: func @replace_single_iteration_const_diff(747// CHECK-SAME: %[[A0:.*]]: index)748func.func @replace_single_iteration_const_diff(%arg0 : index) {749 // CHECK-NEXT: %[[CST:.*]] = arith.constant 2750 %c1 = arith.constant 1 : index751 %c2 = arith.constant 2 : index752 %5 = arith.addi %arg0, %c1 overflow<nsw> : index753 // CHECK-NOT: scf.for754 scf.for %arg2 = %arg0 to %5 step %c1 {755 // CHECK-NEXT: %[[MUL:.*]] = arith.muli %[[A0]], %[[CST]]756 %7 = arith.muli %c2, %arg2 : index757 // CHECK-NEXT: "test.consume"(%[[MUL]])758 "test.consume"(%7) : (index) -> ()759 }760 return761}762 763// -----764 765// CHECK-LABEL: @remove_empty_parallel_loop766func.func @remove_empty_parallel_loop(%lb: index, %ub: index, %s: index) {767 // CHECK: %[[INIT:.*]] = "test.init"768 %init = "test.init"() : () -> f32769 // CHECK-NOT: scf.parallel770 // CHECK-NOT: test.produce771 // CHECK-NOT: test.transform772 %0 = scf.parallel (%i, %j, %k) = (%lb, %ub, %lb) to (%ub, %ub, %ub) step (%s, %s, %s) init(%init) -> f32 {773 %1 = "test.produce"() : () -> f32774 scf.reduce(%1 : f32) {775 ^bb0(%lhs: f32, %rhs: f32):776 %2 = "test.transform"(%lhs, %rhs) : (f32, f32) -> f32777 scf.reduce.return %2 : f32778 }779 }780 // CHECK: "test.consume"(%[[INIT]])781 "test.consume"(%0) : (f32) -> ()782 return783}784 785// -----786 787// CHECK-LABEL: fold_away_iter_with_no_use_and_yielded_input788// CHECK-SAME: %[[A0:[0-9a-z]*]]: i32789func.func @fold_away_iter_with_no_use_and_yielded_input(%arg0 : i32,790 %ub : index, %lb : index, %step : index) -> (i32, i32) {791 // CHECK-NEXT: %[[C32:.*]] = arith.constant 32 : i32792 %cst = arith.constant 32 : i32793 // CHECK-NEXT: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args({{.*}} = %[[A0]]) -> (i32) {794 %0:2 = scf.for %arg1 = %lb to %ub step %step iter_args(%arg2 = %arg0, %arg3 = %cst)795 -> (i32, i32) {796 %1 = arith.addi %arg2, %cst : i32797 scf.yield %1, %cst : i32, i32798 }799 800 // CHECK: return %[[FOR_RES]], %[[C32]] : i32, i32801 return %0#0, %0#1 : i32, i32802}803 804// -----805 806// CHECK-LABEL: fold_away_iter_and_result_with_no_use807// CHECK-SAME: %[[A0:[0-9a-z]*]]: i32808func.func @fold_away_iter_and_result_with_no_use(%arg0 : i32,809 %ub : index, %lb : index, %step : index) -> (i32) {810 %cst = arith.constant 32 : i32811 // CHECK: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args({{.*}} = %[[A0]]) -> (i32) {812 %0:2 = scf.for %arg1 = %lb to %ub step %step iter_args(%arg2 = %arg0, %arg3 = %cst)813 -> (i32, i32) {814 %1 = arith.addi %arg2, %cst : i32815 scf.yield %1, %1 : i32, i32816 }817 818 // CHECK: return %[[FOR_RES]] : i32819 return %0#0 : i32820}821 822// -----823 824// CHECK-LABEL: @replace_duplicate_iter_args825// CHECK-SAME: [[LB:%arg[0-9]]]: index, [[UB:%arg[0-9]]]: index, [[STEP:%arg[0-9]]]: index, [[A:%arg[0-9]]]: index, [[B:%arg[0-9]]]: index826func.func @replace_duplicate_iter_args(%lb: index, %ub: index, %step: index, %a: index, %b: index) -> (index, index, index, index) {827 // CHECK-NEXT: [[RES:%.*]]:2 = scf.for {{.*}} iter_args([[K0:%.*]] = [[A]], [[K1:%.*]] = [[B]])828 %0:4 = scf.for %i = %lb to %ub step %step iter_args(%k0 = %a, %k1 = %b, %k2 = %b, %k3 = %a) -> (index, index, index, index) {829 // CHECK-NEXT: [[V0:%.*]] = arith.addi [[K0]], [[K1]]830 %1 = arith.addi %k0, %k1 : index831 // CHECK-NEXT: [[V1:%.*]] = arith.addi [[K1]], [[K0]]832 %2 = arith.addi %k2, %k3 : index833 // CHECK-NEXT: yield [[V0]], [[V1]]834 scf.yield %1, %2, %2, %1 : index, index, index, index835 }836 // CHECK: return [[RES]]#0, [[RES]]#1, [[RES]]#1, [[RES]]#0837 return %0#0, %0#1, %0#2, %0#3 : index, index, index, index838}839 840// -----841 842func.func private @do(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32>843 844func.func @matmul_on_tensors(%t0: tensor<32x1024xf32>) -> tensor<?x?xf32> {845 %c0 = arith.constant 0 : index846 %c32 = arith.constant 32 : index847 %c1024 = arith.constant 1024 : index848 %0 = tensor.cast %t0 : tensor<32x1024xf32> to tensor<?x?xf32>849 %1 = scf.for %i = %c0 to %c1024 step %c32 iter_args(%iter_t0 = %0) -> (tensor<?x?xf32>) {850 %2 = func.call @do(%iter_t0) : (tensor<?x?xf32>) -> tensor<?x?xf32>851 scf.yield %2 : tensor<?x?xf32>852 } {some_attr}853 return %1 : tensor<?x?xf32>854}855// CHECK-LABEL: matmul_on_tensors856// CHECK-SAME: %[[T0:[0-9a-z]*]]: tensor<32x1024xf32>857 858// CHECK-NOT: tensor.cast859// CHECK: %[[FOR_RES:.*]] = scf.for {{.*}} iter_args(%[[ITER_T0:.*]] = %[[T0]]) -> (tensor<32x1024xf32>) {860// CHECK: %[[CAST:.*]] = tensor.cast %[[ITER_T0]] : tensor<32x1024xf32> to tensor<?x?xf32>861// CHECK: %[[DONE:.*]] = func.call @do(%[[CAST]]) : (tensor<?x?xf32>) -> tensor<?x?xf32>862// CHECK: %[[UNCAST:.*]] = tensor.cast %[[DONE]] : tensor<?x?xf32> to tensor<32x1024xf32>863// CHECK: scf.yield %[[UNCAST]] : tensor<32x1024xf32>864// CHECK: } {some_attr}865// CHECK: %[[RES:.*]] = tensor.cast866// CHECK: return %[[RES]] : tensor<?x?xf32>867 868// -----869 870// CHECK-LABEL: @cond_prop871func.func @cond_prop(%arg0 : i1) -> index {872 %res = scf.if %arg0 -> index {873 %res1 = scf.if %arg0 -> index {874 %v1 = "test.get_some_value1"() : () -> index875 scf.yield %v1 : index876 } else {877 %v2 = "test.get_some_value2"() : () -> index878 scf.yield %v2 : index879 }880 scf.yield %res1 : index881 } else {882 %res2 = scf.if %arg0 -> index {883 %v3 = "test.get_some_value3"() : () -> index884 scf.yield %v3 : index885 } else {886 %v4 = "test.get_some_value4"() : () -> index887 scf.yield %v4 : index888 }889 scf.yield %res2 : index890 }891 return %res : index892}893// CHECK-NEXT: %[[if:.+]] = scf.if %arg0 -> (index) {894// CHECK-NEXT: %[[c1:.+]] = "test.get_some_value1"() : () -> index895// CHECK-NEXT: scf.yield %[[c1]] : index896// CHECK-NEXT: } else {897// CHECK-NEXT: %[[c4:.+]] = "test.get_some_value4"() : () -> index898// CHECK-NEXT: scf.yield %[[c4]] : index899// CHECK-NEXT: }900// CHECK-NEXT: return %[[if]] : index901// CHECK-NEXT:}902 903// -----904 905// CHECK-LABEL: @replace_if_with_cond1906func.func @replace_if_with_cond1(%arg0 : i1) -> (i32, i1) {907 %true = arith.constant true908 %false = arith.constant false909 %res:2 = scf.if %arg0 -> (i32, i1) {910 %v = "test.get_some_value"() : () -> i32911 scf.yield %v, %true : i32, i1912 } else {913 %v2 = "test.get_some_value"() : () -> i32914 scf.yield %v2, %false : i32, i1915 }916 return %res#0, %res#1 : i32, i1917}918// CHECK-NEXT: %[[if:.+]] = scf.if %arg0 -> (i32) {919// CHECK-NEXT: %[[sv1:.+]] = "test.get_some_value"() : () -> i32920// CHECK-NEXT: scf.yield %[[sv1]] : i32921// CHECK-NEXT: } else {922// CHECK-NEXT: %[[sv2:.+]] = "test.get_some_value"() : () -> i32923// CHECK-NEXT: scf.yield %[[sv2]] : i32924// CHECK-NEXT: }925// CHECK-NEXT: return %[[if]], %arg0 : i32, i1926 927// -----928 929// CHECK-LABEL: @replace_if_with_cond2930func.func @replace_if_with_cond2(%arg0 : i1) -> (i32, i1) {931 %true = arith.constant true932 %false = arith.constant false933 %res:2 = scf.if %arg0 -> (i32, i1) {934 %v = "test.get_some_value"() : () -> i32935 scf.yield %v, %false : i32, i1936 } else {937 %v2 = "test.get_some_value"() : () -> i32938 scf.yield %v2, %true : i32, i1939 }940 return %res#0, %res#1 : i32, i1941}942// CHECK-NEXT: %true = arith.constant true943// CHECK-NEXT: %[[toret:.+]] = arith.xori %arg0, %true : i1944// CHECK-NEXT: %[[if:.+]] = scf.if %arg0 -> (i32) {945// CHECK-NEXT: %[[sv1:.+]] = "test.get_some_value"() : () -> i32946// CHECK-NEXT: scf.yield %[[sv1]] : i32947// CHECK-NEXT: } else {948// CHECK-NEXT: %[[sv2:.+]] = "test.get_some_value"() : () -> i32949// CHECK-NEXT: scf.yield %[[sv2]] : i32950// CHECK-NEXT: }951// CHECK-NEXT: return %[[if]], %[[toret]] : i32, i1952 953// -----954 955// CHECK-LABEL: @replace_if_with_cond3956func.func @replace_if_with_cond3(%arg0 : i1, %arg2: i64) -> (i32, i64) {957 %res:2 = scf.if %arg0 -> (i32, i64) {958 %v = "test.get_some_value"() : () -> i32959 scf.yield %v, %arg2 : i32, i64960 } else {961 %v2 = "test.get_some_value"() : () -> i32962 scf.yield %v2, %arg2 : i32, i64963 }964 return %res#0, %res#1 : i32, i64965}966// CHECK-NEXT: %[[if:.+]] = scf.if %arg0 -> (i32) {967// CHECK-NEXT: %[[sv1:.+]] = "test.get_some_value"() : () -> i32968// CHECK-NEXT: scf.yield %[[sv1]] : i32969// CHECK-NEXT: } else {970// CHECK-NEXT: %[[sv2:.+]] = "test.get_some_value"() : () -> i32971// CHECK-NEXT: scf.yield %[[sv2]] : i32972// CHECK-NEXT: }973// CHECK-NEXT: return %[[if]], %arg1 : i32, i64974 975// -----976 977// CHECK-LABEL: @while_move_if_down978func.func @while_move_if_down() -> i32 {979 %defined_outside = "test.get_some_value0" () : () -> (i32)980 %0 = scf.while () : () -> (i32) {981 %used_value = "test.get_some_value1" () : () -> (i32)982 %used_by_subregion = "test.get_some_value2" () : () -> (i32)983 %else_value = "test.get_some_value3" () : () -> (i32)984 %condition = "test.condition"() : () -> i1985 %res = scf.if %condition -> (i32) {986 "test.use0" (%defined_outside) : (i32) -> ()987 "test.use1" (%used_value) : (i32) -> ()988 test.alloca_scope_region {989 "test.use2" (%used_by_subregion) : (i32) -> ()990 }991 %then_value = "test.get_some_value4" () : () -> (i32)992 scf.yield %then_value : i32993 } else {994 scf.yield %else_value : i32995 }996 scf.condition(%condition) %res : i32997 } do {998 ^bb0(%res_arg: i32):999 "test.use3" (%res_arg) : (i32) -> ()1000 scf.yield1001 }1002 return %0 : i321003}1004// CHECK: %[[defined_outside:.*]] = "test.get_some_value0"() : () -> i321005// CHECK: %[[WHILE_RES:.*]]:3 = scf.while : () -> (i32, i32, i32) {1006// CHECK: %[[used_value:.*]] = "test.get_some_value1"() : () -> i321007// CHECK: %[[used_by_subregion:.*]] = "test.get_some_value2"() : () -> i321008// CHECK: %[[else_value:.*]] = "test.get_some_value3"() : () -> i321009// CHECK: %[[condition:.*]] = "test.condition"() : () -> i11010// CHECK: scf.condition(%[[condition]]) %[[else_value]], %[[used_value]], %[[used_by_subregion]] : i32, i32, i321011// CHECK: } do {1012// CHECK: ^bb0(%[[res_arg:.*]]: i32, %[[used_value_arg:.*]]: i32, %[[used_by_subregion_arg:.*]]: i32):1013// CHECK: "test.use0"(%[[defined_outside]]) : (i32) -> ()1014// CHECK: "test.use1"(%[[used_value_arg]]) : (i32) -> ()1015// CHECK: test.alloca_scope_region {1016// CHECK: "test.use2"(%[[used_by_subregion_arg]]) : (i32) -> ()1017// CHECK: }1018// CHECK: %[[then_value:.*]] = "test.get_some_value4"() : () -> i321019// CHECK: "test.use3"(%[[then_value]]) : (i32) -> ()1020// CHECK: scf.yield1021// CHECK: }1022// CHECK: return %[[WHILE_RES]]#0 : i321023// CHECK: }1024 1025// -----1026 1027// CHECK-LABEL: @while_cond_true1028func.func @while_cond_true() -> i1 {1029 %0 = scf.while () : () -> i1 {1030 %condition = "test.condition"() : () -> i11031 scf.condition(%condition) %condition : i11032 } do {1033 ^bb0(%arg0: i1):1034 "test.use"(%arg0) : (i1) -> ()1035 scf.yield1036 }1037 return %0 : i11038}1039// CHECK-NEXT: %[[true:.+]] = arith.constant true1040// CHECK-NEXT: %{{.+}} = scf.while : () -> i1 {1041// CHECK-NEXT: %[[cmp:.+]] = "test.condition"() : () -> i11042// CHECK-NEXT: scf.condition(%[[cmp]]) %[[cmp]] : i11043// CHECK-NEXT: } do {1044// CHECK-NEXT: ^bb0(%arg0: i1):1045// CHECK-NEXT: "test.use"(%[[true]]) : (i1) -> ()1046// CHECK-NEXT: scf.yield1047// CHECK-NEXT: }1048 1049// -----1050 1051// CHECK-LABEL: @invariant_loop_args_in_same_order1052// CHECK-SAME: (%[[FUNC_ARG0:.*]]: tensor<i32>)1053func.func @invariant_loop_args_in_same_order(%f_arg0: tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {1054 %cst_0 = arith.constant dense<0> : tensor<i32>1055 %cst_1 = arith.constant dense<1> : tensor<i32>1056 %cst_42 = arith.constant dense<42> : tensor<i32>1057 1058 %0:5 = scf.while (%arg0 = %cst_0, %arg1 = %f_arg0, %arg2 = %cst_1, %arg3 = %cst_1, %arg4 = %cst_0) : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {1059 %1 = arith.cmpi slt, %arg0, %cst_42 : tensor<i32>1060 %2 = tensor.extract %1[] : tensor<i1>1061 scf.condition(%2) %arg0, %arg1, %arg2, %arg3, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1062 } do {1063 ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>): // no predecessors1064 // %arg1 here will get replaced by %cst_11065 %1 = arith.addi %arg0, %arg1 : tensor<i32>1066 %2 = arith.addi %arg2, %arg3 : tensor<i32>1067 scf.yield %1, %arg1, %2, %2, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1068 }1069 return %0#0, %0#1, %0#2, %0#3, %0#4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1070}1071// CHECK: %[[ZERO:.*]] = arith.constant dense<0>1072// CHECK: %[[ONE:.*]] = arith.constant dense<1>1073// CHECK: %[[CST42:.*]] = arith.constant dense<42>1074// CHECK: %[[WHILE:.*]]:3 = scf.while (%[[ARG0:.*]] = %[[ZERO]], %[[ARG2:.*]] = %[[ONE]], %[[ARG3:.*]] = %[[ONE]])1075// CHECK: arith.cmpi slt, %[[ARG0]], %{{.*}}1076// CHECK: tensor.extract %{{.*}}[]1077// CHECK: scf.condition(%{{.*}}) %[[ARG0]], %[[ARG2]], %[[ARG3]]1078// CHECK: } do {1079// CHECK: ^{{.*}}(%[[ARG0:.*]]: tensor<i32>, %[[ARG2:.*]]: tensor<i32>, %[[ARG3:.*]]: tensor<i32>):1080// CHECK: %[[VAL0:.*]] = arith.addi %[[ARG0]], %[[FUNC_ARG0]]1081// CHECK: %[[VAL1:.*]] = arith.addi %[[ARG2]], %[[ARG3]]1082// CHECK: scf.yield %[[VAL0]], %[[VAL1]], %[[VAL1]]1083// CHECK: }1084// CHECK: return %[[WHILE]]#0, %[[FUNC_ARG0]], %[[WHILE]]#1, %[[WHILE]]#2, %[[ZERO]]1085 1086// CHECK-LABEL: @while_loop_invariant_argument_different_order1087func.func @while_loop_invariant_argument_different_order(%arg : tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {1088 %cst_0 = arith.constant dense<0> : tensor<i32>1089 %cst_1 = arith.constant dense<1> : tensor<i32>1090 %cst_42 = arith.constant dense<42> : tensor<i32>1091 1092 %0:6 = scf.while (%arg0 = %cst_0, %arg1 = %cst_1, %arg2 = %cst_1, %arg3 = %cst_1, %arg4 = %cst_0) : (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) -> (tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>) {1093 %1 = arith.cmpi slt, %arg0, %arg : tensor<i32>1094 %2 = tensor.extract %1[] : tensor<i1>1095 scf.condition(%2) %arg1, %arg0, %arg2, %arg0, %arg3, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1096 } do {1097 ^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>, %arg2: tensor<i32>, %arg3: tensor<i32>, %arg4: tensor<i32>, %arg5: tensor<i32>): // no predecessors1098 %1 = arith.addi %arg0, %cst_1 : tensor<i32>1099 %2 = arith.addi %arg2, %arg3 : tensor<i32>1100 scf.yield %arg3, %arg1, %2, %2, %arg4 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1101 }1102 return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>, tensor<i32>1103}1104// CHECK-SAME: (%[[ARG:.+]]: tensor<i32>)1105// CHECK: %[[ZERO:.*]] = arith.constant dense<0>1106// CHECK: %[[ONE:.*]] = arith.constant dense<1>1107// CHECK: %[[WHILE:.*]]:2 = scf.while (%[[ARG1:.*]] = %[[ONE]], %[[ARG4:.*]] = %[[ZERO]])1108// CHECK: arith.cmpi sgt, %[[ARG]], %[[ZERO]]1109// CHECK: tensor.extract %{{.*}}[]1110// CHECK: scf.condition(%{{.*}}) %[[ARG1]], %[[ARG4]]1111// CHECK: } do {1112// CHECK: ^{{.*}}(%{{.*}}: tensor<i32>, %{{.*}}: tensor<i32>):1113// CHECK: scf.yield %[[ZERO]], %[[ONE]]1114// CHECK: }1115// CHECK: return %[[WHILE]]#0, %[[ZERO]], %[[ONE]], %[[ZERO]], %[[ONE]], %[[WHILE]]#11116 1117// -----1118 1119// CHECK-LABEL: @while_unused_result1120func.func @while_unused_result() -> i32 {1121 %0:2 = scf.while () : () -> (i32, i64) {1122 %condition = "test.condition"() : () -> i11123 %v1 = "test.get_some_value"() : () -> i321124 %v2 = "test.get_some_value"() : () -> i641125 scf.condition(%condition) %v1, %v2 : i32, i641126 } do {1127 ^bb0(%arg0: i32, %arg1: i64):1128 "test.use"(%arg0) : (i32) -> ()1129 scf.yield1130 }1131 return %0#0 : i321132}1133// CHECK-NEXT: %[[res:.*]] = scf.while : () -> i32 {1134// CHECK-NEXT: %[[cmp:.*]] = "test.condition"() : () -> i11135// CHECK-NEXT: %[[val:.*]] = "test.get_some_value"() : () -> i321136// CHECK-NEXT: %{{.*}} = "test.get_some_value"() : () -> i641137// CHECK-NEXT: scf.condition(%[[cmp]]) %[[val]] : i321138// CHECK-NEXT: } do {1139// CHECK-NEXT: ^bb0(%[[arg:.*]]: i32):1140// CHECK-NEXT: "test.use"(%[[arg]]) : (i32) -> ()1141// CHECK-NEXT: scf.yield1142// CHECK-NEXT: }1143// CHECK-NEXT: return %[[res]] : i321144 1145// -----1146 1147// CHECK-LABEL: @while_cmp_lhs1148func.func @while_cmp_lhs(%arg0 : i32) {1149 %0 = scf.while () : () -> i32 {1150 %val = "test.val"() : () -> i321151 %condition = arith.cmpi ne, %val, %arg0 : i321152 scf.condition(%condition) %val : i321153 } do {1154 ^bb0(%val2: i32):1155 %condition2 = arith.cmpi ne, %val2, %arg0 : i321156 %negcondition2 = arith.cmpi eq, %val2, %arg0 : i321157 "test.use"(%condition2, %negcondition2, %val2) : (i1, i1, i32) -> ()1158 scf.yield1159 }1160 return1161}1162// CHECK-DAG: %[[true:.+]] = arith.constant true1163// CHECK-DAG: %[[false:.+]] = arith.constant false1164// CHECK-DAG: %{{.+}} = scf.while : () -> i32 {1165// CHECK-NEXT: %[[val:.+]] = "test.val"1166// CHECK-NEXT: %[[cmp:.+]] = arith.cmpi ne, %[[val]], %arg0 : i321167// CHECK-NEXT: scf.condition(%[[cmp]]) %[[val]] : i321168// CHECK-NEXT: } do {1169// CHECK-NEXT: ^bb0(%arg1: i32):1170// CHECK-NEXT: "test.use"(%[[true]], %[[false]], %arg1) : (i1, i1, i32) -> ()1171// CHECK-NEXT: scf.yield1172// CHECK-NEXT: }1173 1174// -----1175 1176// CHECK-LABEL: @while_cmp_rhs1177func.func @while_cmp_rhs(%arg0 : i32) {1178 %0 = scf.while () : () -> i32 {1179 %val = "test.val"() : () -> i321180 %condition = arith.cmpi ne, %arg0, %val : i321181 scf.condition(%condition) %val : i321182 } do {1183 ^bb0(%val2: i32):1184 %condition2 = arith.cmpi ne, %arg0, %val2 : i321185 %negcondition2 = arith.cmpi eq, %arg0, %val2 : i321186 "test.use"(%condition2, %negcondition2, %val2) : (i1, i1, i32) -> ()1187 scf.yield1188 }1189 return1190}1191// CHECK-DAG: %[[true:.+]] = arith.constant true1192// CHECK-DAG: %[[false:.+]] = arith.constant false1193// CHECK-DAG: %{{.+}} = scf.while : () -> i32 {1194// CHECK-NEXT: %[[val:.+]] = "test.val"1195// CHECK-NEXT: %[[cmp:.+]] = arith.cmpi ne, %arg0, %[[val]] : i321196// CHECK-NEXT: scf.condition(%[[cmp]]) %[[val]] : i321197// CHECK-NEXT: } do {1198// CHECK-NEXT: ^bb0(%arg1: i32):1199// CHECK-NEXT: "test.use"(%[[true]], %[[false]], %arg1) : (i1, i1, i32) -> ()1200// CHECK-NEXT: scf.yield1201// CHECK-NEXT: }1202 1203// -----1204 1205// CHECK-LABEL: @while_duplicated_res1206func.func @while_duplicated_res() -> (i32, i32) {1207 %0:2 = scf.while () : () -> (i32, i32) {1208 %val = "test.val"() : () -> i321209 %condition = "test.condition"() : () -> i11210 scf.condition(%condition) %val, %val : i32, i321211 } do {1212 ^bb0(%val2: i32, %val3: i32):1213 "test.use"(%val2, %val3) : (i32, i32) -> ()1214 scf.yield1215 }1216 return %0#0, %0#1: i32, i321217}1218// CHECK: %[[RES:.*]] = scf.while : () -> i32 {1219// CHECK: %[[VAL:.*]] = "test.val"() : () -> i321220// CHECK: %[[COND:.*]] = "test.condition"() : () -> i11221// CHECK: scf.condition(%[[COND]]) %[[VAL]] : i321222// CHECK: } do {1223// CHECK: ^bb0(%[[ARG:.*]]: i32):1224// CHECK: "test.use"(%[[ARG]], %[[ARG]]) : (i32, i32) -> ()1225// CHECK: scf.yield1226// CHECK: }1227// CHECK: return %[[RES]], %[[RES]] : i32, i321228 1229 1230// -----1231 1232// CHECK-LABEL: @while_unused_arg11233func.func @while_unused_arg1(%x : i32, %y : f64) -> i32 {1234 %0 = scf.while (%arg1 = %x, %arg2 = %y) : (i32, f64) -> (i32) {1235 %condition = "test.condition"(%arg1) : (i32) -> i11236 scf.condition(%condition) %arg1 : i321237 } do {1238 ^bb0(%arg1: i32):1239 %next = "test.use"(%arg1) : (i32) -> (i32)1240 scf.yield %next, %y : i32, f641241 }1242 return %0 : i321243}1244// CHECK-NEXT: %[[res:.*]] = scf.while (%[[arg2:.*]] = %{{.*}}) : (i32) -> i32 {1245// CHECK-NEXT: %[[cmp:.*]] = "test.condition"(%[[arg2]]) : (i32) -> i11246// CHECK-NEXT: scf.condition(%[[cmp]]) %[[arg2]] : i321247// CHECK-NEXT: } do {1248// CHECK-NEXT: ^bb0(%[[post:.*]]: i32):1249// CHECK-NEXT: %[[next:.*]] = "test.use"(%[[post]]) : (i32) -> i321250// CHECK-NEXT: scf.yield %[[next]] : i321251// CHECK-NEXT: }1252// CHECK-NEXT: return %[[res]] : i321253 1254 1255// -----1256 1257// CHECK-LABEL: @while_unused_arg21258func.func @while_unused_arg2(%val0: i32) -> i32 {1259 %0 = scf.while (%val1 = %val0) : (i32) -> i32 {1260 %val = "test.val"() : () -> i321261 %condition = "test.condition"() : () -> i11262 scf.condition(%condition) %val: i321263 } do {1264 ^bb0(%val2: i32):1265 "test.use"(%val2) : (i32) -> ()1266 %val1 = "test.val1"() : () -> i321267 scf.yield %val1 : i321268 }1269 return %0 : i321270}1271// CHECK: %[[RES:.*]] = scf.while : () -> i32 {1272// CHECK: %[[VAL:.*]] = "test.val"() : () -> i321273// CHECK: %[[COND:.*]] = "test.condition"() : () -> i11274// CHECK: scf.condition(%[[COND]]) %[[VAL]] : i321275// CHECK: } do {1276// CHECK: ^bb0(%[[ARG:.*]]: i32):1277// CHECK: "test.use"(%[[ARG]]) : (i32) -> ()1278// CHECK: scf.yield1279// CHECK: }1280// CHECK: return %[[RES]] : i321281 1282 1283// -----1284 1285// CHECK-LABEL: func @test_align_args1286// CHECK: %[[RES:.*]]:3 = scf.while (%[[ARG0:.*]] = %{{.*}}, %[[ARG1:.*]] = %{{.*}}, %[[ARG2:.*]] = %{{.*}}) : (f32, i32, i64) -> (f32, i32, i64) {1287// CHECK: scf.condition(%{{.*}}) %[[ARG0]], %[[ARG1]], %[[ARG2]] : f32, i32, i641288// CHECK: ^bb0(%[[ARG3:.*]]: f32, %[[ARG4:.*]]: i32, %[[ARG5:.*]]: i64):1289// CHECK: %[[R1:.*]] = "test.test"(%[[ARG5]]) : (i64) -> f321290// CHECK: %[[R2:.*]] = "test.test"(%[[ARG3]]) : (f32) -> i321291// CHECK: %[[R3:.*]] = "test.test"(%[[ARG4]]) : (i32) -> i641292// CHECK: scf.yield %[[R1]], %[[R2]], %[[R3]] : f32, i32, i641293// CHECK: return %[[RES]]#2, %[[RES]]#0, %[[RES]]#11294func.func @test_align_args() -> (i64, f32, i32) {1295 %0 = "test.test"() : () -> (f32)1296 %1 = "test.test"() : () -> (i32)1297 %2 = "test.test"() : () -> (i64)1298 %3:3 = scf.while (%arg0 = %0, %arg1 = %1, %arg2 = %2) : (f32, i32, i64) -> (i64, f32, i32) {1299 %cond = "test.test"() : () -> (i1)1300 scf.condition(%cond) %arg2, %arg0, %arg1 : i64, f32, i321301 } do {1302 ^bb0(%arg3: i64, %arg4: f32, %arg5: i32):1303 %4 = "test.test"(%arg3) : (i64) -> (f32)1304 %5 = "test.test"(%arg4) : (f32) -> (i32)1305 %6 = "test.test"(%arg5) : (i32) -> (i64)1306 scf.yield %4, %5, %6 : f32, i32, i641307 }1308 return %3#0, %3#1, %3#2 : i64, f32, i321309}1310 1311 1312// -----1313 1314// CHECK-LABEL: @combineIfs1315func.func @combineIfs(%arg0 : i1, %arg2: i64) -> (i32, i32) {1316 %res = scf.if %arg0 -> i32 {1317 %v = "test.firstCodeTrue"() : () -> i321318 scf.yield %v : i321319 } else {1320 %v2 = "test.firstCodeFalse"() : () -> i321321 scf.yield %v2 : i321322 }1323 %res2 = scf.if %arg0 -> i32 {1324 %v = "test.secondCodeTrue"() : () -> i321325 scf.yield %v : i321326 } else {1327 %v2 = "test.secondCodeFalse"() : () -> i321328 scf.yield %v2 : i321329 }1330 return %res, %res2 : i32, i321331}1332// CHECK-NEXT: %[[res:.+]]:2 = scf.if %arg0 -> (i32, i32) {1333// CHECK-NEXT: %[[tval0:.+]] = "test.firstCodeTrue"() : () -> i321334// CHECK-NEXT: %[[tval:.+]] = "test.secondCodeTrue"() : () -> i321335// CHECK-NEXT: scf.yield %[[tval0]], %[[tval]] : i32, i321336// CHECK-NEXT: } else {1337// CHECK-NEXT: %[[fval0:.+]] = "test.firstCodeFalse"() : () -> i321338// CHECK-NEXT: %[[fval:.+]] = "test.secondCodeFalse"() : () -> i321339// CHECK-NEXT: scf.yield %[[fval0]], %[[fval]] : i32, i321340// CHECK-NEXT: }1341// CHECK-NEXT: return %[[res]]#0, %[[res]]#1 : i32, i321342 1343// -----1344 1345// CHECK-LABEL: @combineIfs21346func.func @combineIfs2(%arg0 : i1, %arg2: i64) -> i32 {1347 scf.if %arg0 {1348 "test.firstCodeTrue"() : () -> ()1349 scf.yield1350 }1351 %res = scf.if %arg0 -> i32 {1352 %v = "test.secondCodeTrue"() : () -> i321353 scf.yield %v : i321354 } else {1355 %v2 = "test.secondCodeFalse"() : () -> i321356 scf.yield %v2 : i321357 }1358 return %res : i321359}1360// CHECK-NEXT: %[[res:.+]] = scf.if %arg0 -> (i32) {1361// CHECK-NEXT: "test.firstCodeTrue"() : () -> ()1362// CHECK-NEXT: %[[tval:.+]] = "test.secondCodeTrue"() : () -> i321363// CHECK-NEXT: scf.yield %[[tval]] : i321364// CHECK-NEXT: } else {1365// CHECK-NEXT: %[[fval:.+]] = "test.secondCodeFalse"() : () -> i321366// CHECK-NEXT: scf.yield %[[fval]] : i321367// CHECK-NEXT: }1368// CHECK-NEXT: return %[[res]] : i321369 1370// -----1371 1372// CHECK-LABEL: @combineIfs31373func.func @combineIfs3(%arg0 : i1, %arg2: i64) -> i32 {1374 %res = scf.if %arg0 -> i32 {1375 %v = "test.firstCodeTrue"() : () -> i321376 scf.yield %v : i321377 } else {1378 %v2 = "test.firstCodeFalse"() : () -> i321379 scf.yield %v2 : i321380 }1381 scf.if %arg0 {1382 "test.secondCodeTrue"() : () -> ()1383 scf.yield1384 }1385 return %res : i321386}1387// CHECK-NEXT: %[[res:.+]] = scf.if %arg0 -> (i32) {1388// CHECK-NEXT: %[[tval:.+]] = "test.firstCodeTrue"() : () -> i321389// CHECK-NEXT: "test.secondCodeTrue"() : () -> ()1390// CHECK-NEXT: scf.yield %[[tval]] : i321391// CHECK-NEXT: } else {1392// CHECK-NEXT: %[[fval:.+]] = "test.firstCodeFalse"() : () -> i321393// CHECK-NEXT: scf.yield %[[fval]] : i321394// CHECK-NEXT: }1395// CHECK-NEXT: return %[[res]] : i321396 1397// -----1398 1399// CHECK-LABEL: @combineIfs41400func.func @combineIfs4(%arg0 : i1, %arg2: i64) {1401 scf.if %arg0 {1402 "test.firstCodeTrue"() : () -> ()1403 scf.yield1404 }1405 scf.if %arg0 {1406 "test.secondCodeTrue"() : () -> ()1407 scf.yield1408 }1409 return1410}1411 1412// CHECK-NEXT: scf.if %arg0 {1413// CHECK-NEXT: "test.firstCodeTrue"() : () -> ()1414// CHECK-NEXT: "test.secondCodeTrue"() : () -> ()1415// CHECK-NEXT: }1416 1417// -----1418 1419// CHECK-LABEL: @combineIfsUsed1420// CHECK-SAME: %[[arg0:.+]]: i11421func.func @combineIfsUsed(%arg0 : i1, %arg2: i64) -> (i32, i32) {1422 %res = scf.if %arg0 -> i32 {1423 %v = "test.firstCodeTrue"() : () -> i321424 scf.yield %v : i321425 } else {1426 %v2 = "test.firstCodeFalse"() : () -> i321427 scf.yield %v2 : i321428 }1429 %res2 = scf.if %arg0 -> i32 {1430 %v = "test.secondCodeTrue"(%res) : (i32) -> i321431 scf.yield %v : i321432 } else {1433 %v2 = "test.secondCodeFalse"(%res) : (i32) -> i321434 scf.yield %v2 : i321435 }1436 return %res, %res2 : i32, i321437}1438// CHECK-NEXT: %[[res:.+]]:2 = scf.if %[[arg0]] -> (i32, i32) {1439// CHECK-NEXT: %[[tval0:.+]] = "test.firstCodeTrue"() : () -> i321440// CHECK-NEXT: %[[tval:.+]] = "test.secondCodeTrue"(%[[tval0]]) : (i32) -> i321441// CHECK-NEXT: scf.yield %[[tval0]], %[[tval]] : i32, i321442// CHECK-NEXT: } else {1443// CHECK-NEXT: %[[fval0:.+]] = "test.firstCodeFalse"() : () -> i321444// CHECK-NEXT: %[[fval:.+]] = "test.secondCodeFalse"(%[[fval0]]) : (i32) -> i321445// CHECK-NEXT: scf.yield %[[fval0]], %[[fval]] : i32, i321446// CHECK-NEXT: }1447// CHECK-NEXT: return %[[res]]#0, %[[res]]#1 : i32, i321448 1449// -----1450 1451// CHECK-LABEL: @combineIfsNot1452// CHECK-SAME: %[[arg0:.+]]: i11453func.func @combineIfsNot(%arg0 : i1, %arg2: i64) {1454 %true = arith.constant true1455 %not = arith.xori %arg0, %true : i11456 scf.if %arg0 {1457 "test.firstCodeTrue"() : () -> ()1458 scf.yield1459 }1460 scf.if %not {1461 "test.secondCodeTrue"() : () -> ()1462 scf.yield1463 }1464 return1465}1466 1467// CHECK-NEXT: scf.if %[[arg0]] {1468// CHECK-NEXT: "test.firstCodeTrue"() : () -> ()1469// CHECK-NEXT: } else {1470// CHECK-NEXT: "test.secondCodeTrue"() : () -> ()1471// CHECK-NEXT: }1472 1473// -----1474 1475// CHECK-LABEL: @combineIfsNot21476// CHECK-SAME: %[[arg0:.+]]: i11477func.func @combineIfsNot2(%arg0 : i1, %arg2: i64) {1478 %true = arith.constant true1479 %not = arith.xori %arg0, %true : i11480 scf.if %not {1481 "test.firstCodeTrue"() : () -> ()1482 scf.yield1483 }1484 scf.if %arg0 {1485 "test.secondCodeTrue"() : () -> ()1486 scf.yield1487 }1488 return1489}1490 1491// CHECK-NEXT: scf.if %[[arg0]] {1492// CHECK-NEXT: "test.secondCodeTrue"() : () -> ()1493// CHECK-NEXT: } else {1494// CHECK-NEXT: "test.firstCodeTrue"() : () -> ()1495// CHECK-NEXT: }1496 1497// -----1498 1499// CHECK-LABEL: func @propagate_into_execute_region1500func.func @propagate_into_execute_region() {1501 %cond = arith.constant 0 : i11502 affine.for %i = 0 to 100 {1503 "test.foo"() : () -> ()1504 %v = scf.execute_region -> i64 {1505 cf.cond_br %cond, ^bb1, ^bb21506 1507 ^bb1:1508 %c1 = arith.constant 1 : i641509 cf.br ^bb3(%c1 : i64)1510 1511 ^bb2:1512 %c2 = arith.constant 2 : i641513 cf.br ^bb3(%c2 : i64)1514 1515 ^bb3(%x : i64):1516 scf.yield %x : i641517 }1518 "test.bar"(%v) : (i64) -> ()1519 // CHECK: %[[C2:.*]] = arith.constant 2 : i641520 // CHECK: "test.foo"1521 // CHECK-NEXT: "test.bar"(%[[C2]]) : (i64) -> ()1522 }1523 return1524}1525 1526// -----1527 1528// CHECK-LABEL: func @execute_region_inline1529func.func @execute_region_inline() {1530 affine.for %i = 0 to 100 {1531 "test.foo"() : () -> ()1532 %v = scf.execute_region -> i64 {1533 %x = "test.val"() : () -> i641534 scf.yield %x : i641535 }1536 "test.bar"(%v) : (i64) -> ()1537 }1538 return1539}1540 1541// CHECK-NEXT: affine.for %arg0 = 0 to 100 {1542// CHECK-NEXT: "test.foo"() : () -> ()1543// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i641544// CHECK-NEXT: "test.bar"(%[[VAL]]) : (i64) -> ()1545// CHECK-NEXT: }1546 1547// -----1548 1549// CHECK-LABEL: func @execute_region_no_inline1550func.func @execute_region_no_inline() {1551 affine.for %i = 0 to 100 {1552 "test.foo"() : () -> ()1553 %v = scf.execute_region -> i64 no_inline {1554 %x = "test.val"() : () -> i641555 scf.yield %x : i641556 }1557 "test.bar"(%v) : (i64) -> ()1558 }1559 return1560}1561 1562// CHECK-NEXT: affine.for %arg0 = 0 to 100 {1563// CHECK-NEXT: "test.foo"() : () -> ()1564// CHECK-NEXT: scf.execute_region1565// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i641566// CHECK-NEXT: scf.yield %[[VAL]] : i641567// CHECK-NOT: no_inline1568 1569// -----1570 1571// CHECK-LABEL: func @execute_region_under_func_no_inline1572func.func @execute_region_under_func_no_inline() {1573 "test.foo"() : () -> ()1574 %v = scf.execute_region -> i64 no_inline {1575 %x = "test.val"() : () -> i641576 scf.yield %x : i641577 }1578 "test.bar"(%v) : (i64) -> ()1579 return1580}1581 1582// CHECK-NEXT: "test.foo"() : () -> ()1583// CHECK-NEXT: scf.execute_region1584// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i641585// CHECK-NEXT: scf.yield %[[VAL]] : i641586 1587// -----1588 1589// CHECK-LABEL: func @func_execute_region_inline1590func.func @func_execute_region_inline() {1591 "test.foo"() : () -> ()1592 %v = scf.execute_region -> i64 {1593 %c = "test.cmp"() : () -> i11594 cf.cond_br %c, ^bb2, ^bb31595 ^bb2:1596 %x = "test.val1"() : () -> i641597 cf.br ^bb4(%x : i64)1598 ^bb3:1599 %y = "test.val2"() : () -> i641600 cf.br ^bb4(%y : i64)1601 ^bb4(%z : i64):1602 scf.yield %z : i641603 }1604 "test.bar"(%v) : (i64) -> ()1605 return1606}1607 1608// CHECK-NOT: execute_region1609// CHECK: "test.foo"1610// CHECK: %[[cmp:.+]] = "test.cmp"1611// CHECK: cf.cond_br %[[cmp]], ^[[bb1:.+]], ^[[bb2:.+]]1612// CHECK: ^[[bb1]]:1613// CHECK: %[[x:.+]] = "test.val1"1614// CHECK: cf.br ^[[bb3:.+]](%[[x]] : i64)1615// CHECK: ^[[bb2]]:1616// CHECK: %[[y:.+]] = "test.val2"1617// CHECK: cf.br ^[[bb3]](%[[y:.+]] : i64)1618// CHECK: ^[[bb3]](%[[z:.+]]: i64):1619// CHECK: "test.bar"(%[[z]])1620// CHECK: return1621 1622// -----1623 1624// CHECK-LABEL: func @func_execute_region_inline_multi_yield1625func.func @func_execute_region_inline_multi_yield() {1626 "test.foo"() : () -> ()1627 %v = scf.execute_region -> i64 {1628 %c = "test.cmp"() : () -> i11629 cf.cond_br %c, ^bb2, ^bb31630 ^bb2:1631 %x = "test.val1"() : () -> i641632 scf.yield %x : i641633 ^bb3:1634 %y = "test.val2"() : () -> i641635 scf.yield %y : i641636 }1637 "test.bar"(%v) : (i64) -> ()1638 return1639}1640 1641// CHECK-NOT: execute_region1642// CHECK: "test.foo"1643// CHECK: %[[cmp:.+]] = "test.cmp"1644// CHECK: cf.cond_br %[[cmp]], ^[[bb1:.+]], ^[[bb2:.+]]1645// CHECK: ^[[bb1]]:1646// CHECK: %[[x:.+]] = "test.val1"1647// CHECK: cf.br ^[[bb3:.+]](%[[x]] : i64)1648// CHECK: ^[[bb2]]:1649// CHECK: %[[y:.+]] = "test.val2"1650// CHECK: cf.br ^[[bb3]](%[[y:.+]] : i64)1651// CHECK: ^[[bb3]](%[[z:.+]]: i64):1652// CHECK: "test.bar"(%[[z]])1653// CHECK: return1654 1655// -----1656 1657// Test case with single scf.yield op inside execute_region and its operand is defined outside the execute_region op.1658// Make scf.execute_region not to return anything.1659 1660// CHECK: scf.execute_region no_inline {1661// CHECK: func.call @foo() : () -> ()1662// CHECK: scf.yield1663// CHECK: }1664 1665module {1666func.func private @foo()->()1667func.func private @execute_region_yeilding_external_value() -> memref<1x60xui8> {1668 %alloc = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1669 %1 = scf.execute_region -> memref<1x60xui8> no_inline { 1670 func.call @foo():()->()1671 scf.yield %alloc: memref<1x60xui8>1672 } 1673 return %1 : memref<1x60xui8>1674}1675}1676 1677// -----1678 1679// Test case with scf.yield op inside execute_region with multiple operands.1680// One of operands is defined outside the execute_region op.1681// Remove just this operand from the op results.1682 1683// CHECK: %[[VAL_1:.*]] = scf.execute_region -> memref<1x120xui8> no_inline {1684// CHECK: %[[VAL_2:.*]] = memref.alloc() {alignment = 64 : i64} : memref<1x120xui8>1685// CHECK: func.call @foo() : () -> ()1686// CHECK: scf.yield %[[VAL_2]] : memref<1x120xui8>1687// CHECK: }1688module {1689func.func private @foo()->()1690func.func private @execute_region_yeilding_external_and_local_values() -> (memref<1x60xui8>, memref<1x120xui8>) {1691 %alloc = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1692 %1, %2 = scf.execute_region -> (memref<1x60xui8>, memref<1x120xui8>) no_inline { 1693 %alloc_1 = memref.alloc() {alignment = 64 : i64} : memref<1x120xui8>1694 func.call @foo():()->()1695 scf.yield %alloc, %alloc_1: memref<1x60xui8>, memref<1x120xui8>1696 } 1697 return %1, %2 : memref<1x60xui8>, memref<1x120xui8>1698}1699}1700 1701// -----1702 1703// Test case with multiple scf.yield ops inside execute_region with same operands and those operands are defined outside the execute_region op..1704// Make scf.execute_region not to return anything.1705// scf.yield must remain, cause scf.execute_region can't be empty.1706 1707// CHECK: scf.execute_region no_inline {1708// CHECK: %[[VAL_3:.*]] = "test.cmp"() : () -> i11709// CHECK: cf.cond_br %[[VAL_3]], ^bb1, ^bb21710// CHECK: ^bb1:1711// CHECK: scf.yield1712// CHECK: ^bb2:1713// CHECK: scf.yield1714// CHECK: }1715 1716module {1717 func.func private @foo()->()1718 func.func private @execute_region_multiple_yields_same_operands() -> (memref<1x60xui8>, memref<1x120xui8>) {1719 %alloc = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1720 %alloc_1 = memref.alloc() {alignment = 64 : i64} : memref<1x120xui8> 1721 %1, %2 = scf.execute_region -> (memref<1x60xui8>, memref<1x120xui8>) no_inline {1722 %c = "test.cmp"() : () -> i11723 cf.cond_br %c, ^bb2, ^bb31724 ^bb2: 1725 func.call @foo():()->()1726 scf.yield %alloc, %alloc_1 : memref<1x60xui8>, memref<1x120xui8>1727 ^bb3: 1728 func.call @foo():()->() 1729 scf.yield %alloc, %alloc_1 : memref<1x60xui8>, memref<1x120xui8>1730 } 1731 return %1, %2 : memref<1x60xui8>, memref<1x120xui8>1732 }1733}1734 1735// -----1736 1737// Test case with multiple scf.yield ops with at least one different operand, then no change.1738 1739// CHECK: %[[VAL_3:.*]]:2 = scf.execute_region -> (memref<1x60xui8>, memref<1x120xui8>) no_inline {1740// CHECK: ^bb1:1741// CHECK: scf.yield %{{.*}}, %{{.*}} : memref<1x60xui8>, memref<1x120xui8>1742// CHECK: ^bb2:1743// CHECK: scf.yield %{{.*}}, %{{.*}} : memref<1x60xui8>, memref<1x120xui8>1744// CHECK: }1745 1746module {1747 func.func private @foo()->()1748 func.func private @execute_region_multiple_yields_different_operands() -> (memref<1x60xui8>, memref<1x120xui8>) {1749 %alloc = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1750 %alloc_1 = memref.alloc() {alignment = 64 : i64} : memref<1x120xui8> 1751 %alloc_2 = memref.alloc() {alignment = 64 : i64} : memref<1x120xui8> 1752 %1, %2 = scf.execute_region -> (memref<1x60xui8>, memref<1x120xui8>) no_inline {1753 %c = "test.cmp"() : () -> i11754 cf.cond_br %c, ^bb2, ^bb31755 ^bb2: 1756 func.call @foo():()->()1757 scf.yield %alloc, %alloc_1 : memref<1x60xui8>, memref<1x120xui8>1758 ^bb3: 1759 func.call @foo():()->() 1760 scf.yield %alloc, %alloc_2 : memref<1x60xui8>, memref<1x120xui8>1761 } 1762 return %1, %2 : memref<1x60xui8>, memref<1x120xui8>1763 }1764}1765 1766// -----1767 1768// Test case with multiple scf.yield ops each has different operand.1769// In this case scf.execute_region isn't changed.1770 1771// CHECK: %[[VAL_2:.*]] = scf.execute_region -> memref<1x60xui8> no_inline {1772// CHECK: ^bb1:1773// CHECK: scf.yield %{{.*}} : memref<1x60xui8>1774// CHECK: ^bb2:1775// CHECK: scf.yield %{{.*}} : memref<1x60xui8>1776// CHECK: }1777 1778module {1779func.func private @foo()->()1780func.func private @execute_region_multiple_yields_different_operands() -> (memref<1x60xui8>) {1781 %alloc = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1782 %alloc_1 = memref.alloc() {alignment = 64 : i64} : memref<1x60xui8> 1783 %1 = scf.execute_region -> (memref<1x60xui8>) no_inline {1784 %c = "test.cmp"() : () -> i11785 cf.cond_br %c, ^bb2, ^bb31786 ^bb2: 1787 func.call @foo():()->()1788 scf.yield %alloc : memref<1x60xui8>1789 ^bb3: 1790 func.call @foo():()->()1791 scf.yield %alloc_1 : memref<1x60xui8>1792 } 1793 return %1 : memref<1x60xui8>1794}1795}1796 1797// -----1798 1799// CHECK-LABEL: func @canonicalize_parallel_insert_slice_indices(1800// CHECK-SAME: %[[arg0:.*]]: tensor<1x5xf32>, %[[arg1:.*]]: tensor<?x?xf32>1801func.func @canonicalize_parallel_insert_slice_indices(1802 %arg0 : tensor<1x5xf32>, %arg1: tensor<?x?xf32>, %num_threads : index) -> index1803{1804 // CHECK: %[[c1:.*]] = arith.constant 1 : index1805 %c1 = arith.constant 1 : index1806 1807 %2 = scf.forall (%tidx) in (%num_threads) shared_outs(%o = %arg1) -> (tensor<?x?xf32>) {1808 scf.forall.in_parallel {1809 tensor.parallel_insert_slice %arg0 into %o[%tidx, 0] [1, 5] [1, 1] : tensor<1x5xf32> into tensor<?x?xf32>1810 }1811 }1812 1813 // CHECK: %[[dim:.*]] = tensor.dim %[[arg1]], %[[c1]]1814 %dim = tensor.dim %2, %c1 : tensor<?x?xf32>1815 // CHECK: return %[[dim]]1816 return %dim : index1817}1818 1819// -----1820 1821// CHECK-LABEL: func @forall_fold_control_operands1822func.func @forall_fold_control_operands(1823 %arg0 : tensor<?x10xf32>, %arg1: tensor<?x10xf32>) -> tensor<?x10xf32> {1824 %c0 = arith.constant 0 : index1825 %c1 = arith.constant 1 : index1826 %dim0 = tensor.dim %arg0, %c0 : tensor<?x10xf32>1827 %dim1 = tensor.dim %arg0, %c1 : tensor<?x10xf32>1828 1829 %result = scf.forall (%i, %j) = (%c0, %c0) to (%dim0, %dim1)1830 step (%c1, %c1) shared_outs(%o = %arg1) -> (tensor<?x10xf32>) {1831 %slice = tensor.extract_slice %arg1[%i, %j] [1, 1] [1, 1]1832 : tensor<?x10xf32> to tensor<1x1xf32>1833 1834 scf.forall.in_parallel {1835 tensor.parallel_insert_slice %slice into %o[%i, %j] [1, 1] [1, 1]1836 : tensor<1x1xf32> into tensor<?x10xf32>1837 }1838 }1839 1840 return %result : tensor<?x10xf32>1841}1842// CHECK: forall (%{{.*}}, %{{.*}}) in (%{{.*}}, 10)1843 1844// -----1845 1846func.func @inline_forall_loop(%in: tensor<8x8xf32>) -> tensor<8x8xf32> {1847 %c8 = arith.constant 8 : index1848 %c0 = arith.constant 0 : index1849 %c1 = arith.constant 1 : index1850 %cst = arith.constant 0.000000e+00 : f321851 %0 = tensor.empty() : tensor<8x8xf32>1852 %1 = scf.forall (%i, %j) = (%c0, %c0) to (%c1, %c1)1853 step (%c8, %c8) shared_outs (%out_ = %0) -> (tensor<8x8xf32>) {1854 %slice = tensor.extract_slice %out_[%i, %j] [2, 3] [1, 1]1855 : tensor<8x8xf32> to tensor<2x3xf32>1856 %fill = linalg.fill ins(%cst : f32) outs(%slice : tensor<2x3xf32>)1857 -> tensor<2x3xf32>1858 scf.forall.in_parallel {1859 tensor.parallel_insert_slice %fill into %out_[%i, %j] [2, 3] [1, 1]1860 : tensor<2x3xf32> into tensor<8x8xf32>1861 }1862 }1863 return %1 : tensor<8x8xf32>1864}1865// CHECK-LABEL: @inline_forall_loop1866// CHECK-NOT: scf.forall1867// CHECK: %[[OUT:.*]] = tensor.empty1868 1869// CHECK-NEXT: %[[SLICE:.*]] = tensor.extract_slice %[[OUT]]1870// CHECK-SAME: : tensor<8x8xf32> to tensor<2x3xf32>1871 1872// CHECK-NEXT: %[[FILL:.*]] = linalg.fill1873// CHECK-SAME: outs(%[[SLICE]]1874 1875// CHECK-NEXT: tensor.insert_slice %[[FILL]]1876// CHECK-SAME: : tensor<2x3xf32> into tensor<8x8xf32>1877 1878// -----1879 1880func.func @do_not_inline_distributed_forall_loop(1881 %in: tensor<8x8xf32>) -> tensor<8x8xf32> {1882 %cst = arith.constant 0.000000e+00 : f321883 %0 = tensor.empty() : tensor<8x8xf32>1884 %1 = scf.forall (%i, %j) = (0, 4) to (1, 5) step (8, 8)1885 shared_outs (%out_ = %0) -> (tensor<8x8xf32>) {1886 %slice = tensor.extract_slice %out_[%i, %j] [2, 3] [1, 1]1887 : tensor<8x8xf32> to tensor<2x3xf32>1888 %fill = linalg.fill ins(%cst : f32) outs(%slice : tensor<2x3xf32>)1889 -> tensor<2x3xf32>1890 scf.forall.in_parallel {1891 tensor.parallel_insert_slice %fill into %out_[%i, %j] [2, 3] [1, 1]1892 : tensor<2x3xf32> into tensor<8x8xf32>1893 }1894 }{ mapping = [#gpu.thread<y>, #gpu.thread<x>] }1895 return %1 : tensor<8x8xf32>1896}1897// CHECK-LABEL: @do_not_inline_distributed_forall_loop1898// CHECK: scf.forall1899// CHECK: tensor.extract_slice %{{.*}}[0, 4] [2, 3] [1, 1]1900// CHECK: tensor.parallel_insert_slice %{{.*}}[0, 4] [2, 3] [1, 1]1901 1902// -----1903 1904func.func @inline_empty_loop_with_empty_mapping(1905 %in: tensor<16xf32>) -> tensor<16xf32> {1906 %cst = arith.constant 0.000000e+00 : f321907 %0 = tensor.empty() : tensor<16xf32>1908 %1 = scf.forall () in () shared_outs (%out_ = %0) -> (tensor<16xf32>) {1909 %slice = tensor.extract_slice %out_[0] [16] [1]1910 : tensor<16xf32> to tensor<16xf32>1911 %generic = linalg.generic {1912 indexing_maps = [affine_map<(d0) -> (d0)>, affine_map<(d0) -> (d0)>],1913 iterator_types = ["parallel"]}1914 ins(%slice : tensor<16xf32>) outs(%0 : tensor<16xf32>) {1915 ^bb0(%b0 : f32, %b1 : f32):1916 %2 = arith.addf %b0, %b0 : f321917 linalg.yield %2 : f321918 } -> tensor<16xf32>1919 scf.forall.in_parallel {1920 tensor.parallel_insert_slice %generic into %out_[0] [16] [1]1921 : tensor<16xf32> into tensor<16xf32>1922 }1923 }{ mapping = [] }1924 return %1 : tensor<16xf32>1925}1926// CHECK-LABEL: func @inline_empty_loop_with_empty_mapping1927// CHECK-NOT: scf.forall1928 1929// -----1930 1931func.func @collapse_one_dim_parallel(%in: tensor<8x8xf32>) -> tensor<8x8xf32> {1932 %c8 = arith.constant 8 : index1933 %c0 = arith.constant 0 : index1934 %c1 = arith.constant 1 : index1935 %c16 = arith.constant 16 : index1936 %cst = arith.constant 0.000000e+00 : f321937 %0 = tensor.empty() : tensor<8x8xf32>1938 %1 = scf.forall (%i, %j) = (0, %c0) to (1, %c16)1939 step (8, %c8) shared_outs (%out_ = %0) -> (tensor<8x8xf32>) {1940 %fill = linalg.fill ins(%cst : f32) outs(%out_ : tensor<8x8xf32>)1941 -> tensor<8x8xf32>1942 scf.forall.in_parallel {1943 tensor.parallel_insert_slice %fill into %out_[%i, %j] [8, 8] [1, 1]1944 : tensor<8x8xf32> into tensor<8x8xf32>1945 }1946 }1947 return %1 : tensor<8x8xf32>1948}1949// CHECK-LABEL: @collapse_one_dim_parallel1950// CHECK: scf.forall (%[[ARG:.*]]) = (0) to (16) step (8)1951// CHECK: linalg.fill1952// CHECK: tensor.parallel_insert_slice1953 1954// -----1955 1956func.func @remove_empty_forall(%in: tensor<8x8xf32>) -> tensor<8x8xf32> {1957 %c8 = arith.constant 8 : index1958 %c0 = arith.constant 0 : index1959 %c1 = arith.constant 1 : index1960 %c16 = arith.constant 16 : index1961 %cst = arith.constant 0.000000e+00 : f321962 %0 = tensor.empty() : tensor<8x8xf32>1963 %1 = scf.forall (%i, %j) = (%c0, %c16) to (%c1, %c16)1964 step (%c8, %c8) shared_outs (%out_ = %0) -> (tensor<8x8xf32>) {1965 %fill = linalg.fill ins(%cst : f32) outs(%out_ : tensor<8x8xf32>)1966 -> tensor<8x8xf32>1967 scf.forall.in_parallel {1968 tensor.parallel_insert_slice %fill into %out_[%i, %j] [8, 8] [1, 1]1969 : tensor<8x8xf32> into tensor<8x8xf32>1970 }1971 }1972 return %1 : tensor<8x8xf32>1973}1974// CHECK-LABEL: @remove_empty_forall1975// CHECK-NOT: scf.forall1976// CHECK: %[[EMPTY:.*]] = tensor.empty1977// CHECK: return %[[EMPTY]]1978 1979// -----1980 1981func.func @fold_tensor_cast_into_forall(1982 %in: tensor<2xi32>, %out: tensor<2xi32>) -> tensor<2xi32> {1983 %cst = arith.constant dense<[100500]> : tensor<1xi32>1984 1985 1986 %out_cast = tensor.cast %out : tensor<2xi32> to tensor<?xi32>1987 %result = scf.forall (%i) = (0) to (2) step (1)1988 shared_outs (%out_ = %out_cast) -> tensor<?xi32> {1989 1990 scf.forall.in_parallel {1991 tensor.parallel_insert_slice %cst into %out_[%i] [1] [1]1992 : tensor<1xi32> into tensor<?xi32>1993 }1994 }1995 %result_cast = tensor.cast %result : tensor<?xi32> to tensor<2xi32>1996 func.return %result_cast : tensor<2xi32>1997}1998// CHECK-LABEL: @fold_tensor_cast_into_forall1999// CHECK-NOT: tensor.cast2000// CHECK: parallel_insert_slice2001// CHECK-SAME: : tensor<1xi32> into tensor<2xi32>2002// CHECK-NOT: tensor.cast2003 2004// -----2005 2006func.func @do_not_fold_tensor_cast_from_dynamic_to_static_type_into_forall(2007 %in: tensor<?xi32>, %out: tensor<?xi32>) -> tensor<?xi32> {2008 %cst = arith.constant dense<[100500]> : tensor<1xi32>2009 2010 2011 %out_cast = tensor.cast %out : tensor<?xi32> to tensor<2xi32>2012 %result = scf.forall (%i) = (0) to (2) step (1)2013 shared_outs (%out_ = %out_cast) -> tensor<2xi32> {2014 2015 scf.forall.in_parallel {2016 tensor.parallel_insert_slice %cst into %out_[%i] [1] [1]2017 : tensor<1xi32> into tensor<2xi32>2018 }2019 }2020 %result_cast = tensor.cast %result : tensor<2xi32> to tensor<?xi32>2021 func.return %result_cast : tensor<?xi32>2022}2023// CHECK-LABEL: @do_not_fold_tensor_cast_2024// CHECK: tensor.cast2025// CHECK: parallel_insert_slice2026// CHECK-SAME: : tensor<1xi32> into tensor<2xi32>2027// CHECK: tensor.cast2028 2029// -----2030 2031#map = affine_map<()[s0, s1] -> (s0 ceildiv s1)>2032#map1 = affine_map<(d0)[s0] -> (d0 * s0)>2033#map2 = affine_map<(d0)[s0, s1] -> (-(d0 * s1) + s0, s1)>2034module {2035 func.func @fold_iter_args_not_being_modified_within_scfforall(%arg0: index, %arg1: tensor<?xf32>, %arg2: tensor<?xf32>) -> (tensor<?xf32>, tensor<?xf32>) {2036 %c0 = arith.constant 0 : index2037 %cst = arith.constant 4.200000e+01 : f322038 %0 = linalg.fill ins(%cst : f32) outs(%arg1 : tensor<?xf32>) -> tensor<?xf32>2039 %dim = tensor.dim %arg1, %c0 : tensor<?xf32>2040 %1 = affine.apply #map()[%dim, %arg0]2041 %2:2 = scf.forall (%arg3) in (%1) shared_outs(%arg4 = %arg1, %arg5 = %arg2) -> (tensor<?xf32>, tensor<?xf32>) {2042 %3 = affine.apply #map1(%arg3)[%arg0]2043 %4 = affine.min #map2(%arg3)[%dim, %arg0]2044 %extracted_slice0 = tensor.extract_slice %arg4[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2045 %extracted_slice1 = tensor.extract_slice %arg5[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2046 %5 = linalg.exp ins(%extracted_slice0 : tensor<?xf32>) outs(%extracted_slice1 : tensor<?xf32>) -> tensor<?xf32>2047 scf.forall.in_parallel {2048 tensor.parallel_insert_slice %5 into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>2049 }2050 }2051 return %2#0, %2#1 : tensor<?xf32>, tensor<?xf32>2052 }2053}2054// CHECK-LABEL: @fold_iter_args_not_being_modified_within_scfforall2055// CHECK-SAME: (%{{.*}}: index, %[[ARG1:.*]]: tensor<?xf32>, %[[ARG2:.*]]: tensor<?xf32>) -> (tensor<?xf32>, tensor<?xf32>) {2056// CHECK: %[[RESULT:.*]] = scf.forall2057// CHECK-SAME: shared_outs(%[[ITER_ARG_5:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {2058// CHECK: %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]2059// CHECK: %[[OPERAND1:.*]] = tensor.extract_slice %[[ITER_ARG_5]]2060// CHECK: %[[ELEM:.*]] = linalg.exp ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>2061// CHECK: scf.forall.in_parallel {2062// CHECK-NEXT: tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_5]]2063// CHECK-NEXT: }2064// CHECK-NEXT: }2065// CHECK-NEXT: return %[[ARG1]], %[[RESULT]]2066 2067// -----2068 2069#map = affine_map<()[s0, s1] -> (s0 ceildiv s1)>2070#map1 = affine_map<(d0)[s0] -> (d0 * s0)>2071#map2 = affine_map<(d0)[s0, s1] -> (-(d0 * s1) + s0, s1)>2072module {2073 func.func @fold_iter_args_with_no_use_of_result_scfforall(%arg0: index, %arg1: tensor<?xf32>, %arg2: tensor<?xf32>, %arg3: tensor<?xf32>) -> tensor<?xf32> {2074 %cst = arith.constant 4.200000e+01 : f322075 %c0 = arith.constant 0 : index2076 %0 = linalg.fill ins(%cst : f32) outs(%arg1 : tensor<?xf32>) -> tensor<?xf32>2077 %dim = tensor.dim %arg1, %c0 : tensor<?xf32>2078 %1 = affine.apply #map()[%dim, %arg0]2079 %2:3 = scf.forall (%arg4) in (%1) shared_outs(%arg5 = %arg1, %arg6 = %arg2, %arg7 = %arg3) -> (tensor<?xf32>, tensor<?xf32>, tensor<?xf32>) {2080 %3 = affine.apply #map1(%arg4)[%arg0]2081 %4 = affine.min #map2(%arg4)[%dim, %arg0]2082 %extracted_slice = tensor.extract_slice %arg5[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2083 %extracted_slice_0 = tensor.extract_slice %arg6[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2084 %extracted_slice_1 = tensor.extract_slice %arg7[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2085 %extracted_slice_2 = tensor.extract_slice %0[%3] [%4] [1] : tensor<?xf32> to tensor<?xf32>2086 %5 = linalg.exp ins(%extracted_slice : tensor<?xf32>) outs(%extracted_slice_1 : tensor<?xf32>) -> tensor<?xf32>2087 scf.forall.in_parallel {2088 tensor.parallel_insert_slice %5 into %arg6[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>2089 tensor.parallel_insert_slice %extracted_slice into %arg5[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>2090 tensor.parallel_insert_slice %extracted_slice_0 into %arg7[%3] [%4] [1] : tensor<?xf32> into tensor<?xf32>2091 tensor.parallel_insert_slice %5 into %arg7[%4] [%3] [1] : tensor<?xf32> into tensor<?xf32>2092 }2093 }2094 return %2#1 : tensor<?xf32>2095 }2096}2097// CHECK-LABEL: @fold_iter_args_with_no_use_of_result_scfforall2098// CHECK-SAME: (%{{.*}}: index, %[[ARG1:.*]]: tensor<?xf32>, %[[ARG2:.*]]: tensor<?xf32>, %[[ARG3:.*]]: tensor<?xf32>) -> tensor<?xf32> {2099// CHECK: %[[RESULT:.*]] = scf.forall2100// CHECK-SAME: shared_outs(%[[ITER_ARG_6:.*]] = %[[ARG2]]) -> (tensor<?xf32>) {2101// CHECK: %[[OPERAND0:.*]] = tensor.extract_slice %[[ARG1]]2102// CHECK: %[[OPERAND1:.*]] = tensor.extract_slice %[[ARG3]]2103// CHECK: %[[ELEM:.*]] = linalg.exp ins(%[[OPERAND0]] : tensor<?xf32>) outs(%[[OPERAND1]] : tensor<?xf32>) -> tensor<?xf32>2104// CHECK: scf.forall.in_parallel {2105// CHECK-NEXT: tensor.parallel_insert_slice %[[ELEM]] into %[[ITER_ARG_6]]2106// CHECK-NEXT: }2107// CHECK-NEXT: }2108// CHECK-NEXT: return %[[RESULT]]2109 2110// -----2111 2112func.func @index_switch_fold() -> (f32, f32) {2113 %switch_cst = arith.constant 1: index2114 %0 = scf.index_switch %switch_cst -> f322115 case 1 {2116 %y = arith.constant 1.0 : f322117 scf.yield %y : f322118 }2119 default {2120 %y = arith.constant 42.0 : f322121 scf.yield %y : f322122 }2123 2124 %switch_cst_2 = arith.constant 2: index2125 %1 = scf.index_switch %switch_cst_2 -> f322126 case 0 {2127 %y = arith.constant 0.0 : f322128 scf.yield %y : f322129 }2130 default {2131 %y = arith.constant 42.0 : f322132 scf.yield %y : f322133 }2134 2135 return %0, %1 : f32, f322136}2137 2138// CHECK-LABEL: func.func @index_switch_fold()2139// CHECK-NEXT: %[[c1:.*]] = arith.constant 1.000000e+00 : f322140// CHECK-NEXT: %[[c42:.*]] = arith.constant 4.200000e+01 : f322141// CHECK-NEXT: return %[[c1]], %[[c42]] : f32, f322142 2143// -----2144 2145func.func @index_switch_fold_no_res() {2146 %c1 = arith.constant 1 : index2147 scf.index_switch %c12148 case 0 {2149 scf.yield2150 }2151 default {2152 "test.op"() : () -> ()2153 scf.yield2154 }2155 return2156}2157 2158// CHECK-LABEL: func.func @index_switch_fold_no_res()2159// CHECK-NEXT: "test.op"() : () -> ()2160 2161// -----2162 2163// Step 0 is invalid, the loop is eliminated.2164// CHECK-LABEL: func @scf_for_all_step_size_0()2165// CHECK-NOT: scf.forall2166func.func @scf_for_all_step_size_0() {2167 %x = arith.constant 0 : index2168 scf.forall (%i, %j) = (0, 4) to (1, 5) step (%x, 8) {2169 vector.print %x : index2170 scf.forall.in_parallel {}2171 }2172 return2173}2174