55#define DEBUG_TYPE "deadargelim"
57STATISTIC(NumArgumentsEliminated,
"Number of unread args removed");
58STATISTIC(NumRetValsEliminated,
"Number of unused return values removed");
60 "Number of unread args replaced with poison");
86 virtual bool shouldHackArguments()
const {
return false; }
89bool isMustTailCalleeAnalyzable(
const CallBase &CB) {
98INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
104struct DAH :
public DAE {
109 bool shouldHackArguments()
const override {
return true; }
117 "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
false,
128bool DeadArgumentEliminationPass::deleteDeadVarargs(
Function &
F) {
129 assert(
F.getFunctionType()->isVarArg() &&
"Function isn't varargs!");
130 if (
F.isDeclaration() || !
F.hasLocalLinkage())
134 if (
F.hasAddressTaken())
140 if (
F.hasFnAttribute(Attribute::Naked)) {
154 if (
II->getIntrinsicID() == Intrinsic::vastart)
167 std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
169 unsigned NumArgs = Params.size();
175 F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
182 std::vector<Value *>
Args;
184 CallBase *CB = dyn_cast<CallBase>(U);
195 for (
unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
210 cast<CallInst>(NewCB)->setTailCallKind(
211 cast<CallInst>(CB)->getTailCallKind());
215 NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
241 I->replaceAllUsesWith(&*I2);
247 F.getAllMetadata(MDs);
248 for (
auto [KindID,
Node] : MDs)
252 F.replaceAllUsesWith(NF);
263bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(
Function &
F) {
275 if (!
F.hasExactDefinition())
283 !
F.getFunctionType()->isVarArg())
289 if (
F.hasFnAttribute(Attribute::Naked))
296 bool Changed =
false;
301 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() &&
302 !Arg.hasPassPointeeByValueCopyAttr()) {
303 if (Arg.isUsedByMetadata()) {
308 F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes);
312 if (UnusedArgs.
empty())
315 for (
Use &U :
F.uses()) {
316 CallBase *CB = dyn_cast<CallBase>(
U.getUser());
322 for (
unsigned ArgNo : UnusedArgs) {
327 ++NumArgumentsReplacedWithPoison;
340 if (
RetTy->isVoidTy())
343 return STy->getNumElements();
345 return ATy->getNumElements();
357 return STy->getElementType(
Idx);
359 return ATy->getElementType();
366DeadArgumentEliminationPass::markIfNotLive(RetOrArg
Use,
367 UseVector &MaybeLiveUses) {
374 MaybeLiveUses.push_back(
Use);
386DeadArgumentEliminationPass::surveyUse(
const Use *U, UseVector &MaybeLiveUses,
387 unsigned RetValNum) {
388 const User *V = U->getUser();
389 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(V)) {
394 const Function *
F = RI->getParent()->getParent();
395 if (RetValNum != -1U) {
398 return markIfNotLive(
Use, MaybeLiveUses);
408 markIfNotLive(
Use, MaybeLiveUses);
421 RetValNum = *
IV->idx_begin();
427 for (
const Use &UU :
IV->uses()) {
428 Result = surveyUse(&UU, MaybeLiveUses, RetValNum);
435 if (
const auto *CB = dyn_cast<CallBase>(V)) {
450 if (ArgNo >=
F->getFunctionType()->getNumParams())
455 "Argument is not where we expected it");
460 return markIfNotLive(
Use, MaybeLiveUses);
474DeadArgumentEliminationPass::surveyUses(
const Value *V,
475 UseVector &MaybeLiveUses) {
479 for (
const Use &U : V->uses()) {
480 Result = surveyUse(&U, MaybeLiveUses);
493void DeadArgumentEliminationPass::surveyFunction(
const Function &
F) {
496 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
497 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
505 if (
F.hasFnAttribute(Attribute::Naked)) {
515 RetVals RetValLiveness(RetCount,
MaybeLive);
522 RetUses MaybeLiveRetUses(RetCount);
524 bool HasMustTailCalls =
false;
528 if (
const auto *TC = BB.getTerminatingMustTailCall()) {
529 HasMustTailCalls =
true;
533 if (!isMustTailCalleeAnalyzable(*TC)) {
540 if (HasMustTailCalls) {
542 <<
" has musttail calls\n");
551 dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
552 <<
F.getName() <<
"\n");
555 unsigned NumLiveRetVals = 0;
557 bool HasMustTailCallers =
false;
560 for (
const Use &U :
F.uses()) {
563 const auto *CB = dyn_cast<CallBase>(U.getUser());
573 HasMustTailCallers =
true;
579 if (NumLiveRetVals == RetCount)
583 for (
const Use &UU : CB->
uses()) {
587 unsigned Idx = *Ext->idx_begin();
588 if (RetValLiveness[
Idx] !=
Live) {
589 RetValLiveness[
Idx] = surveyUses(Ext, MaybeLiveRetUses[
Idx]);
590 if (RetValLiveness[
Idx] ==
Live)
597 if (surveyUse(&UU, MaybeLiveAggregateUses) ==
Live) {
598 NumLiveRetVals = RetCount;
599 RetValLiveness.assign(RetCount,
Live);
603 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
604 if (RetValLiveness[Ri] !=
Live)
605 MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(),
606 MaybeLiveAggregateUses.end());
612 if (HasMustTailCallers) {
614 <<
" has musttail callers\n");
618 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
619 markValue(
createRet(&
F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]);
621 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
622 <<
F.getName() <<
"\n");
628 AI != E; ++AI, ++ArgI) {
630 if (
F.getFunctionType()->isVarArg() || HasMustTailCallers ||
647 Result = surveyUses(&*AI, MaybeLiveArgUses);
651 markValue(
createArg(&
F, ArgI), Result, MaybeLiveArgUses);
653 MaybeLiveArgUses.clear();
660void DeadArgumentEliminationPass::markValue(
const RetOrArg &
RA, Liveness L,
661 const UseVector &MaybeLiveUses) {
667 assert(!isLive(
RA) &&
"Use is already live!");
668 for (
const auto &MaybeLiveUse : MaybeLiveUses) {
669 if (isLive(MaybeLiveUse)) {
676 Uses.emplace(MaybeLiveUse,
RA);
685void DeadArgumentEliminationPass::markLive(
const Function &
F) {
686 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Intrinsically live fn: "
687 <<
F.getName() <<
"\n");
691 for (
unsigned ArgI = 0, E =
F.arg_size(); ArgI != E; ++ArgI)
694 for (
unsigned Ri = 0, E =
numRetVals(&
F); Ri != E; ++Ri)
700void DeadArgumentEliminationPass::markLive(
const RetOrArg &
RA) {
707 <<
RA.getDescription() <<
" live\n");
708 propagateLiveness(
RA);
711bool DeadArgumentEliminationPass::isLive(
const RetOrArg &
RA) {
717void DeadArgumentEliminationPass::propagateLiveness(
const RetOrArg &
RA) {
721 UseMap::iterator Begin =
Uses.lower_bound(
RA);
722 UseMap::iterator E =
Uses.end();
724 for (
I = Begin;
I != E &&
I->first ==
RA; ++
I)
729 Uses.erase(Begin,
I);
735bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(
Function *
F) {
743 std::vector<Type *> Params;
746 bool HasLiveReturnedArg =
false;
762 Params.push_back(
I->getType());
763 ArgAlive[ArgI] =
true;
765 HasLiveReturnedArg |= PAL.
hasParamAttr(ArgI, Attribute::Returned);
767 ++NumArgumentsEliminated;
768 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing argument "
769 << ArgI <<
" (" <<
I->getName() <<
") from "
770 <<
F->getName() <<
"\n");
776 Type *NRetTy =
nullptr;
781 std::vector<Type *> RetTypes;
802 if (
RetTy->isVoidTy() || HasLiveReturnedArg) {
806 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
809 RetTypes.push_back(getRetComponentType(
F, Ri));
810 NewRetIdxs[Ri] = RetTypes.size() - 1;
812 ++NumRetValsEliminated;
814 dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
815 << Ri <<
" from " <<
F->getName() <<
"\n");
818 if (RetTypes.size() > 1) {
823 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
825 assert(isa<ArrayType>(
RetTy) &&
"unexpected multi-value return");
828 }
else if (RetTypes.size() == 1)
831 NRetTy = RetTypes.front();
832 else if (RetTypes.empty())
837 assert(NRetTy &&
"No new return type found?");
850 "Return attributes no longer compatible?");
877 F->getParent()->getFunctionList().insert(
F->getIterator(), NF);
883 std::vector<Value *>
Args;
884 while (!
F->use_empty()) {
885 CallBase &CB = cast<CallBase>(*
F->user_back());
902 for (
unsigned E = FTy->getNumParams(); Pi != E; ++
I, ++Pi)
907 if (NRetTy !=
RetTy &&
Attrs.hasAttribute(Attribute::Returned)) {
923 for (
auto *E = CB.
arg_end();
I != E; ++
I, ++Pi) {
934 F->getContext(), Attribute::AllocSize);
948 cast<CallInst>(NewCB)->setTailCallKind(
949 cast<CallInst>(&CB)->getTailCallKind());
953 NewCB->
copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
968 "Return type changed, but not into a void. The old return type"
969 " must have been a struct or an array!");
983 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
984 if (NewRetIdxs[Ri] != -1) {
987 if (RetTypes.size() > 1)
990 V = IRB.CreateExtractValue(NewCB, NewRetIdxs[Ri],
"newret");
995 RetVal = IRB.CreateInsertValue(RetVal, V, Ri,
"oldret");
1019 I != E; ++
I, ++ArgI)
1020 if (ArgAlive[ArgI]) {
1023 I->replaceAllUsesWith(&*I2);
1036 if (
ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
1038 Value *RetVal =
nullptr;
1040 if (!NFTy->getReturnType()->isVoidTy()) {
1047 Value *OldRet = RI->getOperand(0);
1050 for (
unsigned RetI = 0; RetI != RetCount; ++RetI)
1051 if (NewRetIdxs[RetI] != -1) {
1052 Value *EV = IRB.CreateExtractValue(OldRet, RetI,
"oldret");
1054 if (RetTypes.size() > 1) {
1058 RetVal = IRB.CreateInsertValue(RetVal, EV, NewRetIdxs[RetI],
1071 NewRet->setDebugLoc(RI->getDebugLoc());
1072 RI->eraseFromParent();
1077 F->getAllMetadata(MDs);
1078 for (
auto [KindID,
Node] : MDs)
1079 NF->addMetadata(KindID, *
Node);
1085 if (NFTy != FTy && NF->getSubprogram()) {
1087 auto Temp = SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
1092 F->eraseFromParent();
1097void DeadArgumentEliminationPass::propagateVirtMustcallLiveness(
1102 while (!NewLiveFuncs.empty()) {
1104 for (
const auto *
F : NewLiveFuncs)
1105 for (
const auto *U :
F->users())
1106 if (
const auto *CB = dyn_cast<CallBase>(U))
1109 Temp.insert(CB->
getParent()->getParent());
1110 NewLiveFuncs.clear();
1111 NewLiveFuncs.insert(Temp.begin(), Temp.end());
1112 for (
const auto *
F : Temp)
1119 bool Changed =
false;
1125 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1127 if (
F.getFunctionType()->isVarArg())
1128 Changed |= deleteDeadVarargs(
F);
1133 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1137 propagateVirtMustcallLiveness(M);
1143 Changed |= removeDeadStuffFromFunction(&
F);
1148 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)
This defines the Use class.
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
This header defines various interfaces for pass management in LLVM.
#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 parameter 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 parameter 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, 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.
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.