1212#include " llvm/ADT/SetVector.h"
1313#include " llvm/ADT/SmallPtrSet.h"
1414#include " llvm/ADT/SmallString.h"
15+ #include " llvm/Analysis/TargetLibraryInfo.h"
1516#include " llvm/IR/AutoUpgrade.h"
1617#include " llvm/IR/Constants.h"
1718#include " llvm/IR/DebugInfoMetadata.h"
@@ -399,6 +400,9 @@ class IRLinker {
399400 // / A metadata map that's shared between IRLinker instances.
400401 MDMapT &SharedMDs;
401402
403+ // / A list of libcalls that the current target may call.
404+ IRMover::LibcallHandler &Libcalls;
405+
402406 // / Mapping of values from what they used to be in Src, to what they are now
403407 // / in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead
404408 // / due to the use of Value handles which the Linker doesn't actually need,
@@ -540,10 +544,12 @@ class IRLinker {
540544 IRLinker (Module &DstM, MDMapT &SharedMDs,
541545 IRMover::IdentifiedStructTypeSet &Set, std::unique_ptr<Module> SrcM,
542546 ArrayRef<GlobalValue *> ValuesToLink,
543- IRMover::LazyCallback AddLazyFor, bool IsPerformingImport)
547+ IRMover::LibcallHandler &Libcalls, IRMover::LazyCallback AddLazyFor,
548+ bool IsPerformingImport)
544549 : DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)),
545550 TypeMap (Set), GValMaterializer(*this ), LValMaterializer(*this ),
546- SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport),
551+ SharedMDs(SharedMDs), Libcalls(Libcalls),
552+ IsPerformingImport(IsPerformingImport),
547553 Mapper(ValueMap, RF_ReuseAndMutateDistinctMDs | RF_IgnoreMissingLocals,
548554 &TypeMap, &GValMaterializer),
549555 IndirectSymbolMCID(Mapper.registerAlternateMappingContext(
@@ -561,6 +567,13 @@ class IRLinker {
561567};
562568}
563569
570+ static void addNoBuiltinAttributes (Function &F) {
571+ F.setAttributes (
572+ F.getAttributes ().addFnAttribute (F.getContext (), " no-builtins" ));
573+ F.setAttributes (
574+ F.getAttributes ().addFnAttribute (F.getContext (), Attribute::NoBuiltin));
575+ }
576+
564577// / The LLVM SymbolTable class autorenames globals that conflict in the symbol
565578// / table. This is good for all clients except for us. Go through the trouble
566579// / to force this back.
@@ -1605,14 +1618,26 @@ Error IRLinker::run() {
16051618
16061619 DstM.setTargetTriple (SrcTriple.merge (DstTriple));
16071620
1621+ // Update the target triple's libcall information if it was changed.
1622+ Libcalls.updateLibcalls (Triple (DstM.getTargetTriple ()));
1623+
16081624 // Loop over all of the linked values to compute type mappings.
16091625 computeTypeMapping ();
16101626
1627+ bool AddsLibcalls = false ;
16111628 std::reverse (Worklist.begin (), Worklist.end ());
16121629 while (!Worklist.empty ()) {
16131630 GlobalValue *GV = Worklist.back ();
16141631 Worklist.pop_back ();
16151632
1633+ // If the module already contains libcall functions we need every function
1634+ // linked in to have `nobuiltin` attributes. Otherwise check if this is a
1635+ // libcall definition.
1636+ if (Function *F = dyn_cast<Function>(GV); F && Libcalls.hasLibcalls ())
1637+ addNoBuiltinAttributes (*F);
1638+ else
1639+ AddsLibcalls = Libcalls.checkLibcalls (*GV);
1640+
16161641 // Already mapped.
16171642 if (ValueMap.find (GV) != ValueMap.end () ||
16181643 IndirectSymbolValueMap.find (GV) != IndirectSymbolValueMap.end ())
@@ -1675,6 +1700,13 @@ Error IRLinker::run() {
16751700 }
16761701 }
16771702
1703+ // If we have imported a recognized libcall function we can no longer make any
1704+ // reasonable optimizations based off of its semantics. Add the 'nobuiltin'
1705+ // attribute to every function to suppress libcall detection.
1706+ if (AddsLibcalls)
1707+ for (Function &F : DstM.functions ())
1708+ addNoBuiltinAttributes (F);
1709+
16781710 // Merge the module flags into the DstM module.
16791711 return linkModuleFlagsMetadata ();
16801712}
@@ -1757,6 +1789,22 @@ bool IRMover::IdentifiedStructTypeSet::hasType(StructType *Ty) {
17571789 return I == NonOpaqueStructTypes.end () ? false : *I == Ty;
17581790}
17591791
1792+ void IRMover::LibcallHandler::updateLibcalls (const Triple &TheTriple) {
1793+ if (Triples.count (TheTriple.getTriple ()))
1794+ return ;
1795+ Triples.insert (Saver.save (TheTriple.getTriple ()));
1796+
1797+ // Collect the names of runtime functions that the target may want to call.
1798+ TargetLibraryInfoImpl TLII (TheTriple);
1799+ TargetLibraryInfo TLI (TLII);
1800+ for (unsigned I = 0 , E = static_cast <unsigned >(LibFunc::NumLibFuncs); I != E;
1801+ ++I) {
1802+ LibFunc F = static_cast <LibFunc>(I);
1803+ if (TLI.has (F))
1804+ Libcalls.insert (TLI.getName (F));
1805+ }
1806+ }
1807+
17601808IRMover::IRMover (Module &M) : Composite(M) {
17611809 TypeFinder StructTypes;
17621810 StructTypes.run (M, /* OnlyNamed */ false );
@@ -1772,14 +1820,25 @@ IRMover::IRMover(Module &M) : Composite(M) {
17721820 for (const auto *MD : StructTypes.getVisitedMetadata ()) {
17731821 SharedMDs[MD].reset (const_cast <MDNode *>(MD));
17741822 }
1823+
1824+ // Check the composite module for any already present libcalls. If we define
1825+ // these then it is important to mark any imported functions as 'nobuiltin'.
1826+ Libcalls.updateLibcalls (Triple (Composite.getTargetTriple ()));
1827+ for (Function &F : Composite.functions ())
1828+ if (Libcalls.checkLibcalls (F))
1829+ break ;
1830+
1831+ if (Libcalls.hasLibcalls ())
1832+ for (Function &F : Composite.functions ())
1833+ addNoBuiltinAttributes (F);
17751834}
17761835
17771836Error IRMover::move (std::unique_ptr<Module> Src,
17781837 ArrayRef<GlobalValue *> ValuesToLink,
17791838 LazyCallback AddLazyFor, bool IsPerformingImport) {
17801839 IRLinker TheIRLinker (Composite, SharedMDs, IdentifiedStructTypes,
1781- std::move (Src), ValuesToLink, std::move (AddLazyFor) ,
1782- IsPerformingImport);
1840+ std::move (Src), ValuesToLink, Libcalls ,
1841+ std::move (AddLazyFor), IsPerformingImport);
17831842 Error E = TheIRLinker.run ();
17841843 Composite.dropTriviallyDeadConstantArrays ();
17851844 return E;
0 commit comments