1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[Remarks] Extend the RemarkStreamer to support other emitters

This extends the RemarkStreamer to allow for other emitters (e.g.
frontends, SIL, etc.) to emit remarks through a common interface.

See changes in llvm/docs/Remarks.rst for motivation and design choices.

Differential Revision: https://reviews.llvm.org/D73676
This commit is contained in:
Francis Visoiu Mistrih 2019-10-28 14:53:31 -07:00
parent 5f84616692
commit 57aee84cb1
22 changed files with 406 additions and 257 deletions

View File

@ -612,6 +612,38 @@ The typical usage through the C API is like the following:
bool HasError = LLVMRemarkParserHasError(Parser);
LLVMRemarkParserDispose(Parser);
Remark streamers
================
The ``RemarkStreamer`` interface is used to unify the serialization
capabilities of remarks across all the components that can generate remarks.
All remark serialization should go through the main remark streamer, the
``llvm::remarks::RemarkStreamer`` set up in the ``LLVMContext``. The interface
takes remark objects converted to ``llvm::remarks::Remark``, and takes care of
serializing it to the requested format, using the requested type of metadata,
etc.
Typically, a specialized remark streamer will hold a reference to the one set
up in the ``LLVMContext``, and will operate on its own type of diagnostics.
For example, LLVM IR passes will emit ``llvm::DiagnosticInfoOptimization*``
that get converted to ``llvm::remarks::Remark`` objects. Then, clang could set
up its own specialized remark streamer that takes ``clang::Diagnostic``
objects. This can allow various components of the frontend to emit remarks
using the same techniques as the LLVM remarks.
This gives us the following advantages:
* Composition: during the compilation pipeline, multiple components can set up
their specialized remark streamers that all emit remarks through the same
main streamer.
* Re-using the remark infrastructure in ``lib/Remarks``.
* Using the same file and format for the remark emitters created throughout the
compilation.
at the cost of an extra layer of abstraction.
.. FIXME: add documentation for llvm-opt-report.
.. FIXME: add documentation for Passes supporting optimization remarks
.. FIXME: add documentation for IR Passes

View File

