llvm.org GIT mirror llvm / 73cf01b
libLTO: add a ThinLTOCodeGenerator on the model of LTOCodeGenerator. This is intended to provide a parallel (threaded) ThinLTO scheme for linker plugin use through the libLTO C API. The intent of this patch is to provide a first implementation as a proof-of-concept and allows linker to start supporting ThinLTO by definiing the libLTO C API. Some part of the libLTO API are left unimplemented yet. Following patches will add support for these. The current implementation can link all clang/llvm binaries. Differential Revision: http://reviews.llvm.org/D17066 From: Mehdi Amini <mehdi.amini@apple.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262977 91177308-0d34-0410-b5e6-96231b3b80d8 Mehdi Amini 3 years ago
13 changed file(s) with 1444 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
385385 return std::find(Range.begin(), Range.end(), val);
386386 }
387387
388 /// Provide wrappers to std::find_if which take ranges instead of having to pass
389 /// begin/end explicitly.
390 template
391 auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
392 return std::find_if(Range.begin(), Range.end(), Pred);
393 }
394
388395 //===----------------------------------------------------------------------===//
389396 // Extra additions to
390397 //===----------------------------------------------------------------------===//
6464 static bool isBitcodeFile(const void *mem, size_t length);
6565 static bool isBitcodeFile(const char *path);
6666
67 /// Returns 'true' if the Module is produced for ThinLTO.
68 bool isThinLTO();
69
6770 /// Returns 'true' if the memory buffer is LLVM bitcode for the specified
6871 /// triple.
6972 static bool isBitcodeForTarget(MemoryBuffer *memBuffer,
0 //===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the ThinLTOCodeGenerator class, similar to the
10 // LTOCodeGenerator but for the ThinLTO scheme. It provides an interface for
11 // linker plugin.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_LTO_THINLTOCODEGENERATOR_H
16 #define LLVM_LTO_THINLTOCODEGENERATOR_H
17
18 #include "llvm-c/lto.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/StringSet.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/Support/CodeGen.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Target/TargetOptions.h"
25
26 #include
27
28 namespace llvm {
29 class FunctionInfoIndex;
30 class LLVMContext;
31 class TargetMachine;
32
33 /// Helper to gather options relevant to the target machine creation
34 struct TargetMachineBuilder {
35 Triple TheTriple;
36 std::string MCpu;
37 std::string MAttr;
38 TargetOptions Options;
39 Reloc::Model RelocModel = Reloc::Default;
40 CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
41
42 std::unique_ptr create() const;
43 };
44
45 /// This class define an interface similar to the LTOCodeGenerator, but adapted
46 /// for ThinLTO processing.
47 /// The ThinLTOCodeGenerator is not intended to be reuse for multiple
48 /// compilation: the model is that the client adds modules to the generator and
49 /// ask to perform the ThinLTO optimizations / codegen, and finally destroys the
50 /// codegenerator.
51 class ThinLTOCodeGenerator {
52 public:
53 /// Add given module to the code generator.
54 void addModule(StringRef Identifier, StringRef Data);
55
56 /**
57 * Adds to a list of all global symbols that must exist in the final generated
58 * code. If a symbol is not listed there, it will be optimized away if it is
59 * inlined into every usage.
60 */
61 void preserveSymbol(StringRef Name);
62
63 /**
64 * Adds to a list of all global symbols that are cross-referenced between
65 * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
66 * references from a ThinLTO module to this symbol is optimized away, then
67 * the symbol can be discarded.
68 */
69 void crossReferenceSymbol(StringRef Name);
70
71 /**
72 * Process all the modules that were added to the code generator in parallel.
73 *
74 * Client can access the resulting object files using getProducedBinaries()
75 */
76 void run();
77
78 /**
79 * Return the "in memory" binaries produced by the code generator.
80 */
81 std::vector> &getProducedBinaries() {
82 return ProducedBinaries;
83 }
84
85 /**
86 * \defgroup Options setters
87 * @{
88 */
89
90 /**
91 * \defgroup Cache controlling options
92 *
93 * These entry points control the ThinLTO cache. The cache is intended to
94 * support incremental build, and thus needs to be persistent accross build.
95 * The client enabled the cache by supplying a path to an existing directory.
96 * The code generator will use this to store objects files that may be reused
97 * during a subsequent build.
98 * To avoid filling the disk space, a few knobs are provided:
99 * - The pruning interval limit the frequency at which the garbage collector
100 * will try to scan the cache directory to prune it from expired entries.
101 * Setting to -1 disable the pruning (default).
102 * - The pruning expiration time indicates to the garbage collector how old
103 * an entry needs to be to be removed.
104 * - Finally, the garbage collector can be instructed to prune the cache till
105 * the occupied space goes below a threshold.
106 * @{
107 */
108
109 struct CachingOptions {
110 std::string Path;
111 int PruningInterval = -1; // seconds, -1 to disable pruning
112 unsigned int Expiration; // seconds.
113 unsigned MaxPercentageOfAvailableSpace; // percentage.
114 };
115
116 /// Provide a path to a directory where to store the cached files for
117 /// incremental build.
118 void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); }
119
120 /// Cache policy: interval (seconds) between two prune of the cache. Set to a
121 /// negative value (default) to disable pruning.
122 void setCachePruningInterval(int Interval) {
123 CacheOptions.PruningInterval = Interval;
124 }
125
126 /// Cache policy: expiration (in seconds) for an entry.
127 void setCacheEntryExpiration(unsigned Expiration) {
128 CacheOptions.Expiration = Expiration;
129 }
130
131 /**
132 * Sets the maximum cache size that can be persistent across build, in terms
133 * of percentage of the available space on the the disk. Set to 100 to
134 * indicate no limit, 50 to indicate that the cache size will not be left over
135 * half the available space. A value over 100 will be reduced to 100.
136 *
137 * The formula looks like:
138 * AvailableSpace = FreeSpace + ExistingCacheSize
139 * NewCacheSize = AvailableSpace * P/100
140 *
141 */
142 void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
143 CacheOptions.MaxPercentageOfAvailableSpace = Percentage;
144 }
145
146 /**@}*/
147
148 /// Set the path to a directory where to save temporaries at various stages of
149 /// the processing.
150 void setSaveTempsDir(std::string Path) { SaveTempsDir = std::move(Path); }
151
152 /// CPU to use to initialize the TargetMachine
153 void setCpu(std::string Cpu) { TMBuilder.MCpu = std::move(Cpu); }
154
155 /// Subtarget attributes
156 void setAttr(std::string MAttr) { TMBuilder.MAttr = std::move(MAttr); }
157
158 /// TargetMachine options
159 void setTargetOptions(TargetOptions Options) {
160 TMBuilder.Options = std::move(Options);
161 }
162
163 /// CodeModel
164 void setCodePICModel(Reloc::Model Model) { TMBuilder.RelocModel = Model; }
165
166 /// CodeGen optimization level
167 void setCodeGenOptLevel(CodeGenOpt::Level CGOptLevel) {
168 TMBuilder.CGOptLevel = CGOptLevel;
169 }
170
171 /**@}*/
172
173 /**
174 * \defgroup Set of APIs to run individual stages in isolation.
175 * @{
176 */
177
178 /**
179 * Produce the combined function index from all the bitcode files:
180 * "thin-link".
181 */
182 std::unique_ptr linkCombinedIndex();
183
184 /**
185 * Perform promotion and renaming of exported internal functions.
186 */
187 void promote(Module &Module, FunctionInfoIndex &Index);
188
189 /**
190 * Perform cross-module importing for the module identified by
191 * ModuleIdentifier.
192 */
193 void crossModuleImport(Module &Module, FunctionInfoIndex &Index);
194
195 /**
196 * Perform post-importing ThinLTO optimizations.
197 */
198 void optimize(Module &Module);
199
200 /**
201 * Perform ThinLTO CodeGen.
202 */
203 std::unique_ptr codegen(Module &Module);
204
205 /**@}*/
206
207 private:
208 /// Helper factory to build a TargetMachine
209 TargetMachineBuilder TMBuilder;
210
211 /// Vector holding the in-memory buffer containing the produced binaries.
212 std::vector> ProducedBinaries;
213
214 /// Vector holding the input buffers containing the bitcode modules to
215 /// process.
216 std::vector Modules;
217
218 /// Set of symbols that need to be preserved outside of the set of bitcode
219 /// files.
220 StringSet<> PreservedSymbols;
221
222 /// Set of symbols that are cross-referenced between bitcode files.
223 StringSet<> CrossReferencedSymbols;
224
225 /// Control the caching behavior.
226 CachingOptions CacheOptions;
227
228 /// Path to a directory to save the temporary bitcode files.
229 std::string SaveTempsDir;
230 };
231 }
232 #endif
3939 * @{
4040 */
4141
42 #define LTO_API_VERSION 17
43
42 #define LTO_API_VERSION 18
4443 /**
4544 * \since prior to LTO_API_VERSION=3
4645 */
9089 /** opaque reference to a code generator */
9190 typedef struct LLVMOpaqueLTOCodeGenerator *lto_code_gen_t;
9291
92 /** opaque reference to a thin code generator */
93 typedef struct LLVMOpaqueThinLTOCodeGenerator *thinlto_code_gen_t;
94
9395 #ifdef __cplusplus
9496 extern "C" {
9597 #endif
547549 lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
548550 lto_bool_t ShouldEmbedUselists);
549551
552 /**
553 * @}
554 * @defgroup LLVMCTLTO ThinLTO
555 * @ingroup LLVMC
556 *
557 * @{
558 */
559
560 /**
561 * Type to wrap a single object returned by ThinLTO.
562 *
563 * \since LTO_API_VERSION=18
564 */
565 typedef struct {
566 void *Buffer;
567 size_t Size;
568 } LTOObjectBuffer;
569
570 /**
571 * Instantiates a ThinLTO code generator.
572 * Returns NULL on error (check lto_get_error_message() for details).
573 *
574 *
575 * The ThinLTOCodeGenerator is not intended to be reuse for multiple
576 * compilation: the model is that the client adds modules to the generator and
577 * ask to perform the ThinLTO optimizations / codegen, and finally destroys the
578 * codegenerator.
579 *
580 * \since LTO_API_VERSION=18
581 */
582 extern thinlto_code_gen_t thinlto_create_codegen();
583
584 /**
585 * Frees the generator and all memory it internally allocated.
586 * Upon return the thinlto_code_gen_t is no longer valid.
587 *
588 * \since LTO_API_VERSION=18
589 */
590 extern void thinlto_codegen_dispose(thinlto_code_gen_t cg);
591
592 /**
593 * Add a module to a ThinLTO code generator. Identifier has to be unique among
594 * all the modules in a code generator. The data buffer stays owned by the
595 * client, and is expected to be available for the entire lifetime of the
596 * thinlto_code_gen_t it is added to.
597 *
598 * On failure, returns NULL (check lto_get_error_message() for details).
599 *
600 *
601 * \since LTO_API_VERSION=18
602 */
603 extern void thinlto_codegen_add_module(thinlto_code_gen_t cg,
604 const char *identifier, const char *data,
605 int length);
606
607 /**
608 * Optimize and codegen all the modules added to the codegenerator using
609 * ThinLTO. Resulting objects are accessible using thinlto_module_get_object().
610 *
611 * \since LTO_API_VERSION=18
612 */
613 extern void thinlto_codegen_process(thinlto_code_gen_t cg);
614
615 /**
616 * Returns the number of object files produced by the ThinLTO CodeGenerator.
617 *
618 * It usually matches the number of input files, but this is not a guarantee of
619 * the API and may change in future implementation, so the client should not
620 * assume it.
621 *
622 * \since LTO_API_VERSION=18
623 */
624 extern unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg);
625
626 /**
627 * Returns a reference to the ith object file produced by the ThinLTO
628 * CodeGenerator.
629 *
630 * Client should use \p thinlto_module_get_num_objects() to get the number of
631 * available objects.
632 *
633 * \since LTO_API_VERSION=18
634 */
635 extern LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
636 unsigned int index);
637
638 /**
639 * Sets which PIC code model to generate.
640 * Returns true on error (check lto_get_error_message() for details).
641 *
642 * \since LTO_API_VERSION=18
643 */
644 extern lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
645 lto_codegen_model);
646
647 /**
648 * @}
649 * @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
650 * @ingroup LLVMCTLTO
651 *
652 * These entry points control the ThinLTO cache. The cache is intended to
653 * support incremental build, and thus needs to be persistent accross build.
654 * The client enabled the cache by supplying a path to an existing directory.
655 * The code generator will use this to store objects files that may be reused
656 * during a subsequent build.
657 * To avoid filling the disk space, a few knobs are provided:
658 * - The pruning interval limit the frequency at which the garbage collector
659 * will try to scan the cache directory to prune it from expired entries.
660 * Setting to -1 disable the pruning (default).
661 * - The pruning expiration time indicates to the garbage collector how old an
662 * entry needs to be to be removed.
663 * - Finally, the garbage collector can be instructed to prune the cache till
664 * the occupied space goes below a threshold.
665 * @{
666 */
667
668 /**
669 * Sets the path to a directory to use as a cache storage for incremental build.
670 *
671 * \since LTO_API_VERSION=18
672 */
673 extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
674 const char *cache_dir);
675
676 /**
677 * Sets the cache pruning interval (in seconds). A negative value disable the
678 * pruning (default).
679 *
680 * \since LTO_API_VERSION=18
681 */
682 extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
683 int interval);
684
685 /**
686 * Sets the maximum cache size that can be persistent across build, in terms of
687 * percentage of the available space on the the disk. Set to 100 to indicate
688 * no limit, 50 to indicate that the cache size will not be left over half the
689 * available space. A value over 100 will be reduced to 100.
690 *
691 * The formula looks like:
692 * AvailableSpace = FreeSpace + ExistingCacheSize
693 * NewCacheSize = AvailableSpace * P/100
694 *
695 * \since LTO_API_VERSION=18
696 */
697 extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
698 thinlto_code_gen_t cg, unsigned percentage);
699
700 /**
701 * Sets the expiration (in seconds) for an entry in the cache.
702 *
703 * \since LTO_API_VERSION=18
704 */
705 extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
706 unsigned expiration);
707
708 /**
709 * @}
710 */
711
712 /**
713 * Sets the path to a directory to use as a storage for temporary bitcode files.
714 * The intention is to make the bitcode files available for debugging at various
715 * stage of the pipeline.
716 *
717 * \since LTO_API_VERSION=18
718 */
719 extern void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
720 const char *save_temps_dir);
721
722 /**
723 * Sets the cpu to generate code for.
724 *
725 * \since LTO_API_VERSION=18
726 */
727 extern void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu);
728
729 /**
730 * Parse -mllvm style debug options.
731 *
732 * \since LTO_API_VERSION=18
733 */
734 extern void thinlto_debug_options(const char *const *options, int number);
735
736 /**
737 * Test if a module has support for ThinLTO linking.
738 *
739 * \since LTO_API_VERSION=18
740 */
741 extern bool lto_module_is_thinlto(lto_module_t mod);
742
743 /**
744 * Adds a symbol to the list of global symbols that must exist in the final
745 * generated code. If a function is not listed there, it might be inlined into
746 * every usage and optimized away. For every single module, the functions
747 * referenced from code outside of the ThinLTO modules need to be added here.
748 *
749 * \since LTO_API_VERSION=18
750 */
751 extern void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
752 const char *name,
753 int length);
754
755 /**
756 * Adds a symbol to the list of global symbols that are cross-referenced between
757 * ThinLTO files. If the ThinLTO CodeGenerator can ensure that every
758 * references from a ThinLTO module to this symbol is optimized away, then
759 * the symbol can be discarded.
760 *
761 * \since LTO_API_VERSION=18
762 */
763 extern void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
764 const char *name,
765 int length);
766
550767 #ifdef __cplusplus
551768 }
552769 #endif
0 add_llvm_library(LLVMLTO
11 LTOModule.cpp
22 LTOCodeGenerator.cpp
3 ThinLTOCodeGenerator.cpp
34
45 ADDITIONAL_HEADER_DIRS
56 ${LLVM_MAIN_INCLUDE_DIR}/llvm/LTO
6 )
7 )
78
89 add_dependencies(LLVMLTO intrinsics_gen)
3333 Scalar
3434 Support
3535 Target
36 TransformUtils
7474 return bool(BCData);
7575 }
7676
77 bool LTOModule::isThinLTO() {
78 // Right now the detection is only based on the summary presence. We may want
79 // to add a dedicated flag at some point.
80 return hasFunctionSummary(IRFile->getMemoryBufferRef(),
81 [](const DiagnosticInfo &DI) {
82 DiagnosticPrinterRawOStream DP(errs());
83 DI.print(DP);
84 errs() << '\n';
85 return;
86 });
87 }
88
7789 bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
7890 StringRef TriplePrefix) {
7991 ErrorOr BCOrErr =
0 //===-ThinLTOCodeGenerator.cpp - LLVM Link Time Optimizer -----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Thin Link Time Optimization library. This library is
10 // intended to be used by linker to optimize code at link time.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/LTO/ThinLTOCodeGenerator.h"
15
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/Analysis/TargetLibraryInfo.h"
19 #include "llvm/Analysis/TargetTransformInfo.h"
20 #include "llvm/Bitcode/ReaderWriter.h"
21 #include "llvm/Bitcode/BitcodeWriterPass.h"
22 #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
23 #include "llvm/IR/LLVMContext.h"
24 #include "llvm/IR/DiagnosticPrinter.h"
25 #include "llvm/IR/LegacyPassManager.h"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/IRReader/IRReader.h"
28 #include "llvm/Linker/Linker.h"
29 #include "llvm/MC/SubtargetFeature.h"
30 #include "llvm/Object/FunctionIndexObjectFile.h"
31 #include "llvm/Support/SourceMgr.h"
32 #include "llvm/Support/TargetRegistry.h"
33 #include "llvm/Support/ThreadPool.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Transforms/IPO.h"
36 #include "llvm/Transforms/IPO/FunctionImport.h"
37 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
38 #include "llvm/Transforms/ObjCARC.h"
39 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
40
41 using namespace llvm;
42
43 namespace {
44
45 static cl::opt ThreadCount("threads",
46 cl::init(std::thread::hardware_concurrency()));
47
48 static void diagnosticHandler(const DiagnosticInfo &DI) {
49 DiagnosticPrinterRawOStream DP(errs());
50 DI.print(DP);
51 errs() << '\n';
52 }
53
54 // Simple helper to load a module from bitcode
55 static std::unique_ptr
56 loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
57 bool Lazy) {
58 SMDiagnostic Err;
59 ErrorOr> ModuleOrErr(nullptr);
60 if (Lazy) {
61 ModuleOrErr =
62 getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer, false), Context,
63 /* ShouldLazyLoadMetadata */ Lazy);
64 } else {
65 ModuleOrErr = parseBitcodeFile(Buffer, Context);
66 }
67 if (std::error_code EC = ModuleOrErr.getError()) {
68 Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
69 EC.message());
70 Err.print("ThinLTO", errs());
71 report_fatal_error("Can't load module, abort.");
72 }
73 return std::move(ModuleOrErr.get());
74 }
75
76 // Simple helper to save temporary files for debug.
77 static void saveTempBitcode(const Module &TheModule, StringRef TempDir,
78 unsigned count, StringRef Suffix) {
79 if (TempDir.empty())
80 return;
81 // User asked to save temps, let dump the bitcode file after import.
82 auto SaveTempPath = TempDir + llvm::utostr(count) + Suffix;
83 std::error_code EC;
84 raw_fd_ostream OS(SaveTempPath.str(), EC, sys::fs::F_None);
85 if (EC)
86 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
87 " to save optimized bitcode\n");
88 WriteBitcodeToFile(&TheModule, OS, true, false);
89 }
90
91 static StringMap
92 generateModuleMap(const std::vector &Modules) {
93 StringMap ModuleMap;
94 for (auto &ModuleBuffer : Modules) {
95 assert(ModuleMap.find(ModuleBuffer.getBufferIdentifier()) ==
96 ModuleMap.end() &&
97 "Expect unique Buffer Identifier");
98 ModuleMap[ModuleBuffer.getBufferIdentifier()] = ModuleBuffer;
99 }
100 return ModuleMap;
101 }
102
103 /// Provide a "loader" for the FunctionImporter to access function from other
104 /// modules.
105 class ModuleLoader {
106 /// The context that will be used for importing.
107 LLVMContext &Context;
108
109 /// Map from Module identifier to MemoryBuffer. Used by clients like the
110 /// FunctionImported to request loading a Module.
111 StringMap &ModuleMap;
112
113 public:
114 ModuleLoader(LLVMContext &Context, StringMap &ModuleMap)
115 : Context(Context), ModuleMap(ModuleMap) {}
116
117 /// Load a module on demand.
118 std::unique_ptr operator()(StringRef Identifier) {
119 return loadModuleFromBuffer(ModuleMap[Identifier], Context, /*Lazy*/ true);
120 }
121 };
122
123 static void promoteModule(Module &TheModule, const FunctionInfoIndex &Index) {
124 if (renameModuleForThinLTO(TheModule, Index))
125 report_fatal_error("renameModuleForThinLTO failed");
126 }
127
128 static void crossImportIntoModule(Module &TheModule,
129 const FunctionInfoIndex &Index,
130 StringMap &ModuleMap) {
131 ModuleLoader Loader(TheModule.getContext(), ModuleMap);
132 FunctionImporter Importer(Index, Loader);
133 Importer.importFunctions(TheModule);
134 }
135
136 static void optimizeModule(Module &TheModule, TargetMachine &TM) {
137 // Populate the PassManager
138 PassManagerBuilder PMB;
139 PMB.LibraryInfo = new TargetLibraryInfoImpl(TM.getTargetTriple());
140 PMB.Inliner = createFunctionInliningPass();
141 // FIXME: should get it from the bitcode?
142 PMB.OptLevel = 3;
143 PMB.LoopVectorize = true;
144 PMB.SLPVectorize = true;
145 PMB.VerifyInput = true;
146 PMB.VerifyOutput = false;
147
148 legacy::PassManager PM;
149
150 // Add the TTI (required to inform the vectorizer about register size for
151 // instance)
152 PM.add(createTargetTransformInfoWrapperPass(TM.getTargetIRAnalysis()));
153
154 // Add optimizations
155 PMB.populateThinLTOPassManager(PM);
156 PM.add(createObjCARCContractPass());
157
158 PM.run(TheModule);
159 }
160
161 std::unique_ptr codegenModule(Module &TheModule,
162 TargetMachine &TM) {
163 SmallVector OutputBuffer;
164
165 // CodeGen
166 {
167 raw_svector_ostream OS(OutputBuffer);
168 legacy::PassManager PM;
169 if (TM.addPassesToEmitFile(PM, OS, TargetMachine::CGFT_ObjectFile,
170 /* DisableVerify */ true))
171 report_fatal_error("Failed to setup codegen");
172
173 // Run codegen now. resulting binary is in OutputBuffer.
174 PM.run(TheModule);
175 }
176 return make_unique(std::move(OutputBuffer));
177 }
178
179 static std::unique_ptr
180 ProcessThinLTOModule(Module &TheModule, const FunctionInfoIndex &Index,
181 StringMap &ModuleMap, TargetMachine &TM,
182 ThinLTOCodeGenerator::CachingOptions CacheOptions,
183 StringRef SaveTempsDir, unsigned count) {
184
185 // Save temps: after IPO.
186 saveTempBitcode(TheModule, SaveTempsDir, count, ".1.IPO.bc");
187
188 // "Benchmark"-like optimization: single-source case
189 bool SingleModule = (ModuleMap.size() == 1);
190
191 if (!SingleModule) {
192 promoteModule(TheModule, Index);
193
194 // Save temps: after promotion.
195 saveTempBitcode(TheModule, SaveTempsDir, count, ".2.promoted.bc");
196
197 crossImportIntoModule(TheModule, Index, ModuleMap);
198
199 // Save temps: after cross-module import.
200 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc");
201 }
202
203 optimizeModule(TheModule, TM);
204
205 saveTempBitcode(TheModule, SaveTempsDir, count, ".3.opt.bc");
206
207 return codegenModule(TheModule, TM);
208 }
209
210 // Initialize the TargetMachine builder for a given Triple
211 static void initTMBuilder(TargetMachineBuilder &TMBuilder,
212 const Triple &TheTriple) {
213 // Set a default CPU for Darwin triples (copied from LTOCodeGenerator).
214 // FIXME this looks pretty terrible...
215 if (TMBuilder.MCpu.empty() && TheTriple.isOSDarwin()) {
216 if (TheTriple.getArch() == llvm::Triple::x86_64)
217 TMBuilder.MCpu = "core2";
218 else if (TheTriple.getArch() == llvm::Triple::x86)
219 TMBuilder.MCpu = "yonah";
220 else if (TheTriple.getArch() == llvm::Triple::aarch64)
221 TMBuilder.MCpu = "cyclone";
222 }
223 TMBuilder.TheTriple = std::move(TheTriple);
224 }
225
226 } // end anonymous namespace
227
228 void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) {
229 MemoryBufferRef Buffer(Data, Identifier);
230 if (Modules.empty()) {
231 // First module added, so initialize the triple and some options
232 LLVMContext Context;
233 Triple TheTriple(getBitcodeTargetTriple(Buffer, Context));
234 initTMBuilder(TMBuilder, Triple(TheTriple));
235 }
236 #ifndef NDEBUG
237 else {
238 LLVMContext Context;
239 assert(TMBuilder.TheTriple.str() ==
240 getBitcodeTargetTriple(Buffer, Context) &&
241 "ThinLTO modules with different triple not supported");
242 }
243 #endif
244 Modules.push_back(Buffer);
245 }
246
247 void ThinLTOCodeGenerator::preserveSymbol(StringRef Name) {
248 PreservedSymbols.insert(Name);
249 }
250
251 void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {
252 CrossReferencedSymbols.insert(Name);
253 }
254
255 // TargetMachine factory
256 std::unique_ptr TargetMachineBuilder::create() const {
257 std::string ErrMsg;
258 const Target *TheTarget =
259 TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);
260 if (!TheTarget) {
261 report_fatal_error("Can't load target for this Triple: " + ErrMsg);
262 }
263
264 // Use MAttr as the default set of features.
265 SubtargetFeatures Features(MAttr);
266 Features.getDefaultSubtargetFeatures(TheTriple);
267 std::string FeatureStr = Features.getString();
268 return std::unique_ptr(TheTarget->createTargetMachine(
269 TheTriple.str(), MCpu, FeatureStr, Options, RelocModel,
270 CodeModel::Default, CGOptLevel));
271 }
272
273 /**
274 * Produce the combined function index from all the bitcode files:
275 * "thin-link".
276 */
277 std::unique_ptr ThinLTOCodeGenerator::linkCombinedIndex() {
278 std::unique_ptr CombinedIndex;
279 uint64_t NextModuleId = 0;
280 for (auto &ModuleBuffer : Modules) {
281 ErrorOr> ObjOrErr =
282 object::FunctionIndexObjectFile::create(ModuleBuffer, diagnosticHandler,
283 false);
284 if (std::error_code EC = ObjOrErr.getError()) {
285 // FIXME diagnose
286 errs() << "error: can't create FunctionIndexObjectFile for buffer: "
287 << EC.message() << "\n";
288 return nullptr;
289 }
290 auto Index = (*ObjOrErr)->takeIndex();
291 if (CombinedIndex) {
292 CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId);
293 } else {
294 CombinedIndex = std::move(Index);
295 }
296 }
297 return CombinedIndex;
298 }
299
300 /**
301 * Perform promotion and renaming of exported internal functions.
302 */
303 void ThinLTOCodeGenerator::promote(Module &TheModule,
304 FunctionInfoIndex &Index) {
305 promoteModule(TheModule, Index);
306 }
307
308 /**
309 * Perform cross-module importing for the module identified by ModuleIdentifier.
310 */
311 void ThinLTOCodeGenerator::crossModuleImport(Module &TheModule,
312 FunctionInfoIndex &Index) {
313 auto ModuleMap = generateModuleMap(Modules);
314 crossImportIntoModule(TheModule, Index, ModuleMap);
315 }
316
317 /**
318 * Perform post-importing ThinLTO optimizations.
319 */
320 void ThinLTOCodeGenerator::optimize(Module &TheModule) {
321 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
322 optimizeModule(TheModule, *TMBuilder.create());
323 }
324
325 /**
326 * Perform ThinLTO CodeGen.
327 */
328 std::unique_ptr ThinLTOCodeGenerator::codegen(Module &TheModule) {
329 initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));
330 return codegenModule(TheModule, *TMBuilder.create());
331 }
332
333 // Main entry point for the ThinLTO processing
334 void ThinLTOCodeGenerator::run() {
335 // Sequential linking phase
336 auto Index = linkCombinedIndex();
337
338 // Save temps: index.
339 if (!SaveTempsDir.empty()) {
340 auto SaveTempPath = SaveTempsDir + "index.bc";
341 std::error_code EC;
342 raw_fd_ostream OS(SaveTempPath, EC, sys::fs::F_None);
343 if (EC)
344 report_fatal_error(Twine("Failed to open ") + SaveTempPath +
345 " to save optimized bitcode\n");
346 WriteFunctionSummaryToFile(*Index, OS);
347 }
348
349 // Prepare the resulting object vector
350 assert(ProducedBinaries.empty() && "The generator should not be reused");
351 ProducedBinaries.resize(Modules.size());
352
353 // Prepare the module map.
354 auto ModuleMap = generateModuleMap(Modules);
355
356 // Parallel optimizer + codegen
357 {
358 ThreadPool Pool(ThreadCount);
359 int count = 0;
360 for (auto &ModuleBuffer : Modules) {
361 Pool.async([&](int count) {
362 LLVMContext Context;
363
364 // Parse module now
365 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
366
367 // Save temps: original file.
368 if (!SaveTempsDir.empty()) {
369 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
370 }
371
372 ProducedBinaries[count] = ProcessThinLTOModule(
373 *TheModule, *Index, ModuleMap, *TMBuilder.create(), CacheOptions,
374 SaveTempsDir, count);
375 }, count);
376 count++;
377 }
378 }
379
380 // If statistics were requested, print them out now.
381 if (llvm::AreStatisticsEnabled())
382 llvm::PrintStatistics();
383 }
0 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
1 target triple = "x86_64-apple-macosx10.11.0"
2
3
4 define i32 @main() #0 {
5 entry:
6 call void (...) @weakalias()
7 call void (...) @analias()
8 %call = call i32 (...) @referencestatics()
9 %call1 = call i32 (...) @referenceglobals()
10 %call2 = call i32 (...) @referencecommon()
11 call void (...) @setfuncptr()
12 call void (...) @callfuncptr()
13 call void (...) @callweakfunc()
14 ret i32 0
15 }
16
17 declare void @weakalias(...) #1
18
19 declare void @analias(...) #1
20
21 declare i32 @referencestatics(...) #1
22
23 declare i32 @referenceglobals(...) #1
24
25 declare i32 @referencecommon(...) #1
26
27 declare void @setfuncptr(...) #1
28
29 declare void @callfuncptr(...) #1
30
31 declare void @callweakfunc(...) #1
0 ; Do setup work for all below tests: generate bitcode and combined index
1 ; RUN: llvm-as -function-summary %s -o %t.bc
2 ; RUN: llvm-as -function-summary %p/Inputs/funcimport.ll -o %t2.bc
3 ; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc
4
5 ; Ensure statics are promoted/renamed correctly from this file (all but
6 ; constant variable need promotion).
7 ; RUN: llvm-lto -thinlto-action=promote %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTSTATIC
8 ; EXPORTSTATIC-DAG: @staticvar.llvm.0 = hidden global
9 ; EXPORTSTATIC-DAG: @staticconstvar = internal unnamed_addr constant
10 ; EXPORTSTATIC-DAG: @P.llvm.0 = hidden global void ()* null
11 ; EXPORTSTATIC-DAG: define hidden i32 @staticfunc.llvm.0
12 ; EXPORTSTATIC-DAG: define hidden void @staticfunc2.llvm.0
13
14 ; Ensure that both weak alias to an imported function and strong alias to a
15 ; non-imported function are correctly turned into declarations.
16 ; Also ensures that alias to a linkonce function is turned into a declaration
17 ; and that the associated linkonce function is not in the output, as it is
18 ; lazily linked and never referenced/materialized.
19 ; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORTGLOB1
20 ; IMPORTGLOB1-DAG: define available_externally void @globalfunc1
21 ; IMPORTGLOB1-DAG: declare void @weakalias
22 ; IMPORTGLOB1-DAG: declare void @analias
23 ; IMPORTGLOB1-NOT: @linkoncealias
24 ; IMPORTGLOB1-NOT: @linkoncefunc
25 ; IMPORTGLOB1-NOT: declare void @globalfunc2
26
27 ; Verify that the optimizer run
28 ; RUN: llvm-lto -thinlto-action=optimize %t2.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=OPTIMIZED
29 ; OPTIMIZED: define i32 @main()
30
31 ; Verify that the codegen run
32 ; RUN: llvm-lto -thinlto-action=codegen %t2.bc -o - | llvm-nm -o - | FileCheck %s --check-prefix=CODEGEN
33 ; CODEGEN: T _main
34
35 ; Verify that all run together
36 ; RUN: llvm-lto -thinlto-action=run %t2.bc %t.bc
37 ; RUN: llvm-nm -o - < %t.bc.thinlto.o | FileCheck %s --check-prefix=ALL
38 ; RUN: llvm-nm -o - < %t2.bc.thinlto.o | FileCheck %s --check-prefix=ALL2
39 ; ALL: T _callfuncptr
40 ; ALL2: T _main
41
42 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
43 target triple = "x86_64-apple-macosx10.11.0"
44
45 @globalvar_in_section = global i32 1, align 4
46 @globalvar = global i32 1, align 4
47 @staticvar = internal global i32 1, align 4
48 @staticvar2 = internal global i32 1, align 4
49 @staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10, i32 20], align 4
50 @commonvar = common global i32 0, align 4
51 @P = internal global void ()* null, align 8
52
53 @weakalias = weak alias void (...), bitcast (void ()* @globalfunc1 to void (...)*)
54 @analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*)
55 @linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*)
56
57 define void @globalfunc1() #0 {
58 entry:
59 ret void
60 }
61
62 define void @globalfunc2() #0 {
63 entry:
64 ret void
65 }
66
67 define linkonce_odr void @linkoncefunc() #0 {
68 entry:
69 ret void
70 }
71
72 define i32 @referencestatics(i32 %i) #0 {
73 entry:
74 %i.addr = alloca i32, align 4
75 store i32 %i, i32* %i.addr, align 4
76 %call = call i32 @staticfunc()
77 %0 = load i32, i32* @staticvar, align 4
78 %add = add nsw i32 %call, %0
79 %1 = load i32, i32* %i.addr, align 4
80 %idxprom = sext i32 %1 to i64
81 %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @staticconstvar, i64 0, i64 %idxprom
82 %2 = load i32, i32* %arrayidx, align 4
83 %add1 = add nsw i32 %add, %2
84 ret i32 %add1
85 }
86
87 define i32 @referenceglobals(i32 %i) #0 {
88 entry:
89 %i.addr = alloca i32, align 4
90 store i32 %i, i32* %i.addr, align 4
91 call void @globalfunc1()
92 %0 = load i32, i32* @globalvar, align 4
93 ret i32 %0
94 }
95
96 define i32 @referencecommon(i32 %i) #0 {
97 entry:
98 %i.addr = alloca i32, align 4
99 store i32 %i, i32* %i.addr, align 4
100 %0 = load i32, i32* @commonvar, align 4
101 ret i32 %0
102 }
103
104 define void @setfuncptr() #0 {
105 entry:
106 store void ()* @staticfunc2, void ()** @P, align 8
107 ret void
108 }
109
110 define void @callfuncptr() #0 {
111 entry:
112 %0 = load void ()*, void ()** @P, align 8
113 call void %0()
114 ret void
115 }
116
117 @weakvar = weak global i32 1, align 4
118 define weak void @weakfunc() #0 {
119 entry:
120 ret void
121 }
122
123 define void @callweakfunc() #0 {
124 entry:
125 call void @weakfunc()
126 ret void
127 }
128
129 define internal i32 @staticfunc() #0 {
130 entry:
131 ret i32 1
132 }
133
134 define internal void @staticfunc2() #0 {
135 entry:
136 %0 = load i32, i32* @staticvar2, align 4
137 ret void
138 }
1616 #include "llvm/CodeGen/CommandFlags.h"
1717 #include "llvm/IR/DiagnosticPrinter.h"
1818 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IRReader/IRReader.h"
1920 #include "llvm/LTO/LTOCodeGenerator.h"
21 #include "llvm/LTO/ThinLTOCodeGenerator.h"
2022 #include "llvm/LTO/LTOModule.h"
2123 #include "llvm/Object/FunctionIndexObjectFile.h"
2224 #include "llvm/Support/CommandLine.h"
2426 #include "llvm/Support/ManagedStatic.h"
2527 #include "llvm/Support/PrettyStackTrace.h"
2628 #include "llvm/Support/Signals.h"
29 #include "llvm/Support/SourceMgr.h"
2730 #include "llvm/Support/TargetSelect.h"
2831 #include "llvm/Support/ToolOutputFile.h"
2932 #include "llvm/Support/raw_ostream.h"
6265 static cl::opt
6366 ThinLTO("thinlto", cl::init(false),
6467 cl::desc("Only write combined global index for ThinLTO backends"));
68
69 enum ThinLTOModes {
70 THINLINK,
71 THINPROMOTE,
72 THINIMPORT,
73 THINOPT,
74 THINCODEGEN,
75 THINALL
76 };
77
78 cl::opt ThinLTOMode(
79 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
80 cl::values(
81 clEnumValN(
82 THINLINK, "thinlink",
83 "ThinLink: produces the index by linking only the summaries."),
84 clEnumValN(THINPROMOTE, "promote",
85 "Perform pre-import promotion (requires -thinlto-index)."),
86 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
87 "cross-module importing (requires "
88 "-thinlto-index)."),
89 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
90 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
91 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end"),
92 clEnumValEnd));
93
94 static cl::opt
95 ThinLTOIndex("thinlto-index",
96 cl::desc("Provide the index produced by a ThinLink, required "
97 "to perform the promotion and/or importing."));
6598
6699 static cl::opt
67100 SaveModuleFile("save-merged-module", cl::init(false),
240273 OS.close();
241274 }
242275
276 namespace thinlto {
277
278 std::vector>
279 loadAllFilesForIndex(const FunctionInfoIndex &Index) {
280 std::vector> InputBuffers;
281
282 for (auto &ModPath : Index.modPathStringEntries()) {
283 const auto &Filename = ModPath.first();
284 auto CurrentActivity = "loading file '" + Filename + "'";
285 auto InputOrErr = MemoryBuffer::getFile(Filename);
286 error(InputOrErr, "error " + CurrentActivity);
287 InputBuffers.push_back(std::move(*InputOrErr));
288 }
289 return InputBuffers;
290 }
291
292 std::unique_ptr loadCombinedIndex() {
293 if (ThinLTOIndex.empty())
294 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
295 auto CurrentActivity = "loading file '" + ThinLTOIndex + "'";
296 ErrorOr> IndexOrErr =
297 llvm::getFunctionIndexForFile(ThinLTOIndex, diagnosticHandler);
298 error(IndexOrErr, "error " + CurrentActivity);
299 return std::move(IndexOrErr.get());
300 }
301
302 static std::unique_ptr loadModule(StringRef Filename,
303 LLVMContext &Ctx) {
304 SMDiagnostic Err;
305 std::unique_ptr M(parseIRFile(Filename, Err, Ctx));
306 if (!M) {
307 Err.print("llvm-lto", errs());
308 report_fatal_error("Can't load module for file " + Filename);
309 }
310 return M;
311 }
312
313 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
314 std::error_code EC;
315 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
316 error(EC, "error opening the file '" + Filename + "'");
317 WriteBitcodeToFile(&TheModule, OS, true, false);
318 }
319
320 class ThinLTOProcessing {
321 public:
322 ThinLTOCodeGenerator ThinGenerator;
323
324 ThinLTOProcessing(const TargetOptions &Options) {
325 ThinGenerator.setCodePICModel(RelocModel);
326 ThinGenerator.setTargetOptions(Options);
327 }
328
329 void run() {
330 switch (ThinLTOMode) {
331 case THINLINK:
332 return thinLink();
333 case THINPROMOTE:
334 return promote();
335 case THINIMPORT:
336 return import();
337 case THINOPT:
338 return optimize();
339 case THINCODEGEN:
340 return codegen();
341 case THINALL:
342 return runAll();
343 }
344 }
345
346 private:
347 /// Load the input files, create the combined index, and write it out.
348 void thinLink() {
349 // Perform "ThinLink": just produce the index
350 if (OutputFilename.empty())
351 report_fatal_error(
352 "OutputFilename is necessary to store the combined index.\n");
353
354 LLVMContext Ctx;
355 std::vector> InputBuffers;
356 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
357 auto &Filename = InputFilenames[i];
358 StringRef CurrentActivity = "loading file '" + Filename + "'";
359 auto InputOrErr = MemoryBuffer::getFile(Filename);
360 error(InputOrErr, "error " + CurrentActivity);
361 InputBuffers.push_back(std::move(*InputOrErr));
362 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
363 }
364
365 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
366 std::error_code EC;
367 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
368 error(EC, "error opening the file '" + OutputFilename + "'");
369 WriteFunctionSummaryToFile(*CombinedIndex, OS);
370 return;
371 }
372
373 /// Load the combined index from disk, then load every file referenced by
374 /// the index and add them to the generator, finally perform the promotion
375 /// on the files mentioned on the command line (these must match the index
376 /// content).
377 void promote() {
378 if (InputFilenames.size() != 1 && !OutputFilename.empty())
379 report_fatal_error("Can't handle a single output filename and multiple "
380 "input files, do not provide an output filename and "
381 "the output files will be suffixed from the input "
382 "ones.");
383
384 auto Index = loadCombinedIndex();
385 for (auto &Filename : InputFilenames) {
386 LLVMContext Ctx;
387 auto TheModule = loadModule(Filename, Ctx);
388
389 ThinGenerator.promote(*TheModule, *Index);
390
391 std::string OutputName = OutputFilename;
392 if (OutputName.empty()) {
393 OutputName = Filename + ".thinlto.promoted.bc";
394 }
395 writeModuleToFile(*TheModule, OutputName);
396 }
397 }
398
399 /// Load the combined index from disk, then load every file referenced by
400 /// the index and add them to the generator, then performs the promotion and
401 /// cross module importing on the files mentioned on the command line
402 /// (these must match the index content).
403 void import() {
404 if (InputFilenames.size() != 1 && !OutputFilename.empty())
405 report_fatal_error("Can't handle a single output filename and multiple "
406 "input files, do not provide an output filename and "
407 "the output files will be suffixed from the input "
408 "ones.");
409
410 auto Index = loadCombinedIndex();
411 auto InputBuffers = loadAllFilesForIndex(*Index);
412 for (auto &MemBuffer : InputBuffers)
413 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
414 MemBuffer->getBuffer());
415
416 for (auto &Filename : InputFilenames) {
417 LLVMContext Ctx;
418 auto TheModule = loadModule(Filename, Ctx);
419
420 ThinGenerator.crossModuleImport(*TheModule, *Index);
421
422 std::string OutputName = OutputFilename;
423 if (OutputName.empty()) {
424 OutputName = Filename + ".thinlto.imported.bc";
425 }
426 writeModuleToFile(*TheModule, OutputName);
427 }
428 }
429
430 void optimize() {
431 if (InputFilenames.size() != 1 && !OutputFilename.empty())
432 report_fatal_error("Can't handle a single output filename and multiple "
433 "input files, do not provide an output filename and "
434 "the output files will be suffixed from the input "
435 "ones.");
436 if (!ThinLTOIndex.empty())
437 errs() << "Warning: -thinlto-index ignored for optimize stage";
438
439 for (auto &Filename : InputFilenames) {
440 LLVMContext Ctx;
441 auto TheModule = loadModule(Filename, Ctx);
442
443 ThinGenerator.optimize(*TheModule);
444
445 std::string OutputName = OutputFilename;
446 if (OutputName.empty()) {
447 OutputName = Filename + ".thinlto.imported.bc";
448 }
449 writeModuleToFile(*TheModule, OutputName);
450 }
451 }
452
453 void codegen() {
454 if (InputFilenames.size() != 1 && !OutputFilename.empty())
455 report_fatal_error("Can't handle a single output filename and multiple "
456 "input files, do not provide an output filename and "
457 "the output files will be suffixed from the input "
458 "ones.");
459 if (!ThinLTOIndex.empty())
460 errs() << "Warning: -thinlto-index ignored for codegen stage";
461
462 for (auto &Filename : InputFilenames) {
463 LLVMContext Ctx;
464 auto TheModule = loadModule(Filename, Ctx);
465
466 auto Buffer = ThinGenerator.codegen(*TheModule);
467 std::string OutputName = OutputFilename;
468 if (OutputName.empty()) {
469 OutputName = Filename + ".thinlto.o";
470 }
471 if (OutputName == "-") {
472 outs() << Buffer->getBuffer();
473 return;
474 }
475
476 std::error_code EC;
477 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
478 error(EC, "error opening the file '" + OutputName + "'");
479 OS << Buffer->getBuffer();
480 }
481 }
482
483 /// Full ThinLTO process
484 void runAll() {
485 if (!OutputFilename.empty())
486 report_fatal_error("Do not provide an output filename for ThinLTO "
487 " processing, the output files will be suffixed from "
488 "the input ones.");
489
490 if (!ThinLTOIndex.empty())
491 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
492
493 LLVMContext Ctx;
494 std::vector> InputBuffers;
495 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
496 auto &Filename = InputFilenames[i];
497 StringRef CurrentActivity = "loading file '" + Filename + "'";
498 auto InputOrErr = MemoryBuffer::getFile(Filename);
499 error(InputOrErr, "error " + CurrentActivity);
500 InputBuffers.push_back(std::move(*InputOrErr));
501 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
502 }
503
504 ThinGenerator.run();
505
506 auto &Binaries = ThinGenerator.getProducedBinaries();
507 if (Binaries.size() != InputFilenames.size())
508 report_fatal_error("Number of output objects does not match the number "
509 "of inputs");
510
511 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
512 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
513 std::error_code EC;
514 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
515 error(EC, "error opening the file '" + OutputName + "'");
516 OS << Binaries[BufID]->getBuffer();
517 }
518 }
519
520 /// Load the combined index from disk, then load every file referenced by
521 };
522
523 } // namespace thinlto
524
243525 int main(int argc, char **argv) {
244526 // Print a stack trace if we signal out.
245527 sys::PrintStackTraceOnErrorSignal();
262544
263545 if (ListSymbolsOnly) {
264546 listSymbols(Options);
547 return 0;
548 }
549
550 if (ThinLTOMode.getNumOccurrences()) {
551 if (ThinLTOMode.getNumOccurrences() > 1)
552 report_fatal_error("You can't specify more than one -thinlto-action");
553 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
554 ThinLTOProcessor.run();
265555 return 0;
266556 }
267557
1919 #include "llvm/IR/LLVMContext.h"
2020 #include "llvm/LTO/LTOCodeGenerator.h"
2121 #include "llvm/LTO/LTOModule.h"
22 #include "llvm/LTO/ThinLTOCodeGenerator.h"
2223 #include "llvm/Support/MemoryBuffer.h"
2324 #include "llvm/Support/Signals.h"
2425 #include "llvm/Support/TargetSelect.h"
133134 }
134135
135136 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
137 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThinLTOCodeGenerator, thinlto_code_gen_t)
136138 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
137139
138140 // Convert the subtarget features into a string to pass to LTOCodeGenerator.
439441 lto_bool_t ShouldEmbedUselists) {
440442 unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
441443 }
444
445 // ThinLTO API below
446
447 thinlto_code_gen_t thinlto_create_codegen() {
448 lto_initialize();
449 ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator();
450 CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags());
451
452 return wrap(CodeGen);
453 }
454
455 void thinlto_codegen_dispose(thinlto_code_gen_t cg) { delete unwrap(cg); }
456
457 void thinlto_codegen_add_module(thinlto_code_gen_t cg, const char *Identifier,
458 const char *Data, int Length) {
459 unwrap(cg)->addModule(Identifier, StringRef(Data, Length));
460 }
461
462 void thinlto_codegen_process(thinlto_code_gen_t cg) { unwrap(cg)->run(); }
463
464 unsigned int thinlto_module_get_num_objects(thinlto_code_gen_t cg) {
465 return unwrap(cg)->getProducedBinaries().size();
466 }
467 LTOObjectBuffer thinlto_module_get_object(thinlto_code_gen_t cg,
468 unsigned int index) {
469 assert(index < unwrap(cg)->getProducedBinaries().size() && "Index overflow");
470 auto &MemBuffer = unwrap(cg)->getProducedBinaries()[index];
471 return LTOObjectBuffer{(void *)MemBuffer->getBufferStart(),
472 MemBuffer->getBufferSize()};
473 }
474
475 void thinlto_debug_options(const char *const *options, int number) {
476 // if options were requested, set them
477 if (number && options) {
478 std::vector CodegenArgv(1, "libLTO");
479 for (auto Arg : ArrayRef(options, number))
480 CodegenArgv.push_back(Arg);
481 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
482 }
483 }
484
485 bool lto_module_is_thinlto(lto_module_t mod) {
486 return unwrap(mod)->isThinLTO();
487 }
488
489 void thinlto_codegen_add_must_preserve_symbol(thinlto_code_gen_t cg,
490 const char *Name, int Length) {
491 unwrap(cg)->preserveSymbol(StringRef(Name, Length));
492 }
493
494 void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
495 const char *Name, int Length) {
496 unwrap(cg)->crossReferenceSymbol(StringRef(Name, Length));
497 }
498
499 void thinlto_codegen_set_cpu(thinlto_code_gen_t cg, const char *cpu) {
500 return unwrap(cg)->setCpu(cpu);
501 }
502
503 void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
504 const char *cache_dir) {
505 return unwrap(cg)->setCacheDir(cache_dir);
506 }
507
508 void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
509 int interval) {
510 return unwrap(cg)->setCachePruningInterval(interval);
511 }
512
513 void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
514 unsigned expiration) {
515 return unwrap(cg)->setCacheEntryExpiration(expiration);
516 }
517
518 void thinlto_codegen_set_final_cache_size_relative_to_available_space(
519 thinlto_code_gen_t cg, unsigned Percentage) {
520 return unwrap(cg)->setMaxCacheSizeRelativeToAvailableSpace(Percentage);
521 }
522
523 void thinlto_codegen_set_savetemps_dir(thinlto_code_gen_t cg,
524 const char *save_temps_dir) {
525 return unwrap(cg)->setSaveTempsDir(save_temps_dir);
526 }
527
528 lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
529 lto_codegen_model model) {
530 switch (model) {
531 case LTO_CODEGEN_PIC_MODEL_STATIC:
532 unwrap(cg)->setCodePICModel(Reloc::Static);
533 return false;
534 case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
535 unwrap(cg)->setCodePICModel(Reloc::PIC_);
536 return false;
537 case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
538 unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
539 return false;
540 case LTO_CODEGEN_PIC_MODEL_DEFAULT:
541 unwrap(cg)->setCodePICModel(Reloc::Default);
542 return false;
543 }
544 sLastErrorString = "Unknown PIC model";
545 return true;
546 }
4444 LLVMDisasmDispose
4545 LLVMDisasmInstruction
4646 LLVMSetDisasmOptions
47 thinlto_create_codegen
48 thinlto_codegen_dispose
49 thinlto_codegen_add_module
50 thinlto_codegen_process
51 thinlto_module_get_num_objects
52 thinlto_module_get_object
53 thinlto_codegen_set_pic_model
54 thinlto_codegen_set_cache_dir
55 thinlto_codegen_set_cache_pruning_interval
56 thinlto_codegen_set_cache_entry_expiration
57 thinlto_codegen_set_savetemps_dir
58 thinlto_codegen_set_cpu
59 thinlto_debug_options
60 lto_module_is_thinlto
61 thinlto_codegen_add_must_preserve_symbol
62 thinlto_codegen_add_cross_referenced_symbol
63 thinlto_codegen_set_final_cache_size_relative_to_available_space