mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 01:11:44 +00:00
[OptRemark,LDist] RFC: Add hotness attribute
Summary: This is the first set of changes implementing the RFC from http://thread.gmane.org/gmane.comp.compilers.llvm.devel/98334 This is a cross-sectional patch; rather than implementing the hotness attribute for all optimization remarks and all passes in a patch set, it implements it for the 'missed-optimization' remark for Loop Distribution. My goal is to shake out the design issues before scaling it up to other types and passes. Hotness is computed as an integer as the multiplication of the block frequency with the function entry count. It's only printed in opt currently since clang prints the diagnostic fields directly. E.g.: remark: /tmp/t.c:3:3: loop not distributed: use -Rpass-analysis=loop-distribute for more info (hotness: 300) A new API added is similar to emitOptimizationRemarkMissed. The difference is that it additionally takes a code region that the diagnostic corresponds to. From this, hotness is computed using BFI. The new API is exposed via an analysis pass so that it can be made dependent on LazyBFI. (Thanks to Hal for the analysis pass idea.) This feature can all be enabled by setDiagnosticHotnessRequested in the LLVM context. If this is off, LazyBFI is not calculated (D22141) so there should be no overhead. A new command-line option is added to turn this on in opt. My plan is to switch all user of emitOptimizationRemark* to use this module instead. Reviewers: hfinkel Subscribers: rcox2, mzolotukhin, llvm-commits Differential Revision: http://reviews.llvm.org/D21771 llvm-svn: 275583
This commit is contained in:
parent
58e21cf3cd
commit
cb89dd6834
66
include/llvm/Analysis/OptimizationDiagnosticInfo.h
Normal file
66
include/llvm/Analysis/OptimizationDiagnosticInfo.h
Normal file
@ -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<uint64_t> computeHotness(Value *V);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_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<uint64_t> 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<uint64_t> 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<uint64_t> 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;
|
||||
|
@ -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);
|
||||
|
@ -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&);
|
||||
|
@ -64,6 +64,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
|
||||
initializeModuleDebugInfoPrinterPass(Registry);
|
||||
initializeModuleSummaryIndexWrapperPassPass(Registry);
|
||||
initializeObjCARCAAWrapperPassPass(Registry);
|
||||
initializeOptimizationRemarkEmitterPass(Registry);
|
||||
initializePostDominatorTreeWrapperPassPass(Registry);
|
||||
initializeRegionInfoPassPass(Registry);
|
||||
initializeRegionViewerPass(Registry);
|
||||
|
@ -57,6 +57,7 @@ add_llvm_library(LLVMAnalysis
|
||||
ObjCARCAliasAnalysis.cpp
|
||||
ObjCARCAnalysisUtils.cpp
|
||||
ObjCARCInstKind.cpp
|
||||
OptimizationDiagnosticInfo.cpp
|
||||
OrderedBasicBlock.cpp
|
||||
PHITransAddr.cpp
|
||||
PostDominators.cpp
|
||||
|
69
lib/Analysis/OptimizationDiagnosticInfo.cpp
Normal file
69
lib/Analysis/OptimizationDiagnosticInfo.cpp
Normal file
@ -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<uint64_t> OptimizationRemarkEmitter::computeHotness(Value *V) {
|
||||
if (!BFI)
|
||||
return None;
|
||||
|
||||
return BFI->getBlockProfileCount(cast<BasicBlock>(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<LazyBlockFrequencyInfoPass>().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)
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
|
||||
DiagnosticHandler = nullptr;
|
||||
DiagnosticContext = nullptr;
|
||||
RespectDiagnosticFilters = false;
|
||||
DiagnosticHotnessRequested = false;
|
||||
YieldCallback = nullptr;
|
||||
YieldOpaqueHandle = nullptr;
|
||||
NamedStructTypesUniqueID = 0;
|
||||
|
@ -1043,6 +1043,7 @@ public:
|
||||
LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
|
||||
void *DiagnosticContext;
|
||||
bool RespectDiagnosticFilters;
|
||||
bool DiagnosticHotnessRequested;
|
||||
|
||||
LLVMContext::YieldCallbackTy YieldCallback;
|
||||
void *YieldOpaqueHandle;
|
||||
|
@ -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<LoopAccessLegacyAnalysis>();
|
||||
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
auto *ORE = &getAnalysis<OptimizationRemarkEmitter>();
|
||||
|
||||
// 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<LoopAccessLegacyAnalysis>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<OptimizationRemarkEmitter>();
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -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}
|
74
test/Transforms/LoopDistribute/diagnostics-with-hotness.ll
Normal file
74
test/Transforms/LoopDistribute/diagnostics-with-hotness.ll
Normal file
@ -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}
|
@ -215,6 +215,11 @@ static cl::opt<bool> DiscardValueNames(
|
||||
cl::desc("Discard names from Value (other than GlobalValue)."),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool> 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<Module> M = parseIRFile(InputFilename, Err, Context);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user