43 #define DEBUG_TYPE "deadargelim"
45 STATISTIC(NumArgumentsEliminated,
"Number of unread args removed");
46 STATISTIC(NumRetValsEliminated ,
"Number of unused return values removed");
48 "Number of unread args replaced with undef");
63 bool runOnModule(
Module &M)
override {
72 virtual bool ShouldHackArguments()
const {
return false; }
78 INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
84 struct DAH :
public DAE {
88 bool ShouldHackArguments()
const override {
return true; }
94 "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
105 bool DeadArgumentEliminationPass::DeleteDeadVarargs(
Function &Fn) {
130 if (II->getIntrinsicID() == Intrinsic::vastart)
146 unsigned NumArgs = Params.size();
152 Fn.getParent()->getFunctionList().insert(Fn.getIterator(), NF);
158 std::vector<Value*>
Args;
166 Args.assign(
CS.arg_begin(),
CS.arg_begin() + NumArgs);
175 AttributesVec.
push_back(AttributeSet::get(Fn.getContext(),
177 PAL = AttributeSet::get(Fn.getContext(), AttributesVec);
181 CS.getOperandBundlesAsDefs(OpBundles);
184 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
187 cast<InvokeInst>(New)->setCallingConv(
CS.getCallingConv());
188 cast<InvokeInst>(New)->setAttributes(PAL);
191 cast<CallInst>(New)->setCallingConv(
CS.getCallingConv());
192 cast<CallInst>(New)->setAttributes(PAL);
193 cast<CallInst>(New)->setTailCallKind(
194 cast<CallInst>(Call)->getTailCallKind());
222 I->replaceAllUsesWith(&*I2);
235 Fn.eraseFromParent();
242 bool DeadArgumentEliminationPass::RemoveDeadArgumentsFromCallers(
Function &Fn) {
273 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() && !Arg.hasByValOrInAllocaAttr())
277 if (UnusedArgs.
empty())
280 bool Changed =
false;
284 if (!CS || !
CS.isCallee(&U))
288 for (
unsigned I = 0,
E = UnusedArgs.
size();
I !=
E; ++
I) {
289 unsigned ArgNo = UnusedArgs[
I];
291 Value *Arg =
CS.getArgument(ArgNo);
293 ++NumArgumentsReplacedWithUndef;
308 else if (
StructType *STy = dyn_cast<StructType>(RetTy))
309 return STy->getNumElements();
310 else if (
ArrayType *ATy = dyn_cast<ArrayType>(RetTy))
311 return ATy->getNumElements();
323 if (
StructType *STy = dyn_cast<StructType>(RetTy))
324 return STy->getElementType(Idx);
325 else if (
ArrayType *ATy = dyn_cast<ArrayType>(RetTy))
326 return ATy->getElementType();
335 DeadArgumentEliminationPass::MarkIfNotLive(RetOrArg
Use,
336 UseVector &MaybeLiveUses) {
343 MaybeLiveUses.push_back(Use);
356 DeadArgumentEliminationPass::SurveyUse(
const Use *U, UseVector &MaybeLiveUses,
357 unsigned RetValNum) {
358 const User *V = U->getUser();
359 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(V)) {
364 const Function *
F = RI->getParent()->getParent();
365 if (RetValNum != -1U) {
368 return MarkIfNotLive(Use, MaybeLiveUses);
377 MarkIfNotLive(Use, MaybeLiveUses);
390 RetValNum = *IV->idx_begin();
396 for (
const Use &UU : IV->uses()) {
397 Result = SurveyUse(&UU, MaybeLiveUses, RetValNum);
410 if (
CS.isBundleOperand(U))
417 unsigned ArgNo =
CS.getArgumentNo(U);
424 ==
CS->getOperand(U->getOperandNo())
425 &&
"Argument is not where we expected it");
430 return MarkIfNotLive(Use, MaybeLiveUses);
444 DeadArgumentEliminationPass::SurveyUses(
const Value *V,
445 UseVector &MaybeLiveUses) {
449 for (
const Use &U : V->
uses()) {
450 Result = SurveyUse(&U, MaybeLiveUses);
465 void DeadArgumentEliminationPass::SurveyFunction(
const Function &F) {
484 RetVals RetValLiveness(RetCount,
MaybeLive);
490 RetUses MaybeLiveRetUses(RetCount);
493 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
494 if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType()
506 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
510 unsigned NumLiveRetVals = 0;
512 for (
const Use &U : F.
uses()) {
516 if (!CS || !
CS.isCallee(&U)) {
532 if (NumLiveRetVals == RetCount)
536 for (
const Use &U : TheCall->
uses()) {
540 unsigned Idx = *
Ext->idx_begin();
541 if (RetValLiveness[Idx] !=
Live) {
542 RetValLiveness[Idx] = SurveyUses(
Ext, MaybeLiveRetUses[Idx]);
543 if (RetValLiveness[Idx] ==
Live)
550 if (SurveyUse(&U, MaybeLiveAggregateUses) ==
Live) {
551 NumLiveRetVals = RetCount;
552 RetValLiveness.assign(RetCount,
Live);
555 for (
unsigned i = 0;
i != RetCount; ++
i) {
556 if (RetValLiveness[
i] !=
Live)
557 MaybeLiveRetUses[
i].append(MaybeLiveAggregateUses.begin(),
558 MaybeLiveAggregateUses.end());
566 for (
unsigned i = 0;
i != RetCount; ++
i)
567 MarkValue(
CreateRet(&F,
i), RetValLiveness[
i], MaybeLiveRetUses[
i]);
569 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
588 Result = SurveyUses(&*AI, MaybeLiveArgUses);
592 MarkValue(
CreateArg(&F, i), Result, MaybeLiveArgUses);
594 MaybeLiveArgUses.clear();
602 void DeadArgumentEliminationPass::MarkValue(
const RetOrArg &RA, Liveness
L,
603 const UseVector &MaybeLiveUses) {
605 case Live: MarkLive(RA);
break;
610 for (
const auto &MaybeLiveUse : MaybeLiveUses)
611 Uses.insert(std::make_pair(MaybeLiveUse, RA));
621 void DeadArgumentEliminationPass::MarkLive(
const Function &F) {
622 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Intrinsically live fn: "
627 for (
unsigned i = 0, e = F.
arg_size(); i != e; ++
i)
630 for (
unsigned i = 0, e =
NumRetVals(&F); i != e; ++
i)
637 void DeadArgumentEliminationPass::MarkLive(
const RetOrArg &RA) {
644 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Marking "
645 << RA.getDescription() <<
" live\n");
646 PropagateLiveness(RA);
651 void DeadArgumentEliminationPass::PropagateLiveness(
const RetOrArg &RA) {
655 UseMap::iterator Begin =
Uses.lower_bound(RA);
656 UseMap::iterator
E =
Uses.end();
658 for (I = Begin; I != E && I->first == RA; ++
I)
663 Uses.erase(Begin, I);
670 bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(
Function *F) {
678 std::vector<Type*> Params;
681 bool HasLiveReturnedArg =
false;
697 Params.push_back(I->getType());
704 if (
B.contains(Attribute::Returned))
705 HasLiveReturnedArg =
true;
707 push_back(AttributeSet::get(F->
getContext(), Params.size(),
B));
710 ++NumArgumentsEliminated;
711 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing argument " << i
712 <<
" (" << I->getName() <<
") from " << F->
getName()
719 Type *NRetTy =
nullptr;
724 std::vector<Type*> RetTypes;
745 if (RetTy->
isVoidTy() || HasLiveReturnedArg) {
749 for (
unsigned i = 0; i != RetCount; ++
i) {
753 NewRetIdxs[
i] = RetTypes.size() - 1;
755 ++NumRetValsEliminated;
756 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
757 << i <<
" from " << F->
getName() <<
"\n");
760 if (RetTypes.size() > 1) {
762 if (
StructType *STy = dyn_cast<StructType>(RetTy)) {
765 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
767 assert(isa<ArrayType>(RetTy) &&
"unexpected multi-value return");
770 }
else if (RetTypes.size() == 1)
773 NRetTy = RetTypes.front();
774 else if (RetTypes.size() == 0)
779 assert(NRetTy &&
"No new return type found?");
795 "Return attributes no longer compatible?");
827 std::vector<Value*>
Args;
832 AttributesVec.
clear();
862 if (NRetTy != RetTy &&
B.contains(Attribute::Returned))
863 B.removeAttribute(Attribute::Returned);
865 push_back(AttributeSet::get(F->
getContext(), Args.size(),
B));
875 push_back(AttributeSet::get(F->
getContext(), Args.size(),
B));
880 AttributesVec.
push_back(AttributeSet::get(Call->getContext(),
887 CS.getOperandBundlesAsDefs(OpBundles);
890 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
892 Args, OpBundles,
"", Call->getParent());
893 cast<InvokeInst>(New)->setCallingConv(
CS.getCallingConv());
894 cast<InvokeInst>(New)->setAttributes(NewCallPAL);
897 cast<CallInst>(New)->setCallingConv(
CS.getCallingConv());
898 cast<CallInst>(New)->setAttributes(NewCallPAL);
899 cast<CallInst>(New)->setTailCallKind(
900 cast<CallInst>(Call)->getTailCallKind());
906 if (!Call->use_empty()) {
907 if (New->
getType() == Call->getType()) {
909 Call->replaceAllUsesWith(New);
914 if (!Call->getType()->isX86_MMXTy())
918 "Return type changed, but not into a void. The old return type"
919 " must have been a struct or an array!");
921 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
932 for (
unsigned i = 0; i != RetCount; ++
i)
933 if (NewRetIdxs[i] != -1) {
935 if (RetTypes.size() > 1)
948 Call->replaceAllUsesWith(RetVal);
955 Call->eraseFromParent();
971 I->replaceAllUsesWith(&*I2);
977 if (!I->getType()->isX86_MMXTy())
985 if (
ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
988 if (NFTy->getReturnType()->isVoidTy()) {
997 Value *OldRet = RI->getOperand(0);
1000 for (
unsigned i = 0; i != RetCount; ++
i)
1001 if (NewRetIdxs[i] != -1) {
1004 if (RetTypes.size() > 1) {
1020 BB.getInstList().erase(RI);
1034 bool Changed =
false;
1040 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1044 Changed |= DeleteDeadVarargs(F);
1051 DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1061 Changed |= RemoveDeadStuffFromFunction(F);
1067 Changed |= RemoveDeadArgumentsFromCallers(F);
Return a value (possibly void), from a function.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
LinkageTypes getLinkage() const
iterator_range< use_iterator > uses()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
Eliminate dead arguments (and return values) from functions.
STATISTIC(NumFunctions,"Total number of functions")
A Module instance is used to store all the information related to an LLVM module. ...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
This class represents a function call, abstracting a target machine's calling convention.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
bool hasExactDefinition() const
Return true if this global has an exact defintion.
RetOrArg CreateArg(const Function *F, unsigned Idx)
Convenience wrapper.
Type * getReturnType() const
Returns the type of the ret val.
LiveSet LiveValues
This set contains all values that have been determined to be live.
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
StringRef getName() const
Return a constant reference to the value's name.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
Class to represent struct types.
ModulePass * createDeadArgHackingPass()
DeadArgHacking pass - Same as DAE, but delete arguments of external functions as well.
A Use represents the edge between a Value definition and its users.
param_iterator param_end() const
bool isMustTailCall() const
LLVM_NODISCARD bool empty() const
user_iterator_impl< User > user_iterator
Class to represent function types.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Class to represent array types.
void setComdat(Comdat *C)
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
bool isArrayTy() const
True if this is an instance of ArrayType.
void takeName(Value *V)
Transfer the name from V to this value.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
unsigned getNumSlots() const
Return the number of slots used in this attribute list.
void setSubprogram(DISubprogram *SP)
Set the attached subprogram.
A set of analyses that are preserved following a run of a transformation pass.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
static unsigned getAggregateOperandIndex()
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
AttributeSet getSlotAttributes(unsigned Slot) const
Return the attributes at the given slot.
const Comdat * getComdat() const
param_iterator param_begin() const
ModulePass * createDeadArgEliminationPass()
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
void initializeDAEPass(PassRegistry &)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
static Type * getVoidTy(LLVMContext &C)
void splice(iterator where, iplist_impl &L2)
User * getUser() const
Returns the User that contains this Use.
void copyAttributesFrom(const GlobalValue *Src) override
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
self_iterator getIterator()
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
static InvokeInst * Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, Instruction *InsertBefore=nullptr)
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
static unsigned NumRetVals(const Function *F)
Convenience function that returns the number of return values.
Iterator for intrusive lists based on ilist_node.
const BasicBlockListType & getBasicBlockList() const
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
static Type * getRetComponentType(const Function *F, unsigned Idx)
Returns the sub-type a function will return at a given Idx.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
AttributeSet getAttributes() const
Return the attribute list for this Function.
AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const
Remove the specified attributes at the specified index from this attribute list.
DISubprogram * getSubprogram() const
Get the attached subprogram.
UseMap Uses
This maps a return value or argument to any MaybeLive return values or arguments it uses...
LiveFuncSet LiveFunctions
This set contains all values that are cannot be changed in any way.
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
void setAttributes(AttributeSet Attrs)
Set the attribute list for this Function.
RetOrArg CreateRet(const Function *F, unsigned Idx)
Convenience wrapper.
bool isStructTy() const
True if this is an instance of StructType.
INITIALIZE_PASS(DAH,"deadarghaX0r","Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", false, false) ModulePass *llvm
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
PointerType * getType() const
Global values are always pointers.
iterator insert(iterator where, pointer New)
bool hasAddressTaken(const User **=nullptr) const
hasAddressTaken - returns true if there are any uses of this function other than direct calls or invo...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
unsigned getSlotIndex(unsigned Slot) const
Return the index for the given slot.
bool hasAttributes(unsigned Index) const
Return true if attribute exists at the given index.
static InsertValueInst * Create(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
ImmutableCallSite - establish a view to a call site for examination.
bool ShouldHackArguments
This allows this pass to do double-duty as the dead arg hacking pass (used only by bugpoint)...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasLocalLinkage() const
SmallVector< RetOrArg, 5 > UseVector
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Liveness
Liveness enum - During our initial pass over the program, we determine that things are either alive o...
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
AttrBuilder typeIncompatible(Type *Ty)
Which attributes cannot be applied to a type.
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the edge connecting specified block.
A container for analyses that lazily runs them and caches their results.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
bool isEmpty() const
Return true if there are no attributes.
const BasicBlock * getParent() const
iterator_range< arg_iterator > args()
A wrapper class for inspecting calls to intrinsic functions.
bool isVoidTy() const
Return true if this is 'void'.
This instruction inserts a struct field of array element value into an aggregate value.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
AttributeSet getFnAttributes() const
The function attributes are returned.