[MemProf] Add ability to export or highlight only a portion of graph (#128255)
To simplify debugging and analysis, particularly for very large
applications with large graphs, this patch adds support for either
highlighting a single context id or allocation's context ids, and/or
only exporting the nodes/edges for a single context id or allocation's
context ids. When highlighting, the specified nodes and edges are a
brighter color and larger.
This can be controlled by the new -memprof-dot-scope={all,alloc,context}
flag which controls how much to export, along with two companion flags:
-memprof-dot-alloc-id=ID
-memprof-dot-context-id=ID
These two are interpreted differently depending on the value of
-memprof-dot-scope (where "all" is the default).
If exporting all, one of the above flags can optionally be passed to
highlight the nodes/edges for the given context id or allocation's
context ids.
If exporting alloc scope, an alloc id must be provided. A context id can
optionally be provided to highlight that context.
If exporting context scope, a context id must be provided.
The ids to use can be obtained either by looking at the full graph, or a
context id can be identified from the -memprof-report-hinted-sizes
output after PR128188 is merged.
This commit is contained in:
parent
9d6f2647de
commit
eb92157399
@ -100,6 +100,34 @@ static cl::opt<bool> ExportToDot("memprof-export-to-dot", cl::init(false),
|
||||
cl::Hidden,
|
||||
cl::desc("Export graph to dot files."));
|
||||
|
||||
// How much of the graph to export to dot.
|
||||
enum DotScope {
|
||||
All, // The full CCG graph.
|
||||
Alloc, // Only contexts for the specified allocation.
|
||||
Context, // Only the specified context.
|
||||
};
|
||||
|
||||
static cl::opt<DotScope> DotGraphScope(
|
||||
"memprof-dot-scope", cl::desc("Scope of graph to export to dot"),
|
||||
cl::Hidden, cl::init(DotScope::All),
|
||||
cl::values(
|
||||
clEnumValN(DotScope::All, "all", "Export full callsite graph"),
|
||||
clEnumValN(DotScope::Alloc, "alloc",
|
||||
"Export only nodes with contexts feeding given "
|
||||
"-memprof-dot-alloc-id"),
|
||||
clEnumValN(DotScope::Context, "context",
|
||||
"Export only nodes with given -memprof-dot-context-id")));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
AllocIdForDot("memprof-dot-alloc-id", cl::init(0), cl::Hidden,
|
||||
cl::desc("Id of alloc to export if -memprof-dot-scope=alloc "
|
||||
"or to highlight if -memprof-dot-scope=all"));
|
||||
|
||||
static cl::opt<unsigned> ContextIdForDot(
|
||||
"memprof-dot-context-id", cl::init(0), cl::Hidden,
|
||||
cl::desc("Id of context to export if -memprof-dot-scope=context or to "
|
||||
"highlight otherwise"));
|
||||
|
||||
static cl::opt<bool>
|
||||
DumpCCG("memprof-dump-ccg", cl::init(false), cl::Hidden,
|
||||
cl::desc("Dump CallingContextGraph to stdout after each stage."));
|
||||
@ -548,6 +576,10 @@ protected:
|
||||
/// Map from callsite node to the enclosing caller function.
|
||||
std::map<const ContextNode *, const FuncTy *> NodeToCallingFunc;
|
||||
|
||||
// When exporting to dot, and an allocation id is specified, contains the
|
||||
// context ids on that allocation.
|
||||
DenseSet<uint32_t> DotAllocContextIds;
|
||||
|
||||
private:
|
||||
using EdgeIter = typename std::vector<std::shared_ptr<ContextEdge>>::iterator;
|
||||
|
||||
@ -1324,6 +1356,8 @@ CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::duplicateContextIds(
|
||||
assert(ContextIdToAllocationType.count(OldId));
|
||||
// The new context has the same allocation type as original.
|
||||
ContextIdToAllocationType[LastContextId] = ContextIdToAllocationType[OldId];
|
||||
if (DotAllocContextIds.contains(OldId))
|
||||
DotAllocContextIds.insert(LastContextId);
|
||||
}
|
||||
return NewContextIds;
|
||||
}
|
||||
@ -2084,6 +2118,10 @@ ModuleCallsiteContextGraph::ModuleCallsiteContextGraph(
|
||||
AllocNode, StackContext, CallsiteContext,
|
||||
getMIBAllocType(MIBMD), ContextSizeInfo);
|
||||
}
|
||||
// If exporting the graph to dot and an allocation id of interest was
|
||||
// specified, record all the context ids for this allocation node.
|
||||
if (ExportToDot && AllocNode->OrigStackOrAllocId == AllocIdForDot)
|
||||
DotAllocContextIds = AllocNode->getContextIds();
|
||||
assert(AllocNode->AllocTypes != (uint8_t)AllocationType::None);
|
||||
// Memprof and callsite metadata on memory allocations no longer
|
||||
// needed.
|
||||
@ -2176,6 +2214,10 @@ IndexCallsiteContextGraph::IndexCallsiteContextGraph(
|
||||
ContextSizeInfo);
|
||||
I++;
|
||||
}
|
||||
// If exporting the graph to dot and an allocation id of interest was
|
||||
// specified, record all the context ids for this allocation node.
|
||||
if (ExportToDot && AllocNode->OrigStackOrAllocId == AllocIdForDot)
|
||||
DotAllocContextIds = AllocNode->getContextIds();
|
||||
assert(AllocNode->AllocTypes != (uint8_t)AllocationType::None);
|
||||
// Initialize version 0 on the summary alloc node to the current alloc
|
||||
// type, unless it has both types in which case make it default, so
|
||||
@ -3023,7 +3065,16 @@ struct GraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *> {
|
||||
template <typename DerivedCCG, typename FuncTy, typename CallTy>
|
||||
struct DOTGraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>
|
||||
: public DefaultDOTGraphTraits {
|
||||
DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {}
|
||||
DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {
|
||||
// If the user requested the full graph to be exported, but provided an
|
||||
// allocation id, or if the user gave a context id and requested more than
|
||||
// just a specific context to be exported, note that highlighting is
|
||||
// enabled.
|
||||
DoHighlight =
|
||||
(AllocIdForDot.getNumOccurrences() && DotGraphScope == DotScope::All) ||
|
||||
(ContextIdForDot.getNumOccurrences() &&
|
||||
DotGraphScope != DotScope::Context);
|
||||
}
|
||||
|
||||
using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
|
||||
using GTraits = GraphTraits<GraphType>;
|
||||
@ -3051,12 +3102,29 @@ struct DOTGraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>
|
||||
return LabelString;
|
||||
}
|
||||
|
||||
static std::string getNodeAttributes(NodeRef Node, GraphType) {
|
||||
static std::string getNodeAttributes(NodeRef Node, GraphType G) {
|
||||
auto ContextIds = Node->getContextIds();
|
||||
// If highlighting enabled, see if this node contains any of the context ids
|
||||
// of interest. If so, it will use a different color and a larger fontsize
|
||||
// (which makes the node larger as well).
|
||||
bool Highlight = false;
|
||||
if (DoHighlight) {
|
||||
assert(ContextIdForDot.getNumOccurrences() ||
|
||||
AllocIdForDot.getNumOccurrences());
|
||||
if (ContextIdForDot.getNumOccurrences())
|
||||
Highlight = ContextIds.contains(ContextIdForDot);
|
||||
else
|
||||
Highlight = set_intersects(ContextIds, G->DotAllocContextIds);
|
||||
}
|
||||
std::string AttributeString = (Twine("tooltip=\"") + getNodeId(Node) + " " +
|
||||
getContextIds(Node->getContextIds()) + "\"")
|
||||
getContextIds(ContextIds) + "\"")
|
||||
.str();
|
||||
// Default fontsize is 14
|
||||
if (Highlight)
|
||||
AttributeString += ",fontsize=\"30\"";
|
||||
AttributeString +=
|
||||
(Twine(",fillcolor=\"") + getColor(Node->AllocTypes) + "\"").str();
|
||||
(Twine(",fillcolor=\"") + getColor(Node->AllocTypes, Highlight) + "\"")
|
||||
.str();
|
||||
if (Node->CloneOf) {
|
||||
AttributeString += ",color=\"blue\"";
|
||||
AttributeString += ",style=\"filled,bold,dashed\"";
|
||||
@ -3066,9 +3134,22 @@ struct DOTGraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>
|
||||
}
|
||||
|
||||
static std::string getEdgeAttributes(NodeRef, ChildIteratorType ChildIter,
|
||||
GraphType) {
|
||||
GraphType G) {
|
||||
auto &Edge = *(ChildIter.getCurrent());
|
||||
auto Color = getColor(Edge->AllocTypes);
|
||||
// If highlighting enabled, see if this edge contains any of the context ids
|
||||
// of interest. If so, it will use a different color and a heavier arrow
|
||||
// size and weight (the larger weight makes the highlighted path
|
||||
// straighter).
|
||||
bool Highlight = false;
|
||||
if (DoHighlight) {
|
||||
assert(ContextIdForDot.getNumOccurrences() ||
|
||||
AllocIdForDot.getNumOccurrences());
|
||||
if (ContextIdForDot.getNumOccurrences())
|
||||
Highlight = Edge->ContextIds.contains(ContextIdForDot);
|
||||
else
|
||||
Highlight = set_intersects(Edge->ContextIds, G->DotAllocContextIds);
|
||||
}
|
||||
auto Color = getColor(Edge->AllocTypes, Highlight);
|
||||
std::string AttributeString =
|
||||
(Twine("tooltip=\"") + getContextIds(Edge->ContextIds) + "\"" +
|
||||
// fillcolor is the arrow head and color is the line
|
||||
@ -3077,13 +3158,24 @@ struct DOTGraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>
|
||||
.str();
|
||||
if (Edge->IsBackedge)
|
||||
AttributeString += ",style=\"dotted\"";
|
||||
// Default penwidth and weight are both 1.
|
||||
if (Highlight)
|
||||
AttributeString += ",penwidth=\"2.0\",weight=\"2\"";
|
||||
return AttributeString;
|
||||
}
|
||||
|
||||
// Since the NodeOwners list includes nodes that are no longer connected to
|
||||
// the graph, skip them here.
|
||||
static bool isNodeHidden(NodeRef Node, GraphType) {
|
||||
return Node->isRemoved();
|
||||
static bool isNodeHidden(NodeRef Node, GraphType G) {
|
||||
if (Node->isRemoved())
|
||||
return true;
|
||||
// If a scope smaller than the full graph was requested, see if this node
|
||||
// contains any of the context ids of interest.
|
||||
if (DotGraphScope == DotScope::Alloc)
|
||||
return !set_intersects(Node->getContextIds(), G->DotAllocContextIds);
|
||||
if (DotGraphScope == DotScope::Context)
|
||||
return !Node->getContextIds().contains(ContextIdForDot);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -3100,16 +3192,20 @@ private:
|
||||
return IdString;
|
||||
}
|
||||
|
||||
static std::string getColor(uint8_t AllocTypes) {
|
||||
static std::string getColor(uint8_t AllocTypes, bool Highlight) {
|
||||
// If DoHighlight is not enabled, we want to use the highlight colors for
|
||||
// NotCold and Cold, and the non-highlight color for NotCold+Cold. This is
|
||||
// both compatible with the color scheme before highlighting was supported,
|
||||
// and for the NotCold+Cold color the non-highlight color is a bit more
|
||||
// readable.
|
||||
if (AllocTypes == (uint8_t)AllocationType::NotCold)
|
||||
// Color "brown1" actually looks like a lighter red.
|
||||
return "brown1";
|
||||
return !DoHighlight || Highlight ? "brown1" : "lightpink";
|
||||
if (AllocTypes == (uint8_t)AllocationType::Cold)
|
||||
return "cyan";
|
||||
return !DoHighlight || Highlight ? "cyan" : "lightskyblue";
|
||||
if (AllocTypes ==
|
||||
((uint8_t)AllocationType::NotCold | (uint8_t)AllocationType::Cold))
|
||||
// Lighter purple.
|
||||
return "mediumorchid1";
|
||||
return Highlight ? "magenta" : "mediumorchid1";
|
||||
return "gray";
|
||||
}
|
||||
|
||||
@ -3119,8 +3215,17 @@ private:
|
||||
std::string Result = SStream.str();
|
||||
return Result;
|
||||
}
|
||||
|
||||
// True if we should highlight a specific context or allocation's contexts in
|
||||
// the emitted graph.
|
||||
static bool DoHighlight;
|
||||
};
|
||||
|
||||
template <typename DerivedCCG, typename FuncTy, typename CallTy>
|
||||
bool DOTGraphTraits<
|
||||
const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>::DoHighlight =
|
||||
false;
|
||||
|
||||
template <typename DerivedCCG, typename FuncTy, typename CallTy>
|
||||
void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::exportToDot(
|
||||
std::string Label) const {
|
||||
@ -5183,6 +5288,20 @@ bool MemProfContextDisambiguation::processModule(
|
||||
MemProfContextDisambiguation::MemProfContextDisambiguation(
|
||||
const ModuleSummaryIndex *Summary, bool isSamplePGO)
|
||||
: ImportSummary(Summary), isSamplePGO(isSamplePGO) {
|
||||
// Check the dot graph printing options once here, to make sure we have valid
|
||||
// and expected combinations.
|
||||
if (DotGraphScope == DotScope::Alloc && !AllocIdForDot.getNumOccurrences())
|
||||
llvm::report_fatal_error(
|
||||
"-memprof-dot-scope=alloc requires -memprof-dot-alloc-id");
|
||||
if (DotGraphScope == DotScope::Context &&
|
||||
!ContextIdForDot.getNumOccurrences())
|
||||
llvm::report_fatal_error(
|
||||
"-memprof-dot-scope=context requires -memprof-dot-context-id");
|
||||
if (DotGraphScope == DotScope::All && AllocIdForDot.getNumOccurrences() &&
|
||||
ContextIdForDot.getNumOccurrences())
|
||||
llvm::report_fatal_error(
|
||||
"-memprof-dot-scope=all can't have both -memprof-dot-alloc-id and "
|
||||
"-memprof-dot-context-id");
|
||||
if (ImportSummary) {
|
||||
// The MemProfImportSummary should only be used for testing ThinLTO
|
||||
// distributed backend handling via opt, in which case we don't have a
|
||||
|
||||
265
llvm/test/Transforms/MemProfContextDisambiguation/dot.ll
Normal file
265
llvm/test/Transforms/MemProfContextDisambiguation/dot.ll
Normal file
@ -0,0 +1,265 @@
|
||||
;; Test callsite context graph exporting to dot with various options.
|
||||
;;
|
||||
;; The code is similar to that of basic.ll, but with a second allocation.
|
||||
|
||||
;; Check expected error if alloc scope requested without an alloc id.
|
||||
; RUN: not --crash opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-scope=alloc \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=ERRMISSINGALLOCID
|
||||
; ERRMISSINGALLOCID: -memprof-dot-scope=alloc requires -memprof-dot-alloc-id
|
||||
|
||||
;; Check expected error if context scope requested without a context id.
|
||||
; RUN: not --crash opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-scope=context \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=ERRMISSINGCONTEXTID
|
||||
; ERRMISSINGCONTEXTID: -memprof-dot-scope=context requires -memprof-dot-context-id
|
||||
|
||||
;; Check expected error if both alloc and context ids are specified when we are
|
||||
;; exporting the full graph to dot. It is unclear which scope to highlight.
|
||||
; RUN: not --crash opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-alloc-id=0 -memprof-dot-context-id=2 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=ERRBOTH
|
||||
; ERRBOTH: -memprof-dot-scope=all can't have both -memprof-dot-alloc-id and -memprof-dot-context-id
|
||||
|
||||
;; Export full graph (default), without any highlight.
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s -check-prefix=DOTCOMMON --check-prefix=DOTALLANDALLOC0 --check-prefix=DOTALL --check-prefix=DOTALLNONE
|
||||
|
||||
;; Export full graph (default), with highlight of alloc 0.
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-alloc-id=0 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s --check-prefix=DOTCOMMON --check-prefix=DOTALLANDALLOC0 --check-prefix=DOTALL --check-prefix=DOTALLALLOC0
|
||||
|
||||
;; Export full graph (default), with highlight of context 1.
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-context-id=1 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s --check-prefix=DOTCOMMON --check-prefix=DOTALLANDALLOC0 --check-prefix=DOTALL --check-prefix=DOTALLCONTEXT1
|
||||
|
||||
;; Export alloc 0 only, without any highlight.
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-scope=alloc -memprof-dot-alloc-id=0 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s --check-prefix=DOTCOMMON --check-prefix=DOTALLANDALLOC0 --check-prefix=DOTALLOC0NONE
|
||||
|
||||
;; Export alloc 0 only, with highlight of context 1.
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-scope=alloc -memprof-dot-alloc-id=0 \
|
||||
; RUN: -memprof-dot-context-id=1 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s --check-prefix=DOTCOMMON --check-prefix=DOTALLANDALLOC0 --check-prefix=DOTALLOC0CONTEXT1
|
||||
|
||||
;; Export context 1 only (which means no highlighting).
|
||||
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
|
||||
; RUN: -memprof-export-to-dot -memprof-dot-file-path-prefix=%t. \
|
||||
; RUN: -memprof-dot-scope=context -memprof-dot-context-id=1 \
|
||||
; RUN: %s -S 2>&1 | FileCheck %s --check-prefix=IR
|
||||
; RUN: cat %t.ccg.postbuild.dot | FileCheck %s --check-prefix=DOTCOMMON --check-prefix=DOTCONTEXT1
|
||||
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
%call = call noundef ptr @_Z3foov(), !callsite !0
|
||||
%call1 = call noundef ptr @_Z3foov(), !callsite !1
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
||||
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
|
||||
|
||||
; Function Attrs: nobuiltin
|
||||
declare void @_ZdaPv() #2
|
||||
|
||||
define internal ptr @_Z3barv() #3 {
|
||||
entry:
|
||||
%call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #6, !memprof !2, !callsite !7
|
||||
%call2 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #6, !memprof !13, !callsite !18
|
||||
ret ptr null
|
||||
}
|
||||
|
||||
declare ptr @_Znam(i64)
|
||||
|
||||
define internal ptr @_Z3bazv() #4 {
|
||||
entry:
|
||||
%call = call noundef ptr @_Z3barv(), !callsite !8
|
||||
ret ptr null
|
||||
}
|
||||
|
||||
; Function Attrs: noinline
|
||||
define internal ptr @_Z3foov() #5 {
|
||||
entry:
|
||||
%call = call noundef ptr @_Z3bazv(), !callsite !9
|
||||
ret ptr null
|
||||
}
|
||||
|
||||
; uselistorder directives
|
||||
uselistorder ptr @_Z3foov, { 1, 0 }
|
||||
|
||||
attributes #0 = { "tune-cpu"="generic" }
|
||||
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
|
||||
attributes #2 = { nobuiltin }
|
||||
attributes #3 = { "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" }
|
||||
attributes #4 = { "stack-protector-buffer-size"="8" }
|
||||
attributes #5 = { noinline }
|
||||
attributes #6 = { builtin }
|
||||
|
||||
!0 = !{i64 8632435727821051414}
|
||||
!1 = !{i64 -3421689549917153178}
|
||||
!2 = !{!3, !5}
|
||||
!3 = !{!4, !"notcold", !10}
|
||||
!4 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414}
|
||||
!5 = !{!6, !"cold", !11, !12}
|
||||
!6 = !{i64 9086428284934609951, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178}
|
||||
!7 = !{i64 9086428284934609951}
|
||||
!8 = !{i64 -5964873800580613432}
|
||||
!9 = !{i64 2732490490862098848}
|
||||
!10 = !{i64 123, i64 100}
|
||||
!11 = !{i64 456, i64 200}
|
||||
!12 = !{i64 789, i64 300}
|
||||
!13 = !{!14, !16}
|
||||
!14 = !{!15, !"notcold", !10}
|
||||
!15 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 8632435727821051414}
|
||||
!16 = !{!17, !"cold", !11, !12}
|
||||
!17 = !{i64 123, i64 -5964873800580613432, i64 2732490490862098848, i64 -3421689549917153178}
|
||||
!18 = !{i64 123}
|
||||
|
||||
; IR: define {{.*}} @main
|
||||
;; The first call to foo does not allocate cold memory. It should call the
|
||||
;; original functions, which ultimately call the original allocations decorated
|
||||
;; with a "notcold" attribute.
|
||||
; IR: call {{.*}} @_Z3foov()
|
||||
;; The second call to foo allocates cold memory. It should call cloned functions
|
||||
;; which ultimately call acloned allocations decorated with a "cold" attribute.
|
||||
; IR: call {{.*}} @_Z3foov.memprof.1()
|
||||
; IR: define internal {{.*}} @_Z3barv()
|
||||
; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD:[0-9]+]]
|
||||
; IR: call {{.*}} @_Znam(i64 noundef 10) #[[NOTCOLD]]
|
||||
; IR: define internal {{.*}} @_Z3bazv()
|
||||
; IR: call {{.*}} @_Z3barv()
|
||||
; IR: define internal {{.*}} @_Z3foov()
|
||||
; IR: call {{.*}} @_Z3bazv()
|
||||
; IR: define internal {{.*}} @_Z3barv.memprof.1()
|
||||
; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD:[0-9]+]]
|
||||
; IR: call {{.*}} @_Znam(i64 noundef 10) #[[COLD]]
|
||||
; IR: define internal {{.*}} @_Z3bazv.memprof.1()
|
||||
; IR: call {{.*}} @_Z3barv.memprof.1()
|
||||
; IR: define internal {{.*}} @_Z3foov.memprof.1()
|
||||
; IR: call {{.*}} @_Z3bazv.memprof.1()
|
||||
; IR: attributes #[[NOTCOLD]] = { builtin "memprof"="notcold" }
|
||||
; IR: attributes #[[COLD]] = { builtin "memprof"="cold" }
|
||||
|
||||
|
||||
;; Check highlighting. Alloc 0 includes context ids 1 and 2.
|
||||
|
||||
; DOTCOMMON: Node[[BAR:0x[a-z0-9]+]] [shape=record,tooltip="N[[BAR]] ContextIds: 1 2",
|
||||
;; This node is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLALLOC0-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLCONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLOC0NONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLOC0CONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTCONTEXT1-SAME: fillcolor="mediumorchid1",
|
||||
; DOTCOMMON-SAME: style="filled",label="{OrigId: Alloc0\n_Z3barv -\> _Znam}"];
|
||||
|
||||
; DOTCOMMON: Node[[BAZ:0x[a-z0-9]+]] [shape=record,tooltip="N[[BAZ]] ContextIds: 1 2 3 4",
|
||||
;; This node is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLALLOC0-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLCONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLOC0NONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLOC0CONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTCONTEXT1-SAME: fillcolor="mediumorchid1",
|
||||
; DOTCOMMON-SAME: style="filled",label="{OrigId: 12481870273128938184\n_Z3bazv -\> _Z3barv}"];
|
||||
|
||||
; DOTCOMMON: Node[[BAZ]] -> Node[[BAR]][tooltip="ContextIds: 1 2",
|
||||
;; This edge is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
; DOTALLALLOC0-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTALLCONTEXT1-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTALLOC0NONE-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
; DOTALLOC0CONTEXT1-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTCONTEXT1-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
|
||||
;; This edge is not in alloc 0 or context 0, so only included when exporting
|
||||
;; the whole graph (and never highlighted).
|
||||
; DOTALL: Node[[BAZ]] -> Node[[BAR2:0x[a-z0-9]+]][tooltip="ContextIds: 3 4",fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
|
||||
; DOTCOMMON: Node[[FOO:0x[a-z0-9]+]] [shape=record,tooltip="N[[FOO]] ContextIds: 1 2 3 4",
|
||||
;; This node is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLALLOC0-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLCONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTALLOC0NONE-SAME: fillcolor="mediumorchid1",
|
||||
; DOTALLOC0CONTEXT1-SAME: fontsize="30",fillcolor="magenta",
|
||||
; DOTCONTEXT1-SAME: fillcolor="mediumorchid1",
|
||||
; DOTCOMMON-SAME: style="filled",label="{OrigId: 2732490490862098848\n_Z3foov -\> _Z3bazv}"];
|
||||
|
||||
; DOTCOMMON: Node[[FOO]] -> Node[[BAZ]][tooltip="ContextIds: 1 2 3 4",
|
||||
;; This edge is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
; DOTALLALLOC0-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTALLCONTEXT1-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTALLOC0NONE-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
; DOTALLOC0CONTEXT1-SAME: fillcolor="magenta",color="magenta",penwidth="2.0",weight="2"];
|
||||
; DOTCONTEXT1-SAME: fillcolor="mediumorchid1",color="mediumorchid1"];
|
||||
|
||||
; DOTCOMMON: Node[[MAIN1:0x[a-z0-9]+]] [shape=record,tooltip="N[[MAIN1]] ContextIds: 1 3",
|
||||
;; This node is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
;; Note that the highlight color is the same as when there is no highlighting.
|
||||
; DOTALLALLOC0-SAME: fontsize="30",
|
||||
; DOTALLCONTEXT1-SAME: fontsize="30",
|
||||
; DOTALLOC0CONTEXT1-SAME: fontsize="30",
|
||||
; DOTCOMMON-SAME: fillcolor="brown1",style="filled",label="{OrigId: 8632435727821051414\nmain -\> _Z3foov}"];
|
||||
|
||||
; DOTCOMMON: Node[[MAIN1]] -> Node[[FOO]][tooltip="ContextIds: 1 3",fillcolor="brown1",color="brown1"
|
||||
;; This edge is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0 or context 1, or if dumping alloc 0 and specifying context 1.
|
||||
; DOTALLNONE-SAME: ];
|
||||
; DOTALLALLOC0-SAME: penwidth="2.0",weight="2"];
|
||||
; DOTALLCONTEXT1-SAME: penwidth="2.0",weight="2"];
|
||||
; DOTALLOC0NONE-SAME: ];
|
||||
; DOTALLOC0CONTEXT1-SAME: penwidth="2.0",weight="2"];
|
||||
; DOTCONTEXT1-SAME: ];
|
||||
|
||||
; DOTALLANDALLOC0: Node[[MAIN2:0x[a-z0-9]+]] [shape=record,tooltip="N[[MAIN2]] ContextIds: 2 4",
|
||||
;; This node is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0. Note that the unhighlighted color is different when there is any
|
||||
;; highlighting (lightskyblue) vs no highlighting (cyan).
|
||||
; DOTALLNONE-SAME: fillcolor="cyan",
|
||||
; DOTALLALLOC0-SAME: fontsize="30",fillcolor="cyan",
|
||||
; DOTALLCONTEXT1-SAME: fillcolor="lightskyblue",
|
||||
; DOTALLOC0NONE-SAME: fillcolor="cyan",
|
||||
; DOTALLOC0CONTEXT1-SAME: fillcolor="lightskyblue",
|
||||
; DOTALLANDALLOC0-SAME: style="filled",label="{OrigId: 15025054523792398438\nmain -\> _Z3foov}"];
|
||||
|
||||
; DOTALLANDALLOC0: Node[[MAIN2]] -> Node[[FOO]][tooltip="ContextIds: 2 4",
|
||||
;; This edge is highlighted when dumping the whole graph and specifying
|
||||
;; alloc 0. Note that the unhighlighted color is different when there is any
|
||||
;; highlighting (lightskyblue) vs no highlighting (cyan).
|
||||
; DOTALLNONE-SAME: fillcolor="cyan",color="cyan"];
|
||||
; DOTALLALLOC0-SAME: fillcolor="cyan",color="cyan",penwidth="2.0",weight="2"];
|
||||
; DOTALLCONTEXT1-SAME: fillcolor="lightskyblue",color="lightskyblue"];
|
||||
; DOTALLOC0NONE-SAME: fillcolor="cyan",color="cyan"];
|
||||
; DOTALLOC0CONTEXT1-SAME: fillcolor="lightskyblue",color="lightskyblue"];
|
||||
|
||||
;; This edge is not in alloc 0 or context 0, so only included when exporting
|
||||
;; the whole graph (and never highlighted).
|
||||
; DOTALL: Node[[BAR2]] [shape=record,tooltip="N[[BAR2]] ContextIds: 3 4",fillcolor="mediumorchid1",style="filled",label="{OrigId: Alloc2\n_Z3barv -\> _Znam}"];
|
||||
Loading…
x
Reference in New Issue
Block a user