forked from OSchip/llvm-project
Reapply r271728 after adding move cobstructor for ProfileSummaryInfo
llvm-svn: 271745
This commit is contained in:
parent
c1c67d651d
commit
019e0bf592
|
@ -0,0 +1,113 @@
|
|||
//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a pass that provides access to profile summary
|
||||
// information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
|
||||
#define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/IR/ProfileSummary.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
class ProfileSummary;
|
||||
/// \brief Analysis providing profile information.
|
||||
///
|
||||
/// This is an immutable analysis pass that provides ability to query global
|
||||
/// (program-level) profile information. The main APIs are isHotCount and
|
||||
/// isColdCount that tells whether a given profile count is considered hot/cold
|
||||
/// based on the profile summary. This also provides convenience methods to
|
||||
/// check whether a function is hot or cold.
|
||||
|
||||
// FIXME: Provide convenience methods to determine hotness/coldness of other IR
|
||||
// units. This would require making this depend on BFI.
|
||||
class ProfileSummaryInfo {
|
||||
private:
|
||||
Module &M;
|
||||
std::unique_ptr<ProfileSummary> Summary;
|
||||
void computeSummary();
|
||||
void computeThresholds();
|
||||
// Count thresholds to answer isHotCount and isColdCount queries.
|
||||
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
|
||||
|
||||
public:
|
||||
ProfileSummaryInfo(Module &M) : M(M) {}
|
||||
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
|
||||
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
|
||||
/// \brief Returns true if \p F is a hot function.
|
||||
bool isHotFunction(const Function *F);
|
||||
/// \brief Returns true if \p F is a cold function.
|
||||
bool isColdFunction(const Function *F);
|
||||
/// \brief Returns true if count \p C is considered hot.
|
||||
bool isHotCount(uint64_t C);
|
||||
/// \brief Returns true if count \p C is considered cold.
|
||||
bool isColdCount(uint64_t C);
|
||||
};
|
||||
|
||||
/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
|
||||
class ProfileSummaryInfoWrapperPass : public ImmutablePass {
|
||||
std::unique_ptr<ProfileSummaryInfo> PSI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
ProfileSummaryInfoWrapperPass();
|
||||
|
||||
ProfileSummaryInfo *getPSI(Module &M);
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
|
||||
class ProfileSummaryAnalysis
|
||||
: public AnalysisInfoMixin<ProfileSummaryAnalysis> {
|
||||
public:
|
||||
typedef ProfileSummaryInfo Result;
|
||||
|
||||
ProfileSummaryAnalysis() {}
|
||||
ProfileSummaryAnalysis(const ProfileSummaryAnalysis &Arg) {}
|
||||
ProfileSummaryAnalysis(ProfileSummaryAnalysis &&Arg) {}
|
||||
ProfileSummaryAnalysis &operator=(const ProfileSummaryAnalysis &RHS) {
|
||||
return *this;
|
||||
}
|
||||
ProfileSummaryAnalysis &operator=(ProfileSummaryAnalysis &&RHS) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Result run(Module &M);
|
||||
|
||||
private:
|
||||
friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// \brief Printer pass that uses \c ProfileSummaryAnalysis.
|
||||
class ProfileSummaryPrinterPass
|
||||
: public PassInfoMixin<ProfileSummaryPrinterPass> {
|
||||
raw_ostream &OS;
|
||||
|
||||
public:
|
||||
explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
|
||||
PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -254,6 +254,7 @@ void initializePreISelIntrinsicLoweringPass(PassRegistry&);
|
|||
void initializePrintFunctionPassWrapperPass(PassRegistry&);
|
||||
void initializePrintModulePassWrapperPass(PassRegistry&);
|
||||
void initializePrintBasicBlockPassPass(PassRegistry&);
|
||||
void initializeProfileSummaryInfoWrapperPassPass(PassRegistry &);
|
||||
void initializeProcessImplicitDefsPass(PassRegistry&);
|
||||
void initializePromotePassPass(PassRegistry&);
|
||||
void initializePruneEHPass(PassRegistry&);
|
||||
|
|
|
@ -57,6 +57,7 @@ add_llvm_library(LLVMAnalysis
|
|||
OrderedBasicBlock.cpp
|
||||
PHITransAddr.cpp
|
||||
PostDominators.cpp
|
||||
ProfileSummaryInfo.cpp
|
||||
PtrUseVisitor.cpp
|
||||
RegionInfo.cpp
|
||||
RegionPass.cpp
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
//===- ProfileSummaryInfo.cpp - Global profile summary information --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a pass that provides access to the global profile summary
|
||||
// information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/ProfileSummary.h"
|
||||
using namespace llvm;
|
||||
|
||||
// The following two parameters determine the threshold for a count to be
|
||||
// considered hot/cold. These two parameters are percentile values (multiplied
|
||||
// by 10000). If the counts are sorted in descending order, the minimum count to
|
||||
// reach ProfileSummaryCutoffHot gives the threshold to determine a hot count.
|
||||
// Similarly, the minimum count to reach ProfileSummaryCutoffCold gives the
|
||||
// threshold for determining cold count (everything <= this threshold is
|
||||
// considered cold).
|
||||
|
||||
static cl::opt<int> ProfileSummaryCutoffHot(
|
||||
"profile-summary-cutoff-hot", cl::Hidden, cl::init(999000), cl::ZeroOrMore,
|
||||
cl::desc("A count is hot if it exceeds the minimum count to"
|
||||
" reach this percentile of total counts."));
|
||||
|
||||
static cl::opt<int> ProfileSummaryCutoffCold(
|
||||
"profile-summary-cutoff-cold", cl::Hidden, cl::init(999999), cl::ZeroOrMore,
|
||||
cl::desc("A count is cold if it is below the minimum count"
|
||||
" to reach this percentile of total counts."));
|
||||
|
||||
// Find the minimum count to reach a desired percentile of counts.
|
||||
static uint64_t getMinCountForPercentile(SummaryEntryVector &DS,
|
||||
uint64_t Percentile) {
|
||||
auto Compare = [](const ProfileSummaryEntry &Entry, uint64_t Percentile) {
|
||||
return Entry.Cutoff < Percentile;
|
||||
};
|
||||
auto It = std::lower_bound(DS.begin(), DS.end(), Percentile, Compare);
|
||||
// The required percentile has to be <= one of the percentiles in the
|
||||
// detailed summary.
|
||||
if (It == DS.end())
|
||||
report_fatal_error("Desired percentile exceeds the maximum cutoff");
|
||||
return It->MinCount;
|
||||
}
|
||||
|
||||
// The profile summary metadata may be attached either by the frontend or by
|
||||
// any backend passes (IR level instrumentation, for example). This method
|
||||
// checks if the Summary is null and if so checks if the summary metadata is now
|
||||
// available in the module and parses it to get the Summary object.
|
||||
void ProfileSummaryInfo::computeSummary() {
|
||||
if (Summary)
|
||||
return;
|
||||
auto *SummaryMD = M.getProfileSummary();
|
||||
if (!SummaryMD)
|
||||
return;
|
||||
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
|
||||
}
|
||||
|
||||
// Returns true if the function is a hot function. If it returns false, it
|
||||
// either means it is not hot or it is unknown whether F is hot or not (for
|
||||
// example, no profile data is available).
|
||||
bool ProfileSummaryInfo::isHotFunction(const Function *F) {
|
||||
computeSummary();
|
||||
if (!F || !Summary)
|
||||
return false;
|
||||
auto FunctionCount = F->getEntryCount();
|
||||
// FIXME: The heuristic used below for determining hotness is based on
|
||||
// preliminary SPEC tuning for inliner. This will eventually be a
|
||||
// convenience method that calls isHotCount.
|
||||
return (FunctionCount &&
|
||||
FunctionCount.getValue() >=
|
||||
(uint64_t)(0.3 * (double)Summary->getMaxFunctionCount()));
|
||||
}
|
||||
|
||||
// Returns true if the function is a cold function. If it returns false, it
|
||||
// either means it is not cold or it is unknown whether F is cold or not (for
|
||||
// example, no profile data is available).
|
||||
bool ProfileSummaryInfo::isColdFunction(const Function *F) {
|
||||
computeSummary();
|
||||
if (F->hasFnAttribute(Attribute::Cold)) {
|
||||
return true;
|
||||
}
|
||||
auto FunctionCount = F->getEntryCount();
|
||||
// FIXME: The heuristic used below for determining coldness is based on
|
||||
// preliminary SPEC tuning for inliner. This will eventually be a
|
||||
// convenience method that calls isHotCount.
|
||||
return (FunctionCount &&
|
||||
FunctionCount.getValue() <=
|
||||
(uint64_t)(0.01 * (double)Summary->getMaxFunctionCount()));
|
||||
}
|
||||
|
||||
// Compute the hot and cold thresholds.
|
||||
void ProfileSummaryInfo::computeThresholds() {
|
||||
if (!Summary)
|
||||
computeSummary();
|
||||
if (!Summary)
|
||||
return;
|
||||
auto &DetailedSummary = Summary->getDetailedSummary();
|
||||
HotCountThreshold =
|
||||
getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffHot);
|
||||
ColdCountThreshold =
|
||||
getMinCountForPercentile(DetailedSummary, ProfileSummaryCutoffCold);
|
||||
}
|
||||
|
||||
bool ProfileSummaryInfo::isHotCount(uint64_t C) {
|
||||
if (!HotCountThreshold)
|
||||
computeThresholds();
|
||||
return HotCountThreshold && C >= HotCountThreshold.getValue();
|
||||
}
|
||||
|
||||
bool ProfileSummaryInfo::isColdCount(uint64_t C) {
|
||||
if (!ColdCountThreshold)
|
||||
computeThresholds();
|
||||
return ColdCountThreshold && C <= ColdCountThreshold.getValue();
|
||||
}
|
||||
|
||||
ProfileSummaryInfo *ProfileSummaryInfoWrapperPass::getPSI(Module &M) {
|
||||
if (!PSI)
|
||||
PSI.reset(new ProfileSummaryInfo(M));
|
||||
return PSI.get();
|
||||
}
|
||||
|
||||
INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info",
|
||||
"Profile summary info", false, true)
|
||||
|
||||
ProfileSummaryInfoWrapperPass::ProfileSummaryInfoWrapperPass()
|
||||
: ImmutablePass(ID) {
|
||||
initializeProfileSummaryInfoWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
char ProfileSummaryAnalysis::PassID;
|
||||
ProfileSummaryInfo ProfileSummaryAnalysis::run(Module &M) {
|
||||
return ProfileSummaryInfo(M);
|
||||
}
|
||||
|
||||
// FIXME: This only tests isHotFunction and isColdFunction and not the
|
||||
// isHotCount and isColdCount calls.
|
||||
PreservedAnalyses ProfileSummaryPrinterPass::run(Module &M,
|
||||
AnalysisManager<Module> &AM) {
|
||||
ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(M);
|
||||
|
||||
OS << "Functions in " << M.getName() << " with hot/cold annotations: \n";
|
||||
for (auto &F : M) {
|
||||
OS << F.getName();
|
||||
if (PSI.isHotFunction(&F))
|
||||
OS << " :hot ";
|
||||
else if (PSI.isColdFunction(&F))
|
||||
OS << " :cold ";
|
||||
OS << "\n";
|
||||
}
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
char ProfileSummaryInfoWrapperPass::ID = 0;
|
|
@ -144,6 +144,8 @@ static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) {
|
|||
}
|
||||
|
||||
ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
|
||||
if (!MD)
|
||||
return nullptr;
|
||||
if (!isa<MDTuple>(MD))
|
||||
return nullptr;
|
||||
MDTuple *Tuple = cast<MDTuple>(MD);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
#include "llvm/Analysis/RegionInfo.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
|
@ -68,8 +69,8 @@
|
|||
#include "llvm/Transforms/Scalar/DCE.h"
|
||||
#include "llvm/Transforms/Scalar/DeadStoreElimination.h"
|
||||
#include "llvm/Transforms/Scalar/EarlyCSE.h"
|
||||
#include "llvm/Transforms/Scalar/GVN.h"
|
||||
#include "llvm/Transforms/Scalar/GuardWidening.h"
|
||||
#include "llvm/Transforms/Scalar/GVN.h"
|
||||
#include "llvm/Transforms/Scalar/LoopRotation.h"
|
||||
#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
|
||||
#include "llvm/Transforms/Scalar/LowerAtomic.h"
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
MODULE_ANALYSIS("callgraph", CallGraphAnalysis())
|
||||
MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis())
|
||||
MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis())
|
||||
MODULE_ANALYSIS("profile-summary", ProfileSummaryAnalysis())
|
||||
MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis())
|
||||
MODULE_ANALYSIS("verify", VerifierAnalysis())
|
||||
|
||||
|
@ -50,8 +51,9 @@ MODULE_PASS("no-op-module", NoOpModulePass())
|
|||
MODULE_PASS("pgo-icall-prom", PGOIndirectCallPromotion())
|
||||
MODULE_PASS("pgo-instr-gen", PGOInstrumentationGen())
|
||||
MODULE_PASS("pgo-instr-use", PGOInstrumentationUse())
|
||||
MODULE_PASS("print", PrintModulePass(dbgs()))
|
||||
MODULE_PASS("print-profile-summary", ProfileSummaryPrinterPass(dbgs()))
|
||||
MODULE_PASS("print-callgraph", CallGraphPrinterPass(dbgs()))
|
||||
MODULE_PASS("print", PrintModulePass(dbgs()))
|
||||
MODULE_PASS("print-lcg", LazyCallGraphPrinterPass(dbgs()))
|
||||
MODULE_PASS("sample-profile", SampleProfileLoaderPass())
|
||||
MODULE_PASS("strip-dead-prototypes", StripDeadPrototypesPass())
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
; RUN: opt < %s -disable-output -passes=print-profile-summary -S 2>&1 | FileCheck %s
|
||||
|
||||
define void @f1() !prof !20 {
|
||||
; CHECK-LABEL: f1 :hot
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f2() !prof !21 {
|
||||
; CHECK-LABEL: f2 :cold
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f3() !prof !22 {
|
||||
; CHECK-LABEL: f3
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!1}
|
||||
!20 = !{!"function_entry_count", i64 400}
|
||||
!21 = !{!"function_entry_count", i64 1}
|
||||
!22 = !{!"function_entry_count", i64 100}
|
||||
|
||||
!1 = !{i32 1, !"ProfileSummary", !2}
|
||||
!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
|
||||
!3 = !{!"ProfileFormat", !"InstrProf"}
|
||||
!4 = !{!"TotalCount", i64 10000}
|
||||
!5 = !{!"MaxCount", i64 10}
|
||||
!6 = !{!"MaxInternalCount", i64 1}
|
||||
!7 = !{!"MaxFunctionCount", i64 1000}
|
||||
!8 = !{!"NumCounts", i64 3}
|
||||
!9 = !{!"NumFunctions", i64 3}
|
||||
!10 = !{!"DetailedSummary", !11}
|
||||
!11 = !{!12, !13, !14}
|
||||
!12 = !{i32 10000, i64 100, i32 1}
|
||||
!13 = !{i32 999000, i64 100, i32 1}
|
||||
!14 = !{i32 999999, i64 1, i32 2}
|
Loading…
Reference in New Issue