Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler-rt/include/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,12 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
#define INSTR_PROF_COVMAP_VERSION 6

/* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
* version for other variants of profile. We set the 8th most significant bit
* version for other variants of profile. We set the 8th most significant bit
* (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
* generated profile, and 0 if this is a Clang FE generated profile.
* 1 in bit 57 indicates there are context-sensitive records in the profile.
* The 54th bit indicates whether to always instrument loop entry blocks.
* The 58th bit indicates whether to always instrument function entry blocks.
* The 59th bit indicates whether to use debug info to correlate profiles.
* The 60th bit indicates single byte coverage instrumentation.
* The 61st bit indicates function entry instrumentation only.
Expand All @@ -742,6 +744,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
*/
#define VARIANT_MASKS_ALL 0xffffffff00000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
#define VARIANT_MASK_INSTR_LOOP_ENTRIES (0x1ULL << 55)
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/ProfileData/InstrProf.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,9 @@ enum class InstrProfKind {
MemProf = 0x40,
// A temporal profile.
TemporalProfile = 0x80,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/TemporalProfile)
// A profile with loop entry basic blocks instrumentation.
LoopEntriesInstrumentation = 0x100,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/LoopEntriesInstrumentation)
};

const std::error_category &instrprof_category();
Expand Down
5 changes: 4 additions & 1 deletion llvm/include/llvm/ProfileData/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -730,10 +730,12 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
#define INSTR_PROF_COVMAP_VERSION 6

/* Profile version is always of type uint64_t. Reserve the upper 32 bits in the
* version for other variants of profile. We set the 8th most significant bit
* version for other variants of profile. We set the 8th most significant bit
* (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation
* generated profile, and 0 if this is a Clang FE generated profile.
* 1 in bit 57 indicates there are context-sensitive records in the profile.
* The 54th bit indicates whether to always instrument loop entry blocks.
* The 58th bit indicates whether to always instrument function entry blocks.
* The 59th bit indicates whether to use debug info to correlate profiles.
* The 60th bit indicates single byte coverage instrumentation.
* The 61st bit indicates function entry instrumentation only.
Expand All @@ -742,6 +744,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
*/
#define VARIANT_MASKS_ALL 0xffffffff00000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
#define VARIANT_MASK_INSTR_LOOP_ENTRIES (0x1ULL << 55)
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58)
Expand Down
21 changes: 21 additions & 0 deletions llvm/include/llvm/ProfileData/InstrProfReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ class InstrProfReader {

virtual bool instrEntryBBEnabled() const = 0;

/// Return true if the profile instruments all loop entries.
virtual bool instrLoopEntriesEnabled() const = 0;

/// Return true if the profile has single byte counters representing coverage.
virtual bool hasSingleByteCoverage() const = 0;

Expand Down Expand Up @@ -274,6 +277,11 @@ class TextInstrProfReader : public InstrProfReader {
InstrProfKind::FunctionEntryInstrumentation);
}

bool instrLoopEntriesEnabled() const override {
return static_cast<bool>(ProfileKind &
InstrProfKind::LoopEntriesInstrumentation);
}

bool hasSingleByteCoverage() const override {
return static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage);
}
Expand Down Expand Up @@ -398,6 +406,10 @@ class RawInstrProfReader : public InstrProfReader {
return (Version & VARIANT_MASK_INSTR_ENTRY) != 0;
}

bool instrLoopEntriesEnabled() const override {
return (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) != 0;
}

