132#define DEBUG_TYPE "mergefunc"
134STATISTIC(NumFunctionsMerged,
"Number of functions merged");
135STATISTIC(NumThunksWritten,
"Number of thunks generated");
136STATISTIC(NumAliasesWritten,
"Number of aliases generated");
137STATISTIC(NumDoubleWeak,
"Number of new functions created");
141 cl::desc(
"How many functions in a module could be used for "
142 "MergeFunctions to pass a basic correctness check. "
143 "'0' disables this check. Works only with '-debug' key."),
163 cl::desc(
"Preserve debug info in thunk when mergefunc "
164 "transformations are made."));
169 cl::desc(
"Allow mergefunc to create aliases"));
182 IRHash getHash()
const {
return Hash; }
195class MergeFunctions {
197 MergeFunctions() : FnTree(FunctionNodeCmp(&GlobalNumbers)) {
200 bool runOnModule(
Module &M);
205 class FunctionNodeCmp {
211 bool operator()(
const FunctionNode &LHS,
const FunctionNode &RHS)
const {
213 if (
LHS.getHash() !=
RHS.getHash())
214 return LHS.getHash() <
RHS.getHash();
216 return FCmp.compare() < 0;
219 using FnTreeType = std::set<FunctionNode, FunctionNodeCmp>;
225 std::vector<WeakTrackingVH> Deferred;
233 bool doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist);
246 void removeUsers(
Value *V);
261 filterInstsUnrelatedToPDI(
BasicBlock *GEntryBlock,
262 std::vector<Instruction *> &PDIUnrelatedWL,
263 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
273 eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL,
274 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
289 void replaceFunctionInTree(
const FunctionNode &FN,
Function *
G);
307 if (!MF.runOnModule(M))
313bool MergeFunctions::doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist) {
315 unsigned TripleNumber = 0;
318 dbgs() <<
"MERGEFUNC-VERIFY: Started for first " << Max <<
" functions.\n";
321 for (std::vector<WeakTrackingVH>::iterator
I = Worklist.begin(),
323 I != E && i < Max; ++
I, ++i) {
325 for (std::vector<WeakTrackingVH>::iterator J =
I; J != E && j < Max;
334 dbgs() <<
"MERGEFUNC-VERIFY: Non-symmetric; triple: " << TripleNumber
336 dbgs() << *F1 <<
'\n' << *F2 <<
'\n';
344 for (std::vector<WeakTrackingVH>::iterator K = J; K != E && k < Max;
345 ++k, ++K, ++TripleNumber) {
353 bool Transitive =
true;
355 if (Res1 != 0 && Res1 == Res4) {
357 Transitive = Res3 == Res1;
358 }
else if (Res3 != 0 && Res3 == -Res4) {
360 Transitive = Res3 == Res1;
361 }
else if (Res4 != 0 && -Res3 == Res4) {
363 Transitive = Res4 == -Res1;
367 dbgs() <<
"MERGEFUNC-VERIFY: Non-transitive; triple: "
368 << TripleNumber <<
"\n";
369 dbgs() <<
"Res1, Res3, Res4: " << Res1 <<
", " << Res3 <<
", "
371 dbgs() << *F1 <<
'\n' << *F2 <<
'\n' << *F3 <<
'\n';
378 dbgs() <<
"MERGEFUNC-VERIFY: " << (Valid ?
"Passed." :
"Failed.") <<
"\n";
390 for (
const Instruction &
I : BB.instructionsWithoutDebug()) {
391 if (!isa<IntrinsicInst>(&
I))
395 auto *MDL = dyn_cast<MetadataAsValue>(
Op);
398 if (
MDNode *
N = dyn_cast<MDNode>(MDL->getMetadata()))
409 return !
F.isDeclaration() && !
F.hasAvailableExternallyLinkage() &&
413bool MergeFunctions::runOnModule(
Module &M) {
414 bool Changed =
false;
423 std::vector<std::pair<IRHash, Function *>> HashedFuncs;
432 auto S = HashedFuncs.begin();
433 for (
auto I = HashedFuncs.begin(), IE = HashedFuncs.end();
I != IE; ++
I) {
436 if ((
I != S && std::prev(
I)->first ==
I->first) ||
437 (std::next(
I) != IE && std::next(
I)->first ==
I->first) ) {
443 std::vector<WeakTrackingVH> Worklist;
444 Deferred.swap(Worklist);
449 LLVM_DEBUG(
dbgs() <<
"size of worklist: " << Worklist.size() <<
'\n');
456 if (!
F->isDeclaration() && !
F->hasAvailableExternallyLinkage()) {
457 Changed |= insert(
F);
460 LLVM_DEBUG(
dbgs() <<
"size of FnTree: " << FnTree.size() <<
'\n');
461 }
while (!Deferred.empty());
464 FNodesInTree.clear();
465 GlobalNumbers.
clear();
474 CallBase *CB = dyn_cast<CallBase>(
U.getUser());
490 Type *SrcTy = V->getType();
515void MergeFunctions::eraseInstsUnrelatedToPDI(
516 std::vector<Instruction *> &PDIUnrelatedWL,
517 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) {
519 dbgs() <<
" Erasing instructions (in reverse order of appearance in "
520 "entry block) unrelated to parameter debug info from entry "
522 while (!PDIUnrelatedWL.empty()) {
527 I->eraseFromParent();
528 PDIUnrelatedWL.pop_back();
531 while (!PDVRUnrelatedWL.empty()) {
537 PDVRUnrelatedWL.pop_back();
540 LLVM_DEBUG(
dbgs() <<
" } // Done erasing instructions unrelated to parameter "
541 "debug info from entry block. \n");
545void MergeFunctions::eraseTail(
Function *
G) {
546 std::vector<BasicBlock *> WorklistBB;
548 BB.dropAllReferences();
549 WorklistBB.push_back(&BB);
551 while (!WorklistBB.empty()) {
567void MergeFunctions::filterInstsUnrelatedToPDI(
568 BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL,
569 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) {
570 std::set<Instruction *> PDIRelated;
571 std::set<DbgVariableRecord *> PDVRRelated;
575 auto ExamineDbgValue = [](
auto *DbgVal,
auto &Container) {
584 Container.insert(DbgVal);
592 auto ExamineDbgDeclare = [&PDIRelated](
auto *DbgDecl,
auto &Container) {
600 AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DbgDecl->getAddress());
605 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
606 if (
Value *Arg =
SI->getValueOperand()) {
607 if (isa<Argument>(Arg)) {
611 PDIRelated.insert(AI);
615 PDIRelated.insert(SI);
619 Container.insert(DbgDecl);
650 ExamineDbgValue(&DVR, PDVRRelated);
653 ExamineDbgDeclare(&DVR, PDVRRelated);
657 if (
auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
658 ExamineDbgValue(DVI, PDIRelated);
659 }
else if (
auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
660 ExamineDbgDeclare(DDI, PDIRelated);
661 }
else if (BI->isTerminator() && &*BI == GEntryBlock->
getTerminator()) {
665 PDIRelated.insert(&*BI);
674 <<
" Report parameter debug info related/related instructions: {\n");
676 auto IsPDIRelated = [](
auto *Rec,
auto &Container,
auto &UnrelatedCont) {
677 if (Container.find(Rec) == Container.end()) {
681 UnrelatedCont.push_back(Rec);
692 IsPDIRelated(&DVR, PDVRRelated, PDVRUnrelatedWL);
693 IsPDIRelated(&
I, PDIRelated, PDIUnrelatedWL);
705 if (
F->size() == 1) {
706 if (
F->front().sizeWithoutDebug() < 2) {
708 <<
" is too small to bother creating a thunk for\n");
719 From->getMetadata(Kind, MDs);
734 std::vector<Instruction *> PDIUnrelatedWL;
735 std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
739 LLVM_DEBUG(
dbgs() <<
"writeThunk: (MergeFunctionsPDI) Do not create a new "
740 "function as thunk; retain original: "
741 <<
G->getName() <<
"()\n");
742 GEntryBlock = &
G->getEntryBlock();
744 dbgs() <<
"writeThunk: (MergeFunctionsPDI) filter parameter related "
746 <<
G->getName() <<
"() {\n");
747 filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDVRUnrelatedWL);
752 G->getAddressSpace(),
"",
G->getParent());
768 CallInst *CI = Builder.CreateCall(
F, Args);
776 if (
H->getReturnType()->isVoidTy()) {
777 RI = Builder.CreateRetVoid();
779 RI = Builder.CreateRet(
createCast(Builder, CI,
H->getReturnType()));
793 dbgs() <<
"writeThunk: (MergeFunctionsPDI) No DISubprogram for "
794 <<
G->getName() <<
"()\n");
797 eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDVRUnrelatedWL);
799 dbgs() <<
"} // End of parameter related debug info filtering for: "
800 <<
G->getName() <<
"()\n");
808 G->replaceAllUsesWith(NewG);
809 G->eraseFromParent();
822 assert(
F->hasLocalLinkage() ||
F->hasExternalLinkage()
823 ||
F->hasWeakLinkage() ||
F->hasLinkOnceLinkage());
831 G->getLinkage(),
"",
F,
G->getParent());
835 if (FAlign || GAlign)
838 F->setAlignment(std::nullopt);
840 GA->setVisibility(
G->getVisibility());
844 G->replaceAllUsesWith(GA);
845 G->eraseFromParent();
867 if (
F->isInterposable()) {
879 F->getAddressSpace(),
"",
F->getParent());
887 F->replaceAllUsesWith(NewF);
894 writeThunkOrAlias(
F,
G);
895 writeThunkOrAlias(
F, NewF);
897 if (NewFAlign || GAlign)
900 F->setAlignment(std::nullopt);
903 ++NumFunctionsMerged;
911 if (
G->hasGlobalUnnamedAddr() && !
Used.contains(
G)) {
917 G->replaceAllUsesWith(
F);
921 replaceDirectCallers(
G,
F);
929 G->eraseFromParent();
930 ++NumFunctionsMerged;
934 if (writeThunkOrAlias(
F,
G)) {
935 ++NumFunctionsMerged;
941void MergeFunctions::replaceFunctionInTree(
const FunctionNode &FN,
945 "The two functions must be equal");
947 auto I = FNodesInTree.find(
F);
948 assert(
I != FNodesInTree.end() &&
"F should be in FNodesInTree");
949 assert(FNodesInTree.count(
G) == 0 &&
"FNodesInTree should not contain G");
951 FnTreeType::iterator IterToFNInFnTree =
I->second;
952 assert(&(*IterToFNInFnTree) == &FN &&
"F should map to FN in FNodesInTree.");
954 FNodesInTree.erase(
I);
955 FNodesInTree.insert({
G, IterToFNInFnTree});
962 if (
F->isInterposable() !=
G->isInterposable()) {
965 return !
F->isInterposable();
967 if (
F->hasLocalLinkage() !=
G->hasLocalLinkage()) {
970 return !
F->hasLocalLinkage();
975 return F->getName() <=
G->getName();
980bool MergeFunctions::insert(
Function *NewFunction) {
981 std::pair<FnTreeType::iterator, bool>
Result =
982 FnTree.insert(FunctionNode(NewFunction));
985 assert(FNodesInTree.count(NewFunction) == 0);
986 FNodesInTree.insert({NewFunction,
Result.first});
992 const FunctionNode &OldF = *
Result.first;
997 replaceFunctionInTree(*
Result.first, NewFunction);
999 assert(OldF.getFunc() !=
F &&
"Must have swapped the functions.");
1003 <<
" == " << NewFunction->
getName() <<
'\n');
1006 mergeTwoFunctions(OldF.getFunc(), DeleteF);
1012void MergeFunctions::remove(
Function *
F) {
1013 auto I = FNodesInTree.find(
F);
1014 if (
I != FNodesInTree.end()) {
1016 FnTree.erase(
I->second);
1019 FNodesInTree.erase(
I);
1020 Deferred.emplace_back(
F);
1026void MergeFunctions::removeUsers(
Value *V) {
1027 for (
User *U :
V->users())
1028 if (
auto *
I = dyn_cast<Instruction>(U))
BlockVerifier::State From
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This defines the Use class.
static bool canCreateAliasFor(Function *F)
static bool isEligibleForMerging(Function &F)
Check whether F is eligible for function merging.
static cl::opt< unsigned > NumFunctionsForVerificationCheck("mergefunc-verify", cl::desc("How many functions in a module could be used for " "MergeFunctions to pass a basic correctness check. " "'0' disables this check. Works only with '-debug' key."), cl::init(0), cl::Hidden)
static bool canCreateThunkFor(Function *F)
Whether this function may be replaced by a forwarding thunk.
static cl::opt< bool > MergeFunctionsPDI("mergefunc-preserve-debug-info", cl::Hidden, cl::init(false), cl::desc("Preserve debug info in thunk when mergefunc " "transformations are made."))
static bool hasDistinctMetadataIntrinsic(const Function &F)
Check whether F has an intrinsic which references distinct metadata as an operand.
static Value * createCast(IRBuilder<> &Builder, Value *V, Type *DestTy)
static void copyMetadataIfPresent(Function *From, Function *To, StringRef Kind)
Copy all metadata of a specific kind from one function to another.
static cl::opt< bool > MergeFunctionsAliases("mergefunc-use-aliases", cl::Hidden, cl::init(false), cl::desc("Allow mergefunc to create aliases"))
static bool isFuncOrderCorrect(const Function *F, const Function *G)
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Value handle that asserts if the Value is deleted.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
const Instruction & back() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
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 parameter attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
This class represents an Operation in the Expression.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
void print(raw_ostream &O, bool IsForDebug=false) const
FunctionComparator - Compares two functions to determine whether or not they will generate machine co...
int compare()
Test whether the two functions have equivalent behaviour.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
bool IsNewDbgInfoFormat
Is this function using intrinsics to record the position of debugging information,...
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
static GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
GlobalNumberState assigns an integer to each global value in the program, which is used by the compar...
void erase(GlobalValue *Global)
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
void setComdat(Comdat *C)
void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
@ PrivateLinkage
Like Internal, but omit from symbol table.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const Function * getFunction() const
Return the function this instruction belongs to.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A Module instance is used to store all the information related to an LLVM module.
static 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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Return a value (possibly void), from a function.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
Type * getStructElementType(unsigned N) const
bool isPointerTy() const
True if this is an instance of PointerType.
unsigned getStructNumElements() const
bool isStructTy() const
True if this is an instance of StructType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
Value handle that is nullable, but tries to track the Value.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale)
Compare two scaled numbers.
initializer< Ty > init(const Ty &Val)
NodeAddr< FuncNode * > Func
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
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...
IRHash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Function object to check whether the first component of a container supported by std::get (like std::...