1/*========================== begin_copyright_notice ============================
2
3Copyright (C) 2019-2021 Intel Corporation
4
5SPDX-License-Identifier: MIT
6
7============================= end_copyright_notice ===========================*/
8
9From eeb816d95f0910bd246e37bb2bb3923acf0edf6b Mon Sep 17 00:00:00 2001
10From: Aleksander Us <aleksander.us@intel.com>
11Date: Mon, 26 Aug 2019 15:47:41 +0300
12Subject: [PATCH] [BasicBlockUtils] Add metadata fixing in
13 SplitBlockPredecessors.
14
15In case when BB is header of some loop and predecessor is latch of
16this loop, metadata was not attached to newly created basic block.
17This led to loss of loop metadata for other passes.
18---
19 lib/Transforms/Utils/BasicBlockUtils.cpp      | 23 ++++++++----
20 test/Transforms/LoopSimplify/loop_metadata.ll | 36 +++++++++++++++++++
21 2 files changed, 52 insertions(+), 7 deletions(-)
22 create mode 100644 test/Transforms/LoopSimplify/loop_metadata.ll
23
24diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
25index 5fa371377c8..3a90ae061fb 100644
26--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
27+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
28@@ -579,24 +579,33 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
29
30   // The new block unconditionally branches to the old block.
31   BranchInst *BI = BranchInst::Create(BB, NewBB);
32+  bool IsBBHeader = LI && LI->isLoopHeader(BB);
33+  Loop *BBLoop = LI ? LI->getLoopFor(BB) : nullptr;
34   // Splitting the predecessors of a loop header creates a preheader block.
35-  if (LI && LI->isLoopHeader(BB))
36+  if (IsBBHeader)
37     // Using the loop start line number prevents debuggers stepping into the
38     // loop body for this instruction.
39-    BI->setDebugLoc(LI->getLoopFor(BB)->getStartLoc());
40+    BI->setDebugLoc(BBLoop->getStartLoc());
41   else
42     BI->setDebugLoc(BB->getFirstNonPHIOrDbg()->getDebugLoc());
43
44   // Move the edges from Preds to point to NewBB instead of BB.
45-  for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
46+  for (BasicBlock *Pred : Preds) {
47+    Instruction *PI = Pred->getTerminator();
48     // This is slightly more strict than necessary; the minimum requirement
49     // is that there be no more than one indirectbr branching to BB. And
50     // all BlockAddress uses would need to be updated.
51-    assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) &&
52+    assert(!isa<IndirectBrInst>(PI) &&
53            "Cannot split an edge from an IndirectBrInst");
54-    assert(!isa<CallBrInst>(Preds[i]->getTerminator()) &&
55-           "Cannot split an edge from a CallBrInst");
56-    Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB);
57+    assert(!isa<CallBrInst>(PI) && "Cannot split an edge from a CallBrInst");
58+    if (IsBBHeader && BBLoop->contains(Pred) && BBLoop->isLoopLatch(Pred)) {
59+      // Update loop metadata if it exists.
60+      if (MDNode *LoopMD = PI->getMetadata(LLVMContext::MD_loop)) {
61+        BI->setMetadata(LLVMContext::MD_loop, LoopMD);
62+        PI->setMetadata(LLVMContext::MD_loop, nullptr);
63+      }
64+    }
65+    PI->replaceUsesOfWith(BB, NewBB);
66   }
67
68   // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI
69diff --git a/llvm/test/Transforms/LoopSimplify/loop_metadata.ll b/llvm/test/Transforms/LoopSimplify/loop_metadata.ll
70new file mode 100644
71index 00000000000..c15c92fe3ae
72--- /dev/null
73+++ b/llvm/test/Transforms/LoopSimplify/loop_metadata.ll
74@@ -0,0 +1,36 @@
75+; RUN: opt -S -loop-simplify < %s | FileCheck %s
76+
77+; CHECK: for.cond.loopexit:
78+; CHECK: br label %for.cond, !llvm.loop !0
79+; CHECK: br i1 %cmp1, label %for.body1, label %for.cond.loopexit
80+
81+define void @foo() {
82+entry:
83+  br label %for.cond
84+
85+for.cond:                                         ; preds = %for.cond1, %entry
86+  %j = phi i32 [ 0, %entry ], [ %add, %for.cond1 ]
87+  %cmp = icmp ult i32 %j, 8
88+  br i1 %cmp, label %for.body, label %for.end
89+
90+for.body:                                         ; preds = %for.cond
91+  %dummy1 = add i32 1, 1
92+  %add = add nuw nsw i32 %j, 1
93+  br label %for.cond1
94+
95+for.cond1:                                      ; preds = %for.body1, %for.body
96+  %i.0 = phi i32 [ 1, %for.body ], [ %inc, %for.body1 ]
97+  %cmp1 = icmp ult i32 %i.0, 8
98+  br i1 %cmp1, label %for.body1, label %for.cond, !llvm.loop !0
99+
100+for.body1:                                      ; preds = %for.cond1
101+  %dummy2 = add i32 1, 1
102+  %inc = add nuw nsw i32 %i.0, 1
103+  br label %for.cond1
104+
105+for.end:                                       ; preds = %for.cond
106+  ret void
107+}
108+
109+!0 = distinct !{!0, !1}
110+!1 = !{!"llvm.loop.unroll.full"}
111--
1122.18.0
113
114