12
12
#include " llvm/ADT/SetVector.h"
13
13
#include " llvm/ADT/SmallPtrSet.h"
14
14
#include " llvm/ADT/SmallString.h"
15
+ #include " llvm/Analysis/TargetLibraryInfo.h"
15
16
#include " llvm/IR/AutoUpgrade.h"
16
17
#include " llvm/IR/Constants.h"
17
18
#include " llvm/IR/DebugInfoMetadata.h"
@@ -399,6 +400,9 @@ class IRLinker {
399
400
// / A metadata map that's shared between IRLinker instances.
400
401
MDMapT &SharedMDs;
401
402
403
+ // / A list of libcalls that the current target may call.
404
+ IRMover::LibcallHandler &Libcalls;
405
+
402
406
// / Mapping of values from what they used to be in Src, to what they are now
403
407
// / in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead
404
408
// / due to the use of Value handles which the Linker doesn't actually need,
@@ -540,10 +544,12 @@ class IRLinker {
540
544
IRLinker (Module &DstM, MDMapT &SharedMDs,
541
545
IRMover::IdentifiedStructTypeSet &Set, std::unique_ptr<Module> SrcM,
542
546
ArrayRef<GlobalValue *> ValuesToLink,
543
- IRMover::LazyCallback AddLazyFor, bool IsPerformingImport)
547
+ IRMover::LibcallHandler &Libcalls, IRMover::LazyCallback AddLazyFor,
548
+ bool IsPerformingImport)
544
549
: DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)),
545
550
TypeMap (Set), GValMaterializer(*this ), LValMaterializer(*this ),
546
- SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport),
551
+ SharedMDs(SharedMDs), Libcalls(Libcalls),
552
+ IsPerformingImport(IsPerformingImport),
547
553
Mapper(ValueMap, RF_ReuseAndMutateDistinctMDs | RF_IgnoreMissingLocals,
548
554
&TypeMap, &GValMaterializer),
549
555
IndirectSymbolMCID(Mapper.registerAlternateMappingContext(
@@ -561,6 +567,13 @@ class IRLinker {
561
567
};
562
568
}
563
569
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
+
564
577
// / The LLVM SymbolTable class autorenames globals that conflict in the symbol
565
578
// / table. This is good for all clients except for us. Go through the trouble
566
579
// / to force this back.
@@ -1605,14 +1618,26 @@ Error IRLinker::run() {
1605
1618
1606
1619
DstM.setTargetTriple (SrcTriple.merge (DstTriple));
1607
1620
1621
+ // Update the target triple's libcall information if it was changed.
1622
+ Libcalls.updateLibcalls (Triple (DstM.getTargetTriple ()));
1623
+
1608
1624
// Loop over all of the linked values to compute type mappings.
1609
1625
computeTypeMapping ();
1610
1626
1627
+ bool AddsLibcalls = false ;
1611
1628
std::reverse (Worklist.begin (), Worklist.end ());
1612
1629
while (!Worklist.empty ()) {
1613
1630
GlobalValue *GV = Worklist.back ();
1614
1631
Worklist.pop_back ();
1615
1632
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
+
1616
1641
// Already mapped.
1617
1642
if (ValueMap.find (GV) != ValueMap.end () ||
1618
1643
IndirectSymbolValueMap.find (GV) != IndirectSymbolValueMap.end ())
@@ -1675,6 +1700,13 @@ Error IRLinker::run() {
1675
1700
}
1676
1701
}
1677
1702
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
+
1678
1710
// Merge the module flags into the DstM module.
1679
1711
return linkModuleFlagsMetadata ();
1680
1712
}
@@ -1757,6 +1789,22 @@ bool IRMover::IdentifiedStructTypeSet::hasType(StructType *Ty) {
1757
1789
return I == NonOpaqueStructTypes.end () ? false : *I == Ty;
1758
1790
}
1759
1791
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
+
1760
1808
IRMover::IRMover (Module &M) : Composite(M) {
1761
1809
TypeFinder StructTypes;
1762
1810
StructTypes.run (M, /* OnlyNamed */ false );
@@ -1772,14 +1820,25 @@ IRMover::IRMover(Module &M) : Composite(M) {
1772
1820
for (const auto *MD : StructTypes.getVisitedMetadata ()) {
1773
1821
SharedMDs[MD].reset (const_cast <MDNode *>(MD));
1774
1822
}
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);
1775
1834
}
1776
1835
1777
1836
Error IRMover::move (std::unique_ptr<Module> Src,
1778
1837
ArrayRef<GlobalValue *> ValuesToLink,
1779
1838
LazyCallback AddLazyFor, bool IsPerformingImport) {
1780
1839
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);
1783
1842
Error E = TheIRLinker.run ();
1784
1843
Composite.dropTriviallyDeadConstantArrays ();
1785
1844
return E;
0 commit comments