Skip to content

Commit 6329355

Browse files
authored
[ctxprof] Move test serialization to yaml (llvm#122545)
We have a textual representation of contextual profiles for test scenarios, mainly. This patch moves that to YAML instead of JSON. YAML is more succinct and readable (some of the .ll tests should be illustrative). In addition, JSON is parse-able by the YAML reader. A subsequent patch will address deserialization. (thanks, @kazutakahirata, for showing me how to use the llvm YAML reader/writer APIs, which I incorrectly thought to be more low-level than the JSON ones!)
1 parent af4d76d commit 6329355

31 files changed

+195
-310
lines changed

llvm/include/llvm/ProfileData/PGOCtxProfWriter.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ class PGOCtxProfileWriter final {
8181
static constexpr StringRef ContainerMagic = "CTXP";
8282
};
8383

84-
Error createCtxProfFromJSON(StringRef Profile, raw_ostream &Out);
84+
/// Representation of the context node suitable for yaml / json serialization /
85+
/// deserialization.
86+
struct SerializableCtxRepresentation {
87+
ctx_profile::GUID Guid = 0;
88+
std::vector<uint64_t> Counters;
89+
std::vector<std::vector<SerializableCtxRepresentation>> Callsites;
90+
};
91+
92+
Error createCtxProfFromYAML(StringRef Profile, raw_ostream &Out);
8593
} // namespace llvm
8694
#endif

llvm/lib/ProfileData/PGOCtxProfWriter.cpp

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
#include "llvm/ProfileData/PGOCtxProfWriter.h"
1414
#include "llvm/Bitstream/BitCodeEnums.h"
1515
#include "llvm/ProfileData/CtxInstrContextNode.h"
16+
#include "llvm/Support/Error.h"
1617
#include "llvm/Support/JSON.h"
18+
#include "llvm/Support/MemoryBuffer.h"
19+
#include "llvm/Support/YAMLTraits.h"
20+
#include "llvm/Support/raw_ostream.h"
1721

1822
using namespace llvm;
1923
using namespace llvm::ctx_profile;
@@ -85,22 +89,15 @@ void PGOCtxProfileWriter::write(const ContextNode &RootNode) {
8589
}
8690

8791
namespace {
88-
// A structural representation of the JSON input.
89-
struct DeserializableCtx {
90-
ctx_profile::GUID Guid = 0;
91-
std::vector<uint64_t> Counters;
92-
std::vector<std::vector<DeserializableCtx>> Callsites;
93-
};
94-
9592
ctx_profile::ContextNode *
9693
createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
97-
const std::vector<DeserializableCtx> &DCList);
94+
const std::vector<SerializableCtxRepresentation> &DCList);
9895

9996
// Convert a DeserializableCtx into a ContextNode, potentially linking it to
10097
// its sibling (e.g. callee at same callsite) "Next".
10198
ctx_profile::ContextNode *
10299
createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
103-
const DeserializableCtx &DC,
100+
const SerializableCtxRepresentation &DC,
104101
ctx_profile::ContextNode *Next = nullptr) {
105102
auto AllocSize = ctx_profile::ContextNode::getAllocSize(DC.Counters.size(),
106103
DC.Callsites.size());
@@ -115,38 +112,34 @@ createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
115112
return Ret;
116113
}
117114

118-
// Convert a list of DeserializableCtx into a linked list of ContextNodes.
115+
// Convert a list of SerializableCtxRepresentation into a linked list of
116+
// ContextNodes.
119117
ctx_profile::ContextNode *
120118
createNode(std::vector<std::unique_ptr<char[]>> &Nodes,
121-
const std::vector<DeserializableCtx> &DCList) {
119+
const std::vector<SerializableCtxRepresentation> &DCList) {
122120
ctx_profile::ContextNode *List = nullptr;
123121
for (const auto &DC : DCList)
124122
List = createNode(Nodes, DC, List);
125123
return List;
126124
}
127125
} // namespace
128126

