| Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 1 | //===- UnifyFunctionExitNodes.cpp - Make all functions have a single exit -===// | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 2 | // | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 7 | // | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 9 | // | 
| Chris Lattner | 64d1334 | 2002-05-07 18:51:25 +0000 | [diff] [blame] | 10 | // This pass is used to ensure that functions have at most one return | 
|  | 11 | // instruction in them.  Additionally, it keeps track of which node is the new | 
|  | 12 | // exit node of the CFG.  If there are no exit nodes in the CFG, the getExitNode | 
|  | 13 | // method will return a null pointer. | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 14 | // | 
|  | 15 | //===----------------------------------------------------------------------===// | 
|  | 16 |  | 
| Chris Lattner | 15435fd | 2002-05-07 19:18:48 +0000 | [diff] [blame] | 17 | #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" | 
| Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 18 | #include "llvm/IR/BasicBlock.h" | 
|  | 19 | #include "llvm/IR/Function.h" | 
|  | 20 | #include "llvm/IR/Instructions.h" | 
|  | 21 | #include "llvm/IR/Type.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 22 | #include "llvm/Transforms/Scalar.h" | 
| Chris Lattner | a296000 | 2003-11-21 16:52:05 +0000 | [diff] [blame] | 23 | using namespace llvm; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 24 |  | 
| Devang Patel | 8c78a0b | 2007-05-03 01:11:54 +0000 | [diff] [blame] | 25 | char UnifyFunctionExitNodes::ID = 0; | 
| Owen Anderson | a57b97e | 2010-07-21 22:09:45 +0000 | [diff] [blame] | 26 | INITIALIZE_PASS(UnifyFunctionExitNodes, "mergereturn", | 
| Owen Anderson | df7a4f2 | 2010-10-07 22:25:06 +0000 | [diff] [blame] | 27 | "Unify function exit nodes", false, false) | 
| Chris Lattner | ccf571a | 2002-01-31 00:42:27 +0000 | [diff] [blame] | 28 |  | 
| Chris Lattner | a296000 | 2003-11-21 16:52:05 +0000 | [diff] [blame] | 29 | Pass *llvm::createUnifyFunctionExitNodesPass() { | 
| Chris Lattner | f941396 | 2003-09-10 20:34:51 +0000 | [diff] [blame] | 30 | return new UnifyFunctionExitNodes(); | 
|  | 31 | } | 
|  | 32 |  | 
| Chris Lattner | 07f7e5d | 2003-03-31 17:30:25 +0000 | [diff] [blame] | 33 | void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{ | 
|  | 34 | // We preserve the non-critical-edgeness property | 
|  | 35 | AU.addPreservedID(BreakCriticalEdgesID); | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 36 | // This is a cluster of orthogonal Transforms | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 37 | AU.addPreservedID(LowerSwitchID); | 
| Chris Lattner | 07f7e5d | 2003-03-31 17:30:25 +0000 | [diff] [blame] | 38 | } | 
|  | 39 |  | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 40 | // UnifyAllExitNodes - Unify all exit nodes of the CFG by creating a new | 
|  | 41 | // BasicBlock, and converting all returns to unconditional branches to this | 
|  | 42 | // new basic block.  The singular exit node is returned. | 
|  | 43 | // | 
| Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 44 | // If there are no return stmts in the Function, a null pointer is returned. | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 45 | // | 
| Chris Lattner | fda72b1 | 2002-06-25 16:12:52 +0000 | [diff] [blame] | 46 | bool UnifyFunctionExitNodes::runOnFunction(Function &F) { | 
| Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 47 | // Loop over all of the blocks in a function, tracking all of the blocks that | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 48 | // return. | 
|  | 49 | // | 
| Chris Lattner | 8d0a71a | 2003-05-22 22:00:07 +0000 | [diff] [blame] | 50 | std::vector<BasicBlock*> ReturningBlocks; | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 51 | std::vector<BasicBlock*> UnreachableBlocks; | 
| Duncan P. N. Exon Smith | 5b4c837 | 2015-10-13 02:39:05 +0000 | [diff] [blame] | 52 | for (BasicBlock &I : F) | 
|  | 53 | if (isa<ReturnInst>(I.getTerminator())) | 
|  | 54 | ReturningBlocks.push_back(&I); | 
|  | 55 | else if (isa<UnreachableInst>(I.getTerminator())) | 
|  | 56 | UnreachableBlocks.push_back(&I); | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 57 |  | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 58 | // Then unreachable blocks. | 
|  | 59 | if (UnreachableBlocks.empty()) { | 
| Craig Topper | f40110f | 2014-04-25 05:29:35 +0000 | [diff] [blame] | 60 | UnreachableBlock = nullptr; | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 61 | } else if (UnreachableBlocks.size() == 1) { | 
|  | 62 | UnreachableBlock = UnreachableBlocks.front(); | 
|  | 63 | } else { | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 64 | UnreachableBlock = BasicBlock::Create(F.getContext(), | 
|  | 65 | "UnifiedUnreachableBlock", &F); | 
|  | 66 | new UnreachableInst(F.getContext(), UnreachableBlock); | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 67 |  | 
| Benjamin Kramer | 135f735 | 2016-06-26 12:28:59 +0000 | [diff] [blame] | 68 | for (BasicBlock *BB : UnreachableBlocks) { | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 69 | BB->getInstList().pop_back();  // Remove the unreachable inst. | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 70 | BranchInst::Create(UnreachableBlock, BB); | 
| Chris Lattner | 98e5414 | 2004-10-16 18:21:33 +0000 | [diff] [blame] | 71 | } | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 | // Now handle return blocks. | 
| Chris Lattner | 86595ae | 2002-02-01 04:53:48 +0000 | [diff] [blame] | 75 | if (ReturningBlocks.empty()) { | 
| Craig Topper | f40110f | 2014-04-25 05:29:35 +0000 | [diff] [blame] | 76 | ReturnBlock = nullptr; | 
| Chris Lattner | 64d1334 | 2002-05-07 18:51:25 +0000 | [diff] [blame] | 77 | return false;                          // No blocks return | 
| Chris Lattner | f9f2896 | 2002-01-31 01:12:06 +0000 | [diff] [blame] | 78 | } else if (ReturningBlocks.size() == 1) { | 
| Chris Lattner | f941396 | 2003-09-10 20:34:51 +0000 | [diff] [blame] | 79 | ReturnBlock = ReturningBlocks.front(); // Already has a single return block | 
| Chris Lattner | f9f2896 | 2002-01-31 01:12:06 +0000 | [diff] [blame] | 80 | return false; | 
|  | 81 | } | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 82 |  | 
| Chris Lattner | 62b7fd1 | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 83 | // Otherwise, we need to insert a new basic block into the function, add a PHI | 
| Devang Patel | 3b1c95f | 2008-03-05 21:50:24 +0000 | [diff] [blame] | 84 | // nodes (if the function returns values), and convert all of the return | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 85 | // instructions into unconditional branches. | 
|  | 86 | // | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 87 | BasicBlock *NewRetBlock = BasicBlock::Create(F.getContext(), | 
|  | 88 | "UnifiedReturnBlock", &F); | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 89 |  | 
| Craig Topper | f40110f | 2014-04-25 05:29:35 +0000 | [diff] [blame] | 90 | PHINode *PN = nullptr; | 
| Benjamin Kramer | ccce8ba | 2010-01-05 13:12:22 +0000 | [diff] [blame] | 91 | if (F.getReturnType()->isVoidTy()) { | 
| Craig Topper | f40110f | 2014-04-25 05:29:35 +0000 | [diff] [blame] | 92 | ReturnInst::Create(F.getContext(), nullptr, NewRetBlock); | 
| Dan Gohman | fa1211f | 2008-07-23 00:34:11 +0000 | [diff] [blame] | 93 | } else { | 
| Devang Patel | 3b1c95f | 2008-03-05 21:50:24 +0000 | [diff] [blame] | 94 | // If the function doesn't return void... add a PHI node to the block... | 
| Jay Foad | 5213134 | 2011-03-30 11:28:46 +0000 | [diff] [blame] | 95 | PN = PHINode::Create(F.getReturnType(), ReturningBlocks.size(), | 
|  | 96 | "UnifiedRetVal"); | 
| Devang Patel | 3b1c95f | 2008-03-05 21:50:24 +0000 | [diff] [blame] | 97 | NewRetBlock->getInstList().push_back(PN); | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 98 | ReturnInst::Create(F.getContext(), PN, NewRetBlock); | 
| Devang Patel | 3b1c95f | 2008-03-05 21:50:24 +0000 | [diff] [blame] | 99 | } | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 100 |  | 
|  | 101 | // Loop over all of the blocks, replacing the return instruction with an | 
|  | 102 | // unconditional branch. | 
|  | 103 | // | 
| Benjamin Kramer | 135f735 | 2016-06-26 12:28:59 +0000 | [diff] [blame] | 104 | for (BasicBlock *BB : ReturningBlocks) { | 
| Chris Lattner | 07f7e5d | 2003-03-31 17:30:25 +0000 | [diff] [blame] | 105 | // Add an incoming element to the PHI node for every return instruction that | 
|  | 106 | // is merging into this new block... | 
| Dan Gohman | fa1211f | 2008-07-23 00:34:11 +0000 | [diff] [blame] | 107 | if (PN) | 
|  | 108 | PN->addIncoming(BB->getTerminator()->getOperand(0), BB); | 
| Chris Lattner | 07f7e5d | 2003-03-31 17:30:25 +0000 | [diff] [blame] | 109 |  | 
|  | 110 | BB->getInstList().pop_back();  // Remove the return insn | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 111 | BranchInst::Create(NewRetBlock, BB); | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 112 | } | 
| Chris Lattner | f941396 | 2003-09-10 20:34:51 +0000 | [diff] [blame] | 113 | ReturnBlock = NewRetBlock; | 
| Chris Lattner | f9f2896 | 2002-01-31 01:12:06 +0000 | [diff] [blame] | 114 | return true; | 
| Chris Lattner | 29aae15 | 2001-07-06 16:58:36 +0000 | [diff] [blame] | 115 | } |