<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>