<div dir="ltr">Hi,<div><br></div><div>LoopHeaders isn't declared in this static function. Could you fix this please?</div><div><br></div><div><div>@@ -3480,6 +3484,7 @@ static bool removeEmptyCleanup(CleanupRe</div><div><br></div><div>   // The cleanup pad is now unreachable.  Zap it.</div><div>   BB->eraseFromParent();</div><div>+  if (LoopHeaders) LoopHeaders->erase(BB);</div><div>   return true;</div><div> }</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 28, 2016 at 10:22 AM, Hyojin Sung via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: hsung<br>
Date: Mon Mar 28 12:22:25 2016<br>
New Revision: 264596<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=264596&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=264596&view=rev</a><br>
Log:<br>
[SimlifyCFG] Prevent passes from destroying canonical loop structure, especially for nested loops<br>
<br>
When eliminating or merging almost empty basic blocks, the existence of non-trivial PHI nodes<br>
is currently used to recognize potential loops of which the block is the header and keep the block.<br>
However, the current algorithm fails if the loops' exit condition is evaluated only with volatile<br>
values hence no PHI nodes in the header. Especially when such a loop is an outer loop of a nested<br>
loop, the loop is collapsed into a single loop which prevent later optimizations from being<br>
applied (e.g., transforming nested loops into simplified forms and loop vectorization).<br>
<br>
The patch augments the existing PHI node-based check by adding a pre-test if the BB actually<br>
belongs to a set of loop headers and not eliminating it if yes.<br>
<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp<br>
    llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp<br>
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
    llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll<br>
    llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll<br>
    llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll<br>
    llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Mon Mar 28 12:22:25 2016<br>
@@ -21,6 +21,7 @@<br>
 #include "llvm/IR/GetElementPtrTypeIterator.h"<br>
 #include "llvm/IR/IRBuilder.h"<br>
 #include "llvm/IR/Operator.h"<br>
+#include "llvm/ADT/SmallPtrSet.h"<br>
<br>
 namespace llvm {<br>
<br>
@@ -124,13 +125,16 @@ bool TryToSimplifyUncondBranchFromEmptyB<br>
 /// values, but instcombine orders them so it usually won't matter.<br>
 bool EliminateDuplicatePHINodes(BasicBlock *BB);<br>
<br>
-/// This function is used to do simplification of a CFG.  For example, it<br>
-/// adjusts branches to branches to eliminate the extra hop, it eliminates<br>
-/// unreachable basic blocks, and does other "peephole" optimization of the CFG.<br>
-/// It returns true if a modification was made, possibly deleting the basic<br>
-/// block that was pointed to.<br>
+/// This function is used to do simplification of a CFG.  For<br>
+/// example, it adjusts branches to branches to eliminate the extra hop, it<br>
+/// eliminates unreachable basic blocks, and does other "peephole" optimization<br>
+/// of the CFG.  It returns true if a modification was made, possibly deleting<br>
+/// the basic block that was pointed to. LoopHeaders is an optional input<br>
+/// parameter, providing the set of loop header that SimplifyCFG should not<br>
+/// eliminate.<br>
 bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,<br>
-                 unsigned BonusInstThreshold, AssumptionCache *AC = nullptr);<br>
+                 unsigned BonusInstThreshold, AssumptionCache *AC = nullptr,<br>
+                 SmallPtrSetImpl<BasicBlock *> *LoopHeaders = nullptr);<br>
<br>
 /// This function is used to flatten a CFG. For example, it uses parallel-and<br>
 /// and parallel-or mode to collapse if-conditions and merge if-regions with<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Mon Mar 28 12:22:25 2016<br>
