90 #define DEBUG_TYPE "argpromotion" 92 STATISTIC(NumArgumentsPromoted,
"Number of pointer arguments promoted");
93 STATISTIC(NumAggregatesPromoted,
"Number of aggregate arguments promoted");
94 STATISTIC(NumByValArgsPromoted,
"Number of byval arguments promoted");
95 STATISTIC(NumArgumentsDead,
"Number of dead pointer args eliminated");
111 std::vector<Type *> Params;
113 using ScalarizeTable = std::set<std::pair<Type *, IndicesVector>>;
121 std::map<Argument *, ScalarizeTable> ScalarizedElements;
128 std::map<std::pair<Argument *, IndicesVector>,
LoadInst *> OriginalLoads;
140 if (ByValArgsToTransform.
count(&*
I)) {
142 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
147 ++NumByValArgsPromoted;
148 }
else if (!ArgsToPromote.
count(&*
I)) {
150 Params.push_back(
I->getType());
152 }
else if (
I->use_empty()) {
165 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
166 for (
User *U :
I->users()) {
169 if (
LoadInst *L = dyn_cast<LoadInst>(UI))
170 SrcTy = L->getType();
172 SrcTy = cast<GetElementPtrInst>(UI)->getSourceElementType();
180 Indices.push_back(cast<ConstantInt>(*II)->getSExtValue());
182 if (Indices.size() == 1 && Indices.front() == 0)
184 ArgIndices.insert(std::make_pair(SrcTy, Indices));
186 if (
LoadInst *L = dyn_cast<LoadInst>(UI))
190 OrigLoad = cast<LoadInst>(UI->
user_back());
191 OriginalLoads[std::make_pair(&*
I, Indices)] = OrigLoad;
195 for (
const auto &ArgIndex : ArgIndices) {
198 cast<PointerType>(
I->getType()->getScalarType())->getElementType(),
204 if (ArgIndices.size() == 1 && ArgIndices.begin()->second.empty())
205 ++NumArgumentsPromoted;
207 ++NumAggregatesPromoted;
225 LLVM_DEBUG(
dbgs() <<
"ARG PROMOTION: Promoting to:" << *NF <<
"\n" 243 assert(CS.getCalledFunction() ==
F);
253 if (!ArgsToPromote.
count(&*
I) && !ByValArgsToTransform.
count(&*
I)) {
256 }
else if (ByValArgsToTransform.
count(&*
I)) {
258 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
265 STy, *AI, Idxs, (*AI)->
getName() +
"." +
Twine(i), Call);
270 }
else if (!
I->use_empty()) {
272 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
275 std::vector<Value *> Ops;
276 for (
const auto &ArgIndex : ArgIndices) {
279 OriginalLoads[std::make_pair(&*
I, ArgIndex.second)];
280 if (!ArgIndex.second.empty()) {
281 Ops.reserve(ArgIndex.second.size());
283 for (
auto II : ArgIndex.second) {
291 if (
auto *ElPTy = dyn_cast<PointerType>(ElTy))
292 ElTy = ElPTy->getElementType();
294 ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(II);
316 for (; AI != CS.arg_end(); ++AI, ++ArgNo) {
322 CS.getOperandBundlesAsDefs(OpBundles);
325 if (
InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
327 Args, OpBundles,
"", Call);
330 NewCall->setTailCallKind(cast<CallInst>(Call)->getTailCallKind());
337 NewCS->setDebugLoc(Call->getDebugLoc());
339 if (Call->extractProfTotalWeight(W))
340 NewCS->setProfWeight(W);
346 (*ReplaceCallSite)(CS, NewCS);
348 if (!Call->use_empty()) {
350 NewCS->takeName(Call);
355 Call->eraseFromParent();
368 I2 = NF->arg_begin();
370 if (!ArgsToPromote.
count(&*
I) && !ByValArgsToTransform.
count(&*
I)) {
373 I->replaceAllUsesWith(&*I2);
379 if (ByValArgsToTransform.
count(&*
I)) {
385 Type *AgTy = cast<PointerType>(
I->getType())->getElementType();
387 I->getParamAlignment(),
"", InsertPt);
392 for (
unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
395 AgTy, TheAlloca, Idxs, TheAlloca->
getName() +
"." +
Twine(i),
402 I->replaceAllUsesWith(TheAlloca);
422 ScalarizeTable &ArgIndices = ScalarizedElements[&*
I];
424 while (!
I->use_empty()) {
425 if (
LoadInst *LI = dyn_cast<LoadInst>(
I->user_back())) {
426 assert(ArgIndices.begin()->second.empty() &&
427 "Load element should sort to front!");
428 I2->setName(
I->getName() +
".val");
429 LI->replaceAllUsesWith(&*I2);
430 LI->eraseFromParent();
432 <<
"' in function '" << F->
getName() <<
"'\n");
439 Operands.push_back(cast<ConstantInt>(*II)->getSExtValue());
442 if (Operands.size() == 1 && Operands.front() == 0)
446 for (ScalarizeTable::iterator It = ArgIndices.begin();
447 It->second != Operands; ++It, ++TheArg) {
448 assert(It != ArgIndices.end() &&
"GEP not handled??");
451 std::string NewName =
I->getName();
452 for (
unsigned i = 0, e = Operands.size(); i != e; ++i) {
453 NewName +=
"." +
utostr(Operands[i]);
459 <<
"' of function '" << NF->getName() <<
"'\n");
473 std::advance(I2, ArgIndices.size());
491 assert(CS &&
"Should only have direct calls!");
505 if (Prefix.size() > Longer.size())
507 return std::equal(Prefix.begin(), Prefix.end(), Longer.begin());
512 std::set<IndicesVector> &Set) {
513 std::set<IndicesVector>::iterator Low;
514 Low = Set.upper_bound(Indices);
515 if (Low != Set.begin())
522 return Low != Set.end() &&
isPrefix(*Low, Indices);
531 std::set<IndicesVector> &Safe) {
532 std::set<IndicesVector>::iterator Low;
533 Low = Safe.upper_bound(ToMark);
535 if (Low != Safe.begin())
540 if (Low != Safe.end()) {
550 Low = Safe.insert(Low, ToMark);
553 std::set<IndicesVector>::iterator End = Safe.end();
554 while (Low != End &&
isPrefix(ToMark, *Low)) {
555 std::set<IndicesVector>::iterator Remove = Low;
568 using GEPIndicesSet = std::set<IndicesVector>;
592 GEPIndicesSet SafeToUnconditionallyLoad;
596 GEPIndicesSet ToPromote;
608 if (
LoadInst *LI = dyn_cast<LoadInst>(&
I)) {
609 Value *V = LI->getPointerOperand();
611 V =
GEP->getPointerOperand();
614 Indices.reserve(
GEP->getNumIndices());
618 Indices.push_back(CI->getSExtValue());
628 }
else if (V == Arg) {
639 User *UR = U.getUser();
641 if (
LoadInst *LI = dyn_cast<LoadInst>(UR)) {
647 Operands.push_back(0);
649 if (
GEP->use_empty()) {
652 GEP->eraseFromParent();
664 Operands.push_back(
C->getSExtValue());
669 for (
User *GEPU :
GEP->users())
670 if (
LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
685 if (!
prefixIn(Operands, SafeToUnconditionallyLoad))
691 if (ToPromote.find(Operands) == ToPromote.end()) {
692 if (MaxElements > 0 && ToPromote.size() == MaxElements) {
695 <<
"' because it would require adding more " 696 <<
"than " << MaxElements
697 <<
" arguments to the function.\n");
702 ToPromote.insert(std::move(Operands));
754 if (!isa<CompositeType>(type))
762 StructType *StructTy = cast<StructType>(type);
764 uint64_t StartPos = 0;
769 if (StartPos != Layout->getElementOffsetInBits(i))
792 while (!WorkList.
empty()) {
795 if (isa<GetElementPtrInst>(V) || isa<PHINode>(V)) {
796 if (PtrValues.insert(V).second)
800 }
else if (!isa<LoadInst>(V)) {
807 if (PtrValues.count(
Store->getValueOperand()))
817 for (
const Use &U : F.
uses()) {
819 const Function *Caller = CS.getCaller();
834 unsigned MaxElements,
859 if (
I.getType()->isPointerTy())
861 if (PointerArgs.
empty())
867 bool isSelfRecursive =
false;
871 if (CS.getInstruction() ==
nullptr || !CS.isCallee(&U))
875 if (CS.isMustTailCall())
878 if (CS.getInstruction()->getParent()->getParent() ==
F)
879 isSelfRecursive =
true;
885 if (BB.getTerminatingMustTailCall())
888 const DataLayout &DL = F->getParent()->getDataLayout();
896 for (
Argument *PtrArg : PointerArgs) {
897 Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
901 if (PtrArg->hasStructRetAttr()) {
902 unsigned ArgNo = PtrArg->getArgNo();
916 bool isSafeToPromote =
917 PtrArg->hasByValAttr() &&
919 if (isSafeToPromote) {
920 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
921 if (MaxElements > 0 && STy->getNumElements() > MaxElements) {
924 <<
"' because it would require adding more" 925 <<
" than " << MaxElements
926 <<
" arguments to the function.\n");
931 bool AllSimple =
true;
932 for (
const auto *EltTy : STy->elements()) {
933 if (!EltTy->isSingleValueType()) {
943 ByValArgsToTransform.
insert(PtrArg);
951 if (isSelfRecursive) {
952 if (
StructType *STy = dyn_cast<StructType>(AgTy)) {
953 bool RecursiveType =
false;
954 for (
const auto *EltTy : STy->elements()) {
955 if (EltTy == PtrArg->getType()) {
956 RecursiveType =
true;
968 ArgsToPromote.
insert(PtrArg);
972 if (ArgsToPromote.
empty() && ByValArgsToTransform.
empty())
976 ByValArgsToTransform))
979 return doPromotion(F, ArgsToPromote, ByValArgsToTransform, ReplaceCallSite);
986 bool Changed =
false, LocalChange;
1000 assert(&F == &OldF &&
"Called with an unexpected function!");
1016 C.getOuterRefSCC().replaceNodeFunction(
N, *NewF);
1020 Changed |= LocalChange;
1021 }
while (LocalChange);
1036 explicit ArgPromotion(
unsigned MaxElements = 3)
1054 bool doInitialization(
CallGraph &CG)
override;
1057 unsigned MaxElements;
1065 "Promote 'by reference' arguments to scalars",
false,
1072 "Promote 'by reference' arguments to
scalars",
false, false)
1075 return new ArgPromotion(MaxElements);
1084 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
1088 bool Changed =
false, LocalChange;
1092 LocalChange =
false;
1108 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*OldF);
1110 {ReplaceCallSite}, TTI)) {
1116 if (OldNode->getNumReferences() == 0)
1122 SCC.ReplaceNode(OldNode, NewNode);
1126 Changed |= LocalChange;
1127 }
while (LocalChange);
1132 bool ArgPromotion::doInitialization(
CallGraph &CG) {
Pass interface - Implemented by all 'passes'.
const Function & getFunction() const
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
User::op_iterator arg_iterator
The type of iterator to use when looping over actual arguments at this call site. ...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A parsed version of the target data layout string in and methods for querying it. ...
iterator_range< use_iterator > uses()
bool hasLocalLinkage() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents an incoming formal argument to a Function.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
Type * getElementType(unsigned N) const
bool isSized(SmallPtrSetImpl< Type *> *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
unsigned getNumElements() const
Random access to the elements.
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
void push_back(const T &Elt)
Implements a lazy call graph analysis and related passes for the new pass manager.
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value *> IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This class represents a function call, abstracting a target machine's calling convention.
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.
Analysis pass providing the TargetTransformInfo.
Externally visible function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
STATISTIC(NumFunctions, "Total number of functions")
An instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
This defines the Use class.
bool hasByValAttr() const
Return true if this argument has the byval attribute.
A proxy from a FunctionAnalysisManager to an SCC.
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...
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
unsigned getAllocaAddrSpace() const
AnalysisUsage & addRequired()
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
#define INITIALIZE_PASS_DEPENDENCY(depName)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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 &)
This class is a functor to be used in legacy module or SCC passes for computing AA results for a func...
This file contains the simple types necessary to represent the attributes associated with functions a...
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.
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
InstrTy * getInstruction() const
void setName(const Twine &Name)
Change the name of the value.
unsigned getNumIndices() const
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
Class to represent function types.
Type * getType() const
All values are typed, get the type of this value.
AttributeSet getParamAttributes(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
A lazily constructed view of the call graph of a module.
AttributeList getAttributes() const
Return the attribute list for this Function.
An instruction for storing to memory.
LinkageTypes getLinkage() const
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.
amdgpu Simplify well known AMD library false Value * Callee
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
void getAAMetadata(AAMDNodes &N, bool Merge=false) const
Fills the AAMDNodes structure with AA metadata from this instruction.
void setAttributes(AttributeList PAL)
Set the parameter attributes of the call.
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.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
A set of analyses that are preserved following a run of a transformation pass.
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.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
The instances of the Type class are immutable: once they are created, they are never changed...
DISubprogram * getSubprogram() const
Get the attached subprogram.
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_NODISCARD bool empty() const
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const Instruction & front() const
A manager for alias analyses.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
element_iterator element_end() const
Represent the analysis usage information of a pass.
unsigned getAddressSpace() const
StringRef getName() const
Return the name for this struct type if it has an identity.
void setCallingConv(CallingConv::ID CC)
Set the calling convention of the call.
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
A node in the call graph.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
void setAlignment(unsigned Align)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
void setTailCall(bool isTC=true)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void getAAResultsAnalysisUsage(AnalysisUsage &AU)
A helper for the legacy pass manager to populate AU to add uses to make sure the analyses required by...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Representation for a specific memory location.
This is the superclass of the array and vector type classes.
unsigned getNumOperands() const
This is the shared class of boolean and integer constants.
ValTy * getArgument(unsigned ArgNo) const
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.
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...
Type * getReturnType() const
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)
std::string utostr(uint64_t X, bool isNeg=false)
void setLinkage(LinkageTypes LT)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
The access may modify the value stored in memory.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
iterator_range< user_iterator > users()
iterator insert(iterator I, T &&Elt)
element_iterator element_begin() const
amdgpu Simplify well known AMD library false Value Value * Arg
uint64_t getTypeSizeInBits(Type *Ty) const
Size examples:
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.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
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)
const Function * getParent() const
unsigned getAlignment() const
Return the alignment of the access that is being performed.
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...
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM_NODISCARD bool empty() const
static InvokeInst * Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef< Value *> Args, const Twine &NameStr, Instruction *InsertBefore=nullptr)
This file provides utility analysis objects describing memory locations.
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
const BasicBlockListType & getBasicBlockList() const
Get the underlying elements of the Function...
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
This header provides classes for managing passes over SCCs of the call graph.
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.
An SCC of the call graph.
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...
AttributeSet getFnAttributes() const
The function attributes are returned.
uint64_t getTypeAllocSizeInBits(Type *Ty) const
Returns the offset in bits between successive objects of the specified type, including alignment padd...
This is the interface for LLVM's primary stateless and local alias analysis.
A container for analyses that lazily runs them and caches their results.
This header defines various interfaces for pass management in LLVM.
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...
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute >> Attrs)
Create an AttributeList with the specified parameters in it.
iterator_range< arg_iterator > args()
bool isStructTy() const
True if this is an instance of StructType.
const BasicBlock * getParent() const
an instruction to allocate memory on the stack