#include "llvm/Support/CallSite.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Compiler.h"
#include <set>
using namespace llvm;
namespace {
/// DAE - The dead argument elimination pass.
///
- class DAE : public ModulePass {
+ class VISIBILITY_HIDDEN DAE : public ModulePass {
/// Liveness enum - During our initial pass over the program, we determine
/// that things are either definately alive, definately dead, or in need of
/// interprocedural analysis (MaybeLive).
std::multimap<Function*, CallSite> CallSites;
public:
+ static char ID; // Pass identification, replacement for typeid
+ DAE() : ModulePass((intptr_t)&ID) {}
bool runOnModule(Module &M);
virtual bool ShouldHackArguments() const { return false; }
void RemoveDeadArgumentsFromFunction(Function *F);
};
+ char DAE::ID = 0;
RegisterPass<DAE> X("deadargelim", "Dead Argument Elimination");
/// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but
/// deletes arguments to functions which are external. This is only for use
/// by bugpoint.
struct DAH : public DAE {
+ static char ID;
virtual bool ShouldHackArguments() const { return true; }
};
+ char DAH::ID = 0;
RegisterPass<DAH> Y("deadarghaX0r",
"Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)");
}
unsigned NumArgs = Params.size();
// Create the new function body and insert it into the module...
- Function *NF = new Function(NFTy, Fn.getLinkage(), Fn.getName());
+ Function *NF = new Function(NFTy, Fn.getLinkage());
NF->setCallingConv(Fn.getCallingConv());
Fn.getParent()->getFunctionList().insert(&Fn, NF);
+ NF->takeName(&Fn);
// Loop over all of the callers of the function, transforming the call sites
// to pass in a smaller number of arguments into the new function.
CallSite CS = CallSite::get(Fn.use_back());
Instruction *Call = CS.getInstruction();
- // Loop over the operands, dropping extraneous ones at the end of the list.
+ // Pass all the same arguments.
Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs);
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
- Args, "", Call);
+ Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
} else {
- New = new CallInst(NF, Args, "", Call);
+ New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
Args.clear();
if (!Call->use_empty())
- Call->replaceAllUsesWith(Constant::getNullValue(Call->getType()));
+ Call->replaceAllUsesWith(New);
- if (Call->hasName()) {
- std::string Name = Call->getName();
- Call->setName("");
- New->setName(Name);
- }
+ New->takeName(Call);
// Finally, remove the old call from the program, reducing the use-count of
// F.
- Call->getParent()->getInstList().erase(Call);
+ Call->eraseFromParent();
}
// Since we have now created the new function, splice the body of the old
I2 = NF->arg_begin(); I != E; ++I, ++I2) {
// Move the name and users over to the new version.
I->replaceAllUsesWith(I2);
- I2->setName(I->getName());
+ I2->takeName(I);
}
// Finally, nuke the old function.
FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());
// Create the new function body and insert it into the module...
- Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
+ Function *NF = new Function(NFTy, F->getLinkage());
NF->setCallingConv(F->getCallingConv());
F->getParent()->getFunctionList().insert(F, NF);
+ NF->takeName(F);
// Loop over all of the callers of the function, transforming the call sites
// to pass in a smaller number of arguments into the new function.
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
- Args, "", Call);
+ Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
} else {
- New = new CallInst(NF, Args, "", Call);
+ New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
Call->replaceAllUsesWith(Constant::getNullValue(Call->getType()));
else {
Call->replaceAllUsesWith(New);
- std::string Name = Call->getName();
- Call->setName("");
- New->setName(Name);
+ New->takeName(Call);
}
}
// If this is a live argument, move the name and users over to the new
// version.
I->replaceAllUsesWith(I2);
- I2->setName(I->getName());
+ I2->takeName(I);
++I2;
} else {
// If this argument is dead, replace any uses of it with null constants
}
bool DAE::runOnModule(Module &M) {
- // First phase: loop through the module, determining which arguments are live.
- // We assume all arguments are dead unless proven otherwise (allowing us to
- // determine that dead arguments passed into recursive functions are dead).
- //
- DOUT << "DAE - Determining liveness\n";
+ bool Changed = false;
+ // First pass: Do a simple check to see if any functions can have their "..."
+ // removed. We can do this if they never call va_start. This loop cannot be
+ // fused with the next loop, because deleting a function invalidates
+ // information computed while surveying other functions.
+ DOUT << "DAE - Deleting dead varargs\n";
for (Module::iterator I = M.begin(), E = M.end(); I != E; ) {
Function &F = *I++;
if (F.getFunctionType()->isVarArg())
- if (DeleteDeadVarargs(F))
- continue;
-
- SurveyFunction(F);
+ Changed |= DeleteDeadVarargs(F);
}
+
+ // Second phase:loop through the module, determining which arguments are live.
+ // We assume all arguments are dead unless proven otherwise (allowing us to
+ // determine that dead arguments passed into recursive functions are dead).
+ //
+ DOUT << "DAE - Determining liveness\n";
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ SurveyFunction(*I);
// Loop over the instructions to inspect, propagating liveness among arguments
// and return values which are MaybeLive.
-
while (!InstructionsToInspect.empty()) {
Instruction *I = InstructionsToInspect.back();
InstructionsToInspect.pop_back();
// to do.
if (MaybeLiveArguments.empty() && DeadArguments.empty() &&
MaybeLiveRetVal.empty() && DeadRetVal.empty())
- return false;
+ return Changed;
// Otherwise, compact into one set, and start eliminating the arguments from
// the functions.