llvm.org GIT mirror llvm / aad9c3f
Fast fix for PR12343: http://llvm.org/bugs/show_bug.cgi?id=12343 We have not trivial way for splitting edges that are goes from indirect branch. We can do it with some tricks, but it should be additionally discussed. And it is still dangerous due to difficulty of indirect branches controlling. Fix forbids this case for unswitching. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153879 91177308-0d34-0410-b5e6-96231b3b80d8 Stepan Dyatkovskiy 8 years ago
2 changed file(s) with 75 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
190190 loopHeader = currentLoop->getHeader();
191191 loopPreheader = currentLoop->getLoopPreheader();
192192 }
193
194 /// HasIndirectBrsInPreds - Returns true if there are predecessors, that are
195 /// terminated with indirect branch instruction.
196 bool HasIndirectBrsInPreds(const SmallVectorImpl &ExitBlocks);
193197
194198 /// Split all of the edges from inside the loop to their exit blocks.
195199 /// Update the appropriate Phi nodes as we do so.
198202 bool UnswitchIfProfitable(Value *LoopCond, Constant *Val);
199203 void UnswitchTrivialCondition(Loop *L, Value *Cond, Constant *Val,
200204 BasicBlock *ExitBlock);
201 void UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
205 bool UnswitchNontrivialCondition(Value *LIC, Constant *OnVal, Loop *L);
202206
203207 void RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
204208 Constant *Val, bool isEqual);
633637 if (OptimizeForSize || F->hasFnAttr(Attribute::OptimizeForSize))
634638 return false;
635639
636 UnswitchNontrivialCondition(LoopCond, Val, currentLoop);
637 return true;
640 return UnswitchNontrivialCondition(LoopCond, Val, currentLoop);
638641 }
639642
640643 /// CloneLoop - Recursively clone the specified loop and all of its children,
729732 ++NumTrivial;
730733 }
731734
735 /// HasIndirectBrsInPreds - Returns true if there are predecessors, that are
736 /// terminated with indirect branch instruction.
737 bool LoopUnswitch::HasIndirectBrsInPreds(
738 const SmallVectorImpl &ExitBlocks){
739
740 for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
741 const BasicBlock *ExitBlock = ExitBlocks[i];
742 for (const_pred_iterator p = pred_begin(ExitBlock), e = pred_end(ExitBlock);
743 p != e; ++p) {
744 // Cannot split an edge from an IndirectBrInst
745 if (isa((*p)->getTerminator()))
746 return true;
747
748 }
749 }
750 return false;
751 }
752
732753 /// SplitExitEdges - Split all of the edges from inside the loop to their exit
733754 /// blocks. Update the appropriate Phi nodes as we do so.
734755 void LoopUnswitch::SplitExitEdges(Loop *L,
754775 /// UnswitchNontrivialCondition - We determined that the loop is profitable
755776 /// to unswitch when LIC equal Val. Split it into loop versions and test the
756777 /// condition outside of either loop. Return the loops created as Out1/Out2.
757 void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
778 bool LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val,
758779 Loop *L) {
759780 Function *F = loopHeader->getParent();
760781 DEBUG(dbgs() << "loop-unswitch: Unswitching loop %"
778799
779800 SmallVector ExitBlocks;
780801 L->getUniqueExitBlocks(ExitBlocks);
802 if (HasIndirectBrsInPreds(ExitBlocks))
803 return false;
781804
782805 // Split all of the edges from inside the loop to their exit blocks. Update
783806 // the appropriate Phi nodes as we do so.
892915 if (!LoopProcessWorklist.empty() && LoopProcessWorklist.back() == NewLoop &&
893916 LICHandle && !isa(LICHandle))
894917 RewriteLoopBodyWithConditionConstant(NewLoop, LICHandle, Val, true);
918
919 return true;
895920 }
896921
897922 /// RemoveFromWorklist - Remove all instances of I from the worklist vector
0 ; RUN: opt -loop-unswitch -disable-output -stats -info-output-file - < %s | FileCheck --check-prefix=STATS %s
1 ; RUN: opt -S -loop-unswitch -verify-loop-info -verify-dom-info %s | FileCheck %s
2
3 ; STATS: 1 loop-unswitch - Total number of instructions analyzed
4
5 ; CHECK: %0 = icmp eq i64 undef, 0
6 ; CHECK-NEXT: br i1 %0, label %"5", label %"4"
7
8 ; CHECK: "5": ; preds = %entry
9 ; CHECK-NEXT: br label %"5.split"
10
11 ; CHECK: "5.split": ; preds = %"5"
12 ; CHECK-NEXT: br label %"16"
13
14 ; CHECK: "16": ; preds = %"22", %"5.split"
15 ; CHECK-NEXT: indirectbr i8* undef, [label %"22", label %"33"]
16
17 ; CHECK: "22": ; preds = %"16"
18 ; CHECK-NEXT: br i1 %0, label %"16", label %"26"
19
20 ; CHECK: "26": ; preds = %"22"
21 ; CHECK-NEXT: unreachable
22
23 define void @foo() {
24 entry:
25 %0 = icmp eq i64 undef, 0
26 br i1 %0, label %"5", label %"4"
27
28 "4": ; preds = %entry
29 unreachable
30
31 "5": ; preds = %entry
32 br label %"16"
33
34 "16": ; preds = %"22", %"5"
35 indirectbr i8* undef, [label %"22", label %"33"]
36
37 "22": ; preds = %"16"
38 br i1 %0, label %"16", label %"26"
39
40 "26": ; preds = %"22"
41 unreachable
42
43 "33": ; preds = %"16"
44 unreachable
45 }