10b57cec5SDimitry Andric //===- MergeFunctions.cpp - Merge identical functions ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass looks for equivalent functions that are mergable and folds them.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric // Order relation is defined on set of functions. It was made through
120b57cec5SDimitry Andric // special function comparison procedure that returns
130b57cec5SDimitry Andric // 0 when functions are equal,
140b57cec5SDimitry Andric // -1 when Left function is less than right function, and
150b57cec5SDimitry Andric // 1 for opposite case. We need total-ordering, so we need to maintain
160b57cec5SDimitry Andric // four properties on the functions set:
170b57cec5SDimitry Andric // a <= a (reflexivity)
180b57cec5SDimitry Andric // if a <= b and b <= a then a = b (antisymmetry)
190b57cec5SDimitry Andric // if a <= b and b <= c then a <= c (transitivity).
200b57cec5SDimitry Andric // for all a and b: a <= b or b <= a (totality).
210b57cec5SDimitry Andric //
220b57cec5SDimitry Andric // Comparison iterates through each instruction in each basic block.
230b57cec5SDimitry Andric // Functions are kept on binary tree. For each new function F we perform
240b57cec5SDimitry Andric // lookup in binary tree.
250b57cec5SDimitry Andric // In practice it works the following way:
260b57cec5SDimitry Andric // -- We define Function* container class with custom "operator<" (FunctionPtr).
270b57cec5SDimitry Andric // -- "FunctionPtr" instances are stored in std::set collection, so every
280b57cec5SDimitry Andric // std::set::insert operation will give you result in log(N) time.
290b57cec5SDimitry Andric //
300b57cec5SDimitry Andric // As an optimization, a hash of the function structure is calculated first, and
310b57cec5SDimitry Andric // two functions are only compared if they have the same hash. This hash is
320b57cec5SDimitry Andric // cheap to compute, and has the property that if function F == G according to
330b57cec5SDimitry Andric // the comparison function, then hash(F) == hash(G). This consistency property
340b57cec5SDimitry Andric // is critical to ensuring all possible merging opportunities are exploited.
350b57cec5SDimitry Andric // Collisions in the hash affect the speed of the pass but not the correctness
360b57cec5SDimitry Andric // or determinism of the resulting transformation.
370b57cec5SDimitry Andric //
380b57cec5SDimitry Andric // When a match is found the functions are folded. If both functions are
390b57cec5SDimitry Andric // overridable, we move the functionality into a new internal function and
400b57cec5SDimitry Andric // leave two overridable thunks to it.
410b57cec5SDimitry Andric //
420b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
430b57cec5SDimitry Andric //
440b57cec5SDimitry Andric // Future work:
450b57cec5SDimitry Andric //
460b57cec5SDimitry Andric // * virtual functions.
470b57cec5SDimitry Andric //
480b57cec5SDimitry Andric // Many functions have their address taken by the virtual function table for
490b57cec5SDimitry Andric // the object they belong to. However, as long as it's only used for a lookup
500b57cec5SDimitry Andric // and call, this is irrelevant, and we'd like to fold such functions.
510b57cec5SDimitry Andric //
520b57cec5SDimitry Andric // * be smarter about bitcasts.
530b57cec5SDimitry Andric //
540b57cec5SDimitry Andric // In order to fold functions, we will sometimes add either bitcast instructions
550b57cec5SDimitry Andric // or bitcast constant expressions. Unfortunately, this can confound further
560b57cec5SDimitry Andric // analysis since the two functions differ where one has a bitcast and the
570b57cec5SDimitry Andric // other doesn't. We should learn to look through bitcasts.
580b57cec5SDimitry Andric //
590b57cec5SDimitry Andric // * Compare complex types with pointer types inside.
600b57cec5SDimitry Andric // * Compare cross-reference cases.
610b57cec5SDimitry Andric // * Compare complex expressions.
620b57cec5SDimitry Andric //
630b57cec5SDimitry Andric // All the three issues above could be described as ability to prove that
640b57cec5SDimitry Andric // fA == fB == fC == fE == fF == fG in example below:
650b57cec5SDimitry Andric //
660b57cec5SDimitry Andric // void fA() {
670b57cec5SDimitry Andric // fB();
680b57cec5SDimitry Andric // }
690b57cec5SDimitry Andric // void fB() {
700b57cec5SDimitry Andric // fA();
710b57cec5SDimitry Andric // }
720b57cec5SDimitry Andric //
730b57cec5SDimitry Andric // void fE() {
740b57cec5SDimitry Andric // fF();
750b57cec5SDimitry Andric // }
760b57cec5SDimitry Andric // void fF() {
770b57cec5SDimitry Andric // fG();
780b57cec5SDimitry Andric // }
790b57cec5SDimitry Andric // void fG() {
800b57cec5SDimitry Andric // fE();
810b57cec5SDimitry Andric // }
820b57cec5SDimitry Andric //
830b57cec5SDimitry Andric // Simplest cross-reference case (fA <--> fB) was implemented in previous
840b57cec5SDimitry Andric // versions of MergeFunctions, though it presented only in two function pairs
850b57cec5SDimitry Andric // in test-suite (that counts >50k functions)
860b57cec5SDimitry Andric // Though possibility to detect complex cross-referencing (e.g.: A->B->C->D->A)
870b57cec5SDimitry Andric // could cover much more cases.
880b57cec5SDimitry Andric //
890b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
900b57cec5SDimitry Andric
9181ad6265SDimitry Andric #include "llvm/Transforms/IPO/MergeFunctions.h"
920b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
930b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
940b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
950b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
960b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
970b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
980b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
990b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
1000b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
1010b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
1020b57cec5SDimitry Andric #include "llvm/IR/Function.h"
1030b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
1040b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
1050b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
1060b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
1070b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
1080b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
1090b57cec5SDimitry Andric #include "llvm/IR/Module.h"
1105f757f3fSDimitry Andric #include "llvm/IR/StructuralHash.h"
1110b57cec5SDimitry Andric #include "llvm/IR/Type.h"
1120b57cec5SDimitry Andric #include "llvm/IR/Use.h"
1130b57cec5SDimitry Andric #include "llvm/IR/User.h"
1140b57cec5SDimitry Andric #include "llvm/IR/Value.h"
1150b57cec5SDimitry Andric #include "llvm/IR/ValueHandle.h"
1160b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
1170b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
1180b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
1190b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
1200b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
1210b57cec5SDimitry Andric #include "llvm/Transforms/Utils/FunctionComparator.h"
12281ad6265SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
1230b57cec5SDimitry Andric #include <algorithm>
1240b57cec5SDimitry Andric #include <cassert>
1250b57cec5SDimitry Andric #include <iterator>
1260b57cec5SDimitry Andric #include <set>
1270b57cec5SDimitry Andric #include <utility>
1280b57cec5SDimitry Andric #include <vector>
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric using namespace llvm;
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric #define DEBUG_TYPE "mergefunc"
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric STATISTIC(NumFunctionsMerged, "Number of functions merged");
1350b57cec5SDimitry Andric STATISTIC(NumThunksWritten, "Number of thunks generated");
1360b57cec5SDimitry Andric STATISTIC(NumAliasesWritten, "Number of aliases generated");
1370b57cec5SDimitry Andric STATISTIC(NumDoubleWeak, "Number of new functions created");
1380b57cec5SDimitry Andric
13981ad6265SDimitry Andric static cl::opt<unsigned> NumFunctionsForVerificationCheck(
14081ad6265SDimitry Andric "mergefunc-verify",
14181ad6265SDimitry Andric cl::desc("How many functions in a module could be used for "
14281ad6265SDimitry Andric "MergeFunctions to pass a basic correctness check. "
1430b57cec5SDimitry Andric "'0' disables this check. Works only with '-debug' key."),
1440b57cec5SDimitry Andric cl::init(0), cl::Hidden);
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric // Under option -mergefunc-preserve-debug-info we:
1470b57cec5SDimitry Andric // - Do not create a new function for a thunk.
1480b57cec5SDimitry Andric // - Retain the debug info for a thunk's parameters (and associated
1490b57cec5SDimitry Andric // instructions for the debug info) from the entry block.
1500b57cec5SDimitry Andric // Note: -debug will display the algorithm at work.
1510b57cec5SDimitry Andric // - Create debug-info for the call (to the shared implementation) made by
1520b57cec5SDimitry Andric // a thunk and its return value.
1530b57cec5SDimitry Andric // - Erase the rest of the function, retaining the (minimally sized) entry
1540b57cec5SDimitry Andric // block to create a thunk.
1550b57cec5SDimitry Andric // - Preserve a thunk's call site to point to the thunk even when both occur
1560b57cec5SDimitry Andric // within the same translation unit, to aid debugability. Note that this
1570b57cec5SDimitry Andric // behaviour differs from the underlying -mergefunc implementation which
1580b57cec5SDimitry Andric // modifies the thunk's call site to point to the shared implementation
1590b57cec5SDimitry Andric // when both occur within the same translation unit.
1600b57cec5SDimitry Andric static cl::opt<bool>
1610b57cec5SDimitry Andric MergeFunctionsPDI("mergefunc-preserve-debug-info", cl::Hidden,
1620b57cec5SDimitry Andric cl::init(false),
1630b57cec5SDimitry Andric cl::desc("Preserve debug info in thunk when mergefunc "
1640b57cec5SDimitry Andric "transformations are made."));
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric static cl::opt<bool>
1670b57cec5SDimitry Andric MergeFunctionsAliases("mergefunc-use-aliases", cl::Hidden,
1680b57cec5SDimitry Andric cl::init(false),
1690b57cec5SDimitry Andric cl::desc("Allow mergefunc to create aliases"));
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric namespace {
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric class FunctionNode {
1740b57cec5SDimitry Andric mutable AssertingVH<Function> F;
1755f757f3fSDimitry Andric IRHash Hash;
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric public:
1780b57cec5SDimitry Andric // Note the hash is recalculated potentially multiple times, but it is cheap.
FunctionNode(Function * F)1795f757f3fSDimitry Andric FunctionNode(Function *F) : F(F), Hash(StructuralHash(*F)) {}
1800b57cec5SDimitry Andric
getFunc() const1810b57cec5SDimitry Andric Function *getFunc() const { return F; }
getHash() const1825f757f3fSDimitry Andric IRHash getHash() const { return Hash; }
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric /// Replace the reference to the function F by the function G, assuming their
1850b57cec5SDimitry Andric /// implementations are equal.
replaceBy(Function * G) const1860b57cec5SDimitry Andric void replaceBy(Function *G) const {
1870b57cec5SDimitry Andric F = G;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric };
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric /// MergeFunctions finds functions which will generate identical machine code,
1920b57cec5SDimitry Andric /// by considering all pointer types to be equivalent. Once identified,
1930b57cec5SDimitry Andric /// MergeFunctions will fold them by replacing a call to one to a call to a
1940b57cec5SDimitry Andric /// bitcast of the other.
195480093f4SDimitry Andric class MergeFunctions {
1960b57cec5SDimitry Andric public:
MergeFunctions()197480093f4SDimitry Andric MergeFunctions() : FnTree(FunctionNodeCmp(&GlobalNumbers)) {
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
200480093f4SDimitry Andric bool runOnModule(Module &M);
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric private:
2030b57cec5SDimitry Andric // The function comparison operator is provided here so that FunctionNodes do
2040b57cec5SDimitry Andric // not need to become larger with another pointer.
2050b57cec5SDimitry Andric class FunctionNodeCmp {
2060b57cec5SDimitry Andric GlobalNumberState* GlobalNumbers;
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric public:
FunctionNodeCmp(GlobalNumberState * GN)2090b57cec5SDimitry Andric FunctionNodeCmp(GlobalNumberState* GN) : GlobalNumbers(GN) {}
2100b57cec5SDimitry Andric
operator ()(const FunctionNode & LHS,const FunctionNode & RHS) const2110b57cec5SDimitry Andric bool operator()(const FunctionNode &LHS, const FunctionNode &RHS) const {
2120b57cec5SDimitry Andric // Order first by hashes, then full function comparison.
2130b57cec5SDimitry Andric if (LHS.getHash() != RHS.getHash())
2140b57cec5SDimitry Andric return LHS.getHash() < RHS.getHash();
2150b57cec5SDimitry Andric FunctionComparator FCmp(LHS.getFunc(), RHS.getFunc(), GlobalNumbers);
216bdd1243dSDimitry Andric return FCmp.compare() < 0;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric };
2190b57cec5SDimitry Andric using FnTreeType = std::set<FunctionNode, FunctionNodeCmp>;
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric GlobalNumberState GlobalNumbers;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric /// A work queue of functions that may have been modified and should be
2240b57cec5SDimitry Andric /// analyzed again.
2250b57cec5SDimitry Andric std::vector<WeakTrackingVH> Deferred;
2260b57cec5SDimitry Andric
22781ad6265SDimitry Andric /// Set of values marked as used in llvm.used and llvm.compiler.used.
22881ad6265SDimitry Andric SmallPtrSet<GlobalValue *, 4> Used;
22981ad6265SDimitry Andric
2300b57cec5SDimitry Andric #ifndef NDEBUG
2310b57cec5SDimitry Andric /// Checks the rules of order relation introduced among functions set.
23281ad6265SDimitry Andric /// Returns true, if check has been passed, and false if failed.
23381ad6265SDimitry Andric bool doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist);
2340b57cec5SDimitry Andric #endif
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric /// Insert a ComparableFunction into the FnTree, or merge it away if it's
2370b57cec5SDimitry Andric /// equal to one that's already present.
2380b57cec5SDimitry Andric bool insert(Function *NewFunction);
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric /// Remove a Function from the FnTree and queue it up for a second sweep of
2410b57cec5SDimitry Andric /// analysis.
2420b57cec5SDimitry Andric void remove(Function *F);
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric /// Find the functions that use this Value and remove them from FnTree and
2450b57cec5SDimitry Andric /// queue the functions.
2460b57cec5SDimitry Andric void removeUsers(Value *V);
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric /// Replace all direct calls of Old with calls of New. Will bitcast New if
2490b57cec5SDimitry Andric /// necessary to make types match.
2500b57cec5SDimitry Andric void replaceDirectCallers(Function *Old, Function *New);
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric /// Merge two equivalent functions. Upon completion, G may be deleted, or may
2530b57cec5SDimitry Andric /// be converted into a thunk. In either case, it should never be visited
2540b57cec5SDimitry Andric /// again.
2550b57cec5SDimitry Andric void mergeTwoFunctions(Function *F, Function *G);
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric /// Fill PDIUnrelatedWL with instructions from the entry block that are
2580b57cec5SDimitry Andric /// unrelated to parameter related debug info.
259*0fca6ea1SDimitry Andric /// \param PDVRUnrelatedWL The equivalent non-intrinsic debug records.
260*0fca6ea1SDimitry Andric void
261*0fca6ea1SDimitry Andric filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock,
262*0fca6ea1SDimitry Andric std::vector<Instruction *> &PDIUnrelatedWL,
263*0fca6ea1SDimitry Andric std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric /// Erase the rest of the CFG (i.e. barring the entry block).
2660b57cec5SDimitry Andric void eraseTail(Function *G);
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric /// Erase the instructions in PDIUnrelatedWL as they are unrelated to the
2690b57cec5SDimitry Andric /// parameter debug info, from the entry block.
270*0fca6ea1SDimitry Andric /// \param PDVRUnrelatedWL contains the equivalent set of non-instruction
271*0fca6ea1SDimitry Andric /// debug-info records.
272*0fca6ea1SDimitry Andric void
273*0fca6ea1SDimitry Andric eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL,
274*0fca6ea1SDimitry Andric std::vector<DbgVariableRecord *> &PDVRUnrelatedWL);
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andric /// Replace G with a simple tail call to bitcast(F). Also (unless
2770b57cec5SDimitry Andric /// MergeFunctionsPDI holds) replace direct uses of G with bitcast(F),
2780b57cec5SDimitry Andric /// delete G.
2790b57cec5SDimitry Andric void writeThunk(Function *F, Function *G);
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric // Replace G with an alias to F (deleting function G)
2820b57cec5SDimitry Andric void writeAlias(Function *F, Function *G);
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andric // Replace G with an alias to F if possible, or a thunk to F if possible.
2850b57cec5SDimitry Andric // Returns false if neither is the case.
2860b57cec5SDimitry Andric bool writeThunkOrAlias(Function *F, Function *G);
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric /// Replace function F with function G in the function tree.
2890b57cec5SDimitry Andric void replaceFunctionInTree(const FunctionNode &FN, Function *G);
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric /// The set of all distinct functions. Use the insert() and remove() methods
2920b57cec5SDimitry Andric /// to modify it. The map allows efficient lookup and deferring of Functions.
2930b57cec5SDimitry Andric FnTreeType FnTree;
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andric // Map functions to the iterators of the FunctionNode which contains them
2960b57cec5SDimitry Andric // in the FnTree. This must be updated carefully whenever the FnTree is
2970b57cec5SDimitry Andric // modified, i.e. in insert(), remove(), and replaceFunctionInTree(), to avoid
2980b57cec5SDimitry Andric // dangling iterators into FnTree. The invariant that preserves this is that
2990b57cec5SDimitry Andric // there is exactly one mapping F -> FN for each FunctionNode FN in FnTree.
3000b57cec5SDimitry Andric DenseMap<AssertingVH<Function>, FnTreeType::iterator> FNodesInTree;
3010b57cec5SDimitry Andric };
3020b57cec5SDimitry Andric } // end anonymous namespace
3030b57cec5SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)304480093f4SDimitry Andric PreservedAnalyses MergeFunctionsPass::run(Module &M,
305480093f4SDimitry Andric ModuleAnalysisManager &AM) {
306480093f4SDimitry Andric MergeFunctions MF;
307480093f4SDimitry Andric if (!MF.runOnModule(M))
308480093f4SDimitry Andric return PreservedAnalyses::all();
309480093f4SDimitry Andric return PreservedAnalyses::none();
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric
3120b57cec5SDimitry Andric #ifndef NDEBUG
doFunctionalCheck(std::vector<WeakTrackingVH> & Worklist)31381ad6265SDimitry Andric bool MergeFunctions::doFunctionalCheck(std::vector<WeakTrackingVH> &Worklist) {
31481ad6265SDimitry Andric if (const unsigned Max = NumFunctionsForVerificationCheck) {
3150b57cec5SDimitry Andric unsigned TripleNumber = 0;
3160b57cec5SDimitry Andric bool Valid = true;
3170b57cec5SDimitry Andric
31881ad6265SDimitry Andric dbgs() << "MERGEFUNC-VERIFY: Started for first " << Max << " functions.\n";
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric unsigned i = 0;
3210b57cec5SDimitry Andric for (std::vector<WeakTrackingVH>::iterator I = Worklist.begin(),
3220b57cec5SDimitry Andric E = Worklist.end();
3230b57cec5SDimitry Andric I != E && i < Max; ++I, ++i) {
3240b57cec5SDimitry Andric unsigned j = i;
3250b57cec5SDimitry Andric for (std::vector<WeakTrackingVH>::iterator J = I; J != E && j < Max;
3260b57cec5SDimitry Andric ++J, ++j) {
3270b57cec5SDimitry Andric Function *F1 = cast<Function>(*I);
3280b57cec5SDimitry Andric Function *F2 = cast<Function>(*J);
3290b57cec5SDimitry Andric int Res1 = FunctionComparator(F1, F2, &GlobalNumbers).compare();
3300b57cec5SDimitry Andric int Res2 = FunctionComparator(F2, F1, &GlobalNumbers).compare();
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric // If F1 <= F2, then F2 >= F1, otherwise report failure.
3330b57cec5SDimitry Andric if (Res1 != -Res2) {
33481ad6265SDimitry Andric dbgs() << "MERGEFUNC-VERIFY: Non-symmetric; triple: " << TripleNumber
3350b57cec5SDimitry Andric << "\n";
3360b57cec5SDimitry Andric dbgs() << *F1 << '\n' << *F2 << '\n';
3370b57cec5SDimitry Andric Valid = false;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric if (Res1 == 0)
3410b57cec5SDimitry Andric continue;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric unsigned k = j;
3440b57cec5SDimitry Andric for (std::vector<WeakTrackingVH>::iterator K = J; K != E && k < Max;
3450b57cec5SDimitry Andric ++k, ++K, ++TripleNumber) {
3460b57cec5SDimitry Andric if (K == J)
3470b57cec5SDimitry Andric continue;
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric Function *F3 = cast<Function>(*K);
3500b57cec5SDimitry Andric int Res3 = FunctionComparator(F1, F3, &GlobalNumbers).compare();
3510b57cec5SDimitry Andric int Res4 = FunctionComparator(F2, F3, &GlobalNumbers).compare();
3520b57cec5SDimitry Andric
3530b57cec5SDimitry Andric bool Transitive = true;
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric if (Res1 != 0 && Res1 == Res4) {
3560b57cec5SDimitry Andric // F1 > F2, F2 > F3 => F1 > F3
3570b57cec5SDimitry Andric Transitive = Res3 == Res1;
3580b57cec5SDimitry Andric } else if (Res3 != 0 && Res3 == -Res4) {
3590b57cec5SDimitry Andric // F1 > F3, F3 > F2 => F1 > F2
3600b57cec5SDimitry Andric Transitive = Res3 == Res1;
3610b57cec5SDimitry Andric } else if (Res4 != 0 && -Res3 == Res4) {
3620b57cec5SDimitry Andric // F2 > F3, F3 > F1 => F2 > F1
3630b57cec5SDimitry Andric Transitive = Res4 == -Res1;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric if (!Transitive) {
36781ad6265SDimitry Andric dbgs() << "MERGEFUNC-VERIFY: Non-transitive; triple: "
3680b57cec5SDimitry Andric << TripleNumber << "\n";
3690b57cec5SDimitry Andric dbgs() << "Res1, Res3, Res4: " << Res1 << ", " << Res3 << ", "
3700b57cec5SDimitry Andric << Res4 << "\n";
3710b57cec5SDimitry Andric dbgs() << *F1 << '\n' << *F2 << '\n' << *F3 << '\n';
3720b57cec5SDimitry Andric Valid = false;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
37881ad6265SDimitry Andric dbgs() << "MERGEFUNC-VERIFY: " << (Valid ? "Passed." : "Failed.") << "\n";
3790b57cec5SDimitry Andric return Valid;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric return true;
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric #endif
3840b57cec5SDimitry Andric
3855f757f3fSDimitry Andric /// Check whether \p F has an intrinsic which references
3865f757f3fSDimitry Andric /// distinct metadata as an operand. The most common
3875f757f3fSDimitry Andric /// instance of this would be CFI checks for function-local types.
hasDistinctMetadataIntrinsic(const Function & F)3885f757f3fSDimitry Andric static bool hasDistinctMetadataIntrinsic(const Function &F) {
3895f757f3fSDimitry Andric for (const BasicBlock &BB : F) {
3905f757f3fSDimitry Andric for (const Instruction &I : BB.instructionsWithoutDebug()) {
3915f757f3fSDimitry Andric if (!isa<IntrinsicInst>(&I))
3925f757f3fSDimitry Andric continue;
3935f757f3fSDimitry Andric
3945f757f3fSDimitry Andric for (Value *Op : I.operands()) {
3955f757f3fSDimitry Andric auto *MDL = dyn_cast<MetadataAsValue>(Op);
3965f757f3fSDimitry Andric if (!MDL)
3975f757f3fSDimitry Andric continue;
3985f757f3fSDimitry Andric if (MDNode *N = dyn_cast<MDNode>(MDL->getMetadata()))
3995f757f3fSDimitry Andric if (N->isDistinct())
4005f757f3fSDimitry Andric return true;
4015f757f3fSDimitry Andric }
4025f757f3fSDimitry Andric }
4035f757f3fSDimitry Andric }
4045f757f3fSDimitry Andric return false;
4055f757f3fSDimitry Andric }
4065f757f3fSDimitry Andric
4070b57cec5SDimitry Andric /// Check whether \p F is eligible for function merging.
isEligibleForMerging(Function & F)4080b57cec5SDimitry Andric static bool isEligibleForMerging(Function &F) {
4095f757f3fSDimitry Andric return !F.isDeclaration() && !F.hasAvailableExternallyLinkage() &&
4105f757f3fSDimitry Andric !hasDistinctMetadataIntrinsic(F);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric
runOnModule(Module & M)4130b57cec5SDimitry Andric bool MergeFunctions::runOnModule(Module &M) {
4140b57cec5SDimitry Andric bool Changed = false;
4150b57cec5SDimitry Andric
41681ad6265SDimitry Andric SmallVector<GlobalValue *, 4> UsedV;
41781ad6265SDimitry Andric collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false);
41881ad6265SDimitry Andric collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/true);
41981ad6265SDimitry Andric Used.insert(UsedV.begin(), UsedV.end());
42081ad6265SDimitry Andric
4210b57cec5SDimitry Andric // All functions in the module, ordered by hash. Functions with a unique
4220b57cec5SDimitry Andric // hash value are easily eliminated.
4235f757f3fSDimitry Andric std::vector<std::pair<IRHash, Function *>> HashedFuncs;
4240b57cec5SDimitry Andric for (Function &Func : M) {
4250b57cec5SDimitry Andric if (isEligibleForMerging(Func)) {
4265f757f3fSDimitry Andric HashedFuncs.push_back({StructuralHash(Func), &Func});
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric llvm::stable_sort(HashedFuncs, less_first());
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric auto S = HashedFuncs.begin();
4330b57cec5SDimitry Andric for (auto I = HashedFuncs.begin(), IE = HashedFuncs.end(); I != IE; ++I) {
4340b57cec5SDimitry Andric // If the hash value matches the previous value or the next one, we must
4350b57cec5SDimitry Andric // consider merging it. Otherwise it is dropped and never considered again.
4360b57cec5SDimitry Andric if ((I != S && std::prev(I)->first == I->first) ||
4370b57cec5SDimitry Andric (std::next(I) != IE && std::next(I)->first == I->first) ) {
4380b57cec5SDimitry Andric Deferred.push_back(WeakTrackingVH(I->second));
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric do {
4430b57cec5SDimitry Andric std::vector<WeakTrackingVH> Worklist;
4440b57cec5SDimitry Andric Deferred.swap(Worklist);
4450b57cec5SDimitry Andric
44681ad6265SDimitry Andric LLVM_DEBUG(doFunctionalCheck(Worklist));
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "size of module: " << M.size() << '\n');
4490b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "size of worklist: " << Worklist.size() << '\n');
4500b57cec5SDimitry Andric
4510b57cec5SDimitry Andric // Insert functions and merge them.
4520b57cec5SDimitry Andric for (WeakTrackingVH &I : Worklist) {
4530b57cec5SDimitry Andric if (!I)
4540b57cec5SDimitry Andric continue;
4550b57cec5SDimitry Andric Function *F = cast<Function>(I);
4560b57cec5SDimitry Andric if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) {
4570b57cec5SDimitry Andric Changed |= insert(F);
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "size of FnTree: " << FnTree.size() << '\n');
4610b57cec5SDimitry Andric } while (!Deferred.empty());
4620b57cec5SDimitry Andric
4630b57cec5SDimitry Andric FnTree.clear();
4640b57cec5SDimitry Andric FNodesInTree.clear();
4650b57cec5SDimitry Andric GlobalNumbers.clear();
46681ad6265SDimitry Andric Used.clear();
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric return Changed;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // Replace direct callers of Old with New.
replaceDirectCallers(Function * Old,Function * New)4720b57cec5SDimitry Andric void MergeFunctions::replaceDirectCallers(Function *Old, Function *New) {
473349cc55cSDimitry Andric for (Use &U : llvm::make_early_inc_range(Old->uses())) {
474349cc55cSDimitry Andric CallBase *CB = dyn_cast<CallBase>(U.getUser());
475349cc55cSDimitry Andric if (CB && CB->isCallee(&U)) {
476480093f4SDimitry Andric // Do not copy attributes from the called function to the call-site.
477480093f4SDimitry Andric // Function comparison ensures that the attributes are the same up to
478480093f4SDimitry Andric // type congruences in byval(), in which case we need to keep the byval
479480093f4SDimitry Andric // type of the call-site, not the callee function.
4805ffd83dbSDimitry Andric remove(CB->getFunction());
4815f757f3fSDimitry Andric U.set(New);
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric
4860b57cec5SDimitry Andric // Helper for writeThunk,
4870b57cec5SDimitry Andric // Selects proper bitcast operation,
4880b57cec5SDimitry Andric // but a bit simpler then CastInst::getCastOpcode.
createCast(IRBuilder<> & Builder,Value * V,Type * DestTy)4890b57cec5SDimitry Andric static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) {
4900b57cec5SDimitry Andric Type *SrcTy = V->getType();
4910b57cec5SDimitry Andric if (SrcTy->isStructTy()) {
4920b57cec5SDimitry Andric assert(DestTy->isStructTy());
4930b57cec5SDimitry Andric assert(SrcTy->getStructNumElements() == DestTy->getStructNumElements());
49481ad6265SDimitry Andric Value *Result = PoisonValue::get(DestTy);
4950b57cec5SDimitry Andric for (unsigned int I = 0, E = SrcTy->getStructNumElements(); I < E; ++I) {
496bdd1243dSDimitry Andric Value *Element =
497bdd1243dSDimitry Andric createCast(Builder, Builder.CreateExtractValue(V, ArrayRef(I)),
4980b57cec5SDimitry Andric DestTy->getStructElementType(I));
4990b57cec5SDimitry Andric
500bdd1243dSDimitry Andric Result = Builder.CreateInsertValue(Result, Element, ArrayRef(I));
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric return Result;
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric assert(!DestTy->isStructTy());
5050b57cec5SDimitry Andric if (SrcTy->isIntegerTy() && DestTy->isPointerTy())
5060b57cec5SDimitry Andric return Builder.CreateIntToPtr(V, DestTy);
5070b57cec5SDimitry Andric else if (SrcTy->isPointerTy() && DestTy->isIntegerTy())
5080b57cec5SDimitry Andric return Builder.CreatePtrToInt(V, DestTy);
5090b57cec5SDimitry Andric else
5100b57cec5SDimitry Andric return Builder.CreateBitCast(V, DestTy);
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric // Erase the instructions in PDIUnrelatedWL as they are unrelated to the
5140b57cec5SDimitry Andric // parameter debug info, from the entry block.
eraseInstsUnrelatedToPDI(std::vector<Instruction * > & PDIUnrelatedWL,std::vector<DbgVariableRecord * > & PDVRUnrelatedWL)5150b57cec5SDimitry Andric void MergeFunctions::eraseInstsUnrelatedToPDI(
516*0fca6ea1SDimitry Andric std::vector<Instruction *> &PDIUnrelatedWL,
517*0fca6ea1SDimitry Andric std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) {
5180b57cec5SDimitry Andric LLVM_DEBUG(
5190b57cec5SDimitry Andric dbgs() << " Erasing instructions (in reverse order of appearance in "
5200b57cec5SDimitry Andric "entry block) unrelated to parameter debug info from entry "
5210b57cec5SDimitry Andric "block: {\n");
5220b57cec5SDimitry Andric while (!PDIUnrelatedWL.empty()) {
5230b57cec5SDimitry Andric Instruction *I = PDIUnrelatedWL.back();
5240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Deleting Instruction: ");
5250b57cec5SDimitry Andric LLVM_DEBUG(I->print(dbgs()));
5260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
5270b57cec5SDimitry Andric I->eraseFromParent();
5280b57cec5SDimitry Andric PDIUnrelatedWL.pop_back();
5290b57cec5SDimitry Andric }
530*0fca6ea1SDimitry Andric
531*0fca6ea1SDimitry Andric while (!PDVRUnrelatedWL.empty()) {
532*0fca6ea1SDimitry Andric DbgVariableRecord *DVR = PDVRUnrelatedWL.back();
533*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << " Deleting DbgVariableRecord ");
534*0fca6ea1SDimitry Andric LLVM_DEBUG(DVR->print(dbgs()));
535*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
536*0fca6ea1SDimitry Andric DVR->eraseFromParent();
537*0fca6ea1SDimitry Andric PDVRUnrelatedWL.pop_back();
538*0fca6ea1SDimitry Andric }
539*0fca6ea1SDimitry Andric
5400b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter "
5410b57cec5SDimitry Andric "debug info from entry block. \n");
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric
5440b57cec5SDimitry Andric // Reduce G to its entry block.
eraseTail(Function * G)5450b57cec5SDimitry Andric void MergeFunctions::eraseTail(Function *G) {
5460b57cec5SDimitry Andric std::vector<BasicBlock *> WorklistBB;
547fe6060f1SDimitry Andric for (BasicBlock &BB : drop_begin(*G)) {
548fe6060f1SDimitry Andric BB.dropAllReferences();
549fe6060f1SDimitry Andric WorklistBB.push_back(&BB);
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric while (!WorklistBB.empty()) {
5520b57cec5SDimitry Andric BasicBlock *BB = WorklistBB.back();
5530b57cec5SDimitry Andric BB->eraseFromParent();
5540b57cec5SDimitry Andric WorklistBB.pop_back();
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric // We are interested in the following instructions from the entry block as being
5590b57cec5SDimitry Andric // related to parameter debug info:
5600b57cec5SDimitry Andric // - @llvm.dbg.declare
5610b57cec5SDimitry Andric // - stores from the incoming parameters to locations on the stack-frame
5620b57cec5SDimitry Andric // - allocas that create these locations on the stack-frame
5630b57cec5SDimitry Andric // - @llvm.dbg.value
5640b57cec5SDimitry Andric // - the entry block's terminator
5650b57cec5SDimitry Andric // The rest are unrelated to debug info for the parameters; fill up
5660b57cec5SDimitry Andric // PDIUnrelatedWL with such instructions.
filterInstsUnrelatedToPDI(BasicBlock * GEntryBlock,std::vector<Instruction * > & PDIUnrelatedWL,std::vector<DbgVariableRecord * > & PDVRUnrelatedWL)5670b57cec5SDimitry Andric void MergeFunctions::filterInstsUnrelatedToPDI(
568*0fca6ea1SDimitry Andric BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL,
569*0fca6ea1SDimitry Andric std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) {
5700b57cec5SDimitry Andric std::set<Instruction *> PDIRelated;
571*0fca6ea1SDimitry Andric std::set<DbgVariableRecord *> PDVRRelated;
572*0fca6ea1SDimitry Andric
573*0fca6ea1SDimitry Andric // Work out whether a dbg.value intrinsic or an equivalent DbgVariableRecord
574*0fca6ea1SDimitry Andric // is a parameter to be preserved.
575*0fca6ea1SDimitry Andric auto ExamineDbgValue = [](auto *DbgVal, auto &Container) {
5760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Deciding: ");
577*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgVal->print(dbgs()));
5780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
579*0fca6ea1SDimitry Andric DILocalVariable *DILocVar = DbgVal->getVariable();
5800b57cec5SDimitry Andric if (DILocVar->isParameter()) {
5810b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Include (parameter): ");
582*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgVal->print(dbgs()));
5830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
584*0fca6ea1SDimitry Andric Container.insert(DbgVal);
5850b57cec5SDimitry Andric } else {
5860b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
587*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgVal->print(dbgs()));
5880b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
5890b57cec5SDimitry Andric }
590*0fca6ea1SDimitry Andric };
591*0fca6ea1SDimitry Andric
592*0fca6ea1SDimitry Andric auto ExamineDbgDeclare = [&PDIRelated](auto *DbgDecl, auto &Container) {
5930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Deciding: ");
594*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgDecl->print(dbgs()));
5950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
596*0fca6ea1SDimitry Andric DILocalVariable *DILocVar = DbgDecl->getVariable();
5970b57cec5SDimitry Andric if (DILocVar->isParameter()) {
5980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Parameter: ");
5990b57cec5SDimitry Andric LLVM_DEBUG(DILocVar->print(dbgs()));
600*0fca6ea1SDimitry Andric AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DbgDecl->getAddress());
6010b57cec5SDimitry Andric if (AI) {
6020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Processing alloca users: ");
6030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6040b57cec5SDimitry Andric for (User *U : AI->users()) {
6050b57cec5SDimitry Andric if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
6060b57cec5SDimitry Andric if (Value *Arg = SI->getValueOperand()) {
607fe6060f1SDimitry Andric if (isa<Argument>(Arg)) {
6080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Include: ");
6090b57cec5SDimitry Andric LLVM_DEBUG(AI->print(dbgs()));
6100b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6110b57cec5SDimitry Andric PDIRelated.insert(AI);
6120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Include (parameter): ");
6130b57cec5SDimitry Andric LLVM_DEBUG(SI->print(dbgs()));
6140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6150b57cec5SDimitry Andric PDIRelated.insert(SI);
6160b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Include: ");
617*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgDecl->print(dbgs()));
6180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
619*0fca6ea1SDimitry Andric Container.insert(DbgDecl);
6200b57cec5SDimitry Andric } else {
6210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
6220b57cec5SDimitry Andric LLVM_DEBUG(SI->print(dbgs()));
6230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric } else {
6270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Defer: ");
6280b57cec5SDimitry Andric LLVM_DEBUG(U->print(dbgs()));
6290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric } else {
6330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Delete (alloca NULL): ");
634*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgDecl->print(dbgs()));
6350b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric } else {
6380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Delete (!parameter): ");
639*0fca6ea1SDimitry Andric LLVM_DEBUG(DbgDecl->print(dbgs()));
6400b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6410b57cec5SDimitry Andric }
642*0fca6ea1SDimitry Andric };
643*0fca6ea1SDimitry Andric
644*0fca6ea1SDimitry Andric for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end();
645*0fca6ea1SDimitry Andric BI != BIE; ++BI) {
646*0fca6ea1SDimitry Andric // Examine DbgVariableRecords as they happen "before" the instruction. Are
647*0fca6ea1SDimitry Andric // they connected to parameters?
648*0fca6ea1SDimitry Andric for (DbgVariableRecord &DVR : filterDbgVars(BI->getDbgRecordRange())) {
649*0fca6ea1SDimitry Andric if (DVR.isDbgValue() || DVR.isDbgAssign()) {
650*0fca6ea1SDimitry Andric ExamineDbgValue(&DVR, PDVRRelated);
651*0fca6ea1SDimitry Andric } else {
652*0fca6ea1SDimitry Andric assert(DVR.isDbgDeclare());
653*0fca6ea1SDimitry Andric ExamineDbgDeclare(&DVR, PDVRRelated);
654*0fca6ea1SDimitry Andric }
655*0fca6ea1SDimitry Andric }
656*0fca6ea1SDimitry Andric
657*0fca6ea1SDimitry Andric if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) {
658*0fca6ea1SDimitry Andric ExamineDbgValue(DVI, PDIRelated);
659*0fca6ea1SDimitry Andric } else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) {
660*0fca6ea1SDimitry Andric ExamineDbgDeclare(DDI, PDIRelated);
6610b57cec5SDimitry Andric } else if (BI->isTerminator() && &*BI == GEntryBlock->getTerminator()) {
6620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Will Include Terminator: ");
6630b57cec5SDimitry Andric LLVM_DEBUG(BI->print(dbgs()));
6640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6650b57cec5SDimitry Andric PDIRelated.insert(&*BI);
6660b57cec5SDimitry Andric } else {
6670b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Defer: ");
6680b57cec5SDimitry Andric LLVM_DEBUG(BI->print(dbgs()));
6690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric LLVM_DEBUG(
6730b57cec5SDimitry Andric dbgs()
6740b57cec5SDimitry Andric << " Report parameter debug info related/related instructions: {\n");
675*0fca6ea1SDimitry Andric
676*0fca6ea1SDimitry Andric auto IsPDIRelated = [](auto *Rec, auto &Container, auto &UnrelatedCont) {
677*0fca6ea1SDimitry Andric if (Container.find(Rec) == Container.end()) {
6780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " !PDIRelated: ");
679*0fca6ea1SDimitry Andric LLVM_DEBUG(Rec->print(dbgs()));
6800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
681*0fca6ea1SDimitry Andric UnrelatedCont.push_back(Rec);
6820b57cec5SDimitry Andric } else {
6830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " PDIRelated: ");
684*0fca6ea1SDimitry Andric LLVM_DEBUG(Rec->print(dbgs()));
6850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n");
6860b57cec5SDimitry Andric }
687*0fca6ea1SDimitry Andric };
688*0fca6ea1SDimitry Andric
689*0fca6ea1SDimitry Andric // Collect the set of unrelated instructions and debug records.
690*0fca6ea1SDimitry Andric for (Instruction &I : *GEntryBlock) {
691*0fca6ea1SDimitry Andric for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
692*0fca6ea1SDimitry Andric IsPDIRelated(&DVR, PDVRRelated, PDVRUnrelatedWL);
693*0fca6ea1SDimitry Andric IsPDIRelated(&I, PDIRelated, PDIUnrelatedWL);
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " }\n");
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric
6980b57cec5SDimitry Andric /// Whether this function may be replaced by a forwarding thunk.
canCreateThunkFor(Function * F)6990b57cec5SDimitry Andric static bool canCreateThunkFor(Function *F) {
7000b57cec5SDimitry Andric if (F->isVarArg())
7010b57cec5SDimitry Andric return false;
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric // Don't merge tiny functions using a thunk, since it can just end up
7040b57cec5SDimitry Andric // making the function larger.
7050b57cec5SDimitry Andric if (F->size() == 1) {
7065f757f3fSDimitry Andric if (F->front().sizeWithoutDebug() < 2) {
7070b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "canCreateThunkFor: " << F->getName()
7080b57cec5SDimitry Andric << " is too small to bother creating a thunk for\n");
7090b57cec5SDimitry Andric return false;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric return true;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric
715*0fca6ea1SDimitry Andric /// Copy all metadata of a specific kind from one function to another.
copyMetadataIfPresent(Function * From,Function * To,StringRef Kind)716*0fca6ea1SDimitry Andric static void copyMetadataIfPresent(Function *From, Function *To,
717*0fca6ea1SDimitry Andric StringRef Kind) {
718*0fca6ea1SDimitry Andric SmallVector<MDNode *, 4> MDs;
719*0fca6ea1SDimitry Andric From->getMetadata(Kind, MDs);
720*0fca6ea1SDimitry Andric for (MDNode *MD : MDs)
721*0fca6ea1SDimitry Andric To->addMetadata(Kind, *MD);
7225f757f3fSDimitry Andric }
7235f757f3fSDimitry Andric
7240b57cec5SDimitry Andric // Replace G with a simple tail call to bitcast(F). Also (unless
7250b57cec5SDimitry Andric // MergeFunctionsPDI holds) replace direct uses of G with bitcast(F),
7260b57cec5SDimitry Andric // delete G. Under MergeFunctionsPDI, we use G itself for creating
7270b57cec5SDimitry Andric // the thunk as we preserve the debug info (and associated instructions)
7280b57cec5SDimitry Andric // from G's entry block pertaining to G's incoming arguments which are
7290b57cec5SDimitry Andric // passed on as corresponding arguments in the call that G makes to F.
7300b57cec5SDimitry Andric // For better debugability, under MergeFunctionsPDI, we do not modify G's
7310b57cec5SDimitry Andric // call sites to point to F even when within the same translation unit.
writeThunk(Function * F,Function * G)7320b57cec5SDimitry Andric void MergeFunctions::writeThunk(Function *F, Function *G) {
7330b57cec5SDimitry Andric BasicBlock *GEntryBlock = nullptr;
7340b57cec5SDimitry Andric std::vector<Instruction *> PDIUnrelatedWL;
735*0fca6ea1SDimitry Andric std::vector<DbgVariableRecord *> PDVRUnrelatedWL;
7360b57cec5SDimitry Andric BasicBlock *BB = nullptr;
7370b57cec5SDimitry Andric Function *NewG = nullptr;
7380b57cec5SDimitry Andric if (MergeFunctionsPDI) {
7390b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "writeThunk: (MergeFunctionsPDI) Do not create a new "
7400b57cec5SDimitry Andric "function as thunk; retain original: "
7410b57cec5SDimitry Andric << G->getName() << "()\n");
7420b57cec5SDimitry Andric GEntryBlock = &G->getEntryBlock();
7430b57cec5SDimitry Andric LLVM_DEBUG(
7440b57cec5SDimitry Andric dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related "
7450b57cec5SDimitry Andric "debug info for "
7460b57cec5SDimitry Andric << G->getName() << "() {\n");
747*0fca6ea1SDimitry Andric filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDVRUnrelatedWL);
7480b57cec5SDimitry Andric GEntryBlock->getTerminator()->eraseFromParent();
7490b57cec5SDimitry Andric BB = GEntryBlock;
7500b57cec5SDimitry Andric } else {
7510b57cec5SDimitry Andric NewG = Function::Create(G->getFunctionType(), G->getLinkage(),
7520b57cec5SDimitry Andric G->getAddressSpace(), "", G->getParent());
7530b57cec5SDimitry Andric NewG->setComdat(G->getComdat());
754*0fca6ea1SDimitry Andric NewG->IsNewDbgInfoFormat = G->IsNewDbgInfoFormat;
7550b57cec5SDimitry Andric BB = BasicBlock::Create(F->getContext(), "", NewG);
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric IRBuilder<> Builder(BB);
7590b57cec5SDimitry Andric Function *H = MergeFunctionsPDI ? G : NewG;
7600b57cec5SDimitry Andric SmallVector<Value *, 16> Args;
7610b57cec5SDimitry Andric unsigned i = 0;
7620b57cec5SDimitry Andric FunctionType *FFTy = F->getFunctionType();
7630b57cec5SDimitry Andric for (Argument &AI : H->args()) {
7640b57cec5SDimitry Andric Args.push_back(createCast(Builder, &AI, FFTy->getParamType(i)));
7650b57cec5SDimitry Andric ++i;
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric CallInst *CI = Builder.CreateCall(F, Args);
7690b57cec5SDimitry Andric ReturnInst *RI = nullptr;
770fe6060f1SDimitry Andric bool isSwiftTailCall = F->getCallingConv() == CallingConv::SwiftTail &&
771fe6060f1SDimitry Andric G->getCallingConv() == CallingConv::SwiftTail;
772fe6060f1SDimitry Andric CI->setTailCallKind(isSwiftTailCall ? llvm::CallInst::TCK_MustTail
773fe6060f1SDimitry Andric : llvm::CallInst::TCK_Tail);
7740b57cec5SDimitry Andric CI->setCallingConv(F->getCallingConv());
7750b57cec5SDimitry Andric CI->setAttributes(F->getAttributes());
7760b57cec5SDimitry Andric if (H->getReturnType()->isVoidTy()) {
7770b57cec5SDimitry Andric RI = Builder.CreateRetVoid();
7780b57cec5SDimitry Andric } else {
7790b57cec5SDimitry Andric RI = Builder.CreateRet(createCast(Builder, CI, H->getReturnType()));
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric
7820b57cec5SDimitry Andric if (MergeFunctionsPDI) {
7830b57cec5SDimitry Andric DISubprogram *DIS = G->getSubprogram();
7840b57cec5SDimitry Andric if (DIS) {
785e8d8bef9SDimitry Andric DebugLoc CIDbgLoc =
786e8d8bef9SDimitry Andric DILocation::get(DIS->getContext(), DIS->getScopeLine(), 0, DIS);
787e8d8bef9SDimitry Andric DebugLoc RIDbgLoc =
788e8d8bef9SDimitry Andric DILocation::get(DIS->getContext(), DIS->getScopeLine(), 0, DIS);
7890b57cec5SDimitry Andric CI->setDebugLoc(CIDbgLoc);
7900b57cec5SDimitry Andric RI->setDebugLoc(RIDbgLoc);
7910b57cec5SDimitry Andric } else {
7920b57cec5SDimitry Andric LLVM_DEBUG(
7930b57cec5SDimitry Andric dbgs() << "writeThunk: (MergeFunctionsPDI) No DISubprogram for "
7940b57cec5SDimitry Andric << G->getName() << "()\n");
7950b57cec5SDimitry Andric }
7960b57cec5SDimitry Andric eraseTail(G);
797*0fca6ea1SDimitry Andric eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDVRUnrelatedWL);
7980b57cec5SDimitry Andric LLVM_DEBUG(
7990b57cec5SDimitry Andric dbgs() << "} // End of parameter related debug info filtering for: "
8000b57cec5SDimitry Andric << G->getName() << "()\n");
8010b57cec5SDimitry Andric } else {
8020b57cec5SDimitry Andric NewG->copyAttributesFrom(G);
8030b57cec5SDimitry Andric NewG->takeName(G);
8045f757f3fSDimitry Andric // Ensure CFI type metadata is propagated to the new function.
8055f757f3fSDimitry Andric copyMetadataIfPresent(G, NewG, "type");
8065f757f3fSDimitry Andric copyMetadataIfPresent(G, NewG, "kcfi_type");
8070b57cec5SDimitry Andric removeUsers(G);
8080b57cec5SDimitry Andric G->replaceAllUsesWith(NewG);
8090b57cec5SDimitry Andric G->eraseFromParent();
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "writeThunk: " << H->getName() << '\n');
8130b57cec5SDimitry Andric ++NumThunksWritten;
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric
8160b57cec5SDimitry Andric // Whether this function may be replaced by an alias
canCreateAliasFor(Function * F)8170b57cec5SDimitry Andric static bool canCreateAliasFor(Function *F) {
8180b57cec5SDimitry Andric if (!MergeFunctionsAliases || !F->hasGlobalUnnamedAddr())
8190b57cec5SDimitry Andric return false;
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric // We should only see linkages supported by aliases here
8220b57cec5SDimitry Andric assert(F->hasLocalLinkage() || F->hasExternalLinkage()
8230b57cec5SDimitry Andric || F->hasWeakLinkage() || F->hasLinkOnceLinkage());
8240b57cec5SDimitry Andric return true;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric
8270b57cec5SDimitry Andric // Replace G with an alias to F (deleting function G)
writeAlias(Function * F,Function * G)8280b57cec5SDimitry Andric void MergeFunctions::writeAlias(Function *F, Function *G) {
8290b57cec5SDimitry Andric PointerType *PtrType = G->getType();
830fe6060f1SDimitry Andric auto *GA = GlobalAlias::create(G->getValueType(), PtrType->getAddressSpace(),
8315f757f3fSDimitry Andric G->getLinkage(), "", F, G->getParent());
8320b57cec5SDimitry Andric
833bdd1243dSDimitry Andric const MaybeAlign FAlign = F->getAlign();
834bdd1243dSDimitry Andric const MaybeAlign GAlign = G->getAlign();
835bdd1243dSDimitry Andric if (FAlign || GAlign)
836bdd1243dSDimitry Andric F->setAlignment(std::max(FAlign.valueOrOne(), GAlign.valueOrOne()));
837bdd1243dSDimitry Andric else
838bdd1243dSDimitry Andric F->setAlignment(std::nullopt);
8390b57cec5SDimitry Andric GA->takeName(G);
8400b57cec5SDimitry Andric GA->setVisibility(G->getVisibility());
8410b57cec5SDimitry Andric GA->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric removeUsers(G);
8440b57cec5SDimitry Andric G->replaceAllUsesWith(GA);
8450b57cec5SDimitry Andric G->eraseFromParent();
8460b57cec5SDimitry Andric
8470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "writeAlias: " << GA->getName() << '\n');
8480b57cec5SDimitry Andric ++NumAliasesWritten;
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andric // Replace G with an alias to F if possible, or a thunk to F if
8520b57cec5SDimitry Andric // profitable. Returns false if neither is the case.
writeThunkOrAlias(Function * F,Function * G)8530b57cec5SDimitry Andric bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
8540b57cec5SDimitry Andric if (canCreateAliasFor(G)) {
8550b57cec5SDimitry Andric writeAlias(F, G);
8560b57cec5SDimitry Andric return true;
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric if (canCreateThunkFor(F)) {
8590b57cec5SDimitry Andric writeThunk(F, G);
8600b57cec5SDimitry Andric return true;
8610b57cec5SDimitry Andric }
8620b57cec5SDimitry Andric return false;
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric
8650b57cec5SDimitry Andric // Merge two equivalent functions. Upon completion, Function G is deleted.
mergeTwoFunctions(Function * F,Function * G)8660b57cec5SDimitry Andric void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
8670b57cec5SDimitry Andric if (F->isInterposable()) {
8680b57cec5SDimitry Andric assert(G->isInterposable());
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric // Both writeThunkOrAlias() calls below must succeed, either because we can
8710b57cec5SDimitry Andric // create aliases for G and NewF, or because a thunk for F is profitable.
8720b57cec5SDimitry Andric // F here has the same signature as NewF below, so that's what we check.
8730b57cec5SDimitry Andric if (!canCreateThunkFor(F) &&
8740b57cec5SDimitry Andric (!canCreateAliasFor(F) || !canCreateAliasFor(G)))
8750b57cec5SDimitry Andric return;
8760b57cec5SDimitry Andric
8770b57cec5SDimitry Andric // Make them both thunks to the same internal function.
8780b57cec5SDimitry Andric Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
8790b57cec5SDimitry Andric F->getAddressSpace(), "", F->getParent());
8800b57cec5SDimitry Andric NewF->copyAttributesFrom(F);
8810b57cec5SDimitry Andric NewF->takeName(F);
882*0fca6ea1SDimitry Andric NewF->IsNewDbgInfoFormat = F->IsNewDbgInfoFormat;
8835f757f3fSDimitry Andric // Ensure CFI type metadata is propagated to the new function.
8845f757f3fSDimitry Andric copyMetadataIfPresent(F, NewF, "type");
8855f757f3fSDimitry Andric copyMetadataIfPresent(F, NewF, "kcfi_type");
8860b57cec5SDimitry Andric removeUsers(F);
8870b57cec5SDimitry Andric F->replaceAllUsesWith(NewF);
8880b57cec5SDimitry Andric
889bdd1243dSDimitry Andric // We collect alignment before writeThunkOrAlias that overwrites NewF and
890bdd1243dSDimitry Andric // G's content.
891bdd1243dSDimitry Andric const MaybeAlign NewFAlign = NewF->getAlign();
892bdd1243dSDimitry Andric const MaybeAlign GAlign = G->getAlign();
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric writeThunkOrAlias(F, G);
8950b57cec5SDimitry Andric writeThunkOrAlias(F, NewF);
8960b57cec5SDimitry Andric
897bdd1243dSDimitry Andric if (NewFAlign || GAlign)
898bdd1243dSDimitry Andric F->setAlignment(std::max(NewFAlign.valueOrOne(), GAlign.valueOrOne()));
899bdd1243dSDimitry Andric else
900bdd1243dSDimitry Andric F->setAlignment(std::nullopt);
9010b57cec5SDimitry Andric F->setLinkage(GlobalValue::PrivateLinkage);
9020b57cec5SDimitry Andric ++NumDoubleWeak;
9030b57cec5SDimitry Andric ++NumFunctionsMerged;
9040b57cec5SDimitry Andric } else {
9050b57cec5SDimitry Andric // For better debugability, under MergeFunctionsPDI, we do not modify G's
9060b57cec5SDimitry Andric // call sites to point to F even when within the same translation unit.
9070b57cec5SDimitry Andric if (!G->isInterposable() && !MergeFunctionsPDI) {
90881ad6265SDimitry Andric // Functions referred to by llvm.used/llvm.compiler.used are special:
90981ad6265SDimitry Andric // there are uses of the symbol name that are not visible to LLVM,
91081ad6265SDimitry Andric // usually from inline asm.
91181ad6265SDimitry Andric if (G->hasGlobalUnnamedAddr() && !Used.contains(G)) {
9120b57cec5SDimitry Andric // G might have been a key in our GlobalNumberState, and it's illegal
9130b57cec5SDimitry Andric // to replace a key in ValueMap<GlobalValue *> with a non-global.
9140b57cec5SDimitry Andric GlobalNumbers.erase(G);
9150b57cec5SDimitry Andric // If G's address is not significant, replace it entirely.
9160b57cec5SDimitry Andric removeUsers(G);
9175f757f3fSDimitry Andric G->replaceAllUsesWith(F);
9180b57cec5SDimitry Andric } else {
9190b57cec5SDimitry Andric // Redirect direct callers of G to F. (See note on MergeFunctionsPDI
9200b57cec5SDimitry Andric // above).
9210b57cec5SDimitry Andric replaceDirectCallers(G, F);
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric
9250b57cec5SDimitry Andric // If G was internal then we may have replaced all uses of G with F. If so,
9260b57cec5SDimitry Andric // stop here and delete G. There's no need for a thunk. (See note on
9270b57cec5SDimitry Andric // MergeFunctionsPDI above).
9280b57cec5SDimitry Andric if (G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI) {
9290b57cec5SDimitry Andric G->eraseFromParent();
9300b57cec5SDimitry Andric ++NumFunctionsMerged;
9310b57cec5SDimitry Andric return;
9320b57cec5SDimitry Andric }
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric if (writeThunkOrAlias(F, G)) {
9350b57cec5SDimitry Andric ++NumFunctionsMerged;
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric
9400b57cec5SDimitry Andric /// Replace function F by function G.
replaceFunctionInTree(const FunctionNode & FN,Function * G)9410b57cec5SDimitry Andric void MergeFunctions::replaceFunctionInTree(const FunctionNode &FN,
9420b57cec5SDimitry Andric Function *G) {
9430b57cec5SDimitry Andric Function *F = FN.getFunc();
9440b57cec5SDimitry Andric assert(FunctionComparator(F, G, &GlobalNumbers).compare() == 0 &&
9450b57cec5SDimitry Andric "The two functions must be equal");
9460b57cec5SDimitry Andric
9470b57cec5SDimitry Andric auto I = FNodesInTree.find(F);
9480b57cec5SDimitry Andric assert(I != FNodesInTree.end() && "F should be in FNodesInTree");
9490b57cec5SDimitry Andric assert(FNodesInTree.count(G) == 0 && "FNodesInTree should not contain G");
9500b57cec5SDimitry Andric
9510b57cec5SDimitry Andric FnTreeType::iterator IterToFNInFnTree = I->second;
9520b57cec5SDimitry Andric assert(&(*IterToFNInFnTree) == &FN && "F should map to FN in FNodesInTree.");
9530b57cec5SDimitry Andric // Remove F -> FN and insert G -> FN
9540b57cec5SDimitry Andric FNodesInTree.erase(I);
9550b57cec5SDimitry Andric FNodesInTree.insert({G, IterToFNInFnTree});
9560b57cec5SDimitry Andric // Replace F with G in FN, which is stored inside the FnTree.
9570b57cec5SDimitry Andric FN.replaceBy(G);
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric
9600b57cec5SDimitry Andric // Ordering for functions that are equal under FunctionComparator
isFuncOrderCorrect(const Function * F,const Function * G)9610b57cec5SDimitry Andric static bool isFuncOrderCorrect(const Function *F, const Function *G) {
9620b57cec5SDimitry Andric if (F->isInterposable() != G->isInterposable()) {
9630b57cec5SDimitry Andric // Strong before weak, because the weak function may call the strong
9640b57cec5SDimitry Andric // one, but not the other way around.
9650b57cec5SDimitry Andric return !F->isInterposable();
9660b57cec5SDimitry Andric }
9670b57cec5SDimitry Andric if (F->hasLocalLinkage() != G->hasLocalLinkage()) {
9680b57cec5SDimitry Andric // External before local, because we definitely have to keep the external
9690b57cec5SDimitry Andric // function, but may be able to drop the local one.
9700b57cec5SDimitry Andric return !F->hasLocalLinkage();
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric // Impose a total order (by name) on the replacement of functions. This is
9730b57cec5SDimitry Andric // important when operating on more than one module independently to prevent
9740b57cec5SDimitry Andric // cycles of thunks calling each other when the modules are linked together.
9750b57cec5SDimitry Andric return F->getName() <= G->getName();
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric // Insert a ComparableFunction into the FnTree, or merge it away if equal to one
9790b57cec5SDimitry Andric // that was already inserted.
insert(Function * NewFunction)9800b57cec5SDimitry Andric bool MergeFunctions::insert(Function *NewFunction) {
9810b57cec5SDimitry Andric std::pair<FnTreeType::iterator, bool> Result =
9820b57cec5SDimitry Andric FnTree.insert(FunctionNode(NewFunction));
9830b57cec5SDimitry Andric
9840b57cec5SDimitry Andric if (Result.second) {
9850b57cec5SDimitry Andric assert(FNodesInTree.count(NewFunction) == 0);
9860b57cec5SDimitry Andric FNodesInTree.insert({NewFunction, Result.first});
9870b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inserting as unique: " << NewFunction->getName()
9880b57cec5SDimitry Andric << '\n');
9890b57cec5SDimitry Andric return false;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric
9920b57cec5SDimitry Andric const FunctionNode &OldF = *Result.first;
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric if (!isFuncOrderCorrect(OldF.getFunc(), NewFunction)) {
9950b57cec5SDimitry Andric // Swap the two functions.
9960b57cec5SDimitry Andric Function *F = OldF.getFunc();
9970b57cec5SDimitry Andric replaceFunctionInTree(*Result.first, NewFunction);
9980b57cec5SDimitry Andric NewFunction = F;
9990b57cec5SDimitry Andric assert(OldF.getFunc() != F && "Must have swapped the functions.");
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric
10020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << OldF.getFunc()->getName()
10030b57cec5SDimitry Andric << " == " << NewFunction->getName() << '\n');
10040b57cec5SDimitry Andric
10050b57cec5SDimitry Andric Function *DeleteF = NewFunction;
10060b57cec5SDimitry Andric mergeTwoFunctions(OldF.getFunc(), DeleteF);
10070b57cec5SDimitry Andric return true;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric
10100b57cec5SDimitry Andric // Remove a function from FnTree. If it was already in FnTree, add
10110b57cec5SDimitry Andric // it to Deferred so that we'll look at it in the next round.
remove(Function * F)10120b57cec5SDimitry Andric void MergeFunctions::remove(Function *F) {
10130b57cec5SDimitry Andric auto I = FNodesInTree.find(F);
10140b57cec5SDimitry Andric if (I != FNodesInTree.end()) {
10150b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Deferred " << F->getName() << ".\n");
10160b57cec5SDimitry Andric FnTree.erase(I->second);
10170b57cec5SDimitry Andric // I->second has been invalidated, remove it from the FNodesInTree map to
10180b57cec5SDimitry Andric // preserve the invariant.
10190b57cec5SDimitry Andric FNodesInTree.erase(I);
10200b57cec5SDimitry Andric Deferred.emplace_back(F);
10210b57cec5SDimitry Andric }
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric // For each instruction used by the value, remove() the function that contains
10250b57cec5SDimitry Andric // the instruction. This should happen right before a call to RAUW.
removeUsers(Value * V)10260b57cec5SDimitry Andric void MergeFunctions::removeUsers(Value *V) {
10270b57cec5SDimitry Andric for (User *U : V->users())
10280b57cec5SDimitry Andric if (auto *I = dyn_cast<Instruction>(U))
10290b57cec5SDimitry Andric remove(I->getFunction());
10300b57cec5SDimitry Andric }
1031