@@ -245,10 +245,13 @@ bool JumpThreading::runOnFunction(Functi<br>
       // Can't thread an unconditional jump, but if the block is "almost<br>
       // empty", we can replace uses of it with uses of the successor and make<br>
       // this dead.<br>
+      // We should not eliminate the loop header either, because eliminating<br>
+      // a loop header might later prevent LoopSimplify from transforming nested<br>
+      // loops into simplified form.<br>
       if (BI && BI->isUnconditional() &&<br>
           BB != &BB->getParent()->getEntryBlock() &&<br>
           // If the terminator is the only non-phi instruction, try to nuke it.<br>
-          BB->getFirstNonPHIOrDbg()->isTerminator()) {<br>
+          BB->getFirstNonPHIOrDbg()->isTerminator() && !LoopHeaders.count(BB)) {<br>
         // Since TryToSimplifyUncondBranchFromEmptyBlock may delete the<br>
         // block, we have to make sure it isn't in the LoopHeaders set.  We<br>
         // reinsert afterward if needed.<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp Mon Mar 28 12:22:25 2016<br>
@@ -28,6 +28,7 @@<br>
 #include "llvm/Analysis/GlobalsModRef.h"<br>
 #include "llvm/Analysis/AssumptionCache.h"<br>
 #include "llvm/Analysis/TargetTransformInfo.h"<br>
+#include "llvm/Analysis/CFG.h"<br>
 #include "llvm/IR/Attributes.h"<br>
 #include "llvm/IR/CFG.h"<br>
 #include "llvm/IR/Constants.h"<br>
@@ -130,13 +131,20 @@ static bool iterativelySimplifyCFG(Funct<br>
                                    AssumptionCache *AC,<br>
                                    unsigned BonusInstThreshold) {<br>
   bool Changed = false;<br>
-  bool LocalChange = true;<br>
+  bool LocalChange = true;<br>
+<br>
+  SmallVector<std::pair<const BasicBlock *, const BasicBlock *>, 32> Edges;<br>
+  FindFunctionBackedges(F, Edges);<br>
+  SmallPtrSet<BasicBlock *, 16> LoopHeaders;<br>
+  for (unsigned i = 0, e = Edges.size(); i != e; ++i)<br>
+    LoopHeaders.insert(const_cast<BasicBlock *>(Edges[i].second));<br>
+<br>
   while (LocalChange) {<br>
     LocalChange = false;<br>
<br>
     // Loop over all of the basic blocks and remove them if they are unneeded.<br>
     for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {<br>
-      if (SimplifyCFG(&*BBIt++, TTI, BonusInstThreshold, AC)) {<br>
+      if (SimplifyCFG(&*BBIt++, TTI, BonusInstThreshold, AC, &LoopHeaders)) {<br>
         LocalChange = true;<br>
         ++NumSimpl;<br>
       }<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Mon Mar 28 12:22:25 2016<br>
@@ -135,6 +135,7 @@ class SimplifyCFGOpt {<br>
   const DataLayout &DL;<br>
   unsigned BonusInstThreshold;<br>
   AssumptionCache *AC;<br>
+  SmallPtrSetImpl<BasicBlock *> *LoopHeaders;<br>
   Value *isValueEqualityComparison(TerminatorInst *TI);<br>
   BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,<br>
                                std::vector<ValueEqualityComparisonCase> &Cases);<br>
@@ -157,8 +158,10 @@ class SimplifyCFGOpt {<br>
<br>
 public:<br>
   SimplifyCFGOpt(const TargetTransformInfo &TTI, const DataLayout &DL,<br>
-                 unsigned BonusInstThreshold, AssumptionCache *AC)<br>
-      : TTI(TTI), DL(DL), BonusInstThreshold(BonusInstThreshold), AC(AC) {}<br>
+                 unsigned BonusInstThreshold, AssumptionCache *AC,<br>
+                 SmallPtrSetImpl<BasicBlock *> *LoopHeaders)<br>
+      : TTI(TTI), DL(DL), BonusInstThreshold(BonusInstThreshold), AC(AC),<br>
+        LoopHeaders(LoopHeaders) {}<br>
   bool run(BasicBlock *BB);<br>
 };<br>
 }<br>
@@ -3362,6 +3365,7 @@ bool SimplifyCFGOpt::SimplifySingleResum<br>
<br>
   // The landingpad is now unreachable.  Zap it.<br>
   BB->eraseFromParent();<br>
+  if (LoopHeaders) LoopHeaders->erase(BB);<br>
   return true;<br>
 }<br>
<br>
@@ -3480,6 +3484,7 @@ static bool removeEmptyCleanup(CleanupRe<br>
<br>
   // The cleanup pad is now unreachable.  Zap it.<br>
   BB->eraseFromParent();<br>
+  if (LoopHeaders) LoopHeaders->erase(BB);<br>
   return true;<br>
 }<br>
<br>
@@ -3560,9 +3565,11 @@ bool SimplifyCFGOpt::SimplifyReturn(Retu<br>
     }<br>
<br>
     // If we eliminated all predecessors of the block, delete the block now.<br>
-    if (pred_empty(BB))<br>
+    if (pred_empty(BB)) {<br>
       // We know there are no successors, so just nuke the block.<br>
       BB->eraseFromParent();<br>
+      if (LoopHeaders) LoopHeaders->erase(BB);<br>
+    }<br>
<br>
     return true;<br>
   }<br>
@@ -3719,6 +3726,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable<br>
       BB != &BB->getParent()->getEntryBlock()) {<br>
     // We know there are no successors, so just nuke the block.<br>
     BB->eraseFromParent();<br>
+    if (LoopHeaders) LoopHeaders->erase(BB);<br>
     return true;<br>
   }<br>
<br>
@@ -5062,8 +5070,14 @@ bool SimplifyCFGOpt::SimplifyUncondBranc<br>
     return true;<br>
<br>
   // If the Terminator is the only non-phi instruction, simplify the block.<br>
+  // if LoopHeader is provided, check if the block is a loop header<br>
+  // (This is for early invocations before loop simplify and vectorization<br>
+  // to keep canonical loop forms for nested loops.<br>
+  // These blocks can be eliminated when the pass is invoked later<br>
+  // in the back-end.)<br>
   BasicBlock::iterator I = BB->getFirstNonPHIOrDbg()->getIterator();<br>
   if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() &&<br>
+      (!LoopHeaders || (LoopHeaders && !LoopHeaders->count(BB))) &&<br>
       TryToSimplifyUncondBranchFromEmptyBlock(BB))<br>
     return true;<br>
