Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -160,7 +160,8 @@ const Function &Fn, const DebugLoc &DLoc, const Twine &Msg) { - diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg)); + if (pImpl->optimizationRemarksEnabledFor(PassName)) + diagnose(DiagnosticInfoOptimizationRemark(PassName, Fn, DLoc, Msg)); } //===----------------------------------------------------------------------===// Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -368,6 +368,10 @@ typedef DenseMap PrefixDataMapTy; PrefixDataMapTy PrefixDataMap; + /// \brief Return true if the given pass name should emit optimization + /// remarks. + bool optimizationRemarksEnabledFor(const char *PassName) const; + int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx); int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx); Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -15,6 +15,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Regex.h" #include using namespace llvm; @@ -43,6 +45,59 @@ } namespace { + +/// \brief Regular expression corresponding to the value given in the +/// command line flag -pass-remarks. Passes whose name matches this +/// regexp will emit a diagnostic when calling +/// LLVMContext::emitOptimizationRemark. +static Regex *OptimizationRemarkPattern; + +/// \brief String to hold all the values passed via -pass-remarks. Every +/// instance of -pass-remarks on the command line will be concatenated +/// to this string. Values are stored inside braces and concatenated with +/// the '|' operator. This implements the expected semantics that multiple +/// -pass-remarks are additive. +static std::string OptimizationRemarkExpr; + +struct PassRemarksOpt { + void operator=(const std::string &Val) const { + // Create a regexp object to match pass names for emitOptimizationRemark. + if (!Val.empty()) { + if (!OptimizationRemarkExpr.empty()) + OptimizationRemarkExpr += "|"; + OptimizationRemarkExpr += "(" + Val + ")"; + delete OptimizationRemarkPattern; + OptimizationRemarkPattern = new Regex(OptimizationRemarkExpr); + std::string RegexError; + if (!OptimizationRemarkPattern->isValid(RegexError)) + report_fatal_error("Invalid regular expression '" + Val + + "' in -pass-remarks: " + RegexError, + false); + } + }; +}; + +static PassRemarksOpt PassRemarksOptLoc; + +// -pass-remarks +// Command line flag to enable LLVMContext::emitOptimizationRemark() +// and LLVMContext::emitOptimizationNote() calls. +static cl::opt> +PassRemarks("pass-remarks", cl::value_desc("pattern"), + cl::desc("Enable optimization remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired, + cl::ZeroOrMore); +} + +bool +LLVMContextImpl::optimizationRemarksEnabledFor(const char *PassName) const { + return OptimizationRemarkPattern && + OptimizationRemarkPattern->match(PassName); +} + + +namespace { struct DropReferences { // Takes the value_type of a ConstantUniqueMap's internal map, whose 'second' // is a Constant*. Index: test/Other/optimization-remarks-inline.ll =================================================================== --- /dev/null +++ test/Other/optimization-remarks-inline.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -inline -pass-remarks='inline' -S 2>&1 | FileCheck %s +; RUN: opt < %s -inline -pass-remarks='inl.*' -S 2>&1 | FileCheck %s +; RUN: opt < %s -inline -pass-remarks='vector' -pass-remarks='inl' -S 2>&1 | FileCheck %s +; RUN: opt < %s -inline -pass-remarks='vector' -S 2>&1 | FileCheck --check-prefix=REMARKS %s +; RUN: opt < %s -inline -S 2>&1 | FileCheck --check-prefix=REMARKS %s +; RUN: not opt < %s -pass-remarks='(' 2>&1 | FileCheck --check-prefix=BAD-REGEXP %s + +define i32 @foo(i32 %x, i32 %y) #0 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %0 = load i32* %x.addr, align 4 + %1 = load i32* %y.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +define i32 @bar(i32 %j) #0 { +entry: + %j.addr = alloca i32, align 4 + store i32 %j, i32* %j.addr, align 4 + %0 = load i32* %j.addr, align 4 + %1 = load i32* %j.addr, align 4 + %sub = sub nsw i32 %1, 2 + %call = call i32 @foo(i32 %0, i32 %sub) +; CHECK: foo inlined into bar +; REMARKS-NOT: foo inlined into bar + ret i32 %call +} + +; BAD-REGEXP: Invalid regular expression '(' in -pass-remarks: