Skip to content

Commit

Permalink
Add support for missed and analysis optimization remarks.
Browse files Browse the repository at this point in the history
Summary:
This adds two new diagnostics: -pass-remarks-missed and
-pass-remarks-analysis. They take the same values as -pass-remarks but
are intended to be triggered in different contexts.

-pass-remarks-missed is used by LLVMContext::emitOptimizationRemarkMissed,
which passes call when they tried to apply a transformation but
couldn't.

-pass-remarks-analysis is used by LLVMContext::emitOptimizationRemarkAnalysis,
which passes call when they want to inform the user about analysis
results.

The patch also:

1- Adds support in the inliner for the two new remarks and a
   test case.

2- Moves emitOptimizationRemark* functions to the llvm namespace.

3- Adds an LLVMContext argument instead of making them member functions
   of LLVMContext.

Reviewers: qcolombet

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D3682

llvm-svn: 209442
  • Loading branch information
dnovillo committed May 22, 2014
1 parent 8ff177e commit 7f8af8b
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 92 deletions.
151 changes: 137 additions & 14 deletions llvm/include/llvm/IR/DiagnosticInfo.h
Expand Up @@ -26,6 +26,7 @@ namespace llvm {
class DiagnosticPrinter;
class Function;
class Instruction;
class LLVMContextImpl;
class Twine;
class Value;
class DebugLoc;
Expand All @@ -48,6 +49,8 @@ enum DiagnosticKind {
DK_DebugMetadataVersion,
DK_SampleProfile,
DK_OptimizationRemark,
DK_OptimizationRemarkMissed,
DK_OptimizationRemarkAnalysis,
DK_FirstPluginKind
};

Expand Down Expand Up @@ -239,21 +242,21 @@ class DiagnosticInfoSampleProfile : public DiagnosticInfo {
const Twine &Msg;
};

/// Diagnostic information for optimization remarks.
class DiagnosticInfoOptimizationRemark : public DiagnosticInfo {
/// Common features for diagnostics dealing with optimization remarks.
class DiagnosticInfoOptimizationRemarkBase : public DiagnosticInfo {
public:
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass=, then the
/// diagnostic will be emitted. \p Fn is the function where the diagnostic
/// is being emitted. \p DLoc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic
/// will include the source code location. \p Msg is the message to show.
/// Note that this class does not copy this message, so this reference
/// must be valid for the whole life time of the diagnostic.
DiagnosticInfoOptimizationRemark(const char *PassName, const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg)
: DiagnosticInfo(DK_OptimizationRemark, DS_Remark), PassName(PassName),
Fn(Fn), DLoc(DLoc), Msg(Msg) {}
/// \p PassName is the name of the pass emitting this diagnostic.
/// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
/// the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
/// location. \p Msg is the message to show. Note that this class does not
/// copy this message, so this reference must be valid for the whole life time
/// of the diagnostic.
DiagnosticInfoOptimizationRemarkBase(enum DiagnosticKind Kind,
const char *PassName, const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg)
: DiagnosticInfo(Kind, DS_Remark), PassName(PassName), Fn(Fn), DLoc(DLoc),
Msg(Msg) {}

/// \see DiagnosticInfo::print.
void print(DiagnosticPrinter &DP) const override;
Expand All @@ -263,6 +266,16 @@ class DiagnosticInfoOptimizationRemark : public DiagnosticInfo {
return DI->getKind() == DK_OptimizationRemark;
}

/// Return true if this optimization remark is enabled by one of
/// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
/// or -pass-remarks-analysis). Note that this only handles the LLVM
/// flags. We cannot access Clang flags from here (they are handled
/// in BackendConsumer::OptimizationRemarkHandler).
///
/// \p pImpl points to the current LLVM context. It is needed to query the
/// value of the command line flag associated with this remark.
virtual bool isEnabled(LLVMContextImpl *pImpl) const = 0;

/// Return true if location information is available for this diagnostic.
bool isLocationAvailable() const;

Expand Down Expand Up @@ -296,9 +309,119 @@ class DiagnosticInfoOptimizationRemark : public DiagnosticInfo {
const Twine &Msg;
};

/// Diagnostic information for applied optimization remarks.
class DiagnosticInfoOptimizationRemark
: public DiagnosticInfoOptimizationRemarkBase {
public:
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass=, then the
/// diagnostic will be emitted. \p Fn is the function where the diagnostic
/// is being emitted. \p DLoc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic
/// will include the source code location. \p Msg is the message to show.
/// Note that this class does not copy this message, so this reference
/// must be valid for the whole life time of the diagnostic.
DiagnosticInfoOptimizationRemark(const char *PassName, const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg)
: DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemark, PassName,
Fn, DLoc, Msg) {}

/// Hand rolled RTTI
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemark;
}

/// \see DiagnosticInfoOptimizationRemarkBase::isEnabled.
virtual bool isEnabled(LLVMContextImpl *pImpl) const override;
};

/// Diagnostic information for missed-optimization remarks.
class DiagnosticInfoOptimizationRemarkMissed
: public DiagnosticInfoOptimizationRemarkBase {
public:
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-missed=, then the
/// diagnostic will be emitted. \p Fn is the function where the diagnostic
/// is being emitted. \p DLoc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic
/// will include the source code location. \p Msg is the message to show.
/// Note that this class does not copy this message, so this reference
/// must be valid for the whole life time of the diagnostic.
DiagnosticInfoOptimizationRemarkMissed(const char *PassName,
const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg)
: DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkMissed,
PassName, Fn, DLoc, Msg) {}

/// Hand rolled RTTI
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkMissed;
}

