57 #define DEBUG_TYPE "argpromotion"
59 STATISTIC(NumArgumentsPromoted ,
"Number of pointer arguments promoted");
60 STATISTIC(NumAggregatesPromoted,
"Number of aggregate arguments promoted");
61 STATISTIC(NumByValArgsPromoted ,
"Number of byval arguments promoted");
62 STATISTIC(NumArgumentsDead ,
"Number of dead pointer args eliminated");
77 explicit ArgPromotion(
unsigned maxElements = 3)
85 bool doInitialization(
CallGraph &CG)
override;
97 unsigned MaxElements);
101 unsigned MaxElements);
108 "Promote 'by reference' arguments to scalars",
false,
false)
113 "Promote 'by reference' arguments to
scalars",
false, false)
116 return new ArgPromotion(maxElements);
121 unsigned MaxElements) {
122 bool Changed =
false, LocalChange;
131 SCC.ReplaceNode(OldNode, NewNode);
134 Changed |= LocalChange;
135 }
while (LocalChange);
146 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
159 return runImpl(SCC, CG, AARGetter, maxElements);
174 if (!isa<CompositeType>(type))
182 StructType *StructTy = cast<StructType>(type);
184 uint64_t StartPos = 0;
189 if (StartPos != Layout->getElementOffsetInBits(
i))
213 while (!WorkList.
empty()) {
216 if (isa<GetElementPtrInst>(V) || isa<PHINode>(V)) {
217 if (PtrValues.insert(V).second)
221 }
else if (!isa<LoadInst>(V)) {
228 if (PtrValues.count(
Store->getValueOperand()))
242 unsigned MaxElements) {
258 if (
I.getType()->isPointerTy())
260 if (PointerArgs.
empty())
return nullptr;
265 bool isSelfRecursive =
false;
269 if (CS.getInstruction() ==
nullptr || !CS.isCallee(&U))
return nullptr;
271 if (CS.getInstruction()->getParent()->getParent() ==
F)
272 isSelfRecursive =
true;
283 for (
Argument *PtrArg : PointerArgs) {
284 Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
288 if (PtrArg->hasStructRetAttr()) {
289 unsigned ArgNo = PtrArg->getArgNo();
299 Attribute::StructRet)
308 bool isSafeToPromote =
309 PtrArg->hasByValAttr() &&
311 if (isSafeToPromote) {
312 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
313 if (MaxElements > 0 && STy->getNumElements() > MaxElements) {
314 DEBUG(
dbgs() <<
"argpromotion disable promoting argument '"
315 << PtrArg->getName() <<
"' because it would require adding more"
316 <<
" than " << MaxElements <<
" arguments to the function.\n");
321 bool AllSimple =
true;
322 for (
const auto *EltTy : STy->elements()) {
323 if (!EltTy->isSingleValueType()) {
333 ByValArgsToTransform.
insert(PtrArg);
341 if (isSelfRecursive) {
342 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
343 bool RecursiveType =
false;
344 for (
const auto *EltTy : STy->elements()) {
345 if (EltTy == PtrArg->getType()) {
346 RecursiveType =
true;
358 ArgsToPromote.
insert(PtrArg);
362 if (ArgsToPromote.
empty() && ByValArgsToTransform.
empty())
365 return DoPromotion(F, ArgsToPromote, ByValArgsToTransform, CG);
380 assert(CS &&
"Should only have direct calls!");
394 if (Prefix.size() > Longer.size())
396 return std::equal(Prefix.begin(), Prefix.end(), Longer.begin());
402 std::set<IndicesVector> &Set) {
403 std::set<IndicesVector>::iterator Low;
404 Low = Set.upper_bound(Indices);
405 if (Low != Set.begin())
412 return Low != Set.end() &&
IsPrefix(*Low, Indices);
421 std::set<IndicesVector> &Safe) {
422 std::set<IndicesVector>::iterator Low;
423 Low = Safe.upper_bound(ToMark);
425 if (Low != Safe.begin())
430 if (Low != Safe.end()) {
440 Low = Safe.insert(Low, ToMark);
443 std::set<IndicesVector>::iterator
End = Safe.end();
444 while (Low != End &&
IsPrefix(ToMark, *Low)) {
445 std::set<IndicesVector>::iterator Remove = Low;
458 typedef std::set<IndicesVector> GEPIndicesSet;
482 GEPIndicesSet SafeToUnconditionallyLoad;
486 GEPIndicesSet ToPromote;
498 if (
LoadInst *LI = dyn_cast<LoadInst>(&
I)) {
499 Value *V = LI->getPointerOperand();
501 V =
GEP->getPointerOperand();
504 Indices.reserve(
GEP->getNumIndices());
508 Indices.push_back(CI->getSExtValue());
518 }
else if (V == Arg) {
529 User *UR = U.getUser();
531 if (
LoadInst *LI = dyn_cast<LoadInst>(UR)) {
533 if (!LI->isSimple())
return false;
536 Operands.push_back(0);
538 if (
GEP->use_empty()) {
541 GEP->eraseFromParent();
553 Operands.push_back(
C->getSExtValue());
558 for (
User *GEPU :
GEP->users())
559 if (
LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
561 if (!LI->isSimple())
return false;
573 if (!
PrefixIn(Operands, SafeToUnconditionallyLoad))
579 if (ToPromote.find(Operands) == ToPromote.end()) {
580 if (MaxElements > 0 && ToPromote.size() == MaxElements) {
581 DEBUG(
dbgs() <<
"argpromotion not promoting argument '"
582 << Arg->
getName() <<
"' because it would require adding more "
583 <<
"than " << MaxElements <<
" arguments to the function.\n");
588 ToPromote.insert(std::move(Operands));
592 if (Loads.
empty())
return true;
638 std::vector<Type*> Params;
640 typedef std::set<std::pair<Type *, IndicesVector>> ScalarizeTable;
649 std::map<Argument*, ScalarizeTable> ScalarizedElements;
656 std::map<std::pair<Argument*, IndicesVector>,
LoadInst*> OriginalLoads;
670 unsigned ArgIndex = 1;
673 if (ByValArgsToTransform.
count(&*
I)) {
675 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
678 ++NumByValArgsPromoted;
679 }
else if (!ArgsToPromote.
count(&*
I)) {
681 Params.push_back(
I->getType());
686 push_back(AttributeSet::get(F->
getContext(), Params.size(),
B));
688 }
else if (
I->use_empty()) {
697 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
698 for (
User *U :
I->users()) {
701 if (
LoadInst *
L = dyn_cast<LoadInst>(UI))
702 SrcTy =
L->getType();
704 SrcTy = cast<GetElementPtrInst>(UI)->getSourceElementType();
712 Indices.push_back(cast<ConstantInt>(*II)->getSExtValue());
714 if (Indices.size() == 1 && Indices.front() == 0)
716 ArgIndices.insert(std::make_pair(SrcTy, Indices));
718 if (
LoadInst *
L = dyn_cast<LoadInst>(UI))
722 OrigLoad = cast<LoadInst>(UI->
user_back());
723 OriginalLoads[std::make_pair(&*
I, Indices)] = OrigLoad;
727 for (
const auto &ArgIndex : ArgIndices) {
730 cast<PointerType>(
I->getType()->getScalarType())->getElementType(),
735 if (ArgIndices.size() == 1 && ArgIndices.begin()->second.empty())
736 ++NumArgumentsPromoted;
738 ++NumAggregatesPromoted;
760 DEBUG(
dbgs() <<
"ARG PROMOTION: Promoting to:" << *NF <<
"\n"
765 NF->setAttributes(AttributeSet::get(F->
getContext(), AttributesVec));
766 AttributesVec.
clear();
780 assert(CS.getCalledFunction() ==
F);
794 I !=
E; ++
I, ++AI, ++ArgIndex)
795 if (!ArgsToPromote.
count(&*
I) && !ByValArgsToTransform.
count(&*
I)) {
803 }
else if (ByValArgsToTransform.
count(&*
I)) {
805 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
816 }
else if (!
I->use_empty()) {
818 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
821 std::vector<Value*> Ops;
822 for (
const auto &ArgIndex : ArgIndices) {
825 OriginalLoads[std::make_pair(&*
I, ArgIndex.second)];
826 if (!ArgIndex.second.empty()) {
827 Ops.reserve(ArgIndex.second.size());
829 for (
unsigned long II : ArgIndex.second) {
837 if (
auto *ElPTy = dyn_cast<PointerType>(ElTy))
838 ElTy = ElPTy->getElementType();
840 ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(II);
861 for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
872 AttributesVec.
push_back(AttributeSet::get(Call->getContext(),
876 CS.getOperandBundlesAsDefs(OpBundles);
879 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
882 cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
883 cast<InvokeInst>(New)->setAttributes(AttributeSet::get(II->getContext(),
887 cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
888 cast<CallInst>(New)->setAttributes(AttributeSet::get(New->
getContext(),
890 cast<CallInst>(New)->setTailCallKind(
891 cast<CallInst>(Call)->getTailCallKind());
895 AttributesVec.
clear();
898 CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()];
901 if (!Call->use_empty()) {
902 Call->replaceAllUsesWith(New);
908 Call->eraseFromParent();
920 I2 = NF->arg_begin();
I !=
E; ++
I) {
921 if (!ArgsToPromote.
count(&*
I) && !ByValArgsToTransform.
count(&*
I)) {
924 I->replaceAllUsesWith(&*I2);
930 if (ByValArgsToTransform.
count(&*
I)) {
936 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
945 AgTy, TheAlloca, Idxs, TheAlloca->
getName() +
"." +
Twine(
i),
952 I->replaceAllUsesWith(TheAlloca);
972 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
974 while (!
I->use_empty()) {
975 if (
LoadInst *LI = dyn_cast<LoadInst>(
I->user_back())) {
976 assert(ArgIndices.begin()->second.empty() &&
977 "Load element should sort to front!");
978 I2->setName(
I->getName()+
".val");
979 LI->replaceAllUsesWith(&*I2);
980 LI->eraseFromParent();
981 DEBUG(
dbgs() <<
"*** Promoted load of argument '" <<
I->getName()
982 <<
"' in function '" << F->
getName() <<
"'\n");
989 Operands.push_back(cast<ConstantInt>(*II)->getSExtValue());
992 if (Operands.size() == 1 && Operands.front() == 0)
996 for (ScalarizeTable::iterator It = ArgIndices.begin();
997 It->second != Operands; ++It, ++TheArg) {
998 assert(It != ArgIndices.end() &&
"GEP not handled??");
1001 std::string NewName =
I->getName();
1002 for (
unsigned i = 0, e = Operands.size();
i != e; ++
i) {
1003 NewName +=
"." +
utostr(Operands[
i]);
1006 TheArg->setName(NewName);
1008 DEBUG(
dbgs() <<
"*** Promoted agg argument '" << TheArg->getName()
1009 <<
"' of function '" << NF->getName() <<
"'\n");
1040 bool ArgPromotion::doInitialization(
CallGraph &CG) {
Pass interface - Implemented by all 'passes'.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
LinkageTypes getLinkage() const
iterator_range< use_iterator > uses()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
STATISTIC(NumFunctions,"Total number of functions")
AttributeSet getParamAttributes(unsigned Index) const
The attributes for the specified index are returned.
BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F)
A helper for the legacy pass manager to create a BasicAAResult object populated to the best of our ab...
unsigned getNumOperands() const
This class represents a function call, abstracting a target machine's calling convention.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
An immutable pass that tracks lazily created AssumptionCache objects.
virtual bool doInitialization(CallGraph &CG)
doInitialization - This method is called before the SCC's of the program has been processed...
An efficient, type-erasing, non-owning reference to a callable.
Externally visible function.
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
const Instruction & front() const
The two locations do not alias at all.
An instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
A node in the call graph for a module.
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph...
unsigned getNumIndices() const
The access modifies the value stored in memory.
uint64_t getTypeAllocSizeInBits(Type *Ty) const
Returns the offset in bits between successive objects of the specified type, including alignment padd...
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
StringRef getName() const
Return a constant reference to the value's name.
Function * getFunction() const
Returns the function that this call graph node represents.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
unsigned getNumReferences() const
Returns the number of other CallGraphNodes in this CallGraph that reference this node in their callee...
element_iterator element_end() const
AnalysisUsage & addRequired()
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
#define INITIALIZE_PASS_DEPENDENCY(depName)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
Class to represent struct types.
void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode)
Replaces the edge in the node for the specified call site with a new one.
A Use represents the edge between a Value definition and its users.
void initializeArgPromotionPass(PassRegistry &)
static void advance(T &it, size_t Val)
Pass * createArgumentPromotionPass(unsigned maxElements=3)
createArgumentPromotionPass - This pass promotes "by reference" arguments to be passed by value if th...
Function * removeFunctionFromModule(CallGraphNode *CGN)
Unlink the function from this module, returning it.
element_iterator element_begin() const
void setName(const Twine &Name)
Change the name of the value.
AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR)
A helper for the legacy pass manager to create a AAResults object populated to the best of our abilit...
LLVM_NODISCARD bool empty() const
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
Class to represent function types.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static std::string utostr(uint64_t X, bool isNeg=false)
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
void setSubprogram(DISubprogram *SP)
Set the attached subprogram.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
The ModulePass which wraps up a CallGraph and the logic to build it.
void setAAMetadata(const AAMDNodes &N)
Sets the metadata on this instruction from the AAMDNodes structure.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
const Function * getParent() const
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, const MemoryLocation &Loc, const ModRefInfo Mode)
Check if it is possible for the execution of the specified instructions to mod(according to the mode)...
void stealCalledFunctionsFrom(CallGraphNode *N)
Moves all the callee information from N to this node.
Type * getElementType(unsigned N) const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
static const unsigned End
void copyAttributesFrom(const GlobalValue *Src) override
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
self_iterator getIterator()
void setAlignment(unsigned Align)
LLVM_NODISCARD bool empty() const
void setTailCall(bool isTC=true)
LLVMContext & getContext() const
All values hold a context through their type.
void getAAResultsAnalysisUsage(AnalysisUsage &AU)
A helper for the legacy pass manager to populate AU to add uses to make sure the analyses required by...
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
static InvokeInst * Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr, Instruction *InsertBefore=nullptr)
bool hasByValAttr() const
Return true if this argument has the byval attribute on it in its containing function.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
Representation for a specific memory location.
This is the superclass of the array and vector type classes.
Iterator for intrusive lists based on ilist_node.
const BasicBlockListType & getBasicBlockList() const
This is the shared class of boolean and integer constants.
ValTy * getArgument(unsigned ArgNo) const
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
pred_range predecessors(BasicBlock *BB)
void setLinkage(LinkageTypes LT)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
AttributeSet getAttributes() const
Return the attribute list for this Function.
DISubprogram * getSubprogram() const
Get the attached subprogram.
StringRef getName() const
Return the name for this struct type if it has an identity.
iterator_range< user_iterator > users()
iterator insert(iterator I, T &&Elt)
AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Remove the specified attribute at the specified index from this attribute list.
void setAttributes(AttributeSet Attrs)
Set the attribute list for this Function.
bool isStructTy() const
True if this is an instance of StructType.
static Type * getIndexedType(Type *Ty, ArrayRef< Value * > IdxList)
Returns the type of the element that would be loaded with a load instruction with the specified param...
bool isDereferenceablePointer(const Value *V, const DataLayout &DL, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr)
Return true if this is always a dereferenceable pointer.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
The basic data container for the call graph of a Module of IR.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
iterator insert(iterator where, pointer New)
static IntegerType * getInt32Ty(LLVMContext &C)
bool hasAttributes(unsigned Index) const
Return true if attribute exists at the given index.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
void getAAMetadata(AAMDNodes &N, bool Merge=false) const
Fills the AAMDNodes structure with AA metadata from this instruction.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasLocalLinkage() const
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
const BasicBlock & front() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
CallGraphNode * getOrInsertFunction(const Function *F)
Similar to operator[], but this will insert a new CallGraphNode for F if one does not already exist...
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
uint64_t getTypeSizeInBits(Type *Ty) const
Size examples:
This is the interface for LLVM's primary stateless and local alias analysis.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
unsigned getNumElements() const
Random access to the elements.
void emplace(ArgTypes &&...Args)
Create a new object by constructing it in place with the given arguments.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc)
Check if it is possible for execution of the specified basic block to modify the location Loc...
iterator_range< arg_iterator > args()
an instruction to allocate memory on the stack
AttributeSet getFnAttributes() const
The function attributes are returned.