Skip to content

Commit

Permalink
[ThinLTO] Implement summary visualizer
Browse files Browse the repository at this point in the history
Differential revision: https://reviews.llvm.org/D41297

llvm-svn: 323062
  • Loading branch information
eleviant committed Jan 21, 2018
1 parent 4dd524e commit 453c976
Show file tree
Hide file tree
Showing 14 changed files with 431 additions and 31 deletions.
107 changes: 88 additions & 19 deletions llvm/include/llvm/IR/ModuleSummaryIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,27 @@ class GlobalValueSummary;
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;

struct GlobalValueSummaryInfo {
/// The GlobalValue corresponding to this summary. This is only used in
/// per-module summaries.
const GlobalValue *GV = nullptr;
union NameOrGV {
NameOrGV(bool IsAnalysis) {
if (IsAnalysis)
GV = nullptr;
else
Name = "";
}

/// The GlobalValue corresponding to this summary. This is only used in
/// per-module summaries, when module analysis is being run.
const GlobalValue *GV;

/// Summary string representation. This StringRef points to BC module
/// string table and is valid until module data is stored in memory.
/// This is guaranteed to happen until runThinLTOBackend function is
/// called, so it is safe to use this field during thin link. This field
/// is only valid if summary index was loaded from BC file.
StringRef Name;
} U;

GlobalValueSummaryInfo(bool IsAnalysis) : U(IsAnalysis) {}

/// List of global value summary structures for a particular value held
/// in the GlobalValueMap. Requires a vector in the case of multiple
Expand All @@ -91,32 +109,60 @@ using GlobalValueSummaryMapTy =
/// Struct that holds a reference to a particular GUID in a global value
/// summary.
struct ValueInfo {
const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool>
RefAndFlag;

ValueInfo() = default;
ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
ValueInfo(bool IsAnalysis, const GlobalValueSummaryMapTy::value_type *R) {
RefAndFlag.setPointer(R);
RefAndFlag.setInt(IsAnalysis);
}

operator bool() const { return Ref; }
operator bool() const { return getRef(); }

GlobalValue::GUID getGUID() const { return Ref->first; }
const GlobalValue *getValue() const { return Ref->second.GV; }
GlobalValue::GUID getGUID() const { return getRef()->first; }
const GlobalValue *getValue() const {
assert(isFromAnalysis());
return getRef()->second.U.GV;
}

ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
return Ref->second.SummaryList;
return getRef()->second.SummaryList;
}

StringRef name() const {
return isFromAnalysis() ? getRef()->second.U.GV->getName()
: getRef()->second.U.Name;
}

bool isFromAnalysis() const { return RefAndFlag.getInt(); }

const GlobalValueSummaryMapTy::value_type *getRef() const {
return RefAndFlag.getPointer();
}
};

template <> struct DenseMapInfo<ValueInfo> {
static inline ValueInfo getEmptyKey() {
return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
}

static inline ValueInfo getTombstoneKey() {
return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
}

static inline bool isSpecialKey(ValueInfo V) {
return V == getTombstoneKey() || V == getEmptyKey();
}

static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
static bool isEqual(ValueInfo L, ValueInfo R) {
// We are not supposed to mix ValueInfo(s) with different analysis flag
// in a same container.
assert(isSpecialKey(L) || isSpecialKey(R) ||
(L.isFromAnalysis() == R.isFromAnalysis()));
return L.getRef() == R.getRef();
}
static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
};

