Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 1 | //===-- IPConstantPropagation.cpp - Propagate constants through calls -----===// |
Misha Brukman | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 2 | // |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
Chris Lattner | 4ee451d | 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 | fd93908 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 7 | // |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This pass implements an _extremely_ simple interprocedural constant |
| 11 | // propagation pass. It could certainly be improved in many different ways, |
| 12 | // like using a worklist. This pass makes arguments dead, but does not remove |
| 13 | // them. The existing dead argument elimination pass should be run after this |
| 14 | // to clean up the mess. |
| 15 | // |
| 16 | //===----------------------------------------------------------------------===// |
| 17 | |
Chris Lattner | 86453c5 | 2006-12-19 22:09:18 +0000 | [diff] [blame] | 18 | #define DEBUG_TYPE "ipconstprop" |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 19 | #include "llvm/Transforms/IPO.h" |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 20 | #include "llvm/Constants.h" |
| 21 | #include "llvm/Instructions.h" |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 22 | #include "llvm/Module.h" |
| 23 | #include "llvm/Pass.h" |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 24 | #include "llvm/Support/CallSite.h" |
Reid Spencer | 9133fe2 | 2007-02-05 23:32:05 +0000 | [diff] [blame] | 25 | #include "llvm/Support/Compiler.h" |
Reid Spencer | 551ccae | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/Statistic.h" |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 27 | #include "llvm/ADT/SmallVector.h" |
Chris Lattner | 1e2385b | 2003-11-21 21:54:22 +0000 | [diff] [blame] | 28 | using namespace llvm; |
Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 29 | |
Chris Lattner | 86453c5 | 2006-12-19 22:09:18 +0000 | [diff] [blame] | 30 | STATISTIC(NumArgumentsProped, "Number of args turned into constants"); |
| 31 | STATISTIC(NumReturnValProped, "Number of return values turned into constants"); |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 32 | |
Chris Lattner | 86453c5 | 2006-12-19 22:09:18 +0000 | [diff] [blame] | 33 | namespace { |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 34 | /// IPCP - The interprocedural constant propagation pass |
| 35 | /// |
Reid Spencer | 9133fe2 | 2007-02-05 23:32:05 +0000 | [diff] [blame] | 36 | struct VISIBILITY_HIDDEN IPCP : public ModulePass { |
Nick Lewycky | ecd94c8 | 2007-05-06 13:37:16 +0000 | [diff] [blame] | 37 | static char ID; // Pass identification, replacement for typeid |
Devang Patel | 794fd75 | 2007-05-01 21:15:47 +0000 | [diff] [blame] | 38 | IPCP() : ModulePass((intptr_t)&ID) {} |
| 39 | |
Chris Lattner | b12914b | 2004-09-20 04:48:05 +0000 | [diff] [blame] | 40 | bool runOnModule(Module &M); |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 41 | private: |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 42 | bool PropagateConstantsIntoArguments(Function &F); |
| 43 | bool PropagateConstantReturn(Function &F); |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 44 | }; |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 45 | } |
| 46 | |
Dan Gohman | 844731a | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 47 | char IPCP::ID = 0; |
| 48 | static RegisterPass<IPCP> |
| 49 | X("ipconstprop", "Interprocedural constant propagation"); |
| 50 | |
Chris Lattner | b12914b | 2004-09-20 04:48:05 +0000 | [diff] [blame] | 51 | ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); } |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 52 | |
Chris Lattner | b12914b | 2004-09-20 04:48:05 +0000 | [diff] [blame] | 53 | bool IPCP::runOnModule(Module &M) { |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 54 | bool Changed = false; |
Chris Lattner | 2e8dfb8 | 2003-10-27 21:09:00 +0000 | [diff] [blame] | 55 | bool LocalChange = true; |
| 56 | |
| 57 | // FIXME: instead of using smart algorithms, we just iterate until we stop |
| 58 | // making changes. |
| 59 | while (LocalChange) { |
| 60 | LocalChange = false; |
| 61 | for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) |
Reid Spencer | 5cbf985 | 2007-01-30 20:08:39 +0000 | [diff] [blame] | 62 | if (!I->isDeclaration()) { |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 63 | // Delete any klingons. |
| 64 | I->removeDeadConstantUsers(); |
| 65 | if (I->hasInternalLinkage()) |
| 66 | LocalChange |= PropagateConstantsIntoArguments(*I); |
| 67 | Changed |= PropagateConstantReturn(*I); |
| 68 | } |
Chris Lattner | 2e8dfb8 | 2003-10-27 21:09:00 +0000 | [diff] [blame] | 69 | Changed |= LocalChange; |
| 70 | } |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 71 | return Changed; |
| 72 | } |
| 73 | |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 74 | /// PropagateConstantsIntoArguments - Look at all uses of the specified |
| 75 | /// function. If all uses are direct call sites, and all pass a particular |
| 76 | /// constant in for an argument, propagate that constant in as the argument. |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 77 | /// |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 78 | bool IPCP::PropagateConstantsIntoArguments(Function &F) { |
Chris Lattner | 7f8897f | 2006-08-27 22:42:52 +0000 | [diff] [blame] | 79 | if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit. |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 80 | |
Chris Lattner | 4af6ad3 | 2008-04-23 06:16:27 +0000 | [diff] [blame] | 81 | // For each argument, keep track of its constant value and whether it is a |
| 82 | // constant or not. The bool is driven to true when found to be non-constant. |
| 83 | SmallVector<std::pair<Constant*, bool>, 16> ArgumentConstants; |
Chris Lattner | e4d5c44 | 2005-03-15 04:54:21 +0000 | [diff] [blame] | 84 | ArgumentConstants.resize(F.arg_size()); |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 85 | |
| 86 | unsigned NumNonconstant = 0; |
Chris Lattner | 4af6ad3 | 2008-04-23 06:16:27 +0000 | [diff] [blame] | 87 | for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { |
| 88 | // Used by a non-instruction, or not the callee of a function, do not |
| 89 | // transform. |
| 90 | if (UI.getOperandNo() != 0 || |
| 91 | (!isa<CallInst>(*UI) && !isa<InvokeInst>(*UI))) |
| 92 | return false; |
| 93 | |
| 94 | CallSite CS = CallSite::get(cast<Instruction>(*UI)); |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 95 | |
Chris Lattner | 4af6ad3 | 2008-04-23 06:16:27 +0000 | [diff] [blame] | 96 | // Check out all of the potentially constant arguments. Note that we don't |
| 97 | // inspect varargs here. |
| 98 | CallSite::arg_iterator AI = CS.arg_begin(); |
| 99 | Function::arg_iterator Arg = F.arg_begin(); |
| 100 | for (unsigned i = 0, e = ArgumentConstants.size(); i != e; |
| 101 | ++i, ++AI, ++Arg) { |
| 102 | |
| 103 | // If this argument is known non-constant, ignore it. |
| 104 | if (ArgumentConstants[i].second) |
| 105 | continue; |
| 106 | |
| 107 | Constant *C = dyn_cast<Constant>(*AI); |
| 108 | if (C && ArgumentConstants[i].first == 0) { |
| 109 | ArgumentConstants[i].first = C; // First constant seen. |
| 110 | } else if (C && ArgumentConstants[i].first == C) { |
| 111 | // Still the constant value we think it is. |
| 112 | } else if (*AI == &*Arg) { |
| 113 | // Ignore recursive calls passing argument down. |
| 114 | } else { |
| 115 | // Argument became non-constant. If all arguments are non-constant now, |
| 116 | // give up on this function. |
| 117 | if (++NumNonconstant == ArgumentConstants.size()) |
| 118 | return false; |
| 119 | ArgumentConstants[i].second = true; |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 120 | } |
| 121 | } |
Chris Lattner | 4af6ad3 | 2008-04-23 06:16:27 +0000 | [diff] [blame] | 122 | } |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 123 | |
| 124 | // If we got to this point, there is a constant argument! |
| 125 | assert(NumNonconstant != ArgumentConstants.size()); |
Chris Lattner | 2e8dfb8 | 2003-10-27 21:09:00 +0000 | [diff] [blame] | 126 | bool MadeChange = false; |
Chris Lattner | 4af6ad3 | 2008-04-23 06:16:27 +0000 | [diff] [blame] | 127 | Function::arg_iterator AI = F.arg_begin(); |
| 128 | for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) { |
| 129 | // Do we have a constant argument? |
| 130 | if (ArgumentConstants[i].second || AI->use_empty()) |
| 131 | continue; |
| 132 | |
| 133 | Value *V = ArgumentConstants[i].first; |
| 134 | if (V == 0) V = UndefValue::get(AI->getType()); |
| 135 | AI->replaceAllUsesWith(V); |
| 136 | ++NumArgumentsProped; |
| 137 | MadeChange = true; |
| 138 | } |
Chris Lattner | 2e8dfb8 | 2003-10-27 21:09:00 +0000 | [diff] [blame] | 139 | return MadeChange; |
Chris Lattner | d358e6f | 2003-10-23 16:52:27 +0000 | [diff] [blame] | 140 | } |
Brian Gaeke | d0fde30 | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 141 | |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 142 | |
| 143 | // Check to see if this function returns a constant. If so, replace all callers |
| 144 | // that user the return value with the returned valued. If we can replace ALL |
| 145 | // callers, |
| 146 | bool IPCP::PropagateConstantReturn(Function &F) { |
| 147 | if (F.getReturnType() == Type::VoidTy) |
| 148 | return false; // No return value. |
| 149 | |
Chris Lattner | 18d73c2 | 2008-06-09 07:58:07 +0000 | [diff] [blame^] | 150 | // If this function could be overridden later in the link stage, we can't |
| 151 | // propagate information about its results into callers. |
| 152 | if (F.hasLinkOnceLinkage() || F.hasWeakLinkage()) |
| 153 | return false; |
| 154 | |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 155 | // Check to see if this function returns a constant. |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 156 | SmallVector<Value *,4> RetVals; |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 157 | const StructType *STy = dyn_cast<StructType>(F.getReturnType()); |
| 158 | if (STy) |
Devang Patel | 488b678 | 2008-03-20 18:30:32 +0000 | [diff] [blame] | 159 | RetVals.assign(STy->getNumElements(), 0); |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 160 | else |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 161 | RetVals.push_back(0); |
| 162 | |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 163 | for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) |
Anton Korobeynikov | 07e6e56 | 2008-02-20 11:26:25 +0000 | [diff] [blame] | 164 | if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 165 | assert(RetVals.size() == RI->getNumOperands() && |
| 166 | "Invalid ReturnInst operands!"); |
| 167 | for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { |
| 168 | if (isa<UndefValue>(RI->getOperand(i))) |
| 169 | continue; // Ignore |
| 170 | Constant *C = dyn_cast<Constant>(RI->getOperand(i)); |
| 171 | if (C == 0) |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 172 | return false; // Does not return a constant. |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 173 | |
| 174 | Value *RV = RetVals[i]; |
| 175 | if (RV == 0) |
| 176 | RetVals[i] = C; |
| 177 | else if (RV != C) |
| 178 | return false; // Does not return the same constant. |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 179 | } |
Anton Korobeynikov | 07e6e56 | 2008-02-20 11:26:25 +0000 | [diff] [blame] | 180 | } |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 181 | |
Devang Patel | 488b678 | 2008-03-20 18:30:32 +0000 | [diff] [blame] | 182 | if (STy) { |
| 183 | for (unsigned i = 0, e = RetVals.size(); i < e; ++i) |
| 184 | if (RetVals[i] == 0) |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 185 | RetVals[i] = UndefValue::get(STy->getElementType(i)); |
Devang Patel | 488b678 | 2008-03-20 18:30:32 +0000 | [diff] [blame] | 186 | } else { |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 187 | assert(RetVals.size() == 1); |
| 188 | if (RetVals[0] == 0) |
| 189 | RetVals[0] = UndefValue::get(F.getReturnType()); |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 190 | } |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 191 | |
| 192 | // If we got here, the function returns a constant value. Loop over all |
| 193 | // users, replacing any uses of the return value with the returned constant. |
| 194 | bool ReplacedAllUsers = true; |
| 195 | bool MadeChange = false; |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 196 | for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { |
| 197 | // Make sure this is an invoke or call and that the use is for the callee. |
| 198 | if (!(isa<InvokeInst>(*UI) || isa<CallInst>(*UI)) || |
| 199 | UI.getOperandNo() != 0) { |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 200 | ReplacedAllUsers = false; |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 201 | continue; |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 202 | } |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 203 | |
| 204 | Instruction *Call = cast<Instruction>(*UI); |
| 205 | if (Call->use_empty()) |
| 206 | continue; |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 207 | |
Chris Lattner | e9625c6 | 2008-04-23 05:59:23 +0000 | [diff] [blame] | 208 | MadeChange = true; |
| 209 | |
| 210 | if (STy == 0) { |
| 211 | Call->replaceAllUsesWith(RetVals[0]); |
| 212 | continue; |
| 213 | } |
| 214 | |
| 215 | while (!Call->use_empty()) { |
| 216 | GetResultInst *GR = cast<GetResultInst>(Call->use_back()); |
| 217 | GR->replaceAllUsesWith(RetVals[GR->getIndex()]); |
| 218 | GR->eraseFromParent(); |
| 219 | } |
| 220 | } |
| 221 | |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 222 | // If we replace all users with the returned constant, and there can be no |
| 223 | // other callers of the function, replace the constant being returned in the |
| 224 | // function with an undef value. |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 225 | if (ReplacedAllUsers && F.hasInternalLinkage()) { |
Devang Patel | 488b678 | 2008-03-20 18:30:32 +0000 | [diff] [blame] | 226 | for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { |
| 227 | if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { |
| 228 | for (unsigned i = 0, e = RetVals.size(); i < e; ++i) { |
| 229 | Value *RetVal = RetVals[i]; |
| 230 | if (isa<UndefValue>(RetVal)) |
| 231 | continue; |
| 232 | Value *RV = UndefValue::get(RetVal->getType()); |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 233 | if (RI->getOperand(i) != RV) { |
| 234 | RI->setOperand(i, RV); |
| 235 | MadeChange = true; |
| 236 | } |
Chris Lattner | 2ffa47b | 2004-12-11 17:00:14 +0000 | [diff] [blame] | 237 | } |
Devang Patel | 488b678 | 2008-03-20 18:30:32 +0000 | [diff] [blame] | 238 | } |
Devang Patel | 7db30ba | 2008-03-11 22:24:29 +0000 | [diff] [blame] | 239 | } |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | if (MadeChange) ++NumReturnValProped; |
Chris Lattner | a990d94 | 2004-11-14 06:10:11 +0000 | [diff] [blame] | 243 | return MadeChange; |
| 244 | } |