56#define DEBUG_TYPE "deadargelim"
58STATISTIC(NumArgumentsEliminated,
"Number of unread args removed");
59STATISTIC(NumRetValsEliminated,
"Number of unused return values removed");
61 "Number of unread args replaced with poison");
87 virtual bool shouldHackArguments()
const {
return false; }
90bool isMustTailCalleeAnalyzable(
const CallBase &CB) {
99INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
105struct DAH :
public DAE {
110 bool shouldHackArguments()
const override {
return true; }
118 "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
false,
129bool DeadArgumentEliminationPass::deleteDeadVarargs(
Function &
F) {
130 assert(
F.getFunctionType()->isVarArg() &&
"Function isn't varargs!");
131 if (
F.isDeclaration() || !
F.hasLocalLinkage())
135 if (
F.hasAddressTaken())
141 if (
F.hasFnAttribute(Attribute::Naked)) {
155 if (
II->getIntrinsicID() == Intrinsic::vastart)
168 std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
170 unsigned NumArgs = Params.size();
176 F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
183 std::vector<Value *>
Args;
185 CallBase *CB = dyn_cast<CallBase>(U);
196 for (
unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
211 cast<CallInst>(NewCB)->setTailCallKind(
212 cast<CallInst>(CB)->getTailCallKind());
216 NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
242 I->replaceAllUsesWith(&*I2);
248 F.getAllMetadata(MDs);
249 for (
auto [KindID,
Node] : MDs)
253 F.replaceAllUsesWith(NF);
264bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(
Function &
F) {
276 if (!
F.hasExactDefinition())
284 !
F.getFunctionType()->isVarArg())
290 if (
F.hasFnAttribute(Attribute::Naked))
297 bool Changed =
false;
302 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() &&
303 !Arg.hasPassPointeeByValueCopyAttr()) {
304 if (Arg.isUsedByMetadata()) {
309 F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes);
313 if (UnusedArgs.
empty())
316 for (
Use &U :
F.uses()) {
317 CallBase *CB = dyn_cast<CallBase>(
U.getUser());
323 for (
unsigned ArgNo : UnusedArgs) {
328 ++NumArgumentsReplacedWithPoison;
341 if (
RetTy->isVoidTy())
344 return STy->getNumElements();
346 return ATy->getNumElements();
358 return STy->getElementType(
Idx);
360 return ATy->getElementType();
367DeadArgumentEliminationPass::markIfNotLive(RetOrArg
Use,
368 UseVector &MaybeLiveUses) {
375 MaybeLiveUses.push_back(
Use);
387DeadArgumentEliminationPass::surveyUse(
const Use *U, UseVector &MaybeLiveUses,
388 unsigned RetValNum) {
389 const User *V = U->getUser();
390 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(V)) {
395 const Function *
F = RI->getParent()->getParent();
396 if (RetValNum != -1U) {
399 return markIfNotLive(
Use, MaybeLiveUses);
409 markIfNotLive(
Use, MaybeLiveUses);
422 RetValNum = *
IV->idx_begin();
428 for (
const Use &UU :
IV->uses()) {
429 Result = surveyUse(&UU, MaybeLiveUses, RetValNum);
436 if (
const auto *CB = dyn_cast<CallBase>(V)) {
451 if (ArgNo >=
F->getFunctionType()->getNumParams())
456 "Argument is not where we expected it");
461 return markIfNotLive(
Use, MaybeLiveUses);
475DeadArgumentEliminationPass::surveyUses(
const Value *V,
476 UseVector &MaybeLiveUses) {
480 for (
const Use &U : V->uses()) {
481 Result = surveyUse(&U, MaybeLiveUses);
494void DeadArgumentEliminationPass::surveyFunction(
const Function &
F) {
497 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
498 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
506 if (
F.hasFnAttribute(Attribute::Naked)) {
516 RetVals RetValLiveness(RetCount,
MaybeLive);
523 RetUses MaybeLiveRetUses(RetCount);
525 bool HasMustTailCalls =
false;
529 if (
const auto *TC = BB.getTerminatingMustTailCall()) {
530 HasMustTailCalls =
true;
534 if (!isMustTailCalleeAnalyzable(*TC)) {
541 if (HasMustTailCalls) {
543 <<
" has musttail calls\n");
552 dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
553 <<
F.getName() <<
"\n");
556 unsigned NumLiveRetVals = 0;
558 bool HasMustTailCallers =
false;
561 for (
const Use &U :
F.uses()) {
564 const auto *CB = dyn_cast<CallBase>(U.getUser());
574 HasMustTailCallers =
true;
580 if (NumLiveRetVals == RetCount)
584 for (
const Use &UU : CB->
uses()) {
588 unsigned Idx = *Ext->idx_begin();
589 if (RetValLiveness[
Idx] !=
Live) {
590 RetValLiveness[
Idx] = surveyUses(Ext, MaybeLiveRetUses[
Idx]);
591 if (RetValLiveness[
Idx] ==
Live)
598 if (surveyUse(&UU, MaybeLiveAggregateUses) ==
Live) {
599 NumLiveRetVals = RetCount;
600 RetValLiveness.assign(RetCount,
Live);
604 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
605 if (RetValLiveness[Ri] !=
Live)
606 MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(),
607 MaybeLiveAggregateUses.end());
613 if (HasMustTailCallers) {
615 <<
" has musttail callers\n");
619 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
620 markValue(
createRet(&
F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]);
622 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
623 <<
F.getName() <<
"\n");
629 AI != E; ++AI, ++ArgI) {
631 if (
F.getFunctionType()->isVarArg() || HasMustTailCallers ||
648 Result = surveyUses(&*AI, MaybeLiveArgUses);
652 markValue(
createArg(&
F, ArgI), Result, MaybeLiveArgUses);
654 MaybeLiveArgUses.clear();
661void DeadArgumentEliminationPass::markValue(
const RetOrArg &
RA, Liveness L,
662 const UseVector &MaybeLiveUses) {
668 assert(!isLive(
RA) &&
"Use is already live!");
669 for (
const auto &MaybeLiveUse : MaybeLiveUses) {
670 if (isLive(MaybeLiveUse)) {
677 Uses.emplace(MaybeLiveUse,
RA);
686void DeadArgumentEliminationPass::markLive(
const Function &
F) {
687 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Intrinsically live fn: "
688 <<
F.getName() <<
"\n");
692 for (
unsigned ArgI = 0, E =
F.arg_size(); ArgI != E; ++ArgI)
695 for (
unsigned Ri = 0, E =
numRetVals(&
F); Ri != E; ++Ri)
701void DeadArgumentEliminationPass::markLive(
const RetOrArg &
RA) {
708 <<
RA.getDescription() <<
" live\n");
709 propagateLiveness(
RA);
712bool DeadArgumentEliminationPass::isLive(
const RetOrArg &
RA) {
718void DeadArgumentEliminationPass::propagateLiveness(
const RetOrArg &
RA) {
722 UseMap::iterator Begin =
Uses.lower_bound(
RA);
723 UseMap::iterator E =
Uses.end();
725 for (
I = Begin;
I != E &&
I->first ==
RA; ++
I)
730 Uses.erase(Begin,
I);
736bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(
Function *
F) {
744 std::vector<Type *> Params;
747 bool HasLiveReturnedArg =
false;
764 Params.push_back(
I->getType());
765 ArgAlive[ArgI] =
true;
767 HasLiveReturnedArg |= PAL.
hasParamAttr(ArgI, Attribute::Returned);
769 ++NumArgumentsEliminated;
773 <<
"eliminating argument " <<
ore::NV(
"ArgName",
I->getName())
774 <<
"(" <<
ore::NV(
"ArgIndex", ArgI) <<
")";
776 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing argument "
777 << ArgI <<
" (" <<
I->getName() <<
") from "
778 <<
F->getName() <<
"\n");
784 Type *NRetTy =
nullptr;
789 std::vector<Type *> RetTypes;
810 if (
RetTy->isVoidTy() || HasLiveReturnedArg) {
814 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
817 RetTypes.push_back(getRetComponentType(
F, Ri));
818 NewRetIdxs[Ri] = RetTypes.size() - 1;
820 ++NumRetValsEliminated;
824 <<
"removing return value " << std::to_string(Ri);
827 dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
828 << Ri <<
" from " <<
F->getName() <<
"\n");
831 if (RetTypes.size() > 1) {
836 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
838 assert(isa<ArrayType>(
RetTy) &&
"unexpected multi-value return");
841 }
else if (RetTypes.size() == 1)
844 NRetTy = RetTypes.front();
845 else if (RetTypes.empty())
850 assert(NRetTy &&
"No new return type found?");
864 "Return attributes no longer compatible?");
891 F->getParent()->getFunctionList().insert(
F->getIterator(), NF);
897 std::vector<Value *>
Args;
898 while (!
F->use_empty()) {
899 CallBase &CB = cast<CallBase>(*
F->user_back());
917 for (
unsigned E = FTy->getNumParams(); Pi != E; ++
I, ++Pi)
922 if (NRetTy !=
RetTy &&
Attrs.hasAttribute(Attribute::Returned)) {
938 for (
auto *E = CB.
arg_end();
I != E; ++
I, ++Pi) {
949 F->getContext(), Attribute::AllocSize);
963 cast<CallInst>(NewCB)->setTailCallKind(
964 cast<CallInst>(&CB)->getTailCallKind());
968 NewCB->
copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
983 "Return type changed, but not into a void. The old return type"
984 " must have been a struct or an array!");
998 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
999 if (NewRetIdxs[Ri] != -1) {
1002 if (RetTypes.size() > 1)
1005 V = IRB.CreateExtractValue(NewCB, NewRetIdxs[Ri],
"newret");
1010 RetVal = IRB.CreateInsertValue(RetVal, V, Ri,
"oldret");
1034 I != E; ++
I, ++ArgI)
1035 if (ArgAlive[ArgI]) {
1038 I->replaceAllUsesWith(&*I2);
1051 if (
ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
1053 Value *RetVal =
nullptr;
1055 if (!NFTy->getReturnType()->isVoidTy()) {
1062 Value *OldRet = RI->getOperand(0);
1065 for (
unsigned RetI = 0; RetI != RetCount; ++RetI)
1066 if (NewRetIdxs[RetI] != -1) {
1067 Value *EV = IRB.CreateExtractValue(OldRet, RetI,
"oldret");
1069 if (RetTypes.size() > 1) {
1073 RetVal = IRB.CreateInsertValue(RetVal, EV, NewRetIdxs[RetI],
1086 NewRet->setDebugLoc(RI->getDebugLoc());
1087 RI->eraseFromParent();
1092 F->getAllMetadata(MDs);
1093 for (
auto [KindID,
Node] : MDs)
1094 NF->addMetadata(KindID, *
Node);
1100 if (NFTy != FTy && NF->getSubprogram()) {
1102 auto Temp = SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
1107 F->eraseFromParent();
1112void DeadArgumentEliminationPass::propagateVirtMustcallLiveness(
1117 while (!NewLiveFuncs.empty()) {
1119 for (
const auto *
F : NewLiveFuncs)
1120 for (
const auto *U :
F->users())
1121 if (
const auto *CB = dyn_cast<CallBase>(U))
1124 Temp.insert(CB->
getParent()->getParent());
1125 NewLiveFuncs.clear();
1126 NewLiveFuncs.insert(Temp.begin(), Temp.end());
1127 for (
const auto *
F : Temp)
1134 bool Changed =
false;
1140 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1142 if (
F.getFunctionType()->isVarArg())
1143 Changed |= deleteDeadVarargs(
F);
1148 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1152 propagateVirtMustcallLiveness(M);
1158 Changed |= removeDeadStuffFromFunction(&
F);
1163 Changed |= removeDeadArgumentsFromCallers(
F);
This file contains the simple types necessary to represent the attributes associated with functions a...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
assert(!RetTy->isVoidTy() &&"void type has no subtype")
Convenience function that returns the number of return values It returns for void functions and for functions not returning a struct It returns the number of struct elements for functions returning a struct static unsigned numRetVals(const Function *F)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI optimize exec mask operations pre RA
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static const uint32_t IV[8]
A container for analyses that lazily runs them and caches their results.
This class represents an incoming formal argument to a Function.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
AttributeSet getFnAttrs() const
The function attributes are returned.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
bool isEmpty() const
Return true if there are no attributes.
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Return true if the attribute exists for the given argument.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
static AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
void removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove)
Removes the attributes from the given argument.
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
FunctionType * getFunctionType() const
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
bool isMustTailCall() const
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
DISubprogram * getSubprogram() const
Get the subprogram for this scope.
Eliminate dead arguments (and return values) from functions.
SmallVector< RetOrArg, 5 > UseVector
std::set< const Function * > LiveFuncSet
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Liveness
During our initial pass over the program, we determine that things are either alive or maybe alive.
LiveSet LiveValues
This set contains all values that have been determined to be live.
RetOrArg createRet(const Function *F, unsigned Idx)
Convenience wrapper.
RetOrArg createArg(const Function *F, unsigned Idx)
Convenience wrapper.
bool ShouldHackArguments
This allows this pass to do double-duty as the dead arg hacking pass (used only by bugpoint).
LiveFuncSet LiveFunctions
This set contains all values that are cannot be changed in any way.
UseMap Uses
This maps a return value or argument to any MaybeLive return values or arguments it uses.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void splice(Function::iterator ToIt, Function *FromF)
Transfer all blocks from FromF to this function at ToIt.
bool IsNewDbgInfoFormat
Is this function using intrinsics to record the position of debugging information,...
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Type * getReturnType() const
Returns the type of the ret val.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
void setComdat(Comdat *C)
void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This instruction inserts a struct field of array element value into an aggregate value.
static unsigned getAggregateOperandIndex()
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
A wrapper class for inspecting calls to intrinsic functions.
static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, InsertPosition InsertBefore=nullptr)
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithPermanent(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a permanent one.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
bool skipModule(Module &M) const
Optional passes call this function to check whether the pass should be skipped.
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Return a value (possibly void), from a function.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
bool isUsedByMetadata() const
Return true if there is metadata referencing this value.
iterator_range< use_iterator > uses()
void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
self_iterator getIterator()
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
AttributeMask typeIncompatible(Type *Ty, AttributeSet AS, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createDeadArgEliminationPass()
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void initializeDAEPass(PassRegistry &)
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
ModulePass * createDeadArgHackingPass()
DeadArgHacking pass - Same as DAE, but delete arguments of external functions as well.