[llvm] 58fec78 - Revert "[UnifyLoopExits] Reduce number of guard blocks"
Brendon Cahoon via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 14 08:45:50 PDT 2022
Author: Brendon Cahoon
Date: 2022-07-14T10:33:52-05:00
New Revision: 58fec78231dc29bd503ba91d06471c94851d21a0
URL: https://github.com/llvm/llvm-project/commit/58fec78231dc29bd503ba91d06471c94851d21a0
DIFF: https://github.com/llvm/llvm-project/commit/58fec78231dc29bd503ba91d06471c94851d21a0.diff
LOG: Revert "[UnifyLoopExits] Reduce number of guard blocks"
This reverts commit e13248ab0e79b59d5e5ac73e2fe57d82ce485ce1.
Need to revert because the transformation cannot occur for basic
blocks that contain convergent instructions.
Added:
Modified:
llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
Removed:
llvm/test/Transforms/UnifyLoopExits/reduce_guards.ll
################################################################################
diff --git a/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp b/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
index 832353741500c..9bbfe06b9abbd 100644
--- a/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
+++ b/llvm/lib/Transforms/Utils/UnifyLoopExits.cpp
@@ -145,8 +145,6 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
// locate the exit blocks.
SetVector<BasicBlock *> ExitingBlocks;
SetVector<BasicBlock *> Exits;
- // Record the exit blocks that branch to the same block.
- MapVector<BasicBlock *, SetVector<BasicBlock *> > CommonSuccs;
// We need SetVectors, but the Loop API takes a vector, so we use a temporary.
SmallVector<BasicBlock *, 8> Temp;
@@ -160,11 +158,6 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
if (SL == L || L->contains(SL))
continue;
Exits.insert(S);
- // The typical case for reducing the number of guard blocks occurs when
- // the exit block has a single predecessor and successor.
- if (S->getSinglePredecessor())
- if (auto *Succ = S->getSingleSuccessor())
- CommonSuccs[Succ].insert(S);
}
}
@@ -179,39 +172,13 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
for (auto EB : ExitingBlocks) {
dbgs() << " " << EB->getName();
}
- dbgs() << "\n";
-
- dbgs() << "Exit blocks with a common successor:\n";
- for (auto CS : CommonSuccs) {
- dbgs() << " Succ " << CS.first->getName() << ", exits:";
- for (auto Exit : CS.second)
- dbgs() << " " << Exit->getName();
- dbgs() << "\n";
- });
+ dbgs() << "\n";);
if (Exits.size() <= 1) {
LLVM_DEBUG(dbgs() << "loop does not have multiple exits; nothing to do\n");
return false;
}
- // When multiple exit blocks branch to the same block, change the control
- // flow hub to after the exit blocks rather than before. This reduces the
- // number of guard blocks needed after the loop.
- for (auto CS : CommonSuccs) {
- auto CB = CS.first;
- auto Preds = CS.second;
- if (Exits.contains(CB))
- continue;
- if (Preds.size() < 2 || Preds.size() == Exits.size())
- continue;
- for (auto Exit : Preds) {
- Exits.remove(Exit);
- ExitingBlocks.remove(Exit->getSinglePredecessor());
- ExitingBlocks.insert(Exit);
- }
- Exits.insert(CB);
- }
-
SmallVector<BasicBlock *, 8> GuardBlocks;
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
auto LoopExitBlock = CreateControlFlowHub(&DTU, GuardBlocks, ExitingBlocks,
@@ -231,17 +198,6 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
if (auto ParentLoop = L->getParentLoop()) {
for (auto G : GuardBlocks) {
ParentLoop->addBasicBlockToLoop(G, LI);
- // Ensure the guard block predecessors are in a valid loop. After the
- // change to the control flow hub for common successors, a guard block
- // predecessor may not be in a loop or may be in an outer loop.
- for (auto Pred : predecessors(G)) {
- auto PredLoop = LI.getLoopFor(Pred);
- if (!ParentLoop->contains(PredLoop)) {
- if (PredLoop)
- LI.removeBlock(Pred);
- ParentLoop->addBasicBlockToLoop(Pred, LI);
- }
- }
}
ParentLoop->verifyLoop();
}
diff --git a/llvm/test/Transforms/UnifyLoopExits/reduce_guards.ll b/llvm/test/Transforms/UnifyLoopExits/reduce_guards.ll
deleted file mode 100644
index 54c0557ca7862..0000000000000
--- a/llvm/test/Transforms/UnifyLoopExits/reduce_guards.ll
+++ /dev/null
@@ -1,463 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -unify-loop-exits -enable-new-pm=0 -S | FileCheck %s
-; RUN: opt < %s -passes=unify-loop-exits -S | FileCheck %s
-
-; A loop has exit blocks, B and D, that branch to the same successor.
-; We reduce the number of guard blocks needed by creating the loop
-; exit guard block after B and D rather than before B and D.
-
-define void @unreachable_from_loop(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @unreachable_from_loop(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[E:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[B:%.*]], label [[C:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0:[0-9]+]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[D:%.*]], label [[E]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
-; CHECK: E:
-; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
-; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
-; CHECK: F:
-; CHECK-NEXT: unreachable
-; CHECK: G:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_G:%.*]] = phi i1 [ true, [[E]] ], [ false, [[B]] ], [ false, [[D]] ]
-; CHECK-NEXT: br i1 [[GUARD_G]], label [[G]], label [[F:%.*]]
-;
-entry:
- br i1 %PredEntry, label %A, label %G
-
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %E ]
- br i1 %PredA, label %B, label %C
-
-B:
- tail call fastcc void @check(i32 1) #0
- br label %F
-
-C:
- br i1 %PredB, label %D, label %E
-
-D:
- tail call fastcc void @check(i32 2) #0
- br label %F
-
-E:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %G
-
-F:
- unreachable
-
-G:
- ret void
-}
-
-; A test when the loop exit blocks appear in an inner loop.
-
-define void @unreachable_from_inner_loop(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @unreachable_from_inner_loop(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[I:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[OUTER1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER2:%.*]], [[G:%.*]] ]
-; CHECK-NEXT: br label [[B:%.*]]
-; CHECK: B:
-; CHECK-NEXT: [[INNER1:%.*]] = phi i32 [ 0, [[A]] ], [ [[INNER2:%.*]], [[F:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[D:%.*]], label [[C:%.*]]
-; CHECK: C:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD1:%.*]]
-; CHECK: D:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[E:%.*]], label [[F]]
-; CHECK: E:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD1]]
-; CHECK: F:
-; CHECK-NEXT: [[INNER2]] = add i32 [[INNER1]], 1
-; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[INNER2]], 20
-; CHECK-NEXT: br i1 [[CMP1]], label [[B]], label [[LOOP_EXIT_GUARD1]]
-; CHECK: G:
-; CHECK-NEXT: [[OUTER2]] = add i32 [[OUTER1]], 1
-; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[OUTER2]], 10
-; CHECK-NEXT: br i1 [[CMP2]], label [[A]], label [[LOOP_EXIT_GUARD:%.*]]
-; CHECK: H:
-; CHECK-NEXT: unreachable
-; CHECK: I:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_I:%.*]] = phi i1 [ true, [[G]] ], [ [[GUARD_I_MOVED:%.*]], [[LOOP_EXIT_GUARD1]] ]
-; CHECK-NEXT: br i1 [[GUARD_I]], label [[I]], label [[H:%.*]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: [[GUARD_G:%.*]] = phi i1 [ true, [[F]] ], [ false, [[C]] ], [ false, [[E]] ]
-; CHECK-NEXT: [[GUARD_I_MOVED]] = phi i1 [ undef, [[F]] ], [ false, [[C]] ], [ false, [[E]] ]
-; CHECK-NEXT: br i1 [[GUARD_G]], label [[G]], label [[LOOP_EXIT_GUARD]]
-;
-entry:
- br i1 %PredEntry, label %A, label %I
-
-A:
- %outer1 = phi i32 [ 0, %entry ], [ %outer2, %G ]
- br label %B
-
-B:
- %inner1 = phi i32 [ 0, %A ], [ %inner2, %F ]
- br i1 %PredA, label %D, label %C
-
-C:
- tail call fastcc void @check(i32 1) #0
- br label %H
-
-D:
- br i1 %PredB, label %E, label %F
-
-E:
- tail call fastcc void @check(i32 2) #0
- br label %H
-
-F:
- %inner2 = add i32 %inner1, 1
- %cmp1 = icmp ult i32 %inner2, 20
- br i1 %cmp1, label %B, label %G
-
-G:
- %outer2 = add i32 %outer1, 1
- %cmp2 = icmp ult i32 %outer2, 10
- br i1 %cmp2, label %A, label %I
-
-H:
- unreachable
-
-I:
- ret void
-}
-
-; Test with 3 nested loops to show the case when we need to change the loop for
-; the predecessors of the loop guard. Since UnifyLoopExits works from the outer
-; loop to the inner loop, the predecessors are added to the outermost loop.
-; When a guard block is added to the exit of the inner loop, the predecessor
-; block loops need to change to the middle loop.
-
-define void @three_loops(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @three_loops(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[L1:%.*]], label [[H:%.*]]
-; CHECK: L1:
-; CHECK-NEXT: [[I1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I2:%.*]], [[F:%.*]] ]
-; CHECK-NEXT: br label [[L2:%.*]]
-; CHECK: L2:
-; CHECK-NEXT: [[J1:%.*]] = phi i32 [ 0, [[L1]] ], [ [[J2:%.*]], [[E:%.*]] ]
-; CHECK-NEXT: br label [[L3:%.*]]
-; CHECK: L3:
-; CHECK-NEXT: [[K1:%.*]] = phi i32 [ 0, [[L2]] ], [ [[K2:%.*]], [[D:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[A:%.*]], label [[B:%.*]]
-; CHECK: A:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD2:%.*]]
-; CHECK: B:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[C:%.*]], label [[D]]
-; CHECK: C:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD2]]
-; CHECK: D:
-; CHECK-NEXT: [[K2]] = add i32 [[K1]], 1
-; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[K2]], 20
-; CHECK-NEXT: br i1 [[CMP1]], label [[L3]], label [[LOOP_EXIT_GUARD2]]
-; CHECK: E:
-; CHECK-NEXT: [[J2]] = add i32 [[J1]], 1
-; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[J2]], 10
-; CHECK-NEXT: br i1 [[CMP2]], label [[L2]], label [[LOOP_EXIT_GUARD1:%.*]]
-; CHECK: F:
-; CHECK-NEXT: [[I2]] = add i32 [[I1]], 1
-; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[I2]], 5
-; CHECK-NEXT: br i1 [[CMP3]], label [[L1]], label [[LOOP_EXIT_GUARD:%.*]]
-; CHECK: G:
-; CHECK-NEXT: unreachable
-; CHECK: H:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_H:%.*]] = phi i1 [ true, [[F]] ], [ [[GUARD_H_MOVED:%.*]], [[LOOP_EXIT_GUARD1]] ]
-; CHECK-NEXT: br i1 [[GUARD_H]], label [[H]], label [[G:%.*]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: [[GUARD_F:%.*]] = phi i1 [ true, [[E]] ], [ [[GUARD_F_MOVED:%.*]], [[LOOP_EXIT_GUARD2]] ]
-; CHECK-NEXT: [[GUARD_H_MOVED]] = phi i1 [ undef, [[E]] ], [ [[GUARD_H_MOVED_MOVED:%.*]], [[LOOP_EXIT_GUARD2]] ]
-; CHECK-NEXT: br i1 [[GUARD_F]], label [[F]], label [[LOOP_EXIT_GUARD]]
-; CHECK: loop.exit.guard2:
-; CHECK-NEXT: [[GUARD_E:%.*]] = phi i1 [ true, [[D]] ], [ false, [[A]] ], [ false, [[C]] ]
-; CHECK-NEXT: [[GUARD_F_MOVED]] = phi i1 [ undef, [[D]] ], [ false, [[A]] ], [ false, [[C]] ]
-; CHECK-NEXT: [[GUARD_H_MOVED_MOVED]] = phi i1 [ undef, [[D]] ], [ false, [[A]] ], [ false, [[C]] ]
-; CHECK-NEXT: br i1 [[GUARD_E]], label [[E]], label [[LOOP_EXIT_GUARD1]]
-;
-entry:
- br i1 %PredEntry, label %L1, label %H
-
-L1:
- %i1 = phi i32 [ 0, %entry ], [ %i2, %F ]
- br label %L2
-
-L2:
- %j1 = phi i32 [ 0, %L1 ], [ %j2, %E ]
- br label %L3
-
-L3:
- %k1 = phi i32 [ 0, %L2 ], [ %k2, %D ]
- br i1 %PredA, label %A, label %B
-
-A:
- tail call fastcc void @check(i32 1) #0
- br label %G
-
-B:
- br i1 %PredB, label %C, label %D
-
-C:
- tail call fastcc void @check(i32 2) #0
- br label %G
-
-D:
- %k2 = add i32 %k1, 1
- %cmp1 = icmp ult i32 %k2, 20
- br i1 %cmp1, label %L3, label %E
-
-E:
- %j2 = add i32 %j1, 1
- %cmp2 = icmp ult i32 %j2, 10
- br i1 %cmp2, label %L2, label %F
-
-F:
- %i2 = add i32 %i1, 1
- %cmp3 = icmp ult i32 %i2, 5
- br i1 %cmp3, label %L1, label %H
-
-G:
- unreachable
-
-H:
- ret void
-}
-
-
-; The common successor does not have to be an unreachable block.
-
-define void @common_exit(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @common_exit(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[E:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[B:%.*]], label [[C:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check1(i32 1) #[[ATTR1:[0-9]+]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[D:%.*]], label [[E]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check1(i32 2) #[[ATTR1]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
-; CHECK: E:
-; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
-; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
-; CHECK: F:
-; CHECK-NEXT: br label [[G]]
-; CHECK: G:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_G:%.*]] = phi i1 [ true, [[E]] ], [ false, [[B]] ], [ false, [[D]] ]
-; CHECK-NEXT: br i1 [[GUARD_G]], label [[G]], label [[F:%.*]]
-;
-entry:
- br i1 %PredEntry, label %A, label %G
-
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %E ]
- br i1 %PredA, label %B, label %C
-
-B:
- tail call fastcc void @check1(i32 1) #1
- br label %F
-
-C:
- br i1 %PredB, label %D, label %E
-
-D:
- tail call fastcc void @check1(i32 2) #1
- br label %F
-
-E:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %G
-
-F:
- br label %G
-
-G:
- ret void
-}
-
-; A test with multiple common exits.
-
-define void @multiple_common_successors(i1 %PredEntry, i1 %PredA, i1 %PredB, i1 %PredC, i1 %PredD) {
-; CHECK-LABEL: @multiple_common_successors(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[L:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[I:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[B:%.*]], label [[C:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD:%.*]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[D:%.*]], label [[E:%.*]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
-; CHECK: E:
-; CHECK-NEXT: br i1 [[PREDC:%.*]], label [[F:%.*]], label [[G:%.*]]
-; CHECK: F:
-; CHECK-NEXT: tail call fastcc void @check(i32 3) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
-; CHECK: G:
-; CHECK-NEXT: br i1 [[PREDD:%.*]], label [[H:%.*]], label [[I]]
-; CHECK: H:
-; CHECK-NEXT: tail call fastcc void @check(i32 4) #[[ATTR0]]
-; CHECK-NEXT: br label [[LOOP_EXIT_GUARD]]
-; CHECK: I:
-; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
-; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
-; CHECK: J:
-; CHECK-NEXT: br label [[L]]
-; CHECK: K:
-; CHECK-NEXT: br label [[L]]
-; CHECK: L:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_L:%.*]] = phi i1 [ true, [[I]] ], [ false, [[B]] ], [ false, [[D]] ], [ false, [[F]] ], [ false, [[H]] ]
-; CHECK-NEXT: [[GUARD_J:%.*]] = phi i1 [ false, [[I]] ], [ true, [[B]] ], [ true, [[D]] ], [ false, [[F]] ], [ false, [[H]] ]
-; CHECK-NEXT: br i1 [[GUARD_L]], label [[L]], label [[LOOP_EXIT_GUARD1:%.*]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: br i1 [[GUARD_J]], label [[J:%.*]], label [[K:%.*]]
-;
-entry:
- br i1 %PredEntry, label %A, label %L
-
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %I ]
- br i1 %PredA, label %B, label %C
-
-B:
- tail call fastcc void @check(i32 1) #0
- br label %J
-
-C:
- br i1 %PredB, label %D, label %E
-
-D:
- tail call fastcc void @check(i32 2) #0
- br label %J
-
-E:
- br i1 %PredC, label %F, label %G
-
-F:
- tail call fastcc void @check(i32 3) #0
- br label %K
-
-G:
- br i1 %PredD, label %H, label %I
-
-H:
- tail call fastcc void @check(i32 4) #0
- br label %K
-
-I:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %L
-
-J:
- br label %L
-
-K:
- br label %L
-
-L:
- ret void
-}
-
-; Test when the loop exit block is tha same as a common successor
-; block. The number of guard blocks is unchanged.
-
-define void @common_successor_exit(i1 %PredEntry, i1 %PredA, i1 %PredB) {
-; CHECK-LABEL: @common_successor_exit(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br i1 [[PREDENTRY:%.*]], label [[A:%.*]], label [[G:%.*]]
-; CHECK: A:
-; CHECK-NEXT: [[INC1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC2:%.*]], [[E:%.*]] ]
-; CHECK-NEXT: br i1 [[PREDA:%.*]], label [[LOOP_EXIT_GUARD:%.*]], label [[C:%.*]]
-; CHECK: B:
-; CHECK-NEXT: tail call fastcc void @check(i32 1) #[[ATTR0]]
-; CHECK-NEXT: br label [[G]]
-; CHECK: C:
-; CHECK-NEXT: br i1 [[PREDB:%.*]], label [[LOOP_EXIT_GUARD]], label [[E]]
-; CHECK: D:
-; CHECK-NEXT: tail call fastcc void @check(i32 2) #[[ATTR0]]
-; CHECK-NEXT: br label [[G]]
-; CHECK: E:
-; CHECK-NEXT: [[INC2]] = add i32 [[INC1]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[INC2]], 10
-; CHECK-NEXT: br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
-; CHECK: G:
-; CHECK-NEXT: ret void
-; CHECK: loop.exit.guard:
-; CHECK-NEXT: [[GUARD_B:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ], [ false, [[E]] ]
-; CHECK-NEXT: [[GUARD_D:%.*]] = phi i1 [ false, [[A]] ], [ true, [[C]] ], [ false, [[E]] ]
-; CHECK-NEXT: br i1 [[GUARD_B]], label [[B:%.*]], label [[LOOP_EXIT_GUARD1:%.*]]
-; CHECK: loop.exit.guard1:
-; CHECK-NEXT: br i1 [[GUARD_D]], label [[D:%.*]], label [[G]]
-;
-entry:
- br i1 %PredEntry, label %A, label %G
-
-A:
- %inc1 = phi i32 [ 0, %entry ], [ %inc2, %E ]
- br i1 %PredA, label %B, label %C
-
-B:
- tail call fastcc void @check(i32 1) #0
- br label %G
-
-C:
- br i1 %PredB, label %D, label %E
-
-D:
- tail call fastcc void @check(i32 2) #0
- br label %G
-
-E:
- %inc2 = add i32 %inc1, 1
- %cmp = icmp ult i32 %inc2, 10
- br i1 %cmp, label %A, label %G
-
-G:
- ret void
-}
-
-declare void @check(i32 noundef %i) #0
-declare void @check1(i32 noundef %i) #1
-
-attributes #0 = { noreturn nounwind }
-attributes #1 = { nounwind }
-
More information about the llvm-commits
mailing list