[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