Skip to content

Commit

Permalink
[ThinLTO] Add an option to force summary call edges cold for debugging
Browse files Browse the repository at this point in the history
Summary:
Useful to selectively disable importing into specific modules for
debugging/triaging/workarounds.

Reviewers: eraman

Subscribers: inglorion, llvm-commits

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

llvm-svn: 328909
  • Loading branch information
teresajohnson committed Mar 31, 2018
1 parent ef61d85 commit db83ace
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 2 deletions.
7 changes: 7 additions & 0 deletions llvm/include/llvm/IR/ModuleSummaryIndex.h
Expand Up @@ -404,6 +404,13 @@ class FunctionSummary : public GlobalValueSummary {
/// <CalleeValueInfo, CalleeInfo> call edge pair.
using EdgeTy = std::pair<ValueInfo, CalleeInfo>;

/// Types for -force-summary-edges-cold debugging option.
enum ForceSummaryHotnessType : unsigned {
FSHT_None,
FSHT_AllNonCritical,
FSHT_All
};

/// An "identifier" for a virtual function. This contains the type identifier
/// represented as a GUID and the offset from the address point to the virtual
/// function pointer, where "address point" is as defined in the Itanium ABI:
Expand Down
19 changes: 18 additions & 1 deletion llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
Expand Up @@ -49,6 +49,7 @@
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
Expand All @@ -58,6 +59,18 @@ using namespace llvm;

#define DEBUG_TYPE "module-summary-analysis"

// Option to force edges cold which will block importing when the
// -import-cold-multiplier is set to 0. Useful for debugging.
FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold =
FunctionSummary::FSHT_None;
cl::opt<FunctionSummary::ForceSummaryHotnessType, true> FSEC(
"force-summary-edges-cold", cl::Hidden, cl::location(ForceSummaryEdgesCold),
cl::desc("Force all edges in the function summary to cold"),
cl::values(clEnumValN(FunctionSummary::FSHT_None, "none", "None."),
clEnumValN(FunctionSummary::FSHT_AllNonCritical,
"all-non-critical", "All non-critical edges."),
clEnumValN(FunctionSummary::FSHT_All, "all", "All edges.")));

// Walk through the operands of a given User via worklist iteration and populate
// the set of GlobalValue references encountered. Invoked either on an
// Instruction or a GlobalVariable (which walks its initializer).
Expand Down Expand Up @@ -268,6 +281,8 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
auto ScaledCount = PSI->getProfileCount(&I, BFI);
auto Hotness = ScaledCount ? getHotness(ScaledCount.getValue(), PSI)
: CalleeInfo::HotnessType::Unknown;
if (ForceSummaryEdgesCold != FunctionSummary::FSHT_None)
Hotness = CalleeInfo::HotnessType::Cold;

// Use the original CalledValue, in case it was an alias. We want
// to record the call edge to the alias in that case. Eventually
Expand Down Expand Up @@ -318,7 +333,9 @@ computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
// sample PGO, to enable the same inlines as the profiled optimized binary.
for (auto &I : F.getImportGUIDs())
CallGraphEdges[Index.getOrInsertValueInfo(I)].updateHotness(
CalleeInfo::HotnessType::Critical);
ForceSummaryEdgesCold == FunctionSummary::FSHT_All
? CalleeInfo::HotnessType::Cold
: CalleeInfo::HotnessType::Critical);

bool NonRenamableLocal = isNonRenamableLocal(F);
bool NotEligibleForImport =
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Expand Up @@ -89,6 +89,9 @@ static cl::opt<unsigned>
cl::opt<bool> WriteRelBFToSummary(
"write-relbf-to-summary", cl::Hidden, cl::init(false),
cl::desc("Write relative block frequency to function summary "));

extern FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold;

namespace {

/// These are manifest constants used by the bitcode writer. They do not need to
Expand Down Expand Up @@ -3436,7 +3439,8 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
for (auto &RI : FS->refs())
NameVals.push_back(VE.getValueID(RI.getValue()));

bool HasProfileData = F.hasProfileData();
bool HasProfileData =
F.hasProfileData() || ForceSummaryEdgesCold != FunctionSummary::FSHT_None;
for (auto &ECI : FS->calls()) {
NameVals.push_back(getValueId(ECI.first));
if (HasProfileData)
Expand Down
@@ -0,0 +1,4 @@
define void @foo() {
entry:
ret void
}
36 changes: 36 additions & 0 deletions llvm/test/Transforms/FunctionImport/funcimport_forcecold.ll
@@ -0,0 +1,36 @@
; Test to ensure that building summary with -force-summary-edges-cold
; blocks importing as expected.

; "-stats" and "-debug-only" require +Asserts.
; REQUIRES: asserts

; First do with default options, which should import
; RUN: opt -module-summary %s -o %t.bc
; RUN: opt -module-summary %p/Inputs/funcimport_forcecold.ll -o %t2.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT

; Next rebuild caller module summary with non-critical edges forced cold (which
; should affect all edges in this test as we don't have any sample pgo).
; Make sure we don't import.
; RUN: opt -force-summary-edges-cold=all-non-critical -module-summary %s -o %t.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT

; Next rebuild caller module summary with all edges forced cold.
; Make sure we don't import.
; RUN: opt -force-summary-edges-cold=all -module-summary %s -o %t.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT

define i32 @main() {
entry:
call void @foo()
ret i32 0
}

; IMPORT: Import foo
; NOIMPORT-NOT: Import foo
; IMPORT: define available_externally void @foo()
; NOIMPORT: declare void @foo()
declare void @foo()
@@ -0,0 +1,37 @@
; Test to ensure that building summary with -force-summary-edges-cold
; blocks importing as expected.

; "-stats" and "-debug-only" require +Asserts.
; REQUIRES: asserts

; First do with default options, which should import
; RUN: opt -module-summary %s -o %t.bc
; RUN: opt -module-summary %p/Inputs/funcimport_forcecold.ll -o %t2.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT

; Next rebuild caller module summary with only non-critical edges forced cold,
; which should still import in this case.
; RUN: opt -force-summary-edges-cold=all-non-critical -module-summary %s -o %t.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT

; Next rebuild caller module summary with all edges forced cold.
; Make sure we don't import.
; RUN: opt -force-summary-edges-cold=all -module-summary %s -o %t.bc
; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT

define i32 @main() !prof !1 {
entry:
call void @foo()
ret i32 0
}

; IMPORT: Import foo
; NOIMPORT-NOT: Import foo
; IMPORT: define available_externally void @foo()
; NOIMPORT: declare void @foo()
declare void @foo()

!1 = !{!"function_entry_count", i64 110, i64 6699318081062747564}

0 comments on commit db83ace

Please sign in to comment.