@ -77,7 +77,7 @@ public:
// remarks enabled. We can't currently check whether remarks are requested
// for the calling pass since that requires actually building the remark.
if (F->getContext().getRemarkStreamer() ||
if (F->getContext().getLLVMRemarkStreamer() ||
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) {
auto R = RemarkBuilder();
emit((DiagnosticInfoOptimizationBase &)R);
@ -92,7 +92,7 @@ public:
/// provide more context so that non-trivial false positives can be quickly
/// detected by the user.
bool allowExtraAnalysis(StringRef PassName) const {
return (F->getContext().getRemarkStreamer() ||
return (F->getContext().getLLVMRemarkStreamer() ||
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
}

View File

@ -71,11 +71,14 @@ class MDNode;
class Module;
class ProfileSummaryInfo;
class raw_ostream;
class RemarkStreamer;
class StackMaps;
class TargetLoweringObjectFile;
class TargetMachine;
namespace remarks {
class RemarkStreamer;
};
/// This class is intended to be used as a driving class for all asm writers.
class AsmPrinter : public MachineFunctionPass {
public:
@ -337,7 +340,7 @@ public:
void emitStackSizeSection(const MachineFunction &MF);
void emitRemarksSection(RemarkStreamer &RS);
void emitRemarksSection(remarks::RemarkStreamer &RS);
enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug };
CFIMoveType needsCFIMoves() const;

View File

@ -159,7 +159,7 @@ public:
/// that non-trivial false positives can be quickly detected by the user.
bool allowExtraAnalysis(StringRef PassName) const {
return (
MF.getFunction().getContext().getRemarkStreamer() ||
MF.getFunction().getContext().getLLVMRemarkStreamer() ||
MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(
PassName));
}
@ -172,7 +172,7 @@ public:
// remarks enabled. We can't currently check whether remarks are requested
// for the calling pass since that requires actually building the remark.
if (MF.getFunction().getContext().getRemarkStreamer() ||
if (MF.getFunction().getContext().getLLVMRemarkStreamer() ||
MF.getFunction()
.getContext()
.getDiagHandlerPtr()

View File

@ -34,9 +34,13 @@ template <typename T> class SmallVectorImpl;
class SMDiagnostic;
class StringRef;
class Twine;
class RemarkStreamer;
class LLVMRemarkStreamer;
class raw_ostream;
namespace remarks {
class RemarkStreamer;
};
namespace SyncScope {
typedef uint8_t ID;
@ -218,23 +222,27 @@ public:
/// included in optimization diagnostics.
void setDiagnosticsHotnessThreshold(uint64_t Threshold);
/// Return the streamer used by the backend to save remark diagnostics. If it
/// does not exist, diagnostics are not saved in a file but only emitted via
/// the diagnostic handler.
RemarkStreamer *getRemarkStreamer();
const RemarkStreamer *getRemarkStreamer() const;
/// The "main remark streamer" used by all the specialized remark streamers.
/// This streamer keeps generic remark metadata in memory throughout the life
/// of the LLVMContext. This metadata may be emitted in a section in object
/// files depending on the format requirements.
///
/// All specialized remark streamers should convert remarks to
/// llvm::remarks::Remark and emit them through this streamer.
remarks::RemarkStreamer *getMainRemarkStreamer();
const remarks::RemarkStreamer *getMainRemarkStreamer() const;
void setMainRemarkStreamer(
std::unique_ptr<remarks::RemarkStreamer> LLVMRemarkStreamer);
/// Set the diagnostics output used for optimization diagnostics.
/// This filename may be embedded in a section for tools to find the
/// diagnostics whenever they're needed.
/// The "LLVM remark streamer" used by LLVM to serialize remark diagnostics
/// comming from IR and MIR passes.
///
/// If a remark streamer is already set, it will be replaced with
/// \p RemarkStreamer.
///
/// By default, diagnostics are not saved in a file but only emitted via the
/// diagnostic handler. Even if an output file is set, the handler is invoked
/// for each diagnostic message.
void setRemarkStreamer(std::unique_ptr<RemarkStreamer> RemarkStreamer);
/// If it does not exist, diagnostics are not saved in a file but only emitted
/// via the diagnostic handler.
LLVMRemarkStreamer *getLLVMRemarkStreamer();
const LLVMRemarkStreamer *getLLVMRemarkStreamer() const;
void
setLLVMRemarkStreamer(std::unique_ptr<LLVMRemarkStreamer> LLVMRemarkStreamer);
/// Get the prefix that should be printed in front of a diagnostic of
/// the given \p Severity

View File

@ -0,0 +1,95 @@
//===- llvm/IR/LLVMRemarkStreamer.h - Streamer for LLVM remarks--*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the conversion between IR Diagnostics and
// serializable remarks::Remark objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_LLVMREMARKSTREAMER_H
#define LLVM_IR_LLVMREMARKSTREAMER_H
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/Remarks/RemarkStreamer.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ToolOutputFile.h"
#include <memory>
#include <string>
namespace llvm {
/// Streamer for LLVM remarks which has logic for dealing with DiagnosticInfo
/// objects.
class LLVMRemarkStreamer {
remarks::RemarkStreamer &RS;
/// Convert diagnostics into remark objects.
/// The lifetime of the members of the result is bound to the lifetime of
/// the LLVM diagnostics.
remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag) const;
public:
LLVMRemarkStreamer(remarks::RemarkStreamer &RS) : RS(RS) {}
/// Emit a diagnostic through the streamer.
void emit(const DiagnosticInfoOptimizationBase &Diag);
};
template <typename ThisError>
struct LLVMRemarkSetupErrorInfo : public ErrorInfo<ThisError> {
std::string Msg;
std::error_code EC;
LLVMRemarkSetupErrorInfo(Error E) {
handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) {
Msg = EIB.message();
EC = EIB.convertToErrorCode();
});
}
void log(raw_ostream &OS) const override { OS << Msg; }
std::error_code convertToErrorCode() const override { return EC; }
};
struct LLVMRemarkSetupFileError
: LLVMRemarkSetupErrorInfo<LLVMRemarkSetupFileError> {
static char ID;
using LLVMRemarkSetupErrorInfo<
LLVMRemarkSetupFileError>::LLVMRemarkSetupErrorInfo;
};
struct LLVMRemarkSetupPatternError
: LLVMRemarkSetupErrorInfo<LLVMRemarkSetupPatternError> {
static char ID;
using LLVMRemarkSetupErrorInfo<
LLVMRemarkSetupPatternError>::LLVMRemarkSetupErrorInfo;
};
struct LLVMRemarkSetupFormatError
: LLVMRemarkSetupErrorInfo<LLVMRemarkSetupFormatError> {
static char ID;
using LLVMRemarkSetupErrorInfo<
LLVMRemarkSetupFormatError>::LLVMRemarkSetupErrorInfo;
};
/// Setup optimization remarks that output to a file.
Expected<std::unique_ptr<ToolOutputFile>>
setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned 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.
Error setupLLVMOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
StringRef RemarksPasses,
StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned RemarksHotnessThreshold = 0);
} // end namespace llvm
#endif // LLVM_IR_LLVMREMARKSTREAMER_H

View File

@ -1,108 +0,0 @@
//===- llvm/IR/RemarkStreamer.h - Remark Streamer ---------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the main interface for outputting remarks.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_REMARKSTREAMER_H
#define LLVM_IR_REMARKSTREAMER_H
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <vector>
namespace llvm {
/// Streamer for remarks.
class RemarkStreamer {
/// The regex used to filter remarks based on the passes that emit them.
Optional<Regex> PassFilter;
/// The object used to serialize the remarks to a specific format.
std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer;
/// The filename that the remark diagnostics are emitted to.
const Optional<std::string> Filename;
/// Convert diagnostics into remark objects.
/// The lifetime of the members of the result is bound to the lifetime of
/// the LLVM diagnostics.
remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag);
public:
RemarkStreamer(std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
Optional<StringRef> Filename = None);
/// Return the filename that the remark diagnostics are emitted to.
Optional<StringRef> getFilename() const {
return Filename ? Optional<StringRef>(*Filename) : None;
}
/// Return stream that the remark diagnostics are emitted to.
raw_ostream &getStream() { return RemarkSerializer->OS; }
/// Return the serializer used for this stream.
remarks::RemarkSerializer &getSerializer() { return *RemarkSerializer; }
/// Set a pass filter based on a regex \p Filter.
/// Returns an error if the regex is invalid.
Error setFilter(StringRef Filter);
/// Emit a diagnostic through the streamer.
void emit(const DiagnosticInfoOptimizationBase &Diag);
/// Check if the remarks also need to have associated metadata in a section.
bool needsSection() const;
};
template <typename ThisError>
struct RemarkSetupErrorInfo : public ErrorInfo<ThisError> {
std::string Msg;
std::error_code EC;
RemarkSetupErrorInfo(Error E) {
handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) {
Msg = EIB.message();
EC = EIB.convertToErrorCode();
});
}
void log(raw_ostream &OS) const override { OS << Msg; }
std::error_code convertToErrorCode() const override { return EC; }
};
struct RemarkSetupFileError : RemarkSetupErrorInfo<RemarkSetupFileError> {
static char ID;
using RemarkSetupErrorInfo<RemarkSetupFileError>::RemarkSetupErrorInfo;
};
struct RemarkSetupPatternError : RemarkSetupErrorInfo<RemarkSetupPatternError> {
static char ID;
using RemarkSetupErrorInfo<RemarkSetupPatternError>::RemarkSetupErrorInfo;
};
struct RemarkSetupFormatError : RemarkSetupErrorInfo<RemarkSetupFormatError> {
static char ID;
using RemarkSetupErrorInfo<RemarkSetupFormatError>::RemarkSetupErrorInfo;
};
/// Setup optimization remarks that output to a file.
Expected<std::unique_ptr<ToolOutputFile>>
setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned 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.
Error setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned RemarksHotnessThreshold = 0);
} // end namespace llvm
#endif // LLVM_IR_REMARKSTREAMER_H

View File

@ -19,8 +19,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/LTO/Config.h"
#include "llvm/Linker/IRMover.h"
#include "llvm/Object/IRSymtab.h"
@ -87,9 +87,9 @@ std::string getThinLTOOutputFile(const std::string &Path,
/// Setup optimization remarks.
Expected<std::unique_ptr<ToolOutputFile>>
setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness, int Count = -1);
setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness, int Count = -1);
/// Setups the output file for saving statistics.
Expected<std::unique_ptr<ToolOutputFile>>

View File

@ -0,0 +1,73 @@
//===- llvm/Remarks/RemarkStreamer.h ----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the main interface for streaming remarks.
//
// This is used to stream any llvm::remarks::Remark to an open file taking
// advantage of all the serialization capabilities developed for remarks (e.g.
// metadata in a section, bitstream format, etc.).
//
// Typically, a specialized remark emitter should hold a reference to the main
// remark streamer set up in the LLVMContext, and should convert specialized
// diagnostics to llvm::remarks::Remark objects as they get emitted.
//
// Specialized remark emitters can be components like:
// * Remarks from LLVM (M)IR passes
// * Remarks from the frontend
// * Remarks from an intermediate IR
//
// This allows for composition between specialized remark emitters throughout
// the compilation pipeline, that end up in the same file, using the same format
// and serialization techniques.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_REMARKS_REMARKSTREAMER_H
#define LLVM_REMARKS_REMARKSTREAMER_H
#include "llvm/ADT/Optional.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
namespace llvm {
namespace remarks {
class RemarkStreamer final {
/// The regex used to filter remarks based on the passes that emit them.
Optional<Regex> PassFilter;
/// The object used to serialize the remarks to a specific format.
std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer;
/// The filename that the remark diagnostics are emitted to.
const Optional<std::string> Filename;
public:
RemarkStreamer(std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
Optional<StringRef> Filename = None);
/// Return the filename that the remark diagnostics are emitted to.
Optional<StringRef> getFilename() const {
return Filename ? Optional<StringRef>(*Filename) : None;
}
/// Return stream that the remark diagnostics are emitted to.
raw_ostream &getStream() { return RemarkSerializer->OS; }
/// Return the serializer used for this stream.
remarks::RemarkSerializer &getSerializer() { return *RemarkSerializer; }
/// Set a pass filter based on a regex \p Filter.
/// Returns an error if the regex is invalid.
Error setFilter(StringRef Filter);
/// Check wether the string matches the filter.
bool matchesFilter(StringRef Str);
/// Check if the remarks also need to have associated metadata in a section.
bool needsSection() const;
};
} // end namespace remarks
} // end namespace llvm
#endif // LLVM_REMARKS_REMARKSTREAMER_H