129-
namespace llvm {
130-
namespace json {
131-
bool fromJSON(const Value &E, DeserializableCtx &R, Path P) {
132-
json::ObjectMapper Mapper(E, P);
133-
return Mapper && Mapper.map("Guid", R.Guid) &&
134-
Mapper.map("Counters", R.Counters) &&
135-
Mapper.mapOptional("Callsites", R.Callsites);
136-
}
137-
} // namespace json
138-
} // namespace llvm
139-
140-
Error llvm::createCtxProfFromJSON(StringRef Profile, raw_ostream &Out) {
141-
auto P = json::parse(Profile);
142-
if (!P)
143-
return P.takeError();
127+
LLVM_YAML_IS_SEQUENCE_VECTOR(SerializableCtxRepresentation)
128+
LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector<SerializableCtxRepresentation>)
129+
template <> struct yaml::MappingTraits<SerializableCtxRepresentation> {
130+
static void mapping(yaml::IO &IO, SerializableCtxRepresentation &SCR) {
131+
IO.mapRequired("Guid", SCR.Guid);
132+
IO.mapRequired("Counters", SCR.Counters);
133+
IO.mapOptional("Callsites", SCR.Callsites);
134+
}
135+
};
144136

145-
json::Path::Root R("");
146-
std::vector<DeserializableCtx> DCList;
147-
if (!fromJSON(*P, DCList, R))
148-
return R.getError();
149-
// Nodes provides memory backing for the ContextualNodes.
137+
Error llvm::createCtxProfFromYAML(StringRef Profile, raw_ostream &Out) {
138+
yaml::Input In(Profile);
139+
std::vector<SerializableCtxRepresentation> DCList;
140+
In >> DCList;
141+
if (In.error())
142+
return createStringError(In.error(), "incorrect yaml content");
150143
std::vector<std::unique_ptr<char[]>> Nodes;
151144
std::error_code EC;
152145
if (EC)
@@ -162,4 +155,4 @@ Error llvm::createCtxProfFromJSON(StringRef Profile, raw_ostream &Out) {
162155
if (EC)
163156
return createStringError(EC, "failed to write output");
164157
return Error::success();
165-
}
158+
}

llvm/test/Analysis/CtxProfAnalysis/flatten-and-annotate.ll

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
;
33
; RUN: rm -rf %t
44
; RUN: split-file %s %t
5-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata
5+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata
66
; RUN: opt -module-summary -passes='thinlto-pre-link<O2>' -use-ctx-profile=%t/profile.ctxprofdata \
77
; RUN: %t/example.ll -S -o %t/prelink.ll
88
; RUN: FileCheck --input-file %t/prelink.ll %s --check-prefix=PRELINK
@@ -58,27 +58,15 @@
5858
; CHECK: ![[AN_ENTRYPOINT_EP]] = !{!"function_entry_count", i64 100}
5959
; CHECK: ![[AN_ENTRYPOINT_BW]] = !{!"branch_weights", i32 40, i32 60}
6060

61-
;--- profile.json
62-
[
63-
{
64-
"Guid": 4909520559318251808,
65-
"Counters": [100, 40],
66-
"Callsites": [
67-
[
68-
{
69-
"Guid": 11872291593386833696,
70-
"Counters": [ 100, 5 ]
71-
}
72-
],
73-
[
74-
{
75-
"Guid": 11872291593386833696,
76-
"Counters": [ 40, 10 ]
77-
}
78-
]
79-
]
80-
}
81-
]
61+
;--- profile.yaml
62+
- Guid: 4909520559318251808
63+
Counters: [100, 40]
64+
Callsites: -
65+
- Guid: 11872291593386833696
66+
Counters: [ 100, 5 ]
67+
-
68+
- Guid: 11872291593386833696
69+
Counters: [ 40, 10 ]
8270
;--- example.ll
8371
declare void @bar()
8472

