1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-22 20:43:44 +02:00

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.

llvm-svn: 101213
This commit is contained in:
Nick Lewycky 2010-04-14 03:38:11 +00:00
parent 1158c51fe0
commit 5e0d0d551b

View File

@ -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 <set>
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<ReturnInst>(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<int, 10> 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<UndefValue>(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;
}