/// \see DiagnosticInfoOptimizationRemarkBase::isEnabled.
virtual bool isEnabled(LLVMContextImpl *pImpl) const override;
};

/// Diagnostic information for optimization analysis remarks.
class DiagnosticInfoOptimizationRemarkAnalysis
: public DiagnosticInfoOptimizationRemarkBase {
public:
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-analysis=, then
/// the diagnostic will be emitted. \p Fn is the function where the diagnostic
/// is being emitted. \p DLoc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic will
/// include the source code location. \p Msg is the message to show. Note that
/// this class does not copy this message, so this reference must be valid for
/// the whole life time of the diagnostic.
DiagnosticInfoOptimizationRemarkAnalysis(const char *PassName,
const Function &Fn,
const DebugLoc &DLoc,
const Twine &Msg)
: DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkAnalysis,
PassName, Fn, DLoc, Msg) {}

/// Hand rolled RTTI
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkAnalysis;
}

/// \see DiagnosticInfoOptimizationRemarkBase::isEnabled.
virtual bool isEnabled(LLVMContextImpl *pImpl) const override;
};

// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)

/// Emit an optimization-applied message. \p PassName is the name of the pass
/// emitting the message. If -Rpass= is given and \p PassName matches the
/// regular expression in -Rpass, then the remark will be emitted. \p Fn is
/// the function triggering the remark, \p DLoc is the debug location where
/// the diagnostic is generated. \p Msg is the message string to use.
void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
const Function &Fn, const DebugLoc &DLoc,
const Twine &Msg);

/// Emit an optimization-missed message. \p PassName is the name of the
/// pass emitting the message. If -Rpass-missed= is given and \p PassName
/// matches the regular expression in -Rpass, then the remark will be
/// emitted. \p Fn is the function triggering the remark, \p DLoc is the
/// debug location where the diagnostic is generated. \p Msg is the
/// message string to use.
void emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
const Function &Fn, const DebugLoc &DLoc,
const Twine &Msg);

/// Emit an optimization analysis remark message. \p PassName is the name of
/// the pass emitting the message. If -Rpass-analysis= is given and \p
/// PassName matches the regular expression in -Rpass, then the remark will be
/// emitted. \p Fn is the function triggering the remark, \p DLoc is the debug
/// location where the diagnostic is generated. \p Msg is the message string
/// to use.
void emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName,
const Function &Fn, const DebugLoc &DLoc,
const Twine &Msg);

} // End namespace llvm

#endif
9 changes: 0 additions & 9 deletions llvm/include/llvm/IR/LLVMContext.h
Expand Up @@ -157,15 +157,6 @@ class LLVMContext {
void emitError(const Instruction *I, const Twine &ErrorStr);
void emitError(const Twine &ErrorStr);

/// emitOptimizationRemark - Emit an optimization remark message. \p PassName
/// is the name of the pass emitting the message. If -Rpass= is given
/// and \p PassName matches the regular expression in -Rpass, then the
/// remark will be emitted. \p Fn is the function triggering the remark,
/// \p DLoc is the debug location where the diagnostic is generated.
/// \p Msg is the message string to use.
void emitOptimizationRemark(const char *PassName, const Function &Fn,
const DebugLoc &DLoc, const Twine &Msg);

private:
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
Expand Down
50 changes: 44 additions & 6 deletions llvm/lib/IR/DiagnosticInfo.cpp
Expand Up @@ -12,6 +12,7 @@
// Diagnostics reporting is still done as part of the LLVMContext.
//===----------------------------------------------------------------------===//

#include "LLVMContextImpl.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
Expand Down Expand Up @@ -67,20 +68,20 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
DP << getMsg();
}