llvm/test/Analysis/CtxProfAnalysis/flatten-check-path.ll

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
; already visited blocks count as taken (i.e. the flow continues through them).
44
;
55
; RUN: split-file %s %t
6-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_ok.json --output=%t/profile_ok.ctxprofdata
7-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_pump.json --output=%t/profile_pump.ctxprofdata
8-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile_unreachable.json --output=%t/profile_unreachable.ctxprofdata
6+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile_ok.yaml --output=%t/profile_ok.ctxprofdata
7+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile_pump.yaml --output=%t/profile_pump.ctxprofdata
8+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile_unreachable.yaml --output=%t/profile_unreachable.ctxprofdata
99
;
1010
; RUN: opt -passes=ctx-prof-flatten %t/example_ok.ll -use-ctx-profile=%t/profile_ok.ctxprofdata -S -o - | FileCheck %s
1111
; RUN: not --crash opt -passes=ctx-prof-flatten %t/message_pump.ll -use-ctx-profile=%t/profile_pump.ctxprofdata -S 2>&1 | FileCheck %s --check-prefix=ASSERTION
@@ -38,8 +38,9 @@ exit:
3838
}
3939
!0 = !{i64 1234}
4040

41-
;--- profile_ok.json
42-
[{"Guid":1234, "Counters":[2, 2, 1, 2]}]
41+
;--- profile_ok.yaml
42+
- Guid: 1234
43+
Counters: [2, 2, 1, 2]
4344

4445
;--- message_pump.ll
4546
; This is a message pump: the loop never exits. This should result in an
@@ -59,8 +60,9 @@ exit:
5960
}
6061
!0 = !{i64 1234}
6162

62-
;--- profile_pump.json
63-
[{"Guid":1234, "Counters":[2, 10, 0]}]
63+
;--- profile_pump.yaml
64+
- Guid: 1234
65+
Counters: [2, 10, 0]
6466

6567
;--- unreachable.ll
6668
; An unreachable block is reached, that's an error
@@ -81,5 +83,6 @@ exit:
8183
}
8284
!0 = !{i64 1234}
8385

84-
;--- profile_unreachable.json
85-
[{"Guid":1234, "Counters":[2, 1, 1, 2]}]
86+
;--- profile_unreachable.yaml
87+
- Guid: 1234
88+
Counters: [2, 1, 1, 2]

llvm/test/Analysis/CtxProfAnalysis/flatten-icp.ll

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: split-file %s %t
2-
; RUN: llvm-ctxprof-util fromJSON --input %t/profile.json --output %t/profile.ctxprofdata
2+
; RUN: llvm-ctxprof-util fromYAML --input %t/profile.yaml --output %t/profile.ctxprofdata
33
;
44
; In the given profile, in one of the contexts the indirect call is taken, the
55
; target we're trying to ICP - GUID:2000 - doesn't appear at all. That should
@@ -45,11 +45,18 @@ attributes #1 = { noinline }
4545
!1 = !{i64 3000}
4646
!2 = !{i64 4000}
4747

48-
;--- profile.json
49-
[ {
50-
"Guid": 4000, "Counters":[10], "Callsites": [
51-
[{"Guid":3000, "Counters":[10], "Callsites":[[{"Guid":1000, "Counters":[10]}]]}],
52-
[{"Guid":3000, "Counters":[10], "Callsites":[[{"Guid":9000, "Counters":[10]}]]}]
53-
]
54-
}
55-
]
48+
;--- profile.yaml
49+
- Guid: 4000
50+
Counters: [10]
51+
Callsites: -
52+
- Guid: 3000
53+
Counters: [10]
54+
Callsites: -
55+
- Guid: 1000
56+
Counters: [10]
57+
-
58+
- Guid: 3000
59+
Counters: [10]
60+
Callsites: -
61+
- Guid: 9000
62+
Counters: [10]

llvm/test/Analysis/CtxProfAnalysis/flatten-zero-path.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; Check that flattened profile lowering handles cold subgraphs that end in "unreachable"
22
; RUN: split-file %s %t
3-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata
3+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata
44
; RUN: opt -passes=ctx-prof-flatten %t/example.ll -use-ctx-profile=%t/profile.ctxprofdata -S -o - | FileCheck %s
55