View File

@ -81,7 +81,6 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCAsmInfo.h"
@ -106,6 +105,7 @@
#include "llvm/Pass.h"
#include "llvm/Remarks/Remark.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Remarks/RemarkStreamer.h"
#include "llvm/Remarks/RemarkStringTable.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
@ -1400,7 +1400,7 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
}
}
void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) {
void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
if (!RS.needsSection())
return;
@ -1462,7 +1462,7 @@ bool AsmPrinter::doFinalization(Module &M) {
// Emit the remarks section contents.
// FIXME: Figure out when is the safest time to emit this section. It should
// not come after debug info.
if (RemarkStreamer *RS = M.getContext().getRemarkStreamer())
if (remarks::RemarkStreamer *RS = M.getContext().getMainRemarkStreamer())
emitRemarksSection(*RS);
const TargetLoweringObjectFile &TLOF = getObjFileLowering();

View File

@ -30,6 +30,7 @@ add_llvm_component_library(LLVMCore
IntrinsicInst.cpp
LLVMContext.cpp
LLVMContextImpl.cpp
LLVMRemarkStreamer.cpp
LegacyPassManager.cpp
MDBuilder.cpp
Mangler.cpp
@ -43,7 +44,6 @@ add_llvm_component_library(LLVMCore
PassManager.cpp
PassRegistry.cpp
PassTimingInfo.cpp
RemarkStreamer.cpp
SafepointIRVerifier.cpp
ProfileSummary.cpp
Statepoint.cpp

View File

@ -19,9 +19,10 @@
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/Remarks/RemarkStreamer.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@ -142,15 +143,26 @@ uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
return pImpl->DiagnosticsHotnessThreshold;
}
RemarkStreamer *LLVMContext::getRemarkStreamer() {
return pImpl->RemarkDiagStreamer.get();
remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() {
return pImpl->MainRemarkStreamer.get();
}
const RemarkStreamer *LLVMContext::getRemarkStreamer() const {
return const_cast<LLVMContext *>(this)->getRemarkStreamer();
const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const {
return const_cast<LLVMContext *>(this)->getMainRemarkStreamer();
}
void LLVMContext::setRemarkStreamer(
std::unique_ptr<RemarkStreamer> RemarkStreamer) {
pImpl->RemarkDiagStreamer = std::move(RemarkStreamer);
void LLVMContext::setMainRemarkStreamer(
std::unique_ptr<remarks::RemarkStreamer> RemarkStreamer) {
pImpl->MainRemarkStreamer = std::move(RemarkStreamer);
}
LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() {
return pImpl->LLVMRemarkStreamer.get();
}
const LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() const {
return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer();
}
void LLVMContext::setLLVMRemarkStreamer(
std::unique_ptr<LLVMRemarkStreamer> RemarkStreamer) {
pImpl->LLVMRemarkStreamer = std::move(RemarkStreamer);
}
DiagnosticHandler::DiagnosticHandlerTy
@ -214,7 +226,7 @@ LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
void LLVMContext::diagnose(const DiagnosticInfo &DI) {
if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
if (RemarkStreamer *RS = getRemarkStreamer())
if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer())
RS->emit(*OptDiagBase);
// If there is a report handler, use it.

View File

@ -35,8 +35,8 @@
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
@ -1245,11 +1245,17 @@ public:
LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr;
void *InlineAsmDiagContext = nullptr;
/// The main remark streamer used by all the other streamers (e.g. IR, MIR,
/// frontends, etc.). This should only be used by the specific streamers, and
/// never directly.
std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;
std::unique_ptr<DiagnosticHandler> DiagHandler;
bool RespectDiagnosticFilters = false;
bool DiagnosticsHotnessRequested = false;
uint64_t DiagnosticsHotnessThreshold = 0;
std::unique_ptr<RemarkStreamer> RemarkDiagStreamer;
/// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
std::unique_ptr<LLVMRemarkStreamer> LLVMRemarkStreamer;
LLVMContext::YieldCallbackTy YieldCallback = nullptr;
void *YieldOpaqueHandle = nullptr;

View File

@ -1,4 +1,4 @@
//===- llvm/IR/RemarkStreamer.cpp - Remark Streamer -*- C++ -------------*-===//
//===- llvm/IR/LLVMRemarkStreamer.cpp - Remark Streamer -*- C++ ---------*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,45 +6,18 @@
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation of the remark outputting as part of
// LLVMContext.
// This file contains the implementation of the conversion between IR
// Diagnostics and serializable remarks::Remark objects.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Remarks/BitstreamRemarkSerializer.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
static cl::opt<cl::boolOrDefault> EnableRemarksSection(
"remarks-section",
cl::desc(
"Emit a section containing remark diagnostics metadata. By default, "
"this is enabled for the following formats: yaml-strtab, bitstream."),
cl::init(cl::BOU_UNSET), cl::Hidden);
RemarkStreamer::RemarkStreamer(
std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
Optional<StringRef> FilenameIn)
: PassFilter(), RemarkSerializer(std::move(RemarkSerializer)),
Filename(FilenameIn ? Optional<std::string>(FilenameIn->str()) : None) {}
Error RemarkStreamer::setFilter(StringRef Filter) {
Regex R = Regex(Filter);
std::string RegexError;
if (!R.isValid(RegexError))
return createStringError(std::make_error_code(std::errc::invalid_argument),
RegexError.data());
PassFilter = std::move(R);
return Error::success();
}
/// DiagnosticKind -> remarks::Type
static remarks::Type toRemarkType(enum DiagnosticKind Kind) {
switch (Kind) {
@ -81,7 +54,7 @@ toRemarkLocation(const DiagnosticLocation &DL) {
/// LLVM Diagnostic -> Remark
remarks::Remark
RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
LLVMRemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) const {
remarks::Remark R; // The result.
R.RemarkType = toRemarkType(static_cast<DiagnosticKind>(Diag.getKind()));
R.PassName = Diag.getPassName();
@ -101,51 +74,24 @@ RemarkStreamer::toRemark(const DiagnosticInfoOptimizationBase &Diag) {
return R;
}
void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
if (Optional<Regex> &Filter = PassFilter)
if (!Filter->match(Diag.getPassName()))
void LLVMRemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
if (!RS.matchesFilter(Diag.getPassName()))
return;
// First, convert the diagnostic to a remark.
remarks::Remark R = toRemark(Diag);
// Then, emit the remark through the serializer.
RemarkSerializer->emit(R);
RS.getSerializer().emit(R);
}
bool RemarkStreamer::needsSection() const {
if (EnableRemarksSection == cl::BOU_TRUE)
return true;
char LLVMRemarkSetupFileError::ID = 0;
char LLVMRemarkSetupPatternError::ID = 0;
char LLVMRemarkSetupFormatError::ID = 0;
if (EnableRemarksSection == cl::BOU_FALSE)
return false;
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
// * yaml-strtab
switch (RemarkSerializer->SerializerFormat) {
case remarks::Format::YAMLStrTab:
case remarks::Format::Bitstream:
return true;
default:
return false;
}
}
char RemarkSetupFileError::ID = 0;
char RemarkSetupPatternError::ID = 0;
char RemarkSetupFormatError::ID = 0;
Expected<std::unique_ptr<ToolOutputFile>>
llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned RemarksHotnessThreshold) {
Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
StringRef RemarksFormat, bool RemarksWithHotness,
unsigned RemarksHotnessThreshold) {
if (RemarksWithHotness)
Context.setDiagnosticsHotnessRequested(true);
@ -157,7 +103,7 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
if (Error E = Format.takeError())
return make_error<RemarkSetupFormatError>(std::move(E));
return make_error<LLVMRemarkSetupFormatError>(std::move(E));
std::error_code EC;
auto Flags = *Format == remarks::Format::YAML ? sys::fs::OF_Text
@ -167,29 +113,34 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
// We don't use llvm::FileError here because some diagnostics want the file
// name separately.
if (EC)
return make_error<RemarkSetupFileError>(errorCodeToError(EC));
return make_error<LLVMRemarkSetupFileError>(errorCodeToError(EC));
Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
remarks::createRemarkSerializer(
*Format, remarks::SerializerMode::Separate, RemarksFile->os());
if (Error E = RemarkSerializer.takeError())
return make_error<RemarkSetupFormatError>(std::move(E));
return make_error<LLVMRemarkSetupFormatError>(std::move(E));
Context.setRemarkStreamer(std::make_unique<RemarkStreamer>(
// Create the main remark streamer.
Context.setMainRemarkStreamer(std::make_unique<remarks::RemarkStreamer>(
std::move(*RemarkSerializer), RemarksFilename));
// Create LLVM's optimization remarks streamer.
Context.setLLVMRemarkStreamer(
std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
if (!RemarksPasses.empty())
if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
return make_error<RemarkSetupPatternError>(std::move(E));
if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
return make_error<LLVMRemarkSetupPatternError>(std::move(E));
return std::move(RemarksFile);
}
Error llvm::setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
StringRef RemarksPasses,
StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned RemarksHotnessThreshold) {
Error llvm::setupLLVMOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
StringRef RemarksPasses,
StringRef RemarksFormat,
bool RemarksWithHotness,
unsigned RemarksHotnessThreshold) {
if (RemarksWithHotness)
Context.setDiagnosticsHotnessRequested(true);
@ -198,20 +149,25 @@ Error llvm::setupOptimizationRemarks(LLVMContext &Context, raw_ostream &OS,
Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
if (Error E = Format.takeError())
return make_error<RemarkSetupFormatError>(std::move(E));
return make_error<LLVMRemarkSetupFormatError>(std::move(E));
Expected<std::unique_ptr<remarks::RemarkSerializer>> RemarkSerializer =
remarks::createRemarkSerializer(*Format,
remarks::SerializerMode::Separate, OS);
if (Error E = RemarkSerializer.takeError())
return make_error<RemarkSetupFormatError>(std::move(E));
return make_error<LLVMRemarkSetupFormatError>(std::move(E));
Context.setRemarkStreamer(
std::make_unique<RemarkStreamer>(std::move(*RemarkSerializer)));
// Create the main remark streamer.
Context.setMainRemarkStreamer(
std::make_unique<remarks::RemarkStreamer>(std::move(*RemarkSerializer)));
// Create LLVM's optimization remarks streamer.
Context.setLLVMRemarkStreamer(
std::make_unique<LLVMRemarkStreamer>(*Context.getMainRemarkStreamer()));
if (!RemarksPasses.empty())
if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
return make_error<RemarkSetupPatternError>(std::move(E));
if (Error E = Context.getMainRemarkStreamer()->setFilter(RemarksPasses))
return make_error<LLVMRemarkSetupPatternError>(std::move(E));
return Error::success();
}

View File

@ -22,10 +22,10 @@
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/LTO/LTOBackend.h"
#include "llvm/LTO/SummaryBasedOptimizations.h"
#include "llvm/Linker/IRMover.h"
@ -951,7 +951,7 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
Error LTO::runRegularLTO(AddStreamFn AddStream) {
// Setup optimization remarks.
auto DiagFileOrErr = lto::setupOptimizationRemarks(
auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename,
Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness);
if (!DiagFileOrErr)
@ -1409,10 +1409,9 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
return BackendProc->wait();
}
Expected<std::unique_ptr<ToolOutputFile>>
lto::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
StringRef RemarksPasses, StringRef RemarksFormat,
bool RemarksWithHotness, int Count) {
Expected<std::unique_ptr<ToolOutputFile>> lto::setupLLVMOptimizationRemarks(
LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
StringRef RemarksFormat, bool RemarksWithHotness, int Count) {
std::string Filename = std::string(RemarksFilename);
// For ThinLTO, file.opt.<format> becomes
// file.opt.<format>.thin.<num>.<format>.
@ -1421,7 +1420,7 @@ lto::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
(Twine(Filename) + ".thin." + llvm::utostr(Count) + "." + RemarksFormat)
.str();
auto ResultOrErr = llvm::setupOptimizationRemarks(
auto ResultOrErr = llvm::setupLLVMOptimizationRemarks(
Context, Filename, RemarksPasses, RemarksFormat, RemarksWithHotness);
if (Error E = ResultOrErr.takeError())
return std::move(E);

View File

@ -20,9 +20,9 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/LTO/LTO.h"
#include "llvm/MC/SubtargetFeature.h"
@ -503,7 +503,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
std::unique_ptr<TargetMachine> TM = createTargetMachine(Conf, *TOrErr, Mod);
// Setup optimization remarks.
auto DiagFileOrErr = lto::setupOptimizationRemarks(
auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
Conf.RemarksFormat, Conf.RemarksWithHotness, Task);
if (!DiagFileOrErr)

View File

@ -29,11 +29,11 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassTimingInfo.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/InitializePasses.h"
#include "llvm/LTO/LTO.h"
@ -527,8 +527,8 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
return false;
auto DiagFileOrErr =
lto::setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness);
lto::setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness);
if (!DiagFileOrErr) {
errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
report_fatal_error("Can't get an output file for the remarks");

View File

@ -27,10 +27,10 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/PassTimingInfo.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/LTO/LTO.h"
@ -1079,7 +1079,7 @@ void ThinLTOCodeGenerator::run() {
LLVMContext Context;
Context.setDiscardValueNames(LTODiscardValueNames);
Context.enableDebugTypeODRUniquing();
auto DiagFileOrErr = lto::setupOptimizationRemarks(
auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
Context, RemarksFilename, RemarksPasses, RemarksFormat,
RemarksWithHotness, count);
if (!DiagFileOrErr) {

View File

@ -6,6 +6,7 @@ add_llvm_component_library(LLVMRemarks
RemarkLinker.cpp
RemarkParser.cpp
RemarkSerializer.cpp
RemarkStreamer.cpp
RemarkStringTable.cpp
YAMLRemarkParser.cpp
YAMLRemarkSerializer.cpp

View File

@ -0,0 +1,72 @@
//===- llvm/Remarks/RemarkStreamer.cpp - Remark Streamer -*- C++ --------*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the implementation of the main remark streamer.
//
//===----------------------------------------------------------------------===//
#include "llvm/Remarks/RemarkStreamer.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
using namespace llvm::remarks;
static cl::opt<cl::boolOrDefault> EnableRemarksSection(
"remarks-section",
cl::desc(
"Emit a section containing remark diagnostics metadata. By default, "
"this is enabled for the following formats: yaml-strtab, bitstream."),
cl::init(cl::BOU_UNSET), cl::Hidden);
RemarkStreamer::RemarkStreamer(
std::unique_ptr<remarks::RemarkSerializer> RemarkSerializer,
Optional<StringRef> FilenameIn)
: PassFilter(), RemarkSerializer(std::move(RemarkSerializer)),
Filename(FilenameIn ? Optional<std::string>(FilenameIn->str()) : None) {}
Error RemarkStreamer::setFilter(StringRef Filter) {
Regex R = Regex(Filter);
std::string RegexError;
if (!R.isValid(RegexError))
return createStringError(std::make_error_code(std::errc::invalid_argument),
RegexError.data());
PassFilter = std::move(R);
return Error::success();
}
bool RemarkStreamer::matchesFilter(StringRef Str) {
if (PassFilter)
return PassFilter->match(Str);
// No filter means all strings pass.
return true;
}
bool RemarkStreamer::needsSection() const {
if (EnableRemarksSection == cl::BOU_TRUE)
return true;
if (EnableRemarksSection == cl::BOU_FALSE)
return false;
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
// * yaml-strtab
switch (RemarkSerializer->SerializerFormat) {
case remarks::Format::YAMLStrTab:
case remarks::Format::Bitstream:
return true;
default:
return false;
}
}

View File

@ -29,9 +29,9 @@
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
@ -334,9 +334,9 @@ int main(int argc, char **argv) {
Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError);
Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness,
RemarksHotnessThreshold);
setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness,
RemarksHotnessThreshold);
if (Error E = RemarksFileOrErr.takeError()) {
WithColor::error(errs(), argv[0]) << toString(std::move(E)) << '\n';
return 1;

View File

@ -29,10 +29,10 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
@ -583,9 +583,9 @@ int main(int argc, char **argv) {
Context.enableDebugTypeODRUniquing();
Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness,
RemarksHotnessThreshold);
setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
RemarksFormat, RemarksWithHotness,
RemarksHotnessThreshold);
if (Error E = RemarksFileOrErr.takeError()) {
errs() << toString(std::move(E)) << '\n';
return 1;