<br>
@@ -5343,7 +5357,8 @@ bool SimplifyCFGOpt::run(BasicBlock *BB)<br>
 /// of the CFG.  It returns true if a modification was made.<br>
 ///<br>
 bool llvm::SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,<br>
-                       unsigned BonusInstThreshold, AssumptionCache *AC) {<br>
+                       unsigned BonusInstThreshold, AssumptionCache *AC,<br>
+                       SmallPtrSetImpl<BasicBlock *> *LoopHeaders) {<br>
   return SimplifyCFGOpt(TTI, BB->getModule()->getDataLayout(),<br>
-                        BonusInstThreshold, AC).run(BB);<br>
+                        BonusInstThreshold, AC, LoopHeaders).run(BB);<br>
 }<br>
<br>
Modified: llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll (original)<br>
+++ llvm/trunk/test/Transforms/LoopUnswitch/2015-06-17-Metadata.ll Mon Mar 28 12:22:25 2016<br>
@@ -16,23 +16,23 @@ for.body:<br>
   %cmp1 = icmp eq i32 %a, 12345<br>
   br i1 %cmp1, label %if.then, label %if.else, !prof !0<br>
 ; CHECK: %cmp1 = icmp eq i32 %a, 12345<br>
-; CHECK-NEXT: br i1 %cmp1, label %<a href="http://if.then.us" rel="noreferrer" target="_blank">if.then.us</a>, label %if.else, !prof !0<br>
+; CHECK-NEXT: br i1 %cmp1, label %<a href="http://for.body.us" rel="noreferrer" target="_blank">for.body.us</a>, label %for.body, !prof !0<br>
 if.then:                                          ; preds = %for.body<br>
