diff --git a/include/llvm/Analysis/OptimizationDiagnosticInfo.h b/include/llvm/Analysis/OptimizationDiagnosticInfo.h new file mode 100644 index 00000000000..04e49a78e26 --- /dev/null +++ b/include/llvm/Analysis/OptimizationDiagnosticInfo.h @@ -0,0 +1,66 @@ +//===- OptimizationDiagnosticInfo.h - Optimization Diagnostic ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Optimization diagnostic interfaces. It's packaged as an analysis pass so +// that by using this service passes become dependent on BFI as well. BFI is +// used to compute the "hotness" of the diagnostic message. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H +#define LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Pass.h" + +namespace llvm { +class BlockFrequencyInfo; +class DebugLoc; +class Function; +class LLVMContext; +class Loop; +class Pass; +class Twine; +class Value; + +class OptimizationRemarkEmitter : public FunctionPass { +public: + OptimizationRemarkEmitter(); + + /// Emit an optimization-missed message. + /// + /// \p PassName is the name of the pass emitting the message. If + /// -Rpass-missed= is given and the name 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 V is the IR Value that identifies the code region. \p Msg is + /// the message string to use. + void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc, + Value *V, const Twine &Msg); + + /// \brief Same as above but derives the IR Value for the code region and the + /// debug location from the Loop parameter \p L. + void emitOptimizationRemarkMissed(const char *PassName, Loop *L, + const Twine &Msg); + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + static char ID; + +private: + Function *F; + + BlockFrequencyInfo *BFI; + + Optional computeHotness(Value *V); +}; +} + +#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 02265cff9ce..1c78684da64 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_DIAGNOSTICINFO_H #define LLVM_IR_DIAGNOSTICINFO_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DebugLoc.h" @@ -383,9 +384,10 @@ public: DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind, enum DiagnosticSeverity Severity, const char *PassName, const Function &Fn, - const DebugLoc &DLoc, const Twine &Msg) + const DebugLoc &DLoc, const Twine &Msg, + Optional Hotness = None) : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc), - PassName(PassName), Msg(Msg) {} + PassName(PassName), Msg(Msg), Hotness(Hotness) {} /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; @@ -413,6 +415,10 @@ private: /// Message to report. const Twine &Msg; + + /// If profile information is available, this is the number of times the + /// corresponding code was executed in a profile instrumentation run. + Optional Hotness; }; /// Diagnostic information for applied optimization remarks. @@ -453,9 +459,10 @@ public: /// must be valid for the whole life time of the diagnostic. DiagnosticInfoOptimizationRemarkMissed(const char *PassName, const Function &Fn, - const DebugLoc &DLoc, const Twine &Msg) + const DebugLoc &DLoc, const Twine &Msg, + Optional Hotness = None) : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark, - PassName, Fn, DLoc, Msg) {} + PassName, Fn, DLoc, Msg, Hotness) {} static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_OptimizationRemarkMissed; diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 6f7a9503745..dbf2b456233 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -174,6 +174,13 @@ public: /// setDiagnosticContext. void *getDiagnosticContext() const; + /// \brief Return if a code hotness metric should be included in optimization + /// diagnostics. + bool getDiagnosticHotnessRequested() const; + /// \brief Set if a code hotness metric should be included in optimization + /// diagnostics. + void setDiagnosticHotnessRequested(bool Requested); + /// \brief Get the prefix that should be printed in front of a diagnostic of /// the given \p Severity static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity); diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 31803205156..20eaa89362d 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -243,6 +243,7 @@ void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); +void initializeOptimizationRemarkEmitterPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); void initializePAEvalPass(PassRegistry &); void initializePEIPass(PassRegistry&); diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp index 2bcfe402e68..ffc4b2ef592 100644 --- a/lib/Analysis/Analysis.cpp +++ b/lib/Analysis/Analysis.cpp @@ -64,6 +64,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeModuleDebugInfoPrinterPass(Registry); initializeModuleSummaryIndexWrapperPassPass(Registry); initializeObjCARCAAWrapperPassPass(Registry); + initializeOptimizationRemarkEmitterPass(Registry); initializePostDominatorTreeWrapperPassPass(Registry); initializeRegionInfoPassPass(Registry); initializeRegionViewerPass(Registry); diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 5c6011d77ce..57ad437ef4f 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -57,6 +57,7 @@ add_llvm_library(LLVMAnalysis ObjCARCAliasAnalysis.cpp ObjCARCAnalysisUtils.cpp ObjCARCInstKind.cpp + OptimizationDiagnosticInfo.cpp OrderedBasicBlock.cpp PHITransAddr.cpp PostDominators.cpp diff --git a/lib/Analysis/OptimizationDiagnosticInfo.cpp b/lib/Analysis/OptimizationDiagnosticInfo.cpp new file mode 100644 index 00000000000..9a22633b6e4 --- /dev/null +++ b/lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -0,0 +1,69 @@ +//===- OptimizationDiagnosticInfo.cpp - Optimization Diagnostic -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Optimization diagnostic interfaces. It's packaged as an analysis pass so +// that by using this service passes become dependent on BFI as well. BFI is +// used to compute the "hotness" of the diagnostic message. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" +#include "llvm/Analysis/LazyBlockFrequencyInfo.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/LLVMContext.h" + +using namespace llvm; + +OptimizationRemarkEmitter::OptimizationRemarkEmitter() : FunctionPass(ID) { + initializeOptimizationRemarkEmitterPass(*PassRegistry::getPassRegistry()); +} + +Optional OptimizationRemarkEmitter::computeHotness(Value *V) { + if (!BFI) + return None; + + return BFI->getBlockProfileCount(cast(V)); +} + +void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( + const char *PassName, const DebugLoc &DLoc, Value *V, const Twine &Msg) { + LLVMContext &Ctx = F->getContext(); + Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg, + computeHotness(V))); +} + +void OptimizationRemarkEmitter::emitOptimizationRemarkMissed( + const char *PassName, Loop *L, const Twine &Msg) { + emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg); +} + +bool OptimizationRemarkEmitter::runOnFunction(Function &Fn) { + F = &Fn; + + if (Fn.getContext().getDiagnosticHotnessRequested()) + BFI = &getAnalysis().getBFI(); + else + BFI = nullptr; + + return false; +} + +void OptimizationRemarkEmitter::getAnalysisUsage(AnalysisUsage &AU) const { + LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); + AU.setPreservesAll(); +} + +char OptimizationRemarkEmitter::ID = 0; +static const char ore_name[] = "Optimization Remark Emitter"; +#define ORE_NAME "opt-remark-emitter" + +INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitter, ORE_NAME, ore_name, false, + true) +INITIALIZE_PASS_DEPENDENCY(LazyBFIPass) +INITIALIZE_PASS_END(OptimizationRemarkEmitter, ORE_NAME, ore_name, false, true) diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index a3214d72132..ce67be328ab 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -172,6 +172,8 @@ const std::string DiagnosticInfoWithDebugLocBase::getLocationStr() const { void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { DP << getLocationStr() << ": " << getMsg(); + if (Hotness) + DP << " (hotness: " << *Hotness << ")"; } bool DiagnosticInfoOptimizationRemark::isEnabled() const { diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index c7ba400ced1..d27fcfb1b7a 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -196,6 +196,13 @@ void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, pImpl->RespectDiagnosticFilters = RespectFilters; } +void LLVMContext::setDiagnosticHotnessRequested(bool Requested) { + pImpl->DiagnosticHotnessRequested = Requested; +} +bool LLVMContext::getDiagnosticHotnessRequested() const { + return pImpl->DiagnosticHotnessRequested; +} + LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { return pImpl->DiagnosticHandler; } diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 3e354b5e0cf..b0b2c61bdf1 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -45,6 +45,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) DiagnosticHandler = nullptr; DiagnosticContext = nullptr; RespectDiagnosticFilters = false; + DiagnosticHotnessRequested = false; YieldCallback = nullptr; YieldOpaqueHandle = nullptr; NamedStructTypesUniqueID = 0; diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index cb4e79ac74e..7820e2ab958 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -1043,6 +1043,7 @@ public: LLVMContext::DiagnosticHandlerTy DiagnosticHandler; void *DiagnosticContext; bool RespectDiagnosticFilters; + bool DiagnosticHotnessRequested; LLVMContext::YieldCallbackTy YieldCallback; void *YieldOpaqueHandle; diff --git a/lib/Transforms/Scalar/LoopDistribute.cpp b/lib/Transforms/Scalar/LoopDistribute.cpp index 6133c251f3b..e09b33b29f7 100644 --- a/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/lib/Transforms/Scalar/LoopDistribute.cpp @@ -26,8 +26,10 @@ #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/Pass.h" @@ -589,8 +591,8 @@ private: class LoopDistributeForLoop { public: LoopDistributeForLoop(Loop *L, Function *F, LoopInfo *LI, DominatorTree *DT, - ScalarEvolution *SE) - : L(L), F(F), LI(LI), LAI(nullptr), DT(DT), SE(SE) { + ScalarEvolution *SE, OptimizationRemarkEmitter *ORE) + : L(L), F(F), LI(LI), LAI(nullptr), DT(DT), SE(SE), ORE(ORE) { setForced(); } @@ -757,8 +759,8 @@ public: DEBUG(dbgs() << "Skipping; " << Message << "\n"); // With Rpass-missed report that distribution failed. - emitOptimizationRemarkMissed( - Ctx, LDIST_NAME, *F, L->getStartLoc(), + ORE->emitOptimizationRemarkMissed( + LDIST_NAME, L, "loop not distributed: use -Rpass-analysis=loop-distribute for more " "info"); @@ -847,6 +849,7 @@ private: const LoopAccessInfo *LAI; DominatorTree *DT; ScalarEvolution *SE; + OptimizationRemarkEmitter *ORE; /// \brief Indicates whether distribution is forced to be enabled/disabled for /// the loop. @@ -880,6 +883,7 @@ public: auto *LAA = &getAnalysis(); auto *DT = &getAnalysis().getDomTree(); auto *SE = &getAnalysis().getSE(); + auto *ORE = &getAnalysis(); // Build up a worklist of inner-loops to vectorize. This is necessary as the // act of distributing a loop creates new loops and can invalidate iterators @@ -895,7 +899,7 @@ public: // Now walk the identified inner loops. bool Changed = false; for (Loop *L : Worklist) { - LoopDistributeForLoop LDL(L, &F, LI, DT, SE); + LoopDistributeForLoop LDL(L, &F, LI, DT, SE, ORE); // If distribution was forced for the specific loop to be // enabled/disabled, follow that. Otherwise use the global flag. @@ -914,6 +918,7 @@ public: AU.addRequired(); AU.addRequired(); AU.addPreserved(); + AU.addRequired(); } static char ID; @@ -933,6 +938,7 @@ INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) +INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitter) INITIALIZE_PASS_END(LoopDistribute, LDIST_NAME, ldist_name, false, false) namespace llvm { diff --git a/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll b/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll new file mode 100644 index 00000000000..a67a71c5cfb --- /dev/null +++ b/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll @@ -0,0 +1,77 @@ +; Check that BFI is not computed when -pass-remarks-with-hotness is off + +; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: -debug-only=block-freq -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS +; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: -debug-only=block-freq < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS + +; REQUIRES: asserts + +; HOTNESS: block-frequency: forced +; NO_HOTNESS-NOT: block-frequency: forced + +; This is the input program: +; +; 1 void forced (char *A, char *B, char *C, int N) { +; 2 #pragma clang loop distribute(enable) +; 3 for(int i = 0; i < N; i++) { +; 4 A[i] = B[i] * C[i]; +; 5 } +; 6 } + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + + +define void @forced(i8* %A, i8* %B, i8* %C, i32 %N) !dbg !7 !prof !22 { +entry: + %cmp12 = icmp sgt i32 %N, 0, !dbg !9 + br i1 %cmp12, label %ph, label %for.cond.cleanup, !dbg !10, !prof !23 + +ph: + br label %for.body + +for.body: + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ] + %arrayidx = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !12 + %0 = load i8, i8* %arrayidx, align 1, !dbg !12, !tbaa !13 + %arrayidx2 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !16 + %1 = load i8, i8* %arrayidx2, align 1, !dbg !16, !tbaa !13 + %mul = mul i8 %1, %0, !dbg !17 + %arrayidx6 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !18 + store i8 %mul, i8* %arrayidx6, align 1, !dbg !19, !tbaa !13 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10 + %exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !10 + br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !10, !llvm.loop !20, !prof !24 + +for.cond.cleanup: + ret void, !dbg !11 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633) (llvm/trunk 267675)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "/tmp/t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 2} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DISubprogram(name: "forced", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 3, column: 20, scope: !7) +!10 = !DILocation(line: 3, column: 3, scope: !7) +!11 = !DILocation(line: 6, column: 1, scope: !7) +!12 = !DILocation(line: 4, column: 12, scope: !7) +!13 = !{!14, !14, i64 0} +!14 = !{!"omnipotent char", !15, i64 0} +!15 = !{!"Simple C/C++ TBAA"} +!16 = !DILocation(line: 4, column: 19, scope: !7) +!17 = !DILocation(line: 4, column: 17, scope: !7) +!18 = !DILocation(line: 4, column: 5, scope: !7) +!19 = !DILocation(line: 4, column: 10, scope: !7) +!20 = distinct !{!20, !21} +!21 = !{!"llvm.loop.distribute.enable", i1 true} +!22 = !{!"function_entry_count", i64 3} +!23 = !{!"branch_weights", i32 99, i32 1} +!24 = !{!"branch_weights", i32 1, i32 99} diff --git a/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll b/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll new file mode 100644 index 00000000000..21ddfcd6f52 --- /dev/null +++ b/test/Transforms/LoopDistribute/diagnostics-with-hotness.ll @@ -0,0 +1,74 @@ +; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS +; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS + +; REQUIRES: asserts + +; This is the input program: +; +; 1 void forced (char *A, char *B, char *C, int N) { +; 2 #pragma clang loop distribute(enable) +; 3 for(int i = 0; i < N; i++) { +; 4 A[i] = B[i] * C[i]; +; 5 } +; 6 } + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +; HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info (hotness: 300) +; NO_HOTNESS: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info{{$}} + +define void @forced(i8* %A, i8* %B, i8* %C, i32 %N) !dbg !7 !prof !22 { +entry: + %cmp12 = icmp sgt i32 %N, 0, !dbg !9 + br i1 %cmp12, label %ph, label %for.cond.cleanup, !dbg !10, !prof !23 + +ph: + br label %for.body + +for.body: + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ] + %arrayidx = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !12 + %0 = load i8, i8* %arrayidx, align 1, !dbg !12, !tbaa !13 + %arrayidx2 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !16 + %1 = load i8, i8* %arrayidx2, align 1, !dbg !16, !tbaa !13 + %mul = mul i8 %1, %0, !dbg !17 + %arrayidx6 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !18 + store i8 %mul, i8* %arrayidx6, align 1, !dbg !19, !tbaa !13 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10 + %exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !10 + br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !10, !llvm.loop !20, !prof !24 + +for.cond.cleanup: + ret void, !dbg !11 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 267633) (llvm/trunk 267675)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "/tmp/t.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 2} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DISubprogram(name: "forced", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 3, column: 20, scope: !7) +!10 = !DILocation(line: 3, column: 3, scope: !7) +!11 = !DILocation(line: 6, column: 1, scope: !7) +!12 = !DILocation(line: 4, column: 12, scope: !7) +!13 = !{!14, !14, i64 0} +!14 = !{!"omnipotent char", !15, i64 0} +!15 = !{!"Simple C/C++ TBAA"} +!16 = !DILocation(line: 4, column: 19, scope: !7) +!17 = !DILocation(line: 4, column: 17, scope: !7) +!18 = !DILocation(line: 4, column: 5, scope: !7) +!19 = !DILocation(line: 4, column: 10, scope: !7) +!20 = distinct !{!20, !21} +!21 = !{!"llvm.loop.distribute.enable", i1 true} +!22 = !{!"function_entry_count", i64 3} +!23 = !{!"branch_weights", i32 99, i32 1} +!24 = !{!"branch_weights", i32 1, i32 99} diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 8ad560323af..0a4ce1dfe8e 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -215,6 +215,11 @@ static cl::opt DiscardValueNames( cl::desc("Discard names from Value (other than GlobalValue)."), cl::init(false), cl::Hidden); +static cl::opt PassRemarksWithHotness( + "pass-remarks-with-hotness", + cl::desc("With PGO, include profile count in optimization remarks"), + cl::Hidden); + static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { // Add the pass to the pass manager... PM.add(P); @@ -384,6 +389,9 @@ int main(int argc, char **argv) { if (!DisableDITypeMap) Context.enableDebugTypeODRUniquing(); + if (PassRemarksWithHotness) + Context.setDiagnosticHotnessRequested(true); + // Load the input module... std::unique_ptr M = parseIRFile(InputFilename, Err, Context);