diff options
Diffstat (limited to 'lib/Transforms/IPO/IPConstantPropagation.cpp')
-rw-r--r-- | lib/Transforms/IPO/IPConstantPropagation.cpp | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/lib/Transforms/IPO/IPConstantPropagation.cpp b/lib/Transforms/IPO/IPConstantPropagation.cpp index af541d155254..916135e33cd5 100644 --- a/lib/Transforms/IPO/IPConstantPropagation.cpp +++ b/lib/Transforms/IPO/IPConstantPropagation.cpp @@ -41,44 +41,14 @@ namespace { } bool runOnModule(Module &M) override; - private: - bool PropagateConstantsIntoArguments(Function &F); - bool PropagateConstantReturn(Function &F); }; } -char IPCP::ID = 0; -INITIALIZE_PASS(IPCP, "ipconstprop", - "Interprocedural constant propagation", false, false) - -ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); } - -bool IPCP::runOnModule(Module &M) { - bool Changed = false; - bool LocalChange = true; - - // FIXME: instead of using smart algorithms, we just iterate until we stop - // making changes. - while (LocalChange) { - LocalChange = false; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration()) { - // Delete any klingons. - I->removeDeadConstantUsers(); - if (I->hasLocalLinkage()) - LocalChange |= PropagateConstantsIntoArguments(*I); - Changed |= PropagateConstantReturn(*I); - } - Changed |= LocalChange; - } - return Changed; -} - /// PropagateConstantsIntoArguments - Look at all uses of the specified /// function. If all uses are direct call sites, and all pass a particular /// constant in for an argument, propagate that constant in as the argument. /// -bool IPCP::PropagateConstantsIntoArguments(Function &F) { +static bool PropagateConstantsIntoArguments(Function &F) { if (F.arg_empty() || F.use_empty()) return false; // No arguments? Early exit. // For each argument, keep track of its constant value and whether it is a @@ -157,13 +127,14 @@ bool IPCP::PropagateConstantsIntoArguments(Function &F) { // Additionally if a function always returns one of its arguments directly, // callers will be updated to use the value they pass in directly instead of // using the return value. -bool IPCP::PropagateConstantReturn(Function &F) { +static bool PropagateConstantReturn(Function &F) { if (F.getReturnType()->isVoidTy()) return false; // No return value. - // If this function could be overridden later in the link stage, we can't - // propagate information about its results into callers. - if (F.mayBeOverridden()) + // We can infer and propagate the return value only when we know that the + // definition we'll get at link time is *exactly* the definition we see now. + // For more details, see GlobalValue::mayBeDerefined. + if (!F.isDefinitionExact()) return false; // Check to see if this function returns a constant. @@ -176,8 +147,8 @@ bool IPCP::PropagateConstantReturn(Function &F) { RetVals.push_back(UndefValue::get(F.getReturnType())); unsigned NumNonConstant = 0; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { + for (BasicBlock &BB : F) + if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) { for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { // Already found conflicting return values? Value *RV = RetVals[i]; @@ -277,3 +248,33 @@ bool IPCP::PropagateConstantReturn(Function &F) { if (MadeChange) ++NumReturnValProped; return MadeChange; } + +char IPCP::ID = 0; +INITIALIZE_PASS(IPCP, "ipconstprop", + "Interprocedural constant propagation", false, false) + +ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); } + +bool IPCP::runOnModule(Module &M) { + if (skipModule(M)) + return false; + + bool Changed = false; + bool LocalChange = true; + + // FIXME: instead of using smart algorithms, we just iterate until we stop + // making changes. + while (LocalChange) { + LocalChange = false; + for (Function &F : M) + if (!F.isDeclaration()) { + // Delete any klingons. + F.removeDeadConstantUsers(); + if (F.hasLocalLinkage()) + LocalChange |= PropagateConstantsIntoArguments(F); + Changed |= PropagateConstantReturn(F); + } + Changed |= LocalChange; + } + return Changed; +} |