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; }
94INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
100struct DAH :
public DAE {
105 bool shouldHackArguments()
const override {
return true; }
113 "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
false,
124bool DeadArgumentEliminationPass::deleteDeadVarargs(
Function &
F) {
125 assert(
F.getFunctionType()->isVarArg() &&
"Function isn't varargs!");
126 if (
F.isDeclaration() || !
F.hasLocalLinkage())
130 if (
F.hasAddressTaken())
136 if (
F.hasFnAttribute(Attribute::Naked)) {
150 if (
II->getIntrinsicID() == Intrinsic::vastart)
163 std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
165 unsigned NumArgs = Params.size();
171 F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
177 std::vector<Value *>
Args;
179 CallBase *CB = dyn_cast<CallBase>(U);
190 for (
unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
205 cast<CallInst>(NewCB)->setTailCallKind(
206 cast<CallInst>(CB)->getTailCallKind());
210 NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
236 I->replaceAllUsesWith(&*I2);
242 F.getAllMetadata(MDs);
243 for (
auto [KindID,
Node] : MDs)
247 F.replaceAllUsesWith(NF);
258bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(
Function &
F) {
270 if (!
F.hasExactDefinition())
278 !
F.getFunctionType()->isVarArg())
284 if (
F.hasFnAttribute(Attribute::Naked))
291 bool Changed =
false;
296 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() &&
297 !Arg.hasPassPointeeByValueCopyAttr()) {
298 if (Arg.isUsedByMetadata()) {
303 F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes);
307 if (UnusedArgs.
empty())
310 for (
Use &U :
F.uses()) {
311 CallBase *CB = dyn_cast<CallBase>(
U.getUser());
317 for (
unsigned ArgNo : UnusedArgs) {
322 ++NumArgumentsReplacedWithPoison;
335 if (
RetTy->isVoidTy())
338 return STy->getNumElements();
340 return ATy->getNumElements();
352 return STy->getElementType(
Idx);
354 return ATy->getElementType();
361DeadArgumentEliminationPass::markIfNotLive(RetOrArg
Use,
362 UseVector &MaybeLiveUses) {
369 MaybeLiveUses.push_back(
Use);
381DeadArgumentEliminationPass::surveyUse(
const Use *U, UseVector &MaybeLiveUses,
382 unsigned RetValNum) {
383 const User *V = U->getUser();
384 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(V)) {
389 const Function *
F = RI->getParent()->getParent();
390 if (RetValNum != -1U) {
393 return markIfNotLive(
Use, MaybeLiveUses);
403 markIfNotLive(
Use, MaybeLiveUses);
416 RetValNum = *
IV->idx_begin();
422 for (
const Use &UU :
IV->uses()) {
423 Result = surveyUse(&UU, MaybeLiveUses, RetValNum);
430 if (
const auto *CB = dyn_cast<CallBase>(V)) {
445 if (ArgNo >=
F->getFunctionType()->getNumParams())
450 "Argument is not where we expected it");
455 return markIfNotLive(
Use, MaybeLiveUses);
469DeadArgumentEliminationPass::surveyUses(
const Value *V,
470 UseVector &MaybeLiveUses) {
474 for (
const Use &U : V->uses()) {
475 Result = surveyUse(&U, MaybeLiveUses);
488void DeadArgumentEliminationPass::surveyFunction(
const Function &
F) {
491 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
492 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
500 if (
F.hasFnAttribute(Attribute::Naked)) {
510 RetVals RetValLiveness(RetCount,
MaybeLive);
517 RetUses MaybeLiveRetUses(RetCount);
520 if (BB.getTerminatingMustTailCall()) {
522 <<
" has musttail calls\n");
523 if (markFnOrRetTyFrozenOnMusttail(
F))
534 dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
535 <<
F.getName() <<
"\n");
538 unsigned NumLiveRetVals = 0;
541 for (
const Use &U :
F.uses()) {
544 const auto *CB = dyn_cast<CallBase>(U.getUser());
553 <<
" has musttail callers\n");
554 if (markFnOrRetTyFrozenOnMusttail(
F))
562 if (NumLiveRetVals == RetCount)
566 for (
const Use &UU : CB->
uses()) {
570 unsigned Idx = *Ext->idx_begin();
571 if (RetValLiveness[
Idx] !=
Live) {
572 RetValLiveness[
Idx] = surveyUses(Ext, MaybeLiveRetUses[
Idx]);
573 if (RetValLiveness[
Idx] ==
Live)
580 if (surveyUse(&UU, MaybeLiveAggregateUses) ==
Live) {
581 NumLiveRetVals = RetCount;
582 RetValLiveness.assign(RetCount,
Live);
586 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
587 if (RetValLiveness[Ri] !=
Live)
588 MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(),
589 MaybeLiveAggregateUses.end());
596 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
597 markValue(
createRet(&
F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]);
599 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
600 <<
F.getName() <<
"\n");
606 AI != E; ++AI, ++ArgI) {
608 if (
F.getFunctionType()->isVarArg()) {
618 Result = surveyUses(&*AI, MaybeLiveArgUses);
622 markValue(
createArg(&
F, ArgI), Result, MaybeLiveArgUses);
624 MaybeLiveArgUses.clear();
631void DeadArgumentEliminationPass::markValue(
const RetOrArg &
RA, Liveness L,
632 const UseVector &MaybeLiveUses) {
638 assert(!isLive(
RA) &&
"Use is already live!");
639 for (
const auto &MaybeLiveUse : MaybeLiveUses) {
640 if (isLive(MaybeLiveUse)) {
647 Uses.emplace(MaybeLiveUse,
RA);
657bool DeadArgumentEliminationPass::markFnOrRetTyFrozenOnMusttail(
672void DeadArgumentEliminationPass::markFrozen(
const Function &
F) {
674 <<
F.getName() <<
"\n");
678 for (
unsigned ArgI = 0, E =
F.arg_size(); ArgI != E; ++ArgI)
681 for (
unsigned Ri = 0, E =
numRetVals(&
F); Ri != E; ++Ri)
685void DeadArgumentEliminationPass::markRetTyFrozen(
const Function &
F) {
686 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - frozen return type fn: "
687 <<
F.getName() <<
"\n");
693void DeadArgumentEliminationPass::markLive(
const RetOrArg &
RA) {
700 <<
RA.getDescription() <<
" live\n");
701 propagateLiveness(
RA);
704bool DeadArgumentEliminationPass::isLive(
const RetOrArg &
RA) {
710void DeadArgumentEliminationPass::propagateLiveness(
const RetOrArg &
RA) {
714 UseMap::iterator Begin =
Uses.lower_bound(
RA);
715 UseMap::iterator E =
Uses.end();
717 for (
I = Begin;
I != E &&
I->first ==
RA; ++
I)
722 Uses.erase(Begin,
I);
728bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(
Function *
F) {
736 std::vector<Type *> Params;
739 bool HasLiveReturnedArg =
false;
756 Params.push_back(
I->getType());
757 ArgAlive[ArgI] =
true;
759 HasLiveReturnedArg |= PAL.
hasParamAttr(ArgI, Attribute::Returned);
761 ++NumArgumentsEliminated;
765 <<
"eliminating argument " <<
ore::NV(
"ArgName",
I->getName())
766 <<
"(" <<
ore::NV(
"ArgIndex", ArgI) <<
")";
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 ||
807 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
810 RetTypes.push_back(getRetComponentType(
F, Ri));
811 NewRetIdxs[Ri] = RetTypes.size() - 1;
813 ++NumRetValsEliminated;
817 <<
"removing return value " << std::to_string(Ri);
820 dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
821 << Ri <<
" from " <<
F->getName() <<
"\n");
824 if (RetTypes.size() > 1) {
829 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
831 assert(isa<ArrayType>(
RetTy) &&
"unexpected multi-value return");
834 }
else if (RetTypes.size() == 1)
837 NRetTy = RetTypes.front();
838 else if (RetTypes.empty())
843 assert(NRetTy &&
"No new return type found?");
857 "Return attributes no longer compatible?");
884 F->getParent()->getFunctionList().insert(
F->getIterator(), NF);
889 std::vector<Value *>
Args;
890 while (!
F->use_empty()) {
891 CallBase &CB = cast<CallBase>(*
F->user_back());
909 for (
unsigned E = FTy->getNumParams(); Pi != E; ++
I, ++Pi)
914 if (NRetTy !=
RetTy &&
Attrs.hasAttribute(Attribute::Returned)) {
930 for (
auto *E = CB.
arg_end();
I != E; ++
I, ++Pi) {
941 F->getContext(), Attribute::AllocSize);
955 cast<CallInst>(NewCB)->setTailCallKind(
956 cast<CallInst>(&CB)->getTailCallKind());
960 NewCB->
copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
975 "Return type changed, but not into a void. The old return type"
976 " must have been a struct or an array!");
990 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
991 if (NewRetIdxs[Ri] != -1) {
994 if (RetTypes.size() > 1)
997 V = IRB.CreateExtractValue(NewCB, NewRetIdxs[Ri],
"newret");
1002 RetVal = IRB.CreateInsertValue(RetVal, V, Ri,
"oldret");
1026 I != E; ++
I, ++ArgI)
1027 if (ArgAlive[ArgI]) {
1030 I->replaceAllUsesWith(&*I2);
1043 if (
ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
1045 Value *RetVal =
nullptr;
1047 if (!NFTy->getReturnType()->isVoidTy()) {
1054 Value *OldRet = RI->getOperand(0);
1057 for (
unsigned RetI = 0; RetI != RetCount; ++RetI)
1058 if (NewRetIdxs[RetI] != -1) {
1059 Value *EV = IRB.CreateExtractValue(OldRet, RetI,
"oldret");
1061 if (RetTypes.size() > 1) {
1065 RetVal = IRB.CreateInsertValue(RetVal, EV, NewRetIdxs[RetI],
1078 NewRet->setDebugLoc(RI->getDebugLoc());
1079 RI->eraseFromParent();
1084 F->getAllMetadata(MDs);
1085 for (
auto [KindID,
Node] : MDs)
1086 NF->addMetadata(KindID, *
Node);
1092 if (NFTy != FTy && NF->getSubprogram()) {
1094 auto Temp =
SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
1099 F->eraseFromParent();
1106 bool Changed =
false;
1112 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1114 if (
F.getFunctionType()->isVarArg())
1115 Changed |= deleteDeadVarargs(
F);
1120 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1128 Changed |= removeDeadStuffFromFunction(&
F);
1133 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...
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
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)
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 LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_ABI AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
LLVM_ABI AttributeSet getFnAttrs() const
The function attributes are returned.
static LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
LLVM_ABI AttributeSet removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Remove the specified attribute from this set.
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM Basic Block Representation.
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...
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.
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.
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
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
Subprogram description. Uses SubclassData1.
Eliminate dead arguments (and return values) from functions.
SmallVector< RetOrArg, 5 > UseVector
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.
bool ShouldHackArguments
This allows this pass to do double-duty as the dead arg hacking pass (used only by bugpoint).
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.
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.
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()
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.
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(const 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 LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
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 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.
static LLVM_ABI 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.
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.
LLVM_ABI AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
LLVM_ABI 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.
@ 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 ...
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
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.
LLVM_ABI void initializeDAEPass(PassRegistry &)
LLVM_ABI ModulePass * createDeadArgEliminationPass()
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
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...
LLVM_ABI ModulePass * createDeadArgHackingPass()
DeadArgHacking pass - Same as DAE, but delete arguments of external functions as well.