/// \brief Function and variable summary information to aid decisions and
Expand Down Expand Up @@ -619,6 +665,11 @@ class ModuleSummaryIndex {
/// considered live.
bool WithGlobalValueDeadStripping = false;

/// If true then we're performing analysis of IR module, filling summary
/// accordingly. The value of 'false' means we're reading summary from
/// BC or YAML source. Affects the type of value stored in NameOrGV union
bool IsAnalysis;

std::set<std::string> CfiFunctionDefs;
std::set<std::string> CfiFunctionDecls;

Expand All @@ -627,10 +678,16 @@ class ModuleSummaryIndex {

GlobalValueSummaryMapTy::value_type *
getOrInsertValuePtr(GlobalValue::GUID GUID) {
return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(IsAnalysis)).first;
}

public:
// See IsAnalysis variable comment.
ModuleSummaryIndex(bool IsPerformingAnalysis)
: IsAnalysis(IsPerformingAnalysis) {}

bool isPerformingAnalysis() const { return IsAnalysis; }

gvsummary_iterator begin() { return GlobalValueMap.begin(); }
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
gvsummary_iterator end() { return GlobalValueMap.end(); }
Expand All @@ -652,19 +709,28 @@ class ModuleSummaryIndex {
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
auto I = GlobalValueMap.find(GUID);
return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
return ValueInfo(IsAnalysis, I == GlobalValueMap.end() ? nullptr : &*I);
}

/// Return a ValueInfo for \p GUID.
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
return ValueInfo(getOrInsertValuePtr(GUID));
return ValueInfo(IsAnalysis, getOrInsertValuePtr(GUID));
}

/// Return a ValueInfo for \p GUID setting value \p Name.
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
assert(!IsAnalysis);
auto VP = getOrInsertValuePtr(GUID);
VP->second.U.Name = Name;
return ValueInfo(IsAnalysis, VP);
}

/// Return a ValueInfo for \p GV and mark it as belonging to GV.
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
assert(IsAnalysis);
auto VP = getOrInsertValuePtr(GV->getGUID());
VP->second.GV = GV;
return ValueInfo(VP);
VP->second.U.GV = GV;
return ValueInfo(IsAnalysis, VP);
}

/// Return the GUID for \p OriginalId in the OidGuidMap.
Expand Down Expand Up @@ -692,7 +758,7 @@ class ModuleSummaryIndex {
addOriginalName(VI.getGUID(), Summary->getOriginalName());
// Here we have a notionally const VI, but the value it points to is owned
// by the non-const *this.
const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref)
const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef())
->second.SummaryList.push_back(std::move(Summary));
}

Expand Down Expand Up @@ -823,6 +889,9 @@ class ModuleSummaryIndex {
/// Summary).
void collectDefinedGVSummariesPerModule(
StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const;

/// Export summary to dot file for GraphViz.
void exportToDot(raw_ostream& OS) const;
};

} // end namespace llvm
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/IR/ModuleSummaryIndexYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
io.setError("key not an integer");
return;
}
auto &Elem = V[KeyInt];
auto P = V.emplace(KeyInt, /*IsAnalysis=*/false);
auto &Elem = (*P.first).second;
for (auto &FSum : FSums) {
Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>(
GlobalValueSummary::GVFlags(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
ProfileSummaryInfo *PSI) {
assert(PSI);
ModuleSummaryIndex Index;
ModuleSummaryIndex Index(/*IsPerformingAnalysis=*/true);

// Identify the local values in the llvm.used and llvm.compiler.used sets,
// which should not be exported as they would then require renaming and
Expand Down
11 changes: 8 additions & 3 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4813,8 +4813,12 @@ void ModuleSummaryIndexBitcodeReader::setValueGUID(
if (PrintSummaryGUIDs)
dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
<< ValueName << "\n";
ValueIdToValueInfoMap[ValueID] =
std::make_pair(TheIndex.getOrInsertValueInfo(ValueGUID), OriginalNameID);

// UseStrtab is false for legacy summary formats and value names are
// created on stack. We can't use them outside of parseValueSymbolTable.
ValueIdToValueInfoMap[ValueID] = std::make_pair(
TheIndex.getOrInsertValueInfo(ValueGUID, UseStrtab ? ValueName : ""),
OriginalNameID);
}

// Specialized value symbol table parser used when reading module index
Expand Down Expand Up @@ -5679,7 +5683,8 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
BitstreamCursor Stream(Buffer);
Stream.JumpToBit(ModuleBit);

auto Index = llvm::make_unique<ModuleSummaryIndex>();
auto Index =
llvm::make_unique<ModuleSummaryIndex>(/*IsPerformingAnalysis=*/false);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index,
ModuleIdentifier, 0);

Expand Down
Loading

0 comments on commit 453c976

Please sign in to comment.