54 #define DEBUG_TYPE "argpromotion"
56 STATISTIC(NumArgumentsPromoted ,
"Number of pointer arguments promoted");
57 STATISTIC(NumAggregatesPromoted,
"Number of aggregate arguments promoted");
58 STATISTIC(NumByValArgsPromoted ,
"Number of byval arguments promoted");
59 STATISTIC(NumArgumentsDead ,
"Number of dead pointer args eliminated");
72 explicit ArgPromotion(
unsigned maxElements = 3)
78 typedef std::vector<uint64_t> IndicesVector;
82 bool canPaddingBeAccessed(
Argument *Arg);
84 bool isSafeToPromoteArgument(
Argument *Arg,
bool isByVal)
const;
90 bool doInitialization(
CallGraph &CG)
override;
99 "Promote 'by reference' arguments to scalars",
false,
false)
103 "Promote 'by reference' arguments to
scalars",
false, false)
106 return new ArgPromotion(maxElements);
110 bool Changed =
false, LocalChange;
121 Changed |= LocalChange;
122 }
while (LocalChange);
128 bool ArgPromotion::isDenselyPacked(
Type *type,
const DataLayout &DL) {
139 if (!isa<CompositeType>(type))
144 return isa<PointerType>(seqTy) ||
145 isDenselyPacked(seqTy->getElementType(), DL);
148 StructType *StructTy = cast<StructType>(type);
150 uint64_t StartPos = 0;
151 for (
unsigned i = 0, E = StructTy->getNumElements(); i < E; ++i) {
152 Type *ElTy = StructTy->getElementType(i);
153 if (!isDenselyPacked(ElTy, DL))
155 if (StartPos != Layout->getElementOffsetInBits(i))
164 bool ArgPromotion::canPaddingBeAccessed(
Argument *arg) {
179 while (!WorkList.
empty()) {
182 if (isa<GetElementPtrInst>(V) || isa<PHINode>(V)) {
183 if (PtrValues.insert(V).second)
187 }
else if (!isa<LoadInst>(V)) {
194 if (PtrValues.count(
Store->getValueOperand()))
221 if (
I->getType()->isPointerTy())
223 if (PointerArgs.
empty())
return nullptr;
228 bool isSelfRecursive =
false;
232 if (
CS.getInstruction() ==
nullptr || !
CS.isCallee(&U))
return nullptr;
234 if (
CS.getInstruction()->getParent()->getParent() ==
F)
235 isSelfRecursive =
true;
244 for (
unsigned i = 0, e = PointerArgs.
size(); i != e; ++i) {
246 Type *AgTy = cast<PointerType>(PtrArg->
getType())->getElementType();
251 unsigned ArgNo = PtrArg->
getArgNo();
270 bool isSafeToPromote =
272 (isDenselyPacked(AgTy, DL) || !canPaddingBeAccessed(PtrArg));
273 if (isSafeToPromote) {
274 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
275 if (maxElements > 0 && STy->getNumElements() > maxElements) {
276 DEBUG(
dbgs() <<
"argpromotion disable promoting argument '"
277 << PtrArg->
getName() <<
"' because it would require adding more"
278 <<
" than " << maxElements <<
" arguments to the function.\n");
283 bool AllSimple =
true;
284 for (
unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
285 if (!STy->getElementType(i)->isSingleValueType()) {
295 ByValArgsToTransform.
insert(PtrArg);
303 if (isSelfRecursive) {
304 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
305 bool RecursiveType =
false;
306 for (
unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
307 if (STy->getElementType(i) == PtrArg->
getType()) {
308 RecursiveType =
true;
319 ArgsToPromote.
insert(PtrArg);
323 if (ArgsToPromote.
empty() && ByValArgsToTransform.
empty())
326 return DoPromotion(F, ArgsToPromote, ByValArgsToTransform);
341 assert(CS &&
"Should only have direct calls!");
355 const ArgPromotion::IndicesVector &Longer) {
356 if (Prefix.size() > Longer.size())
358 return std::equal(Prefix.begin(), Prefix.end(), Longer.begin());
363 static bool PrefixIn(
const ArgPromotion::IndicesVector &Indices,
364 std::set<ArgPromotion::IndicesVector> &Set) {
365 std::set<ArgPromotion::IndicesVector>::iterator Low;
366 Low = Set.upper_bound(Indices);
367 if (Low != Set.begin())
374 return Low != Set.end() &&
IsPrefix(*Low, Indices);
383 std::set<ArgPromotion::IndicesVector> &Safe) {
384 std::set<ArgPromotion::IndicesVector>::iterator Low;
385 Low = Safe.upper_bound(ToMark);
387 if (Low != Safe.begin())
392 if (Low != Safe.end()) {
402 Low = Safe.insert(Low, ToMark);
405 std::set<ArgPromotion::IndicesVector>::iterator End = Safe.end();
406 while (Low != End &&
IsPrefix(ToMark, *Low)) {
407 std::set<ArgPromotion::IndicesVector>::iterator Remove = Low;
418 bool ArgPromotion::isSafeToPromoteArgument(
Argument *Arg,
419 bool isByValOrInAlloca)
const {
420 typedef std::set<IndicesVector> GEPIndicesSet;
444 GEPIndicesSet SafeToUnconditionallyLoad;
448 GEPIndicesSet ToPromote;
452 SafeToUnconditionallyLoad.insert(IndicesVector(1, 0));
458 IndicesVector Indices;
461 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
462 Value *V = LI->getPointerOperand();
464 V =
GEP->getPointerOperand();
467 Indices.reserve(
GEP->getNumIndices());
471 Indices.push_back(CI->getSExtValue());
481 }
else if (V == Arg) {
492 User *UR = U.getUser();
494 if (
LoadInst *LI = dyn_cast<LoadInst>(UR)) {
496 if (!LI->isSimple())
return false;
499 Operands.push_back(0);
501 if (
GEP->use_empty()) {
504 getAnalysis<AliasAnalysis>().deleteValue(
GEP);
505 GEP->eraseFromParent();
509 return isSafeToPromoteArgument(Arg, isByValOrInAlloca);
516 Operands.push_back(
C->getSExtValue());
521 for (
User *GEPU :
GEP->users())
522 if (
LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
524 if (!LI->isSimple())
return false;
536 if (!
PrefixIn(Operands, SafeToUnconditionallyLoad))
542 if (ToPromote.find(Operands) == ToPromote.end()) {
543 if (maxElements > 0 && ToPromote.size() == maxElements) {
544 DEBUG(
dbgs() <<
"argpromotion not promoting argument '"
545 << Arg->
getName() <<
"' because it would require adding more "
546 <<
"than " << maxElements <<
" arguments to the function.\n");
551 ToPromote.insert(std::move(Operands));
555 if (Loads.
empty())
return true;
568 for (
unsigned i = 0, e = Loads.
size(); i != e; ++i) {
605 std::vector<Type*> Params;
607 typedef std::set<std::pair<Type *, IndicesVector>> ScalarizeTable;
616 std::map<Argument*, ScalarizeTable> ScalarizedElements;
623 std::map<std::pair<Argument*, IndicesVector>,
LoadInst*> OriginalLoads;
637 unsigned ArgIndex = 1;
640 if (ByValArgsToTransform.
count(
I)) {
642 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
645 ++NumByValArgsPromoted;
646 }
else if (!ArgsToPromote.
count(
I)) {
648 Params.push_back(
I->getType());
653 push_back(AttributeSet::get(F->
getContext(), Params.size(), B));
655 }
else if (
I->use_empty()) {
664 ScalarizeTable &ArgIndices = ScalarizedElements[
I];
665 for (
User *U :
I->users()) {
668 if (
LoadInst *L = dyn_cast<LoadInst>(UI))
669 SrcTy = L->getType();
671 SrcTy = cast<GetElementPtrInst>(UI)->getSourceElementType();
672 IndicesVector Indices;
679 Indices.push_back(cast<ConstantInt>(*II)->getSExtValue());
681 if (Indices.size() == 1 && Indices.front() == 0)
683 ArgIndices.insert(std::make_pair(SrcTy, Indices));
685 if (
LoadInst *L = dyn_cast<LoadInst>(UI))
689 OrigLoad = cast<LoadInst>(UI->
user_back());
690 OriginalLoads[std::make_pair(
I, Indices)] = OrigLoad;
694 for (ScalarizeTable::iterator SI = ArgIndices.begin(),
695 E = ArgIndices.end();
SI != E; ++
SI) {
698 cast<PointerType>(
I->getType()->getScalarType())->getElementType(),
700 assert(Params.back());
703 if (ArgIndices.size() == 1 && ArgIndices.begin()->second.empty())
704 ++NumArgumentsPromoted;
706 ++NumAggregatesPromoted;
725 auto DI = FunctionDIs.find(F);
726 if (DI != FunctionDIs.end()) {
731 FunctionDIs.erase(DI);
732 FunctionDIs[NF] = SP;
735 DEBUG(
dbgs() <<
"ARG PROMOTION: Promoting to:" << *NF <<
"\n"
740 NF->setAttributes(AttributeSet::get(F->
getContext(), AttributesVec));
741 AttributesVec.
clear();
752 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
763 assert(
CS.getCalledFunction() ==
F);
777 I != E; ++
I, ++AI, ++ArgIndex)
778 if (!ArgsToPromote.
count(
I) && !ByValArgsToTransform.
count(
I)) {
786 }
else if (ByValArgsToTransform.
count(
I)) {
788 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
799 }
else if (!
I->use_empty()) {
801 ScalarizeTable &ArgIndices = ScalarizedElements[
I];
804 std::vector<Value*> Ops;
805 for (ScalarizeTable::iterator SI = ArgIndices.begin(),
806 E = ArgIndices.end();
SI != E; ++
SI) {
808 LoadInst *OrigLoad = OriginalLoads[std::make_pair(
I,
SI->second)];
809 if (!
SI->second.empty()) {
810 Ops.reserve(
SI->second.size());
812 for (IndicesVector::const_iterator II =
SI->second.begin(),
813 IE =
SI->second.end();
822 ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(*II);
843 for (; AI !=
CS.arg_end(); ++AI, ++ArgIndex) {
854 AttributesVec.
push_back(AttributeSet::get(Call->getContext(),
858 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
861 cast<InvokeInst>(New)->setCallingConv(
CS.getCallingConv());
862 cast<InvokeInst>(New)->setAttributes(AttributeSet::get(II->getContext(),
866 cast<CallInst>(New)->setCallingConv(
CS.getCallingConv());
867 cast<CallInst>(New)->setAttributes(AttributeSet::get(New->
getContext(),
869 if (cast<CallInst>(Call)->isTailCall())
870 cast<CallInst>(New)->setTailCall();
874 AttributesVec.
clear();
881 CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()];
884 if (!Call->use_empty()) {
885 Call->replaceAllUsesWith(New);
891 Call->eraseFromParent();
903 I2 = NF->arg_begin();
I != E; ++
I) {
904 if (!ArgsToPromote.
count(
I) && !ByValArgsToTransform.
count(
I)) {
907 I->replaceAllUsesWith(I2);
914 if (ByValArgsToTransform.
count(
I)) {
920 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
929 AgTy, TheAlloca, Idxs, TheAlloca->
getName() +
"." +
Twine(i),
936 I->replaceAllUsesWith(TheAlloca);
951 if (
I->use_empty()) {
959 ScalarizeTable &ArgIndices = ScalarizedElements[
I];
961 while (!
I->use_empty()) {
962 if (
LoadInst *LI = dyn_cast<LoadInst>(
I->user_back())) {
963 assert(ArgIndices.begin()->second.empty() &&
964 "Load element should sort to front!");
965 I2->setName(
I->getName()+
".val");
966 LI->replaceAllUsesWith(I2);
968 LI->eraseFromParent();
969 DEBUG(
dbgs() <<
"*** Promoted load of argument '" <<
I->getName()
970 <<
"' in function '" << F->
getName() <<
"'\n");
977 Operands.push_back(cast<ConstantInt>(*II)->getSExtValue());
980 if (Operands.size() == 1 && Operands.front() == 0)
984 for (ScalarizeTable::iterator It = ArgIndices.begin();
985 It->second !=
Operands; ++It, ++TheArg) {
986 assert(It != ArgIndices.end() &&
"GEP not handled??");
989 std::string NewName =
I->getName();
990 for (
unsigned i = 0, e = Operands.size(); i != e; ++i) {
991 NewName +=
"." +
utostr(Operands[i]);
994 TheArg->setName(NewName);
996 DEBUG(
dbgs() <<
"*** Promoted agg argument '" << TheArg->getName()
997 <<
"' of function '" << NF->getName() <<
"'\n");
1027 delete CG.removeFunctionFromModule(CGN);
1034 bool ArgPromotion::doInitialization(
CallGraph &CG) {
void replaceWithNewValue(Value *Old, Value *New)
replaceWithNewValue - This method is the obvious combination of the two above, and it provided as a h...
Pass interface - Implemented by all 'passes'.
iplist< Instruction >::iterator eraseFromParent()
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.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
STATISTIC(NumFunctions,"Total number of functions")
AttributeSet getParamAttributes(unsigned Index) const
The attributes for the specified index are returned.
ValTy * getArgument(unsigned ArgNo) const
std::vector< CallGraphNode * >::const_iterator iterator
bool hasByValOrInAllocaAttr() const
Return true if this argument has the byval attribute or inalloca attribute on it in its containing fu...
unsigned getNumOperands() const
CallInst - 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.
virtual bool doInitialization(CallGraph &CG)
doInitialization - This method is called before the SCC's of the program has been processed...
Externally visible function.
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
const Instruction & front() const
void replaceFunction(Function *F)
Replace the function.
LoadInst - an instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
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
Module & getModule() const
Returns the module the call graph corresponds to.
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...
iterator begin()
Instruction iterator methods.
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)
AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const
Remove the specified attribute at the specified index from this attribute list.
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...
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
StructType - 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 &)
bool isDereferenceablePointer(const Value *V, const DataLayout &DL, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)
isDereferenceablePointer - Return true if this is always a dereferenceable pointer.
static void advance(T &it, size_t Val)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Pass * createArgumentPromotionPass(unsigned maxElements=3)
createArgumentPromotionPass - This pass promotes "by reference" arguments to be passed by value if th...
bool isSized(SmallPtrSetImpl< const Type * > *Visited=nullptr) const
isSized - Return true if it makes sense to take the size of this type.
element_iterator element_begin() const
void setName(const Twine &Name)
Change the name of the value.
Hidden pointer to structure to return.
load Combine Adjacent Loads
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
FunctionType - Class to represent function types.
LLVMContext & getContext() const
getContext - Return the LLVMContext in which this type was uniqued.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
bool hasStructRetAttr() const
Return true if this argument has the sret attribute on it in its containing function.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
static std::string utostr(uint64_t X, bool isNeg=false)
StoreInst - 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.
Considered to not alias after call.
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
GetElementPtrInst - an instruction for type-safe pointer arithmetic to access elements of arrays and ...
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
void setDebugLoc(DebugLoc Loc)
setDebugLoc - 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)
setAAMetadata - 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
void stealCalledFunctionsFrom(CallGraphNode *N)
Moves all the callee information from N to this node.
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.
iterator insert(iterator where, NodeTy *New)
void copyAttributesFrom(const GlobalValue *Src) override
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
void setAlignment(unsigned Align)
#define INITIALIZE_AG_DEPENDENCY(depName)
void setTailCall(bool isTC=true)
virtual void deleteValue(Value *V)
Methods that clients should call when they transform the program to allow alias analyses to update th...
LLVMContext & getContext() const
All values hold a context through their type.
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, 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.
SequentialType - This is the superclass of the array, pointer and vector type classes.
static InvokeInst * Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
const BasicBlockListType & getBasicBlockList() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
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()
user_back - Specialize the methods defined in Value, as we know that an instruction can only be used ...
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)
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.
StringRef getName() const
getName - Return the name for this struct type if it has an identity.
iterator_range< user_iterator > users()
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator insert(iterator I, T &&Elt)
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, const MemoryLocation &Loc, const ModRefResult Mode)
canInstructionRangeModRef - Return true if it is possible for the execution of the specified instruct...
bool isStructTy() const
isStructTy - True if this is an instance of StructType.
static Type * getIndexedType(Type *Ty, ArrayRef< Value * > IdxList)
getIndexedType - Returns the type of the element that would be loaded with a load instruction with th...
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.
void ReplaceNode(CallGraphNode *Old, CallGraphNode *New)
ReplaceNode - This informs the SCC and the pass manager that the specified Old node has been deleted...
static IntegerType * getInt32Ty(LLVMContext &C)
bool hasAttributes(unsigned Index) const
Return true if attribute exists at the given index.
unsigned getAlignment() const
getAlignment - Return the alignment of the access that is being performed
void getAAMetadata(AAMDNodes &N, bool Merge=false) const
getAAMetadata - Fills the AAMDNodes structure with AA metadata from this instruction.
FunctionType * getFunctionType() const
bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc)
Higher level methods for querying mod/ref information.
void setAttributes(AttributeSet attrs)
Set the attribute list for this Function.
bool hasLocalLinkage() const
Type * getReturnType() const
user_iterator user_begin()
DenseMap< const Function *, DISubprogram * > makeSubprogramMap(const Module &M)
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.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
uint64_t getTypeSizeInBits(Type *Ty) const
Size examples:
InvokeInst - Invoke instruction.
C - The default llvm calling convention, compatible with C.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
unsigned getNumElements() const
Random access to the elements.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
const BasicBlock * getParent() const
AllocaInst - an instruction to allocate memory on the stack.
AttributeSet getFnAttributes() const
The function attributes are returned.