bool hasSingleByteCoverage() const override {
return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
}
Expand Down Expand Up @@ -564,6 +576,7 @@ struct InstrProfReaderIndexBase {
virtual bool isIRLevelProfile() const = 0;
virtual bool hasCSIRLevelProfile() const = 0;
virtual bool instrEntryBBEnabled() const = 0;
virtual bool instrLoopEntriesEnabled() const = 0;
virtual bool hasSingleByteCoverage() const = 0;
virtual bool functionEntryOnly() const = 0;
virtual bool hasMemoryProfile() const = 0;
Expand Down Expand Up @@ -628,6 +641,10 @@ class InstrProfReaderIndex : public InstrProfReaderIndexBase {
return (FormatVersion & VARIANT_MASK_INSTR_ENTRY) != 0;
}

bool instrLoopEntriesEnabled() const override {
return (FormatVersion & VARIANT_MASK_INSTR_LOOP_ENTRIES) != 0;
}

bool hasSingleByteCoverage() const override {
return (FormatVersion & VARIANT_MASK_BYTE_COVERAGE) != 0;
}
Expand Down Expand Up @@ -753,6 +770,10 @@ class IndexedInstrProfReader : public InstrProfReader {
return Index->instrEntryBBEnabled();
}

bool instrLoopEntriesEnabled() const override {
return Index->instrLoopEntriesEnabled();
}

bool hasSingleByteCoverage() const override {
return Index->hasSingleByteCoverage();
}
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/ProfileData/InstrProfWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ class InstrProfWriter {
return make_error<InstrProfError>(instrprof_error::unsupported_version);
}
if (testIncompatible(InstrProfKind::FunctionEntryOnly,
InstrProfKind::FunctionEntryInstrumentation)) {
InstrProfKind::FunctionEntryInstrumentation) ||
testIncompatible(InstrProfKind::FunctionEntryOnly,
InstrProfKind::LoopEntriesInstrumentation)) {
return make_error<InstrProfError>(
instrprof_error::unsupported_version,
"cannot merge FunctionEntryOnly profiles and BB profiles together");
Expand Down
41 changes: 38 additions & 3 deletions llvm/include/llvm/Transforms/Instrumentation/CFGMST.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/BranchProbability.h"
Expand Down Expand Up @@ -52,10 +53,14 @@ template <class Edge, class BBInfo> class CFGMST {

BranchProbabilityInfo *const BPI;
BlockFrequencyInfo *const BFI;
LoopInfo *const LI;

// If function entry will be always instrumented.
const bool InstrumentFuncEntry;

// If true loop entries will be always instrumented.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If true loop entries will be always instrumented.
/// If true loop entries will be always instrumented.

I'm aware that other parts of this file do not follow the style guide, so maybe it's better to stay consistent instead.

const bool InstrumentLoopEntries;

// Find the root group of the G and compress the path from G to the root.
BBInfo *findAndCompressGroup(BBInfo *G) {
if (G->Group != G)
Expand Down Expand Up @@ -154,6 +159,16 @@ template <class Edge, class BBInfo> class CFGMST {
}
if (BPI != nullptr)
Weight = BPI->getEdgeProbability(&BB, TargetBB).scale(scaleFactor);
// If InstrumentLoopEntries is on and the current edge leads to a loop
// (i.e., TargetBB is a loop head and BB is outside its loop), set
// Weight to be minimal, so that the edge won't be chosen for the MST
// and will be instrumented.
if (InstrumentLoopEntries && LI->isLoopHeader(TargetBB)) {
Loop *TargetLoop = LI->getLoopFor(TargetBB);
assert(TargetLoop);
if (!TargetLoop->contains(&BB))
Weight = 0;
}
if (Weight == 0)
Weight++;
auto *E = &addEdge(&BB, TargetBB, Weight);
Expand Down Expand Up @@ -252,6 +267,19 @@ template <class Edge, class BBInfo> class CFGMST {
}
}

[[maybe_unused]] bool validateLoopEntryInstrumentation() {
if (!InstrumentLoopEntries)
return true;
for (auto &Ei : AllEdges) {
if (Ei->Removed)
continue;
if (Ei->DestBB && LI->isLoopHeader(Ei->DestBB) &&
!LI->getLoopFor(Ei->DestBB)->contains(Ei->SrcBB) && Ei->InMST)
return false;
}
return true;
}

public:
// Dump the Debug information about the instrumentation.
void dumpEdges(raw_ostream &OS, const Twine &Message) const {
Expand Down Expand Up @@ -291,13 +319,20 @@ template <class Edge, class BBInfo> class CFGMST {
return *AllEdges.back();
}

CFGMST(Function &Func, bool InstrumentFuncEntry,
CFGMST(Function &Func, bool InstrumentFuncEntry, bool InstrumentLoopEntries,
BranchProbabilityInfo *BPI = nullptr,
BlockFrequencyInfo *BFI = nullptr)
: F(Func), BPI(BPI), BFI(BFI), InstrumentFuncEntry(InstrumentFuncEntry) {
BlockFrequencyInfo *BFI = nullptr, LoopInfo *LI = nullptr)
: F(Func), BPI(BPI), BFI(BFI), LI(LI),
InstrumentFuncEntry(InstrumentFuncEntry),
InstrumentLoopEntries(InstrumentLoopEntries) {
assert(!(InstrumentLoopEntries && !LI) &&
"expected a LoopInfo to instrumenting loop entries");
buildEdges();
sortEdgesByWeight();
computeMinimumSpanningTree();
assert(validateLoopEntryInstrumentation() &&
"Loop entries should not be in MST when "
"InstrumentLoopEntries is on");
if (AllEdges.size() > 1 && InstrumentFuncEntry)
std::iter_swap(std::move(AllEdges.begin()),
std::move(AllEdges.begin() + AllEdges.size() - 1));
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/ProfileData/InstrProfReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
if (Version & VARIANT_MASK_INSTR_ENTRY) {
ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
}
if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) {
ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
}
if (Version & VARIANT_MASK_BYTE_COVERAGE) {
ProfileKind |= InstrProfKind::SingleByteCoverage;
}
Expand Down Expand Up @@ -262,6 +265,8 @@ Error TextInstrProfReader::readHeader() {
ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
else if (Str.equals_insensitive("not_entry_first"))
ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation;
else if (Str.equals_insensitive("instrument_loop_entries"))
ProfileKind |= InstrProfKind::LoopEntriesInstrumentation;
else if (Str.equals_insensitive("single_byte_coverage"))
ProfileKind |= InstrProfKind::SingleByteCoverage;
else if (Str.equals_insensitive("temporal_prof_traces")) {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/ProfileData/InstrProfWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,9 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
if (static_cast<bool>(ProfileKind &
InstrProfKind::FunctionEntryInstrumentation))
Header.Version |= VARIANT_MASK_INSTR_ENTRY;
if (static_cast<bool>(ProfileKind &
InstrProfKind::LoopEntriesInstrumentation))
Header.Version |= VARIANT_MASK_INSTR_LOOP_ENTRIES;
if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage))
Header.Version |= VARIANT_MASK_BYTE_COVERAGE;
if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly))
Expand Down Expand Up @@ -1120,6 +1123,10 @@ Error InstrProfWriter::writeText(raw_fd_ostream &OS) {
if (static_cast<bool>(ProfileKind &
InstrProfKind::FunctionEntryInstrumentation))
OS << "# Always instrument the function entry block\n:entry_first\n";
if (static_cast<bool>(ProfileKind &
InstrProfKind::LoopEntriesInstrumentation))
OS << "# Always instrument the loop entry "
"blocks\n:instrument_loop_entries\n";
if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage))
OS << "# Instrument block coverage\n:single_byte_coverage\n";
InstrProfSymtab Symtab;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,8 @@ bool GCOVProfiler::emitProfileNotes(
SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI,
BFI);

CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry_=*/false, BPI, BFI);
CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry=*/false,
/*InstrumentLoopEntries=*/false, BPI, BFI);

// getInstrBB can split basic blocks and push elements to AllEdges.
for (size_t I : llvm::seq<size_t>(0, MST.numEdges())) {
Expand Down
Loading
Loading