Skip to content

Commit 6357614

Browse files
committed
[MLIR][CF] Bail out of collapseBranch when any cycle is detected (#159743)
It is safest to bail out as soon as we detect a cycle in collapseBranch. We need not continue with optimizations on infinite loops.
1 parent d6f7526 commit 6357614

File tree

2 files changed

+78
-72
lines changed

2 files changed

+78
-72
lines changed

mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,11 @@ static LogicalResult collapseBranch(Block *&successor,
124124
return failure();
125125
// Don't try to collapse branches which participate in a cycle.
126126
BranchOp nextBranch = dyn_cast<BranchOp>(successorDest->getTerminator());
127-
llvm::DenseSet<Block *> visited{successorDest};
127+
llvm::DenseSet<Block *> visited{successor, successorDest};
128128
while (nextBranch) {
129129
Block *nextBranchDest = nextBranch.getDest();
130-
if (nextBranchDest == successor)
130+
if (visited.contains(nextBranchDest))
131131
return failure();
132-
else if (visited.contains(nextBranchDest))
133-
break;
134132
visited.insert(nextBranchDest);
135133
nextBranch = dyn_cast<BranchOp>(nextBranchDest->getTerminator());
136134
}

mlir/test/Dialect/ControlFlow/canonicalize.mlir

Lines changed: 76 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -501,24 +501,24 @@ func.func @branchCondProp(%arg0: i1) {
501501
// CHECK: cf.br ^bb1
502502
func.func @cycle_2_blocks() {
503503
cf.br ^bb1
504-
^bb1:
505-
cf.br ^bb2
506-
^bb2:
507-
cf.br ^bb1
504+
^bb1:
505+
cf.br ^bb2
506+
^bb2:
507+
cf.br ^bb1
508508
}
509509

510510
// CHECK-LABEL: @no_cycle_2_blocks
511511
// CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
512512
// CHECK: return %[[VAL_0]] : i32
513513
func.func @no_cycle_2_blocks() -> i32 {
514514
cf.br ^bb1
515-
^bb1:
516-
cf.br ^bb2
517-
^bb2:
518-
cf.br ^bb3
519-
^bb3:
520-
%ret = arith.constant 1 : i32
521-
return %ret : i32
515+
^bb1:
516+
cf.br ^bb2
517+
^bb2:
518+
cf.br ^bb3
519+
^bb3:
520+
%ret = arith.constant 1 : i32
521+
return %ret : i32
522522
}
523523

524524
// CHECK-LABEL: @cycle_4_blocks
@@ -527,32 +527,32 @@ func.func @no_cycle_2_blocks() -> i32 {
527527
// CHECK: cf.br ^bb1
528528
func.func @cycle_4_blocks() {
529529
cf.br ^bb1
530-
^bb1:
531-
cf.br ^bb2
532-
^bb2:
533-
cf.br ^bb3
534-
^bb3:
535-
cf.br ^bb4
536-
^bb4:
537-
cf.br ^bb1
530+
^bb1:
531+
cf.br ^bb2
532+
^bb2:
533+
cf.br ^bb3
534+
^bb3:
535+
cf.br ^bb4
536+
^bb4:
537+
cf.br ^bb1
538538
}
539539

540540
// CHECK-LABEL: @no_cycle_4_blocks
541541
// CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
542542
// CHECK: return %[[VAL_0]] : i32
543543
func.func @no_cycle_4_blocks() -> i32 {
544544
cf.br ^bb1
545-
^bb1:
546-
cf.br ^bb2
547-
^bb2:
548-
cf.br ^bb3
549-
^bb3:
550-
cf.br ^bb4
551-
^bb4:
552-
cf.br ^bb5
553-
^bb5:
554-
%ret = arith.constant 1 : i32
555-
return %ret : i32
545+
^bb1:
546+
cf.br ^bb2
547+
^bb2:
548+
cf.br ^bb3
549+
^bb3:
550+
cf.br ^bb4
551+
^bb4:
552+
cf.br ^bb5
553+
^bb5:
554+
%ret = arith.constant 1 : i32
555+
return %ret : i32
556556
}
557557

558558
// CHECK-LABEL: @delayed_3_cycle
@@ -561,16 +561,16 @@ func.func @no_cycle_4_blocks() -> i32 {
561561
// CHECK: cf.br ^bb1
562562
func.func @delayed_3_cycle() {
563563
cf.br ^bb1
564-
^bb1:
565-
cf.br ^bb2
566-
^bb2:
567-
cf.br ^bb3
568-
^bb3:
569-
cf.br ^bb4
570-
^bb4:
571-
cf.br ^bb5
572-
^bb5:
573-
cf.br ^bb3
564+
^bb1:
565+
cf.br ^bb2
566+
^bb2:
567+
cf.br ^bb3
568+
^bb3:
569+
cf.br ^bb4
570+
^bb4:
571+
cf.br ^bb5
572+
^bb5:
573+
cf.br ^bb3
574574
}
575575

576576
// CHECK-LABEL: @cycle_1_block
@@ -579,50 +579,58 @@ func.func @delayed_3_cycle() {
579579
// CHECK: cf.br ^bb1
580580
func.func @cycle_1_block() {
581581
cf.br ^bb1
582-
^bb1:
583-
cf.br ^bb2
584-
^bb2:
585-
cf.br ^bb2
582+
^bb1:
583+
cf.br ^bb2
584+
^bb2:
585+
cf.br ^bb2
586586
}
587587

588588
// CHECK-LABEL: @unsimplified_cycle_1
589589
// CHECK-SAME: %[[ARG0:.*]]: i1) {
590-
// CHECK: cf.br ^bb1
590+
// CHECK: cf.cond_br %[[ARG0]], ^bb1, ^bb2
591591
// CHECK: ^bb1:
592-
// CHECK: cf.br ^bb1
592+
// CHECK: cf.br ^bb2
593+
// CHECK: ^bb2:
594+
// CHECK: cf.br ^bb3
595+
// CHECK: ^bb3:
596+
// CHECK: cf.br ^bb3
593597
func.func @unsimplified_cycle_1(%c : i1) {
594598
cf.cond_br %c, ^bb1, ^bb2
595-
^bb1:
596-
cf.br ^bb2
597-
^bb2:
598-
cf.br ^bb3
599-
^bb3:
600-
cf.br ^bb4
601-
^bb4:
602-
cf.br ^bb3
599+
^bb1:
600+
cf.br ^bb2
601+
^bb2:
602+
cf.br ^bb3
603+
^bb3:
604+
cf.br ^bb4
605+
^bb4:
606+
cf.br ^bb3
603607
}
604608

605609
// Make sure we terminate when other cf passes can't help us.
606610

607611
// CHECK-LABEL: @unsimplified_cycle_2
608612
// CHECK-SAME: %[[ARG0:.*]]: i1) {
609-
// CHECK: cf.br ^bb1
613+
// CHECK: cf.cond_br %[[ARG0]], ^bb1, ^bb3
610614
// CHECK: ^bb1:
611-
// CHECK: cf.br ^bb1 {E}
615+
// CHECK: cf.br ^bb2 {A}
616+
// CHECK: ^bb2:
617+
// CHECK: cf.br ^bb2 {E}
618+
// CHECK: ^bb3:
619+
// CHECK: cf.br ^bb1
612620
func.func @unsimplified_cycle_2(%c : i1) {
613621
cf.cond_br %c, ^bb6, ^bb7
614-
^bb6:
622+
^bb6:
615623
cf.br ^bb5 {F}
616-
^bb5:
624+
^bb5:
617625
cf.br ^bb1 {A}
618-
^bb1:
619-
cf.br ^bb2 {B}
620-
^bb2:
621-
cf.br ^bb3 {C}
622-
^bb3:
623-
cf.br ^bb4 {D}
624-
^bb4:
625-
cf.br ^bb1 {E}
626-
^bb7:
627-
cf.br ^bb6
626+
^bb1:
627+
cf.br ^bb2 {B}
628+
^bb2:
629+
cf.br ^bb3 {C}
630+
^bb3:
631+
cf.br ^bb4 {D}
632+
^bb4:
633+
cf.br ^bb1 {E}
634+
^bb7:
635+
cf.br ^bb6
628636
}

0 commit comments

Comments
 (0)