66
; CHECK-LABEL: entry:
@@ -51,5 +51,6 @@ exit:
5151

5252
!0 = !{i64 1234}
5353

54-
;--- profile.json
55-
[{"Guid":1234, "Counters":[6,0,0,0]}]
54+
;--- profile.yaml
55+
- Guid: 1234
56+
Counters: [6,0,0,0]

llvm/test/Analysis/CtxProfAnalysis/full-cycle.ll

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
; different counter values, and we expect resulting flat profile to be the sum
99
; (of values at the same index).
1010
;
11-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata
11+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata
1212
;
1313
; RUN: opt -module-summary -passes='thinlto-pre-link<O2>' -use-ctx-profile=%t/profile.ctxprofdata -o %t/m1.bc %t/m1.ll
1414
; RUN: opt -module-summary -passes='thinlto-pre-link<O2>' -use-ctx-profile=%t/profile.ctxprofdata -o %t/m2.bc %t/m2.ll
@@ -65,55 +65,21 @@ define void @entrypoint() {
6565
call void @f3()
6666
ret void
6767
}
68-
;--- profile.json
69-
[
70-
{
71-
"Callsites": [
72-
[
73-
{
74-
"Callsites": [
75-
[
76-
{
77-
"Counters": [
78-
10,
79-
7
80-
],
81-
"Guid": 3087265239403591524
82-
}
83-
]
84-
],
85-
"Counters": [
86-
7
87-
],
88-
"Guid": 2072045998141807037
89-
}
90-
],
91-
[
92-
{
93-
"Callsites": [
94-
[
95-
{
96-
"Counters": [
97-
1,
98-
2
99-
],
100-
"Guid": 3087265239403591524
101-
}
102-
]
103-
],
104-
"Counters": [
105-
2
106-
],
107-
"Guid": 4197650231481825559
108-
}
109-
]
110-
],
111-
"Counters": [
112-
1
113-
],
114-
"Guid": 10507721908651011566
115-
}
116-
]
68+
;--- profile.yaml
69+
- Guid: 10507721908651011566
70+
Counters: [1]
71+
Callsites: -
72+
- Guid: 2072045998141807037
73+
Counters: [7]
74+
Callsites: -
75+
- Guid: 3087265239403591524
76+
Counters: [10, 7]
77+
-
78+
- Guid: 4197650231481825559
79+
Counters: [2]
80+
Callsites: -
81+
- Guid: 3087265239403591524
82+
Counters: [1, 2]
11783
;--- expected.txt
11884
Function Info:
11985
2072045998141807037 : f1. MaxCounterID: 1. MaxCallsiteID: 1

llvm/test/Analysis/CtxProfAnalysis/handle-select.ll

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
; the `select` is elided.
55
;
66
; RUN: split-file %s %t
7-
; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata
7+
; RUN: llvm-ctxprof-util fromYAML --input=%t/profile.yaml --output=%t/profile.ctxprofdata
88
;
99
; RUN: opt -passes=ctx-instr-gen %t/example.ll -use-ctx-profile=%t/profile.ctxprofdata -S -o - | FileCheck %s --check-prefix=INSTR
1010
; RUN: opt -passes=ctx-instr-gen,module-inline %t/example.ll -use-ctx-profile=%t/profile.ctxprofdata -S -o - | FileCheck %s --check-prefix=POST-INL
@@ -72,5 +72,12 @@ define i32 @bar(i32 %t) !guid !1 {
7272
!0 = !{i64 1234}
7373
!1 = !{i64 5678}
7474

75-
;--- profile.json
76-
[{"Guid":1234, "Counters":[10, 4], "Callsites":[[{"Guid": 5678, "Counters":[4,3]}],[{"Guid": 5678, "Counters":[6,6]}]]}]
75+
;--- profile.yaml
76+
- Guid: 1234
77+
Counters: [10, 4]
78+
Callsites: -
79+
- Guid: 5678
80+
Counters: [4,3]
81+
-
82+
- Guid: 5678
83+
Counters: [6,6]

0 commit comments

Comments
 (0)