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