2017-09-08 07:28:24 +08:00
|
|
|
//===- llvm-lto: a simple command-line program to link modules with LTO ---===//
|
2013-09-20 06:15:52 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-09-20 06:15:52 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This program takes in a list of bitcode files, links them, performs link-time
|
|
|
|
// optimization, and outputs an object file.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm-c/lto.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2013-11-01 04:51:58 +08:00
|
|
|
#include "llvm/ADT/StringSet.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2016-11-11 13:34:58 +08:00
|
|
|
#include "llvm/Bitcode/BitcodeReader.h"
|
|
|
|
#include "llvm/Bitcode/BitcodeWriter.h"
|
2020-03-04 07:47:43 +08:00
|
|
|
#include "llvm/CodeGen/CommandFlags.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
2015-11-19 13:52:29 +08:00
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
2015-10-19 22:30:44 +08:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
2016-04-20 09:04:26 +08:00
|
|
|
#include "llvm/IR/Verifier.h"
|
2016-03-09 09:37:22 +08:00
|
|
|
#include "llvm/IRReader/IRReader.h"
|
2016-07-15 05:21:16 +08:00
|
|
|
#include "llvm/LTO/legacy/LTOCodeGenerator.h"
|
|
|
|
#include "llvm/LTO/legacy/LTOModule.h"
|
|
|
|
#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
2013-09-20 06:15:52 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/ErrorOr.h"
|
2014-04-30 07:26:49 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2018-04-14 02:26:06 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2016-05-17 22:45:30 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2016-03-09 09:37:22 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
2013-09-25 07:52:22 +08:00
|
|
|
#include "llvm/Support/TargetSelect.h"
|
2015-08-28 07:37:36 +08:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2014-01-13 16:04:33 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-09-08 07:28:24 +08:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <cstdlib>
|
2015-08-28 07:37:36 +08:00
|
|
|
#include <list>
|
2017-09-08 07:28:24 +08:00
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <system_error>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2013-09-20 06:15:52 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2020-03-04 07:47:43 +08:00
|
|
|
static codegen::RegisterCodeGenFlags CGF;
|
|
|
|
|
2015-03-20 06:01:00 +08:00
|
|
|
static cl::opt<char>
|
2016-04-14 05:41:35 +08:00
|
|
|
OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
|
|
|
|
"(default = '-O2')"),
|
|
|
|
cl::Prefix, cl::ZeroOrMore, cl::init('2'));
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2016-09-15 05:04:59 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
IndexStats("thinlto-index-stats",
|
|
|
|
cl::desc("Print statistic for the index in every input files"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2015-09-16 07:05:59 +08:00
|
|
|
static cl::opt<bool> DisableVerify(
|
|
|
|
"disable-verify", cl::init(false),
|
|
|
|
cl::desc("Do not run the verifier during the optimization pipeline"));
|
|
|
|
|
2016-04-14 05:41:35 +08:00
|
|
|
static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
|
|
|
|
cl::desc("Do not run the inliner pass"));
|
2013-10-01 00:39:19 +08:00
|
|
|
|
|
|
|
static cl::opt<bool>
|
2016-04-14 05:41:35 +08:00
|
|
|
DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
|
|
|
|
cl::desc("Do not run the GVN load PRE pass"));
|
2013-10-01 00:39:19 +08:00
|
|
|
|
2016-04-14 05:41:35 +08:00
|
|
|
static cl::opt<bool> DisableLTOVectorization(
|
|
|
|
"disable-lto-vectorization", cl::init(false),
|
|
|
|
cl::desc("Do not run loop or slp vectorization during LTO"));
|
2014-10-27 05:50:58 +08:00
|
|
|
|
2017-03-29 02:55:44 +08:00
|
|
|
static cl::opt<bool> EnableFreestanding(
|
|
|
|
"lto-freestanding", cl::init(false),
|
|
|
|
cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
|
|
|
|
|
2016-04-14 05:41:35 +08:00
|
|
|
static cl::opt<bool> UseDiagnosticHandler(
|
|
|
|
"use-diagnostic-handler", cl::init(false),
|
|
|
|
cl::desc("Use a diagnostic handler to test the handler interface"));
|
2014-10-02 02:36:03 +08:00
|
|
|
|
2015-11-03 02:02:11 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
ThinLTO("thinlto", cl::init(false),
|
|
|
|
cl::desc("Only write combined global index for ThinLTO backends"));
|
2015-10-19 22:30:44 +08:00
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
enum ThinLTOModes {
|
|
|
|
THINLINK,
|
2016-05-10 21:48:23 +08:00
|
|
|
THINDISTRIBUTE,
|
2016-05-10 23:54:09 +08:00
|
|
|
THINEMITIMPORTS,
|
2016-03-09 09:37:22 +08:00
|
|
|
THINPROMOTE,
|
|
|
|
THINIMPORT,
|
2016-04-24 11:18:01 +08:00
|
|
|
THININTERNALIZE,
|
2016-03-09 09:37:22 +08:00
|
|
|
THINOPT,
|
|
|
|
THINCODEGEN,
|
|
|
|
THINALL
|
|
|
|
};
|
|
|
|
|
|
|
|
cl::opt<ThinLTOModes> ThinLTOMode(
|
|
|
|
"thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
|
|
|
|
cl::values(
|
|
|
|
clEnumValN(
|
|
|
|
THINLINK, "thinlink",
|
|
|
|
"ThinLink: produces the index by linking only the summaries."),
|
2016-05-10 21:48:23 +08:00
|
|
|
clEnumValN(THINDISTRIBUTE, "distributedindexes",
|
|
|
|
"Produces individual indexes for distributed backends."),
|
2016-05-10 23:54:09 +08:00
|
|
|
clEnumValN(THINEMITIMPORTS, "emitimports",
|
|
|
|
"Emit imports files for distributed backends."),
|
2016-03-09 09:37:22 +08:00
|
|
|
clEnumValN(THINPROMOTE, "promote",
|
|
|
|
"Perform pre-import promotion (requires -thinlto-index)."),
|
|
|
|
clEnumValN(THINIMPORT, "import", "Perform both promotion and "
|
|
|
|
"cross-module importing (requires "
|
|
|
|
"-thinlto-index)."),
|
2016-04-24 11:18:01 +08:00
|
|
|
clEnumValN(THININTERNALIZE, "internalize",
|
|
|
|
"Perform internalization driven by -exported-symbol "
|
|
|
|
"(requires -thinlto-index)."),
|
2016-03-09 09:37:22 +08:00
|
|
|
clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
|
|
|
|
clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
|
2016-10-09 03:41:06 +08:00
|
|
|
clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
|
2016-03-09 09:37:22 +08:00
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
ThinLTOIndex("thinlto-index",
|
|
|
|
cl::desc("Provide the index produced by a ThinLink, required "
|
|
|
|
"to perform the promotion and/or importing."));
|
|
|
|
|
2016-05-17 22:45:30 +08:00
|
|
|
static cl::opt<std::string> ThinLTOPrefixReplace(
|
|
|
|
"thinlto-prefix-replace",
|
|
|
|
cl::desc("Control where files for distributed backends are "
|
2016-05-18 02:43:22 +08:00
|
|
|
"created. Expects 'oldprefix;newprefix' and if path "
|
2016-05-17 22:45:30 +08:00
|
|
|
"prefix of output file is oldprefix it will be "
|
|
|
|
"replaced with newprefix."));
|
|
|
|
|
2016-05-06 00:33:51 +08:00
|
|
|
static cl::opt<std::string> ThinLTOModuleId(
|
|
|
|
"thinlto-module-id",
|
|
|
|
cl::desc("For the module ID for the file to process, useful to "
|
|
|
|
"match what is in the index."));
|
|
|
|
|
2016-05-14 13:16:41 +08:00
|
|
|
static cl::opt<std::string>
|
|
|
|
ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
|
|
|
|
|
2017-12-19 22:42:38 +08:00
|
|
|
static cl::opt<int>
|
2018-02-16 07:29:21 +08:00
|
|
|
ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
|
|
|
|
cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
|
2017-12-19 22:42:38 +08:00
|
|
|
|
2019-04-24 10:40:20 +08:00
|
|
|
static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
|
|
|
|
"thinlto-cache-max-size-bytes",
|
2018-03-02 11:51:27 +08:00
|
|
|
cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
|
|
|
|
|
|
|
|
static cl::opt<int>
|
|
|
|
ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
|
|
|
|
cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
|
|
|
|
|
2018-10-03 21:00:20 +08:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
|
|
|
|
cl::desc("Set ThinLTO cache entry expiration time."));
|
|
|
|
|
2016-08-16 07:24:57 +08:00
|
|
|
static cl::opt<std::string> ThinLTOSaveTempsPrefix(
|
|
|
|
"thinlto-save-temps",
|
|
|
|
cl::desc("Save ThinLTO temp files using filenames created by adding "
|
|
|
|
"suffixes to the given file path prefix."));
|
|
|
|
|
2016-12-14 12:56:42 +08:00
|
|
|
static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
|
|
|
|
"thinlto-save-objects",
|
|
|
|
cl::desc("Save ThinLTO generated object files using filenames created in "
|
|
|
|
"the given directory."));
|
|
|
|
|
2020-08-27 02:17:26 +08:00
|
|
|
static cl::opt<bool> SaveLinkedModuleFile(
|
|
|
|
"save-linked-module", cl::init(false),
|
|
|
|
cl::desc("Write linked LTO module to file before optimize"));
|
|
|
|
|
2015-11-20 08:13:05 +08:00
|
|
|
static cl::opt<bool>
|
2016-04-14 05:41:35 +08:00
|
|
|
SaveModuleFile("save-merged-module", cl::init(false),
|
|
|
|
cl::desc("Write merged LTO module to file before CodeGen"));
|
2015-11-20 08:13:05 +08:00
|
|
|
|
2016-04-14 05:41:35 +08:00
|
|
|
static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
|
|
|
|
cl::desc("<input bitcode files>"));
|
2013-10-01 00:39:19 +08:00
|
|
|
|
2016-04-14 05:41:35 +08:00
|
|
|
static cl::opt<std::string> OutputFilename("o", cl::init(""),
|
|
|
|
cl::desc("Override output filename"),
|
|
|
|
cl::value_desc("filename"));
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2016-04-24 11:18:01 +08:00
|
|
|
static cl::list<std::string> ExportedSymbols(
|
|
|
|
"exported-symbol",
|
|
|
|
cl::desc("List of symbols to export from the resulting object file"),
|
|
|
|
cl::ZeroOrMore);
|
2013-10-02 22:12:56 +08:00
|
|
|
|
2013-10-04 02:29:09 +08:00
|
|
|
static cl::list<std::string>
|
2016-04-14 05:41:35 +08:00
|
|
|
DSOSymbols("dso-symbol",
|
|
|
|
cl::desc("Symbol to put in the symtab in the resulting dso"),
|
|
|
|
cl::ZeroOrMore);
|
2013-10-02 22:12:56 +08:00
|
|
|
|
2014-12-17 10:00:38 +08:00
|
|
|
static cl::opt<bool> ListSymbolsOnly(
|
|
|
|
"list-symbols-only", cl::init(false),
|
|
|
|
cl::desc("Instead of running LTO, list the symbols in each IR file"));
|
|
|
|
|
2019-06-12 19:07:56 +08:00
|
|
|
static cl::opt<bool> ListDependentLibrariesOnly(
|
|
|
|
"list-dependent-libraries-only", cl::init(false),
|
|
|
|
cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
|
|
|
|
|
2015-02-24 08:45:56 +08:00
|
|
|
static cl::opt<bool> SetMergedModule(
|
|
|
|
"set-merged-module", cl::init(false),
|
|
|
|
cl::desc("Use the first input module as the merged module"));
|
|
|
|
|
2015-08-28 07:37:36 +08:00
|
|
|
static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
|
|
|
|
cl::desc("Number of backend threads"));
|
|
|
|
|
2016-01-19 07:35:24 +08:00
|
|
|
static cl::opt<bool> RestoreGlobalsLinkage(
|
|
|
|
"restore-linkage", cl::init(false),
|
|
|
|
cl::desc("Restore original linkage of globals prior to CodeGen"));
|
|
|
|
|
2016-07-12 07:10:18 +08:00
|
|
|
static cl::opt<bool> CheckHasObjC(
|
|
|
|
"check-for-objc", cl::init(false),
|
|
|
|
cl::desc("Only check if the module has objective-C defined in it"));
|
|
|
|
|
2020-02-19 09:13:47 +08:00
|
|
|
static cl::opt<bool> PrintMachOCPUOnly(
|
|
|
|
"print-macho-cpu-only", cl::init(false),
|
|
|
|
cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"));
|
|
|
|
|
2013-11-01 04:51:58 +08:00
|
|
|
namespace {
|
2017-09-08 07:28:24 +08:00
|
|
|
|
2013-11-01 04:51:58 +08:00
|
|
|
struct ModuleInfo {
|
|
|
|
std::vector<bool> CanBeHidden;
|
|
|
|
};
|
2017-09-08 07:28:24 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2013-11-01 04:51:58 +08:00
|
|
|
|
2015-03-10 00:23:46 +08:00
|
|
|
static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
|
|
|
|
const char *Msg, void *) {
|
2015-11-11 02:52:48 +08:00
|
|
|
errs() << "llvm-lto: ";
|
2014-10-02 02:36:03 +08:00
|
|
|
switch (Severity) {
|
|
|
|
case LTO_DS_NOTE:
|
|
|
|
errs() << "note: ";
|
|
|
|
break;
|
|
|
|
case LTO_DS_REMARK:
|
|
|
|
errs() << "remark: ";
|
|
|
|
break;
|
|
|
|
case LTO_DS_ERROR:
|
|
|
|
errs() << "error: ";
|
|
|
|
break;
|
|
|
|
case LTO_DS_WARNING:
|
|
|
|
errs() << "warning: ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
errs() << Msg << "\n";
|
|
|
|
}
|
|
|
|
|
2015-12-05 00:14:31 +08:00
|
|
|
static std::string CurrentActivity;
|
2017-09-16 03:53:54 +08:00
|
|
|
|
2017-09-16 04:10:09 +08:00
|
|
|
namespace {
|
|
|
|
struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
|
|
|
|
bool handleDiagnostics(const DiagnosticInfo &DI) override {
|
|
|
|
raw_ostream &OS = errs();
|
|
|
|
OS << "llvm-lto: ";
|
|
|
|
switch (DI.getSeverity()) {
|
|
|
|
case DS_Error:
|
|
|
|
OS << "error";
|
|
|
|
break;
|
|
|
|
case DS_Warning:
|
|
|
|
OS << "warning";
|
|
|
|
break;
|
|
|
|
case DS_Remark:
|
|
|
|
OS << "remark";
|
|
|
|
break;
|
|
|
|
case DS_Note:
|
|
|
|
OS << "note";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!CurrentActivity.empty())
|
|
|
|
OS << ' ' << CurrentActivity;
|
|
|
|
OS << ": ";
|
|
|
|
|
|
|
|
DiagnosticPrinterRawOStream DP(OS);
|
|
|
|
DI.print(DP);
|
|
|
|
OS << '\n';
|
|
|
|
|
|
|
|
if (DI.getSeverity() == DS_Error)
|
|
|
|
exit(1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2015-11-19 13:52:29 +08:00
|
|
|
|
2015-12-04 08:45:57 +08:00
|
|
|
static void error(const Twine &Msg) {
|
|
|
|
errs() << "llvm-lto: " << Msg << '\n';
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void error(std::error_code EC, const Twine &Prefix) {
|
|
|
|
if (EC)
|
|
|
|
error(Prefix + ": " + EC.message());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static void error(const ErrorOr<T> &V, const Twine &Prefix) {
|
|
|
|
error(V.getError(), Prefix);
|
|
|
|
}
|
|
|
|
|
2016-04-20 09:04:26 +08:00
|
|
|
static void maybeVerifyModule(const Module &Mod) {
|
2016-12-24 07:53:57 +08:00
|
|
|
if (!DisableVerify && verifyModule(Mod, &errs()))
|
2016-04-20 09:04:26 +08:00
|
|
|
error("Broken Module");
|
|
|
|
}
|
|
|
|
|
2015-03-10 00:23:46 +08:00
|
|
|
static std::unique_ptr<LTOModule>
|
2014-12-17 10:00:38 +08:00
|
|
|
getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
|
2015-12-04 08:45:57 +08:00
|
|
|
const TargetOptions &Options) {
|
2014-12-17 10:00:38 +08:00
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
|
|
|
|
MemoryBuffer::getFile(Path);
|
2015-12-04 08:45:57 +08:00
|
|
|
error(BufferOrErr, "error loading file '" + Path + "'");
|
2014-12-17 10:00:38 +08:00
|
|
|
Buffer = std::move(BufferOrErr.get());
|
2015-12-05 00:14:31 +08:00
|
|
|
CurrentActivity = ("loading file '" + Path + "'").str();
|
2019-08-15 23:54:37 +08:00
|
|
|
std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
|
|
|
|
Context->setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
|
2017-09-16 04:10:09 +08:00
|
|
|
true);
|
2015-12-05 00:14:31 +08:00
|
|
|
ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
|
2016-03-01 21:13:49 +08:00
|
|
|
std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
|
|
|
|
Options, Path);
|
2015-12-05 00:14:31 +08:00
|
|
|
CurrentActivity = "";
|
2016-04-20 09:04:26 +08:00
|
|
|
maybeVerifyModule((*Ret)->getModule());
|
2015-12-05 00:14:31 +08:00
|
|
|
return std::move(*Ret);
|
2014-12-17 10:00:38 +08:00
|
|
|
}
|
|
|
|
|
2016-09-15 05:04:59 +08:00
|
|
|
/// Print some statistics on the index for each input files.
|
2020-09-27 06:57:09 +08:00
|
|
|
static void printIndexStats() {
|
2016-09-15 05:04:59 +08:00
|
|
|
for (auto &Filename : InputFilenames) {
|
2016-11-12 03:50:39 +08:00
|
|
|
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
|
|
|
|
std::unique_ptr<ModuleSummaryIndex> Index =
|
2017-09-08 07:28:24 +08:00
|
|
|
ExitOnErr(getModuleSummaryIndexForFile(Filename));
|
2016-09-15 05:04:59 +08:00
|
|
|
// Skip files without a module summary.
|
|
|
|
if (!Index)
|
|
|
|
report_fatal_error(Filename + " does not contain an index");
|
|
|
|
|
|
|
|
unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
|
|
|
|
for (auto &Summaries : *Index) {
|
2017-05-05 02:03:25 +08:00
|
|
|
for (auto &Summary : Summaries.second.SummaryList) {
|
2016-09-15 05:04:59 +08:00
|
|
|
Refs += Summary->refs().size();
|
|
|
|
if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
|
|
|
|
Functions++;
|
|
|
|
Calls += FuncSummary->calls().size();
|
|
|
|
} else if (isa<AliasSummary>(Summary.get()))
|
|
|
|
Alias++;
|
|
|
|
else
|
|
|
|
Globals++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
outs() << "Index " << Filename << " contains "
|
|
|
|
<< (Alias + Globals + Functions) << " nodes (" << Functions
|
|
|
|
<< " functions, " << Alias << " alias, " << Globals
|
|
|
|
<< " globals) and " << (Calls + Refs) << " edges (" << Refs
|
|
|
|
<< " refs and " << Calls << " calls)\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// List symbols in each IR file.
|
2014-12-17 10:00:38 +08:00
|
|
|
///
|
|
|
|
/// The main point here is to provide lit-testable coverage for the LTOModule
|
|
|
|
/// functionality that's exposed by the C API to list symbols. Moreover, this
|
|
|
|
/// provides testing coverage for modules that have been created in their own
|
|
|
|
/// contexts.
|
2015-12-04 08:45:57 +08:00
|
|
|
static void listSymbols(const TargetOptions &Options) {
|
2014-12-17 10:00:38 +08:00
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
std::unique_ptr<MemoryBuffer> Buffer;
|
|
|
|
std::unique_ptr<LTOModule> Module =
|
2015-12-04 08:45:57 +08:00
|
|
|
getLocalLTOModule(Filename, Buffer, Options);
|
2014-12-17 10:00:38 +08:00
|
|
|
|
|
|
|
// List the symbols.
|
|
|
|
outs() << Filename << ":\n";
|
|
|
|
for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
|
|
|
|
outs() << Module->getSymbolName(I) << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 19:07:56 +08:00
|
|
|
static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
|
|
|
|
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
|
|
|
|
"': ");
|
|
|
|
return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void listDependentLibraries() {
|
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
std::string E;
|
|
|
|
std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
|
|
|
|
Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
|
|
|
|
E));
|
|
|
|
if (!Input)
|
|
|
|
error(E);
|
|
|
|
|
|
|
|
// List the dependent libraries.
|
|
|
|
outs() << Filename << ":\n";
|
|
|
|
for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
|
|
|
|
I != C; ++I) {
|
|
|
|
size_t L = 0;
|
|
|
|
const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
|
|
|
|
assert(S);
|
|
|
|
outs() << StringRef(S, L) << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-19 09:13:47 +08:00
|
|
|
static void printMachOCPUOnly() {
|
|
|
|
LLVMContext Context;
|
|
|
|
Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
|
|
|
|
true);
|
2020-10-14 23:55:55 +08:00
|
|
|
TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
|
2020-02-19 09:13:47 +08:00
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
|
|
|
|
LTOModule::createFromFile(Context, Filename, Options);
|
|
|
|
if (!ModuleOrErr)
|
|
|
|
error(ModuleOrErr, "llvm-lto: ");
|
|
|
|
|
|
|
|
Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
|
|
|
|
Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
|
|
|
|
if (!CPUType)
|
|
|
|
error("Error while printing mach-o cputype: " +
|
|
|
|
toString(CPUType.takeError()));
|
|
|
|
if (!CPUSubType)
|
|
|
|
error("Error while printing mach-o cpusubtype: " +
|
|
|
|
toString(CPUSubType.takeError()));
|
|
|
|
outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
|
|
|
|
Filename.c_str(), *CPUType, *CPUSubType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-19 22:30:44 +08:00
|
|
|
/// Create a combined index file from the input IR files and write it.
|
|
|
|
///
|
|
|
|
/// This is meant to enable testing of ThinLTO combined index generation,
|
|
|
|
/// currently available via the gold plugin via -thinlto.
|
2016-03-15 08:04:37 +08:00
|
|
|
static void createCombinedModuleSummaryIndex() {
|
2018-06-07 06:22:01 +08:00
|
|
|
ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
|
2015-10-19 22:30:44 +08:00
|
|
|
uint64_t NextModuleId = 0;
|
|
|
|
for (auto &Filename : InputFilenames) {
|
2016-11-12 03:50:39 +08:00
|
|
|
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
|
2017-05-02 06:04:36 +08:00
|
|
|
std::unique_ptr<MemoryBuffer> MB =
|
|
|
|
ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
|
2018-05-16 22:58:14 +08:00
|
|
|
ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
|
2015-10-19 22:30:44 +08:00
|
|
|
}
|
|
|
|
std::error_code EC;
|
|
|
|
assert(!OutputFilename.empty());
|
|
|
|
raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
|
2019-08-05 13:43:48 +08:00
|
|
|
sys::fs::OpenFlags::OF_None);
|
2015-12-04 08:45:57 +08:00
|
|
|
error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
WriteIndexToFile(CombinedIndex, OS);
|
2015-10-19 22:30:44 +08:00
|
|
|
OS.close();
|
|
|
|
}
|
|
|
|
|
2016-05-17 22:45:30 +08:00
|
|
|
/// Parse the thinlto_prefix_replace option into the \p OldPrefix and
|
|
|
|
/// \p NewPrefix strings, if it was specified.
|
|
|
|
static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
|
|
|
|
std::string &NewPrefix) {
|
|
|
|
assert(ThinLTOPrefixReplace.empty() ||
|
2016-05-18 02:43:22 +08:00
|
|
|
ThinLTOPrefixReplace.find(";") != StringRef::npos);
|
2016-05-17 22:45:30 +08:00
|
|
|
StringRef PrefixReplace = ThinLTOPrefixReplace;
|
2016-05-18 02:43:22 +08:00
|
|
|
std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
|
2016-05-17 22:45:30 +08:00
|
|
|
OldPrefix = Split.first.str();
|
|
|
|
NewPrefix = Split.second.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Given the original \p Path to an output file, replace any path
|
|
|
|
/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
|
|
|
|
/// resulting directory if it does not yet exist.
|
|
|
|
static std::string getThinLTOOutputFile(const std::string &Path,
|
|
|
|
const std::string &OldPrefix,
|
|
|
|
const std::string &NewPrefix) {
|
|
|
|
if (OldPrefix.empty() && NewPrefix.empty())
|
|
|
|
return Path;
|
|
|
|
SmallString<128> NewPath(Path);
|
|
|
|
llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
|
|
|
|
StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
|
|
|
|
if (!ParentPath.empty()) {
|
|
|
|
// Make sure the new directory exists, creating it if necessary.
|
|
|
|
if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
|
|
|
|
error(EC, "error creating the directory '" + ParentPath + "'");
|
|
|
|
}
|
2020-01-29 03:23:46 +08:00
|
|
|
return std::string(NewPath.str());
|
2016-05-17 22:45:30 +08:00
|
|
|
}
|
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
namespace thinlto {
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<MemoryBuffer>>
|
2016-03-15 08:04:37 +08:00
|
|
|
loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
|
2016-03-09 09:37:22 +08:00
|
|
|
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
|
|
|
|
|
2016-03-26 11:35:38 +08:00
|
|
|
for (auto &ModPath : Index.modulePaths()) {
|
2016-03-09 09:37:22 +08:00
|
|
|
const auto &Filename = ModPath.first();
|
2017-07-04 23:13:02 +08:00
|
|
|
std::string CurrentActivity = ("loading file '" + Filename + "'").str();
|
2016-03-09 09:37:22 +08:00
|
|
|
auto InputOrErr = MemoryBuffer::getFile(Filename);
|
|
|
|
error(InputOrErr, "error " + CurrentActivity);
|
|
|
|
InputBuffers.push_back(std::move(*InputOrErr));
|
|
|
|
}
|
|
|
|
return InputBuffers;
|
|
|
|
}
|
|
|
|
|
2016-03-15 08:04:37 +08:00
|
|
|
std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
|
2016-03-09 09:37:22 +08:00
|
|
|
if (ThinLTOIndex.empty())
|
|
|
|
report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
|
2016-11-12 03:50:39 +08:00
|
|
|
ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
|
|
|
|
"': ");
|
2017-09-08 07:28:24 +08:00
|
|
|
return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
|
|
|
|
ExitOnError ExitOnErr("llvm-lto: error loading input '" +
|
|
|
|
Buffer.getBufferIdentifier().str() + "': ");
|
|
|
|
return ExitOnErr(lto::InputFile::create(Buffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
|
|
|
|
LLVMContext &CTX) {
|
|
|
|
auto &Mod = File.getSingleBitcodeModule();
|
|
|
|
auto ModuleOrErr = Mod.parseModule(CTX);
|
|
|
|
if (!ModuleOrErr) {
|
|
|
|
handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
|
|
|
|
SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
|
|
|
|
SourceMgr::DK_Error, EIB.message());
|
|
|
|
Err.print("llvm-lto", errs());
|
|
|
|
});
|
|
|
|
report_fatal_error("Can't load module, abort.");
|
|
|
|
}
|
|
|
|
maybeVerifyModule(**ModuleOrErr);
|
2016-05-06 00:33:51 +08:00
|
|
|
if (ThinLTOModuleId.getNumOccurrences()) {
|
|
|
|
if (InputFilenames.size() != 1)
|
|
|
|
report_fatal_error("Can't override the module id for multiple files");
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
(*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
|
2016-05-06 00:33:51 +08:00
|
|
|
}
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
return std::move(*ModuleOrErr);
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void writeModuleToFile(Module &TheModule, StringRef Filename) {
|
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
|
2016-03-09 09:37:22 +08:00
|
|
|
error(EC, "error opening the file '" + Filename + "'");
|
2016-04-20 09:04:26 +08:00
|
|
|
maybeVerifyModule(TheModule);
|
2018-02-15 03:11:32 +08:00
|
|
|
WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
class ThinLTOProcessing {
|
|
|
|
public:
|
|
|
|
ThinLTOCodeGenerator ThinGenerator;
|
|
|
|
|
|
|
|
ThinLTOProcessing(const TargetOptions &Options) {
|
2020-03-04 07:47:43 +08:00
|
|
|
ThinGenerator.setCodePICModel(codegen::getExplicitRelocModel());
|
2016-03-09 09:37:22 +08:00
|
|
|
ThinGenerator.setTargetOptions(Options);
|
2016-05-14 13:16:41 +08:00
|
|
|
ThinGenerator.setCacheDir(ThinLTOCacheDir);
|
2017-12-19 22:42:38 +08:00
|
|
|
ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
|
2018-10-03 21:00:20 +08:00
|
|
|
ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
|
2018-03-02 11:51:27 +08:00
|
|
|
ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
|
|
|
|
ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
|
2017-03-29 02:55:44 +08:00
|
|
|
ThinGenerator.setFreestanding(EnableFreestanding);
|
2016-04-24 11:18:01 +08:00
|
|
|
|
|
|
|
// Add all the exported symbols to the table of symbols to preserve.
|
|
|
|
for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
|
|
|
|
ThinGenerator.preserveSymbol(ExportedSymbols[i]);
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void run() {
|
|
|
|
switch (ThinLTOMode) {
|
|
|
|
case THINLINK:
|
|
|
|
return thinLink();
|
2016-05-10 21:48:23 +08:00
|
|
|
case THINDISTRIBUTE:
|
|
|
|
return distributedIndexes();
|
2016-05-10 23:54:09 +08:00
|
|
|
case THINEMITIMPORTS:
|
|
|
|
return emitImports();
|
2016-03-09 09:37:22 +08:00
|
|
|
case THINPROMOTE:
|
|
|
|
return promote();
|
|
|
|
case THINIMPORT:
|
|
|
|
return import();
|
2016-04-24 11:18:01 +08:00
|
|
|
case THININTERNALIZE:
|
|
|
|
return internalize();
|
2016-03-09 09:37:22 +08:00
|
|
|
case THINOPT:
|
|
|
|
return optimize();
|
|
|
|
case THINCODEGEN:
|
|
|
|
return codegen();
|
|
|
|
case THINALL:
|
|
|
|
return runAll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Load the input files, create the combined index, and write it out.
|
|
|
|
void thinLink() {
|
|
|
|
// Perform "ThinLink": just produce the index
|
|
|
|
if (OutputFilename.empty())
|
|
|
|
report_fatal_error(
|
|
|
|
"OutputFilename is necessary to store the combined index.\n");
|
|
|
|
|
|
|
|
LLVMContext Ctx;
|
|
|
|
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
|
|
|
|
for (unsigned i = 0; i < InputFilenames.size(); ++i) {
|
|
|
|
auto &Filename = InputFilenames[i];
|
2017-07-04 23:13:02 +08:00
|
|
|
std::string CurrentActivity = "loading file '" + Filename + "'";
|
2016-03-09 09:37:22 +08:00
|
|
|
auto InputOrErr = MemoryBuffer::getFile(Filename);
|
|
|
|
error(InputOrErr, "error " + CurrentActivity);
|
|
|
|
InputBuffers.push_back(std::move(*InputOrErr));
|
|
|
|
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto CombinedIndex = ThinGenerator.linkCombinedIndex();
|
2016-10-08 12:44:18 +08:00
|
|
|
if (!CombinedIndex)
|
|
|
|
report_fatal_error("ThinLink didn't create an index");
|
2016-03-09 09:37:22 +08:00
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
|
2016-03-09 09:37:22 +08:00
|
|
|
error(EC, "error opening the file '" + OutputFilename + "'");
|
[ThinLTO] Support for reference graph in per-module and combined summary.
Summary:
This patch adds support for including a full reference graph including
call graph edges and other GV references in the summary.
The reference graph edges can be used to make importing decisions
without materializing any source modules, can be used in the plugin
to make file staging decisions for distributed build systems, and is
expected to have other uses.
The call graph edges are recorded in each function summary in the
bitcode via a list of <CalleeValueIds, StaticCount> tuples when no PGO
data exists, or <CalleeValueId, StaticCount, ProfileCount> pairs when
there is PGO, where the ValueId can be mapped to the function GUID via
the ValueSymbolTable. In the function index in memory, the call graph
edges reference the target via the CalleeGUID instead of the
CalleeValueId.
The reference graph edges are recorded in each summary record with a
list of referenced value IDs, which can be mapped to value GUID via the
ValueSymbolTable.
Addtionally, a new summary record type is added to record references
from global variable initializers. A number of bitcode records and data
structures have been renamed to reflect the newly expanded scope of the
summary beyond functions. More cleanup will follow.
Reviewers: joker.eph, davidxl
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17212
llvm-svn: 263275
2016-03-12 02:52:24 +08:00
|
|
|
WriteIndexToFile(*CombinedIndex, OS);
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
|
2016-05-10 21:48:23 +08:00
|
|
|
/// Load the combined index from disk, then compute and generate
|
|
|
|
/// individual index files suitable for ThinLTO distributed backend builds
|
|
|
|
/// on the files mentioned on the command line (these must match the index
|
|
|
|
/// content).
|
|
|
|
void distributedIndexes() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
|
2016-05-17 22:45:30 +08:00
|
|
|
std::string OldPrefix, NewPrefix;
|
|
|
|
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
|
|
|
|
|
2016-05-10 21:48:23 +08:00
|
|
|
auto Index = loadCombinedIndex();
|
|
|
|
for (auto &Filename : InputFilenames) {
|
[ThinLTO] Import local variables from the same module as caller
Summary:
We can sometimes end up with multiple copies of a local variable that
have the same GUID in the index. This happens when there are local
variables with the same name that are in different source files having the
same name/path at compile time (but compiled into different bitcode objects).
In this case make sure we import the copy in the caller's module.
This enables importing both of the variables having the same GUID
(but which will have different promoted names since the module paths,
and therefore the module hashes, will be distinct).
Importing the wrong copy is particularly problematic for read only
variables, since we must import them as a local copy whenever
referenced. Otherwise we get undefs at link time.
Note that the llvm-lto.cpp and ThinLTOCodeGenerator changes are needed
for testing the distributed index case via clang, which will be sent as
a separate clang-side patch shortly. We were previously not doing the
dead code/read only computation before computing imports when testing
distributed index generation (like it was for testing importing and
other ThinLTO mechanisms alone).
Reviewers: evgeny777
Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D55047
llvm-svn: 347886
2018-11-30 01:02:42 +08:00
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
[ThinLTO] Import local variables from the same module as caller
Summary:
We can sometimes end up with multiple copies of a local variable that
have the same GUID in the index. This happens when there are local
variables with the same name that are in different source files having the
same name/path at compile time (but compiled into different bitcode objects).
In this case make sure we import the copy in the caller's module.
This enables importing both of the variables having the same GUID
(but which will have different promoted names since the module paths,
and therefore the module hashes, will be distinct).
Importing the wrong copy is particularly problematic for read only
variables, since we must import them as a local copy whenever
referenced. Otherwise we get undefs at link time.
Note that the llvm-lto.cpp and ThinLTOCodeGenerator changes are needed
for testing the distributed index case via clang, which will be sent as
a separate clang-side patch shortly. We were previously not doing the
dead code/read only computation before computing imports when testing
distributed index generation (like it was for testing importing and
other ThinLTO mechanisms alone).
Reviewers: evgeny777
Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D55047
llvm-svn: 347886
2018-11-30 01:02:42 +08:00
|
|
|
|
2016-05-10 21:48:23 +08:00
|
|
|
// Build a map of module to the GUIDs and summary objects that should
|
|
|
|
// be written to its index.
|
|
|
|
std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
ThinGenerator.gatherImportedSummariesForModule(
|
|
|
|
*TheModule, *Index, ModuleToSummariesForIndex, *Input);
|
2016-05-10 21:48:23 +08:00
|
|
|
|
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".thinlto.bc";
|
|
|
|
}
|
2016-05-17 22:45:30 +08:00
|
|
|
OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
|
2016-05-10 21:48:23 +08:00
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
|
2016-05-10 21:48:23 +08:00
|
|
|
error(EC, "error opening the file '" + OutputName + "'");
|
|
|
|
WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 23:54:09 +08:00
|
|
|
/// Load the combined index from disk, compute the imports, and emit
|
|
|
|
/// the import file lists for each module to disk.
|
|
|
|
void emitImports() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
|
2016-05-17 22:45:30 +08:00
|
|
|
std::string OldPrefix, NewPrefix;
|
|
|
|
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
|
|
|
|
|
2016-05-10 23:54:09 +08:00
|
|
|
auto Index = loadCombinedIndex();
|
|
|
|
for (auto &Filename : InputFilenames) {
|
[ThinLTO] Import local variables from the same module as caller
Summary:
We can sometimes end up with multiple copies of a local variable that
have the same GUID in the index. This happens when there are local
variables with the same name that are in different source files having the
same name/path at compile time (but compiled into different bitcode objects).
In this case make sure we import the copy in the caller's module.
This enables importing both of the variables having the same GUID
(but which will have different promoted names since the module paths,
and therefore the module hashes, will be distinct).
Importing the wrong copy is particularly problematic for read only
variables, since we must import them as a local copy whenever
referenced. Otherwise we get undefs at link time.
Note that the llvm-lto.cpp and ThinLTOCodeGenerator changes are needed
for testing the distributed index case via clang, which will be sent as
a separate clang-side patch shortly. We were previously not doing the
dead code/read only computation before computing imports when testing
distributed index generation (like it was for testing importing and
other ThinLTO mechanisms alone).
Reviewers: evgeny777
Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D55047
llvm-svn: 347886
2018-11-30 01:02:42 +08:00
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
2016-05-10 23:54:09 +08:00
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".imports";
|
|
|
|
}
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
OutputName =
|
|
|
|
getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
|
|
|
|
ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
|
2016-05-10 23:54:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
/// Load the combined index from disk, then load every file referenced by
|
|
|
|
/// the index and add them to the generator, finally perform the promotion
|
|
|
|
/// on the files mentioned on the command line (these must match the index
|
|
|
|
/// content).
|
|
|
|
void promote() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
|
|
|
|
auto Index = loadCombinedIndex();
|
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
2016-03-09 09:37:22 +08:00
|
|
|
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
ThinGenerator.promote(*TheModule, *Index, *Input);
|
2016-03-09 09:37:22 +08:00
|
|
|
|
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".thinlto.promoted.bc";
|
|
|
|
}
|
|
|
|
writeModuleToFile(*TheModule, OutputName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Load the combined index from disk, then load every file referenced by
|
|
|
|
/// the index and add them to the generator, then performs the promotion and
|
|
|
|
/// cross module importing on the files mentioned on the command line
|
|
|
|
/// (these must match the index content).
|
|
|
|
void import() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
|
|
|
|
auto Index = loadCombinedIndex();
|
|
|
|
auto InputBuffers = loadAllFilesForIndex(*Index);
|
|
|
|
for (auto &MemBuffer : InputBuffers)
|
|
|
|
ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
|
|
|
|
MemBuffer->getBuffer());
|
|
|
|
|
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
2016-03-09 09:37:22 +08:00
|
|
|
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
|
2016-03-09 09:37:22 +08:00
|
|
|
|
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".thinlto.imported.bc";
|
|
|
|
}
|
|
|
|
writeModuleToFile(*TheModule, OutputName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 11:18:01 +08:00
|
|
|
void internalize() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
|
|
|
|
if (ExportedSymbols.empty())
|
|
|
|
errs() << "Warning: -internalize will not perform without "
|
|
|
|
"-exported-symbol\n";
|
|
|
|
|
|
|
|
auto Index = loadCombinedIndex();
|
|
|
|
auto InputBuffers = loadAllFilesForIndex(*Index);
|
|
|
|
for (auto &MemBuffer : InputBuffers)
|
|
|
|
ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
|
|
|
|
MemBuffer->getBuffer());
|
|
|
|
|
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
2016-04-24 11:18:01 +08:00
|
|
|
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
ThinGenerator.internalize(*TheModule, *Index, *Input);
|
2016-04-24 11:18:01 +08:00
|
|
|
|
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".thinlto.internalized.bc";
|
|
|
|
}
|
|
|
|
writeModuleToFile(*TheModule, OutputName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
void optimize() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
if (!ThinLTOIndex.empty())
|
|
|
|
errs() << "Warning: -thinlto-index ignored for optimize stage";
|
|
|
|
|
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
LLVMContext Ctx;
|
[ThinLTO] Fix ThinLTOCodegenerator to export llvm.used symbols
Summary:
Reapply r357931 with fixes to ThinLTO testcases and llvm-lto tool.
ThinLTOCodeGenerator currently does not preserve llvm.used symbols and
it can internalize them. In order to pass the necessary information to the
legacy ThinLTOCodeGenerator, the input to the code generator is
rewritten to be based on lto::InputFile.
Now ThinLTO using the legacy LTO API will requires data layout in
Module.
"internalize" thinlto action in llvm-lto is updated to run both
"promote" and "internalize" with the same configuration as
ThinLTOCodeGenerator. The old "promote" + "internalize" option does not
produce the same output as ThinLTOCodeGenerator.
This fixes: PR41236
rdar://problem/49293439
Reviewers: tejohnson, pcc, kromanova, dexonsmith
Reviewed By: tejohnson
Subscribers: ormris, bd1976llvm, mehdi_amini, inglorion, eraman, hiraditya, jkorous, dexonsmith, arphaman, dang, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60421
llvm-svn: 358601
2019-04-18 01:38:09 +08:00
|
|
|
auto Buffer = loadFile(Filename);
|
|
|
|
auto Input = loadInputFile(Buffer->getMemBufferRef());
|
|
|
|
auto TheModule = loadModuleFromInput(*Input, Ctx);
|
2016-03-09 09:37:22 +08:00
|
|
|
|
|
|
|
ThinGenerator.optimize(*TheModule);
|
|
|
|
|
|
|
|
std::string OutputName = OutputFilename;
|
|
|
|
if (OutputName.empty()) {
|
|
|
|
OutputName = Filename + ".thinlto.imported.bc";
|
|
|
|
}
|
|
|
|
writeModuleToFile(*TheModule, OutputName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void codegen() {
|
|
|
|
if (InputFilenames.size() != 1 && !OutputFilename.empty())
|
|
|
|
report_fatal_error("Can't handle a single output filename and multiple "
|
|
|
|
"input files, do not provide an output filename and "
|
|
|
|
"the output files will be suffixed from the input "
|
|
|
|
"ones.");
|
|
|
|
if (!ThinLTOIndex.empty())
|
|
|
|
errs() << "Warning: -thinlto-index ignored for codegen stage";
|
|
|
|
|
2017-05-20 01:54:58 +08:00
|
|
|
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
|
2016-03-09 09:37:22 +08:00
|
|
|
for (auto &Filename : InputFilenames) {
|
|
|
|
LLVMContext Ctx;
|
2017-05-20 01:54:58 +08:00
|
|
|
auto InputOrErr = MemoryBuffer::getFile(Filename);
|
|
|
|
error(InputOrErr, "error " + CurrentActivity);
|
|
|
|
InputBuffers.push_back(std::move(*InputOrErr));
|
|
|
|
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
|
|
|
|
}
|
|
|
|
ThinGenerator.setCodeGenOnly(true);
|
|
|
|
ThinGenerator.run();
|
|
|
|
for (auto BinName :
|
|
|
|
zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
|
2016-03-09 09:37:22 +08:00
|
|
|
std::string OutputName = OutputFilename;
|
2017-05-20 01:54:58 +08:00
|
|
|
if (OutputName.empty())
|
|
|
|
OutputName = std::get<1>(BinName) + ".thinlto.o";
|
|
|
|
else if (OutputName == "-") {
|
|
|
|
outs() << std::get<0>(BinName)->getBuffer();
|
2016-03-09 09:37:22 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
|
2016-03-09 09:37:22 +08:00
|
|
|
error(EC, "error opening the file '" + OutputName + "'");
|
2017-05-20 01:54:58 +08:00
|
|
|
OS << std::get<0>(BinName)->getBuffer();
|
2016-03-09 09:37:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Full ThinLTO process
|
|
|
|
void runAll() {
|
|
|
|
if (!OutputFilename.empty())
|
|
|
|
report_fatal_error("Do not provide an output filename for ThinLTO "
|
|
|
|
" processing, the output files will be suffixed from "
|
|
|
|
"the input ones.");
|
|
|
|
|
|
|
|
if (!ThinLTOIndex.empty())
|
|
|
|
errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
|
|
|
|
|
|
|
|
LLVMContext Ctx;
|
|
|
|
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
|
|
|
|
for (unsigned i = 0; i < InputFilenames.size(); ++i) {
|
|
|
|
auto &Filename = InputFilenames[i];
|
2017-07-04 23:13:02 +08:00
|
|
|
std::string CurrentActivity = "loading file '" + Filename + "'";
|
2016-03-09 09:37:22 +08:00
|
|
|
auto InputOrErr = MemoryBuffer::getFile(Filename);
|
|
|
|
error(InputOrErr, "error " + CurrentActivity);
|
|
|
|
InputBuffers.push_back(std::move(*InputOrErr));
|
|
|
|
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
|
|
|
|
}
|
|
|
|
|
2016-08-16 07:24:57 +08:00
|
|
|
if (!ThinLTOSaveTempsPrefix.empty())
|
|
|
|
ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
|
2016-12-14 12:56:42 +08:00
|
|
|
|
|
|
|
if (!ThinLTOGeneratedObjectsDir.empty()) {
|
|
|
|
ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
|
|
|
|
ThinGenerator.run();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
ThinGenerator.run();
|
|
|
|
|
|
|
|
auto &Binaries = ThinGenerator.getProducedBinaries();
|
|
|
|
if (Binaries.size() != InputFilenames.size())
|
|
|
|
report_fatal_error("Number of output objects does not match the number "
|
|
|
|
"of inputs");
|
|
|
|
|
|
|
|
for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
|
|
|
|
auto OutputName = InputFilenames[BufID] + ".thinlto.o";
|
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
|
2016-03-09 09:37:22 +08:00
|
|
|
error(EC, "error opening the file '" + OutputName + "'");
|
|
|
|
OS << Binaries[BufID]->getBuffer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Load the combined index from disk, then load every file referenced by
|
|
|
|
};
|
|
|
|
|
2017-09-08 07:28:24 +08:00
|
|
|
} // end namespace thinlto
|
2016-03-09 09:37:22 +08:00
|
|
|
|
2013-09-20 06:15:52 +08:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-14 02:26:06 +08:00
|
|
|
InitLLVM X(argc, argv);
|
2013-09-20 06:15:52 +08:00
|
|
|
cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
|
|
|
|
|
2015-12-04 08:45:57 +08:00
|
|
|
if (OptLevel < '0' || OptLevel > '3')
|
|
|
|
error("optimization level must be between 0 and 3");
|
2015-03-20 06:01:00 +08:00
|
|
|
|
2013-09-25 07:52:22 +08:00
|
|
|
// Initialize the configured targets.
|
|
|
|
InitializeAllTargets();
|
|
|
|
InitializeAllTargetMCs();
|
|
|
|
InitializeAllAsmPrinters();
|
|
|
|
InitializeAllAsmParsers();
|
|
|
|
|
2013-10-01 00:39:19 +08:00
|
|
|
// set up the TargetOptions for the machine
|
2020-10-14 23:55:55 +08:00
|
|
|
TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
|
2013-10-01 00:39:19 +08:00
|
|
|
|
2015-12-04 08:45:57 +08:00
|
|
|
if (ListSymbolsOnly) {
|
|
|
|
listSymbols(Options);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-12-17 10:00:38 +08:00
|
|
|
|
2019-06-12 19:07:56 +08:00
|
|
|
if (ListDependentLibrariesOnly) {
|
|
|
|
listDependentLibraries();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-15 05:04:59 +08:00
|
|
|
if (IndexStats) {
|
|
|
|
printIndexStats();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-12 07:10:18 +08:00
|
|
|
if (CheckHasObjC) {
|
|
|
|
for (auto &Filename : InputFilenames) {
|
2016-11-12 03:50:24 +08:00
|
|
|
ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
|
|
|
|
Filename + "': ");
|
|
|
|
std::unique_ptr<MemoryBuffer> BufferOrErr =
|
|
|
|
ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
|
2016-07-12 07:10:18 +08:00
|
|
|
auto Buffer = std::move(BufferOrErr.get());
|
2017-09-08 07:28:24 +08:00
|
|
|
if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
|
2016-07-12 07:10:18 +08:00
|
|
|
outs() << "Bitcode " << Filename << " contains ObjC\n";
|
|
|
|
else
|
|
|
|
outs() << "Bitcode " << Filename << " does not contain ObjC\n";
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-19 09:13:47 +08:00
|
|
|
if (PrintMachOCPUOnly) {
|
|
|
|
printMachOCPUOnly();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-09 09:37:22 +08:00
|
|
|
if (ThinLTOMode.getNumOccurrences()) {
|
|
|
|
if (ThinLTOMode.getNumOccurrences() > 1)
|
|
|
|
report_fatal_error("You can't specify more than one -thinlto-action");
|
|
|
|
thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
|
|
|
|
ThinLTOProcessor.run();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-12-04 08:45:57 +08:00
|
|
|
if (ThinLTO) {
|
2016-03-15 08:04:37 +08:00
|
|
|
createCombinedModuleSummaryIndex();
|
2015-12-04 08:45:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-10-19 22:30:44 +08:00
|
|
|
|
2013-09-20 06:15:52 +08:00
|
|
|
unsigned BaseArg = 0;
|
|
|
|
|
2015-12-05 00:14:31 +08:00
|
|
|
LLVMContext Context;
|
2019-08-15 23:54:37 +08:00
|
|
|
Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
|
2017-09-16 04:10:09 +08:00
|
|
|
true);
|
2015-12-05 00:14:31 +08:00
|
|
|
|
|
|
|
LTOCodeGenerator CodeGen(Context);
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2014-10-02 02:36:03 +08:00
|
|
|
if (UseDiagnosticHandler)
|
|
|
|
CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
|
|
|
|
|
2020-03-04 07:47:43 +08:00
|
|
|
CodeGen.setCodePICModel(codegen::getExplicitRelocModel());
|
2017-03-29 02:55:44 +08:00
|
|
|
CodeGen.setFreestanding(EnableFreestanding);
|
2014-04-14 21:54:16 +08:00
|
|
|
|
2013-09-25 07:52:22 +08:00
|
|
|
CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
|
2013-10-01 00:39:19 +08:00
|
|
|
CodeGen.setTargetOptions(Options);
|
2016-01-19 07:35:24 +08:00
|
|
|
CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2017-09-08 07:28:24 +08:00
|
|
|
StringSet<MallocAllocator> DSOSymbolsSet;
|
2013-11-01 04:51:58 +08:00
|
|
|
for (unsigned i = 0; i < DSOSymbols.size(); ++i)
|
|
|
|
DSOSymbolsSet.insert(DSOSymbols[i]);
|
|
|
|
|
|
|
|
std::vector<std::string> KeptDSOSyms;
|
|
|
|
|
2013-09-20 06:15:52 +08:00
|
|
|
for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
|
2015-12-05 00:14:31 +08:00
|
|
|
CurrentActivity = "loading file '" + InputFilenames[i] + "'";
|
|
|
|
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
|
2016-11-03 00:43:50 +08:00
|
|
|
LTOModule::createFromFile(Context, InputFilenames[i], Options);
|
2015-12-05 00:14:31 +08:00
|
|
|
std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
|
|
|
|
CurrentActivity = "";
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2015-08-22 03:09:42 +08:00
|
|
|
unsigned NumSyms = Module->getSymbolCount();
|
|
|
|
for (unsigned I = 0; I < NumSyms; ++I) {
|
|
|
|
StringRef Name = Module->getSymbolName(I);
|
|
|
|
if (!DSOSymbolsSet.count(Name))
|
|
|
|
continue;
|
|
|
|
lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
|
|
|
|
unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
|
|
|
|
if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
|
2020-01-29 03:23:46 +08:00
|
|
|
KeptDSOSyms.push_back(std::string(Name));
|
2015-08-22 03:09:42 +08:00
|
|
|
}
|
2015-02-24 08:45:56 +08:00
|
|
|
|
|
|
|
// We use the first input module as the destination module when
|
|
|
|
// SetMergedModule is true.
|
|
|
|
if (SetMergedModule && i == BaseArg) {
|
|
|
|
// Transfer ownership to the code generator.
|
2015-08-25 06:22:53 +08:00
|
|
|
CodeGen.setModule(std::move(Module));
|
2015-09-12 04:01:53 +08:00
|
|
|
} else if (!CodeGen.addModule(Module.get())) {
|
|
|
|
// Print a message here so that we know addModule() did not abort.
|
2016-04-14 06:08:26 +08:00
|
|
|
error("error adding file '" + InputFilenames[i] + "'");
|
2015-09-12 04:01:53 +08:00
|
|
|
}
|
2013-09-20 06:15:52 +08:00
|
|
|
}
|
|
|
|
|
2013-10-02 22:12:56 +08:00
|
|
|
// Add all the exported symbols to the table of symbols to preserve.
|
|
|
|
for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
|
2016-11-03 00:43:50 +08:00
|
|
|
CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
|
2013-10-02 22:12:56 +08:00
|
|
|
|
2013-10-04 02:29:09 +08:00
|
|
|
// Add all the dso symbols to the table of symbols to expose.
|
2013-11-01 04:51:58 +08:00
|
|
|
for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
|
2016-11-03 00:43:50 +08:00
|
|
|
CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
|
2013-10-04 02:29:09 +08:00
|
|
|
|
2015-01-30 09:14:28 +08:00
|
|
|
// Set cpu and attrs strings for the default target/subtarget.
|
2020-03-04 07:47:43 +08:00
|
|
|
CodeGen.setCpu(codegen::getMCPU().c_str());
|
2015-01-30 09:14:28 +08:00
|
|
|
|
2015-03-20 06:01:00 +08:00
|
|
|
CodeGen.setOptLevel(OptLevel - '0');
|
|
|
|
|
2020-03-04 07:47:43 +08:00
|
|
|
auto MAttrs = codegen::getMAttrs();
|
|
|
|
if (!MAttrs.empty()) {
|
|
|
|
std::string attrs = join(MAttrs, ",");
|
2016-11-03 00:43:50 +08:00
|
|
|
CodeGen.setAttr(attrs);
|
2020-03-04 07:47:43 +08:00
|
|
|
}
|
2014-04-26 05:46:51 +08:00
|
|
|
|
2020-03-04 07:47:43 +08:00
|
|
|
if (auto FT = codegen::getExplicitFileType())
|
|
|
|
CodeGen.setFileType(FT.getValue());
|
2015-11-20 08:13:05 +08:00
|
|
|
|
2013-09-20 06:15:52 +08:00
|
|
|
if (!OutputFilename.empty()) {
|
2020-08-27 02:17:26 +08:00
|
|
|
if (SaveLinkedModuleFile) {
|
|
|
|
std::string ModuleFilename = OutputFilename;
|
|
|
|
ModuleFilename += ".linked.bc";
|
|
|
|
std::string ErrMsg;
|
|
|
|
|
|
|
|
if (!CodeGen.writeMergedModules(ModuleFilename))
|
|
|
|
error("writing linked module failed.");
|
|
|
|
}
|
|
|
|
|
2015-09-16 07:05:59 +08:00
|
|
|
if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
|
2015-11-18 03:48:12 +08:00
|
|
|
DisableLTOVectorization)) {
|
|
|
|
// Diagnostic messages should have been printed by the handler.
|
2016-04-14 06:08:26 +08:00
|
|
|
error("error optimizing the code");
|
2013-09-20 06:15:52 +08:00
|
|
|
}
|
|
|
|
|
2015-11-20 08:13:05 +08:00
|
|
|
if (SaveModuleFile) {
|
|
|
|
std::string ModuleFilename = OutputFilename;
|
|
|
|
ModuleFilename += ".merged.bc";
|
|
|
|
std::string ErrMsg;
|
|
|
|
|
2016-11-03 00:43:50 +08:00
|
|
|
if (!CodeGen.writeMergedModules(ModuleFilename))
|
2016-04-14 06:08:26 +08:00
|
|
|
error("writing merged module failed.");
|
2015-11-20 08:13:05 +08:00
|
|
|
}
|
|
|
|
|
2017-09-23 09:03:17 +08:00
|
|
|
std::list<ToolOutputFile> OSs;
|
2015-08-28 07:37:36 +08:00
|
|
|
std::vector<raw_pwrite_stream *> OSPtrs;
|
|
|
|
for (unsigned I = 0; I != Parallelism; ++I) {
|
|
|
|
std::string PartFilename = OutputFilename;
|
|
|
|
if (Parallelism != 1)
|
|
|
|
PartFilename += "." + utostr(I);
|
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
OSs.emplace_back(PartFilename, EC, sys::fs::OF_None);
|
2016-04-14 06:08:26 +08:00
|
|
|
if (EC)
|
|
|
|
error("error opening the file '" + PartFilename + "': " + EC.message());
|
2015-08-28 07:37:36 +08:00
|
|
|
OSPtrs.push_back(&OSs.back().os());
|
|
|
|
}
|
|
|
|
|
2016-04-14 06:08:26 +08:00
|
|
|
if (!CodeGen.compileOptimized(OSPtrs))
|
2015-11-18 03:48:12 +08:00
|
|
|
// Diagnostic messages should have been printed by the handler.
|
2016-04-14 06:08:26 +08:00
|
|
|
error("error compiling the code");
|
2013-09-20 06:15:52 +08:00
|
|
|
|
2017-09-23 09:03:17 +08:00
|
|
|
for (ToolOutputFile &OS : OSs)
|
2015-08-28 07:37:36 +08:00
|
|
|
OS.keep();
|
2013-09-20 06:15:52 +08:00
|
|
|
} else {
|
2016-04-14 06:08:26 +08:00
|
|
|
if (Parallelism != 1)
|
|
|
|
error("-j must be specified together with -o");
|
2015-08-28 07:37:36 +08:00
|
|
|
|
2016-04-14 06:08:26 +08:00
|
|
|
if (SaveModuleFile)
|
|
|
|
error(": -save-merged-module must be specified with -o");
|
2015-11-20 08:13:05 +08:00
|
|
|
|
2014-04-25 12:24:47 +08:00
|
|
|
const char *OutputName = nullptr;
|
2015-09-16 07:05:59 +08:00
|
|
|
if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
|
2016-04-14 06:08:26 +08:00
|
|
|
DisableGVNLoadPRE, DisableLTOVectorization))
|
|
|
|
error("error compiling the code");
|
2015-11-18 03:48:12 +08:00
|
|
|
// Diagnostic messages should have been printed by the handler.
|
2013-09-20 06:15:52 +08:00
|
|
|
|
|
|
|
outs() << "Wrote native object file '" << OutputName << "'\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|