130#define DEBUG_TYPE "mergefunc"
132STATISTIC(NumFunctionsMerged,
"Number of functions merged");
133STATISTIC(NumThunksWritten,
"Number of thunks generated");
134STATISTIC(NumAliasesWritten,
"Number of aliases generated");
135STATISTIC(NumDoubleWeak,
"Number of new functions created");
139 cl::desc(
"How many functions in a module could be used for "
140 "MergeFunctions to pass a basic correctness check. "
141 "'0' disables this check. Works only with '-debug' key."),
161 cl::desc(
"Preserve debug info in thunk when mergefunc "
162 "transformations are made."));
167 cl::desc(
"Allow mergefunc to create aliases"));
179 Function *getFunc()
const {
return F; }
184 void replaceBy(Function *
G)
const {
193class MergeFunctions {
195 MergeFunctions() : FnTree(FunctionNodeCmp(&GlobalNumbers)) {
198 template <
typename FuncContainer>
bool run(FuncContainer &Functions);
201 SmallPtrSet<GlobalValue *, 4> &getUsed();
206 class FunctionNodeCmp {
207 GlobalNumberState* GlobalNumbers;
210 FunctionNodeCmp(GlobalNumberState* GN) : GlobalNumbers(GN) {}
212 bool operator()(
const FunctionNode &
LHS,
const FunctionNode &
RHS)
const {
214 if (
LHS.getHash() !=
RHS.getHash())
215 return LHS.getHash() <
RHS.getHash();
216 FunctionComparator FCmp(
LHS.getFunc(),
RHS.getFunc(), GlobalNumbers);
217 return FCmp.compare() < 0;
220 using FnTreeType = std::set<FunctionNode, FunctionNodeCmp>;
222 GlobalNumberState GlobalNumbers;
226 std::vector<WeakTrackingVH> Deferred;
229 SmallPtrSet<GlobalValue *, 4> Used;
234 bool doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist);
239 bool insert(Function *NewFunction);
247 void removeUsers(
Value *V);
251 void replaceDirectCallers(Function *Old, Function *New);
256 void mergeTwoFunctions(Function *
F, Function *
G);
262 filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock,
263 std::vector<Instruction *> &PDIUnrelatedWL,
264 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
267 void eraseTail(Function *
G);
274 eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL,
275 std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
280 void writeThunk(Function *
F, Function *
G);
283 void writeAlias(Function *
F, Function *
G);
288 bool writeThunkOrAliasIfNeeded(Function *
F, Function *
G);
291 void replaceFunctionInTree(
const FunctionNode &FN, Function *
G);
302 DenseMap<AssertingVH<Function>, FnTreeType::iterator> FNodesInTree;
305 DenseMap<Function *, Function *> DelToNewMap;
323 MF.getUsed().insert_range(UsedV);
330 return MF.runOnFunctions(
F);
334bool MergeFunctions::doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist) {
336 unsigned TripleNumber = 0;
339 dbgs() <<
"MERGEFUNC-VERIFY: Started for first " << Max <<
" functions.\n";
342 for (std::vector<WeakTrackingVH>::iterator
I = Worklist.begin(),
344 I != E && i < Max; ++
I, ++i) {
346 for (std::vector<WeakTrackingVH>::iterator J =
I; J != E && j < Max;
355 dbgs() <<
"MERGEFUNC-VERIFY: Non-symmetric; triple: " << TripleNumber
357 dbgs() << *F1 <<
'\n' << *F2 <<
'\n';
365 for (std::vector<WeakTrackingVH>::iterator K = J; K !=
E && k < Max;
366 ++k, ++K, ++TripleNumber) {
374 bool Transitive =
true;
376 if (Res1 != 0 && Res1 == Res4) {
378 Transitive = Res3 == Res1;
379 }
else if (Res3 != 0 && Res3 == -Res4) {
381 Transitive = Res3 == Res1;
382 }
else if (Res4 != 0 && -Res3 == Res4) {
384 Transitive = Res4 == -Res1;
388 dbgs() <<
"MERGEFUNC-VERIFY: Non-transitive; triple: "
389 << TripleNumber <<
"\n";
390 dbgs() <<
"Res1, Res3, Res4: " << Res1 <<
", " << Res3 <<
", "
392 dbgs() << *F1 <<
'\n' << *F2 <<
'\n' << *F3 <<
'\n';
399 dbgs() <<
"MERGEFUNC-VERIFY: " << (Valid ?
"Passed." :
"Failed.") <<
"\n";
411 for (
const Instruction &
I : BB.instructionsWithoutDebug()) {
430 return !
F.isDeclaration() && !
F.hasAvailableExternallyLinkage() &&
437template <
typename FuncContainer>
bool MergeFunctions::run(FuncContainer &M) {
442 std::vector<std::pair<stable_hash, Function *>> HashedFuncs;
443 for (
auto &Func : M) {
452 auto S = HashedFuncs.begin();
453 for (
auto I = HashedFuncs.begin(), IE = HashedFuncs.end();
I != IE; ++
I) {
456 if ((
I != S && std::prev(
I)->first ==
I->first) ||
457 (std::next(
I) != IE && std::next(
I)->first ==
I->first)) {
463 std::vector<WeakTrackingVH> Worklist;
464 Deferred.swap(Worklist);
469 LLVM_DEBUG(
dbgs() <<
"size of worklist: " << Worklist.size() <<
'\n');
476 if (!
F->isDeclaration() && !
F->hasAvailableExternallyLinkage()) {
480 LLVM_DEBUG(
dbgs() <<
"size of FnTree: " << FnTree.size() <<
'\n');
481 }
while (!Deferred.empty());
484 FNodesInTree.clear();
485 GlobalNumbers.
clear();
493 [[maybe_unused]]
bool MergeResult = this->
run(
F);
494 assert(MergeResult == !DelToNewMap.empty());
495 return this->DelToNewMap;
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()) {
554 WorklistBB.pop_back();
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;
584 PDVRRelated.insert(DbgVal);
592 auto ExamineDbgDeclare = [&PDIRelated,
607 if (
Value *Arg =
SI->getValueOperand()) {
612 PDIRelated.insert(AI);
616 PDIRelated.insert(
SI);
620 PDVRRelated.insert(DbgDecl);
651 ExamineDbgValue(&DVR);
654 ExamineDbgDeclare(&DVR);
658 if (BI->isTerminator() && &*BI == GEntryBlock->
getTerminator()) {
662 PDIRelated.insert(&*BI);
671 <<
" Report parameter debug info related/related instructions: {\n");
673 auto IsPDIRelated = [](
auto *Rec,
auto &Container,
auto &UnrelatedCont) {
674 if (Container.find(Rec) == Container.end()) {
678 UnrelatedCont.push_back(Rec);
689 IsPDIRelated(&DVR, PDVRRelated, PDVRUnrelatedWL);
690 IsPDIRelated(&
I, PDIRelated, PDIUnrelatedWL);
702 if (
F->size() == 1) {
703 if (
F->front().sizeWithoutDebug() < 2) {
705 <<
" is too small to bother creating a thunk for\n");
731 std::vector<Instruction *> PDIUnrelatedWL;
732 std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
736 LLVM_DEBUG(
dbgs() <<
"writeThunk: (MergeFunctionsPDI) Do not create a new "
737 "function as thunk; retain original: "
738 <<
G->getName() <<
"()\n");
739 GEntryBlock = &
G->getEntryBlock();
741 dbgs() <<
"writeThunk: (MergeFunctionsPDI) filter parameter related "
743 <<
G->getName() <<
"() {\n");
744 filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDVRUnrelatedWL);
749 G->getAddressSpace(),
"",
G->getParent());
760 Args.push_back(Builder.CreateAggregateCast(&AI, FFTy->getParamType(i)));
764 CallInst *CI = Builder.CreateCall(
F, Args);
772 if (
H->getReturnType()->isVoidTy()) {
773 RI = Builder.CreateRetVoid();
775 RI = Builder.CreateRet(Builder.CreateAggregateCast(CI,
H->getReturnType()));
789 dbgs() <<
"writeThunk: (MergeFunctionsPDI) No DISubprogram for "
790 <<
G->getName() <<
"()\n");
793 eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDVRUnrelatedWL);
795 dbgs() <<
"} // End of parameter related debug info filtering for: "
796 <<
G->getName() <<
"()\n");
804 G->replaceAllUsesWith(NewG);
805 G->eraseFromParent();
818 assert(
F->hasLocalLinkage() ||
F->hasExternalLinkage()
819 ||
F->hasWeakLinkage() ||
F->hasLinkOnceLinkage());
827 G->getLinkage(),
"",
F,
G->getParent());
831 if (FAlign || GAlign)
834 F->setAlignment(std::nullopt);
836 GA->setVisibility(
G->getVisibility());
840 G->replaceAllUsesWith(GA);
841 G->eraseFromParent();
852 G->eraseFromParent();
868 return F->hasWeakODRLinkage() ||
F->hasLinkOnceODRLinkage();
879 "if G is ODR, F must also be ODR due to ordering");
891 F->getAddressSpace(),
"",
F->getParent());
895 F->setComdat(
nullptr);
900 F->replaceAllUsesWith(NewF);
905 replaceDirectCallers(
G,
F);
907 replaceDirectCallers(NewF,
F);
914 writeThunkOrAliasIfNeeded(
F,
G);
915 writeThunkOrAliasIfNeeded(
F, NewF);
917 if (NewFAlign || GAlign)
920 F->setAlignment(std::nullopt);
923 ++NumFunctionsMerged;
931 if (
G->hasGlobalUnnamedAddr() && !
Used.contains(
G)) {
937 G->replaceAllUsesWith(
F);
941 replaceDirectCallers(
G,
F);
949 G->eraseFromParent();
950 ++NumFunctionsMerged;
954 if (writeThunkOrAliasIfNeeded(
F,
G)) {
955 ++NumFunctionsMerged;
961void MergeFunctions::replaceFunctionInTree(
const FunctionNode &FN,
965 "The two functions must be equal");
967 auto I = FNodesInTree.find(
F);
968 assert(
I != FNodesInTree.end() &&
"F should be in FNodesInTree");
969 assert(FNodesInTree.count(
G) == 0 &&
"FNodesInTree should not contain G");
971 FnTreeType::iterator IterToFNInFnTree =
I->second;
972 assert(&(*IterToFNInFnTree) == &FN &&
"F should map to FN in FNodesInTree.");
974 FNodesInTree.erase(
I);
975 FNodesInTree.insert({
G, IterToFNInFnTree});
988 if (
F->isInterposable() !=
G->isInterposable()) {
991 return !
F->isInterposable();
994 if (
F->hasLocalLinkage() !=
G->hasLocalLinkage()) {
997 return !
F->hasLocalLinkage();
1003 return F->getName() <=
G->getName();
1008bool MergeFunctions::insert(
Function *NewFunction) {
1009 std::pair<FnTreeType::iterator, bool>
Result =
1010 FnTree.insert(FunctionNode(NewFunction));
1013 assert(FNodesInTree.count(NewFunction) == 0);
1014 FNodesInTree.insert({NewFunction,
Result.first});
1020 const FunctionNode &OldF = *
Result.first;
1025 replaceFunctionInTree(*
Result.first, NewFunction);
1027 assert(OldF.getFunc() !=
F &&
"Must have swapped the functions.");
1031 <<
" == " << NewFunction->
getName() <<
'\n');
1034 mergeTwoFunctions(OldF.getFunc(), DeleteF);
1035 this->DelToNewMap.insert({DeleteF, OldF.getFunc()});
1041void MergeFunctions::remove(
Function *
F) {
1042 auto I = FNodesInTree.find(
F);
1043 if (
I != FNodesInTree.end()) {
1045 FnTree.erase(
I->second);
1048 FNodesInTree.erase(
I);
1049 Deferred.emplace_back(
F);
1055void MergeFunctions::removeUsers(
Value *V) {
1056 for (
User *U :
V->users())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Module.h This file contains the declarations for the Module class.
This defines the Use class.
static bool canCreateAliasFor(Function *F)
static bool isEligibleForMerging(Function &F)
Check whether F is eligible for function merging.
static bool isODR(const Function *F)
Returns true if F is either weak_odr or linkonce_odr.
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.
Function * asPtr(Function *Fn)
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)
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
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.
LLVM_ABI 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...
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 attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
LLVM_ABI DISubprogram * getSubprogram() const
Get the subprogram for this scope.
Subprogram description. Uses SubclassData1.
LLVM_ABI void eraseFromParent()
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
bool isDbgDeclare() const
FunctionComparator - Compares two functions to determine whether or not they will generate machine co...
LLVM_ABI int compare()
Test whether the two functions have equivalent behaviour.
Class to represent function types.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
MaybeAlign getAlign() const
Returns the alignment of the given function.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
static LLVM_ABI 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...
void erase(GlobalValue *Global)
LLVM_ABI void setComdat(Comdat *C)
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
@ PrivateLinkage
Like Internal, but omit from symbol table.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI 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
static LLVM_ABI DenseMap< Function *, Function * > runOnFunctions(ArrayRef< Function * > F)
static LLVM_ABI bool runOnModule(Module &M)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A Module instance is used to store all the information related to an LLVM module.
Class to represent pointers.
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.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI 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)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
LLVM_ABI 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.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
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...
uint64_t stable_hash
An opaque object representing a stable hash code.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
LLVM_ABI stable_hash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI 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::...