[llvm] r341926 - [LoopInfo] Fix Loop::getLoopID() for loops with multiple latches

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 11 04:44:17 PDT 2018


Author: jdoerfert
Date: Tue Sep 11 04:44:17 2018
New Revision: 341926

URL: http://llvm.org/viewvc/llvm-project?rev=341926&view=rev
Log:
[LoopInfo] Fix Loop::getLoopID() for loops with multiple latches

The previous implementation traversed all loop blocks and bailed if one
was not a latch block. Since we are only interested in latch blocks, we
should only traverse those.

Modified:
    llvm/trunk/lib/Analysis/LoopInfo.cpp
    llvm/trunk/unittests/Analysis/LoopInfoTest.cpp

Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=341926&r1=341925&r2=341926&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LoopInfo.cpp Tue Sep 11 04:44:17 2018
@@ -218,20 +218,13 @@ MDNode *Loop::getLoopID() const {
   } else {
     assert(!getLoopLatch() &&
            "The loop should have no single latch at this point");
-    // Go through each predecessor of the loop header and check the
-    // terminator for the metadata.
-    BasicBlock *H = getHeader();
-    for (BasicBlock *BB : this->blocks()) {
+    // Go through the latch blocks and check the terminator for the metadata.
+    SmallVector<BasicBlock *, 4> LatchesBlocks;
+    getLoopLatches(LatchesBlocks);
+    for (BasicBlock *BB : LatchesBlocks) {
       TerminatorInst *TI = BB->getTerminator();
-      MDNode *MD = nullptr;
+      MDNode *MD = TI->getMetadata(LLVMContext::MD_loop);
 
-      // Check if this terminator branches to the loop header.
-      for (BasicBlock *Successor : successors(TI)) {
-        if (Successor == H) {
-          MD = TI->getMetadata(LLVMContext::MD_loop);
-          break;
-        }
-      }
       if (!MD)
         return nullptr;
 

Modified: llvm/trunk/unittests/Analysis/LoopInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/LoopInfoTest.cpp?rev=341926&r1=341925&r2=341926&view=diff
==============================================================================
--- llvm/trunk/unittests/Analysis/LoopInfoTest.cpp (original)
+++ llvm/trunk/unittests/Analysis/LoopInfoTest.cpp Tue Sep 11 04:44:17 2018
@@ -82,6 +82,62 @@ TEST(LoopInfoTest, LoopWithSingleLatch)
   });
 }
 
+// Test loop id handling for a loop with multiple latches.
+TEST(LoopInfoTest, LoopWithMultipleLatches) {
+  const char *ModuleStr =
+      "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
+      "define void @foo(i32 %n) {\n"
+      "entry:\n"
+      "  br i1 undef, label %for.cond, label %for.end\n"
+      "for.cond:\n"
+      "  %i.0 = phi i32 [ 0, %entry ], [ %inc, %latch.1 ], [ %inc, %latch.2 ]\n"
+      "  %inc = add nsw i32 %i.0, 1\n"
+      "  %cmp = icmp slt i32 %i.0, %n\n"
+      "  br i1 %cmp, label %latch.1, label %for.end\n"
+      "latch.1:\n"
+      "  br i1 undef, label %for.cond, label %latch.2, !llvm.loop !0\n"
+      "latch.2:\n"
+      "  br label %for.cond, !llvm.loop !0\n"
+      "for.end:\n"
+      "  ret void\n"
+      "}\n"
+      "!0 = distinct !{!0, !1}\n"
+      "!1 = !{!\"llvm.loop.distribute.enable\", i1 true}\n";
+
+  // Parse the module.
+  LLVMContext Context;
+  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
+
+  runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) {
+    Function::iterator FI = F.begin();
+    F.dump();
+    // First basic block is entry - skip it.
+    BasicBlock *Header = &*(++FI);
+    assert(Header->getName() == "for.cond");
+    Loop *L = LI.getLoopFor(Header);
+    EXPECT_NE(L, nullptr);
+
+    // This loop is not in simplified form.
+    EXPECT_FALSE(L->isLoopSimplifyForm());
+
+    // Try to get and set the metadata id for the loop.
+    MDNode *OldLoopID = L->getLoopID();
+    EXPECT_NE(OldLoopID, nullptr);
+
+    MDNode *NewLoopID = MDNode::get(Context, {nullptr});
+    // Set operand 0 to refer to the loop id itself.
+    NewLoopID->replaceOperandWith(0, NewLoopID);
+
+    L->setLoopID(NewLoopID);
+    EXPECT_EQ(L->getLoopID(), NewLoopID);
+    EXPECT_NE(L->getLoopID(), OldLoopID);
+
+    L->setLoopID(OldLoopID);
+    EXPECT_EQ(L->getLoopID(), OldLoopID);
+    EXPECT_NE(L->getLoopID(), NewLoopID);
+  });
+}
+
 TEST(LoopInfoTest, PreorderTraversals) {
   const char *ModuleStr = "define void @f() {\n"
                           "entry:\n"




More information about the llvm-commits mailing list