15adb96ccSEugene Zelenko //===- FlatternCFG.cpp - Code to perform CFG flattening -------------------===//
2aa664d9bSTom Stellard //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aa664d9bSTom Stellard //
7aa664d9bSTom Stellard //===----------------------------------------------------------------------===//
8aa664d9bSTom Stellard //
9aa664d9bSTom Stellard // Reduce conditional branches in CFG.
10aa664d9bSTom Stellard //
11aa664d9bSTom Stellard //===----------------------------------------------------------------------===//
12aa664d9bSTom Stellard 
13aa664d9bSTom Stellard #include "llvm/ADT/SmallPtrSet.h"
14aa664d9bSTom Stellard #include "llvm/Analysis/AliasAnalysis.h"
1531b98d2eSDavid Blaikie #include "llvm/Transforms/Utils/Local.h"
16aa664d9bSTom Stellard #include "llvm/Analysis/ValueTracking.h"
175adb96ccSEugene Zelenko #include "llvm/IR/BasicBlock.h"
18aa664d9bSTom Stellard #include "llvm/IR/IRBuilder.h"
195adb96ccSEugene Zelenko #include "llvm/IR/InstrTypes.h"
205adb96ccSEugene Zelenko #include "llvm/IR/Instruction.h"
215adb96ccSEugene Zelenko #include "llvm/IR/Instructions.h"
225adb96ccSEugene Zelenko #include "llvm/IR/Value.h"
235adb96ccSEugene Zelenko #include "llvm/Support/Casting.h"
24aa664d9bSTom Stellard #include "llvm/Support/Debug.h"
2571044cbeSSerge Pavlov #include "llvm/Support/raw_ostream.h"
26aa664d9bSTom Stellard #include "llvm/Transforms/Utils/BasicBlockUtils.h"
275adb96ccSEugene Zelenko #include <cassert>
285adb96ccSEugene Zelenko 
29aa664d9bSTom Stellard using namespace llvm;
30aa664d9bSTom Stellard 
31964daaafSChandler Carruth #define DEBUG_TYPE "flattencfg"
32964daaafSChandler Carruth 
33aa664d9bSTom Stellard namespace {
345adb96ccSEugene Zelenko 
35aa664d9bSTom Stellard class FlattenCFGOpt {
36aa664d9bSTom Stellard   AliasAnalysis *AA;
375adb96ccSEugene Zelenko 
385f8f34e4SAdrian Prantl   /// Use parallel-and or parallel-or to generate conditions for
39aa664d9bSTom Stellard   /// conditional branches.
40843fb204SJustin Bogner   bool FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder);
415adb96ccSEugene Zelenko 
425f8f34e4SAdrian Prantl   /// If \param BB is the merge block of an if-region, attempt to merge
43aa664d9bSTom Stellard   /// the if-region with an adjacent if-region upstream if two if-regions
44aa664d9bSTom Stellard   /// contain identical instructions.
45843fb204SJustin Bogner   bool MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder);
465adb96ccSEugene Zelenko 
475f8f34e4SAdrian Prantl   /// Compare a pair of blocks: \p Block1 and \p Block2, which
48111ddc57SEhud Katz   /// are from two if-regions, where \p Head2 is the entry block of the 2nd
49111ddc57SEhud Katz   /// if-region.  \returns true if \p Block1 and \p Block2 contain identical
50aa664d9bSTom Stellard   /// instructions, and have no memory reference alias with \p Head2.
51aa664d9bSTom Stellard   /// This is used as a legality check for merging if-regions.
52111ddc57SEhud Katz   bool CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
53111ddc57SEhud Katz                             BasicBlock *Head2);
54aa664d9bSTom Stellard 
55aa664d9bSTom Stellard public:
FlattenCFGOpt(AliasAnalysis * AA)56aa664d9bSTom Stellard   FlattenCFGOpt(AliasAnalysis *AA) : AA(AA) {}
575adb96ccSEugene Zelenko 
58aa664d9bSTom Stellard   bool run(BasicBlock *BB);
59aa664d9bSTom Stellard };
605adb96ccSEugene Zelenko 
615adb96ccSEugene Zelenko } // end anonymous namespace
62aa664d9bSTom Stellard 
63aa664d9bSTom Stellard /// If \param [in] BB has more than one predecessor that is a conditional
64aa664d9bSTom Stellard /// branch, attempt to use parallel and/or for the branch condition. \returns
65aa664d9bSTom Stellard /// true on success.
66aa664d9bSTom Stellard ///
67aa664d9bSTom Stellard /// Before:
68aa664d9bSTom Stellard ///   ......
69aa664d9bSTom Stellard ///   %cmp10 = fcmp une float %tmp1, %tmp2
70d98cb81cSJakub Kuderski ///   br i1 %cmp10, label %if.then, label %lor.rhs
71aa664d9bSTom Stellard ///
72aa664d9bSTom Stellard /// lor.rhs:
73aa664d9bSTom Stellard ///   ......
74aa664d9bSTom Stellard ///   %cmp11 = fcmp une float %tmp3, %tmp4
75aa664d9bSTom Stellard ///   br i1 %cmp11, label %if.then, label %ifend
76aa664d9bSTom Stellard ///
77aa664d9bSTom Stellard /// if.end:  // the merge block
78aa664d9bSTom Stellard ///   ......
79aa664d9bSTom Stellard ///
80aa664d9bSTom Stellard /// if.then: // has two predecessors, both of them contains conditional branch.
81aa664d9bSTom Stellard ///   ......
82aa664d9bSTom Stellard ///   br label %if.end;
83aa664d9bSTom Stellard ///
84aa664d9bSTom Stellard /// After:
85aa664d9bSTom Stellard ///  ......
86aa664d9bSTom Stellard ///  %cmp10 = fcmp une float %tmp1, %tmp2
87aa664d9bSTom Stellard ///  ......
88aa664d9bSTom Stellard ///  %cmp11 = fcmp une float %tmp3, %tmp4
89aa664d9bSTom Stellard ///  %cmp12 = or i1 %cmp10, %cmp11    // parallel-or mode.
90aa664d9bSTom Stellard ///  br i1 %cmp12, label %if.then, label %ifend
91aa664d9bSTom Stellard ///
92aa664d9bSTom Stellard ///  if.end:
93aa664d9bSTom Stellard ///    ......
94aa664d9bSTom Stellard ///
95aa664d9bSTom Stellard ///  if.then:
96aa664d9bSTom Stellard ///    ......
97aa664d9bSTom Stellard ///    br label %if.end;
98aa664d9bSTom Stellard ///
99aa664d9bSTom Stellard ///  Current implementation handles two cases.
100cfb5b144SSimon Pilgrim ///  Case 1: BB is on the else-path.
101aa664d9bSTom Stellard ///
102aa664d9bSTom Stellard ///          BB1
103aa664d9bSTom Stellard ///        /     |
104aa664d9bSTom Stellard ///       BB2    |
105aa664d9bSTom Stellard ///      /   \   |
106aa664d9bSTom Stellard ///     BB3   \  |     where, BB1, BB2 contain conditional branches.
107aa664d9bSTom Stellard ///      \    |  /     BB3 contains unconditional branch.
108cfb5b144SSimon Pilgrim ///       \   | /      BB4 corresponds to BB which is also the merge.
109aa664d9bSTom Stellard ///  BB => BB4
110aa664d9bSTom Stellard ///
111aa664d9bSTom Stellard ///
112aa664d9bSTom Stellard ///  Corresponding source code:
113aa664d9bSTom Stellard ///
114aa664d9bSTom Stellard ///  if (a == b && c == d)
115aa664d9bSTom Stellard ///    statement; // BB3
116aa664d9bSTom Stellard ///
117cfb5b144SSimon Pilgrim ///  Case 2: BB is on the then-path.
118aa664d9bSTom Stellard ///
119aa664d9bSTom Stellard ///             BB1
120aa664d9bSTom Stellard ///          /      |
121aa664d9bSTom Stellard ///         |      BB2
122aa664d9bSTom Stellard ///         \    /    |  where BB1, BB2 contain conditional branches.
123aa664d9bSTom Stellard ///  BB =>   BB3      |  BB3 contains unconditiona branch and corresponds
124cfb5b144SSimon Pilgrim ///           \     /    to BB.  BB4 is the merge.
125aa664d9bSTom Stellard ///             BB4
126aa664d9bSTom Stellard ///
127aa664d9bSTom Stellard ///  Corresponding source code:
128aa664d9bSTom Stellard ///
129aa664d9bSTom Stellard ///  if (a == b || c == d)
130aa664d9bSTom Stellard ///    statement;  // BB3
131aa664d9bSTom Stellard ///
132cfb5b144SSimon Pilgrim ///  In both cases, BB is the common successor of conditional branches.
133cfb5b144SSimon Pilgrim ///  In Case 1, BB (BB4) has an unconditional branch (BB3) as
134cfb5b144SSimon Pilgrim ///  its predecessor.  In Case 2, BB (BB3) only has conditional branches
135aa664d9bSTom Stellard ///  as its predecessors.
FlattenParallelAndOr(BasicBlock * BB,IRBuilder<> & Builder)136843fb204SJustin Bogner bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
137aa664d9bSTom Stellard   PHINode *PHI = dyn_cast<PHINode>(BB->begin());
138aa664d9bSTom Stellard   if (PHI)
139aa664d9bSTom Stellard     return false; // For simplicity, avoid cases containing PHI nodes.
140aa664d9bSTom Stellard 
141f40110f4SCraig Topper   BasicBlock *LastCondBlock = nullptr;
142f40110f4SCraig Topper   BasicBlock *FirstCondBlock = nullptr;
143f40110f4SCraig Topper   BasicBlock *UnCondBlock = nullptr;
144aa664d9bSTom Stellard   int Idx = -1;
145aa664d9bSTom Stellard 
146aa664d9bSTom Stellard   // Check predecessors of \param BB.
147aa664d9bSTom Stellard   SmallPtrSet<BasicBlock *, 16> Preds(pred_begin(BB), pred_end(BB));
148aa664d9bSTom Stellard   for (SmallPtrSetIterator<BasicBlock *> PI = Preds.begin(), PE = Preds.end();
149aa664d9bSTom Stellard        PI != PE; ++PI) {
150aa664d9bSTom Stellard     BasicBlock *Pred = *PI;
151aa664d9bSTom Stellard     BranchInst *PBI = dyn_cast<BranchInst>(Pred->getTerminator());
152aa664d9bSTom Stellard 
153aa664d9bSTom Stellard     // All predecessors should terminate with a branch.
154aa664d9bSTom Stellard     if (!PBI)
155aa664d9bSTom Stellard       return false;
156aa664d9bSTom Stellard 
157aa664d9bSTom Stellard     BasicBlock *PP = Pred->getSinglePredecessor();
158aa664d9bSTom Stellard 
159aa664d9bSTom Stellard     if (PBI->isUnconditional()) {
160aa664d9bSTom Stellard       // Case 1: Pred (BB3) is an unconditional block, it should
161aa664d9bSTom Stellard       // have a single predecessor (BB2) that is also a predecessor
162aa664d9bSTom Stellard       // of \param BB (BB4) and should not have address-taken.
163aa664d9bSTom Stellard       // There should exist only one such unconditional
164aa664d9bSTom Stellard       // branch among the predecessors.
165*c714da2cSKazu Hirata       if (UnCondBlock || !PP || !Preds.contains(PP) ||
166aa664d9bSTom Stellard           Pred->hasAddressTaken())
167aa664d9bSTom Stellard         return false;
168aa664d9bSTom Stellard 
169aa664d9bSTom Stellard       UnCondBlock = Pred;
170aa664d9bSTom Stellard       continue;
171aa664d9bSTom Stellard     }
172aa664d9bSTom Stellard 
173aa664d9bSTom Stellard     // Only conditional branches are allowed beyond this point.
174aa664d9bSTom Stellard     assert(PBI->isConditional());
175aa664d9bSTom Stellard 
176aa664d9bSTom Stellard     // Condition's unique use should be the branch instruction.
177aa664d9bSTom Stellard     Value *PC = PBI->getCondition();
178aa664d9bSTom Stellard     if (!PC || !PC->hasOneUse())
179aa664d9bSTom Stellard       return false;
180aa664d9bSTom Stellard 
181aa664d9bSTom Stellard     if (PP && Preds.count(PP)) {
182aa664d9bSTom Stellard       // These are internal condition blocks to be merged from, e.g.,
183aa664d9bSTom Stellard       // BB2 in both cases.
184aa664d9bSTom Stellard       // Should not be address-taken.
185aa664d9bSTom Stellard       if (Pred->hasAddressTaken())
186aa664d9bSTom Stellard         return false;
187aa664d9bSTom Stellard 
188aa664d9bSTom Stellard       // Instructions in the internal condition blocks should be safe
189aa664d9bSTom Stellard       // to hoist up.
1905b4c837cSDuncan P. N. Exon Smith       for (BasicBlock::iterator BI = Pred->begin(), BE = PBI->getIterator();
1915b4c837cSDuncan P. N. Exon Smith            BI != BE;) {
1925b4c837cSDuncan P. N. Exon Smith         Instruction *CI = &*BI++;
193aa664d9bSTom Stellard         if (isa<PHINode>(CI) || !isSafeToSpeculativelyExecute(CI))
194aa664d9bSTom Stellard           return false;
195aa664d9bSTom Stellard       }
196aa664d9bSTom Stellard     } else {
197aa664d9bSTom Stellard       // This is the condition block to be merged into, e.g. BB1 in
198aa664d9bSTom Stellard       // both cases.
199aa664d9bSTom Stellard       if (FirstCondBlock)
200aa664d9bSTom Stellard         return false;
201aa664d9bSTom Stellard       FirstCondBlock = Pred;
202aa664d9bSTom Stellard     }
203aa664d9bSTom Stellard 
204aa664d9bSTom Stellard     // Find whether BB is uniformly on the true (or false) path
205aa664d9bSTom Stellard     // for all of its predecessors.
206aa664d9bSTom Stellard     BasicBlock *PS1 = PBI->getSuccessor(0);
207aa664d9bSTom Stellard     BasicBlock *PS2 = PBI->getSuccessor(1);
208aa664d9bSTom Stellard     BasicBlock *PS = (PS1 == BB) ? PS2 : PS1;
209aa664d9bSTom Stellard     int CIdx = (PS1 == BB) ? 0 : 1;
210aa664d9bSTom Stellard 
211aa664d9bSTom Stellard     if (Idx == -1)
212aa664d9bSTom Stellard       Idx = CIdx;
213aa664d9bSTom Stellard     else if (CIdx != Idx)
214aa664d9bSTom Stellard       return false;
215aa664d9bSTom Stellard 
216aa664d9bSTom Stellard     // PS is the successor which is not BB. Check successors to identify
217aa664d9bSTom Stellard     // the last conditional branch.
218*c714da2cSKazu Hirata     if (!Preds.contains(PS)) {
219aa664d9bSTom Stellard       // Case 2.
220aa664d9bSTom Stellard       LastCondBlock = Pred;
221aa664d9bSTom Stellard     } else {
222aa664d9bSTom Stellard       // Case 1
223aa664d9bSTom Stellard       BranchInst *BPS = dyn_cast<BranchInst>(PS->getTerminator());
224aa664d9bSTom Stellard       if (BPS && BPS->isUnconditional()) {
225aa664d9bSTom Stellard         // Case 1: PS(BB3) should be an unconditional branch.
226aa664d9bSTom Stellard         LastCondBlock = Pred;
227aa664d9bSTom Stellard       }
228aa664d9bSTom Stellard     }
229aa664d9bSTom Stellard   }
230aa664d9bSTom Stellard 
231aa664d9bSTom Stellard   if (!FirstCondBlock || !LastCondBlock || (FirstCondBlock == LastCondBlock))
232aa664d9bSTom Stellard     return false;
233aa664d9bSTom Stellard 
234edb12a83SChandler Carruth   Instruction *TBB = LastCondBlock->getTerminator();
235aa664d9bSTom Stellard   BasicBlock *PS1 = TBB->getSuccessor(0);
236aa664d9bSTom Stellard   BasicBlock *PS2 = TBB->getSuccessor(1);
237aa664d9bSTom Stellard   BranchInst *PBI1 = dyn_cast<BranchInst>(PS1->getTerminator());
238aa664d9bSTom Stellard   BranchInst *PBI2 = dyn_cast<BranchInst>(PS2->getTerminator());
239aa664d9bSTom Stellard 
240aa664d9bSTom Stellard   // If PS1 does not jump into PS2, but PS2 jumps into PS1,
241aa664d9bSTom Stellard   // attempt branch inversion.
242aa664d9bSTom Stellard   if (!PBI1 || !PBI1->isUnconditional() ||
243aa664d9bSTom Stellard       (PS1->getTerminator()->getSuccessor(0) != PS2)) {
244aa664d9bSTom Stellard     // Check whether PS2 jumps into PS1.
245aa664d9bSTom Stellard     if (!PBI2 || !PBI2->isUnconditional() ||
246aa664d9bSTom Stellard         (PS2->getTerminator()->getSuccessor(0) != PS1))
247aa664d9bSTom Stellard       return false;
248aa664d9bSTom Stellard 
249aa664d9bSTom Stellard     // Do branch inversion.
250aa664d9bSTom Stellard     BasicBlock *CurrBlock = LastCondBlock;
251aa664d9bSTom Stellard     bool EverChanged = false;
2520cd3ec6cSJan Vesely     for (; CurrBlock != FirstCondBlock;
2530cd3ec6cSJan Vesely          CurrBlock = CurrBlock->getSinglePredecessor()) {
254c15cd009SSimon Pilgrim       auto *BI = cast<BranchInst>(CurrBlock->getTerminator());
255c15cd009SSimon Pilgrim       auto *CI = dyn_cast<CmpInst>(BI->getCondition());
2560cd3ec6cSJan Vesely       if (!CI)
2570cd3ec6cSJan Vesely         continue;
2580cd3ec6cSJan Vesely 
259aa664d9bSTom Stellard       CmpInst::Predicate Predicate = CI->getPredicate();
260cb402911SAlp Toker       // Canonicalize icmp_ne -> icmp_eq, fcmp_one -> fcmp_oeq
261aa664d9bSTom Stellard       if ((Predicate == CmpInst::ICMP_NE) || (Predicate == CmpInst::FCMP_ONE)) {
262aa664d9bSTom Stellard         CI->setPredicate(ICmpInst::getInversePredicate(Predicate));
263aa664d9bSTom Stellard         BI->swapSuccessors();
264aa664d9bSTom Stellard         EverChanged = true;
265aa664d9bSTom Stellard       }
266aa664d9bSTom Stellard     }
267aa664d9bSTom Stellard     return EverChanged;
268aa664d9bSTom Stellard   }
269aa664d9bSTom Stellard 
270aa664d9bSTom Stellard   // PS1 must have a conditional branch.
271aa664d9bSTom Stellard   if (!PBI1 || !PBI1->isUnconditional())
272aa664d9bSTom Stellard     return false;
273aa664d9bSTom Stellard 
274aa664d9bSTom Stellard   // PS2 should not contain PHI node.
275aa664d9bSTom Stellard   PHI = dyn_cast<PHINode>(PS2->begin());
276aa664d9bSTom Stellard   if (PHI)
277aa664d9bSTom Stellard     return false;
278aa664d9bSTom Stellard 
279aa664d9bSTom Stellard   // Do the transformation.
280aa664d9bSTom Stellard   BasicBlock *CB;
281c15cd009SSimon Pilgrim   BranchInst *PBI = cast<BranchInst>(FirstCondBlock->getTerminator());
282aa664d9bSTom Stellard   bool Iteration = true;
2836e931528SBenjamin Kramer   IRBuilder<>::InsertPointGuard Guard(Builder);
284aa664d9bSTom Stellard   Value *PC = PBI->getCondition();
285aa664d9bSTom Stellard 
286aa664d9bSTom Stellard   do {
287aa664d9bSTom Stellard     CB = PBI->getSuccessor(1 - Idx);
288aa664d9bSTom Stellard     // Delete the conditional branch.
289aa664d9bSTom Stellard     FirstCondBlock->getInstList().pop_back();
290aa664d9bSTom Stellard     FirstCondBlock->getInstList()
291aa664d9bSTom Stellard         .splice(FirstCondBlock->end(), CB->getInstList());
292aa664d9bSTom Stellard     PBI = cast<BranchInst>(FirstCondBlock->getTerminator());
293aa664d9bSTom Stellard     Value *CC = PBI->getCondition();
294aa664d9bSTom Stellard     // Merge conditions.
295aa664d9bSTom Stellard     Builder.SetInsertPoint(PBI);
296aa664d9bSTom Stellard     Value *NC;
297aa664d9bSTom Stellard     if (Idx == 0)
298aa664d9bSTom Stellard       // Case 2, use parallel or.
299aa664d9bSTom Stellard       NC = Builder.CreateOr(PC, CC);
300aa664d9bSTom Stellard     else
301aa664d9bSTom Stellard       // Case 1, use parallel and.
302aa664d9bSTom Stellard       NC = Builder.CreateAnd(PC, CC);
303aa664d9bSTom Stellard 
304aa664d9bSTom Stellard     PBI->replaceUsesOfWith(CC, NC);
305aa664d9bSTom Stellard     PC = NC;
306aa664d9bSTom Stellard     if (CB == LastCondBlock)
307aa664d9bSTom Stellard       Iteration = false;
308aa664d9bSTom Stellard     // Remove internal conditional branches.
309aa664d9bSTom Stellard     CB->dropAllReferences();
310aa664d9bSTom Stellard     // make CB unreachable and let downstream to delete the block.
311aa664d9bSTom Stellard     new UnreachableInst(CB->getContext(), CB);
312aa664d9bSTom Stellard   } while (Iteration);
313aa664d9bSTom Stellard 
314d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "Use parallel and/or in:\n" << *FirstCondBlock);
315aa664d9bSTom Stellard   return true;
316aa664d9bSTom Stellard }
317aa664d9bSTom Stellard 
318111ddc57SEhud Katz /// Compare blocks from two if-regions, where \param Head2 is the entry of the
319111ddc57SEhud Katz /// 2nd if-region. \param Block1 is a block in the 1st if-region to compare.
320111ddc57SEhud Katz /// \param Block2 is a block in the 2nd if-region to compare.  \returns true if
321cfb5b144SSimon Pilgrim /// Block1 and Block2 have identical instructions and do not have
322cfb5b144SSimon Pilgrim /// memory reference alias with Head2.
CompareIfRegionBlock(BasicBlock * Block1,BasicBlock * Block2,BasicBlock * Head2)323111ddc57SEhud Katz bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Block1, BasicBlock *Block2,
324111ddc57SEhud Katz                                          BasicBlock *Head2) {
325edb12a83SChandler Carruth   Instruction *PTI2 = Head2->getTerminator();
3265b4c837cSDuncan P. N. Exon Smith   Instruction *PBI2 = &Head2->front();
327aa664d9bSTom Stellard 
328aa664d9bSTom Stellard   // Check whether instructions in Block1 and Block2 are identical
329aa664d9bSTom Stellard   // and do not alias with instructions in Head2.
330aa664d9bSTom Stellard   BasicBlock::iterator iter1 = Block1->begin();
3315b4c837cSDuncan P. N. Exon Smith   BasicBlock::iterator end1 = Block1->getTerminator()->getIterator();
332aa664d9bSTom Stellard   BasicBlock::iterator iter2 = Block2->begin();
3335b4c837cSDuncan P. N. Exon Smith   BasicBlock::iterator end2 = Block2->getTerminator()->getIterator();
334aa664d9bSTom Stellard 
3355adb96ccSEugene Zelenko   while (true) {
336aa664d9bSTom Stellard     if (iter1 == end1) {
337aa664d9bSTom Stellard       if (iter2 != end2)
338aa664d9bSTom Stellard         return false;
339aa664d9bSTom Stellard       break;
340aa664d9bSTom Stellard     }
341aa664d9bSTom Stellard 
3425b4c837cSDuncan P. N. Exon Smith     if (!iter1->isIdenticalTo(&*iter2))
343aa664d9bSTom Stellard       return false;
344aa664d9bSTom Stellard 
345aa664d9bSTom Stellard     // Illegal to remove instructions with side effects except
346aa664d9bSTom Stellard     // non-volatile stores.
347aa664d9bSTom Stellard     if (iter1->mayHaveSideEffects()) {
348aa664d9bSTom Stellard       Instruction *CurI = &*iter1;
349aa664d9bSTom Stellard       StoreInst *SI = dyn_cast<StoreInst>(CurI);
350aa664d9bSTom Stellard       if (!SI || SI->isVolatile())
351aa664d9bSTom Stellard         return false;
352aa664d9bSTom Stellard     }
353aa664d9bSTom Stellard 
354aa664d9bSTom Stellard     // For simplicity and speed, data dependency check can be
355aa664d9bSTom Stellard     // avoided if read from memory doesn't exist.
356aa664d9bSTom Stellard     if (iter1->mayReadFromMemory())
357aa664d9bSTom Stellard       return false;
358aa664d9bSTom Stellard 
359aa664d9bSTom Stellard     if (iter1->mayWriteToMemory()) {
3605b4c837cSDuncan P. N. Exon Smith       for (BasicBlock::iterator BI(PBI2), BE(PTI2); BI != BE; ++BI) {
361aa664d9bSTom Stellard         if (BI->mayReadFromMemory() || BI->mayWriteToMemory()) {
362aa664d9bSTom Stellard           // Check alias with Head2.
363d0660797Sdfukalov           if (!AA || !AA->isNoAlias(&*iter1, &*BI))
364aa664d9bSTom Stellard             return false;
365aa664d9bSTom Stellard         }
366aa664d9bSTom Stellard       }
367aa664d9bSTom Stellard     }
368aa664d9bSTom Stellard     ++iter1;
369aa664d9bSTom Stellard     ++iter2;
370aa664d9bSTom Stellard   }
371aa664d9bSTom Stellard 
372aa664d9bSTom Stellard   return true;
373aa664d9bSTom Stellard }
374aa664d9bSTom Stellard 
375aa664d9bSTom Stellard /// Check whether \param BB is the merge block of a if-region.  If yes, check
376aa664d9bSTom Stellard /// whether there exists an adjacent if-region upstream, the two if-regions
377042f10ceSRobert Wilhelm /// contain identical instructions and can be legally merged.  \returns true if
378aa664d9bSTom Stellard /// the two if-regions are merged.
379aa664d9bSTom Stellard ///
380aa664d9bSTom Stellard /// From:
381aa664d9bSTom Stellard /// if (a)
382aa664d9bSTom Stellard ///   statement;
383aa664d9bSTom Stellard /// if (b)
384aa664d9bSTom Stellard ///   statement;
385aa664d9bSTom Stellard ///
386aa664d9bSTom Stellard /// To:
387aa664d9bSTom Stellard /// if (a || b)
388aa664d9bSTom Stellard ///   statement;
389111ddc57SEhud Katz ///
390111ddc57SEhud Katz ///
391111ddc57SEhud Katz /// And from:
392111ddc57SEhud Katz /// if (a)
393111ddc57SEhud Katz ///   ;
394111ddc57SEhud Katz /// else
395111ddc57SEhud Katz ///   statement;
396111ddc57SEhud Katz /// if (b)
397111ddc57SEhud Katz ///   ;
398111ddc57SEhud Katz /// else
399111ddc57SEhud Katz ///   statement;
400111ddc57SEhud Katz ///
401111ddc57SEhud Katz /// To:
402111ddc57SEhud Katz /// if (a && b)
403111ddc57SEhud Katz ///   ;
404111ddc57SEhud Katz /// else
405111ddc57SEhud Katz ///   statement;
406111ddc57SEhud Katz ///
407111ddc57SEhud Katz /// We always take the form of the first if-region. This means that if the
408111ddc57SEhud Katz /// statement in the first if-region, is in the "then-path", while in the second
409111ddc57SEhud Katz /// if-region it is in the "else-path", then we convert the second to the first
410111ddc57SEhud Katz /// form, by inverting the condition and the branch successors. The same
411111ddc57SEhud Katz /// approach goes for the opposite case.
MergeIfRegion(BasicBlock * BB,IRBuilder<> & Builder)412843fb204SJustin Bogner bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder) {
413aa664d9bSTom Stellard   BasicBlock *IfTrue2, *IfFalse2;
4142aa2fdeeSRoman Lebedev   BranchInst *DomBI2 = GetIfCondition(BB, IfTrue2, IfFalse2);
4152aa2fdeeSRoman Lebedev   if (!DomBI2)
4162aa2fdeeSRoman Lebedev     return false;
4172aa2fdeeSRoman Lebedev   Instruction *CInst2 = dyn_cast<Instruction>(DomBI2->getCondition());
418aa664d9bSTom Stellard   if (!CInst2)
419aa664d9bSTom Stellard     return false;
420aa664d9bSTom Stellard 
421aa664d9bSTom Stellard   BasicBlock *SecondEntryBlock = CInst2->getParent();
422aa664d9bSTom Stellard   if (SecondEntryBlock->hasAddressTaken())
423aa664d9bSTom Stellard     return false;
424aa664d9bSTom Stellard 
425aa664d9bSTom Stellard   BasicBlock *IfTrue1, *IfFalse1;
4262aa2fdeeSRoman Lebedev   BranchInst *DomBI1 = GetIfCondition(SecondEntryBlock, IfTrue1, IfFalse1);
4272aa2fdeeSRoman Lebedev   if (!DomBI1)
4282aa2fdeeSRoman Lebedev     return false;
4292aa2fdeeSRoman Lebedev   Instruction *CInst1 = dyn_cast<Instruction>(DomBI1->getCondition());
430aa664d9bSTom Stellard   if (!CInst1)
431aa664d9bSTom Stellard     return false;
432aa664d9bSTom Stellard 
433aa664d9bSTom Stellard   BasicBlock *FirstEntryBlock = CInst1->getParent();
434aa664d9bSTom Stellard 
435aa664d9bSTom Stellard   // Either then-path or else-path should be empty.
436111ddc57SEhud Katz   bool InvertCond2 = false;
437111ddc57SEhud Katz   BinaryOperator::BinaryOps CombineOp;
438111ddc57SEhud Katz   if (IfFalse1 == FirstEntryBlock) {
439111ddc57SEhud Katz     // The else-path is empty, so we must use "or" operation to combine the
440111ddc57SEhud Katz     // conditions.
441111ddc57SEhud Katz     CombineOp = BinaryOperator::Or;
442111ddc57SEhud Katz     if (IfFalse2 != SecondEntryBlock) {
443111ddc57SEhud Katz       if (IfTrue2 != SecondEntryBlock)
444aa664d9bSTom Stellard         return false;
445111ddc57SEhud Katz 
446111ddc57SEhud Katz       InvertCond2 = true;
447111ddc57SEhud Katz       std::swap(IfTrue2, IfFalse2);
448111ddc57SEhud Katz     }
449111ddc57SEhud Katz 
450111ddc57SEhud Katz     if (!CompareIfRegionBlock(IfTrue1, IfTrue2, SecondEntryBlock))
451111ddc57SEhud Katz       return false;
452111ddc57SEhud Katz   } else if (IfTrue1 == FirstEntryBlock) {
453111ddc57SEhud Katz     // The then-path is empty, so we must use "and" operation to combine the
454111ddc57SEhud Katz     // conditions.
455111ddc57SEhud Katz     CombineOp = BinaryOperator::And;
456111ddc57SEhud Katz     if (IfTrue2 != SecondEntryBlock) {
457111ddc57SEhud Katz       if (IfFalse2 != SecondEntryBlock)
458111ddc57SEhud Katz         return false;
459111ddc57SEhud Katz 
460111ddc57SEhud Katz       InvertCond2 = true;
461111ddc57SEhud Katz       std::swap(IfTrue2, IfFalse2);
462111ddc57SEhud Katz     }
463111ddc57SEhud Katz 
464111ddc57SEhud Katz     if (!CompareIfRegionBlock(IfFalse1, IfFalse2, SecondEntryBlock))
465111ddc57SEhud Katz       return false;
466111ddc57SEhud Katz   } else
467aa664d9bSTom Stellard     return false;
468aa664d9bSTom Stellard 
469edb12a83SChandler Carruth   Instruction *PTI2 = SecondEntryBlock->getTerminator();
4705b4c837cSDuncan P. N. Exon Smith   Instruction *PBI2 = &SecondEntryBlock->front();
471aa664d9bSTom Stellard 
472aa664d9bSTom Stellard   // Check whether \param SecondEntryBlock has side-effect and is safe to
473aa664d9bSTom Stellard   // speculate.
4745b4c837cSDuncan P. N. Exon Smith   for (BasicBlock::iterator BI(PBI2), BE(PTI2); BI != BE; ++BI) {
4755b4c837cSDuncan P. N. Exon Smith     Instruction *CI = &*BI;
476aa664d9bSTom Stellard     if (isa<PHINode>(CI) || CI->mayHaveSideEffects() ||
477aa664d9bSTom Stellard         !isSafeToSpeculativelyExecute(CI))
478aa664d9bSTom Stellard       return false;
479aa664d9bSTom Stellard   }
480aa664d9bSTom Stellard 
481aa664d9bSTom Stellard   // Merge \param SecondEntryBlock into \param FirstEntryBlock.
482aa664d9bSTom Stellard   FirstEntryBlock->getInstList().pop_back();
483aa664d9bSTom Stellard   FirstEntryBlock->getInstList()
484aa664d9bSTom Stellard       .splice(FirstEntryBlock->end(), SecondEntryBlock->getInstList());
485c15cd009SSimon Pilgrim   BranchInst *PBI = cast<BranchInst>(FirstEntryBlock->getTerminator());
4862aa2fdeeSRoman Lebedev   assert(PBI->getCondition() == CInst2);
487aa664d9bSTom Stellard   BasicBlock *SaveInsertBB = Builder.GetInsertBlock();
488aa664d9bSTom Stellard   BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();
489aa664d9bSTom Stellard   Builder.SetInsertPoint(PBI);
490111ddc57SEhud Katz   if (InvertCond2) {
491111ddc57SEhud Katz     // If this is a "cmp" instruction, only used for branching (and nowhere
492111ddc57SEhud Katz     // else), then we can simply invert the predicate.
493111ddc57SEhud Katz     auto Cmp2 = dyn_cast<CmpInst>(CInst2);
494111ddc57SEhud Katz     if (Cmp2 && Cmp2->hasOneUse())
495111ddc57SEhud Katz       Cmp2->setPredicate(Cmp2->getInversePredicate());
496111ddc57SEhud Katz     else
497111ddc57SEhud Katz       CInst2 = cast<Instruction>(Builder.CreateNot(CInst2));
498111ddc57SEhud Katz     PBI->swapSuccessors();
499111ddc57SEhud Katz   }
500111ddc57SEhud Katz   Value *NC = Builder.CreateBinOp(CombineOp, CInst1, CInst2);
5012aa2fdeeSRoman Lebedev   PBI->replaceUsesOfWith(CInst2, NC);
502aa664d9bSTom Stellard   Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);
503aa664d9bSTom Stellard 
504d98cb81cSJakub Kuderski   // Handle PHI node to replace its predecessors to FirstEntryBlock.
505d98cb81cSJakub Kuderski   for (BasicBlock *Succ : successors(PBI)) {
506d98cb81cSJakub Kuderski     for (PHINode &Phi : Succ->phis()) {
507d98cb81cSJakub Kuderski       for (unsigned i = 0, e = Phi.getNumIncomingValues(); i != e; ++i) {
508d98cb81cSJakub Kuderski         if (Phi.getIncomingBlock(i) == SecondEntryBlock)
509d98cb81cSJakub Kuderski           Phi.setIncomingBlock(i, FirstEntryBlock);
510d98cb81cSJakub Kuderski       }
511d98cb81cSJakub Kuderski     }
512d98cb81cSJakub Kuderski   }
513d98cb81cSJakub Kuderski 
514aa664d9bSTom Stellard   // Remove IfTrue1
515aa664d9bSTom Stellard   if (IfTrue1 != FirstEntryBlock) {
516aa664d9bSTom Stellard     IfTrue1->dropAllReferences();
517aa664d9bSTom Stellard     IfTrue1->eraseFromParent();
518aa664d9bSTom Stellard   }
519aa664d9bSTom Stellard 
520aa664d9bSTom Stellard   // Remove IfFalse1
521aa664d9bSTom Stellard   if (IfFalse1 != FirstEntryBlock) {
522aa664d9bSTom Stellard     IfFalse1->dropAllReferences();
523aa664d9bSTom Stellard     IfFalse1->eraseFromParent();
524aa664d9bSTom Stellard   }
525aa664d9bSTom Stellard 
526aa664d9bSTom Stellard   // Remove \param SecondEntryBlock
527aa664d9bSTom Stellard   SecondEntryBlock->dropAllReferences();
528aa664d9bSTom Stellard   SecondEntryBlock->eraseFromParent();
529d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "If conditions merged into:\n" << *FirstEntryBlock);
530aa664d9bSTom Stellard   return true;
531aa664d9bSTom Stellard }
532aa664d9bSTom Stellard 
run(BasicBlock * BB)533aa664d9bSTom Stellard bool FlattenCFGOpt::run(BasicBlock *BB) {
534aa664d9bSTom Stellard   assert(BB && BB->getParent() && "Block not embedded in function!");
535aa664d9bSTom Stellard   assert(BB->getTerminator() && "Degenerate basic block encountered!");
536aa664d9bSTom Stellard 
537aa664d9bSTom Stellard   IRBuilder<> Builder(BB);
538aa664d9bSTom Stellard 
539500929dfSDavide Italiano   if (FlattenParallelAndOr(BB, Builder) || MergeIfRegion(BB, Builder))
540aa664d9bSTom Stellard     return true;
541500929dfSDavide Italiano   return false;
542aa664d9bSTom Stellard }
543aa664d9bSTom Stellard 
544aa664d9bSTom Stellard /// FlattenCFG - This function is used to flatten a CFG.  For
545aa664d9bSTom Stellard /// example, it uses parallel-and and parallel-or mode to collapse
5465adb96ccSEugene Zelenko /// if-conditions and merge if-regions with identical statements.
FlattenCFG(BasicBlock * BB,AAResults * AA)547a53dddb3SSimon Pilgrim bool llvm::FlattenCFG(BasicBlock *BB, AAResults *AA) {
548aa664d9bSTom Stellard   return FlattenCFGOpt(AA).run(BB);
549aa664d9bSTom Stellard }
550