From dfbd76bda01e804a66c3750193f5e766e4e4cf62 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 22 Sep 2025 16:41:39 +0100 Subject: [PATCH] [Remarks] Restructure bitstream remarks to be fully standalone (#156715) Currently there are two serialization modes for bitstream Remarks: standalone and separate. The separate mode splits remark metadata (e.g. the string table) from actual remark data. The metadata is written into the object file by the AsmPrinter, while the remark data is stored in a separate remarks file. This means we can't use bitstream remarks with tools like opt that don't generate an object file. Also, it is confusing to post-process bitstream remarks files, because only the standalone files can be read by llvm-remarkutil. We always need to use dsymutil to convert the separate files to standalone files, which only works for MachO. It is not possible for clang/opt to directly emit bitstream remark files in standalone mode, because the string table can only be serialized after all remarks were emitted. Therefore, this change completely removes the separate serialization mode. Instead, the remark string table is now always written to the end of the remarks file. This requires us to tell the serializer when to finalize remark serialization. This automatically happens when the serializer goes out of scope. However, often the remark file goes out of scope before the serializer is destroyed. To diagnose this, I have added an assert to alert users that they need to explicitly call finalizeLLVMOptimizationRemarks. This change paves the way for further improvements to the remark infrastructure, including more tooling (e.g. #159784), size optimizations for bitstream remarks, and more. Pull Request: https://github.com/llvm/llvm-project/pull/156715 --- clang/lib/CodeGen/BackendUtil.cpp | 5 + clang/lib/CodeGen/CodeGenAction.cpp | 19 +- flang/lib/Frontend/FrontendActions.cpp | 5 +- llvm/docs/Remarks.rst | 127 ++---------- llvm/include/llvm/IR/LLVMRemarkStreamer.h | 72 ++++++- llvm/include/llvm/LTO/LTO.h | 5 +- llvm/include/llvm/LTO/LTOBackend.h | 3 +- .../llvm/LTO/legacy/LTOCodeGenerator.h | 2 +- .../llvm/Remarks/BitstreamRemarkContainer.h | 48 ++--- .../llvm/Remarks/BitstreamRemarkSerializer.h | 113 ++++------ llvm/include/llvm/Remarks/RemarkSerializer.h | 36 ++-- llvm/include/llvm/Remarks/RemarkStreamer.h | 9 + .../llvm/Remarks/YAMLRemarkSerializer.h | 18 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 19 +- llvm/lib/IR/LLVMRemarkStreamer.cpp | 63 ++++-- llvm/lib/LTO/LTO.cpp | 8 +- llvm/lib/LTO/LTOBackend.cpp | 6 +- llvm/lib/LTO/LTOCodeGenerator.cpp | 1 + llvm/lib/Remarks/BitstreamRemarkParser.cpp | 186 +++++++++-------- llvm/lib/Remarks/BitstreamRemarkParser.h | 51 +++-- .../lib/Remarks/BitstreamRemarkSerializer.cpp | 151 +++++--------- llvm/lib/Remarks/RemarkLinker.cpp | 2 +- llvm/lib/Remarks/RemarkSerializer.cpp | 16 +- llvm/lib/Remarks/RemarkStreamer.cpp | 24 +-- llvm/lib/Remarks/YAMLRemarkParser.cpp | 6 +- llvm/lib/Remarks/YAMLRemarkSerializer.cpp | 21 +- .../optimization-remarks-passed-yaml.ll | 5 + .../ARM/remarks-linking-bundle-empty.test | 13 ++ .../dsymutil/ARM/remarks-linking-bundle.test | 81 ++++++++ llvm/test/tools/dsymutil/Inputs/basic1.c | 4 +- .../tmp/remarks/basic1.macho.remarks.arm64.o | Bin 0 -> 2008 bytes .../basic1.macho.remarks.arm64.opt.yaml | 47 +++++ .../basic1.macho.remarks.empty.arm64.o | Bin 0 -> 2000 bytes ...1.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/basic2.macho.remarks.arm64.o | Bin 0 -> 2816 bytes .../basic2.macho.remarks.arm64.opt.yaml | 194 ++++++++++++++++++ .../basic2.macho.remarks.empty.arm64.o | Bin 0 -> 2800 bytes ...2.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/basic3.macho.remarks.arm64.o | Bin 0 -> 2528 bytes .../basic3.macho.remarks.arm64.opt.yaml | 181 ++++++++++++++++ .../basic3.macho.remarks.empty.arm64.o | Bin 0 -> 2584 bytes ...3.macho.remarks.empty.arm64.opt.bitstream} | 0 .../tmp/remarks/fat.macho.remarks.x86.o | Bin 0 -> 34800 bytes .../remarks/fat.macho.remarks.x86_64.opt.yaml | 53 +++++ .../fat.macho.remarks.x86_64h.opt.yaml | 53 +++++ .../Inputs/remarks/basic.macho.remarks.arm64 | Bin 0 -> 34216 bytes .../remarks/basic.macho.remarks.empty.arm64 | Bin 0 -> 34416 bytes .../remarks/basic.macho.remarks.empty.x86_64 | Bin 9296 -> 0 bytes .../Inputs/remarks/basic.macho.remarks.x86_64 | Bin 9280 -> 0 bytes .../basic1.macho.remarks.empty.x86_64.o | Bin 2088 -> 0 bytes .../remarks/basic1.macho.remarks.x86_64.o | Bin 2416 -> 0 bytes .../basic1.macho.remarks.x86_64.opt.bitstream | Bin 384 -> 0 bytes .../basic2.macho.remarks.empty.x86_64.o | Bin 2892 -> 0 bytes .../remarks/basic2.macho.remarks.x86_64.o | Bin 3356 -> 0 bytes .../basic2.macho.remarks.x86_64.opt.bitstream | Bin 592 -> 0 bytes .../basic3.macho.remarks.empty.x86_64.o | Bin 2624 -> 0 bytes .../remarks/basic3.macho.remarks.x86_64.o | Bin 3080 -> 0 bytes .../basic3.macho.remarks.x86_64.opt.bitstream | Bin 592 -> 0 bytes .../fat.macho.remarks.i386.opt.bitstream | Bin 372 -> 0 bytes .../Inputs/remarks/fat.macho.remarks.x86 | Bin 24876 -> 16792 bytes .../Inputs/remarks/fat.macho.remarks.x86.c | 6 +- .../Inputs/remarks/fat.macho.remarks.x86.o | Bin 14440 -> 0 bytes .../fat.macho.remarks.x86.opt.bitstream | Bin 372 -> 0 bytes .../fat.macho.remarks.x86_64.opt.bitstream | Bin 344 -> 0 bytes .../fat.macho.remarks.x86_64h.opt.bitstream | Bin 344 -> 0 bytes .../X86/remarks-linking-bundle-empty.test | 13 -- .../dsymutil/X86/remarks-linking-bundle.test | 67 ------ .../X86/remarks-linking-fat-bundle.test | 13 +- .../Inputs/two-remarks.bitstream | Bin 500 -> 512 bytes .../Inputs/two-remarks.v0.bitstream | Bin 0 -> 500 bytes llvm/test/tools/llvm-remarkutil/convert.test | 3 + llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 1 + llvm/tools/llc/llc.cpp | 4 +- llvm/tools/llvm-remarkutil/RemarkConvert.cpp | 7 +- llvm/tools/opt/optdriver.cpp | 4 +- .../Remarks/BitstreamRemarksFormatTest.cpp | 2 +- .../Remarks/BitstreamRemarksParsingTest.cpp | 14 +- .../BitstreamRemarksSerializerTest.cpp | 172 ++++++++-------- llvm/unittests/Remarks/RemarksLinkingTest.cpp | 48 +++-- .../Remarks/YAMLRemarksSerializerTest.cpp | 16 +- mlir/include/mlir/Remark/RemarkStreamer.h | 5 +- mlir/lib/Remark/RemarkStreamer.cpp | 9 +- offload/plugins-nextgen/common/src/JIT.cpp | 7 +- 83 files changed, 1275 insertions(+), 763 deletions(-) create mode 100644 llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test create mode 100644 llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.o rename llvm/test/tools/dsymutil/Inputs/{remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream => private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream} (100%) create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86_64.opt.yaml create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.yaml create mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.arm64 create mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 delete mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 delete mode 100755 llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.i386.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86_64.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86_64h.opt.bitstream delete mode 100644 llvm/test/tools/dsymutil/X86/remarks-linking-bundle-empty.test delete mode 100644 llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test create mode 100644 llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 77bf0c8251fc..106363fa83e2 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -29,6 +29,7 @@ #include "llvm/Frontend/Driver/CodeGenOptions.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/ModuleSummaryIndex.h" @@ -1384,6 +1385,10 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex, Conf.CGFileType = getCodeGenFileType(Action); break; } + + // FIXME: Both ExecuteAction and thinBackend set up optimization remarks for + // the same context. + finalizeLLVMOptimizationRemarks(M->getContext()); if (Error E = thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList, ModuleToDefinedGVSummaries[M->getModuleIdentifier()], diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index dc54c97eeae8..8e3234998df2 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -29,6 +29,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/Demangle/Demangle.h" @@ -259,19 +260,18 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) { Ctx.setDefaultTargetCPU(TargetOpts.CPU); Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); - Expected> OptRecordFileOrErr = - setupLLVMOptimizationRemarks( - Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, - CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, - CodeGenOpts.DiagnosticsHotnessThreshold); + Expected OptRecordFileOrErr = + setupLLVMOptimizationRemarks( + Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, + CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, + CodeGenOpts.DiagnosticsHotnessThreshold); if (Error E = OptRecordFileOrErr.takeError()) { reportOptRecordError(std::move(E), Diags, CodeGenOpts); return; } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + LLVMRemarkFileHandle OptRecordFile = std::move(*OptRecordFileOrErr); if (OptRecordFile && CodeGenOpts.getProfileUse() != llvm::driver::ProfileInstrKind::ProfileNone) @@ -1173,7 +1173,7 @@ void CodeGenAction::ExecuteAction() { Ctx.setDefaultTargetCPU(TargetOpts.CPU); Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); - Expected> OptRecordFileOrErr = + Expected OptRecordFileOrErr = setupLLVMOptimizationRemarks( Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, @@ -1183,8 +1183,7 @@ void CodeGenAction::ExecuteAction() { reportOptRecordError(std::move(E), Diagnostics, CodeGenOpts); return; } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + LLVMRemarkFileHandle OptRecordFile = std::move(*OptRecordFileOrErr); emitBackendOutput(CI, CI.getCodeGenOpts(), CI.getTarget().getDataLayoutString(), TheModule.get(), BA, diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index c3c53d51015a..db6b98998785 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -1352,7 +1352,7 @@ void CodeGenAction::executeAction() { std::make_unique(remarkConsumer)); // write optimization-record - llvm::Expected> optRecordFileOrErr = + llvm::Expected optRecordFileOrErr = setupLLVMOptimizationRemarks( llvmModule->getContext(), codeGenOpts.OptRecordFile, codeGenOpts.OptRecordPasses, codeGenOpts.OptRecordFormat, @@ -1364,8 +1364,7 @@ void CodeGenAction::executeAction() { return; } - std::unique_ptr optRecordFile = - std::move(*optRecordFileOrErr); + llvm::LLVMRemarkFileHandle optRecordFile = std::move(*optRecordFileOrErr); if (optRecordFile) { optRecordFile->keep(); diff --git a/llvm/docs/Remarks.rst b/llvm/docs/Remarks.rst index c89940f9ff4d..67ed94d9740f 100644 --- a/llvm/docs/Remarks.rst +++ b/llvm/docs/Remarks.rst @@ -152,26 +152,6 @@ Other tools that support remarks: .. option:: -opt-remarks-format= .. option:: -opt-remarks-with-hotness -Serialization modes -=================== - -There are two modes available for serializing remarks: - -``Separate`` - - In this mode, the remarks and the metadata are serialized separately. The - client is responsible for parsing the metadata first, then use the metadata - to correctly parse the remarks. - -``Standalone`` - - In this mode, the remarks and the metadata are serialized to the same - stream. The metadata will always come before the remarks. - - The compiler does not support emitting standalone remarks. This mode is - more suited for post-processing tools like linkers, that can merge the - remarks for one whole project. - .. _yamlremarks: YAML remarks @@ -374,27 +354,11 @@ This block can contain the following records: The remark container -------------------- -Bitstream remarks are designed to be used in two different modes: +The bitstream remark container supports multiple types: -``The separate mode`` +.. _bitstreamremarksfileexternal: - The separate mode is the mode that is typically used during compilation. It - provides a way to serialize the remark entries to a stream while some - metadata is kept in memory to be emitted in the product of the compilation - (typically, an object file). - -``The standalone mode`` - - The standalone mode is typically stored and used after the distribution of - a program. It contains all the information that allows the parsing of all - the remarks without having any external dependencies. - -In order to support multiple modes, the format introduces the concept of a -bitstream remark container type. - -.. _bitstreamremarksseparateremarksmeta: - -``SeparateRemarksMeta: the metadata emitted separately`` +``RemarksFileExternal: a link to an external remarks file`` This container type expects only a :ref:`META_BLOCK ` containing only: @@ -406,84 +370,33 @@ bitstream remark container type. clients to retrieve remarks and their associated metadata directly from intermediate products. -``SeparateRemarksFile: the remark entries emitted separately`` + The container versions of the external separate container should match in order to + have a well-formed file. - This container type expects only a :ref:`META_BLOCK ` containing only: +.. _bitstreamremarksfile: + +``RemarksFile: a standalone remarks file`` + + This container type expects a :ref:`META_BLOCK ` containing only: * :ref:`RECORD_META_CONTAINER_INFO ` * :ref:`RECORD_META_REMARK_VERSION ` - This container type expects 0 or more :ref:`REMARK_BLOCK `. + Then, this container type expects 1 or more :ref:`REMARK_BLOCK `. + If no remarks are emitted, the meta blocks are also not emitted, so the file is empty. - Typically, this is emitted in a side-file alongside an object file, and is - made to be able to stream to without increasing the memory consumption of - the compiler. This is referenced by the :ref:`RECORD_META_EXTERNAL_FILE - ` entry in the - :ref:`SeparateRemarksMeta ` container. - -When the parser tries to parse a container that contains the metadata for the -separate remarks, it should parse the version and type, then keep the string -table in memory while opening the external file, validating its metadata and -parsing the remark entries. - -The container versions from the separate container should match in order to -have a well-formed file. - -``Standalone: the metadata and the remark entries emitted together`` - - This container type expects only a :ref:`META_BLOCK ` containing only: - - * :ref:`RECORD_META_CONTAINER_INFO ` - * :ref:`RECORD_META_REMARK_VERSION ` + After the remark blocks, another :ref:`META_BLOCK ` is emitted, containing: * :ref:`RECORD_META_STRTAB ` - This container type expects 0 or more :ref:`REMARK_BLOCK `. + When the parser reads this container type, it jumps to the end of the file + to read the string table before parsing the individual remarks. -A complete output of :program:`llvm-bcanalyzer` on the different container types: + Standalone remarks files can be referenced by the + :ref:`RECORD_META_EXTERNAL_FILE ` + entry in the :ref:`RemarksFileExternal + ` container. -``SeparateRemarksMeta`` - -.. code-block:: none - - - - - blob data = 'pass\\x00key\\x00value\\x00' - blob data = '/path/to/file/name' - - -``SeparateRemarksFile`` - -.. code-block:: none - - - - - - - - - - - - - -``Standalone`` - -.. code-block:: none - - - - - - blob data = 'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x00' - - - - - - - +.. FIXME: Add complete output of :program:`llvm-bcanalyzer` on the different container types (once format changes are completed) opt-viewer ========== diff --git a/llvm/include/llvm/IR/LLVMRemarkStreamer.h b/llvm/include/llvm/IR/LLVMRemarkStreamer.h index 376acdec49fb..96cccebf0d70 100644 --- a/llvm/include/llvm/IR/LLVMRemarkStreamer.h +++ b/llvm/include/llvm/IR/LLVMRemarkStreamer.h @@ -17,6 +17,7 @@ #include "llvm/Remarks/Remark.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ToolOutputFile.h" #include #include #include @@ -82,20 +83,81 @@ struct LLVMRemarkSetupFormatError LLVMRemarkSetupFormatError>::LLVMRemarkSetupErrorInfo; }; -/// Setup optimization remarks that output to a file. -LLVM_ABI Expected> setupLLVMOptimizationRemarks( +/// RAII handle that manages the lifetime of the ToolOutputFile used to output +/// remarks. On destruction (or when calling releaseFile()), this handle ensures +/// that the optimization remarks are finalized and the RemarkStreamer is +/// correctly deregistered from the LLVMContext. +class LLVMRemarkFileHandle final { + struct Finalizer { + LLVMContext *Context; + + Finalizer(LLVMContext *Ctx) : Context(Ctx) {} + + Finalizer(const Finalizer &) = delete; + Finalizer &operator=(const Finalizer &) = delete; + + Finalizer(Finalizer &&Other) : Context(Other.Context) { + Other.Context = nullptr; + } + + Finalizer &operator=(Finalizer &&Other) { + std::swap(Context, Other.Context); + return *this; + } + + ~Finalizer() { finalize(); } + + LLVM_ABI void finalize(); + }; + + std::unique_ptr OutputFile; + Finalizer Finalize; + +public: + LLVMRemarkFileHandle() : OutputFile(nullptr), Finalize(nullptr) {} + + LLVMRemarkFileHandle(std::unique_ptr OutputFile, + LLVMContext &Ctx) + : OutputFile(std::move(OutputFile)), Finalize(&Ctx) {} + + ToolOutputFile *get() { return OutputFile.get(); } + explicit operator bool() { return bool(OutputFile); } + + /// Finalize remark emission and release the underlying ToolOutputFile. + std::unique_ptr releaseFile() { + finalize(); + return std::move(OutputFile); + } + + void finalize() { Finalize.finalize(); } + + ToolOutputFile &operator*() { return *OutputFile; } + ToolOutputFile *operator->() { return &*OutputFile; } +}; + +/// Set up optimization remarks that output to a file. The LLVMRemarkFileHandle +/// manages the lifetime of the underlying ToolOutputFile to ensure \ref +/// finalizeLLVMOptimizationRemarks() is called before the file is destroyed or +/// released from the handle. The handle must be kept alive until all remarks +/// were emitted through the remark streamer. +LLVM_ABI Expected setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0); -/// Setup optimization remarks that output directly to a raw_ostream. -/// \p OS is managed by the caller and should be open for writing as long as \p -/// Context is streaming remarks to it. +/// Set up optimization remarks that output directly to a raw_ostream. +/// \p OS is managed by the caller and must be open for writing until +/// \ref finalizeLLVMOptimizationRemarks() is called. LLVM_ABI Error setupLLVMOptimizationRemarks( LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0); +/// Finalize optimization remarks and deregister the RemarkStreamer from the \p +/// Context. This must be called before closing the (file) stream that was used +/// to set up the remarks. +LLVM_ABI void finalizeLLVMOptimizationRemarks(LLVMContext &Context); + } // end namespace llvm #endif // LLVM_IR_LLVMREMARKSTREAMER_H diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index 323c478691a9..3a9a7f7c2585 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -15,6 +15,7 @@ #ifndef LLVM_LTO_LTO_H #define LLVM_LTO_LTO_H +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/Support/Compiler.h" #include @@ -91,7 +92,7 @@ LLVM_ABI std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix, StringRef NewPrefix); /// Setup optimization remarks. -LLVM_ABI Expected> setupLLVMOptimizationRemarks( +LLVM_ABI Expected setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold = 0, int Count = -1); @@ -579,7 +580,7 @@ private: DenseSet DynamicExportSymbols; // Diagnostic optimization remarks file - std::unique_ptr DiagnosticOutputFile; + LLVMRemarkFileHandle DiagnosticOutputFile; }; /// The resolution for a symbol. The linker must provide a SymbolResolution for diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h index 86b488c764e0..48ad5aa64f61 100644 --- a/llvm/include/llvm/LTO/LTOBackend.h +++ b/llvm/include/llvm/LTO/LTOBackend.h @@ -65,8 +65,7 @@ thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream, Module &M, AddStreamFn IRAddStream = nullptr, const std::vector &CmdArgs = std::vector()); -LLVM_ABI Error -finalizeOptimizationRemarks(std::unique_ptr DiagOutputFile); +LLVM_ABI Error finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile); /// Returns the BitcodeModule that is ThinLTO. LLVM_ABI BitcodeModule *findThinLTOModule(MutableArrayRef BMs); diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h index 806d3c5bdfd7..caff198358ca 100644 --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -244,7 +244,7 @@ private: bool ShouldInternalize = EnableLTOInternalization; bool ShouldEmbedUselists = false; bool ShouldRestoreGlobalsLinkage = false; - std::unique_ptr DiagnosticOutputFile; + LLVMRemarkFileHandle DiagnosticOutputFile; std::unique_ptr StatsFile = nullptr; std::string SaveIRBeforeOptPath; diff --git a/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h b/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h index 48a148a3adc1..d4b70e54bf6b 100644 --- a/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h +++ b/llvm/include/llvm/Remarks/BitstreamRemarkContainer.h @@ -23,35 +23,35 @@ namespace remarks { /// The current version of the remark container. /// Note: this is different from the version of the remark entry. -constexpr uint64_t CurrentContainerVersion = 0; +constexpr uint64_t CurrentContainerVersion = 1; /// The magic number used for identifying remark blocks. constexpr StringLiteral ContainerMagic("RMRK"); /// Type of the remark container. -/// The remark container has two modes: -/// * separate: the metadata is separate from the remarks and points to the -/// auxiliary file that contains the remarks. -/// * standalone: the metadata and the remarks are emitted together. enum class BitstreamRemarkContainerType { - /// The metadata emitted separately. - /// This will contain the following: - /// * Container version and type - /// * String table - /// * External file - SeparateRemarksMeta, - /// The remarks emitted separately. - /// This will contain the following: - /// * Container version and type - /// * Remark version - SeparateRemarksFile, - /// Everything is emitted together. - /// This will contain the following: - /// * Container version and type - /// * Remark version - /// * String table - Standalone, - First = SeparateRemarksMeta, - Last = Standalone, + /// Emit a link to an external remarks file + /// (usually as a section of the object file, to enable discovery of all + /// remarks files from the final linked object file) + /// RemarksFileExternal: + /// | Meta: + /// | | Container info + /// | | External file + RemarksFileExternal, + /// Emit metadata and remarks into a file + /// RemarksFile: + /// | Meta: + /// | | Container info + /// | | Remark version + /// | Remarks: + /// | | Remark0 + /// | | Remark1 + /// | | Remark2 + /// | | ... + /// | Late Meta: + /// | | String table + RemarksFile, + First = RemarksFileExternal, + Last = RemarksFile }; /// The possible blocks that will be encountered in a bitstream remark diff --git a/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h b/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h index 623680033750..76e2d5b4fd3b 100644 --- a/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h +++ b/llvm/include/llvm/Remarks/BitstreamRemarkSerializer.h @@ -27,31 +27,7 @@ struct Remarks; /// Serialize the remarks to LLVM bitstream. /// This class provides ways to emit remarks in the LLVM bitstream format and /// its associated metadata. -/// -/// * The separate model: -/// Separate meta: | Container info -/// | String table -/// | External file -/// -/// Separate remarks: | Container info -/// | Remark version -/// | Remark0 -/// | Remark1 -/// | Remark2 -/// | ... -/// -/// * The standalone model: | Container info -/// | String table -/// | Remark version -/// | Remark0 -/// | Remark1 -/// | Remark2 -/// | ... -/// struct BitstreamRemarkSerializerHelper { - /// Buffer used for encoding the bitstream before writing it to the final - /// stream. - SmallVector Encoded; /// Buffer used to construct records and pass to the bitstream writer. SmallVector R; /// The Bitstream writer. @@ -73,7 +49,8 @@ struct BitstreamRemarkSerializerHelper { uint64_t RecordRemarkArgWithDebugLocAbbrevID = 0; uint64_t RecordRemarkArgWithoutDebugLocAbbrevID = 0; - BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType); + BitstreamRemarkSerializerHelper(BitstreamRemarkContainerType ContainerType, + raw_ostream &OS); // Disable copy and move: Bitstream points to Encoded, which needs special // handling during copy/move, but moving the vectors is probably useless @@ -104,20 +81,15 @@ struct BitstreamRemarkSerializerHelper { /// The block info for the remarks block. void setupRemarkBlockInfo(); - /// Emit the metadata for the remarks. - void emitMetaBlock(uint64_t ContainerVersion, - std::optional RemarkVersion, - std::optional StrTab = std::nullopt, - std::optional Filename = std::nullopt); + /// Emit the main metadata at the beginning of the file + void emitMetaBlock(std::optional Filename = std::nullopt); + + /// Emit the remaining metadata at the end of the file. Here we emit metadata + /// that is only known once all remarks were emitted. + void emitLateMetaBlock(const StringTable &StrTab); /// Emit a remark block. The string table is required. - void emitRemarkBlock(const Remark &Remark, StringTable &StrTab); - /// Finalize the writing to \p OS. - void flushToStream(raw_ostream &OS); - /// Finalize the writing to a buffer. - /// The contents of the buffer remain valid for the lifetime of the object. - /// Any call to any other function in this class will invalidate the buffer. - StringRef getBuffer(); + void emitRemark(const Remark &Remark, StringTable &StrTab); }; /// Implementation of the remark serializer using LLVM bitstream. @@ -127,68 +99,57 @@ struct BitstreamRemarkSerializer : public RemarkSerializer { /// 2) The metadata block that contains various information about the remarks /// in the file. /// 3) A number of remark blocks. + /// 4) Another metadata block for metadata that is only finalized once all + /// remarks were emitted (e.g. StrTab) - /// We need to set up 1) and 2) first, so that we can emit 3) after. This flag - /// is used to emit the first two blocks only once. - bool DidSetUp = false; - /// The helper to emit bitstream. - BitstreamRemarkSerializerHelper Helper; + /// The helper to emit bitstream. This is nullopt when the Serializer has not + /// been setup yet. + std::optional Helper; /// Construct a serializer that will create its own string table. - BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode); + BitstreamRemarkSerializer(raw_ostream &OS); /// Construct a serializer with a pre-filled string table. - BitstreamRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - StringTable StrTab); + BitstreamRemarkSerializer(raw_ostream &OS, StringTable StrTab); + + ~BitstreamRemarkSerializer() override; /// Emit a remark to the stream. This also emits the metadata associated to - /// the remarks based on the SerializerMode specified at construction. - /// This writes the serialized output to the provided stream. + /// the remarks. This writes the serialized output to the provided stream. void emit(const Remark &Remark) override; + + /// Finalize emission of remarks. This emits the late metadata block and + /// flushes internal buffers. It is safe to call this function multiple times, + /// and it is automatically executed on destruction of the Serializer. + void finalize() override; + /// The metadata serializer associated to this remark serializer. Based on the /// container type of the current serializer, the container type of the /// metadata serializer will change. - std::unique_ptr metaSerializer( - raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) override; + std::unique_ptr + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) override; static bool classof(const RemarkSerializer *S) { return S->SerializerFormat == Format::Bitstream; } + +private: + void setup(); }; /// Serializer of metadata for bitstream remarks. struct BitstreamMetaSerializer : public MetaSerializer { - /// This class can be used with [1] a pre-constructed - /// BitstreamRemarkSerializerHelper, or with [2] one that is owned by the meta - /// serializer. In case of [1], we need to be able to store a reference to the - /// object, while in case of [2] we need to store the whole object. - std::optional TmpHelper; - /// The actual helper, that can point to \p TmpHelper or to an external helper - /// object. - BitstreamRemarkSerializerHelper *Helper = nullptr; + std::optional Helper; - std::optional StrTab; - std::optional ExternalFilename; + StringRef ExternalFilename; /// Create a new meta serializer based on \p ContainerType. - BitstreamMetaSerializer( - raw_ostream &OS, BitstreamRemarkContainerType ContainerType, - std::optional StrTab = std::nullopt, - std::optional ExternalFilename = std::nullopt) - : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(nullptr), - StrTab(StrTab), ExternalFilename(ExternalFilename) { - TmpHelper.emplace(ContainerType); - Helper = &*TmpHelper; + BitstreamMetaSerializer(raw_ostream &OS, + BitstreamRemarkContainerType ContainerType, + StringRef ExternalFilename) + : MetaSerializer(OS), ExternalFilename(ExternalFilename) { + Helper.emplace(ContainerType, OS); } - /// Create a new meta serializer based on a previously built \p Helper. - BitstreamMetaSerializer( - raw_ostream &OS, BitstreamRemarkSerializerHelper &Helper, - std::optional StrTab = std::nullopt, - std::optional ExternalFilename = std::nullopt) - : MetaSerializer(OS), TmpHelper(std::nullopt), Helper(&Helper), - StrTab(StrTab), ExternalFilename(ExternalFilename) {} - void emit() override; }; diff --git a/llvm/include/llvm/Remarks/RemarkSerializer.h b/llvm/include/llvm/Remarks/RemarkSerializer.h index 05ef14ae5566..1785152b87c7 100644 --- a/llvm/include/llvm/Remarks/RemarkSerializer.h +++ b/llvm/include/llvm/Remarks/RemarkSerializer.h @@ -26,16 +26,6 @@ namespace remarks { struct Remark; -enum class SerializerMode { - Separate, // A mode where the metadata is serialized separately from the - // remarks. Typically, this is used when the remarks need to be - // streamed to a side file and the metadata is embedded into the - // final result of the compilation. - Standalone // A mode where everything can be retrieved in the same - // file/buffer. Typically, this is used for storing remarks for - // later use. -}; - struct MetaSerializer; /// This is the base class for a remark serializer. @@ -45,24 +35,27 @@ struct RemarkSerializer { Format SerializerFormat; /// The open raw_ostream that the remark diagnostics are emitted to. raw_ostream &OS; - /// The serialization mode. - SerializerMode Mode; /// The string table containing all the unique strings used in the output. /// The table can be serialized to be consumed after the compilation. std::optional StrTab; - RemarkSerializer(Format SerializerFormat, raw_ostream &OS, - SerializerMode Mode) - : SerializerFormat(SerializerFormat), OS(OS), Mode(Mode) {} + RemarkSerializer(Format SerializerFormat, raw_ostream &OS) + : SerializerFormat(SerializerFormat), OS(OS) {} - /// This is just an interface. virtual ~RemarkSerializer() = default; + + /// Finalize remark emission (e.g. finish writing metadata, flush internal + /// buffers). It is safe to call this function multiple times, and it should + /// have the same behavior as destructing the RemarkSerializer. + /// After finalizing, the behavior of emit is unspecified. + virtual void finalize() {} + /// Emit a remark to the stream. virtual void emit(const Remark &Remark) = 0; + /// Return the corresponding metadata serializer. virtual std::unique_ptr - metaSerializer(raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) = 0; + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) = 0; }; /// This is the base class for a remark metadata serializer. @@ -79,13 +72,12 @@ struct MetaSerializer { /// Create a remark serializer. LLVM_ABI Expected> -createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS); +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS); /// Create a remark serializer that uses a pre-filled string table. LLVM_ABI Expected> -createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS, remarks::StringTable StrTab); +createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab); } // end namespace remarks } // end namespace llvm diff --git a/llvm/include/llvm/Remarks/RemarkStreamer.h b/llvm/include/llvm/Remarks/RemarkStreamer.h index 5b1cc81cdbf5..dd5bfcbc7ff9 100644 --- a/llvm/include/llvm/Remarks/RemarkStreamer.h +++ b/llvm/include/llvm/Remarks/RemarkStreamer.h @@ -52,6 +52,7 @@ class RemarkStreamer final { public: RemarkStreamer(std::unique_ptr RemarkSerializer, std::optional Filename = std::nullopt); + ~RemarkStreamer(); /// Return the filename that the remark diagnostics are emitted to. std::optional getFilename() const { @@ -61,6 +62,14 @@ public: raw_ostream &getStream() { return RemarkSerializer->OS; } /// Return the serializer used for this stream. remarks::RemarkSerializer &getSerializer() { return *RemarkSerializer; } + + /// Release the underlying RemarkSerializer. Destructing the RemarkStreamer + /// will assert that the RemarkStreamer has been released, to ensure that the + /// remarks were properly finalized. + std::unique_ptr releaseSerializer() { + return std::move(RemarkSerializer); + } + /// Set a pass filter based on a regex \p Filter. /// Returns an error if the regex is invalid. Error setFilter(StringRef Filter); diff --git a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h index d80464c0fe74..69b8f9f000e1 100644 --- a/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h +++ b/llvm/include/llvm/Remarks/YAMLRemarkSerializer.h @@ -36,28 +36,22 @@ struct LLVM_ABI YAMLRemarkSerializer : public RemarkSerializer { /// The YAML streamer. yaml::Output YAMLOutput; - YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - std::optional StrTab = std::nullopt); + YAMLRemarkSerializer(raw_ostream &OS); + YAMLRemarkSerializer(raw_ostream &OS, StringTable StrTabIn); void emit(const Remark &Remark) override; - std::unique_ptr metaSerializer( - raw_ostream &OS, - std::optional ExternalFilename = std::nullopt) override; + std::unique_ptr + metaSerializer(raw_ostream &OS, StringRef ExternalFilename) override; static bool classof(const RemarkSerializer *S) { return S->SerializerFormat == Format::YAML; } - -protected: - YAMLRemarkSerializer(Format SerializerFormat, raw_ostream &OS, - SerializerMode Mode, - std::optional StrTab = std::nullopt); }; struct LLVM_ABI YAMLMetaSerializer : public MetaSerializer { - std::optional ExternalFilename; + StringRef ExternalFilename; - YAMLMetaSerializer(raw_ostream &OS, std::optional ExternalFilename) + YAMLMetaSerializer(raw_ostream &OS, StringRef ExternalFilename) : MetaSerializer(OS), ExternalFilename(ExternalFilename) {} void emit() override; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index cd14a4f57f76..57fdc8b7c5ff 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -78,6 +78,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -2508,6 +2509,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) { void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { if (!RS.needsSection()) return; + if (!RS.getFilename()) + return; MCSection *RemarksSection = OutContext.getObjectFileInfo()->getRemarksSection(); @@ -2518,20 +2521,16 @@ void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { return; } - remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer(); - - std::optional> Filename; - if (std::optional FilenameRef = RS.getFilename()) { - Filename = *FilenameRef; - sys::fs::make_absolute(*Filename); - assert(!Filename->empty() && "The filename can't be empty."); - } + SmallString<128> Filename = *RS.getFilename(); + sys::fs::make_absolute(Filename); + assert(!Filename.empty() && "The filename can't be empty."); std::string Buf; raw_string_ostream OS(Buf); + + remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer(); std::unique_ptr MetaSerializer = - Filename ? RemarkSerializer.metaSerializer(OS, Filename->str()) - : RemarkSerializer.metaSerializer(OS); + RemarkSerializer.metaSerializer(OS, Filename); MetaSerializer->emit(); // Switch to the remarks section. diff --git a/llvm/lib/IR/LLVMRemarkStreamer.cpp b/llvm/lib/IR/LLVMRemarkStreamer.cpp index 71f8d4a4b1c7..9e1e45998f2f 100644 --- a/llvm/lib/IR/LLVMRemarkStreamer.cpp +++ b/llvm/lib/IR/LLVMRemarkStreamer.cpp @@ -92,7 +92,7 @@ char LLVMRemarkSetupFileError::ID = 0; char LLVMRemarkSetupPatternError::ID = 0; char LLVMRemarkSetupFormatError::ID = 0; -Expected> llvm::setupLLVMOptimizationRemarks( +Expected llvm::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold) { @@ -102,7 +102,7 @@ Expected> llvm::setupLLVMOptimizationRemarks( Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold); if (RemarksFilename.empty()) - return nullptr; + return LLVMRemarkFileHandle(); Expected Format = remarks::parseFormat(RemarksFormat); if (Error E = Format.takeError()) @@ -119,24 +119,35 @@ Expected> llvm::setupLLVMOptimizationRemarks( return make_error(errorCodeToError(EC)); Expected> RemarkSerializer = - remarks::createRemarkSerializer( - *Format, remarks::SerializerMode::Separate, RemarksFile->os()); + remarks::createRemarkSerializer(*Format, RemarksFile->os()); if (Error E = RemarkSerializer.takeError()) return make_error(std::move(E)); - // Create the main remark streamer. - Context.setMainRemarkStreamer(std::make_unique( - std::move(*RemarkSerializer), RemarksFilename)); + auto RS = std::make_unique( + std::move(*RemarkSerializer), RemarksFilename); + + if (!RemarksPasses.empty()) + if (Error E = RS->setFilter(RemarksPasses)) { + RS->releaseSerializer(); + return make_error(std::move(E)); + } + + // Install the main remark streamer. Only install this after setting the + // filter, because this might fail. + Context.setMainRemarkStreamer(std::move(RS)); // Create LLVM's optimization remarks streamer. Context.setLLVMRemarkStreamer( std::make_unique(*Context.getMainRemarkStreamer())); - if (!RemarksPasses.empty()) - if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses)) - return make_error(std::move(E)); + return LLVMRemarkFileHandle{std::move(RemarksFile), Context}; +} - return std::move(RemarksFile); +void LLVMRemarkFileHandle::Finalizer::finalize() { + if (!Context) + return; + finalizeLLVMOptimizationRemarks(*Context); + Context = nullptr; } Error llvm::setupLLVMOptimizationRemarks( @@ -153,22 +164,34 @@ Error llvm::setupLLVMOptimizationRemarks( return make_error(std::move(E)); Expected> RemarkSerializer = - remarks::createRemarkSerializer(*Format, - remarks::SerializerMode::Separate, OS); + remarks::createRemarkSerializer(*Format, OS); if (Error E = RemarkSerializer.takeError()) return make_error(std::move(E)); - // Create the main remark streamer. - Context.setMainRemarkStreamer( - std::make_unique(std::move(*RemarkSerializer))); + auto RS = + std::make_unique(std::move(*RemarkSerializer)); + + if (!RemarksPasses.empty()) + if (Error E = RS->setFilter(RemarksPasses)) { + RS->releaseSerializer(); + return make_error(std::move(E)); + } + + // Install the main remark streamer. Only install this after setting the + // filter, because this might fail. + Context.setMainRemarkStreamer(std::move(RS)); // Create LLVM's optimization remarks streamer. Context.setLLVMRemarkStreamer( std::make_unique(*Context.getMainRemarkStreamer())); - if (!RemarksPasses.empty()) - if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses)) - return make_error(std::move(E)); - return Error::success(); } + +void llvm::finalizeLLVMOptimizationRemarks(LLVMContext &Context) { + Context.setLLVMRemarkStreamer(nullptr); + if (auto *RS = Context.getMainRemarkStreamer()) { + RS->releaseSerializer(); + Context.setMainRemarkStreamer(nullptr); + } +} diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index ce9ecc35e192..7b252627d73f 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -1290,11 +1290,11 @@ void lto::updateMemProfAttributes(Module &Mod, Error LTO::runRegularLTO(AddStreamFn AddStream) { llvm::TimeTraceScope timeScope("Run regular LTO"); + LLVMContext &CombinedCtx = RegularLTO.CombinedModule->getContext(); // Setup optimization remarks. auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( - RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename, - Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness, - Conf.RemarksHotnessThreshold); + CombinedCtx, Conf.RemarksFilename, Conf.RemarksPasses, Conf.RemarksFormat, + Conf.RemarksWithHotness, Conf.RemarksHotnessThreshold); LLVM_DEBUG(dbgs() << "Running regular LTO\n"); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); @@ -2177,7 +2177,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache, return RunBackends(SecondRoundLTO.get()); } -Expected> lto::setupLLVMOptimizationRemarks( +Expected lto::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional RemarksHotnessThreshold, int Count) { diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index ce42fc526bea..c126e8efe82b 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -540,12 +540,12 @@ static Expected initAndLookupTarget(const Config &C, return T; } -Error lto::finalizeOptimizationRemarks( - std::unique_ptr DiagOutputFile) { +Error lto::finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile) { // Make sure we flush the diagnostic remarks file in case the linker doesn't // call the global destructors before exiting. if (!DiagOutputFile) return Error::success(); + DiagOutputFile.finalize(); DiagOutputFile->keep(); DiagOutputFile->os().flush(); return Error::success(); @@ -640,7 +640,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream, auto OptimizeAndCodegen = [&](Module &Mod, TargetMachine *TM, - std::unique_ptr DiagnosticOutputFile) { + LLVMRemarkFileHandle DiagnosticOutputFile) { // Perform optimization and code generation for ThinLTO. if (!opt(Conf, TM, Task, Mod, /*IsThinLTO=*/true, /*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex, diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index d8a96f73110f..8aa404da1528 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -545,6 +545,7 @@ void LTOCodeGenerator::finishOptimizationRemarks() { if (DiagnosticOutputFile) { DiagnosticOutputFile->keep(); // FIXME: LTOCodeGenerator dtor is not invoked on Darwin + DiagnosticOutputFile.finalize(); DiagnosticOutputFile->os().flush(); } } diff --git a/llvm/lib/Remarks/BitstreamRemarkParser.cpp b/llvm/lib/Remarks/BitstreamRemarkParser.cpp index d40b40dfb2ba..33eedd6042c3 100644 --- a/llvm/lib/Remarks/BitstreamRemarkParser.cpp +++ b/llvm/lib/Remarks/BitstreamRemarkParser.cpp @@ -197,14 +197,9 @@ Error BitstreamRemarkParserHelper::parseNext() { Loc.reset(); Args.clear(); - if (Error E = expectBlock()) - return E; return parseBlock(); } -BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer) - : Stream(Buffer) {} - Error BitstreamParserHelper::expectMagic() { std::array Result; for (unsigned I = 0; I < 4; ++I) @@ -244,14 +239,57 @@ Error BitstreamParserHelper::parseBlockInfoBlock() { return Error::success(); } -Error BitstreamParserHelper::advanceToMetaBlock() { +Error BitstreamParserHelper::parseMeta() { if (Error E = expectMagic()) return E; if (Error E = parseBlockInfoBlock()) return E; + + // Parse early meta block. + if (Error E = MetaHelper.expectBlock()) + return E; + if (Error E = MetaHelper.parseBlock()) + return E; + + // Skip all Remarks blocks. + while (!Stream.AtEndOfStream()) { + auto MaybeBlockID = expectSubBlock(Stream); + if (!MaybeBlockID) + return MaybeBlockID.takeError(); + if (*MaybeBlockID == META_BLOCK_ID) + break; + if (*MaybeBlockID != REMARK_BLOCK_ID) + return error("Unexpected block between meta blocks."); + // Remember first remark block. + if (!RemarkStartBitPos) + RemarkStartBitPos = Stream.GetCurrentBitNo(); + if (Error E = Stream.SkipBlock()) + return E; + } + + // Late meta block is optional if there are no remarks. + if (Stream.AtEndOfStream()) + return Error::success(); + + // Parse late meta block. + if (Error E = MetaHelper.parseBlock()) + return E; return Error::success(); } +Error BitstreamParserHelper::parseRemark() { + if (RemarkStartBitPos) { + RemarkStartBitPos.reset(); + } else { + auto MaybeBlockID = expectSubBlock(Stream); + if (!MaybeBlockID) + return MaybeBlockID.takeError(); + if (*MaybeBlockID != REMARK_BLOCK_ID) + return make_error(); + } + return RemarksHelper->parseNext(); +} + Expected> remarks::createBitstreamParserFromMeta( StringRef Buf, std::optional ExternalFilePrependPath) { @@ -263,45 +301,52 @@ remarks::createBitstreamParserFromMeta( return std::move(Parser); } -Expected> BitstreamRemarkParser::next() { - if (ParserHelper.atEndOfStream()) - return make_error(); +BitstreamRemarkParser::BitstreamRemarkParser(StringRef Buf) + : RemarkParser(Format::Bitstream), ParserHelper(Buf) {} + +Expected> BitstreamRemarkParser::next() { + if (!IsMetaReady) { + // Container is completely empty. + if (ParserHelper->Stream.AtEndOfStream()) + return make_error(); - if (!ReadyToParseRemarks) { if (Error E = parseMeta()) return std::move(E); - ReadyToParseRemarks = true; + IsMetaReady = true; + + // Container has meta, but no remarks blocks. + if (!ParserHelper->RemarkStartBitPos) + return error( + "Container is non-empty, but does not contain any remarks blocks."); + + if (Error E = + ParserHelper->Stream.JumpToBit(*ParserHelper->RemarkStartBitPos)) + return std::move(E); + ParserHelper->RemarksHelper.emplace(ParserHelper->Stream); } - return parseRemark(); + if (Error E = ParserHelper->parseRemark()) + return std::move(E); + return processRemark(); } Error BitstreamRemarkParser::parseMeta() { - if (Error E = ParserHelper.advanceToMetaBlock()) + if (Error E = ParserHelper->parseMeta()) return E; - - BitstreamMetaParserHelper MetaHelper(ParserHelper.Stream); - if (Error E = MetaHelper.expectBlock()) - return E; - if (Error E = MetaHelper.parseBlock()) - return E; - - if (Error E = processCommonMeta(MetaHelper)) + if (Error E = processCommonMeta()) return E; switch (ContainerType) { - case BitstreamRemarkContainerType::Standalone: - return processStandaloneMeta(MetaHelper); - case BitstreamRemarkContainerType::SeparateRemarksFile: - return processSeparateRemarksFileMeta(MetaHelper); - case BitstreamRemarkContainerType::SeparateRemarksMeta: - return processSeparateRemarksMetaMeta(MetaHelper); + case BitstreamRemarkContainerType::RemarksFileExternal: + return processExternalFilePath(); + case BitstreamRemarkContainerType::RemarksFile: + return processFileContainerMeta(); } llvm_unreachable("Unknown BitstreamRemarkContainerType enum"); } -Error BitstreamRemarkParser::processCommonMeta( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processCommonMeta() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.Container) return Helper.error("Missing container info."); auto &Container = *Helper.Container; @@ -313,7 +358,16 @@ Error BitstreamRemarkParser::processCommonMeta( return Error::success(); } -Error BitstreamRemarkParser::processStrTab(BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processFileContainerMeta() { + if (Error E = processRemarkVersion()) + return E; + if (Error E = processStrTab()) + return E; + return Error::success(); +} + +Error BitstreamRemarkParser::processStrTab() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.StrTabBuf) return Helper.error("Missing string table."); // Parse and assign the string table. @@ -321,26 +375,25 @@ Error BitstreamRemarkParser::processStrTab(BitstreamMetaParserHelper &Helper) { return Error::success(); } -Error BitstreamRemarkParser::processRemarkVersion( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processRemarkVersion() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.RemarkVersion) return Helper.error("Missing remark version."); RemarkVersion = *Helper.RemarkVersion; return Error::success(); } -Error BitstreamRemarkParser::processExternalFilePath( - BitstreamMetaParserHelper &Helper) { +Error BitstreamRemarkParser::processExternalFilePath() { + auto &Helper = ParserHelper->MetaHelper; if (!Helper.ExternalFilePath) return Helper.error("Missing external file path."); - StringRef ExternalFilePath = *Helper.ExternalFilePath; SmallString<80> FullPath(ExternalFilePrependPath); - sys::path::append(FullPath, ExternalFilePath); + sys::path::append(FullPath, *Helper.ExternalFilePath); // External file: open the external file, parse it, check if its metadata - // matches the one from the separate metadata, then replace the current parser - // with the one parsing the remarks. + // matches the one from the separate metadata, then replace the current + // parser with the one parsing the remarks. ErrorOr> BufferOrErr = MemoryBuffer::getFile(FullPath); if (std::error_code EC = BufferOrErr.getError()) @@ -353,58 +406,19 @@ Error BitstreamRemarkParser::processExternalFilePath( return make_error(); // Create a separate parser used for parsing the separate file. - ParserHelper = BitstreamParserHelper(TmpRemarkBuffer->getBuffer()); - // Advance and check until we can parse the meta block. - if (Error E = ParserHelper.advanceToMetaBlock()) - return E; - // Parse the meta from the separate file. - // Note: here we overwrite the BlockInfo with the one from the file. This will - // be used to parse the rest of the file. - BitstreamMetaParserHelper SeparateMetaHelper(ParserHelper.Stream); - if (Error E = SeparateMetaHelper.expectBlock()) - return E; - if (Error E = SeparateMetaHelper.parseBlock()) + ParserHelper.emplace(TmpRemarkBuffer->getBuffer()); + if (Error E = parseMeta()) return E; - if (Error E = processCommonMeta(SeparateMetaHelper)) - return E; + if (ContainerType != BitstreamRemarkContainerType::RemarksFile) + return ParserHelper->MetaHelper.error( + "Wrong container type in external file."); - if (ContainerType != BitstreamRemarkContainerType::SeparateRemarksFile) - return SeparateMetaHelper.error("Wrong container type in external file."); - - // Process the meta from the separate file. - return processSeparateRemarksFileMeta(SeparateMetaHelper); + return Error::success(); } -Error BitstreamRemarkParser::processStandaloneMeta( - BitstreamMetaParserHelper &Helper) { - if (Error E = processStrTab(Helper)) - return E; - return processRemarkVersion(Helper); -} - -Error BitstreamRemarkParser::processSeparateRemarksFileMeta( - BitstreamMetaParserHelper &Helper) { - return processRemarkVersion(Helper); -} - -Error BitstreamRemarkParser::processSeparateRemarksMetaMeta( - BitstreamMetaParserHelper &Helper) { - if (Error E = processStrTab(Helper)) - return E; - return processExternalFilePath(Helper); -} - -Expected> BitstreamRemarkParser::parseRemark() { - BitstreamRemarkParserHelper RemarkHelper(ParserHelper.Stream); - if (Error E = RemarkHelper.parseNext()) - return std::move(E); - - return processRemark(RemarkHelper); -} - -Expected> -BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { +Expected> BitstreamRemarkParser::processRemark() { + auto &Helper = *ParserHelper->RemarksHelper; std::unique_ptr Result = std::make_unique(); Remark &R = *Result; @@ -491,5 +505,3 @@ BitstreamRemarkParser::processRemark(BitstreamRemarkParserHelper &Helper) { return std::move(Result); } -llvm::remarks::BitstreamRemarkParser::BitstreamRemarkParser(StringRef Buf) - : RemarkParser(Format::Bitstream), ParserHelper(Buf) {} diff --git a/llvm/lib/Remarks/BitstreamRemarkParser.h b/llvm/lib/Remarks/BitstreamRemarkParser.h index d756e3296a87..4f66c47bb4b2 100644 --- a/llvm/lib/Remarks/BitstreamRemarkParser.h +++ b/llvm/lib/Remarks/BitstreamRemarkParser.h @@ -187,35 +187,49 @@ struct BitstreamParserHelper { BitstreamCursor Stream; /// The block info block. BitstreamBlockInfo BlockInfo; + + /// Helper to parse the metadata blocks in this bitstream. + BitstreamMetaParserHelper MetaHelper; + /// Helper to parse the remark blocks in this bitstream. Only needed + /// for ContainerType RemarksFile. + std::optional RemarksHelper; + /// The position of the first remark block we encounter after + /// the initial metadata block. + std::optional RemarkStartBitPos; + /// Start parsing at \p Buffer. - BitstreamParserHelper(StringRef Buffer); + BitstreamParserHelper(StringRef Buffer) + : Stream(Buffer), MetaHelper(Stream), RemarksHelper(Stream) {} + /// Parse and validate the magic number. Error expectMagic(); - /// Advance to the meta block - Error advanceToMetaBlock(); /// Parse the block info block containing all the abbrevs. /// This needs to be called before calling any other parsing function. Error parseBlockInfoBlock(); - /// Return true if the parser reached the end of the stream. - bool atEndOfStream() { return Stream.AtEndOfStream(); } + + /// Parse all metadata blocks in the file. This populates the meta helper. + Error parseMeta(); + /// Parse the next remark. This populates the remark helper data. + Error parseRemark(); }; /// Parses and holds the state of the latest parsed remark. struct BitstreamRemarkParser : public RemarkParser { /// The buffer to parse. - BitstreamParserHelper ParserHelper; + std::optional ParserHelper; /// The string table used for parsing strings. std::optional StrTab; /// Temporary remark buffer used when the remarks are stored separately. std::unique_ptr TmpRemarkBuffer; + /// Whether the metadata has already been parsed, so we can continue parsing + /// remarks. + bool IsMetaReady = false; /// The common metadata used to decide how to parse the buffer. /// This is filled when parsing the metadata block. uint64_t ContainerVersion = 0; uint64_t RemarkVersion = 0; BitstreamRemarkContainerType ContainerType = - BitstreamRemarkContainerType::Standalone; - /// Wether the parser is ready to parse remarks. - bool ReadyToParseRemarks = false; + BitstreamRemarkContainerType::RemarksFile; /// Create a parser that expects to find a string table embedded in the /// stream. @@ -230,20 +244,15 @@ struct BitstreamRemarkParser : public RemarkParser { /// Parse and process the metadata of the buffer. Error parseMeta(); - /// Parse a Bitstream remark. - Expected> parseRemark(); - private: - Error processCommonMeta(BitstreamMetaParserHelper &Helper); - Error processStandaloneMeta(BitstreamMetaParserHelper &Helper); - Error processSeparateRemarksFileMeta(BitstreamMetaParserHelper &Helper); - Error processSeparateRemarksMetaMeta(BitstreamMetaParserHelper &Helper); - Error processExternalFilePath(BitstreamMetaParserHelper &Helper); - Error processStrTab(BitstreamMetaParserHelper &Helper); - Error processRemarkVersion(BitstreamMetaParserHelper &Helper); + Error processCommonMeta(); + Error processFileContainerMeta(); + Error processExternalFilePath(); - Expected> - processRemark(BitstreamRemarkParserHelper &Helper); + Expected> processRemark(); + + Error processStrTab(); + Error processRemarkVersion(); }; Expected> createBitstreamParserFromMeta( diff --git a/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp b/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp index b2627196bce6..abd436e0ee56 100644 --- a/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp +++ b/llvm/lib/Remarks/BitstreamRemarkSerializer.cpp @@ -12,25 +12,23 @@ //===----------------------------------------------------------------------===// #include "llvm/Remarks/BitstreamRemarkSerializer.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Remarks/Remark.h" +#include #include using namespace llvm; using namespace llvm::remarks; BitstreamRemarkSerializerHelper::BitstreamRemarkSerializerHelper( - BitstreamRemarkContainerType ContainerType) - : Bitstream(Encoded), ContainerType(ContainerType) {} - -static void push(SmallVectorImpl &R, StringRef Str) { - append_range(R, Str); -} + BitstreamRemarkContainerType ContainerType, raw_ostream &OS) + : Bitstream(OS), ContainerType(ContainerType) {} static void setRecordName(unsigned RecordID, BitstreamWriter &Bitstream, SmallVectorImpl &R, StringRef Str) { R.clear(); R.push_back(RecordID); - push(R, Str); + append_range(R, Str); Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETRECORDNAME, R); } @@ -41,7 +39,7 @@ static void initBlock(unsigned BlockID, BitstreamWriter &Bitstream, Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_SETBID, R); R.clear(); - push(R, Str); + append_range(R, Str); Bitstream.EmitRecord(bitc::BLOCKINFO_CODE_BLOCKNAME, R); } @@ -200,75 +198,64 @@ void BitstreamRemarkSerializerHelper::setupBlockInfo() { Bitstream.Emit(static_cast(C), 8); Bitstream.EnterBlockInfoBlock(); + auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); }); // Setup the main metadata. Depending on the container type, we'll setup the // required records next. setupMetaBlockInfo(); switch (ContainerType) { - case BitstreamRemarkContainerType::SeparateRemarksMeta: - // Needs a string table that the separate remark file is using. - setupMetaStrTab(); + case BitstreamRemarkContainerType::RemarksFileExternal: // Needs to know where the external remarks file is. setupMetaExternalFile(); - break; - case BitstreamRemarkContainerType::SeparateRemarksFile: - // Contains remarks: emit the version. - setupMetaRemarkVersion(); - // Contains remarks: emit the remark abbrevs. - setupRemarkBlockInfo(); - break; - case BitstreamRemarkContainerType::Standalone: + return; + case BitstreamRemarkContainerType::RemarksFile: // Contains remarks: emit the version. setupMetaRemarkVersion(); // Needs a string table. setupMetaStrTab(); // Contains remarks: emit the remark abbrevs. setupRemarkBlockInfo(); - break; + return; } - - Bitstream.ExitBlock(); + llvm_unreachable("Unexpected BitstreamRemarkContainerType"); } void BitstreamRemarkSerializerHelper::emitMetaBlock( - uint64_t ContainerVersion, std::optional RemarkVersion, - std::optional StrTab, std::optional Filename) { // Emit the meta block Bitstream.EnterSubblock(META_BLOCK_ID, 3); + auto ExitBlock = make_scope_exit([&] { Bitstream.ExitBlock(); }); // The container version and type. R.clear(); R.push_back(RECORD_META_CONTAINER_INFO); - R.push_back(ContainerVersion); + R.push_back(CurrentContainerVersion); R.push_back(static_cast(ContainerType)); Bitstream.EmitRecordWithAbbrev(RecordMetaContainerInfoAbbrevID, R); switch (ContainerType) { - case BitstreamRemarkContainerType::SeparateRemarksMeta: - assert(StrTab != std::nullopt && *StrTab != nullptr); - emitMetaStrTab(**StrTab); + case BitstreamRemarkContainerType::RemarksFileExternal: assert(Filename != std::nullopt); emitMetaExternalFile(*Filename); - break; - case BitstreamRemarkContainerType::SeparateRemarksFile: - assert(RemarkVersion != std::nullopt); - emitMetaRemarkVersion(*RemarkVersion); - break; - case BitstreamRemarkContainerType::Standalone: - assert(RemarkVersion != std::nullopt); - emitMetaRemarkVersion(*RemarkVersion); - assert(StrTab != std::nullopt && *StrTab != nullptr); - emitMetaStrTab(**StrTab); - break; + return; + case BitstreamRemarkContainerType::RemarksFile: + emitMetaRemarkVersion(CurrentRemarkVersion); + return; } + llvm_unreachable("Unexpected BitstreamRemarkContainerType"); +} +void BitstreamRemarkSerializerHelper::emitLateMetaBlock( + const StringTable &StrTab) { + // Emit the late meta block (after all remarks are serialized) + Bitstream.EnterSubblock(META_BLOCK_ID, 3); + emitMetaStrTab(StrTab); Bitstream.ExitBlock(); } -void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark, - StringTable &StrTab) { +void BitstreamRemarkSerializerHelper::emitRemark(const Remark &Remark, + StringTable &StrTab) { Bitstream.EnterSubblock(REMARK_BLOCK_ID, 4); R.clear(); @@ -317,73 +304,49 @@ void BitstreamRemarkSerializerHelper::emitRemarkBlock(const Remark &Remark, Bitstream.ExitBlock(); } -void BitstreamRemarkSerializerHelper::flushToStream(raw_ostream &OS) { - OS.write(Encoded.data(), Encoded.size()); - Encoded.clear(); -} - -StringRef BitstreamRemarkSerializerHelper::getBuffer() { - return StringRef(Encoded.data(), Encoded.size()); -} - -BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, - SerializerMode Mode) - : RemarkSerializer(Format::Bitstream, OS, Mode), - Helper(BitstreamRemarkContainerType::SeparateRemarksFile) { - assert(Mode == SerializerMode::Separate && - "For SerializerMode::Standalone, a pre-filled string table needs to " - "be provided."); - // We always use a string table with bitstream. +BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS) + : RemarkSerializer(Format::Bitstream, OS) { StrTab.emplace(); } BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS, - SerializerMode Mode, StringTable StrTabIn) - : RemarkSerializer(Format::Bitstream, OS, Mode), - Helper(Mode == SerializerMode::Separate - ? BitstreamRemarkContainerType::SeparateRemarksFile - : BitstreamRemarkContainerType::Standalone) { + : RemarkSerializer(Format::Bitstream, OS) { StrTab = std::move(StrTabIn); } -void BitstreamRemarkSerializer::emit(const Remark &Remark) { - if (!DidSetUp) { - // Emit the metadata that is embedded in the remark file. - // If we're in standalone mode, serialize the string table as well. - bool IsStandalone = - Helper.ContainerType == BitstreamRemarkContainerType::Standalone; - BitstreamMetaSerializer MetaSerializer( - OS, Helper, - IsStandalone ? &*StrTab - : std::optional(std::nullopt)); - MetaSerializer.emit(); - DidSetUp = true; - } +BitstreamRemarkSerializer::~BitstreamRemarkSerializer() { finalize(); } - assert(DidSetUp && - "The Block info block and the meta block were not emitted yet."); - Helper.emitRemarkBlock(Remark, *StrTab); - - Helper.flushToStream(OS); +void BitstreamRemarkSerializer::setup() { + if (Helper) + return; + Helper.emplace(BitstreamRemarkContainerType::RemarksFile, OS); + Helper->setupBlockInfo(); + Helper->emitMetaBlock(); } -std::unique_ptr BitstreamRemarkSerializer::metaSerializer( - raw_ostream &OS, std::optional ExternalFilename) { - assert(Helper.ContainerType != - BitstreamRemarkContainerType::SeparateRemarksMeta); - bool IsStandalone = - Helper.ContainerType == BitstreamRemarkContainerType::Standalone; +void BitstreamRemarkSerializer::finalize() { + if (!Helper) + return; + Helper->emitLateMetaBlock(*StrTab); + Helper = std::nullopt; +} + +void BitstreamRemarkSerializer::emit(const Remark &Remark) { + setup(); + Helper->emitRemark(Remark, *StrTab); +} + +std::unique_ptr +BitstreamRemarkSerializer::metaSerializer(raw_ostream &OS, + StringRef ExternalFilename) { return std::make_unique( - OS, - IsStandalone ? BitstreamRemarkContainerType::Standalone - : BitstreamRemarkContainerType::SeparateRemarksMeta, - &*StrTab, ExternalFilename); + OS, BitstreamRemarkContainerType::RemarksFileExternal, ExternalFilename); } void BitstreamMetaSerializer::emit() { + assert(Helper && "BitstreamMetaSerializer emitted multiple times"); Helper->setupBlockInfo(); - Helper->emitMetaBlock(CurrentContainerVersion, CurrentRemarkVersion, StrTab, - ExternalFilename); - Helper->flushToStream(OS); + Helper->emitMetaBlock(ExternalFilename); + Helper = std::nullopt; } diff --git a/llvm/lib/Remarks/RemarkLinker.cpp b/llvm/lib/Remarks/RemarkLinker.cpp index b00419bd4e51..f0feeccbfe1b 100644 --- a/llvm/lib/Remarks/RemarkLinker.cpp +++ b/llvm/lib/Remarks/RemarkLinker.cpp @@ -108,7 +108,7 @@ Error RemarkLinker::link(const object::ObjectFile &Obj, Format RemarkFormat) { Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { Expected> MaybeSerializer = - createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, + createRemarkSerializer(RemarksFormat, OS, std::move(const_cast(StrTab))); if (!MaybeSerializer) return MaybeSerializer.takeError(); diff --git a/llvm/lib/Remarks/RemarkSerializer.cpp b/llvm/lib/Remarks/RemarkSerializer.cpp index df1da53d7c8a..80388b4c47cb 100644 --- a/llvm/lib/Remarks/RemarkSerializer.cpp +++ b/llvm/lib/Remarks/RemarkSerializer.cpp @@ -18,34 +18,32 @@ using namespace llvm; using namespace llvm::remarks; Expected> -remarks::createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS) { +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS) { switch (RemarksFormat) { case Format::Unknown: case Format::Auto: return createStringError(std::errc::invalid_argument, "Invalid remark serializer format."); case Format::YAML: - return std::make_unique(OS, Mode); + return std::make_unique(OS); case Format::Bitstream: - return std::make_unique(OS, Mode); + return std::make_unique(OS); } llvm_unreachable("Unknown remarks::Format enum"); } Expected> -remarks::createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, - raw_ostream &OS, remarks::StringTable StrTab) { +remarks::createRemarkSerializer(Format RemarksFormat, raw_ostream &OS, + remarks::StringTable StrTab) { switch (RemarksFormat) { case Format::Unknown: case Format::Auto: return createStringError(std::errc::invalid_argument, "Invalid remark serializer format."); case Format::YAML: - return std::make_unique(OS, Mode, std::move(StrTab)); + return std::make_unique(OS, std::move(StrTab)); case Format::Bitstream: - return std::make_unique(OS, Mode, - std::move(StrTab)); + return std::make_unique(OS, std::move(StrTab)); } llvm_unreachable("Unknown remarks::Format enum"); } diff --git a/llvm/lib/Remarks/RemarkStreamer.cpp b/llvm/lib/Remarks/RemarkStreamer.cpp index bb62c8b5c2fd..d9be2f1fcb6a 100644 --- a/llvm/lib/Remarks/RemarkStreamer.cpp +++ b/llvm/lib/Remarks/RemarkStreamer.cpp @@ -12,6 +12,7 @@ #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Support/CommandLine.h" +#include #include using namespace llvm; @@ -31,6 +32,14 @@ RemarkStreamer::RemarkStreamer( Filename(FilenameIn ? std::optional(FilenameIn->str()) : std::nullopt) {} +RemarkStreamer::~RemarkStreamer() { + // Ensure that llvm::finalizeOptimizationRemarks was called before the + // RemarkStreamer is destroyed. + assert(!RemarkSerializer && + "RemarkSerializer must be released before RemarkStreamer is " + "destroyed. Ensure llvm::finalizeOptimizationRemarks is called."); +} + Error RemarkStreamer::setFilter(StringRef Filter) { Regex R = Regex(Filter); std::string RegexError; @@ -57,16 +66,7 @@ bool RemarkStreamer::needsSection() const { assert(EnableRemarksSection == cl::BOU_UNSET); - // We only need a section if we're in separate mode. - if (RemarkSerializer->Mode != remarks::SerializerMode::Separate) - return false; - - // Only some formats need a section: - // * bitstream - switch (RemarkSerializer->SerializerFormat) { - case remarks::Format::Bitstream: - return true; - default: - return false; - } + // Enable remark sections by default for bitstream remarks (so dsymutil can + // find all remarks for a linked binary) + return RemarkSerializer->SerializerFormat == Format::Bitstream; } diff --git a/llvm/lib/Remarks/YAMLRemarkParser.cpp b/llvm/lib/Remarks/YAMLRemarkParser.cpp index 5ff42fe6b9a9..baad378d72bd 100644 --- a/llvm/lib/Remarks/YAMLRemarkParser.cpp +++ b/llvm/lib/Remarks/YAMLRemarkParser.cpp @@ -385,7 +385,11 @@ Expected YAMLRemarkParser::parseArg(yaml::Node &Node) { if (!ValueStr) return error("argument value is missing.", *ArgMap); - return Argument{*KeyStr, *ValueStr, Loc}; + Argument Arg; + Arg.Key = *KeyStr; + Arg.Val = *ValueStr; + Arg.Loc = Loc; + return Arg; } Expected> YAMLRemarkParser::next() { diff --git a/llvm/lib/Remarks/YAMLRemarkSerializer.cpp b/llvm/lib/Remarks/YAMLRemarkSerializer.cpp index 846a72182d8f..f8b610dd7f73 100644 --- a/llvm/lib/Remarks/YAMLRemarkSerializer.cpp +++ b/llvm/lib/Remarks/YAMLRemarkSerializer.cpp @@ -19,8 +19,6 @@ using namespace llvm; using namespace llvm::remarks; -// Use the same keys whether we use a string table or not (respectively, T is an -// unsigned or a StringRef). static void mapRemarkHeader(yaml::IO &io, StringRef PassName, StringRef RemarkName, std::optional RL, StringRef FunctionName, @@ -131,10 +129,13 @@ template <> struct MappingTraits { LLVM_YAML_IS_SEQUENCE_VECTOR(Argument) -YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode, - std::optional StrTabIn) - : RemarkSerializer(Format::YAML, OS, Mode), - YAMLOutput(OS, reinterpret_cast(this)) { +YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS) + : RemarkSerializer(Format::YAML, OS), + YAMLOutput(OS, reinterpret_cast(this)) {} + +YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, + StringTable StrTabIn) + : YAMLRemarkSerializer(OS) { StrTab = std::move(StrTabIn); } @@ -145,8 +146,9 @@ void YAMLRemarkSerializer::emit(const Remark &Remark) { YAMLOutput << R; } -std::unique_ptr YAMLRemarkSerializer::metaSerializer( - raw_ostream &OS, std::optional ExternalFilename) { +std::unique_ptr +YAMLRemarkSerializer::metaSerializer(raw_ostream &OS, + StringRef ExternalFilename) { return std::make_unique(OS, ExternalFilename); } @@ -186,6 +188,5 @@ void YAMLMetaSerializer::emit() { support::endian::write64le(StrTabSizeBuf.data(), StrTabSize); OS.write(StrTabSizeBuf.data(), StrTabSizeBuf.size()); - if (ExternalFilename) - emitExternalFile(OS, *ExternalFilename); + emitExternalFile(OS, ExternalFilename); } diff --git a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll index b65ed66fcce6..b0a238ff8efe 100644 --- a/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll +++ b/llvm/test/Transforms/Inline/optimization-remarks-passed-yaml.ll @@ -8,6 +8,11 @@ ; RUN: -pass-remarks-with-hotness 2>&1 | FileCheck %s ; RUN: cat %t | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s +; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t.bitstream -pass-remarks=inline \ +; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ +; RUN: -pass-remarks-with-hotness -pass-remarks-format=bitstream 2>&1 | FileCheck %s +; RUN: llvm-remarkutil bitstream2yaml %t.bitstream | FileCheck -check-prefixes=YAML,YAML-NO-ANNOTATE %s + ; RUN: opt < %s -S -passes=inliner-wrapper -pass-remarks-output=%t -pass-remarks=inline \ ; RUN: -pass-remarks-missed=inline -pass-remarks-analysis=inline \ ; RUN: -annotate-inline-phase=false \ diff --git a/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test new file mode 100644 index 000000000000..0a89fa1ddee3 --- /dev/null +++ b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle-empty.test @@ -0,0 +1,13 @@ +RUN: rm -rf %t +RUN: mkdir -p %t +RUN: cat %p/../Inputs/remarks/basic.macho.remarks.empty.arm64 > %t/basic.macho.remarks.empty.arm64 + +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.arm64 + +Check that the remark file in the bundle does not exist: +RUN: not cat %t/basic.macho.remarks.empty.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 2>&1 + +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.arm64 + +Check that the remark file in the bundle does not exist: +RUN: not cat %t/basic.macho.remarks.empty.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.arm64 2>&1 diff --git a/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test new file mode 100644 index 000000000000..e1b04455b0d9 --- /dev/null +++ b/llvm/test/tools/dsymutil/ARM/remarks-linking-bundle.test @@ -0,0 +1,81 @@ +RUN: rm -rf %t +RUN: mkdir -p %t/private/tmp/remarks +RUN: cat %p/../Inputs/remarks/basic.macho.remarks.arm64> %t/basic.macho.remarks.arm64 +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic1.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic1.macho.remarks.arm64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic2.macho.remarks.arm64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.opt.yaml -o %t/private/tmp/remarks/basic3.macho.remarks.arm64.opt.bitstream + +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 + +Check that the remark file in the bundle exists and is sane: +RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s + +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 + +Check that the remark file in the bundle exists and is sane: +RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s + +Now emit it in a different format: YAML. +RUN: dsymutil -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 +RUN: cat %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s --check-prefix=CHECK-YAML + +RUN: dsymutil --linker parallel -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/basic.macho.remarks.arm64 +RUN: cat %t/basic.macho.remarks.arm64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.arm64 | FileCheck %s --check-prefix=CHECK-YAML + +CHECK: FP;ns6E4O?jd5o8ZGjDm_>y^VW_ISc^Yz|`pWpuM zA%qfGxcPzlaEk!J3IVNhHoNV%=5y4O=mX1@tAR(VMI|gzwA34x!#ncW>B+GT+2t4v zK|F*$2OxHEelqXc;3txe@bLJB4GR}%iK#BTiVYJMxuX!ptSZk=iIOav zY8ml|Ceov4D%Q)48*w!Om#LiF;%SAPffio8AIvSu&XFDBl`K;H88w%mBVD*{yObuU(w&`M?un6?6DW`H^a*? zk1@d8(g2Srii)8ZCB+hF3)i(m7UpHB@-tvE%sIl8%YcVtKlzXN@>)Sf7jJw;hIfhK zy=D1c-2tA6P4>*+dxjTgc%6XbSzFSN!^izVPMPW}rf7uvY4FFEuEH6C6Yr^8OUxSy zeev3`QUmv2D>!;#^gP`~NF%sa)0Zb!PNqJd>Khz)yMhP9ZO?=2cf;?};m;jypXi?9jsu^bwFPT}gml0|)eKm0kf(PDi4{$)ELm#I z(u*X)q$%CJE-BLn&y>7m>b(ixC|bO%Sx{Y7(pf6Bkw&A<0WNy)cGPTXXladp znF}?xHdU2cV1jsx?AN)_%@7xbqMRdh&G%^NE^UR%@Pv!@*ACPk4h@EmhrkUWj{yY; zCXHn~K&a1VLE`LEqU5u=0EaCC7(eMGZNRt}46n~EAV`or0$K!8@={?cQdZ59W)vdv zI4|(Rlx9Vaz;*&?dRFFPzWXgh)}&Hb$&#{p)r{ryWxcCt8Z)Y5@o1muQ+s4pNgnG- zWqXBGT}CXrnu2U3-^NUFQJ!n|V>Rg^Ti(2}XMD@7!_jtMeIQKtq07?!?=ziO%9+KpE9>d;v$CHAcJC%N6=*I>eSSdMZp=37 zgGg*aY+aZe{K~%Vc%El6-nlwE2FJJwW%w1#$1YWQzzazltikt*#X#DxnWAp{Z!&|X2}!U0fsd2c*Ui?`C|NpIfA%=>xX zdo$ywUq1ZPLWn?saHsv=w+sWa_%Z-vQS>jWIx;-2ggrGdh73#i74DuI}1L zex5$EYJ1vlt{@&lrvZd*u8u5tYfvhRO-!1uShg27i! zMafcaZbnfx&8B6^pytIbIk)2Gj*OKKd^GI86Qs?3Ssux)c|o z|2V{BOYee=fW&+1)e`eY##p>Iywsr8PXAWO^Obqw&dNS=>CZ>qOK+RWgLfkN{I)s$ z08p;1%xCVvnoEC)%FC(4Q-_2`LfT-WLAaN`Kbm^BZ+K+nVc&9PFKD+bd#_YR7BYL5 zDyij1nT6r{#`f*u&YSHY&xN04!f$#yUkNP}JzcMEbhbCO6Vd|@8VCY{T)#y~tY{l$ z)uA!REXMe=5!2L?p$|x=s-LhV?v$umbWTdDZ4MG7dE5Nim)(Pwa5?-5m z;M2gDf%Uvvn2D6BT{5gfBp#P!NuDvBNFNMo;1hG21ZR4WV`+w3>MuEJHc#zXK3_Kb zi?%gObw|SWiD5dZQ9b$7U@AK#r{elhDk;-cP9D?~i4@Jsi3HUL)#NV1OQMt5x+No~ zY7|&egDeTyqe~MYFpIV41a;&lV9Xd_XE`a$pfdmL*~L?sC6XYCTk7yfBlI$R?SK^n z`p@gFf)lrq1Str@*U&~3{HvgJqe?`fJJ1>o3qPQ7`{JkB9mmR(mk-?km^pet1I(uC zoe_J5U}!_*TyR7Ecu;H}53~T@dIx86o4s-wj literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic1.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..81a972e9510d735418d2b1a21ab12665c878c326 GIT binary patch literal 2816 zcma)8O>7%g5Pr|=-8godG>uVe<-e+FipbhYogXKu8bb;wNkxewno6L}+TJ7v|3vFe zKnYcnriX$+0@Opr0fnln%7p{s&{UOZ#RYL82S7P+fCHizB*YC+5Z~;+jbkg7GSa-6 zd2img^JeBf`}=?X_^*aB&OkKC;KyDJ?O;#{JWci!XjrWIXd|d!*j3PpkI*DY(=6j{ z%h4Ts>iqOn$#%7Ap%9)2`bafnh>tNZTO;9;rloaDcP+vnO-v<9_8yLynh|&2mhl_kUc$xfcfgEt&GQ4X7&n?mWhr}yd zrdF7pEmq>~2)s@a%`bo@Kw@SP_!rP7S3xT(Z{u4Dn z5HGLi461P@-nQ_*E@IjNUKv1zscES~Zb463+G75#Og@c%85LV?F)caPh?t!5F-B7l z5ud;=u z=Ua7qt}3*n;2rEINt?*;F>HDV?)vc_K?cAV!9-LlVmcC*-F!ehJmL5sGCs0}9l_m| zuRq_F*he(y<0F5Aw-6|O@&?US!#*vu`fAR$$o9h?haG_3$^8NH-CcQf_o1ZyMCW@3 zJb7VqoWr>udKLe2_F7^rdQ}D;&Ti{ey&(F0l8D=q4$hY_Os8KaKm$BMA zF^quc7n3S(=%7_dX7plL(bCgd!;ECJOS!HEv+#zIvQ+Yq4H&&iBh`PVH=gc`#(PqI z@&2e0pN;mWVzIc9j>cj}s#otn%|vlhEOKD+*kXRMXr#O0XR=H_#byfyaT+%($Q>dl zqAnonbOgq0U^=(B%l16o4`S*;+DX4i(f()@YMI}=#p{8#wd(=@4}(LL8#hnnN6$8; zn5$BQ7ghGOKvE;}0SwG@jz%I*nJRX1{~AV|C-jzJ^UN=CH(keu^>Ymbni zQ-Pth*$0$(o2O20-lru$mnG$@%#=y_ zn14gASMJOHG3ESy`Q*!Tqw<&Bri{TMFoyQy{Gf|fsvR43BAFN#lCpr1&c-0|#ffKy zq{_fPOIg7i)kSX_nm>!HO!9TA2hCFgu-{Gx;j}xpLjJH7JNJ;}Pqw=b)3(Qj^mv$; zdpZZaQt)^)<}QM3vB4!$YZ1_EVuI>gi{^0u=Oo1Xv{)aiSnnkp!On>F2-!G@`#VMP z*5M;=eP0x|aAzmT#`j%(yM^3E$QJOvaPb3{)R&niUO6q3w`j&>8eI!*NzXF;aMFcw Z{ugHP48|CZXY8@Z9=lzqZrh~B{~ucyRFePz literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml new file mode 100644 index 000000000000..4aa53015a988 --- /dev/null +++ b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.arm64.opt.yaml @@ -0,0 +1,194 @@ +--- !Missed +Pass: inline +Name: NoDefinition +DebugLoc: { File: basic2.c, Line: 11, Column: 3 } +Function: unused1 +Args: + - Callee: bar + DebugLoc: { File: basic2.c, Line: 0, Column: 0 } + - String: ' will not be inlined into ' + - Caller: unused1 + DebugLoc: { File: basic2.c, Line: 10, Column: 0 } + - String: ' because its definition is unavailable' +... +--- !Missed +Pass: inline +Name: NoDefinition +DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +Function: foo +Args: + - Callee: bar + DebugLoc: { File: basic2.c, Line: 0, Column: 0 } + - String: ' will not be inlined into ' + - Caller: foo + DebugLoc: { File: basic2.c, Line: 19, Column: 0 } + - String: ' because its definition is unavailable' +... +--- !Passed +Pass: inline +Name: Inlined +DebugLoc: { File: basic2.c, Line: 20, Column: 25 } +Function: foo +Args: + - String: '''' + - Callee: inc + DebugLoc: { File: basic2.c, Line: 14, Column: 0 } + - String: ''' inlined into ''' + - Caller: foo + DebugLoc: { File: basic2.c, Line: 19, Column: 0 } + - String: '''' + - String: ' with ' + - String: '(cost=' + - Cost: '-15015' + - String: ', threshold=' + - Threshold: '75' + - String: ')' + - String: ' at callsite ' + - String: foo + - String: ':' + - Line: '1' + - String: ':' + - Column: '25' + - String: ';' +... +--- !Missed +Pass: gvn +Name: LoadClobbered +DebugLoc: { File: basic2.c, Line: 15, Column: 10 } +Function: foo +Args: + - String: 'load of type ' + - Type: i32 + - String: ' not eliminated' + - String: ' because it is clobbered by ' + - ClobberedBy: call + DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +... +--- !Missed +Pass: gvn +Name: LoadClobbered +DebugLoc: { File: basic2.c, Line: 20, Column: 36 } +Function: foo +Args: + - String: 'load of type ' + - Type: i32 + - String: ' not eliminated' + - String: ' because it is clobbered by ' + - ClobberedBy: call + DebugLoc: { File: basic2.c, Line: 20, Column: 10 } +... +--- !Analysis +Pass: prologepilog +Name: StackSize +DebugLoc: { File: basic2.c, Line: 10, Column: 0 } +Function: unused1 +Args: + - NumStackBytes: '0' + - String: ' stack bytes in function ''' + - Function: unused1 + - String: '''' +... +--- !Analysis +Pass: prologepilog +Name: StackSize +DebugLoc: { File: basic2.c, Line: 19, Column: 0 } +Function: foo +Args: + - NumStackBytes: '16' + - String: ' stack bytes in function ''' + - Function: foo + - String: '''' +... +--- !Analysis +Pass: asm-printer +Name: InstructionMix +DebugLoc: { File: basic2.c, Line: 11, Column: 7 } +Function: unused1 +Args: + - String: 'BasicBlock: ' + - BasicBlock: entry + - String: "\n" + - String: ADRP + - String: ': ' + - INST_ADRP: '1' + - String: "\n" + - String: LDRWui + - String: ': ' + - INST_LDRWui: '1' + - String: "\n" + - String: TCRETURNdi + - String: ': ' + - INST_TCRETURNdi: '1' + - String: "\n" +... +--- !Analysis +Pass: asm-printer +Name: InstructionCount +DebugLoc: { File: basic2.c, Line: 10, Column: 0 } +Function: unused1 +Args: + - NumInstructions: '3' + - String: ' instructions in function' +... +--- !Analysis +Pass: asm-printer +Name: InstructionMix +Function: foo +Args: + - String: 'BasicBlock: ' + - BasicBlock: entry + - String: "\n" + - String: ADDWrs + - String: ': ' + - INST_ADDWrs: '3' + - String: "\n" + - String: ADRP + - String: ': ' + - INST_ADRP: '3' + - String: "\n" + - String: LDRWui + - String: ': ' + - INST_LDRWui: '3' + - String: "\n" + - String: ADDWri + - String: ': ' + - INST_ADDWri: '2' + - String: "\n" + - String: STRWui + - String: ': ' + - INST_STRWui: '2' + - String: "\n" + - String: ADDXri + - String: ': ' + - INST_ADDXri: '1' + - String: "\n" + - String: BL + - String: ': ' + - INST_BL: '1' + - String: "\n" + - String: LDPXpost + - String: ': ' + - INST_LDPXpost: '1' + - String: "\n" + - String: LDRXui + - String: ': ' + - INST_LDRXui: '1' + - String: "\n" + - String: RET + - String: ': ' + - INST_RET: '1' + - String: "\n" + - String: STPXpre + - String: ': ' + - INST_STPXpre: '1' + - String: "\n" +... +--- !Analysis +Pass: asm-printer +Name: InstructionCount +DebugLoc: { File: basic2.c, Line: 19, Column: 0 } +Function: foo +Args: + - NumInstructions: '19' + - String: ' instructions in function' +... diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..8c55fb3d9d9b813cb54b0d5dbf0d7d985049bcf9 GIT binary patch literal 2800 zcma)8O-y4|6uz&ISAIHEV8AeB7$^iBW(;j%%1`-8S_dZvI*AfgOf+|1Umwu1e`y~$ z0!9QDjKKs9D;EaQ1WD zcg{Wc-uBBse*XImV-f?=Py{}p!374@g2%}I4{8;2zX{nSWHI82&x&=N8~SY{2g3R2 zQ)8n!+tOBqLU=alu2O+f#OAFSlAK3WL(O?O9}JELbGC(3B3w&K7B3fZT;n{P$>g~T z@tQ?lLYR@1pGCBH`NVlzkE`idEKJTrq33VpBG!evCFBb7E1-OMs#gzBO>i|FPV3WD z|KJP3k?TiG`b7dh;qlpzrYz+|yl7%PNdbj;DS_83R!^Q1FJq*6a(p~fh<8`uH4D7W z)8m;d3h}-Wc$)(6(^KN9kw}`B6yl}C?zjZrBpqJRGR~izRZrZ%gc{eW$Ax&SB6=>n zmMsJC7(ju^xt5HlRL$U1iC3eE2+qr(SZaz2k;F~mEWyDh*T(N3BEP?^izjS|V|X2KoCjyWRelsjLFB(L?)_>R zV>e+tz|Vk*2%4BmApbF7*r%bx*-y3)Wwr*KRVD>?v1a{n_QBSDnSb}sBK!JqR@y$i z#@06W8+Nw#Ic>}8WhwAGc$Z0~^x5@?4rZ?VNoIE+Is&^Tti*wd)hJ@FD6I09gn7gs z&IY%ExklLZy;97(FpuJQ$wzx|1w3+NWLQE#CG=wHqrk^c`oFr?)8GG~_1obyI!aX7w*`)_)$X|Gu&AKspm@ym;__U3F4zj(UEPNj6i3 zB{O=f$+EFJj72u-B?v{fQSNr;A_GiBS9cctI`|#%yWsc0T1-t$xTf`VCYnsRIy&55 zw|63HxLPp;z>`y9H||%jkqk%GOk2iKBQZVgiN&VlZK-tfmaZ9Yiud*Conc+;zS`-J zbb0+9T9?1utNX{jotn?**CSq^PuDut?#oPUo5nmRZY!HgOl9;)I~z|XSu~-Ul__SG zNEbwv65Y-UQ&N@U?wMXX-^4h3=1Ten@pgN?G?^cFC$sEmm|u33ebd`#?Fj7-5j~64 zf5|OZ7158m^aKVb(fwnR^%|3rC6Sl7&6YQpFSQ2r$h=ht^$hgLm0X3B>hFe>BY{aiX z5(U8d^Yr`g#Llln5>Y))6lVP%QQqai7w3kBgbiWRC5+{H_*Jm;(#1<~+-5wi&M+=s vDjrQ30>1+|+dH30N4({yZ& literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic2.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.arm64.o new file mode 100644 index 0000000000000000000000000000000000000000..3497e3add648ad038dc25025214f0d94fb1ed79a GIT binary patch literal 2528 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 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream similarity index 100% rename from llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.opt.bitstream rename to llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/basic3.macho.remarks.empty.arm64.opt.bitstream diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/remarks/fat.macho.remarks.x86.o new file mode 100644 index 0000000000000000000000000000000000000000..14094faf1a3cbfea3389f130e1e19d912e8397a3 GIT binary patch literal 34800 zcmeI4U1%d!6vyu*O+R+~-AI*fyQvtdU?*cun`XC2<9<-Ei&9oAs0@?Iq{(i+m`rO~ zD^?4#il7fZh#>BYD++=jf{QG&QbgGo`=HPVeH49B`s~N*IWu?CG^S9&hXwx^?woUP z?)}fbzd3XBbmqp*&psDI1Qa3K$OeU&CDXP;mu}hDF2s7Rj~o;b009sH0T2KI5C8!X z009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2Lz|Cqoxzx{HP68{xS{1=q(FIuQx=806^mt*`ke@uXDC;v!A*Bxus@qDj+_SEBNciX<#BOTV;bK4fN?vG)s z>$X)i?DJLGsq6FekDb{a;p<$IU7zj|b2|gOqggLwrI(jgtgOf8(Q4f#lV zcT2k%s{Q0UP4)7nY?%i%>U}3?-7D?02h^)NwqDL=tBraJKRhZ!o)I4$T+f}+s5dP2 z-jjM?9#GH7WNe<&sJAKgdZpg^R?oT4!RNV6`IU^K#m~4=?^`+P5vjLEdV2&Kn!0Y5 zixtCk^ySji`BH}B<)obInlU*!B0IN8k3;+Geb;B@^sG&*^Csx}-gusqdb3h*N9xI@ zI4nfY_u2aKSIC!K#m4DKn}og+i< zgm<1Fxse+AespMC>6{-O-o88(?g$GpO6OERY4LG&=@}tn6+6FTI9ALlR$}s`iDeB( zEgEL7tjZpBb$UvlimT;{qo(r?VYZASDbP0ilxTDy6pX&G7PSX^2aiPij`X)y2ML%e z*bPQ$)EL!};C(QdVW9+Ems&x=h`AMTy%ra~{|@pS_A=F1s9vUO7L3wTWW}n}1w>!sbF=~=r)xv(IV z)n28yv#tF#8pR5HcE0iFUv8;Ic&fYi#lVR!d0dGnXbf*6K~_t!dfDfGlnVofn;pfVRLEGh>vZEPxwdCqfx_uP-o`FiBHu?i8N!2IyJa4R5kKrHk`=EK*(jcHxEy5-51M>p!|WV07f z9=b|to}b~yw6(OiO%B`ZW0S|k(LoHWYi(-A|0wY%0{6_A46 zIzPtj=-Zju~0)o|MlScN=}qW)xt|s+Dak-BGkL2QpgQO4>3E zx~_3!67hUodqtZrAId3OZ05R*>CENaxoAuC1+ZSZP2@x0`Wn4^dK1uU3*cJE)4wiUx9n`= z`yXwtTk%KxUHg_}%z_u6sY>LAD!Z>|Ljqq07NfDBPc`fgJfG(2@V+=`-B+JqW5xHl z8js_+Idj_&#V z*l?No&YmBR4c#&*+YgGgS(qnb8Pb@Ac|VSi*JxQc!L_yEY8Jf6LHx>U6|}m3&uZHD zn)0r|7g=j(vA+wSb3U9E-r4Mv011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg zz<)zP|4&RK0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH* zAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*`2Pu5 zC;|7T+pg8z zCz4qScgC|)*`3MAymUO(CpG=?Ui+@@OQFDeO}7L-TQA>^73)~48b!GG(`#)BPl5NT zhP$>29k1R3-Hj(|PJGy-b98A0KY9na_APk5N9$NU9AVp3Zzzd-_kS62?|yHV=#$V> z?VrE~np^LI*Zp0sWA$(w23pm+zZ<^@-B7}(0lB8*a~bm!aMwoA@#-?<*81)#;d2T( zb?+PDTA!3CO9CgQA##IxzUnR2pE2R`$kYk#nrA4pamK8T(_{rh*G4W> z41?s`(E6&>sxgMw&5`TP tf35YeR~|Y1>VrcaPh5QXq2T>reRK50(!rg#pL(OLFlWi0=g*Ic{0+b?v-to3 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.arm64 new file mode 100755 index 0000000000000000000000000000000000000000..49c0a2749f35017ead09b3cbfee227719158afd7 GIT binary patch literal 34416 zcmeI5ZHSar6vxl(&e{z7rnaP_)fCH?o6Xd!r9n7bF0NE6w%}IEbzYgtotbrJTwkdT zwUqXQ!a@;}_904BC=uKxtOe->Bw{~Q5G31|T7!bZJ|yb)KhHdmK0EHNlpiAaA2`o_ z&OPUzd+zVvXTA;h>r200tr77Eqyjnv8t{tjl>pvE=0Mw_#;j>w(e`}X+SS@SUaZ06 zyKb;F&nVQGj<(K@@osB;czmDOb``o+wKf%FiivH-(tF7spKl{-*L*&^D7Brj)+n#^ zTCM#sW=nQ!IvY3XY%+(w^7>MkTvMg&c(upnv-_P!*SQ1(j9K2=(dzV~4cm~>T2j_l zqSI0J8xxNdBl=d7$?{=&B?(Vmmod>o!HGp%p3jT%y3T9)@a|rx`rKknESJgTvQA%l zK418s<-2~)o?f}?skY@Soiox~#tpVg_q0;0b-8O>B+@%wUA@=`Gz)Ee3G6knbxpIO z2Vg&lcH?f5P9&(tyZTk`w^h%b#{3(p!=L~Z-Je! z@16Ph+`g`t_O~pH6ruoU9I7go4 z!SeYu=cwj7Dw|J;bYN)>*u#FU0~{K3yw4vVynq<3dGSXhd8tk2axya$NoQqNPo&Gb%X-AOV0}ZU z2=4KgIt(7g#9GHgw%uXfUM{j&ZM_6LT=GArHe#Lo>vc?AAGWMO8+Qz}8_Mh?>?CGd z5+6uum<|o%p?7iXdjQ(#vbC=fx&W%8_Np?!d;YiKch7&S%svBqqWSym`SqT7o!_yY z`PZXg#hKsj*ZLiPeswmJ z_p-gdJM8)#+o=yn!4kEVuiLNdbIyaF4_%*QYkVWLe0`2z@3#*?9npCAe(7H&P(G1~Ovk?AgO4@UBt zM-~Nh6OSvUZJ9D{OK_^R)=H)*dEu0~7fzWQeBE;Ce9aI@A4i{VrAh<(u#KKKr2>bn z!uo~UhJNQr`9<~&1uCS*ioWT?*} zexYa4?7APWHYH|84<9>O(Y&tVuFd}1WuKhhaQ@v{{kNL`X5-J@lS-b;f0aDF`_O%T c1BZWk=HgF@=Xzf4xb2;~(Rr_Y*{U4>22n&0Jpcdz literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.empty.x86_64 deleted file mode 100755 index a730148ba387047682c588a62a9601da8a7cfcc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9296 zcmeHNU1%It6uy&WZK$=o6eg<|^7@-K!tZuQXi;Yy2a+%$oC5xHevOhIZ z0>xEuSo{H>d=d4@$G%nY#k2*BFH!KJeUTyvTeRSV;3A9h`)1~5XE!me55CAfaOU3c z+8LLKwqBoE;KE#G&Sh5bp>RH6g~J8K{)m+2_))q+fi2)_yVi z;kJl=+E6JM(l0Occk#z3`fVb_F_@{$jUr{;S*{250QdVlw-=K^!);+w#F$P`M#R}3 zpua}>^-{SYOXXq(4TJf82}00%6ZOUfRuBy3$u|n%*Rhj&2yjx|3WE8 zNm;P#c5nPY`P-Zu{Oy#Nl(|~1=Wa`WBVm4<{?Iq-&(FPYe7@qkm9jDo<~RB;{q@$_ zv7^VIPtP4yYs4Jj4VaP*6J=h}+#bL>PWe4qA$(tJ>e6dc}88Gy|Fe&46Y=Gw@$C@KVP6In(?#@lCqR zP~K`M<28P3t#;b`05i=?iBlIpjEL%=c`r7GcW7_5+nVpT62|x5dYkX}Ub@r9JF{rb zcZ{`G>;_F2nimXj|4*nIYu@F+XZ*n1z(UYpEA}mF&94nFwuVYyKot*(HCH%;rR}dcy(iA15K@THwaX;RH*oYxgZ`!obpFB*9>peyUc+6 z9=HceiI#k~=ez$DO6qxhuTog&H^Uyh^CyC@37QRlKWNbmXa+O`ngPv#WaM%0xzKq#{U@h zX#CHCw~K!bdoFad4rP3WX=5zzHBpEeKZ=>Z;_C;rbG*Xr&++@A6k?87_$u&tgwG#| zM|ym+|4#G!h3!x!zoW9<{IcQwyB`jjpThKiEAvzLe>@zouo};uF$yu~r|==vO*VwW z_UL@L9^(cU6NGIX7e__q$8&XJbwA7ytM$V3?Kn=t)&B~IfYF_!kB4vK(Wk=q HND}@AAlzFj diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 b/llvm/test/tools/dsymutil/Inputs/remarks/basic.macho.remarks.x86_64 deleted file mode 100755 index 59e53c8de9acbfd3a4c3b28fe28346d910c12db7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9280 zcmeHN-)me&6rP)8O{lTE6)LS(d#R;rZSTf3ED=PEX4@^AHq;1G3B%nVAs4f|vOi*4 z8Yr#>FBhx$;-mco`p~|#f-j~O4ZhU=2c;maV4;tTY#YDt-aFa5o21qUUt|uPJM*2H zIdjgpGjQ+B-umm_!$Bd8ej(2H2_fQ8b3lj-!bDAo-OvnF%IS$?>C@>`Cu!{#qZ@9D z=%)#lawh%ZOm`Q5e4^VXLL7sc%GfAU)(T6tpdR3Ee^<6688kc*21Sf?Ix-;6cL4p> zOP@NWymU%)Wi<50_dN)qD{?>~R`!QZ3ek}_MZcHC`f!{rRzXjn9>f#d1lRdgB}Vm;O5I?7ibB z-c3&)S8K%V;SHGbRv0MbipI7N>v+WP@edC(_)VGPF6cDyVU*^JP&j;&HYnw#P`M5d zL8J2lK9*n^3KKdEP1dWGuA?VKbrr zobhegpxgX9*9sPP-$4|hdR<;d{`A9j9~I6!4rN>LyBbKx=){6}-ak{V6^ho|7UFWU z!RP}h=s#l$F@*A!5R)%0ngPv#WIoWnZ}=qU(#((6U|v_s`%c?U_OkP^+z;T40p&~<%Ikm*aM|R zOTOFl-G2-v^*X*+DXjCGVHofHiQsF3W`o}kS~LTi0nLDBKr^5j&Gy|Fe&46Y= zGoTsxpEF=c+^@%Eab6ad3b}f%Amiy;>|^SLA=BBg?@46 zc|7j$@!Jb{d||>eGHv2OE<-uL!nAQNo)uAuIe!#0{t=wB zueMUEo v8nw0>!I2HVj%?}6&(Qb9+~8v~uR{C{BSBEG diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.empty.x86_64.o deleted file mode 100644 index aef4841d64c728c81d7600a885f9beea7497e613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2088 zcmbVN%TE(w5TB*AR4An=5tUMlj|3kqtr$b02a2LKVqy>#59Z6ZE>NWpOF=LqkS0dr zg@Y$fYWxe-1BqOSMiUNd42hVKcrxLDi3bnF7tZX?meOEooOE^`-^}lu@0*?NyB}Zw z6ah#kzz1?6@&Y~F$VfYpyU6|reJaowRyfA65fg|@IZud`I+S7qg%F)>U7c&Tq3vUZ z@Cb6AiX&ekjFB)%h@=`-lGpp$Aw+xo#k0mLfPpj3E~j~IjWw=Zw}iN=h6Z{>e=4at zgg9|2&~Y-8w8+{imh*YyDWOnO9i;QF$J?tN3Sc+mRar7y8OnzBMPl7?3dqH4WjsG; zH!mlj^Nr3WbN9^iUEj`2!{N>FpqSn6~KlP>w$B~*+jVpXZ!QfF9avP z1k=loH*LQtd}3rJI5F_;{>aJ_nZfic$CZ~IXFJYFxPK*jilnD4&s%-(k2m`Lv$Zqn zX4Iafn;)e8V}YjWv~T8RV64$%t=Qw5QnoJzTpwnu-%7Tn8t1F=>bby;mfguEsS z=fmFt;4Q+LO(Cj8Vjz`E`|aDzCcC4u%3dyQ#W%P>22xCR+@%qjDh9A>O|*eWvjBW7 zNzi=qtDzgM+G6m0AZWCXB(<1G_vy28ZFK53jSppz{~$6^b}reuxvNP36GN>a(*FuA zD9w1l5+FQ%1)p>tB&uf}8OhSE4v>Z%lEYSHox~`LcOp;zCYaS#&c`O%9d`?kml~gi zHjF6*H$Ejv`e`pEL7N~;YYjpNz?RH?n%t7vUTnQ=F1Gm1rmg}DW?{fCWR!J>bZK$1 bL_vN_9ZTA~j1rhg%`$Q5yW?>X+RN}44(bA8 diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.o deleted file mode 100644 index f8aa44116ebe3020b91be19781527e31737bcb32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2416 zcmbVN&2Jl35PuuTj*~jB3l=5dxEoZY1jyPBCUIIL*-e66kyI!t5DwMqdA+u`-4C<7 zcGIe*sVpHPKq(6xm2wL^Z*g39ys)Zlmke)AXQKiW_I8DORgF*t9kQg z-pudKys!P`??3+?B82l1Xn+TScd+4sfyRK>QGWtWv9UcSJsmI!@+gZFMO)sm+aRKN zc4_@=Tlad$SqJeDGB)hy1$tJ_&nXv|VXi9tcqqWVhgDA>Xv24O_czXAJyT$Nw?l8H* z@R&*t5mNQ~D82ikD!PN%yM7ND-f0%J!|KgGAwS%=2>Ko#aUyVWp9fxK=d}bf1UlqF z-U03;Jd+-G+7Hryx3Kklq4`JTho#5pzIF9cVXMCP>D5QOs1};{BIoX|uB^VzLH_qcVkK*ZG(56 zO#%ZFty?f^TYRZC0k2qmU8fDIsI;icfJdbZYszJr)J#J)DsoMMmYk_;&d8}tHk|XB zG~q3Do%d5HeG`xZP`Saj&X~mQUroq0o_Pn!dXhN z=RLt{hj*%K2+SyKWM;+Lv|!Y1p$KK!rc5Rbl)9z>kWx*kYC{vimzUGhY_gclB&Fnhsw~gV&CSwM zDMRJ*>!mlO8Je1bFC(R=+8gAhO`Lt>j&LuBpY{8~k)tn$k8sbxKVv{3*ztuS*9DG;Lj>`hfp&w10AW^L_HwKS1bpEdT%j diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/remarks/basic1.macho.remarks.x86_64.opt.bitstream deleted file mode 100644 index ac700c36c6c7b7002403f87531b638b8964d94fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmWIY4f1B>U|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{-13?2p*1%VX@*%%lan1CE1t_%wqCxZ(h1wi27%mh})3S^t43a)4bssjTf Ysf+?317rqBZVS5*Le5PkV+K$R0990TCIA2c diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic2.macho.remarks.empty.x86_64.o deleted file mode 100644 index 9bb1405bf9e0d021743c7ba43971aa87dda4dda2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2892 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 K2)Qgfus#3-qLPFF diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.empty.x86_64.o deleted file mode 100644 index fff0a7122fb637c78da911750a42f2ade68ad816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2624 zcmbVOT}&KR6h6c33=1sFmSS5YKZB`BtulpT2o!3Vwir^uRIEx&>ScBrV3qxG8Gc$* zrCmeVkQg3(@}W^o_p^3 zx!*l=&;8l^fBx}zIe?-9Hpl_wb!rS`q(_m5N&gobXJ4MBrz0j1SMxX_TxZVR1`*<7 z-|)q4-RmuIhwun;qyj)ETL9)scqBx|N!Xb;r`RCGz`!emo)^Hwxy`0`v~3^v%1SLl zj5^WjaWUm)q*;h_uUbRT6+@n-#X%Y>2+m>=(<9r>L^-w|Z#tEmJaMxr3HKfrNx zWDPVMC@~+nfJ{VVh$)t)-2sgHe(2@?+^_vh@={pp+@KMcR>#bmruXFFv1RGc{vOF) z&1bLXkJr3U7nzL9^=s67>rwVQYoOr%UUnoc6^UN+}CJ4DAbW-9HP(YT9uqhlvj2& z2b3qm2Q@VuIs91ofKrRsSD6XaQNuXlYsi#5Kv3?O5VT4Spo=Am1?1vppzl6I1_K)+ z3;8^9S(-E?s^SZ>*Z-2$Pq?(3h;g|jkxePQKN5Hg>6?+os;2qHs;VDPbz@q5($+D>8(48!S%?Co0P}amKO(BII>W7w%U9CD2`Tj zp5r(VtlsXpNsPP2aa2o5zPPv17ytuXMN$3=SCgQmk(KRji3Wg*;?_B$g)2YTDs@v+ zhc(cD)~Zk~*UxJqeO%M@VKsSO3+w7ZSF6RC${tO1HAO$IfjS#>wMqd4CbcyuzZSTBg$6#I-z1Ll>#wiPlBMsif>fm^aA_?lY&sm diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.o deleted file mode 100644 index 9508c979596385d4111997f602bd88b76a834292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3080 zcmbVOU2GIp6h71KY?rod7pQ=-w6_M6f_C~tZMQ!pUD}$Wg=neTnBXuwJKG(ZomqBf zwgrP0*ANsvu_@KrIUrdbgp&`5wcpyAjVtnAis4pfp(S%2WL_Fv2o$hw2fp|9O zo_p^7?sw0*f3vIi|N5s6KnejCsI{oKsbHumPovI~{~t0CE_K`$n7~I)Al)j)sj6oz zc)~%WsxuR_Gi5)hofj42Bg&2j06s-6ECv{|s+u>lTK=Rf8dY^_>Ww31M8Gp%Q)(;7 zw|6y^kvaC)Iqv3BKS6+42t0Ze`!yT-g zFH*cFEk%}Y9=|?)Wcn2;0ZI>Rzdtm1dn`UOa;@WPaTse~6^AbsM-~%9E5*U9 z*At8JaHRR!)=#yaYl+q$ukHCkYFuk?xp8jKt;DI(ww5oO@1ASDm1zCBz2%P7IMu%A z&KE7sTbhx(y%E4iONZxkB?L#EaU*Tore``fm^R-`-}YT2)eA|@HT46E4r7{S83v>s z2ab7p)1Cu1Z(0_!9gigqRvMN<>p83h&I5Mn8uBpHb6IMA4raQ{x3z+1T3XUFaE?42 zH3~-laA|JS)`9bGB&}d$ZpQJg6tihm<@C^@JFa(-x9@`?2GfS-Vpg`pG;3Zv?UpE+ z=3x#=-!m{7O+R_eJYzsE?^w>9ku$M`qkfk696IgcO^yR|3CEJ;Vv;QF+d5yb!!~{# zd|n@OeA@%f&35K+fjk4V^0O8FE(`#UUB_=E>g|J`K^Vk6`2>$~m-vu%i4DLPIpZjz zQCW!htNne7lk=1$uC13hv@8xp(JjrMW4J0VZYJyLR`AC6SYLiKGI*gatL{(KbTuOGY!&0Oo}zuMV1k@ z7r`y4EB7gihYtfBB%-nNHDg|XgI!8*cjR<5(N81xi(?J(2_ibN`4@;?iDWoZlaID3sLFq VRq0Vz3z`KgT~++AQF{9U{sp`i_45D# diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream b/llvm/test/tools/dsymutil/Inputs/remarks/basic3.macho.remarks.x86_64.opt.bitstream deleted file mode 100644 index e29471cd769055d4d82762c7a64d4b6aaed0463e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 592 zcmWIY4f1B>U|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{-13?2p*1%VZeObiSSK+GV-m0=;{WMBbO00a)sOi1biRvZKxfTYf_0jvt4 z4rmR-64ihejUbDF79J3kXl8|~F)`s=DB%F*EI8QM#xA8GF%jYpkeV%>LMsk3LgmAB zGIju&AUA^KOmu`1a#>~>50K=xbOxU|?`yU|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0-XPD%}gPJJ|Wo{_~704c7 zkUga+a{{RNp@N4Fcgh4s=NAW!5Yi1YryONoJ(M}nAbT%S=1?QV#7hl*4vGObHtjl7 zoUL1$ZPqYLEI4d^0qCg1HfNe2F)nQ9<7BP0Xs^m>FDhWKVrZ`RV6SpuH&AFV5@@fo zU^hr;FPCU9SkPWl!CrpBWr1@$*gO?ajT470uQ&t!1~e?0N!AMJeFjAy1_ovz%>u+L zKmtIZD!{rhd@DKV30lPuV-=gpOF6-#-qSel&1!rJ^s zOuR93Nd0OqcATnR<25)ibTM~spjs>HsjJh}w`kz$V9Yqw36X_(3m#d_95;RzeiwYr zVJ~zB{tk>zhe!pZ+9ObvR-?LC=l@1_;gADugSvCGWp}DL?&jyG^6*vmLp6_}`QhWG z=cj}FgW>ykJ+~hn!<++6YQnFvEgjpyhacos(@_jaeN_&lK8>Tlmo562900910S&Di1C%zX3CZRdtYAXerm|>6yQ8?q4gU~PEm~~~+k20Y@QJBt{sZ1q%Dl;ML?p}Yh zeu$uu011!)36KB@kN^pg011!)36Q`h5~$w)>m6y_3uEN{e+@A2|3w_&*y#TM^T(6t z@Ah^tJvrFnf4ctQJMaHRc>iDfKcYnfBtQZrKmsH{0wh2JB(OCII7nkl-~YG#fA{~t E0K<|ACIA2c literal 24876 zcmeI4O-NKx7>3WNQIur0h@zlL>=&DvqRgOz!a=1-ON9vHI^&EvI}QFoKNjx?-#zC$_uO;OdG2h!d*;1w z=BJ(;V=6<&tVX%Um<=d4cH>aZwsD*@CRS)eh5gXh&bE3Ss^Kyb5CIVo0TB=Z5fA|p z5CIVo0TB>^6-?mWx4C&F^dThvrUJemK8wmt6GqLLt?(AOWwoDbj$evjXk%;8@Sb2% z<2bW$%j%3@>?nq}qE`J7XC;^27qYp@ucKw%r>Dz|PIRc72D zTGr^mwah@u$_(@l;za5E9=qd_0gbUY7pEn7Eb= z4_Ir=cq}+{`3U2%ALq0M-iUY|%2||ol&rVIX?(_X_FW72-w)xEjK7aCoG*Q%qa(x7 z{!B8O8tYFXrfq|B9(AqnyXQ^Al}8_5ne!iyJv@ZAFxfIIO6;`&-O6Su(qq(%zmrkV8!)9kTkr^<%IB=!8zr*f~d$^SY zh`pSTr;e7yZHRlnzqd!iulWUw-O~^^! z*u2?}i{q0G+6z~Nk=g&eM$29!(^qRGH=4APcoTr7M~Bnd#PHRTsOe4QBH2Vw-(bXT zisTy`B0a?(YKm6F1^WLG|2$8v zby@BI0=j8lH*H@R+)K9w*xq$0`60n&Y5So)*o14SA*e!GFrTJ>F+Kkz#%RHXlNf{R zEoa4bmuUFI=*{`V>(PnxXJ5~1@gItq7c5lrdYtF|sbi-mojUzVlzEiDL$gmkL^;jA zr`MnR`gFSK(~)Pln&daW diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c index 8153fc294680..830456141be1 100644 --- a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c +++ b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.c @@ -4,11 +4,11 @@ * - fat.macho.remarks.x86 */ -/* for ARCH in x86_64 x86_64h i386 +/* for ARCH in x86_64 x86_64h * do * clang -gline-tables-only -c fat.macho.remarks.x86.c -fsave-optimization-record=bitstream -foptimization-record-file=fat.macho.remarks."$ARCH".opt.bitstream -mllvm -remarks-section -arch "$ARCH" * done - * lipo -create -output fat.macho.remarks.x86.o fat.macho.remarks.x86_64.o fat.macho.remarks.x86_64h.o fat.macho.remarks.i386.o - * clang -gline-tables-only fat.macho.remarks.x86.o -arch x86_64 -arch x86_64h -arch i386 -o fat.macho.remarks.x86 + * lipo -create -output fat.macho.remarks.x86.o fat.macho.remarks.x86_64.o fat.macho.remarks.x86_64h.o + * clang -gline-tables-only fat.macho.remarks.x86.o -arch x86_64 -arch x86_64h -o fat.macho.remarks.x86 */ int main(void) { return 0; } diff --git a/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o b/llvm/test/tools/dsymutil/Inputs/remarks/fat.macho.remarks.x86.o deleted file mode 100644 index 2f5b8f3c4bc09d5583092b96a76797dbd4708358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14440 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 oKmtIZD!{ %t/basic.macho.remarks.empty.x86_64 - -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.x86_64 - -Check that the remark file in the bundle does not exist: -RUN: not cat %t/basic.macho.remarks.empty.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.x86_64 2>&1 - -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.empty.x86_64 - -Check that the remark file in the bundle does not exist: -RUN: not cat %t/basic.macho.remarks.empty.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.empty.x86_64 2>&1 diff --git a/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test b/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test deleted file mode 100644 index d85cd54c8f64..000000000000 --- a/llvm/test/tools/dsymutil/X86/remarks-linking-bundle.test +++ /dev/null @@ -1,67 +0,0 @@ -RUN: rm -rf %t -RUN: mkdir -p %t -RUN: cat %p/../Inputs/remarks/basic.macho.remarks.x86_64 > %t/basic.macho.remarks.x86_64 - -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 - -Check that the remark file in the bundle exists and is sane: -RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s - -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 - -Check that the remark file in the bundle exists and is sane: -RUN: llvm-bcanalyzer -dump %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s - -Now emit it in a different format: YAML. -RUN: dsymutil -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 -RUN: cat %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s --check-prefix=CHECK-YAML - -RUN: dsymutil --linker parallel -remarks-output-format=yaml -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/basic.macho.remarks.x86_64 -RUN: cat %t/basic.macho.remarks.x86_64.dSYM/Contents/Resources/Remarks/basic.macho.remarks.x86_64 | FileCheck %s --check-prefix=CHECK-YAML - -CHECK: %t/fat.macho.remarks.x86 +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/fat.macho.remarks.x86_64.opt.yaml -o %t/private/tmp/remarks/fat.macho.remarks.x86_64.opt.bitstream +RUN: llvm-remarkutil yaml2bitstream %p/../Inputs/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.yaml -o %t/private/tmp/remarks/fat.macho.remarks.x86_64h.opt.bitstream -RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/fat.macho.remarks.x86 +RUN: dsymutil -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/fat.macho.remarks.x86 Check that the remark files in the bundle exist and are all sane: RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64h | FileCheck %s RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64 | FileCheck %s -RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-i386 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-i386 -RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%p/../Inputs %t/fat.macho.remarks.x86 +RUN: dsymutil --linker parallel -oso-prepend-path=%p/../Inputs -remarks-prepend-path=%t %t/fat.macho.remarks.x86 Check that the remark files in the bundle exist and are all sane: RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64h | FileCheck %s RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-x86_64 | FileCheck %s -RUN: llvm-bcanalyzer -dump %t/fat.macho.remarks.x86.dSYM/Contents/Resources/Remarks/fat.macho.remarks.x86-i386 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-i386 CHECK: 5MZcn=ons0A^kWZ~y=R diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream b/llvm/test/tools/llvm-remarkutil/Inputs/two-remarks.v0.bitstream new file mode 100644 index 0000000000000000000000000000000000000000..2a528436791aeb4b28ef64cf6f9746804a6047eb GIT binary patch literal 500 zcmWIY4f1B>U|?`%U|?Wp+~lyu$?}4;g^kTYjXllQK-Q9G>nY7P4USejnl1Mnc5JX< z;}B7jlXDb1wNUnuquez{o;M3+o+Qd$dMJCxG0_-`GIVQ0>!}L5nsF|`*=9VH*pX>n!*;9%#CxB)=RPfN@PMM(S{NkVyLb^fbl%ve6 zhcX8mWbY-)9BPDEbg7}wK{3F_rd?->vvo_e%^GHj1&6IK0Nr}n=1lV=#)a*CoUD}= z?Nu4=MFs3t49(RZ>{Slz1`6#(0_{~mmnF29OSBg(XfLT?FTdcjz_}f4o{Fc&iNlsx zoPk~j8kWo?YsH|*!@!^k3>y|8-T=f5%QzVdit=;v(^CsFfh0q4Nn&z#aAs91Lt1HG zvH^o%X)ajEsj?)sn86SzUzC}b&Y(~XQm2pv5>?2|QvfM0$;{7VNG#6PEdVMhNiAaV z%quP_Dg}!>=a=S{fDA(tD`o)dgsVU`2IMqV0R{$UAiae_-~b~dHyg5;$rFJCER5V- GATa>F(5cP< literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-remarkutil/convert.test b/llvm/test/tools/llvm-remarkutil/convert.test index 0d7ab8e4682a..2b1bdcb0a5b3 100644 --- a/llvm/test/tools/llvm-remarkutil/convert.test +++ b/llvm/test/tools/llvm-remarkutil/convert.test @@ -1,8 +1,11 @@ RUN: llvm-remarkutil bitstream2yaml %p/Inputs/two-remarks.bitstream -o %t.yaml RUN: FileCheck %s -strict-whitespace < %t.yaml +RUN: not llvm-remarkutil bitstream2yaml %p/Inputs/two-remarks.v0.bitstream 2>&1 -o - | FileCheck %s --check-prefix=ERR RUN: llvm-remarkutil yaml2bitstream %p/Inputs/two-remarks.yaml -o %t.bitstream RUN: llvm-remarkutil bitstream2yaml %t.bitstream -o - | FileCheck %s -strict-whitespace +; ERR: error: Unsupported remark container version (expected: 1, read: 0). Please upgrade/downgrade your toolchain to read this container. + ; CHECK: --- !Analysis ; CHECK-NEXT: Pass: prologepilog ; CHECK-NEXT: Name: StackSize diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 138c5d0a513e..b91c27e6a0f8 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -291,6 +291,7 @@ ErrorOr> DwarfLinkerForBinary::loadObject( [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); }); Error E = RL.link(*ErrorOrObj); + // FIXME: Remark parsing errors are not propagated to the user. if (Error NewE = handleErrors( std::move(E), [&](std::unique_ptr EC) -> Error { return remarksErrorHandler(Obj, *this, std::move(EC)); diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index b3d7185e7f14..a2327fbc3b66 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -387,13 +387,13 @@ int main(int argc, char **argv) { // Set a diagnostic handler that doesn't exit on the first error Context.setDiagnosticHandler(std::make_unique()); - Expected> RemarksFileOrErr = + Expected RemarksFileOrErr = setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, RemarksFormat, RemarksWithHotness, RemarksHotnessThreshold); if (Error E = RemarksFileOrErr.takeError()) reportError(std::move(E), RemarksFilename); - std::unique_ptr RemarksFile = std::move(*RemarksFileOrErr); + LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") reportError("input language must be '', 'IR' or 'MIR'"); diff --git a/llvm/tools/llvm-remarkutil/RemarkConvert.cpp b/llvm/tools/llvm-remarkutil/RemarkConvert.cpp index 207c5e0a8048..203c8266b077 100644 --- a/llvm/tools/llvm-remarkutil/RemarkConvert.cpp +++ b/llvm/tools/llvm-remarkutil/RemarkConvert.cpp @@ -80,8 +80,8 @@ static Error tryReserializeYAML2Bitstream( if (!MaybeOF) return MaybeOF.takeError(); auto OF = std::move(*MaybeOF); - auto MaybeSerializer = createRemarkSerializer( - OutputFormat, SerializerMode::Standalone, OF->os(), std::move(StrTab)); + auto MaybeSerializer = + createRemarkSerializer(OutputFormat, OF->os(), std::move(StrTab)); if (!MaybeSerializer) return MaybeSerializer.takeError(); auto Serializer = std::move(*MaybeSerializer); @@ -110,8 +110,7 @@ static Error tryBitstream2YAML() { if (!MaybeOF) return MaybeOF.takeError(); auto OF = std::move(*MaybeOF); - auto MaybeSerializer = createRemarkSerializer( - OutputFormat, SerializerMode::Standalone, OF->os()); + auto MaybeSerializer = createRemarkSerializer(OutputFormat, OF->os()); if (!MaybeSerializer) return MaybeSerializer.takeError(); diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp index 26902b213571..d4fa6eb50cda 100644 --- a/llvm/tools/opt/optdriver.cpp +++ b/llvm/tools/opt/optdriver.cpp @@ -510,7 +510,7 @@ extern "C" int optMain( if (!DisableDITypeMap) Context.enableDebugTypeODRUniquing(); - Expected> RemarksFileOrErr = + Expected RemarksFileOrErr = setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, RemarksFormat, RemarksWithHotness, RemarksHotnessThreshold); @@ -518,7 +518,7 @@ extern "C" int optMain( errs() << toString(std::move(E)) << '\n'; return 1; } - std::unique_ptr RemarksFile = std::move(*RemarksFileOrErr); + LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr); // Load the input module... auto SetDataLayout = [&](StringRef IRTriple, diff --git a/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp index ea61691f4c83..ddf744521ef1 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksFormatTest.cpp @@ -21,7 +21,7 @@ TEST(BitstreamRemarksFormat, Magic) { // This should be updated whenever any of the tests below are modified. TEST(BitstreamRemarksFormat, ContainerVersion) { - EXPECT_EQ(remarks::CurrentContainerVersion, 0UL); + EXPECT_EQ(remarks::CurrentContainerVersion, 1UL); } // The values of the current blocks should not change over time. diff --git a/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp index 6234931b3bec..f5973f5431c9 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksParsingTest.cpp @@ -14,7 +14,7 @@ using namespace llvm; -template void parseGood(const char (&Buf)[N]) { +template static void parseGood(const char (&Buf)[N]) { // 1. Parse the YAML remark -> FromYAMLRemark // 2. Serialize it to bitstream -> BSStream // 3. Parse it back -> FromBSRemark @@ -48,11 +48,11 @@ template void parseGood(const char (&Buf)[N]) { std::string BSBuf; raw_string_ostream BSStream(BSBuf); Expected> BSSerializer = - remarks::createRemarkSerializer(remarks::Format::Bitstream, - remarks::SerializerMode::Standalone, - BSStream, std::move(BSStrTab)); + remarks::createRemarkSerializer(remarks::Format::Bitstream, BSStream, + std::move(BSStrTab)); EXPECT_FALSE(errorToBool(BSSerializer.takeError())); (*BSSerializer)->emit(*FromYAMLRemark); + (*BSSerializer)->finalize(); // 3. Expected> MaybeBSParser = @@ -256,11 +256,11 @@ TEST(BitstreamRemarks, ContentsCAPI) { std::string BSBuf; raw_string_ostream BSStream(BSBuf); Expected> BSSerializer = - remarks::createRemarkSerializer(remarks::Format::Bitstream, - remarks::SerializerMode::Standalone, - BSStream, std::move(BSStrTab)); + remarks::createRemarkSerializer(remarks::Format::Bitstream, BSStream, + std::move(BSStrTab)); EXPECT_FALSE(errorToBool(BSSerializer.takeError())); (*BSSerializer)->emit(ToSerializeRemark); + (*BSSerializer)->finalize(); StringRef Buf = BSStream.str(); LLVMRemarkParserRef Parser = diff --git a/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp b/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp index 8113d35b3aff..3b460965fdb2 100644 --- a/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp +++ b/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Bitcode/BitcodeAnalyzer.h" -#include "llvm/Remarks/BitstreamRemarkSerializer.h" #include "llvm/Remarks/Remark.h" +#include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" #include @@ -34,23 +34,24 @@ static void checkAnalyze(StringRef Input, StringRef Expected) { EXPECT_EQ(OutputOS.str(), Expected); } -static void check(remarks::SerializerMode Mode, const remarks::Remark &R, - StringRef ExpectedR, std::optional ExpectedMeta, - std::optional StrTab) { +static void check(const remarks::Remark &R, StringRef ExpectedR, + std::optional ExpectedMeta = std::nullopt, + std::optional StrTab = std::nullopt) { // Emit the remark. std::string InputBuf; raw_string_ostream InputOS(InputBuf); Expected> MaybeSerializer = [&] { if (StrTab) - return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS, + return createRemarkSerializer(remarks::Format::Bitstream, InputOS, std::move(*StrTab)); else - return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS); + return createRemarkSerializer(remarks::Format::Bitstream, InputOS); }(); EXPECT_FALSE(errorToBool(MaybeSerializer.takeError())); std::unique_ptr Serializer = std::move(*MaybeSerializer); Serializer->emit(R); + Serializer->finalize(); // Analyze the serialized remark. checkAnalyze(InputOS.str(), ExpectedR); @@ -66,20 +67,6 @@ static void check(remarks::SerializerMode Mode, const remarks::Remark &R, } } -static void check(const remarks::Remark &R, StringRef ExpectedR, - StringRef ExpectedMeta, - std::optional StrTab = std::nullopt) { - return check(remarks::SerializerMode::Separate, R, ExpectedR, ExpectedMeta, - std::move(StrTab)); -} - -static void -checkStandalone(const remarks::Remark &R, StringRef ExpectedR, - std::optional StrTab = std::nullopt) { - return check(remarks::SerializerMode::Standalone, R, ExpectedR, - /*ExpectedMeta=*/std::nullopt, std::move(StrTab)); -} - TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) { remarks::Remark R; R.RemarkType = remarks::Type::Missed; @@ -89,19 +76,21 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -118,19 +107,21 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionalsSeparateStrTab) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'function\\x00pass\\x00remark\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n", std::move(StrTab)); } @@ -148,20 +139,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00path\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -175,20 +168,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileHotness) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -204,20 +199,22 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgNoDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00key\\x00value\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -237,21 +234,23 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgDebugLoc) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00key\\x00value\\x00path\\x00'\n" - " blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -276,7 +275,7 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) { check(R, "\n" "\n" - " \n" + " \n" " \n" "\n" "\n" @@ -285,14 +284,17 @@ TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) { " \n" " \n" - "\n", - "\n" - "\n" - " \n" - " blob data = " + "\n" + "\n" + " blob data = " "'remark\\x00pass\\x00function\\x00path\\x00key\\x00value\\x00argpa" - "th\\x00'\n blob data = " - "'" EXTERNALFILETESTPATH"'\n" + "th\\x00'\n" + "\n", + "\n" + "\n" + " \n" + " blob data = " + "'" EXTERNALFILETESTPATH "'\n" "\n"); } @@ -323,15 +325,12 @@ TEST(BitstreamRemarkSerializer, Standalone) { R.Args.back().Loc->SourceFilePath = "argpath"; R.Args.back().Loc->SourceLine = 11; R.Args.back().Loc->SourceColumn = 66; - checkStandalone( + check( R, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0" - "0'\n" "\n" "\n" " \n" @@ -339,6 +338,11 @@ TEST(BitstreamRemarkSerializer, Standalone) { " \n" " \n" - "\n", - std::move(StrTab)); + "\n" + "\n" + " blob data = " + "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0" + "0'\n" + "\n", + std::nullopt, std::move(StrTab)); } diff --git a/llvm/unittests/Remarks/RemarksLinkingTest.cpp b/llvm/unittests/Remarks/RemarksLinkingTest.cpp index 89de9e8f4f95..54942ff681b4 100644 --- a/llvm/unittests/Remarks/RemarksLinkingTest.cpp +++ b/llvm/unittests/Remarks/RemarksLinkingTest.cpp @@ -133,16 +133,18 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" "\n" "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" + "\n"); // Check that we keep remarks without debug info. check(remarks::Format::YAML, @@ -153,15 +155,17 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00'\n" "\n" "\n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00'\n" + "\n"); // Check that we deduplicate remarks. check(remarks::Format::YAML, @@ -179,16 +183,18 @@ TEST(Remarks, LinkingGoodBitstream) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" "\n" "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n" + "\n"); } TEST(Remarks, LinkingGoodStrTab) { @@ -209,11 +215,9 @@ TEST(Remarks, LinkingGoodStrTab) { "...\n", remarks::Format::Bitstream, "\n" - "\n" - " \n" + "\n" + " \n" " \n" - " blob data = " - "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00Ok\\x00'\n" "\n" "\n" " \n" @@ -222,7 +226,11 @@ TEST(Remarks, LinkingGoodStrTab) { "\n" " \n" " \n" - "\n"); + "\n" + "\n" + " blob data = " + "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00Ok\\x00'\n" + "\n"); } // Check that we propagate parsing errors. diff --git a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp index 7e994ac4d58b..112cd9228568 100644 --- a/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp +++ b/llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp @@ -23,23 +23,23 @@ using namespace llvm; static void check(remarks::Format SerializerFormat, - remarks::SerializerMode Mode, ArrayRef Rs, - StringRef ExpectedR, std::optional ExpectedMeta, + ArrayRef Rs, StringRef ExpectedR, + std::optional ExpectedMeta, std::optional StrTab = std::nullopt) { std::string Buf; raw_string_ostream OS(Buf); Expected> MaybeS = [&] { if (StrTab) - return createRemarkSerializer(SerializerFormat, Mode, OS, - std::move(*StrTab)); + return createRemarkSerializer(SerializerFormat, OS, std::move(*StrTab)); else - return createRemarkSerializer(SerializerFormat, Mode, OS); + return createRemarkSerializer(SerializerFormat, OS); }(); EXPECT_FALSE(errorToBool(MaybeS.takeError())); std::unique_ptr S = std::move(*MaybeS); for (const remarks::Remark &R : Rs) S->emit(R); + S->finalize(); EXPECT_EQ(OS.str(), ExpectedR); if (ExpectedMeta) { @@ -54,8 +54,7 @@ static void check(remarks::Format SerializerFormat, static void check(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, StringRef ExpectedMeta, std::optional StrTab = std::nullopt) { - return check(SerializerFormat, remarks::SerializerMode::Separate, - ArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, + return check(SerializerFormat, ArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, std::move(StrTab)); } @@ -63,8 +62,7 @@ static void checkStandalone(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, std::optional StrTab = std::nullopt) { - return check(SerializerFormat, remarks::SerializerMode::Standalone, - ArrayRef(&R, &R + 1), ExpectedR, + return check(SerializerFormat, ArrayRef(&R, &R + 1), ExpectedR, /*ExpectedMeta=*/std::nullopt, std::move(StrTab)); } diff --git a/mlir/include/mlir/Remark/RemarkStreamer.h b/mlir/include/mlir/Remark/RemarkStreamer.h index 8bfd176d9bad..170d6b439a44 100644 --- a/mlir/include/mlir/Remark/RemarkStreamer.h +++ b/mlir/include/mlir/Remark/RemarkStreamer.h @@ -26,14 +26,15 @@ public: createToFile(llvm::StringRef path, llvm::remarks::Format fmt); void streamOptimizationRemark(const Remark &remark) override; - void finalize() override {} + void finalize() override; ~LLVMRemarkStreamer() override; private: LLVMRemarkStreamer() = default; - std::unique_ptr remarkStreamer; std::unique_ptr file; + // RemarkStreamer must be destructed before file is destroyed! + std::unique_ptr remarkStreamer; }; } // namespace mlir::remark::detail diff --git a/mlir/lib/Remark/RemarkStreamer.cpp b/mlir/lib/Remark/RemarkStreamer.cpp index 8e3544ff2c34..d213a1a2068d 100644 --- a/mlir/lib/Remark/RemarkStreamer.cpp +++ b/mlir/lib/Remark/RemarkStreamer.cpp @@ -20,8 +20,7 @@ LLVMRemarkStreamer::createToFile(llvm::StringRef path, if (ec) return failure(); - auto serOr = llvm::remarks::createRemarkSerializer( - fmt, llvm::remarks::SerializerMode::Separate, f->os()); + auto serOr = llvm::remarks::createRemarkSerializer(fmt, f->os()); if (!serOr) { llvm::consumeError(serOr.takeError()); return failure(); @@ -50,6 +49,12 @@ LLVMRemarkStreamer::~LLVMRemarkStreamer() { if (file && remarkStreamer) file->keep(); } + +void LLVMRemarkStreamer::finalize() { + if (!remarkStreamer) + return; + remarkStreamer->releaseSerializer(); +} } // namespace mlir::remark::detail namespace mlir::remark { diff --git a/offload/plugins-nextgen/common/src/JIT.cpp b/offload/plugins-nextgen/common/src/JIT.cpp index 07ef05e7e9d3..881e27dad384 100644 --- a/offload/plugins-nextgen/common/src/JIT.cpp +++ b/offload/plugins-nextgen/common/src/JIT.cpp @@ -180,9 +180,10 @@ Expected> JITEngine::backend(Module &M, const std::string &ComputeUnitKind, unsigned OptLevel) { - auto RemarksFileOrErr = setupLLVMOptimizationRemarks( - M.getContext(), /*RemarksFilename=*/"", /*RemarksPasses=*/"", - /*RemarksFormat=*/"", /*RemarksWithHotness=*/false); + Expected RemarksFileOrErr = + setupLLVMOptimizationRemarks( + M.getContext(), /*RemarksFilename=*/"", /*RemarksPasses=*/"", + /*RemarksFormat=*/"", /*RemarksWithHotness=*/false); if (Error E = RemarksFileOrErr.takeError()) return std::move(E); if (*RemarksFileOrErr)