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");
74 DAE() : ModulePass(ID) {}
76 bool runOnModule(
Module &M)
override {
79 DeadArgumentEliminationPass DAEP;
81 PreservedAnalyses PA = DAEP.
run(M, DummyMAM);
90INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
98bool DeadArgumentEliminationPass::deleteDeadVarargs(
Function &
F) {
99 assert(
F.getFunctionType()->isVarArg() &&
"Function isn't varargs!");
100 if (
F.isDeclaration() || !
F.hasLocalLinkage())
104 if (
F.hasAddressTaken())
110 if (
F.hasFnAttribute(Attribute::Naked)) {
116 for (BasicBlock &BB :
F) {
117 for (Instruction &
I : BB) {
124 if (
II->getIntrinsicID() == Intrinsic::vastart)
135 FunctionType *FTy =
F.getFunctionType();
137 std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
139 unsigned NumArgs = Params.size();
145 F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
151 std::vector<Value *>
Args;
162 if (!PAL.isEmpty()) {
164 for (
unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
165 ArgAttrs.
push_back(PAL.getParamAttrs(ArgNo));
166 PAL = AttributeList::get(
F.getContext(), PAL.getFnAttrs(),
167 PAL.getRetAttrs(), ArgAttrs);
173 CallBase *NewCB =
nullptr;
184 NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
210 I->replaceAllUsesWith(&*I2);
216 F.getAllMetadata(MDs);
217 for (
auto [KindID, Node] : MDs)
221 F.replaceAllUsesWith(NF);
232bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(
Function &
F) {
244 if (!
F.hasExactDefinition())
252 !
F.getFunctionType()->isVarArg())
258 if (
F.hasFnAttribute(Attribute::Naked))
264 SmallVector<unsigned, 8> UnusedArgs;
267 AttributeMask UBImplyingAttributes =
268 AttributeFuncs::getUBImplyingAttributes();
269 for (Argument &Arg :
F.args()) {
270 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() &&
271 !Arg.hasPassPointeeByValueCopyAttr()) {
272 if (Arg.isUsedByMetadata()) {
277 F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes);
281 if (UnusedArgs.
empty())
284 for (Use &U :
F.uses()) {
291 for (
unsigned ArgNo : UnusedArgs) {
296 ++NumArgumentsReplacedWithPoison;
308 Type *RetTy =
F->getReturnType();
312 return STy->getNumElements();
314 return ATy->getNumElements();
322 Type *RetTy =
F->getReturnType();
326 return STy->getElementType(Idx);
328 return ATy->getElementType();
335DeadArgumentEliminationPass::markIfNotLive(RetOrArg
Use,
336 UseVector &MaybeLiveUses) {
343 MaybeLiveUses.push_back(Use);
355DeadArgumentEliminationPass::surveyUse(
const Use *U, UseVector &MaybeLiveUses,
356 unsigned RetValNum) {
357 const User *
V =
U->getUser();
363 const Function *
F = RI->getParent()->getParent();
364 if (RetValNum != -1U) {
367 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);
419 if (ArgNo >=
F->getFunctionType()->getNumParams())
424 "Argument is not where we expected it");
429 return markIfNotLive(Use, MaybeLiveUses);
443DeadArgumentEliminationPass::surveyUses(
const Value *V,
444 UseVector &MaybeLiveUses) {
448 for (
const Use &U :
V->uses()) {
449 Result = surveyUse(&U, MaybeLiveUses);
462void DeadArgumentEliminationPass::surveyFunction(
const Function &
F) {
464 if (!
F.hasLocalLinkage()) {
471 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
472 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
480 if (
F.hasFnAttribute(Attribute::Naked)) {
490 RetVals RetValLiveness(RetCount,
MaybeLive);
497 RetUses MaybeLiveRetUses(RetCount);
499 for (
const BasicBlock &BB :
F) {
500 if (BB.getTerminatingMustTailCall()) {
502 <<
" has musttail calls\n");
503 if (markFnOrRetTyFrozenOnMusttail(
F))
509 dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
510 <<
F.getName() <<
"\n");
513 unsigned NumLiveRetVals = 0;
516 for (
const Use &U :
F.uses()) {
528 <<
" has musttail callers\n");
529 if (markFnOrRetTyFrozenOnMusttail(
F))
537 if (NumLiveRetVals == RetCount)
541 for (
const Use &UU : CB->
uses()) {
545 unsigned Idx = *Ext->idx_begin();
546 if (RetValLiveness[Idx] !=
Live) {
547 RetValLiveness[Idx] = surveyUses(Ext, MaybeLiveRetUses[Idx]);
548 if (RetValLiveness[Idx] ==
Live)
555 if (surveyUse(&UU, MaybeLiveAggregateUses) ==
Live) {
556 NumLiveRetVals = RetCount;
557 RetValLiveness.assign(RetCount,
Live);
561 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
562 if (RetValLiveness[Ri] !=
Live)
563 MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(),
564 MaybeLiveAggregateUses.end());
571 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
572 markValue(
createRet(&
F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]);
574 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
575 <<
F.getName() <<
"\n");
581 AI !=
E; ++AI, ++ArgI) {
583 if (
F.getFunctionType()->isVarArg()) {
593 Result = surveyUses(&*AI, MaybeLiveArgUses);
597 markValue(
createArg(&
F, ArgI), Result, MaybeLiveArgUses);
599 MaybeLiveArgUses.clear();
606void DeadArgumentEliminationPass::markValue(
const RetOrArg &
RA, Liveness L,
607 const UseVector &MaybeLiveUses) {
613 assert(!isLive(
RA) &&
"Use is already live!");
614 for (
const auto &MaybeLiveUse : MaybeLiveUses) {
615 if (isLive(MaybeLiveUse)) {
622 Uses.emplace(MaybeLiveUse,
RA);
632bool DeadArgumentEliminationPass::markFnOrRetTyFrozenOnMusttail(
647void DeadArgumentEliminationPass::markFrozen(
const Function &
F) {
649 <<
F.getName() <<
"\n");
653 for (
unsigned ArgI = 0,
E =
F.arg_size(); ArgI !=
E; ++ArgI)
660void DeadArgumentEliminationPass::markRetTyFrozen(
const Function &
F) {
661 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - frozen return type fn: "
662 <<
F.getName() <<
"\n");
668void DeadArgumentEliminationPass::markLive(
const RetOrArg &
RA) {
675 <<
RA.getDescription() <<
" live\n");
676 propagateLiveness(
RA);
679bool DeadArgumentEliminationPass::isLive(
const RetOrArg &
RA) {
685void DeadArgumentEliminationPass::propagateLiveness(
const RetOrArg &
RA) {
689 UseMap::iterator Begin =
Uses.lower_bound(
RA);
690 UseMap::iterator
E =
Uses.end();
692 for (
I = Begin;
I !=
E &&
I->first ==
RA; ++
I)
697 Uses.erase(Begin,
I);
703bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(
Function *
F) {
710 FunctionType *FTy =
F->getFunctionType();
711 std::vector<Type *> Params;
714 bool HasLiveReturnedArg =
false;
718 const AttributeList &PAL =
F->getAttributes();
719 OptimizationRemarkEmitter ORE(
F);
731 Params.push_back(
I->getType());
732 ArgAlive[ArgI] =
true;
733 ArgAttrVec.
push_back(PAL.getParamAttrs(ArgI));
734 HasLiveReturnedArg |= PAL.hasParamAttr(ArgI, Attribute::Returned);
736 ++NumArgumentsEliminated;
739 return OptimizationRemark(
DEBUG_TYPE,
"ArgumentRemoved",
F)
740 <<
"eliminating argument " <<
ore::NV(
"ArgName",
I->getName())
741 <<
"(" <<
ore::NV(
"ArgIndex", ArgI) <<
")";
743 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing argument "
744 << ArgI <<
" (" <<
I->getName() <<
") from "
745 <<
F->getName() <<
"\n");
750 Type *RetTy = FTy->getReturnType();
751 Type *NRetTy =
nullptr;
756 std::vector<Type *> RetTypes;
777 if (RetTy->
isVoidTy() || HasLiveReturnedArg ||
782 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
786 NewRetIdxs[Ri] = RetTypes.size() - 1;
788 ++NumRetValsEliminated;
791 return OptimizationRemark(
DEBUG_TYPE,
"ReturnValueRemoved",
F)
792 <<
"removing return value " << std::to_string(Ri);
795 dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
796 << Ri <<
" from " <<
F->getName() <<
"\n");
799 if (RetTypes.size() > 1) {
804 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
809 }
else if (RetTypes.size() == 1)
812 NRetTy = RetTypes.front();
813 else if (RetTypes.empty())
818 assert(NRetTy &&
"No new return type found?");
821 AttrBuilder RAttrs(
F->getContext(), PAL.getRetAttrs());
828 RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs()));
831 AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs())) &&
832 "Return attributes no longer compatible?");
837 AttributeSet FnAttrs =
838 PAL.getFnAttrs().removeAttribute(
F->getContext(), Attribute::AllocSize);
842 AttributeList NewPAL =
843 AttributeList::get(
F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
859 F->getParent()->getFunctionList().insert(
F->getIterator(), NF);
864 std::vector<Value *>
Args;
865 while (!
F->use_empty()) {
873 AttrBuilder RAttrs(
F->getContext(), CallPAL.getRetAttrs());
875 AttributeFuncs::typeIncompatible(NRetTy, CallPAL.getRetAttrs()));
884 for (
unsigned E = FTy->getNumParams(); Pi !=
E; ++
I, ++Pi)
888 AttributeSet
Attrs = CallPAL.getParamAttrs(Pi);
889 if (NRetTy != RetTy &&
Attrs.hasAttribute(Attribute::Returned)) {
896 F->getContext(), AttrBuilder(
F->getContext(), Attrs)
897 .removeAttribute(Attribute::Returned)));
907 ArgAttrVec.
push_back(CallPAL.getParamAttrs(Pi));
915 AttributeSet FnAttrs = CallPAL.getFnAttrs().removeAttribute(
916 F->getContext(), Attribute::AllocSize);
918 AttributeList NewCallPAL =
919 AttributeList::get(
F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
924 CallBase *NewCB =
nullptr;
935 NewCB->
copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
950 "Return type changed, but not into a void. The old return type"
951 " must have been a struct or an array!");
965 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
966 if (NewRetIdxs[Ri] != -1) {
969 if (RetTypes.size() > 1)
972 V = IRB.CreateExtractValue(NewCB, NewRetIdxs[Ri],
"newret");
977 RetVal = IRB.CreateInsertValue(RetVal, V, Ri,
"oldret");
1001 I !=
E; ++
I, ++ArgI)
1002 if (ArgAlive[ArgI]) {
1005 I->replaceAllUsesWith(&*I2);
1017 for (BasicBlock &BB : *NF)
1020 Value *RetVal =
nullptr;
1022 if (!NFTy->getReturnType()->isVoidTy()) {
1029 Value *OldRet = RI->getOperand(0);
1032 for (
unsigned RetI = 0; RetI != RetCount; ++RetI)
1033 if (NewRetIdxs[RetI] != -1) {
1034 Value *EV = IRB.CreateExtractValue(OldRet, RetI,
"oldret");
1036 if (RetTypes.size() > 1) {
1040 RetVal = IRB.CreateInsertValue(RetVal, EV, NewRetIdxs[RetI],
1053 NewRet->setDebugLoc(RI->getDebugLoc());
1054 RI->eraseFromParent();
1059 F->getAllMetadata(MDs);
1060 for (
auto [KindID, Node] : MDs)
1061 NF->addMetadata(KindID, *Node);
1067 if (NFTy != FTy && NF->getSubprogram()) {
1068 DISubprogram *
SP = NF->getSubprogram();
1069 auto Temp =
SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
1074 F->eraseFromParent();
1087 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1089 if (
F.getFunctionType()->isVarArg())
1095 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1103 Changed |= removeDeadStuffFromFunction(&
F);
1108 Changed |= removeDeadArgumentsFromCallers(
F);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static Type * getRetComponentType(const Function *F, unsigned Idx)
Returns the sub-type a function will return at a given Idx.
static unsigned numRetVals(const Function *F)
Convenience function that returns the number of return values.
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.
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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]
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
void setCallingConv(CallingConv::ID CC)
void removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove)
Removes the attributes from the given argument.
LLVM_ABI 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.
LLVM_ABI 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.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
bool isMustTailCall() const
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
SmallVector< RetOrArg, 5 > UseVector
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
FuncSet FrozenRetTyFunctions
This set contains all functions that cannot change return type;.
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.
FuncSet FrozenFunctions
This set contains all functions that 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 LLVM_ABI 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.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
Type * getReturnType() const
Returns the type of the ret val.
const Argument * const_arg_iterator
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
LLVM_ABI void setComdat(Comdat *C)
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
static unsigned getAggregateOperandIndex()
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
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...
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI 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.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
void push_back(const T &Elt)
Class to represent struct types.
static LLVM_ABI 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.
bool isArrayTy() const
True if this is an instance of ArrayType.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
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.
LLVM_ABI 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()
LLVM_ABI 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ BasicBlock
Various leaf nodes.
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI ModulePass * createDeadArgEliminationPass()
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI 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...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Struct that represents (part of) either a return value or a function argument.