[PATCH] D53876: Preserve loop metadata when splitting exit blocks

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 7 03:32:15 PDT 2019


This revision was automatically updated to reflect the committed changes.
Closed by commit rG3c87c2a3c50b: Preserve loop metadata when splitting exit blocks (authored by craig.topper).
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.

Changed prior to commit:
  https://reviews.llvm.org/D53876?vs=182694&id=223475#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53876/new/

https://reviews.llvm.org/D53876

Files:
  llvm/lib/Transforms/Utils/LoopUtils.cpp
  llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata2.ll


Index: llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata2.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/LoopSimplify/preserve-llvm-loop-metadata2.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -loop-simplify < %s | FileCheck %s
+
+; Two-loop nest with llvm.loop metadata on each loop.
+; inner.header exits to outer.header. inner.header is a latch for the outer
+; loop, and contains the outer loop's metadata.
+; After loop-simplify, a new block "outer.header.loopexit" is created between
+; inner.header and outer.header. The metadata from inner.header must be moved
+; to the new block, as the new block becomes the outer loop latch.
+; The metadata on the inner loop's latch should be untouched.
+
+; CHECK: outer.header.loopexit:
+; CHECK-NEXT: llvm.loop [[UJAMTAG:.*]]
+; CHECK-NOT: br i1 {{.*}}, label {{.*}}, label %outer.header.loopexit, !llvm.loop
+; CHECK: br label %inner.header, !llvm.loop [[UNROLLTAG:.*]]
+
+; CHECK: distinct !{[[UJAMTAG]], [[UJAM:.*]]}
+; CHECK: [[UJAM]] = !{!"llvm.loop.unroll_and_jam.count", i32 17}
+; CHECK: distinct !{[[UNROLLTAG]], [[UNROLL:.*]]}
+; CHECK: [[UNROLL]] = !{!"llvm.loop.unroll.count", i32 1}
+
+
+define dso_local void @loopnest() local_unnamed_addr #0 {
+entry:
+  br label %outer.header
+
+outer.header:                                         ; preds = %inner.header, %entry
+  %ii.0 = phi i64 [ 2, %entry ], [ %add, %inner.header ]
+  %cmp = icmp ult i64 %ii.0, 64
+  br i1 %cmp, label %inner.header, label %outer.header.cleanup
+
+outer.header.cleanup:                                 ; preds = %outer.header
+  ret void
+
+inner.header:                                        ; preds = %outer.header, %inner.body
+  %j.0 = phi i64 [ %add10, %inner.body ], [ %ii.0, %outer.header ]
+  %add = add nuw nsw i64 %ii.0, 16
+  %cmp2 = icmp ult i64 %j.0, %add
+  br i1 %cmp2, label %inner.body, label %outer.header, !llvm.loop !2
+
+inner.body:                                        ; preds = %inner.header
+  %add10 = add nuw nsw i64 %j.0, 1
+  br label %inner.header, !llvm.loop !4
+}
+
+!2 = distinct !{!2, !3}
+!3 = !{!"llvm.loop.unroll_and_jam.count", i32 17}
+!4 = distinct !{!4, !5}
+!5 = !{!"llvm.loop.unroll.count", i32 1}
Index: llvm/lib/Transforms/Utils/LoopUtils.cpp
===================================================================
--- llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -74,9 +74,41 @@
     if (IsDedicatedExit)
       return false;
 
+    // With nested loops, the inner loop might exit to the header of an
+    // enclosing loop, and the in-loop-predecessor is a latch for that
+    // enclosing loop. If we insert a block between the latch and the header,
+    // that block becomes the new latch. Any loop metadata from the old latch
+    // needs to be moved to the new one.
+    MDNode *OuterLoopMD = nullptr;
+
+    // If the exit block is a header of a different loop, get that loop's
+    // metadata before we split the block.
+    if (LI->isLoopHeader(BB))
+      OuterLoopMD = LI->getLoopFor(BB)->getLoopID();
+
     auto *NewExitBB = SplitBlockPredecessors(
         BB, InLoopPredecessors, ".loopexit", DT, LI, nullptr, PreserveLCSSA);
 
+    // If OuterLoopMD is non-null, we know that the exit block BB is a
+    // loop header for a different loop, with metadata on its back edges.
+    // If NewExitBB is a member of that loop, then NewExitBB is a latch,
+    // and the loop's metadata needs to be copied to NewExitBB.
+    if (NewExitBB && OuterLoopMD &&
+        LI->getLoopFor(NewExitBB) == LI->getLoopFor(BB)) {
+      // The preds of NewExitBB are all former latches of the outer loop.
+      // Remove their metadata.
+      for (auto *PredLoopBB : InLoopPredecessors) {
+        Instruction *TI = PredLoopBB->getTerminator();
+        // All the latches should have the same metadata (ensured by
+        // getLoopID()).
+        assert(TI->getMetadata(LLVMContext::MD_loop) == OuterLoopMD &&
+               "exit edge to other loop doesn't contain expected metadata");
+        TI->setMetadata(LLVMContext::MD_loop, nullptr);
+      }
+      NewExitBB->getTerminator()->setMetadata(LLVMContext::MD_loop,
+                                              OuterLoopMD);
+    }
+
     if (!NewExitBB)
       LLVM_DEBUG(
           dbgs() << "WARNING: Can't create a dedicated exit block for loop: "


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D53876.223475.patch
Type: text/x-patch
Size: 4406 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191007/45b1a7f5/attachment.bin>


More information about the llvm-commits mailing list