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