From 5894c0b60ef75f382d64b268a5f1a0f2b0db840f Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Wed, 14 Apr 2010 03:38:11 +0000 Subject: [PATCH] While DAE can't modify the function signature of an externally visible function, it can check whether the visible direct callers are passing in parameters to dead arguments and replace those with undef. This reinstates r94322 with bugs fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101213 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/DeadArgumentElimination.cpp | 80 +++++++++++++++++++++----- 1 file changed, 66 insertions(+), 14 deletions(-) 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; } -- 2.11.0