bool DiagnosticInfoOptimizationRemark::isLocationAvailable() const {
bool DiagnosticInfoOptimizationRemarkBase::isLocationAvailable() const {
return getFunction().getParent()->getNamedMetadata("llvm.dbg.cu") != nullptr;
}

void DiagnosticInfoOptimizationRemark::getLocation(StringRef *Filename,
unsigned *Line,
unsigned *Column) const {
void DiagnosticInfoOptimizationRemarkBase::getLocation(StringRef *Filename,
unsigned *Line,
unsigned *Column) const {
DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext()));
*Filename = DIL.getFilename();
*Line = DIL.getLineNumber();
*Column = DIL.getColumnNumber();
}

const std::string DiagnosticInfoOptimizationRemark::getLocationStr() const {
const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const {
StringRef Filename("<unknown>");
unsigned Line = 0;
unsigned Column = 0;
Expand All @@ -89,6 +90,43 @@ const std::string DiagnosticInfoOptimizationRemark::getLocationStr() const {
return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
}

void DiagnosticInfoOptimizationRemark::print(DiagnosticPrinter &DP) const {
void DiagnosticInfoOptimizationRemarkBase::print(DiagnosticPrinter &DP) const {
DP << getLocationStr() << ": " << getMsg();
}

bool
DiagnosticInfoOptimizationRemark::isEnabled(LLVMContextImpl *pImpl) const {
return pImpl->optimizationRemarkEnabledFor(this);
}

bool DiagnosticInfoOptimizationRemarkMissed::isEnabled(
LLVMContextImpl *pImpl) const {
return pImpl->optimizationRemarkEnabledFor(this);
}

bool DiagnosticInfoOptimizationRemarkAnalysis::isEnabled(
LLVMContextImpl *pImpl) const {
return pImpl->optimizationRemarkEnabledFor(this);
}

void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
const Function &Fn, const DebugLoc &DLoc,
const Twine &Msg) {
Ctx.diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg));
}

void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
const Function &Fn,
const DebugLoc &DLoc,
const Twine &Msg) {
Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, Fn, DLoc, Msg));
}

void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
const char *PassName,
const Function &Fn,
const DebugLoc &DLoc,
const Twine &Msg) {
Ctx.diagnose(
DiagnosticInfoOptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg));
}
35 changes: 20 additions & 15 deletions llvm/lib/IR/LLVMContext.cpp
Expand Up @@ -142,14 +142,26 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
return;
}

// Optimization remarks are selective. They need to check whether
// the regexp pattern, passed via -pass-remarks, matches the name
// of the pass that is emitting the diagnostic. If there is no match,
// ignore the diagnostic and return.
if (DI.getKind() == llvm::DK_OptimizationRemark &&
!pImpl->optimizationRemarksEnabledFor(
cast<DiagnosticInfoOptimizationRemark>(DI).getPassName()))
return;
// Optimization remarks are selective. They need to check whether the regexp
// pattern, passed via one of the -pass-remarks* flags, matches the name of
// the pass that is emitting the diagnostic. If there is no match, ignore the
// diagnostic and return.
switch (DI.getKind()) {
case llvm::DK_OptimizationRemark:
if (!cast<DiagnosticInfoOptimizationRemark>(DI).isEnabled(pImpl))
return;
break;
case llvm::DK_OptimizationRemarkMissed:
if (!cast<DiagnosticInfoOptimizationRemarkMissed>(DI).isEnabled(pImpl))
return;
break;
case llvm::DK_OptimizationRemarkAnalysis:
if (!cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI).isEnabled(pImpl))
return;
break;
default:
break;
}

// Otherwise, print the message with a prefix based on the severity.
std::string MsgStorage;
Expand Down Expand Up @@ -177,13 +189,6 @@ void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
}

void LLVMContext::emitOptimizationRemark(const char *PassName,
const Function &Fn,
const DebugLoc &DLoc,
const Twine &Msg) {
diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg));
}

//===----------------------------------------------------------------------===//
// Metadata Kind Uniquing
//===----------------------------------------------------------------------===//
Expand Down

0 comments on commit 7f8af8b

Please sign in to comment.