[PGO] Fix PGO use ICE when there are unreachable BBs

For -O0 there might be unreachable BBs, which breaks the assumption that all the
BBs have an auxiliary data structure.  In this patch, we add another interface
called findBBInfo() so that a nullptr can be returned for the unreachable BBs
(and the callers can ignore those BBs).

This fixes the bug reported
https://llvm.org/bugs/show_bug.cgi?id=31209

Differential Revision: https://reviews.llvm.org/D27280

llvm-svn: 288528
This commit is contained in:
Rong Xu 2016-12-02 19:10:29 +00:00
parent 5419861a52
commit a5b5745a62
4 changed files with 85 additions and 21 deletions

View File

@ -78,6 +78,14 @@ public:
return *It->second.get();
}
// Give BB, return the auxiliary information if it's available.
BBInfo *findBBInfo(const BasicBlock *BB) const {
auto It = BBInfos.find(BB);
if (It == BBInfos.end())
return nullptr;
return It->second.get();
}
// Traverse the CFG using a stack. Find all the edges and assign the weight.
// Edges with large weight will be put into MST first so they are less likely
// to be instrumented.

View File

@ -327,6 +327,9 @@ public:
// Return the auxiliary BB information.
BBInfo &getBBInfo(const BasicBlock *BB) const { return MST.getBBInfo(BB); }
// Return the auxiliary BB information if available.
BBInfo *findBBInfo(const BasicBlock *BB) const { return MST.findBBInfo(BB); }
// Dump edges and BB information.
void dumpInfo(std::string Str = "") const {
MST.dumpEdges(dbgs(), Twine("Dump Function ") + FuncName + " Hash: " +
@ -386,7 +389,10 @@ void FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash() {
const TerminatorInst *TI = BB.getTerminator();
for (unsigned I = 0, E = TI->getNumSuccessors(); I != E; ++I) {
BasicBlock *Succ = TI->getSuccessor(I);
uint32_t Index = getBBInfo(Succ).Index;
auto BI = findBBInfo(Succ);
if (BI == nullptr)
continue;
uint32_t Index = BI->Index;
for (int J = 0; J < 4; J++)
Indexes.push_back((char)(Index >> (J * 8)));
}
@ -672,6 +678,11 @@ public:
return FuncInfo.getBBInfo(BB);
}
// Return the auxiliary BB information if available.
UseBBInfo *findBBInfo(const BasicBlock *BB) const {
return FuncInfo.findBBInfo(BB);
}
private:
Function &F;
Module *M;
@ -857,27 +868,29 @@ void PGOUseFunc::populateCounters() {
// For efficient traversal, it's better to start from the end as most
// of the instrumented edges are at the end.
for (auto &BB : reverse(F)) {
UseBBInfo &Count = getBBInfo(&BB);
if (!Count.CountValid) {
if (Count.UnknownCountOutEdge == 0) {
Count.CountValue = sumEdgeCount(Count.OutEdges);
Count.CountValid = true;
UseBBInfo *Count = findBBInfo(&BB);
if (Count == nullptr)
continue;
if (!Count->CountValid) {
if (Count->UnknownCountOutEdge == 0) {
Count->CountValue = sumEdgeCount(Count->OutEdges);
Count->CountValid = true;
Changes = true;
} else if (Count.UnknownCountInEdge == 0) {
Count.CountValue = sumEdgeCount(Count.InEdges);
Count.CountValid = true;
} else if (Count->UnknownCountInEdge == 0) {
Count->CountValue = sumEdgeCount(Count->InEdges);
Count->CountValid = true;
Changes = true;
}
}
if (Count.CountValid) {
if (Count.UnknownCountOutEdge == 1) {
uint64_t Total = Count.CountValue - sumEdgeCount(Count.OutEdges);
setEdgeCount(Count.OutEdges, Total);
if (Count->CountValid) {
if (Count->UnknownCountOutEdge == 1) {
uint64_t Total = Count->CountValue - sumEdgeCount(Count->OutEdges);
setEdgeCount(Count->OutEdges, Total);
Changes = true;
}
if (Count.UnknownCountInEdge == 1) {
uint64_t Total = Count.CountValue - sumEdgeCount(Count.InEdges);
setEdgeCount(Count.InEdges, Total);
if (Count->UnknownCountInEdge == 1) {
uint64_t Total = Count->CountValue - sumEdgeCount(Count->InEdges);
setEdgeCount(Count->InEdges, Total);
Changes = true;
}
}
@ -887,14 +900,22 @@ void PGOUseFunc::populateCounters() {
DEBUG(dbgs() << "Populate counts in " << NumPasses << " passes.\n");
#ifndef NDEBUG
// Assert every BB has a valid counter.
for (auto &BB : F)
assert(getBBInfo(&BB).CountValid && "BB count is not valid");
for (auto &BB : F) {
auto BI = findBBInfo(&BB);
if (BI == nullptr)
continue;
assert(BI->CountValid && "BB count is not valid");
}
#endif
uint64_t FuncEntryCount = getBBInfo(&*F.begin()).CountValue;
F.setEntryCount(FuncEntryCount);
uint64_t FuncMaxCount = FuncEntryCount;
for (auto &BB : F)
FuncMaxCount = std::max(FuncMaxCount, getBBInfo(&BB).CountValue);
for (auto &BB : F) {
auto BI = findBBInfo(&BB);
if (BI == nullptr)
continue;
FuncMaxCount = std::max(FuncMaxCount, BI->CountValue);
}
markFunctionAttributes(FuncEntryCount, FuncMaxCount);
// Now annotate select instructions
@ -974,7 +995,10 @@ void SelectInstVisitor::annotateOneSelectInst(SelectInst &SI) {
uint64_t SCounts[2];
SCounts[0] = CountFromProfile[*CurCtrIdx]; // True count
++(*CurCtrIdx);
uint64_t TotalCount = UseFunc->getBBInfo(SI.getParent()).CountValue;
uint64_t TotalCount = 0;
auto BI = UseFunc->findBBInfo(SI.getParent());
if (BI != nullptr)
TotalCount = BI->CountValue;
// False Count
SCounts[1] = (TotalCount > SCounts[0] ? TotalCount - SCounts[0] : 0);
uint64_t MaxCount = std::max(SCounts[0], SCounts[1]);

View File

@ -0,0 +1,9 @@
# IR level Instrumentation Flag
:ir
foo
# Func Hash:
12884901887
# Num Counters:
1
# Counter Values:
0

View File

@ -0,0 +1,23 @@
; RUN: llvm-profdata merge %S/Inputs/unreachable_bb.proftext -o %t.profdata
; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @foo() {
entry:
call void @bar()
unreachable
return:
ret void
}
declare void @bar()
;USE: !0 = !{i32 1, !"ProfileSummary", !1}
;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
;USE: !2 = !{!"ProfileFormat", !"InstrProf"}
;USE: !3 = !{!"TotalCount", i64 0}