IPConstantPropagation.cpp revision 2e56dd82b3b3ab9dde8cc55c06df78cec4dbd3b7
1//===-- IPConstantPropagation.cpp - Propagate constants through calls -----===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 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 18#include "llvm/Transforms/IPO.h" 19#include "llvm/Module.h" 20#include "llvm/Pass.h" 21#include "llvm/Constants.h" 22#include "llvm/Support/CallSite.h" 23#include "Support/Statistic.h" 24 25namespace { 26 Statistic<> NumArgumentsProped("ipconstprop", 27 "Number of args turned into constants"); 28 29 /// IPCP - The interprocedural constant propagation pass 30 /// 31 struct IPCP : public Pass { 32 bool run(Module &M); 33 private: 34 bool processFunction(Function &F); 35 }; 36 RegisterOpt<IPCP> X("ipconstprop", "Interprocedural constant propagation"); 37} 38 39Pass *createIPConstantPropagationPass() { return new IPCP(); } 40 41bool IPCP::run(Module &M) { 42 bool Changed = false; 43 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 44 if (!I->isExternal() && I->hasInternalLinkage()) 45 Changed |= processFunction(*I); 46 return Changed; 47} 48 49/// processFunction - Look at all uses of the specified function. If all uses 50/// are direct call sites, and all pass a particular constant in for an 51/// argument, propagate that constant in as the argument. 52/// 53bool IPCP::processFunction(Function &F) { 54 if (F.aempty() || F.use_empty()) return false; // No arguments? Early exit. 55 56 std::vector<std::pair<Constant*, bool> > ArgumentConstants; 57 ArgumentConstants.resize(F.asize()); 58 59 unsigned NumNonconstant = 0; 60 61 for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) 62 if (!isa<Instruction>(*I)) 63 return false; // Used by a non-instruction, do not transform 64 else { 65 CallSite CS = CallSite::get(cast<Instruction>(*I)); 66 if (CS.getInstruction() == 0 || 67 CS.getCalledFunction() != &F) 68 return false; // Not a direct call site? 69 70 // Check out all of the potentially constant arguments 71 CallSite::arg_iterator AI = CS.arg_begin(); 72 for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) { 73 if (*AI == &F) return false; // Passes the function into itself 74 75 if (!ArgumentConstants[i].second) { 76 if (isa<Constant>(*AI) || isa<GlobalValue>(*AI)) { 77 Constant *C = dyn_cast<Constant>(*AI); 78 if (!C) C = ConstantPointerRef::get(cast<GlobalValue>(*AI)); 79 80 if (!ArgumentConstants[i].first) 81 ArgumentConstants[i].first = C; 82 else if (ArgumentConstants[i].first != C) { 83 // Became non-constant 84 ArgumentConstants[i].second = true; 85 ++NumNonconstant; 86 if (NumNonconstant == ArgumentConstants.size()) return false; 87 } 88 } else { 89 // This is not a constant argument. Mark the argument as 90 // non-constant. 91 ArgumentConstants[i].second = true; 92 ++NumNonconstant; 93 if (NumNonconstant == ArgumentConstants.size()) return false; 94 } 95 } 96 } 97 } 98 99 // If we got to this point, there is a constant argument! 100 assert(NumNonconstant != ArgumentConstants.size()); 101 Function::aiterator AI = F.abegin(); 102 for (unsigned i = 0, e = ArgumentConstants.size(); i != e; ++i, ++AI) 103 // Do we have a constant argument!? 104 if (!ArgumentConstants[i].second) { 105 assert(ArgumentConstants[i].first && "Unknown constant value!"); 106 Value *V = ArgumentConstants[i].first; 107 if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V)) 108 V = CPR->getValue(); 109 AI->replaceAllUsesWith(V); 110 ++NumArgumentsProped; 111 } 112 return true; 113} 114