diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 191c62a3f66..0da14d8b29b 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -37,8 +38,9 @@ #include using namespace llvm; -STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); -STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); +STATISTIC(NumArgumentsEliminated , "Number of unread args removed"); +STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); +STATISTIC(NumParametersEliminated, "Number of parameters replaced with undef"); namespace { /// DAE - The dead argument elimination pass. @@ -140,6 +142,7 @@ namespace { void MarkLive(const Function &F); void PropagateLiveness(const RetOrArg &RA); bool RemoveDeadStuffFromFunction(Function *F); + bool RemoveDeadParamsFromCallersOf(Function *F); bool DeleteDeadVarargs(Function &Fn); }; } @@ -397,7 +400,9 @@ DAE::Liveness DAE::SurveyUses(const Value *V, UseVector &MaybeLiveUses) { // map. // // We consider arguments of non-internal functions to be intrinsically alive as -// well as arguments to functions which have their "address taken". +// well as arguments to functions which have their "address taken". Externally +// visible functions are assumed to only have their return values intrinsically +// alive, permitting removal of parameters to unused arguments in callers. // void DAE::SurveyFunction(const Function &F) { unsigned RetCount = NumRetVals(&F); @@ -420,7 +425,14 @@ void DAE::SurveyFunction(const Function &F) { return; } - if (!F.hasLocalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) { + if (F.hasExternalLinkage() && !F.isDeclaration()) { + DEBUG(dbgs() << "DAE - Intrinsically live return from " << F.getName() + << "\n"); + // Mark the return values alive. + for (unsigned i = 0, e = NumRetVals(&F); i != e; ++i) + MarkLive(CreateRet(&F, i)); + } else if (!F.hasLocalLinkage() && + (!ShouldHackArguments() || F.isIntrinsic())) { MarkLive(F); return; } @@ -532,14 +544,14 @@ void DAE::MarkValue(const RetOrArg &RA, Liveness L, /// values (according to Uses) live as well. void DAE::MarkLive(const Function &F) { DEBUG(dbgs() << "DAE - Intrinsically live fn: " << F.getName() << "\n"); - // Mark the function as live. - LiveFunctions.insert(&F); - // Mark all arguments as live. - for (unsigned i = 0, e = F.arg_size(); i != e; ++i) - PropagateLiveness(CreateArg(&F, i)); - // Mark all return values as live. - for (unsigned i = 0, e = NumRetVals(&F); i != e; ++i) - PropagateLiveness(CreateRet(&F, i)); + // Mark the function as live. + LiveFunctions.insert(&F); + // Mark all arguments as live. + for (unsigned i = 0, e = F.arg_size(); i != e; ++i) + PropagateLiveness(CreateArg(&F, i)); + // Mark all return values as live. + for (unsigned i = 0, e = NumRetVals(&F); i != e; ++i) + PropagateLiveness(CreateRet(&F, i)); } /// MarkLive - Mark the given return value or argument as live. Additionally, @@ -853,7 +865,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { Value *RetVal; - if (NFTy->getReturnType() == Type::getVoidTy(F->getContext())) { + if (NFTy->getReturnType()->isVoidTy()) { RetVal = 0; } else { assert (RetTy->isStructTy()); @@ -894,6 +906,43 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { return true; } +bool DAE::RemoveDeadParamsFromCallersOf(Function *F) { + // Don't modify fully live functions + if (LiveFunctions.count(F)) + return false; + + // Make a list of the dead arguments. + SmallVector ArgDead; + unsigned i = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++i) { + RetOrArg Arg = CreateArg(F, i); + if (!LiveValues.count(Arg)) + ArgDead.push_back(i); + } + if (ArgDead.empty()) + return false; + + bool MadeChange = false; + for (Function::use_iterator I = F->use_begin(), E = F->use_end(); + I != E; ++I) { + CallSite CS = CallSite::get(*I); + if (CS.getInstruction() && CS.isCallee(I)) { + for (unsigned i = 0, e = ArgDead.size(); i != e; ++i) { + Value *A = CS.getArgument(ArgDead[i]); + if (!isa(A)) { + ++NumParametersEliminated; + MadeChange = true; + CS.setArgument(ArgDead[i], UndefValue::get(A->getType())); + RecursivelyDeleteTriviallyDeadInstructions(A); + } + } + } + } + + return MadeChange; +} + bool DAE::runOnModule(Module &M) { bool Changed = false; @@ -922,7 +971,10 @@ bool DAE::runOnModule(Module &M) { // Increment now, because the function will probably get removed (ie. // replaced by a new one). Function *F = I++; - Changed |= RemoveDeadStuffFromFunction(F); + if (F->hasExternalLinkage() && !F->isDeclaration()) + Changed |= RemoveDeadParamsFromCallersOf(F); + else + Changed |= RemoveDeadStuffFromFunction(F); } return Changed; }