1//===-- CodeGenData.cpp ---------------------------------------------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 9// This file contains support for codegen data that has stable summary which 10// can be used to optimize the code in the subsequent codegen. 12//===----------------------------------------------------------------------===// 25#define DEBUG_TYPE "cg-data" 32cl::desc(
"Emit CodeGen Data into custom sections"));
35cl::desc(
"File path to where .cgdata file is read"));
38cl::desc(
"Enable two-round ThinLTO code generation. The first round " 39"emits codegen data, while the second round uses the emitted " 40"codegen data for further optimizations."));
43const std::string &ErrMsg =
"") {
48case cgdata_error::success:
51case cgdata_error::eof:
54case cgdata_error::bad_magic:
55OS <<
"invalid codegen data (bad magic)";
57case cgdata_error::bad_header:
58OS <<
"invalid codegen data (file header is corrupt)";
60case cgdata_error::empty_cgdata:
61OS <<
"empty codegen data";
63case cgdata_error::malformed:
64OS <<
"malformed codegen data";
66case cgdata_error::unsupported_version:
67OS <<
"unsupported codegen data version";
71// If optional error message is not empty, append it to the message. 80// FIXME: This class is only here to support the transition to llvm::Error. It 81// will be removed once this transition is complete. Clients should prefer to 82// deal with the Error value directly, rather than converting to error_code. 83classCGDataErrorCategoryType :
public std::error_category {
84constchar *
name()
const noexcept
override{
return"llvm.cgdata"; }
86 std::string message(
int IE)
const override{
91}
// end anonymous namespace 94static CGDataErrorCategoryType ErrorCategory;
106constchar *CodeGenDataSectNameCommon[] = {
107#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ 112constchar *CodeGenDataSectNameCoff[] = {
113#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) \ 118constchar *CodeGenDataSectNamePrefix[] = {
119#define CG_DATA_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Prefix, 129bool AddSegmentInfo) {
130 std::string SectName;
133 SectName = CodeGenDataSectNamePrefix[CGSK];
136 SectName += CodeGenDataSectNameCoff[CGSK];
138 SectName += CodeGenDataSectNameCommon[CGSK];
143std::unique_ptr<CodeGenData> CodeGenData::Instance =
nullptr;
144std::once_flag CodeGenData::OnceFlag;
147 std::call_once(CodeGenData::OnceFlag, []() {
148 Instance = std::unique_ptr<CodeGenData>(
newCodeGenData());
151 Instance->EmitCGData =
true;
153// Initialize the global CGData if the input file name is given. 154// We do not error-out when failing to parse the input file. 155// Instead, just emit an warning message and fall back as if no CGData 159if (
Error E = ReaderOrErr.takeError()) {
163// Publish each CGData based on the data type in the header. 164auto Reader = ReaderOrErr->get();
165if (Reader->hasOutlinedHashTree())
166 Instance->publishOutlinedHashTree(Reader->releaseOutlinedHashTree());
167if (Reader->hasStableFunctionMap())
168 Instance->publishStableFunctionMap(Reader->releaseStableFunctionMap());
174namespaceIndexedCGData {
177using namespacesupport;
179static_assert(std::is_standard_layout_v<llvm::IndexedCGData::Header>,
180"The header should be standard layout type since we use offset " 181"of fields to read.");
183H.Magic = endian::readNext<uint64_t, endianness::little, unaligned>(Curr);
186H.Version = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);
189H.DataKind = endian::readNext<uint32_t, endianness::little, unaligned>(Curr);
192"Please update the offset computation below if a new field has " 193"been added to the header.");
194H.OutlinedHashTreeOffset =
195 endian::readNext<uint64_t, endianness::little, unaligned>(Curr);
197H.StableFunctionMapOffset =
198 endian::readNext<uint64_t, endianness::little, unaligned>(Curr);
203}
// end namespace IndexedCGData 207voidwarn(
Twine Message, std::string Whence, std::string Hint) {
210errs() << Whence <<
": ";
211errs() << Message <<
"\n";
227 <<
" in Task " << Task <<
"\n");
232 std::unique_ptr<CachedFileStream> &Stream = *StreamOrErr;
235/*ShouldPreserveUseListOrder=*/true);
243 <<
" in Task " << Task <<
"\n");
245 IRFiles[Task],
"in-memory IR file",
/*RequiresNullTerminator=*/false);
249Twine(
"Failed to parse optimized bitcode loaded for Task: ") +
252// Restore the original module identifier. 254return std::move(*RestoredModule);
261for (
auto File : ObjFiles) {
265 File,
"in-memory object file",
/*RequiresNullTerminator=*/false);
271 std::unique_ptr<object::ObjectFile> &Obj = BinOrErr.
get();
273 Obj.get(), GlobalOutlineRecord, GlobalStableFunctionMapRecord,
278 GlobalStableFunctionMapRecord.
finalize();
280if (!GlobalOutlineRecord.
empty())
282if (!GlobalStableFunctionMapRecord.
empty())
284 std::move(GlobalStableFunctionMapRecord.
FunctionMap));
289}
// end namespace cgdata 291}
// end namespace llvm static std::string getCGDataErrString(cgdata_error Err, const std::string &ErrMsg="")
cl::opt< bool > CodeGenDataThinLTOTwoRounds("codegen-data-thinlto-two-rounds", cl::init(false), cl::Hidden, cl::desc("Enable two-round ThinLTO code generation. The first round " "emits codegen data, while the second round uses the emitted " "codegen data for further optimizations."))
cl::opt< std::string > CodeGenDataUsePath("codegen-data-use-path", cl::init(""), cl::Hidden, cl::desc("File path to where .cgdata file is read"))
cl::opt< bool > CodeGenDataGenerate("codegen-data-generate", cl::init(false), cl::Hidden, cl::desc("Emit CodeGen Data into custom sections"))
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents a module in a bitcode file.
StringRef getModuleIdentifier() const
std::string message() const override
Return the error message as a string.
static Expected< std::unique_ptr< CodeGenDataReader > > create(const Twine &Path, vfs::FileSystem &FS)
Factory method to create an appropriately typed reader for the given codegen data file path and file ...
static Error mergeFromObjectFile(const object::ObjectFile *Obj, OutlinedHashTreeRecord &GlobalOutlineRecord, StableFunctionMapRecord &GlobalFunctionMapRecord, stable_hash *CombinedHash=nullptr)
Extract the cgdata embedded in sections from the given object file and merge them into the GlobalOutl...
static CodeGenData & getInstance()
Lightweight error class with error context and mandatory checking.
bool isA() const
Check whether one error is a subclass of another.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
This is an important class for using LLVM in a threaded context.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
A Module instance is used to store all the information related to an LLVM module.
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
A raw_ostream that writes to an std::string.
Expected< stable_hash > mergeCodeGenData(ArrayRef< StringRef > ObjectFiles)
Merge the codegen data from the scratch objects ObjectFiles from the first codegen round.
void publishOutlinedHashTree(std::unique_ptr< OutlinedHashTree > HashTree)
void warn(Error E, StringRef Whence="")
void publishStableFunctionMap(std::unique_ptr< StableFunctionMap > FunctionMap)
void saveModuleForTwoRounds(const Module &TheModule, unsigned Task, AddStreamFn AddStream)
Save TheModule before the first codegen round.
std::unique_ptr< Module > loadModuleForTwoRounds(BitcodeModule &OrigModule, unsigned Task, LLVMContext &Context, ArrayRef< StringRef > IRFiles)
Load the optimized bitcode module for the second codegen round.
initializer< Ty > init(const Ty &Val)
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)
Write the specified module to the specified raw output stream.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
std::function< Expected< std::unique_ptr< CachedFileStream > >(unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
const std::error_category & cgdata_category()
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
std::string getCodeGenDataSectionName(CGDataSectKind CGSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
static Expected< Header > readFromBuffer(const unsigned char *Curr)
std::unique_ptr< OutlinedHashTree > HashTree
void finalize(bool SkipTrim=false)
Finalize the stable function map by trimming content.
std::unique_ptr< StableFunctionMap > FunctionMap