#include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
+#include "llvm/LTO/Config.h"
+#include "llvm/LTO/LTO.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ToolOutputFile.h"
LTOCodeGenerator(LLVMContext &Context);
~LTOCodeGenerator();
+ /// Return a lto::Config object which contains the options set in
+ /// LTOCodeGenerator.
+ lto::Config toConfig() const;
+
/// Merge given module. Return true on success.
///
/// Resets \a HasVerifiedInput.
/// if the compilation was not successful.
std::unique_ptr<MemoryBuffer> compileOptimized();
- /// Compile the merged optimized module into out.size() output files each
+ /// Compile the merged optimized module \p ParallelismLevel output files each
/// representing a linkable partition of the module. If out contains more
- /// than one element, code generation is done in parallel with out.size()
- /// threads. Output files will be written to members of out. Returns true on
- /// success.
+ /// than one element, code generation is done in parallel with \p
+ /// ParallelismLevel threads. Output files will be written to the streams
+ /// created using the \p AddStream callback. Returns true on success.
///
/// Calls \a verifyMergedModuleOnce().
- bool compileOptimized(ArrayRef<raw_pwrite_stream *> Out);
+ bool compileOptimized(lto::AddStreamFn AddStream, unsigned ParallelismLevel);
/// Enable the Freestanding mode: indicate that the optimizer should not
/// assume builtins are present on the target.
void DiagnosticHandler(const DiagnosticInfo &DI);
private:
- void initializeLTOPasses();
-
/// Verify the merged module on first call.
///
/// Sets \a HasVerifiedInput on first call and doesn't run again on the same
#include "llvm/IR/Verifier.h"
#include "llvm/InitializePasses.h"
#include "llvm/LTO/LTO.h"
+#include "llvm/LTO/LTOBackend.h"
#include "llvm/LTO/legacy/LTOModule.h"
#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
#include "llvm/Linker/Linker.h"
TheLinker(new Linker(*MergedModule)) {
Context.setDiscardValueNames(LTODiscardValueNames);
Context.enableDebugTypeODRUniquing();
- initializeLTOPasses();
}
LTOCodeGenerator::~LTOCodeGenerator() {}
-// Initialize LTO passes. Please keep this function in sync with
-// PassManagerBuilder::populateLTOPassManager(), and make sure all LTO
-// passes are initialized.
-void LTOCodeGenerator::initializeLTOPasses() {
- PassRegistry &R = *PassRegistry::getPassRegistry();
-
- initializeInternalizeLegacyPassPass(R);
- initializeIPSCCPLegacyPassPass(R);
- initializeGlobalOptLegacyPassPass(R);
- initializeConstantMergeLegacyPassPass(R);
- initializeDAHPass(R);
- initializeInstructionCombiningPassPass(R);
- initializeSimpleInlinerPass(R);
- initializePruneEHPass(R);
- initializeGlobalDCELegacyPassPass(R);
- initializeOpenMPOptLegacyPassPass(R);
- initializeArgPromotionPass(R);
- initializeJumpThreadingPass(R);
- initializeSROALegacyPassPass(R);
- initializeAttributorLegacyPassPass(R);
- initializeAttributorCGSCCLegacyPassPass(R);
- initializePostOrderFunctionAttrsLegacyPassPass(R);
- initializeReversePostOrderFunctionAttrsLegacyPassPass(R);
- initializeGlobalsAAWrapperPassPass(R);
- initializeLegacyLICMPassPass(R);
- initializeMergedLoadStoreMotionLegacyPassPass(R);
- initializeGVNLegacyPassPass(R);
- initializeMemCpyOptLegacyPassPass(R);
- initializeDCELegacyPassPass(R);
- initializeCFGSimplifyPassPass(R);
+lto::Config LTOCodeGenerator::toConfig() const {
+ lto::Config Conf;
+ Conf.CGFileType = FileType;
+ Conf.CPU = MCpu;
+ Conf.MAttrs = MAttrs;
+ Conf.RelocModel = RelocModel;
+ Conf.Options = Options;
+ Conf.CodeModel = None;
+ Conf.StatsFile = LTOStatsFile;
+ Conf.OptLevel = OptLevel;
+ Conf.Freestanding = Freestanding;
+ Conf.PTO.LoopVectorization = OptLevel > 1;
+ Conf.PTO.SLPVectorization = OptLevel > 1;
+ Conf.DisableVerify = DisableVerify;
+ Conf.PreCodeGenPassesHook = [](legacy::PassManager &PM) {
+ PM.add(createObjCARCContractPass());
+ };
+
+ return Conf;
}
void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) {
bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) {
// make unique temp output file to put generated code
SmallString<128> Filename;
- int FD;
- StringRef Extension
- (FileType == CGFT_AssemblyFile ? "s" : "o");
+ auto AddStream =
+ [&](size_t Task) -> std::unique_ptr<lto::NativeObjectStream> {
+ StringRef Extension(FileType == CGFT_AssemblyFile ? "s" : "o");
- std::error_code EC =
- sys::fs::createTemporaryFile("lto-llvm", Extension, FD, Filename);
- if (EC) {
- emitError(EC.message());
- return false;
- }
+ int FD;
+ std::error_code EC =
+ sys::fs::createTemporaryFile("lto-llvm", Extension, FD, Filename);
+ if (EC)
+ emitError(EC.message());
- // generate object file
- ToolOutputFile objFile(Filename, FD);
+ return std::make_unique<lto::NativeObjectStream>(
+ std::make_unique<llvm::raw_fd_ostream>(FD, true));
+ };
- bool genResult = compileOptimized(&objFile.os());
- objFile.os().close();
- if (objFile.os().has_error()) {
- emitError((Twine("could not write object file: ") + Filename + ": " +
- objFile.os().error().message())
- .str());
- objFile.os().clear_error();
- sys::fs::remove(Twine(Filename));
- return false;
- }
+ bool genResult = compileOptimized(AddStream, 1);
- objFile.keep();
if (!genResult) {
sys::fs::remove(Twine(Filename));
return false;
}
+ // If statistics were requested, save them to the specified file or
+ // print them out after codegen.
+ if (StatsFile)
+ PrintStatisticsJSON(StatsFile->os());
+ else if (AreStatisticsEnabled())
+ PrintStatistics();
+
NativeObjectPath = Filename.c_str();
*Name = NativeObjectPath.c_str();
return true;
// Write LTOPostLink flag for passes that require all the modules.
MergedModule->addModuleFlag(Module::Error, "LTOPostLink", 1);
- // Instantiate the pass manager to organize the passes.
- legacy::PassManager passes;
-
// Add an appropriate DataLayout instance for this module...
MergedModule->setDataLayout(TargetMach->createDataLayout());
- passes.add(
- createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis()));
-
- Triple TargetTriple(TargetMach->getTargetTriple());
- PassManagerBuilder PMB;
- PMB.LoopVectorize = true;
- PMB.SLPVectorize = true;
- PMB.Inliner = createFunctionInliningPass();
- PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple);
- if (Freestanding)
- PMB.LibraryInfo->disableAllFunctions();
- PMB.OptLevel = OptLevel;
- PMB.VerifyInput = !DisableVerify;
- PMB.VerifyOutput = !DisableVerify;
-
- PMB.populateLTOPassManager(passes);
+ lto::Config Conf = toConfig();
- // Run our queue of passes all at once now, efficiently.
- passes.run(*MergedModule);
+ ModuleSummaryIndex CombinedIndex(false);
+ TargetMach = createTargetMachine();
+ if (!opt(Conf, TargetMach.get(), 0, *MergedModule, /*IsThinLTO=*/false,
+ /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr,
+ /*CmdArgs*/ std::vector<uint8_t>())) {
+ emitError("LTO middle-end optimizations failed");
+ return false;
+ }
return true;
}
-bool LTOCodeGenerator::compileOptimized(ArrayRef<raw_pwrite_stream *> Out) {
+bool LTOCodeGenerator::compileOptimized(lto::AddStreamFn AddStream,
+ unsigned ParallelismLevel) {
if (!this->determineTarget())
return false;
// been called in optimize(), this call will return early.
verifyMergedModuleOnce();
- legacy::PassManager preCodeGenPasses;
-
- // If the bitcode files contain ARC code and were compiled with optimization,
- // the ObjCARCContractPass must be run, so do it unconditionally here.
- preCodeGenPasses.add(createObjCARCContractPass());
- preCodeGenPasses.run(*MergedModule);
-
// Re-externalize globals that may have been internalized to increase scope
// for splitting
restoreLinkageForExternals();
- splitCodeGen(
- *MergedModule, Out, {}, [&]() { return createTargetMachine(); }, FileType,
- ShouldRestoreGlobalsLinkage);
+ lto::Config Conf = toConfig();
+ ModuleSummaryIndex CombinedIndex(false);
+
+ Error Err =
+ backend(Conf, AddStream, ParallelismLevel, *MergedModule, CombinedIndex);
+ assert(!Err && "unexpected code-generation failure");
+ (void)Err;
// If statistics were requested, save them to the specified file or
// print them out after codegen.