-; CHECK: <a href="http://if.then.us" rel="noreferrer" target="_blank">if.then.us</a>:<br>
+; CHECK: <a href="http://for.body.us" rel="noreferrer" target="_blank">for.body.us</a>:<br>
 ; CHECK: add nsw i32 %{{.*}}, 123<br>
 ; CHECK: %<a href="http://exitcond.us" rel="noreferrer" target="_blank">exitcond.us</a> = icmp eq i32 %<a href="http://inc.us" rel="noreferrer" target="_blank">inc.us</a>, %b<br>
-; CHECK: br i1 %<a href="http://exitcond.us" rel="noreferrer" target="_blank">exitcond.us</a>, label %for.cond.cleanup, label %<a href="http://if.then.us" rel="noreferrer" target="_blank">if.then.us</a><br>
+; CHECK: br i1 %<a href="http://exitcond.us" rel="noreferrer" target="_blank">exitcond.us</a>, label %for.cond.cleanup, label %<a href="http://for.body.us" rel="noreferrer" target="_blank">for.body.us</a><br>
   %add = add nsw i32 %add.i, 123<br>
   br label %for.inc<br>
<br>
 if.else:                                          ; preds = %for.body<br>
   %mul = mul nsw i32 %mul.i, %b<br>
   br label %for.inc<br>
-; CHECK: if.else:<br>
+; CHECK: for.body:<br>
 ; CHECK: %mul = mul nsw i32 %mul.i, %b<br>
 ; CHECK: %inc = add nuw nsw i32 %inc.i, 1<br>
 ; CHECK: %exitcond = icmp eq i32 %inc, %b<br>
-; CHECK: br i1 %exitcond, label %for.cond.cleanup, label %if.else<br>
+; CHECK: br i1 %exitcond, label %for.cond.cleanup, label %for.body<br>
 for.inc:                                          ; preds = %if.then, %if.else<br>
   %mul.p = phi i32 [ %b, %if.then ], [ %mul, %if.else ]<br>
   %add.p = phi i32 [ %add, %if.then ], [ %a, %if.else ]<br>
<br>
Modified: llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll (original)<br>
+++ llvm/trunk/test/Transforms/LoopUnswitch/infinite-loop.ll Mon Mar 28 12:22:25 2016<br>
@@ -16,10 +16,10 @@<br>
 ; CHECK-NEXT: br i1 %a, label %entry.split, label %abort0.split<br>
<br>
 ; CHECK: entry.split:<br>
