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(shouldHackArguments());
81 PreservedAnalyses PA = DAEP.run(M, DummyMAM);
85 virtual bool shouldHackArguments()
const {
return false; }
92INITIALIZE_PASS(DAE,
"deadargelim",
"Dead Argument Elimination",
false,
false)
98struct DAH :
public DAE {
103 bool shouldHackArguments()
const override {
return true; }
111 "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)",
false,
122bool DeadArgumentEliminationPass::deleteDeadVarargs(
Function &
F) {
123 assert(
F.getFunctionType()->isVarArg() &&
"Function isn't varargs!");
124 if (
F.isDeclaration() || !
F.hasLocalLinkage())
128 if (
F.hasAddressTaken())
134 if (
F.hasFnAttribute(Attribute::Naked)) {
140 for (BasicBlock &BB :
F) {
141 for (Instruction &
I : BB) {
148 if (
II->getIntrinsicID() == Intrinsic::vastart)
159 FunctionType *FTy =
F.getFunctionType();
161 std::vector<Type *> Params(FTy->param_begin(), FTy->param_end());
163 unsigned NumArgs = Params.size();
169 F.getParent()->getFunctionList().insert(
F.getIterator(), NF);
175 std::vector<Value *>
Args;
186 if (!PAL.isEmpty()) {
188 for (
unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo)
189 ArgAttrs.
push_back(PAL.getParamAttrs(ArgNo));
190 PAL = AttributeList::get(
F.getContext(), PAL.getFnAttrs(),
191 PAL.getRetAttrs(), ArgAttrs);
197 CallBase *NewCB =
nullptr;
208 NewCB->
copyMetadata(*CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
234 I->replaceAllUsesWith(&*I2);
240 F.getAllMetadata(MDs);
241 for (
auto [KindID, Node] : MDs)
245 F.replaceAllUsesWith(NF);
256bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(
Function &
F) {
268 if (!
F.hasExactDefinition())
276 !
F.getFunctionType()->isVarArg())
282 if (
F.hasFnAttribute(Attribute::Naked))
288 SmallVector<unsigned, 8> UnusedArgs;
291 AttributeMask UBImplyingAttributes =
292 AttributeFuncs::getUBImplyingAttributes();
293 for (Argument &Arg :
F.args()) {
294 if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() &&
295 !Arg.hasPassPointeeByValueCopyAttr()) {
296 if (Arg.isUsedByMetadata()) {
301 F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes);
305 if (UnusedArgs.
empty())
308 for (Use &U :
F.uses()) {
315 for (
unsigned ArgNo : UnusedArgs) {
320 ++NumArgumentsReplacedWithPoison;
332 Type *RetTy =
F->getReturnType();
336 return STy->getNumElements();
338 return ATy->getNumElements();
346 Type *RetTy =
F->getReturnType();
350 return STy->getElementType(Idx);
352 return ATy->getElementType();
359DeadArgumentEliminationPass::markIfNotLive(RetOrArg
Use,
360 UseVector &MaybeLiveUses) {
367 MaybeLiveUses.push_back(Use);
379DeadArgumentEliminationPass::surveyUse(
const Use *U, UseVector &MaybeLiveUses,
380 unsigned RetValNum) {
381 const User *
V =
U->getUser();
387 const Function *
F = RI->getParent()->getParent();
388 if (RetValNum != -1U) {
391 return markIfNotLive(Use, MaybeLiveUses);
401 markIfNotLive(Use, MaybeLiveUses);
414 RetValNum = *
IV->idx_begin();
420 for (
const Use &UU :
IV->uses()) {
421 Result = surveyUse(&UU, MaybeLiveUses, RetValNum);
443 if (ArgNo >=
F->getFunctionType()->getNumParams())
448 "Argument is not where we expected it");
453 return markIfNotLive(Use, MaybeLiveUses);
467DeadArgumentEliminationPass::surveyUses(
const Value *V,
468 UseVector &MaybeLiveUses) {
472 for (
const Use &U :
V->uses()) {
473 Result = surveyUse(&U, MaybeLiveUses);
486void DeadArgumentEliminationPass::surveyFunction(
const Function &
F) {
489 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
490 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
498 if (
F.hasFnAttribute(Attribute::Naked)) {
508 RetVals RetValLiveness(RetCount,
MaybeLive);
515 RetUses MaybeLiveRetUses(RetCount);
517 for (
const BasicBlock &BB :
F) {
518 if (BB.getTerminatingMustTailCall()) {
520 <<
" has musttail calls\n");
521 if (markFnOrRetTyFrozenOnMusttail(
F))
532 dbgs() <<
"DeadArgumentEliminationPass - Inspecting callers for fn: "
533 <<
F.getName() <<
"\n");
536 unsigned NumLiveRetVals = 0;
539 for (
const Use &U :
F.uses()) {
551 <<
" has musttail callers\n");
552 if (markFnOrRetTyFrozenOnMusttail(
F))
560 if (NumLiveRetVals == RetCount)
564 for (
const Use &UU : CB->
uses()) {
568 unsigned Idx = *Ext->idx_begin();
569 if (RetValLiveness[Idx] !=
Live) {
570 RetValLiveness[Idx] = surveyUses(Ext, MaybeLiveRetUses[Idx]);
571 if (RetValLiveness[Idx] ==
Live)
578 if (surveyUse(&UU, MaybeLiveAggregateUses) ==
Live) {
579 NumLiveRetVals = RetCount;
580 RetValLiveness.assign(RetCount,
Live);
584 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
585 if (RetValLiveness[Ri] !=
Live)
586 MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(),
587 MaybeLiveAggregateUses.end());
594 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
595 markValue(
createRet(&
F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]);
597 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Inspecting args for fn: "
598 <<
F.getName() <<
"\n");
604 AI !=
E; ++AI, ++ArgI) {
606 if (
F.getFunctionType()->isVarArg()) {
616 Result = surveyUses(&*AI, MaybeLiveArgUses);
620 markValue(
createArg(&
F, ArgI), Result, MaybeLiveArgUses);
622 MaybeLiveArgUses.clear();
629void DeadArgumentEliminationPass::markValue(
const RetOrArg &
RA, Liveness L,
630 const UseVector &MaybeLiveUses) {
636 assert(!isLive(
RA) &&
"Use is already live!");
637 for (
const auto &MaybeLiveUse : MaybeLiveUses) {
638 if (isLive(MaybeLiveUse)) {
645 Uses.emplace(MaybeLiveUse,
RA);
655bool DeadArgumentEliminationPass::markFnOrRetTyFrozenOnMusttail(
670void DeadArgumentEliminationPass::markFrozen(
const Function &
F) {
672 <<
F.getName() <<
"\n");
676 for (
unsigned ArgI = 0,
E =
F.arg_size(); ArgI !=
E; ++ArgI)
683void DeadArgumentEliminationPass::markRetTyFrozen(
const Function &
F) {
684 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - frozen return type fn: "
685 <<
F.getName() <<
"\n");
691void DeadArgumentEliminationPass::markLive(
const RetOrArg &
RA) {
698 <<
RA.getDescription() <<
" live\n");
699 propagateLiveness(
RA);
702bool DeadArgumentEliminationPass::isLive(
const RetOrArg &
RA) {
708void DeadArgumentEliminationPass::propagateLiveness(
const RetOrArg &
RA) {
712 UseMap::iterator Begin =
Uses.lower_bound(
RA);
713 UseMap::iterator
E =
Uses.end();
715 for (
I = Begin;
I !=
E &&
I->first ==
RA; ++
I)
720 Uses.erase(Begin,
I);
726bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(
Function *
F) {
733 FunctionType *FTy =
F->getFunctionType();
734 std::vector<Type *> Params;
737 bool HasLiveReturnedArg =
false;
741 const AttributeList &PAL =
F->getAttributes();
742 OptimizationRemarkEmitter ORE(
F);
754 Params.push_back(
I->getType());
755 ArgAlive[ArgI] =
true;
756 ArgAttrVec.
push_back(PAL.getParamAttrs(ArgI));
757 HasLiveReturnedArg |= PAL.hasParamAttr(ArgI, Attribute::Returned);
759 ++NumArgumentsEliminated;
762 return OptimizationRemark(
DEBUG_TYPE,
"ArgumentRemoved",
F)
763 <<
"eliminating argument " <<
ore::NV(
"ArgName",
I->getName())
764 <<
"(" <<
ore::NV(
"ArgIndex", ArgI) <<
")";
766 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Removing argument "
767 << ArgI <<
" (" <<
I->getName() <<
") from "
768 <<
F->getName() <<
"\n");
773 Type *RetTy = FTy->getReturnType();
774 Type *NRetTy =
nullptr;
779 std::vector<Type *> RetTypes;
800 if (RetTy->
isVoidTy() || HasLiveReturnedArg ||
805 for (
unsigned Ri = 0; Ri != RetCount; ++Ri) {
809 NewRetIdxs[Ri] = RetTypes.size() - 1;
811 ++NumRetValsEliminated;
814 return OptimizationRemark(
DEBUG_TYPE,
"ReturnValueRemoved",
F)
815 <<
"removing return value " << std::to_string(Ri);
818 dbgs() <<
"DeadArgumentEliminationPass - Removing return value "
819 << Ri <<
" from " <<
F->getName() <<
"\n");
822 if (RetTypes.size() > 1) {
827 NRetTy =
StructType::get(STy->getContext(), RetTypes, STy->isPacked());
832 }
else if (RetTypes.size() == 1)
835 NRetTy = RetTypes.front();
836 else if (RetTypes.empty())
841 assert(NRetTy &&
"No new return type found?");
844 AttrBuilder RAttrs(
F->getContext(), PAL.getRetAttrs());
851 RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs()));
854 AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs())) &&
855 "Return attributes no longer compatible?");
860 AttributeSet FnAttrs =
861 PAL.getFnAttrs().removeAttribute(
F->getContext(), Attribute::AllocSize);
865 AttributeList NewPAL =
866 AttributeList::get(
F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
882 F->getParent()->getFunctionList().insert(
F->getIterator(), NF);
887 std::vector<Value *>
Args;
888 while (!
F->use_empty()) {
896 AttrBuilder RAttrs(
F->getContext(), CallPAL.getRetAttrs());
898 AttributeFuncs::typeIncompatible(NRetTy, CallPAL.getRetAttrs()));
907 for (
unsigned E = FTy->getNumParams(); Pi !=
E; ++
I, ++Pi)
911 AttributeSet
Attrs = CallPAL.getParamAttrs(Pi);
912 if (NRetTy != RetTy &&
Attrs.hasAttribute(Attribute::Returned)) {
919 F->getContext(), AttrBuilder(
F->getContext(), Attrs)
920 .removeAttribute(Attribute::Returned)));
930 ArgAttrVec.
push_back(CallPAL.getParamAttrs(Pi));
938 AttributeSet FnAttrs = CallPAL.getFnAttrs().removeAttribute(
939 F->getContext(), Attribute::AllocSize);
941 AttributeList NewCallPAL =
942 AttributeList::get(
F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
947 CallBase *NewCB =
nullptr;
958 NewCB->
copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
973 "Return type changed, but not into a void. The old return type"
974 " must have been a struct or an array!");
988 for (
unsigned Ri = 0; Ri != RetCount; ++Ri)
989 if (NewRetIdxs[Ri] != -1) {
992 if (RetTypes.size() > 1)
995 V = IRB.CreateExtractValue(NewCB, NewRetIdxs[Ri],
"newret");
1000 RetVal = IRB.CreateInsertValue(RetVal, V, Ri,
"oldret");
1024 I !=
E; ++
I, ++ArgI)
1025 if (ArgAlive[ArgI]) {
1028 I->replaceAllUsesWith(&*I2);
1040 for (BasicBlock &BB : *NF)
1043 Value *RetVal =
nullptr;
1045 if (!NFTy->getReturnType()->isVoidTy()) {
1052 Value *OldRet = RI->getOperand(0);
1055 for (
unsigned RetI = 0; RetI != RetCount; ++RetI)
1056 if (NewRetIdxs[RetI] != -1) {
1057 Value *EV = IRB.CreateExtractValue(OldRet, RetI,
"oldret");
1059 if (RetTypes.size() > 1) {
1063 RetVal = IRB.CreateInsertValue(RetVal, EV, NewRetIdxs[RetI],
1076 NewRet->setDebugLoc(RI->getDebugLoc());
1077 RI->eraseFromParent();
1082 F->getAllMetadata(MDs);
1083 for (
auto [KindID, Node] : MDs)
1084 NF->addMetadata(KindID, *Node);
1090 if (NFTy != FTy && NF->getSubprogram()) {
1091 DISubprogram *
SP = NF->getSubprogram();
1092 auto Temp =
SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
1097 F->eraseFromParent();
1110 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Deleting dead varargs\n");
1112 if (
F.getFunctionType()->isVarArg())
1118 LLVM_DEBUG(
dbgs() <<
"DeadArgumentEliminationPass - Determining liveness\n");
1126 Changed |= removeDeadStuffFromFunction(&
F);
1131 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
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.
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
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 >
LLVM_ABI ModulePass * createDeadArgEliminationPass()
createDeadArgEliminationPass - This pass removes arguments from functions which are not used by the b...
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...
LLVM_ABI ModulePass * createDeadArgHackingPass()
DeadArgHacking pass - Same as DAE, but delete arguments of external functions as well.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Struct that represents (part of) either a return value or a function argument.