| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| //===- FunctionIndexObjectFile.h - Function index file implementation -----===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file declares the FunctionIndexObjectFile template class. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H | ||
| #define LLVM_OBJECT_FUNCTIONINDEXOBJECTFILE_H | ||
|
|
||
| #include "llvm/Object/SymbolicFile.h" | ||
|
|
||
| namespace llvm { | ||
| class FunctionInfoIndex; | ||
|
|
||
| namespace object { | ||
| class ObjectFile; | ||
|
|
||
| /// This class is used to read just the function summary index related | ||
| /// sections out of the given object (which may contain a single module's | ||
| /// bitcode or be a combined index bitcode file). It builds a FunctionInfoIndex | ||
| /// object. | ||
| class FunctionIndexObjectFile : public SymbolicFile { | ||
| std::unique_ptr<FunctionInfoIndex> Index; | ||
|
|
||
| public: | ||
| FunctionIndexObjectFile(MemoryBufferRef Object, | ||
| std::unique_ptr<FunctionInfoIndex> I); | ||
| ~FunctionIndexObjectFile() override; | ||
|
|
||
| // TODO: Walk through FunctionMap entries for function symbols. | ||
| // However, currently these interfaces are not used by any consumers. | ||
| void moveSymbolNext(DataRefImpl &Symb) const override { | ||
| llvm_unreachable("not implemented"); | ||
| } | ||
| std::error_code printSymbolName(raw_ostream &OS, | ||
| DataRefImpl Symb) const override { | ||
| llvm_unreachable("not implemented"); | ||
| return std::error_code(); | ||
| } | ||
| uint32_t getSymbolFlags(DataRefImpl Symb) const override { | ||
| llvm_unreachable("not implemented"); | ||
| return 0; | ||
| } | ||
| basic_symbol_iterator symbol_begin_impl() const override { | ||
| llvm_unreachable("not implemented"); | ||
| return basic_symbol_iterator(BasicSymbolRef()); | ||
| } | ||
| basic_symbol_iterator symbol_end_impl() const override { | ||
| llvm_unreachable("not implemented"); | ||
| return basic_symbol_iterator(BasicSymbolRef()); | ||
| } | ||
|
|
||
| const FunctionInfoIndex &getIndex() const { | ||
| return const_cast<FunctionIndexObjectFile *>(this)->getIndex(); | ||
| } | ||
| FunctionInfoIndex &getIndex() { return *Index; } | ||
| std::unique_ptr<FunctionInfoIndex> takeIndex(); | ||
|
|
||
| static inline bool classof(const Binary *v) { return v->isFunctionIndex(); } | ||
|
|
||
| /// \brief Finds and returns bitcode embedded in the given object file, or an | ||
| /// error code if not found. | ||
| static ErrorOr<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); | ||
|
|
||
| /// \brief Finds and returns bitcode in the given memory buffer (which may | ||
| /// be either a bitcode file or a native object file with embedded bitcode), | ||
| /// or an error code if not found. | ||
| static ErrorOr<MemoryBufferRef> findBitcodeInMemBuffer( | ||
| MemoryBufferRef Object); | ||
|
|
||
| /// \brief Looks for function summary in the given memory buffer, | ||
| /// returns true if found, else false. | ||
| static bool hasFunctionSummaryInMemBuffer(MemoryBufferRef Object, | ||
| LLVMContext &Context); | ||
|
|
||
| /// \brief Parse function index in the given memory buffer. | ||
| /// Return new FunctionIndexObjectFile instance containing parsed function | ||
| /// summary/index. | ||
| static ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> create( | ||
| MemoryBufferRef Object, LLVMContext &Context, bool IsLazy = false); | ||
|
|
||
| /// \brief Parse the function summary information for function with the | ||
| /// given name out of the given buffer. Parsed information is | ||
| /// stored on the index object saved in this object. | ||
| std::error_code findFunctionSummaryInMemBuffer(MemoryBufferRef Object, | ||
| LLVMContext &Context, | ||
| StringRef FunctionName); | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| //===-- FunctionInfo.cpp - Function Info Index ----------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file implements the function info index and summary classes for the | ||
| // IR library. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/IR/FunctionInfo.h" | ||
| #include "llvm/ADT/StringMap.h" | ||
| using namespace llvm; | ||
|
|
||
| // Create the combined function index/summary from multiple | ||
| // per-module instances. | ||
| void FunctionInfoIndex::mergeFrom(std::unique_ptr<FunctionInfoIndex> Other, | ||
| uint64_t NextModuleId) { | ||
|
|
||
| StringRef ModPath; | ||
| for (auto &OtherFuncInfoLists : *Other) { | ||
| StringRef FuncName = OtherFuncInfoLists.getKey(); | ||
| FunctionInfoList &List = OtherFuncInfoLists.second; | ||
|
|
||
| // Assert that the func info list only has one entry, since we shouldn't | ||
| // have duplicate names within a single per-module index. | ||
| assert(List.size() == 1); | ||
| std::unique_ptr<FunctionInfo> Info = std::move(List.front()); | ||
|
|
||
| // Add the module path string ref for this module if we haven't already | ||
| // saved a reference to it. | ||
| if (ModPath.empty()) | ||
| ModPath = | ||
| addModulePath(Info->functionSummary()->modulePath(), NextModuleId); | ||
| else | ||
| assert(ModPath == Info->functionSummary()->modulePath() && | ||
| "Each module in the combined map should have a unique ID"); | ||
|
|
||
| // Note the module path string ref was copied above and is still owned by | ||
| // the original per-module index. Reset it to the new module path | ||
| // string reference owned by the combined index. | ||
| Info->functionSummary()->setModulePath(ModPath); | ||
|
|
||
| // If it is a local function, rename it. | ||
| if (Info->functionSummary()->isLocalFunction()) { | ||
| // Any local functions are virtually renamed when being added to the | ||
| // combined index map, to disambiguate from other functions with | ||
| // the same name. The symbol table created for the combined index | ||
| // file should contain the renamed symbols. | ||
| FuncName = | ||
| FunctionInfoIndex::getGlobalNameForLocal(FuncName, NextModuleId); | ||
| } | ||
|
|
||
| // Add new function info to existing list. There may be duplicates when | ||
| // combining FunctionMap entries, due to COMDAT functions. Any local | ||
| // functions were virtually renamed above. | ||
| addFunctionInfo(FuncName, std::move(Info)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| //===- FunctionIndexObjectFile.cpp - Function index file implementation ----===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the FunctionIndexObjectFile class implementation. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/Object/FunctionIndexObjectFile.h" | ||
| #include "llvm/ADT/STLExtras.h" | ||
| #include "llvm/Bitcode/ReaderWriter.h" | ||
| #include "llvm/IR/FunctionInfo.h" | ||
| #include "llvm/MC/MCStreamer.h" | ||
| #include "llvm/Object/ObjectFile.h" | ||
| #include "llvm/Support/MemoryBuffer.h" | ||
| #include "llvm/Support/raw_ostream.h" | ||
| using namespace llvm; | ||
| using namespace object; | ||
|
|
||
| FunctionIndexObjectFile::FunctionIndexObjectFile( | ||
| MemoryBufferRef Object, std::unique_ptr<FunctionInfoIndex> I) | ||
| : SymbolicFile(Binary::ID_FunctionIndex, Object), Index(std::move(I)) {} | ||
|
|
||
| FunctionIndexObjectFile::~FunctionIndexObjectFile() {} | ||
|
|
||
| std::unique_ptr<FunctionInfoIndex> FunctionIndexObjectFile::takeIndex() { | ||
| return std::move(Index); | ||
| } | ||
|
|
||
| ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInObject( | ||
| const ObjectFile &Obj) { | ||
| for (const SectionRef &Sec : Obj.sections()) { | ||
| StringRef SecName; | ||
| if (std::error_code EC = Sec.getName(SecName)) return EC; | ||
| if (SecName == ".llvmbc") { | ||
| StringRef SecContents; | ||
| if (std::error_code EC = Sec.getContents(SecContents)) return EC; | ||
| return MemoryBufferRef(SecContents, Obj.getFileName()); | ||
| } | ||
| } | ||
|
|
||
| return object_error::bitcode_section_not_found; | ||
| } | ||
|
|
||
| ErrorOr<MemoryBufferRef> FunctionIndexObjectFile::findBitcodeInMemBuffer( | ||
| MemoryBufferRef Object) { | ||
| sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); | ||
| switch (Type) { | ||
| case sys::fs::file_magic::bitcode: | ||
| return Object; | ||
| case sys::fs::file_magic::elf_relocatable: | ||
| case sys::fs::file_magic::macho_object: | ||
| case sys::fs::file_magic::coff_object: { | ||
| ErrorOr<std::unique_ptr<ObjectFile>> ObjFile = | ||
| ObjectFile::createObjectFile(Object, Type); | ||
| if (!ObjFile) return ObjFile.getError(); | ||
| return findBitcodeInObject(*ObjFile->get()); | ||
| } | ||
| default: | ||
| return object_error::invalid_file_type; | ||
| } | ||
| } | ||
|
|
||
| // Looks for function index in the given memory buffer. | ||
| // returns true if found, else false. | ||
| bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer( | ||
| MemoryBufferRef Object, LLVMContext &Context) { | ||
| ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); | ||
| if (!BCOrErr) return false; | ||
|
|
||
| return hasFunctionSummary(BCOrErr.get(), Context, nullptr); | ||
| } | ||
|
|
||
| // Parse function index in the given memory buffer. | ||
| // Return new FunctionIndexObjectFile instance containing parsed | ||
| // function summary/index. | ||
| ErrorOr<std::unique_ptr<FunctionIndexObjectFile>> | ||
| FunctionIndexObjectFile::create(MemoryBufferRef Object, LLVMContext &Context, | ||
| bool IsLazy) { | ||
| std::unique_ptr<FunctionInfoIndex> Index; | ||
|
|
||
| ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); | ||
| if (!BCOrErr) return BCOrErr.getError(); | ||
|
|
||
| ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr = | ||
| getFunctionInfoIndex(BCOrErr.get(), Context, nullptr, IsLazy); | ||
|
|
||
| if (std::error_code EC = IOrErr.getError()) return EC; | ||
|
|
||
| Index = std::move(IOrErr.get()); | ||
|
|
||
| return llvm::make_unique<FunctionIndexObjectFile>(Object, std::move(Index)); | ||
| } | ||
|
|
||
| // Parse the function summary information for function with the | ||
| // given name out of the given buffer. Parsed information is | ||
| // stored on the index object saved in this object. | ||
| std::error_code FunctionIndexObjectFile::findFunctionSummaryInMemBuffer( | ||
| MemoryBufferRef Object, LLVMContext &Context, StringRef FunctionName) { | ||
| sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); | ||
| switch (Type) { | ||
| case sys::fs::file_magic::bitcode: { | ||
| return readFunctionSummary(Object, Context, nullptr, FunctionName, | ||
| std::move(Index)); | ||
| } | ||
| default: | ||
| return object_error::invalid_file_type; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| ; RUN: llvm-as -function-summary < %s | llvm-bcanalyzer -dump | FileCheck %s -check-prefix=BC | ||
| ; Check for function summary block/records. | ||
|
|
||
| ; BC: <FUNCTION_SUMMARY_BLOCK | ||
| ; BC-NEXT: <PERMODULE_ENTRY | ||
| ; BC-NEXT: <PERMODULE_ENTRY | ||
| ; BC-NEXT: <PERMODULE_ENTRY | ||
| ; BC-NEXT: </FUNCTION_SUMMARY_BLOCK | ||
|
|
||
| ; RUN: llvm-as -function-summary < %s | llvm-dis | FileCheck %s | ||
| ; Check that this round-trips correctly. | ||
|
|
||
| ; ModuleID = '<stdin>' | ||
| target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
| target triple = "x86_64-unknown-linux-gnu" | ||
|
|
||
| ; CHECK: define i32 @foo() | ||
|
|
||
| ; Function Attrs: nounwind uwtable | ||
| define i32 @foo() #0 { | ||
| entry: | ||
| ret i32 1 | ||
| } | ||
|
|
||
| ; CHECK: define i32 @bar(i32 %x) | ||
|
|
||
| ; Function Attrs: nounwind uwtable | ||
| define i32 @bar(i32 %x) #0 { | ||
| entry: | ||
| ret i32 %x | ||
| } | ||
|
|
||
| ; Check an anonymous function as well, since in that case only the alias | ||
| ; ends up in the value symbol table and having a summary. | ||
| @f = alias void (), void ()* @0 ; <void ()*> [#uses=0] | ||
| @h = external global void ()* ; <void ()*> [#uses=0] | ||
|
|
||
| define internal void @0() nounwind { | ||
| entry: | ||
| store void()* @0, void()** @h | ||
| br label %return | ||
|
|
||
| return: ; preds = %entry | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| define void @g() { | ||
| entry: | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ; RUN: llvm-as -function-summary %s -o %t.o | ||
| ; RUN: llvm-as -function-summary %p/Inputs/thinlto.ll -o %t2.o | ||
|
|
||
| ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ | ||
| ; RUN: --plugin-opt=thinlto \ | ||
| ; RUN: -shared %t.o %t2.o -o %t3 | ||
| ; RUN: llvm-bcanalyzer -dump %t3.thinlto.bc | FileCheck %s --check-prefix=COMBINED | ||
| ; RUN: not test -e %t3 | ||
|
|
||
| ; COMBINED: <MODULE_STRTAB_BLOCK | ||
| ; COMBINED-NEXT: <ENTRY | ||
| ; COMBINED-NEXT: <ENTRY | ||
| ; COMBINED-NEXT: </MODULE_STRTAB_BLOCK | ||
| ; COMBINED-NEXT: <FUNCTION_SUMMARY_BLOCK | ||
| ; COMBINED-NEXT: <COMBINED_ENTRY | ||
| ; COMBINED-NEXT: <COMBINED_ENTRY | ||
| ; COMBINED-NEXT: </FUNCTION_SUMMARY_BLOCK | ||
|
|
||
| define void @f() { | ||
| entry: | ||
| ret void | ||
| } |