-; CHECK-NEXT: br i1 %b, label %cond.end, label %abort1.split<br>
+; CHECK-NEXT: br i1 %b, label %for.body, label %abort1.split<br>
<br>
-; CHECK: cond.end:<br>
-; CHECK-NEXT: br label %cond.end<br>
+; CHECK: for.body:<br>
+; CHECK-NEXT: br label %for.body<br>
<br>
 ; CHECK: abort0.split:<br>
 ; CHECK-NEXT: call void @end0() [[NOR_NUW:#[0-9]+]]<br>
<br>
Modified: llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll Mon Mar 28 12:22:25 2016<br>
@@ -1,6 +1,6 @@<br>
 ; RUN: opt < %s -simplifycfg -S > %t<br>
 ; RUN: not grep "^BB.tomerge" %t<br>
-; RUN: grep "^BB.nomerge" %t | count 2<br>
+; RUN: grep "^BB.nomerge" %t | count 4<br>
<br>
 ; ModuleID = '<stdin>'<br>
 declare i1 @foo()<br>
@@ -54,24 +54,24 @@ Exit:               ; preds = %Succ<br>
        ret void<br>
 }<br>
<br>
-; This function can be merged<br>
+; This function can't be merged (for keeping canonical loop structures)<br>
 define void @c() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %BB.nomerge<br>
<br>
-BB.tomerge:            ; preds = %Common, %entry<br>
+BB.nomerge:            ; preds = %Common, %entry<br>
        br label %Succ<br>
<br>
 Succ:          ; preds = %Common, %BB.tomerge, %Pre-Exit<br>
         ; This phi has identical values for Common and (through BB) Common,<br>
         ; blocks can't be merged<br>
-       %b = phi i32 [ 1, %BB.tomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]<br>
+       %b = phi i32 [ 1, %BB.nomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Common, label %Pre-Exit<br>
<br>
 Common:                ; preds = %Succ<br>
        %cond = call i1 @foo( )         ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Succ<br>
+       br i1 %cond, label %BB.nomerge, label %Succ<br>
<br>
 Pre-Exit:       ; preds = %Succ<br>
         ; This adds a backedge, so the %b phi node gets a third branch and is<br>
@@ -83,25 +83,25 @@ Exit:               ; preds = %Pre-Exit<br>
        ret void<br>
 }<br>
<br>
-; This function can be merged<br>
+; This function can't be merged (for keeping canonical loop structures)<br>
 define void @d() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %BB.nomerge<br>
<br>
-BB.tomerge:            ; preds = %Common, %entry<br>
+BB.nomerge:            ; preds = %Common, %entry<br>
         ; This phi has a matching value (0) with below phi (0), so blocks<br>
         ; can be merged.<br>
        %a = phi i32 [ 1, %entry ], [ 0, %Common ]              ; <i32> [#uses=1]<br>
        br label %Succ<br>
<br>
 Succ:          ; preds = %Common, %BB.tomerge<br>
-       %b = phi i32 [ %a, %BB.tomerge ], [ 0, %Common ]                ; <i32> [#uses=0]<br>
+       %b = phi i32 [ %a, %BB.nomerge ], [ 0, %Common ]                ; <i32> [#uses=0]<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Common, label %Exit<br>
<br>
 Common:                ; preds = %Succ<br>
        %cond = call i1 @foo( )         ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Succ<br>
+       br i1 %cond, label %BB.nomerge, label %Succ<br>
<br>
 Exit:          ; preds = %Succ<br>
        ret void<br>
@@ -110,21 +110,21 @@ Exit:             ; preds = %Succ<br>
 ; This function can be merged<br>
 define void @e() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %Succ<br>
<br>
-BB.tomerge:            ; preds = %Use, %entry<br>
+Succ:          ; preds = %Use, %entry<br>
         ; This phi is used somewhere else than Succ, but this should not prevent<br>
         ; merging this block<br>
        %a = phi i32 [ 1, %entry ], [ 0, %Use ]         ; <i32> [#uses=1]<br>
-       br label %Succ<br>
+       br label %BB.tomerge<br>
<br>
-Succ:          ; preds = %BB.tomerge<br>
+BB.tomerge:            ; preds = %BB.tomerge<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Use, label %Exit<br>
<br>
 Use:           ; preds = %Succ<br>
        %cond = call i1 @bar( i32 %a )          ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Exit<br>
+       br i1 %cond, label %Succ, label %Exit<br>
<br>
 Exit:          ; preds = %Use, %Succ<br>
        ret void<br>
<br>
Modified: llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll?rev=264596&r1=264595&r2=264596&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll?rev=264596&r1=264595&r2=264596&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll Mon Mar 28 12:22:25 2016<br>
@@ -5,7 +5,7 @@<br>
 ; RUN: not grep X: %t<br>
 ; RUN: not grep 'switch i32[^U]+%U' %t<br>
 ; RUN: not grep "^BB.tomerge" %t<br>
-; RUN: grep "^BB.nomerge" %t | count 2<br>
+; RUN: grep "^BB.nomerge" %t | count 4<br>
 ;<br>
<br>
 ; ModuleID = '<stdin>'<br>
@@ -179,24 +179,24 @@ Exit:             ; preds = %Succ<br>
        ret void<br>
 }<br>
<br>
-; This function can be merged<br>
+; This function can't be merged (for keeping canonical loop structures)<br>
 define void @c() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %BB.nomerge<br>
<br>
-BB.tomerge:            ; preds = %Common, %entry<br>
+BB.nomerge:            ; preds = %Common, %entry<br>
        br label %Succ<br>
<br>
 Succ:          ; preds = %Common, %BB.tomerge, %Pre-Exit<br>
         ; This phi has identical values for Common and (through BB) Common,<br>
         ; blocks can't be merged<br>
-       %b = phi i32 [ 1, %BB.tomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]<br>
+       %b = phi i32 [ 1, %BB.nomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Common, label %Pre-Exit<br>
<br>
 Common:                ; preds = %Succ<br>
        %cond = call i1 @foo( )         ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Succ<br>
+       br i1 %cond, label %BB.nomerge, label %Succ<br>
<br>
 Pre-Exit:       ; preds = %Succ<br>
         ; This adds a backedge, so the %b phi node gets a third branch and is<br>
@@ -208,25 +208,25 @@ Exit:             ; preds = %Pre-Exit<br>
        ret void<br>
 }<br>
<br>
-; This function can be merged<br>
+; This function can't be merged (for keeping canonical loop structures)<br>
 define void @d() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %BB.nomerge<br>
<br>
-BB.tomerge:            ; preds = %Common, %entry<br>
+BB.nomerge:            ; preds = %Common, %entry<br>
         ; This phi has a matching value (0) with below phi (0), so blocks<br>
         ; can be merged.<br>
        %a = phi i32 [ 1, %entry ], [ 0, %Common ]              ; <i32> [#uses=1]<br>
        br label %Succ<br>
<br>
 Succ:          ; preds = %Common, %BB.tomerge<br>
-       %b = phi i32 [ %a, %BB.tomerge ], [ 0, %Common ]                ; <i32> [#uses=0]<br>
+       %b = phi i32 [ %a, %BB.nomerge ], [ 0, %Common ]                ; <i32> [#uses=0]<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Common, label %Exit<br>
<br>
 Common:                ; preds = %Succ<br>
        %cond = call i1 @foo( )         ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Succ<br>
+       br i1 %cond, label %BB.nomerge, label %Succ<br>
<br>
 Exit:          ; preds = %Succ<br>
        ret void<br>
@@ -235,21 +235,21 @@ Exit:             ; preds = %Succ<br>
 ; This function can be merged<br>
 define void @e() {<br>
 entry:<br>
-       br label %BB.tomerge<br>
+       br label %Succ<br>
<br>
-BB.tomerge:            ; preds = %Use, %entry<br>
+Succ:          ; preds = %Use, %entry<br>
         ; This phi is used somewhere else than Succ, but this should not prevent<br>
         ; merging this block<br>
        %a = phi i32 [ 1, %entry ], [ 0, %Use ]         ; <i32> [#uses=1]<br>
-       br label %Succ<br>
+       br label %BB.tomerge<br>
<br>
-Succ:          ; preds = %BB.tomerge<br>
+BB.tomerge:            ; preds = %Succ<br>
        %conde = call i1 @foo( )                ; <i1> [#uses=1]<br>
        br i1 %conde, label %Use, label %Exit<br>
<br>
 Use:           ; preds = %Succ<br>
        %cond = call i1 @bar( i32 %a )          ; <i1> [#uses=1]<br>
-       br i1 %cond, label %BB.tomerge, label %Exit<br>
+       br i1 %cond, label %Succ, label %Exit<br>
<br>
 Exit:          ; preds = %Use, %Succ<br>
        ret void<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>