[llvm] f7fc892 - [LoopDeletion] Check for irreducible cycles when deleting loops.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 15 04:56:45 PDT 2021


Author: Florian Hahn
Date: 2021-06-15T12:56:12+01:00
New Revision: f7fc8927c0885ff155ea16f99bcf6db6fb10357a

URL: https://github.com/llvm/llvm-project/commit/f7fc8927c0885ff155ea16f99bcf6db6fb10357a
DIFF: https://github.com/llvm/llvm-project/commit/f7fc8927c0885ff155ea16f99bcf6db6fb10357a.diff

LOG: [LoopDeletion] Check for irreducible cycles when deleting loops.

Loops with irreducible cycles may loop infinitely. Those cannot be
removed, unless the loop/function is marked as mustprogress.

Also discussed in D103382.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D104238

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/LoopDeletion.cpp
    llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 62b145b0c8264..9e7eff10d56f7 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -16,11 +16,14 @@
 #include "llvm/Transforms/Scalar/LoopDeletion.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/CFG.h"
 #include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/LoopIterator.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/Analysis/MemorySSA.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/IR/Dominators.h"
+
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Transforms/Scalar.h"
@@ -54,7 +57,7 @@ static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B) {
 static bool isLoopDead(Loop *L, ScalarEvolution &SE,
                        SmallVectorImpl<BasicBlock *> &ExitingBlocks,
                        BasicBlock *ExitBlock, bool &Changed,
-                       BasicBlock *Preheader) {
+                       BasicBlock *Preheader, LoopInfo &LI) {
   // Make sure that all PHI entries coming from the loop are loop invariant.
   // Because the code is in LCSSA form, any values used outside of the loop
   // must pass through a PHI in the exit block, meaning that this check is
@@ -108,6 +111,12 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE,
   if (L->getHeader()->getParent()->mustProgress())
     return true;
 
+  LoopBlocksRPO RPOT(L);
+  RPOT.perform(&LI);
+  // If the loop contains an irreducible cycle, it may loop infinitely.
+  if (containsIrreducibleCFG<const BasicBlock *>(RPOT, LI))
+    return false;
+
   SmallVector<Loop *, 8> WorkList;
   WorkList.push_back(L);
   while (!WorkList.empty()) {
@@ -248,7 +257,7 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
   }
   // Finally, we have to check that the loop really is dead.
   bool Changed = false;
-  if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader)) {
+  if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader, LI)) {
     LLVM_DEBUG(dbgs() << "Loop is not invariant, cannot delete.\n");
     return Changed ? LoopDeletionResult::Modified
                    : LoopDeletionResult::Unmodified;

diff  --git a/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll b/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll
index d82d2c5cf04b2..5c55c8a1362c9 100644
--- a/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll
+++ b/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll
@@ -3,12 +3,28 @@
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
 
+; loop1 contains an irreducible cycle, which may loop infinitely. Do not remove
+; the loop.
 define void @irreducible_subloop_no_mustprogress(i1 %c1, i1 %c2, i1 %c3) {
 ; CHECK-LABEL: @irreducible_subloop_no_mustprogress(
-; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP1:%.*]]
+; CHECK:       loop1:
+; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LOOP1_BB1:%.*]], label [[IRR_BB1:%.*]]
+; CHECK:       loop1.bb1:
+; CHECK-NEXT:    br label [[IRR_BB2:%.*]]
+; CHECK:       irr.bb1:
+; CHECK-NEXT:    br i1 [[C2:%.*]], label [[LOOP1_LATCH:%.*]], label [[IRR_BB2]]
+; CHECK:       irr.bb2:
+; CHECK-NEXT:    br i1 [[C3:%.*]], label [[LOOP1_LATCH]], label [[IRR_BB1]]
+; CHECK:       loop1.latch:
+; CHECK-NEXT:    br i1 false, label [[LOOP1_LATCH_LOOP1_CRIT_EDGE:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop1.latch.loop1_crit_edge:
+; CHECK-NEXT:    unreachable
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ;
+entry:
   br label %loop1
 
 loop1:


        


More information about the llvm-commits mailing list