//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "llvm/ParameterAttributes.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/Debug.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
+#include <map>
#include <set>
using namespace llvm;
void RemoveDeadArgumentsFromFunction(Function *F);
};
- char DAE::ID = 0;
- RegisterPass<DAE> X("deadargelim", "Dead Argument Elimination");
+}
+
+char DAE::ID = 0;
+static RegisterPass<DAE>
+X("deadargelim", "Dead Argument Elimination");
+namespace {
/// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but
/// deletes arguments to functions which are external. This is only for use
/// by bugpoint.
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)");
}
+char DAH::ID = 0;
+static RegisterPass<DAH>
+Y("deadarghaX0r", "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)");
+
/// createDeadArgEliminationPass - This pass removes arguments from functions
/// which are not used by the body of the function.
///
bool DAE::DeleteDeadVarargs(Function &Fn) {
assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!");
if (Fn.isDeclaration() || !Fn.hasInternalLinkage()) return false;
-
+
// Ensure that the function is only directly called.
for (Value::use_iterator I = Fn.use_begin(), E = Fn.use_end(); I != E; ++I) {
// If this use is anything other than a call site, give up.
CallSite CS = CallSite::get(*I);
Instruction *TheCall = CS.getInstruction();
if (!TheCall) return false; // Not a direct call site?
-
+
// The addr of this function is passed to the call.
if (I.getOperandNo() != 0) return false;
}
-
+
// Okay, we know we can transform this function if safe. Scan its body
// looking for calls to llvm.vastart.
for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
}
}
}
-
+
// If we get here, there are no calls to llvm.vastart in the function body,
// remove the "..." and adjust all the calls.
-
+
// Start by computing a new prototype for the function, which is the same as
// the old function, but has fewer arguments.
const FunctionType *FTy = Fn.getFunctionType();
std::vector<const Type*> Params(FTy->param_begin(), FTy->param_end());
FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false);
unsigned NumArgs = Params.size();
-
+
// Create the new function body and insert it into the module...
- Function *NF = new Function(NFTy, Fn.getLinkage());
+ Function *NF = Function::Create(NFTy, Fn.getLinkage());
NF->setCallingConv(Fn.getCallingConv());
NF->setParamAttrs(Fn.getParamAttrs());
+ if (Fn.hasCollector())
+ NF->setCollector(Fn.getCollector());
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.
//
while (!Fn.use_empty()) {
CallSite CS = CallSite::get(Fn.use_back());
Instruction *Call = CS.getInstruction();
-
+
// Pass all the same arguments.
Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs);
-
+
+ // Drop any attributes that were on the vararg arguments.
+ PAListPtr PAL = CS.getParamAttrs();
+ if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) {
+ SmallVector<ParamAttrsWithIndex, 8> ParamAttrsVec;
+ for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i)
+ ParamAttrsVec.push_back(PAL.getSlot(i));
+ PAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end());
+ }
+
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
- New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
- Args.begin(), Args.end(), "", Call);
+ New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
+ Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
- cast<InvokeInst>(New)->setParamAttrs(NF->getParamAttrs());
+ cast<InvokeInst>(New)->setParamAttrs(PAL);
} else {
- New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
+ New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
- cast<CallInst>(New)->setParamAttrs(NF->getParamAttrs());
+ cast<CallInst>(New)->setParamAttrs(PAL);
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}
Args.clear();
-
+
if (!Call->use_empty())
Call->replaceAllUsesWith(New);
-
+
New->takeName(Call);
-
+
// Finally, remove the old call from the program, reducing the use-count of
// F.
Call->eraseFromParent();
}
-
+
// Since we have now created the new function, splice the body of the old
// function right into the new function, leaving the old rotting hulk of the
// function empty.
NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList());
-
+
// Loop over the argument list, transfering uses of the old arguments over to
// the new arguments, also transfering over the names as well. While we're at
// it, remove the dead arguments from the DeadArguments list.
I->replaceAllUsesWith(I2);
I2->takeName(I);
}
-
+
// Finally, nuke the old function.
Fn.eraseFromParent();
return true;
const Function *F = A.getParent();
// If this is the return value of a struct function, it's not really dead.
- if (F->isStructReturn() && &*(F->arg_begin()) == &A)
+ if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A)
return Live;
if (A.use_empty()) // First check, directly dead?
std::vector<const Type*> Params;
// Set up to build a new list of parameter attributes
- ParamAttrsVector ParamAttrsVec;
- const ParamAttrsList *PAL = F->getParamAttrs();
+ SmallVector<ParamAttrsWithIndex, 8> ParamAttrsVec;
+ const PAListPtr &PAL = F->getParamAttrs();
+
+ // The existing function return attributes.
+ ParameterAttributes RAttrs = PAL.getParamAttrs(0);
+
+ // Make the function return void if the return value is dead.
+ const Type *RetTy = FTy->getReturnType();
+ if (DeadRetVal.count(F)) {
+ RetTy = Type::VoidTy;
+ RAttrs &= ~ParamAttr::typeIncompatible(RetTy);
+ DeadRetVal.erase(F);
+ }
+
+ if (RAttrs)
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs));
// Construct the new parameter list from non-dead arguments. Also construct
// a new set of parameter attributes to correspond.
++I, ++index)
if (!DeadArguments.count(I)) {
Params.push_back(I->getType());
- if (PAL) {
- uint16_t Attrs = PAL->getParamAttrs(index);
- if (Attrs != ParamAttr::None)
- ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(),
- Attrs));
- }
+
+ if (ParameterAttributes Attrs = PAL.getParamAttrs(index))
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs));
}
// Reconstruct the ParamAttrsList based on the vector we constructed.
- if (ParamAttrsVec.empty())
- PAL = 0;
- else
- PAL = ParamAttrsList::get(ParamAttrsVec);
-
- // Make the function return void if the return value is dead.
- const Type *RetTy = FTy->getReturnType();
- if (DeadRetVal.count(F)) {
- RetTy = Type::VoidTy;
- DeadRetVal.erase(F);
- }
+ PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end());
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
// have zero fixed arguments.
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());
+ Function *NF = Function::Create(NFTy, F->getLinkage());
NF->setCallingConv(F->getCallingConv());
- NF->setParamAttrs(PAL);
+ NF->setParamAttrs(NewPAL);
+ if (F->hasCollector())
+ NF->setCollector(F->getCollector());
F->getParent()->getFunctionList().insert(F, NF);
NF->takeName(F);
while (!F->use_empty()) {
CallSite CS = CallSite::get(F->use_back());
Instruction *Call = CS.getInstruction();
+ ParamAttrsVec.clear();
+ const PAListPtr &CallPAL = CS.getParamAttrs();
+
+ // The call return attributes.
+ ParameterAttributes RAttrs = CallPAL.getParamAttrs(0);
+ // Adjust in case the function was changed to return void.
+ RAttrs &= ~ParamAttr::typeIncompatible(NF->getReturnType());
+ if (RAttrs)
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs));
// Loop over the operands, deleting dead ones...
CallSite::arg_iterator AI = CS.arg_begin();
+ index = 1;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
- I != E; ++I, ++AI)
- if (!DeadArguments.count(I)) // Remove operands for dead arguments
+ I != E; ++I, ++AI, ++index)
+ if (!DeadArguments.count(I)) { // Remove operands for dead arguments
Args.push_back(*AI);
+ if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index))
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
+ }
if (ExtraArgHack)
Args.push_back(UndefValue::get(Type::Int32Ty));
- // Push any varargs arguments on the list
- for (; AI != CS.arg_end(); ++AI)
+ // Push any varargs arguments on the list. Don't forget their attributes.
+ for (; AI != CS.arg_end(); ++AI) {
Args.push_back(*AI);
+ if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++))
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
+ }
+
+ // Reconstruct the ParamAttrsList based on the vector we constructed.
+ PAListPtr NewCallPAL = PAListPtr::get(ParamAttrsVec.begin(),
+ ParamAttrsVec.end());
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
- New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
- Args.begin(), Args.end(), "", Call);
+ New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
+ Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
- cast<InvokeInst>(New)->setParamAttrs(PAL);
+ cast<InvokeInst>(New)->setParamAttrs(NewCallPAL);
} else {
- New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
+ New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
- cast<CallInst>(New)->setParamAttrs(PAL);
+ cast<CallInst>(New)->setParamAttrs(NewCallPAL);
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}
if (F->getReturnType() != NF->getReturnType())
for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
- new ReturnInst(0, RI);
+ ReturnInst::Create(0, RI);
BB->getInstList().erase(RI);
}