llvm.org GIT mirror llvm / 520236e
[ADCE] Add code to remove dead branches Summary: This is last in of a series of patches to evolve ADCE.cpp to support removing of unnecessary control flow. This patch adds the code to update the control and data flow graphs to remove the dead control flow. Also update unit tests to test the capability to remove dead, may-be-infinite loop which is enabled by the switch -adce-remove-loops. Previous patches: D23824 [ADCE] Add handling of PHI nodes when removing control flow D23559 [ADCE] Add control dependence computation D23225 [ADCE] Modify data structures to support removing control flow D23065 [ADCE] Refactor anticipating new functionality (NFC) D23102 [ADCE] Refactoring for new functionality (NFC) Reviewers: dberlin, majnemer, nadav, mehdi_amini Subscribers: llvm-commits, david2050, freik, twoh Differential Revision: https://reviews.llvm.org/D24918 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289548 91177308-0d34-0410-b5e6-96231b3b80d8 David Callahan 2 years ago
18 changed file(s) with 333 addition(s) and 66 deletion(s). Raw diff Collapse all Expand all
1616 #include "llvm/Transforms/Scalar/ADCE.h"
1717
1818 #include "llvm/ADT/DepthFirstIterator.h"
19 #include "llvm/ADT/PostOrderIterator.h"
1920 #include "llvm/ADT/SmallPtrSet.h"
2021 #include "llvm/ADT/SmallVector.h"
2122 #include "llvm/ADT/Statistic.h"
2526 #include "llvm/IR/BasicBlock.h"
2627 #include "llvm/IR/CFG.h"
2728 #include "llvm/IR/DebugInfoMetadata.h"
29 #include "llvm/IR/IRBuilder.h"
2830 #include "llvm/IR/InstIterator.h"
2931 #include "llvm/IR/Instructions.h"
3032 #include "llvm/IR/IntrinsicInst.h"
3638 #define DEBUG_TYPE "adce"
3739
3840 STATISTIC(NumRemoved, "Number of instructions removed");
41 STATISTIC(NumBranchesRemoved, "Number of branch instructions removed");
3942
4043 // This is a tempoary option until we change the interface
4144 // to this pass based on optimization level.
4245 static cl::opt RemoveControlFlowFlag("adce-remove-control-flow",
43 cl::init(false), cl::Hidden);
46 cl::init(true), cl::Hidden);
47
48 // This option enables removing of may-be-infinite loops which have no other
49 // effect.
50 static cl::opt RemoveLoops("adce-remove-loops", cl::init(false),
51 cl::Hidden);
4452
4553 namespace {
4654 /// Information about Instructions
7179 /// Corresponding BasicBlock.
7280 BasicBlock *BB = nullptr;
7381
74 /// Cache of BB->getTerminator()
82 /// Cache of BB->getTerminator().
7583 TerminatorInst *Terminator = nullptr;
84
85 /// Post-order numbering of reverse control flow graph.
86 unsigned PostOrder;
7687 };
7788
7889 class AggressiveDeadCodeElimination {
96107 /// Set of blocks with not known to have live terminators.
97108 SmallPtrSet BlocksWithDeadTerminators;
98109
99 /// The set of blocks which we have determined are live in the
100 /// most recent iteration of propagating liveness.
110 /// The set of blocks which we have determined whose control
111 /// dependence sources must be live and which have not had
112 /// those dependences analyized.
101113 SmallPtrSet NewLiveBlocks;
102114
103115 /// Set up auxiliary data structures for Instructions and BasicBlocks and
112124 void markLiveInstructions();
113125 /// Mark an instruction as live.
114126 void markLive(Instruction *I);
115
127 /// Mark a block as live.
128 void markLive(BlockInfoType &BB);
129 void markLive(BasicBlock *BB) { markLive(BlockInfo[BB]); }
130
116131 /// Mark terminators of control predecessors of a PHI node live.
117132 void markPhiLive(PHINode *PN);
118133
128143 /// Remove instructions not marked live, return if any any instruction
129144 /// was removed.
130145 bool removeDeadInstructions();
146
147 /// Identify connected sections of the control flow grap which have
148 /// dead terminators and rewrite the control flow graph to remove them.
149 void updateDeadRegions();
150
151 /// Set the BlockInfo::PostOrder field based on a post-order
152 /// numbering of the reverse control flow graph.
153 void computeReversePostOrder();
154
155 /// Make the terminator of this block an unconditional branch to \p Target.
156 void makeUnconditional(BasicBlock *BB, BasicBlock *Target);
131157
132158 public:
133159 AggressiveDeadCodeElimination(Function &F, PostDominatorTree &PDT)
143169 }
144170
145171 static bool isUnconditionalBranch(TerminatorInst *Term) {
146 auto BR = dyn_cast(Term);
172 auto *BR = dyn_cast(Term);
147173 return BR && BR->isUnconditional();
148174 }
149175
185211 if (!RemoveControlFlowFlag)
186212 return;
187213
188 // This is temporary: will update with post order traveral to
189 // find loop bottoms
190 SmallPtrSet Seen;
191 for (auto &BB : F) {
192 Seen.insert(&BB);
193 TerminatorInst *Term = BB.getTerminator();
194 if (isLive(Term))
214 if (!RemoveLoops) {
215 // This stores state for the depth-first iterator. In addition
216 // to recording which nodes have been visited we also record whether
217 // a node is currently on the "stack" of active ancestors of the current
218 // node.
219 typedef DenseMap StatusMap ;
220 class DFState : public StatusMap {
221 public:
222 std::pair insert(BasicBlock *BB) {
223 return StatusMap::insert(std::make_pair(BB, true));
224 }
225
226 // Invoked after we have visited all children of a node.
227 void completed(BasicBlock *BB) { (*this)[BB] = false; }
228
229 // Return true if \p BB is currently on the active stack
230 // of ancestors.
231 bool onStack(BasicBlock *BB) {
232 auto Iter = find(BB);
233 return Iter != end() && Iter->second;
234 }
235 } State;
236
237 State.reserve(F.size());
238 // Iterate over blocks in depth-first pre-order and
239 // treat all edges to a block already seen as loop back edges
240 // and mark the branch live it if there is a back edge.
241 for (auto *BB: depth_first_ext(&F.getEntryBlock(), State)) {
242 TerminatorInst *Term = BB->getTerminator();
243 if (isLive(Term))
244 continue;
245
246 for (auto *Succ : successors(BB))
247 if (State.onStack(Succ)) {
248 // back edge....
249 markLive(Term);
250 break;
251 }
252 }
253 }
254
255 // Mark blocks live if there is no path from the block to the
256 // return of the function or a successor for which this is true.
257 // This protects IDFCalculator which cannot handle such blocks.
258 for (auto &BBInfoPair : BlockInfo) {
259 auto &BBInfo = BBInfoPair.second;
260 if (BBInfo.terminatorIsLive())
195261 continue;
196
197 for (auto Succ : successors(&BB))
198 if (Seen.count(Succ)) {
199 // back edge....
200 markLive(Term);
262 auto *BB = BBInfo.BB;
263 if (!PDT.getNode(BB)) {
264 markLive(BBInfo.Terminator);
265 continue;
266 }
267 for (auto *Succ : successors(BB))
268 if (!PDT.getNode(Succ)) {
269 markLive(BBInfo.Terminator);
201270 break;
202271 }
203272 }
204 // End temporary handling of loops.
205273
206274 // Mark blocks live if there is no path from the block to the
207275 // return of the function or a successor for which this is true.
217285 markLive(BBInfo.Terminator);
218286 continue;
219287 }
220 for (auto Succ : successors(BB))
288 for (auto *Succ : successors(BB))
221289 if (!PDT.getNode(Succ)) {
222290 DEBUG(dbgs() << "Successor not post-dominated by return: "
223291 << BB->getName() << '\n';);
277345 Instruction *LiveInst = Worklist.pop_back_val();
278346 DEBUG(dbgs() << "work live: "; LiveInst->dump(););
279347
280 // Collect the live debug info scopes attached to this instruction.
281 if (const DILocation *DL = LiveInst->getDebugLoc())
282 collectLiveScopes(*DL);
283
284348 for (Use &OI : LiveInst->operands())
285349 if (Instruction *Inst = dyn_cast(OI))
286350 markLive(Inst);
287
351
288352 if (auto *PN = dyn_cast(LiveInst))
289353 markPhiLive(PN);
290354 }
355
356 // After data flow liveness has been identified, examine which branch
357 // decisions are required to determine live instructions are executed.
291358 markLiveBranchesFromControlDependences();
292359
293 if (Worklist.empty()) {
294 // Temporary until we can actually delete branches.
295 SmallVector DeadTerminators;
296 for (auto *BB : BlocksWithDeadTerminators)
297 DeadTerminators.push_back(BB->getTerminator());
298 for (auto *I : DeadTerminators)
299 markLive(I);
300 assert(BlocksWithDeadTerminators.empty());
301 // End temporary.
302 }
303360 } while (!Worklist.empty());
304
305 assert(BlocksWithDeadTerminators.empty());
306361 }
307362
308363 void AggressiveDeadCodeElimination::markLive(Instruction *I) {
315370 Info.Live = true;
316371 Worklist.push_back(I);
317372
373 // Collect the live debug info scopes attached to this instruction.
374 if (const DILocation *DL = I->getDebugLoc())
375 collectLiveScopes(*DL);
376
318377 // Mark the containing block live
319378 auto &BBInfo = *Info.Block;
320 if (BBInfo.Terminator == I)
379 if (BBInfo.Terminator == I) {
321380 BlocksWithDeadTerminators.erase(BBInfo.BB);
381 // For live terminators, mark destination blocks
382 // live to preserve this control flow edges.
383 if (!BBInfo.UnconditionalBranch)
384 for (auto *BB : successors(I->getParent()))
385 markLive(BB);
386 }
387 markLive(BBInfo);
388 }
389
390 void AggressiveDeadCodeElimination::markLive(BlockInfoType &BBInfo) {
322391 if (BBInfo.Live)
323392 return;
324
325393 DEBUG(dbgs() << "mark block live: " << BBInfo.BB->getName() << '\n');
326394 BBInfo.Live = true;
327395 if (!BBInfo.CFLive) {
331399
332400 // Mark unconditional branches at the end of live
333401 // blocks as live since there is no work to do for them later
334 if (BBInfo.UnconditionalBranch && I != BBInfo.Terminator)
402 if (BBInfo.UnconditionalBranch)
335403 markLive(BBInfo.Terminator);
336404 }
337405
407475 NewLiveBlocks.clear();
408476
409477 // Dead terminators which control live blocks are now marked live.
410 for (auto BB : IDFBlocks) {
478 for (auto *BB : IDFBlocks) {
411479 DEBUG(dbgs() << "live control in: " << BB->getName() << '\n');
412480 markLive(BB->getTerminator());
413481 }
420488 //===----------------------------------------------------------------------===//
421489 bool AggressiveDeadCodeElimination::removeDeadInstructions() {
422490
423 // The inverse of the live set is the dead set. These are those instructions
424 // which have no side effects and do not influence the control flow or return
425 // value of the function, and may therefore be deleted safely.
426 // NOTE: We reuse the Worklist vector here for memory efficiency.
427 for (Instruction &I : instructions(F)) {
428 // Check if the instruction is alive.
429 if (isLive(&I))
430 continue;
431
432 assert(!I.isTerminator() && "NYI: Removing Control Flow");
433
434 if (auto *DII = dyn_cast(&I)) {
435 // Check if the scope of this variable location is alive.
436 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
491 // Updates control and dataflow around dead blocks
492 updateDeadRegions();
493
494 DEBUG({
495 for (Instruction &I : instructions(F)) {
496 // Check if the instruction is alive.
497 if (isLive(&I))
437498 continue;
438499
439 // Fallthrough and drop the intrinsic.
440 DEBUG({
500 if (auto *DII = dyn_cast(&I)) {
501 // Check if the scope of this variable location is alive.
502 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
503 continue;
504
441505 // If intrinsic is pointing at a live SSA value, there may be an
442506 // earlier optimization bug: if we know the location of the variable,
443507 // why isn't the scope of the location alive?
445509 if (Instruction *II = dyn_cast(V))
446510 if (isLive(II))
447511 dbgs() << "Dropping debug info for " << *DII << "\n";
448 });
512 }
513 }
514 });
515
516 // The inverse of the live set is the dead set. These are those instructions
517 // that have no side effects and do not influence the control flow or return
518 // value of the function, and may therefore be deleted safely.
519 // NOTE: We reuse the Worklist vector here for memory efficiency.
520 for (Instruction &I : instructions(F)) {
521 // Check if the instruction is alive.
522 if (isLive(&I))
523 continue;
524
525 if (auto *DII = dyn_cast(&I)) {
526 // Check if the scope of this variable location is alive.
527 if (AliveScopes.count(DII->getDebugLoc()->getScope()))
528 continue;
529
530 // Fallthrough and drop the intrinsic.
449531 }
450532
451533 // Prepare to delete.
459541 }
460542
461543 return !Worklist.empty();
544 }
545
546 // A dead region is the set of dead blocks with a common live post-dominator.
547 void AggressiveDeadCodeElimination::updateDeadRegions() {
548
549 DEBUG({
550 dbgs() << "final dead terminator blocks: " << '\n';
551 for (auto *BB : BlocksWithDeadTerminators)
552 dbgs() << '\t' << BB->getName()
553 << (BlockInfo[BB].Live ? " LIVE\n" : "\n");
554 });
555
556 // Don't compute the post ordering unless we needed it.
557 bool HavePostOrder = false;
558
559 for (auto *BB : BlocksWithDeadTerminators) {
560 auto &Info = BlockInfo[BB];
561 if (Info.UnconditionalBranch) {
562 InstInfo[Info.Terminator].Live = true;
563 continue;
564 }
565
566 if (!HavePostOrder) {
567 computeReversePostOrder();
568 HavePostOrder = true;
569 }
570
571 // Add an unconditional branch to the successor closest to the
572 // end of the function which insures a path to the exit for each
573 // live edge.
574 BlockInfoType *PreferredSucc = nullptr;
575 for (auto *Succ : successors(BB)) {
576 auto *Info = &BlockInfo[Succ];
577 if (!PreferredSucc || PreferredSucc->PostOrder < Info->PostOrder)
578 PreferredSucc = Info;
579 }
580 assert((PreferredSucc && PreferredSucc->PostOrder > 0) &&
581 "Failed to find safe successor for dead branc");
582 bool First = true;
583 for (auto *Succ : successors(BB)) {
584 if (!First || Succ != PreferredSucc->BB)
585 Succ->removePredecessor(BB);
586 else
587 First = false;
588 }
589 makeUnconditional(BB, PreferredSucc->BB);
590 NumBranchesRemoved += 1;
591 }
592 }
593
594 // reverse top-sort order
595 void AggressiveDeadCodeElimination::computeReversePostOrder() {
596
597 // This provides a post-order numbering of the reverse conrtol flow graph
598 // Note that it is incomplete in the presence of infinite loops but we don't
599 // need numbers blocks which don't reach the end of the functions since
600 // all branches in those blocks are forced live.
601
602 // For each block without successors, extend the DFS from the bloack
603 // backward through the graph
604 SmallPtrSet Visited;
605 unsigned PostOrder = 0;
606 for (auto &BB : F) {
607 if (succ_begin(&BB) != succ_end(&BB))
608 continue;
609 for (BasicBlock *Block : inverse_post_order_ext(&BB,Visited))
610 BlockInfo[Block].PostOrder = PostOrder++;
611 }
612 }
613
614 void AggressiveDeadCodeElimination::makeUnconditional(BasicBlock *BB,
615 BasicBlock *Target) {
616 TerminatorInst *PredTerm = BB->getTerminator();
617 // Collect the live debug info scopes attached to this instruction.
618 if (const DILocation *DL = PredTerm->getDebugLoc())
619 collectLiveScopes(*DL);
620
621 // Just mark live an existing unconditional branch
622 if (isUnconditionalBranch(PredTerm)) {
623 PredTerm->setSuccessor(0, Target);
624 InstInfo[PredTerm].Live = true;
625 return;
626 }
627 DEBUG(dbgs() << "making unconditional " << BB->getName() << '\n');
628 NumBranchesRemoved += 1;
629 IRBuilder<> Builder(PredTerm);
630 auto *NewTerm = Builder.CreateBr(Target);
631 InstInfo[NewTerm].Live = true;
632 if (const DILocation *DL = PredTerm->getDebugLoc())
633 NewTerm->setDebugLoc(DL);
462634 }
463635
464636 //===----------------------------------------------------------------------===//
493665
494666 void getAnalysisUsage(AnalysisUsage &AU) const override {
495667 AU.addRequired();
496 AU.setPreservesCFG(); // TODO -- will remove when we start removing branches
668 if (!RemoveControlFlowFlag)
669 AU.setPreservesCFG();
497670 AU.addPreserved();
498671 }
499672 };
33 ; removed even though there were uses still around. Now the uses are filled
44 ; in with a dummy value before the PHI is deleted.
55 ;
6 ; RUN: opt < %s -adce
6 ; RUN: opt < %s -S -adce | grep bb1
7 ; RUN: opt < %s -S -adce -adce-remove-loops | FileCheck %s
78
89 %node_t = type { double*, %node_t*, %node_t**, double**, double*, i32, i32 }
910
1617 bb1: ; preds = %bb0
1718 %reg107 = load %node_t*, %node_t** %nodelist.upgrd.1 ; <%node_t*> [#uses=2]
1819 %cond211 = icmp eq %node_t* %reg107, null ; [#uses=1]
20 ; CHECK: br label %bb3
1921 br i1 %cond211, label %bb3, label %bb2
2022
2123 bb2: ; preds = %bb2, %bb1
2325 %reg212 = getelementptr %node_t, %node_t* %reg109, i64 0, i32 1 ; <%node_t**> [#uses=1]
2426 %reg110 = load %node_t*, %node_t** %reg212 ; <%node_t*> [#uses=2]
2527 %cond213 = icmp ne %node_t* %reg110, null ; [#uses=1]
28 ; CHECK: br label %bb3
2629 br i1 %cond213, label %bb2, label %bb3
2730
2831 bb3: ; preds = %bb2, %bb1
0 ; This testcase is a distilled form of: 2002-05-28-Crash.ll
11
22 ; RUN: opt < %s -adce
3 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
34
45 define float @test(i32 %i) {
56 %F = sitofp i32 %i to float ; [#uses=1]
89
910 Loop: ; preds = %Loop, %0
1011 %B = icmp ne i32 %I, 0 ; [#uses=1]
12 ; CHECK: br label %Out
1113 br i1 %B, label %Out, label %Loop
1214
1315 Out: ; preds = %Loop
1111 ;}
1212 ;
1313 ; RUN: opt < %s -adce
14 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
1415
1516 define i32 @rx_bitset_empty(i32 %size, i32* %set) {
1617 bb1:
2728 %reg124 = getelementptr i32, i32* %set, i64 %reg114-idxcast-offset.upgrd.1 ; [#uses=1]
2829 %reg125 = load i32, i32* %reg124 ; [#uses=1]
2930 %cond232 = icmp ne i32 %reg125, 0 ; [#uses=1]
31 ; CHECK: br label %bb3
3032 br i1 %cond232, label %bb3, label %bb2
3133
3234 bb2: ; preds = %bb2, %bb1
22 ; block in this function, it would work fine, but that would be the part we
33 ; have to fix now, wouldn't it....
44 ;
5 ; RUN: opt < %s -adce
5 ; RUN: opt < %s -adce -S | FileCheck %s
66
77 define void @foo(i8* %reg5481) {
88 %cast611 = bitcast i8* %reg5481 to i8** ; [#uses=1]
99 %reg162 = load i8*, i8** %cast611 ; [#uses=1]
10 ; CHECK-NOT: ptrtoint
1011 ptrtoint i8* %reg162 to i32 ; :1 [#uses=0]
1112 ret void
1213 }
0 ; This testcase was extracted from the gzip SPEC benchmark
11 ;
2 ; RUN: opt < %s -adce
2 ; RUN: opt < %s -adce | FileCheck %s
33
44 @bk = external global i32 ; [#uses=2]
55 @hufts = external global i32 ; [#uses=1]
1515 bb3: ; preds = %bb2
1616 br label %UnifiedExitNode
1717
18 ; CHECK-NOT: bb4:
19 ; CHECK-NOT: bb5:
1820 bb4: ; preds = %bb2
1921 %reg117 = load i32, i32* @hufts ; [#uses=2]
2022 %cond241 = icmp ule i32 %reg117, %reg128 ; [#uses=1]
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -disable-output -adce-remove-loops
12
23 define void @test() {
34 br label %BB3
0 ; Testcase reduced from 197.parser by bugpoint
11 ; RUN: opt < %s -adce
2 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
23
34 define void @conjunction_prune() {
45 ;
67
78 bb19: ; preds = %bb23, %bb22, %0
89 %reg205 = phi i8* [ null, %bb22 ], [ null, %bb23 ], [ null, %0 ] ; [#uses=1]
10 ; CHECK: br label %bb22
911 br i1 false, label %bb21, label %bb22
1012
1113 bb21: ; preds = %bb19
1214 %cast455 = bitcast i8* %reg205 to i8** ; [#uses=0]
15 ; CHECK: br label %bb22
1316 br label %bb22
1417
1518 bb22: ; preds = %bb21, %bb19
19 ; CHECK: br label %bb23
1620 br i1 false, label %bb19, label %bb23
1721
1822 bb23: ; preds = %bb22
23 ; CHECK: br label %bb28
1924 br i1 false, label %bb19, label %bb28
2025
2126 bb28: ; preds = %bb23
11 ; entries for it's postdominator. But I think this can only happen when the
22 ; PHI node is dead, so we just avoid patching up dead PHI nodes.
33
4 ; RUN: opt < %s -adce
4 ; RUN: opt < %s -adce -S | FileCheck %s
5 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
56
67 target datalayout = "e-p:32:32"
78
1415 br i1 false, label %no_exit, label %return
1516
1617 no_exit: ; preds = %loopentry
18 ; CHECK: br label %then
1719 br i1 false, label %then, label %else
1820
1921 then: ; preds = %no_exit
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -adce-remove-loops -disable-output
12
23 @G = external global i32* ; [#uses=1]
34
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -adce-remove-loops=true -disable-output
2
13 target datalayout = "e-p:32:32"
24 %struct..CppObjTypeDesc = type { i32, i16, i16 }
35 %struct..TypeToken = type { i32, i16, i16 }
2931 br i1 false, label %no_exit.1, label %loopentry.0
3032
3133 no_exit.1: ; preds = %loopentry.1
34 ; CHECK: switch
3235 switch i32 0, label %label.17 [
3336 i32 2, label %label.11
3437 i32 19, label %label.10
None ; RUN: opt < %s -adce -simplifycfg -S | not grep then:
0 ; RUN: opt < %s -adce -S | FileCheck %s
1 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
12
23 define void @dead_test8(i32* %data.1, i32 %idx.1) {
34 entry:
1617 %i.0 = phi i32 [ %inc.1, %endif ], [ 0, %no_exit.preheader ] ; [#uses=1]
1718 %tmp.12 = load i32, i32* %tmp.11 ; [#uses=1]
1819 %tmp.14 = sub i32 0, %tmp.12 ; [#uses=1]
20 ; CHECK-NOT: %tmp.161
1921 %tmp.161 = icmp ne i32 %k.1, %tmp.14 ; [#uses=1]
22 ; CHECK: br label %then
2023 br i1 %tmp.161, label %then, label %else
2124
2225 then: ; preds = %no_exit
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -adce-remove-loops -disable-output
12
23 define i32 @main() {
34 br label %loop
0 ; RUN: opt < %s -adce -simplifycfg -S | grep call
1 ; RUN: opt < %s -adce -adce-remove-loops -simplifycfg -S | grep call
2
13 declare void @exit(i32)
24
35 define i32 @main(i32 %argc) {
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -adce-remove-loops -disable-output
12
23 define void @test() {
34 entry:
0 ; RUN: opt < %s -sroa -adce -adce-remove-loops -S | FileCheck %s
1 ; ModuleID = 'test1.bc'
2 source_filename = "test1.c"
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
5
6 ; Function Attrs: nounwind uwtable
7 define i32 @foo(i32, i32, i32) #0 {
8 %4 = alloca i32, align 4
9 %5 = alloca i32, align 4
10 %6 = alloca i32, align 4
11 %7 = alloca i32, align 4
12 %8 = alloca i32, align 4
13 store i32 %0, i32* %4, align 4
14 store i32 %1, i32* %5, align 4
15 store i32 %2, i32* %6, align 4
16 store i32 0, i32* %7, align 4
17 %9 = load i32, i32* %5, align 4
18 %I10 = icmp ne i32 %9, 0
19 br i1 %I10, label %B11, label %B21
20
21 B11:
22 store i32 0, i32* %8, align 4
23 br label %B12
24
25 B12:
26 %I13 = load i32, i32* %8, align 4
27 %I14 = load i32, i32* %6, align 4
28 %I15 = icmp slt i32 %I13, %I14
29 ; CHECK: br label %B20
30 br i1 %I15, label %B16, label %B20
31
32 B16:
33 br label %B17
34
35 B17:
36 %I18 = load i32, i32* %8, align 4
37 %I19 = add nsw i32 %I18, 1
38 store i32 %I19, i32* %8, align 4
39 br label %B12
40
41 B20:
42 store i32 1, i32* %7, align 4
43 br label %B21
44
45 B21:
46 %I22 = load i32, i32* %7, align 4
47 ret i32 %I22
48 }
49
50 attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
51
52 !llvm.ident = !{!0}
53
54 !0 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git 5864a13abf4490e76ae2eb0896198e1305927df2)"}
None ; RUN: opt < %s -adce -simplifycfg | llvm-dis
0 ; RUN: opt < %s -adce -S | FileCheck %s
1 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
2
13 %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 }
24 %spec_fd_t = type { i32, i32, i32, i8* }
35 @__iob = external global [20 x %FILE] ; <[20 x %FILE]*> [#uses=1]
2325 define i32 @spec_getc(i32 %fd) {
2426 %reg109 = load i32, i32* @dbglvl ; [#uses=1]
2527 %cond266 = icmp sle i32 %reg109, 4 ; [#uses=1]
28 ; CHECKL br label %bb3
2629 br i1 %cond266, label %bb3, label %bb2
2730
2831 bb2: ; preds = %0
5457 bb6: ; preds = %bb5
5558 %reg134 = load i32, i32* @dbglvl ; [#uses=1]
5659 %cond271 = icmp sle i32 %reg134, 4 ; [#uses=1]
60 ; CHECK: br label %bb8
5761 br i1 %cond271, label %bb8, label %bb7
5862
5963 bb7: ; preds = %bb6
7680 store i32 %reg157, i32* %idx5
7781 %reg163 = load i32, i32* @dbglvl ; [#uses=1]
7882 %cond272 = icmp sle i32 %reg163, 4 ; [#uses=1]
83 ; CHECK: br label %bb11
7984 br i1 %cond272, label %bb11, label %bb10
8085
8186 bb10: ; preds = %bb9
None ; RUN: opt < %s -adce -simplifycfg | llvm-dis
0 ; RUN: opt < %s -adce -disable-output
1 ; RUN: opt < %s -adce -adce-remove-loops -S | FileCheck %s
2
13 %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 }
24 %spec_fd_t = type { i32, i32, i32, i8* }
35 @__iob = external global [20 x %FILE] ; <[20 x %FILE]*> [#uses=1]
2325 define i32 @spec_getc(i32 %fd) {
2426 %reg109 = load i32, i32* @dbglvl ; [#uses=1]
2527 %cond266 = icmp sle i32 %reg109, 4 ; [#uses=1]
28 ; CHECK: br label %bb3
2629 br i1 %cond266, label %bb3, label %bb2
2730
2831 bb2: ; preds = %0
5457 bb6: ; preds = %bb5
5558 %reg134 = load i32, i32* @dbglvl ; [#uses=1]
5659 %cond271 = icmp sle i32 %reg134, 4 ; [#uses=1]
60 ; CHECK: br label %bb8
5761 br i1 %cond271, label %bb8, label %bb7
5862
5963 bb7: ; preds = %bb6
7680 store i32 %reg157, i32* %idx5
7781 %reg163 = load i32, i32* @dbglvl ; [#uses=1]
7882 %cond272 = icmp sle i32 %reg163, 4 ; [#uses=1]
83 ; CHECK: br label %bb11
7984 br i1 %cond272, label %bb11, label %bb10
8085
8186 bb10: ; preds = %bb9