Skip to content

Commit 87ba0bc

Browse files
author
git apple-llvm automerger
committed
Merge commit '937924eb4956' from llvm.org/main into next
2 parents a551aa6 + 937924e commit 87ba0bc

File tree

5 files changed

+241
-63
lines changed

5 files changed

+241
-63
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; RUN: llvm-profgen --format=text --unsymbolized-profile=%S/Inputs/cold-profile-trimming.raw.prof --binary=%S/Inputs/inline-noprobe2.perfbin --output=%t1 --use-offset=0
2+
; RUN: llvm-profgen --format=text --llvm-sample-profile=%t1 --binary=%S/Inputs/inline-noprobe2.perfbin --output=%t2 --trim-cold-profile=1 --profile-summary-cold-count=1000
3+
; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-TRIM
4+
5+
6+
;CHECK-TRIM: partition_pivot_last:5187:7
7+
;CHECK-TRIM: partition_pivot_first:3010:5
8+
;CHECK-TRIM-NOT: quick_sort:903:25
9+
;CHECK-TRIM-NOT: main:820:0
10+
11+
; original code:
12+
; clang -O3 -g -fno-optimize-sibling-calls -fdebug-info-for-profiling qsort.c -o a.out
13+
#include <stdio.h>
14+
#include <stdlib.h>
15+
16+
void swap(int *a, int *b) {
17+
int t = *a;
18+
*a = *b;
19+
*b = t;
20+
}
21+
22+
int partition_pivot_last(int* array, int low, int high) {
23+
int pivot = array[high];
24+
int i = low - 1;
25+
for (int j = low; j < high; j++)
26+
if (array[j] < pivot)
27+
swap(&array[++i], &array[j]);
28+
swap(&array[i + 1], &array[high]);
29+
return (i + 1);
30+
}
31+
32+
int partition_pivot_first(int* array, int low, int high) {
33+
int pivot = array[low];
34+
int i = low + 1;
35+
for (int j = low + 1; j <= high; j++)
36+
if (array[j] < pivot) { if (j != i) swap(&array[i], &array[j]); i++;}
37+
swap(&array[i - 1], &array[low]);
38+
return i - 1;
39+
}
40+
41+
void quick_sort(int* array, int low, int high, int (*partition_func)(int *, int, int)) {
42+
if (low < high) {
43+
int pi = (*partition_func)(array, low, high);
44+
quick_sort(array, low, pi - 1, partition_func);
45+
quick_sort(array, pi + 1, high, partition_func);
46+
}
47+
}
48+
49+
int main() {
50+
const int size = 200;
51+
int sum = 0;
52+
int *array = malloc(size * sizeof(int));
53+
for(int i = 0; i < 100 * 1000; i++) {
54+
for(int j = 0; j < size; j++)
55+
array[j] = j % 10 ? rand() % size: j;
56+
int (*fptr)(int *, int, int) = i % 3 ? partition_pivot_last : partition_pivot_first;
57+
quick_sort(array, 0, size - 1, fptr);
58+
sum += array[i % size];
59+
}
60+
printf("sum=%d\n", sum);
61+
62+
return 0;
63+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; Test default llvm-profgen with preinline off
2+
; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --csspgo-preinliner=0 --gen-cs-nested-profile=0 --output=%t1
3+
4+
; Test llvm-profgen with preinliner on will merge not inlinable profile into base profile.
5+
; RUN: llvm-profgen --format=text --llvm-sample-profile=%t1 --binary=%S/Inputs/inline-cs-noprobe.perfbin --csspgo-preinliner=1 --gen-cs-nested-profile=0 --sample-profile-hot-inline-threshold=3000 --sample-profile-cold-inline-threshold=45 --output=%t2
6+
; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-PREINL
7+
8+
; Test default llvm-profgen with preinline off
9+
; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --csspgo-preinliner=0 --gen-cs-nested-profile=0 --output=%t3
10+
11+
; Test llvm-profgen with preinliner on will merge not inlinable profile into base profile.
12+
; RUN: llvm-profgen --format=text --llvm-sample-profile=%t3 --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --csspgo-preinliner=1 --gen-cs-nested-profile=0 --sample-profile-hot-inline-threshold=3000 --sample-profile-cold-inline-threshold=45 --output=%t4
13+
; RUN: FileCheck %s --input-file %t4 --check-prefix=CHECK-PREINL-PROBE
14+
15+
; CHECK-PREINL: [foo]:309:0
16+
; CHECK-PREINL-NEXT: 2.1: 14
17+
; CHECK-PREINL-NEXT: 3: 15
18+
; CHECK-PREINL-NEXT: 3.1: 14 bar:14
19+
; CHECK-PREINL-NEXT: 3.2: 1
20+
; CHECK-PREINL-NEXT: 65526: 14
21+
; CHECK-PREINL-NEXT: !Attributes: 1
22+
; CHECK-PREINL-NEXT:[foo:3.1 @ bar]:84:0
23+
; CHECK-PREINL-NEXT: 1: 14
24+
; CHECK-PREINL-NEXT: !Attributes: 3
25+
26+
27+
; CHECK-PREINL-PROBE: [foo]:74:0
28+
; CHECK-PREINL-PROBE-NEXT: 1: 0
29+
; CHECK-PREINL-PROBE-NEXT: 2: 15
30+
; CHECK-PREINL-PROBE-NEXT: 3: 15
31+
; CHECK-PREINL-PROBE-NEXT: 4: 14
32+
; CHECK-PREINL-PROBE-NEXT: 5: 1
33+
; CHECK-PREINL-PROBE-NEXT: 6: 15
34+
; CHECK-PREINL-PROBE-NEXT: 7: 0
35+
; CHECK-PREINL-PROBE-NEXT: 8: 14 bar:14
36+
; CHECK-PREINL-PROBE-NEXT: 9: 0
37+
; CHECK-PREINL-PROBE-NEXT: !CFGChecksum: 563088904013236
38+
; CHECK-PREINL-PROBE-NEXT: !Attributes: 1
39+
; CHECK-PREINL-PROBE-NEXT:[foo:8 @ bar]:28:14
40+
; CHECK-PREINL-PROBE-NEXT: 1: 14
41+
; CHECK-PREINL-PROBE-NEXT: 4: 14
42+
; CHECK-PREINL-PROBE-NEXT: !CFGChecksum: 72617220756
43+
; CHECK-PREINL-PROBE-NEXT: !Attributes: 3

llvm/tools/llvm-profgen/ProfileGenerator.cpp

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
//===----------------------------------------------------------------------===//
88
#include "ProfileGenerator.h"
99
#include "ErrorHandling.h"
10+
#include "PerfReader.h"
1011
#include "ProfiledBinary.h"
1112
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
1213
#include "llvm/ProfileData/ProfileCommon.h"
1314
#include <algorithm>
1415
#include <float.h>
1516
#include <unordered_set>
17+
#include <utility>
1618

1719
cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
1820
cl::Required,
@@ -109,7 +111,7 @@ bool ProfileGeneratorBase::UseFSDiscriminator = false;
109111

110112
std::unique_ptr<ProfileGeneratorBase>
111113
ProfileGeneratorBase::create(ProfiledBinary *Binary,
112-
const ContextSampleCounterMap &SampleCounters,
114+
const ContextSampleCounterMap *SampleCounters,
113115
bool ProfileIsCSFlat) {
114116
std::unique_ptr<ProfileGeneratorBase> Generator;
115117
if (ProfileIsCSFlat) {
@@ -125,6 +127,24 @@ ProfileGeneratorBase::create(ProfiledBinary *Binary,
125127
return Generator;
126128
}
127129

130+
std::unique_ptr<ProfileGeneratorBase>
131+
ProfileGeneratorBase::create(ProfiledBinary *Binary,
132+
const SampleProfileMap &&Profiles,
133+
bool ProfileIsCSFlat) {
134+
std::unique_ptr<ProfileGeneratorBase> Generator;
135+
if (ProfileIsCSFlat) {
136+
if (Binary->useFSDiscriminator())
137+
exitWithError("FS discriminator is not supported in CS profile.");
138+
Generator.reset(new CSProfileGenerator(Binary, std::move(Profiles)));
139+
} else {
140+
Generator.reset(new ProfileGenerator(Binary, std::move(Profiles)));
141+
}
142+
ProfileGeneratorBase::UseFSDiscriminator = Binary->useFSDiscriminator();
143+
FunctionSamples::ProfileIsFS = Binary->useFSDiscriminator();
144+
145+
return Generator;
146+
}
147+
128148
void ProfileGeneratorBase::write(std::unique_ptr<SampleProfileWriter> Writer,
129149
SampleProfileMap &ProfileMap) {
130150
// Populate profile symbol list if extended binary format is used.
@@ -372,31 +392,39 @@ void ProfileGeneratorBase::updateTotalSamples() {
372392

373393
void ProfileGeneratorBase::collectProfiledFunctions() {
374394
std::unordered_set<const BinaryFunction *> ProfiledFunctions;
375-
// Go through all the stacks, ranges and branches in sample counters, use the
376-
// start of the range to look up the function it belongs and record the
377-
// function.
378-
for (const auto &CI : SampleCounters) {
379-
if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
380-
for (auto Addr : CtxKey->Context) {
381-
if (FuncRange *FRange = Binary->findFuncRangeForOffset(
382-
Binary->virtualAddrToOffset(Addr)))
395+
if (SampleCounters) {
396+
// Go through all the stacks, ranges and branches in sample counters, use
397+
// the start of the range to look up the function it belongs and record the
398+
// function.
399+
for (const auto &CI : *SampleCounters) {
400+
if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
401+
for (auto Addr : CtxKey->Context) {
402+
if (FuncRange *FRange = Binary->findFuncRangeForOffset(
403+
Binary->virtualAddrToOffset(Addr)))
404+
ProfiledFunctions.insert(FRange->Func);
405+
}
406+
}
407+
408+
for (auto Item : CI.second.RangeCounter) {
409+
uint64_t StartOffset = Item.first.first;
410+
if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
383411
ProfiledFunctions.insert(FRange->Func);
384412
}
385-
}
386413

387-
for (auto Item : CI.second.RangeCounter) {
388-
uint64_t StartOffset = Item.first.first;
389-
if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
390-
ProfiledFunctions.insert(FRange->Func);
414+
for (auto Item : CI.second.BranchCounter) {
415+
uint64_t SourceOffset = Item.first.first;
416+
uint64_t TargetOffset = Item.first.first;
417+
if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
418+
ProfiledFunctions.insert(FRange->Func);
419+
if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
420+
ProfiledFunctions.insert(FRange->Func);
421+
}
391422
}
392-
393-
for (auto Item : CI.second.BranchCounter) {
394-
uint64_t SourceOffset = Item.first.first;
395-
uint64_t TargetOffset = Item.first.first;
396-
if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
397-
ProfiledFunctions.insert(FRange->Func);
398-
if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
399-
ProfiledFunctions.insert(FRange->Func);
423+
} else {
424+
// This is for the case the input is a llvm sample profile.
425+
for (const auto &FS : ProfileMap) {
426+
if (auto *Func = Binary->getBinaryFunction(FS.first.getName()))
427+
ProfiledFunctions.insert(Func);
400428
}
401429
}
402430

@@ -416,11 +444,18 @@ ProfileGenerator::getTopLevelFunctionProfile(StringRef FuncName) {
416444

417445
void ProfileGenerator::generateProfile() {
418446
collectProfiledFunctions();
419-
if (Binary->usePseudoProbes()) {
420-
generateProbeBasedProfile();
421-
} else {
422-
generateLineNumBasedProfile();
447+
448+
if (Binary->usePseudoProbes())
449+
Binary->decodePseudoProbe();
450+
451+
if (SampleCounters) {
452+
if (Binary->usePseudoProbes()) {
453+
generateProbeBasedProfile();
454+
} else {
455+
generateLineNumBasedProfile();
456+
}
423457
}
458+
424459
postProcessProfiles();
425460
}
426461

@@ -448,9 +483,9 @@ void ProfileGenerator::trimColdProfiles(const SampleProfileMap &Profiles,
448483
}
449484

450485
void ProfileGenerator::generateLineNumBasedProfile() {
451-
assert(SampleCounters.size() == 1 &&
486+
assert(SampleCounters->size() == 1 &&
452487
"Must have one entry for profile generation.");
453-
const SampleCounter &SC = SampleCounters.begin()->second;
488+
const SampleCounter &SC = SampleCounters->begin()->second;
454489
// Fill in function body samples
455490
populateBodySamplesForAllFunctions(SC.RangeCounter);
456491
// Fill in boundary sample counts as well as call site samples for calls
@@ -460,12 +495,11 @@ void ProfileGenerator::generateLineNumBasedProfile() {
460495
}
461496

462497
void ProfileGenerator::generateProbeBasedProfile() {
463-
assert(SampleCounters.size() == 1 &&
498+
assert(SampleCounters->size() == 1 &&
464499
"Must have one entry for profile generation.");
465-
Binary->decodePseudoProbe();
466500
// Enable pseudo probe functionalities in SampleProf
467501
FunctionSamples::ProfileIsProbeBased = true;
468-
const SampleCounter &SC = SampleCounters.begin()->second;
502+
const SampleCounter &SC = SampleCounters->begin()->second;
469503
// Fill in function body samples
470504
populateBodySamplesWithProbesForAllFunctions(SC.RangeCounter);
471505
// Fill in boundary sample counts as well as call site samples for calls
@@ -687,10 +721,15 @@ void CSProfileGenerator::generateProfile() {
687721

688722
collectProfiledFunctions();
689723

690-
if (Binary->usePseudoProbes()) {
691-
generateProbeBasedProfile();
692-
} else {
693-
generateLineNumBasedProfile();
724+
if (Binary->usePseudoProbes())
725+
Binary->decodePseudoProbe();
726+
727+
if (SampleCounters) {
728+
if (Binary->usePseudoProbes()) {
729+
generateProbeBasedProfile();
730+
} else {
731+
generateLineNumBasedProfile();
732+
}
694733
}
695734

696735
if (Binary->getTrackFuncContextSize())
@@ -709,7 +748,7 @@ void CSProfileGenerator::computeSizeForProfiledFunctions() {
709748
}
710749

711750
void CSProfileGenerator::generateLineNumBasedProfile() {
712-
for (const auto &CI : SampleCounters) {
751+
for (const auto &CI : *SampleCounters) {
713752
const auto *CtxKey = cast<StringBasedCtxKey>(CI.first.getPtr());
714753

715754
// Get or create function profile for the range
@@ -967,10 +1006,9 @@ extractPrefixContextStack(SampleContextFrameVector &ContextStack,
9671006
}
9681007

9691008
void CSProfileGenerator::generateProbeBasedProfile() {
970-
Binary->decodePseudoProbe();
9711009
// Enable pseudo probe functionalities in SampleProf
9721010
FunctionSamples::ProfileIsProbeBased = true;
973-
for (const auto &CI : SampleCounters) {
1011+
for (const auto &CI : *SampleCounters) {
9741012
const AddrBasedCtxKey *CtxKey =
9751013
dyn_cast<AddrBasedCtxKey>(CI.first.getPtr());
9761014
SampleContextFrameVector ContextStack;

llvm/tools/llvm-profgen/ProfileGenerator.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,18 @@ class ProfileGeneratorBase {
3333

3434
public:
3535
ProfileGeneratorBase(ProfiledBinary *Binary,
36-
const ContextSampleCounterMap &Counters)
36+
const ContextSampleCounterMap *Counters)
3737
: Binary(Binary), SampleCounters(Counters){};
38+
ProfileGeneratorBase(ProfiledBinary *Binary,
39+
const SampleProfileMap &&Profiles)
40+
: Binary(Binary), ProfileMap(std::move(Profiles)){};
41+
3842
virtual ~ProfileGeneratorBase() = default;
3943
static std::unique_ptr<ProfileGeneratorBase>
40-
create(ProfiledBinary *Binary, const ContextSampleCounterMap &SampleCounters,
44+
create(ProfiledBinary *Binary, const ContextSampleCounterMap *Counters,
45+
bool ProfileIsCSFlat);
46+
static std::unique_ptr<ProfileGeneratorBase>
47+
create(ProfiledBinary *Binary, const SampleProfileMap &&ProfileMap,
4148
bool ProfileIsCSFlat);
4249
virtual void generateProfile() = 0;
4350
void write();
@@ -113,20 +120,22 @@ class ProfileGeneratorBase {
113120

114121
uint64_t ColdCountThreshold;
115122

123+
ProfiledBinary *Binary = nullptr;
124+
116125
// Used by SampleProfileWriter
117126
SampleProfileMap ProfileMap;
118127

119-
ProfiledBinary *Binary = nullptr;
120-
121-
const ContextSampleCounterMap &SampleCounters;
128+
const ContextSampleCounterMap *SampleCounters = nullptr;
122129
};
123130

124131
class ProfileGenerator : public ProfileGeneratorBase {
125132

126133
public:
127134
ProfileGenerator(ProfiledBinary *Binary,
128-
const ContextSampleCounterMap &Counters)
135+
const ContextSampleCounterMap *Counters)
129136
: ProfileGeneratorBase(Binary, Counters){};
137+
ProfileGenerator(ProfiledBinary *Binary, const SampleProfileMap &&Profiles)
138+
: ProfileGeneratorBase(Binary, std::move(Profiles)){};
130139
void generateProfile() override;
131140

132141
private:
@@ -143,9 +152,10 @@ class ProfileGenerator : public ProfileGeneratorBase {
143152
void populateBodySamplesForAllFunctions(const RangeSample &RangeCounter);
144153
void
145154
populateBoundarySamplesForAllFunctions(const BranchSample &BranchCounters);
146-
void populateBodySamplesWithProbesForAllFunctions(const RangeSample &RangeCounter);
147155
void
148-
populateBoundarySamplesWithProbesForAllFunctions(const BranchSample &BranchCounters);
156+
populateBodySamplesWithProbesForAllFunctions(const RangeSample &RangeCounter);
157+
void populateBoundarySamplesWithProbesForAllFunctions(
158+
const BranchSample &BranchCounters);
149159
void postProcessProfiles();
150160
void trimColdProfiles(const SampleProfileMap &Profiles,
151161
uint64_t ColdCntThreshold);
@@ -154,9 +164,10 @@ class ProfileGenerator : public ProfileGeneratorBase {
154164
class CSProfileGenerator : public ProfileGeneratorBase {
155165
public:
156166
CSProfileGenerator(ProfiledBinary *Binary,
157-
const ContextSampleCounterMap &Counters)
167+
const ContextSampleCounterMap *Counters)
158168
: ProfileGeneratorBase(Binary, Counters){};
159-
169+
CSProfileGenerator(ProfiledBinary *Binary, const SampleProfileMap &&Profiles)
170+
: ProfileGeneratorBase(Binary, std::move(Profiles)){};
160171
void generateProfile() override;
161172

162173
// Trim the context stack at a given depth.

0 commit comments

Comments
 (0)