Skip to content

Commit 59b4074

Browse files
authored
[Propeller] Read the CFG profile from the propeller directive. (#160422)
The CFG allows us to do layout optimization in the compiler. Furthermore, it allows further branch optimization.
1 parent 792a7bb commit 59b4074

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ struct FunctionPathAndClusterInfo {
5050
// the edge a -> b (a is not cloned). The index of the path in this vector
5151
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
5252
SmallVector<SmallVector<unsigned>> ClonePaths;
53+
// Node counts for each basic block.
54+
DenseMap<UniqueBBID, uint64_t> NodeCounts;
55+
// Edge counts for each edge, stored as a nested map.
56+
DenseMap<UniqueBBID, DenseMap<UniqueBBID, uint64_t>> EdgeCounts;
5357
};
5458

5559
class BasicBlockSectionsProfileReader {
@@ -77,6 +81,11 @@ class BasicBlockSectionsProfileReader {
7781
SmallVector<SmallVector<unsigned>>
7882
getClonePathsForFunction(StringRef FuncName) const;
7983

84+
// Returns the profile count for the edge from `SrcBBID` to `SinkBBID` in
85+
// function `FuncName` or zero if it does not exist.
86+
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
87+
const UniqueBBID &SinkBBID) const;
88+
8089
private:
8190
StringRef getAliasName(StringRef FuncName) const {
8291
auto R = FuncAliasMap.find(FuncName);
@@ -183,6 +192,9 @@ class BasicBlockSectionsProfileReaderWrapperPass : public ImmutablePass {
183192
SmallVector<SmallVector<unsigned>>
184193
getClonePathsForFunction(StringRef FuncName) const;
185194

195+
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
196+
const UniqueBBID &DestBBID) const;
197+
186198
// Initializes the FunctionNameToDIFilename map for the current module and
187199
// then reads the profile for the matching functions.
188200
bool doInitialization(Module &M) override;

llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ BasicBlockSectionsProfileReader::getClonePathsForFunction(
7676
return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
7777
}
7878

79+
uint64_t BasicBlockSectionsProfileReader::getEdgeCount(
80+
StringRef FuncName, const UniqueBBID &SrcBBID,
81+
const UniqueBBID &SinkBBID) const {
82+
auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
83+
if (It == ProgramPathAndClusterInfo.end())
84+
return 0;
85+
auto NodeIt = It->second.EdgeCounts.find(SrcBBID);
86+
if (NodeIt == It->second.EdgeCounts.end())
87+
return 0;
88+
auto EdgeIt = NodeIt->second.find(SinkBBID);
89+
if (EdgeIt == NodeIt->second.end())
90+
return 0;
91+
return EdgeIt->second;
92+
}
93+
7994
// Reads the version 1 basic block sections profile. Profile for each function
8095
// is encoded as follows:
8196
// m <module_name>
@@ -240,6 +255,38 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
240255
}
241256
continue;
242257
}
258+
case 'g': { // CFG profile specifier.
259+
// Skip the profile when we the profile iterator (FI) refers to the
260+
// past-the-end element.
261+
if (FI == ProgramPathAndClusterInfo.end())
262+
continue;
263+
// For each node, its CFG profile is encoded as
264+
// <src>:<count>,<sink_1>:<count_1>,<sink_2>:<count_2>,...
265+
for (auto BasicBlockEdgeProfile : Values) {
266+
if (BasicBlockEdgeProfile.empty())
267+
continue;
268+
SmallVector<StringRef, 4> NodeEdgeCounts;
269+
BasicBlockEdgeProfile.split(NodeEdgeCounts, ',');
270+
UniqueBBID SrcBBID;
271+
for (size_t i = 0; i < NodeEdgeCounts.size(); ++i) {
272+
auto [BBIDStr, CountStr] = NodeEdgeCounts[i].split(':');
273+
auto BBID = parseUniqueBBID(BBIDStr);
274+
if (!BBID)
275+
return BBID.takeError();
276+
unsigned long long Count = 0;
277+
if (getAsUnsignedInteger(CountStr, 10, Count))
278+
return createProfileParseError(
279+
Twine("unsigned integer expected: '") + CountStr + "'");
280+
if (i == 0) {
281+
// The first element represents the source and its total count.
282+
FI->second.NodeCounts[SrcBBID = *BBID] = Count;
283+
continue;
284+
}
285+
FI->second.EdgeCounts[SrcBBID][*BBID] = Count;
286+
}
287+
}
288+
continue;
289+
}
243290
default:
244291
return createProfileParseError(Twine("invalid specifier: '") +
245292
Twine(Specifier) + "'");
@@ -440,6 +487,12 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
440487
return BBSPR.getClonePathsForFunction(FuncName);
441488
}
442489

490+
uint64_t BasicBlockSectionsProfileReaderWrapperPass::getEdgeCount(
491+
StringRef FuncName, const UniqueBBID &SrcBBID,
492+
const UniqueBBID &SinkBBID) const {
493+
return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
494+
}
495+
443496
BasicBlockSectionsProfileReader &
444497
BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
445498
return BBSPR;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; BB section test with CFG.
2+
;
3+
;; Profile for version 1:
4+
; RUN: echo 'v1' > %t
5+
; RUN: echo 'f foo' >> %t
6+
; RUN: echo 'g 0:10,1:9,2:1 1:8,3:8 2:2,3:2 3:11' >> %t
7+
; RUN: echo 'c 0 2 3' >> %t
8+
;
9+
; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t | FileCheck %s
10+
;
11+
define void @foo(i1 zeroext) nounwind {
12+
%2 = alloca i8, align 1
13+
%3 = zext i1 %0 to i8
14+
store i8 %3, ptr %2, align 1
15+
%4 = load i8, ptr %2, align 1
16+
%5 = trunc i8 %4 to i1
17+
br i1 %5, label %6, label %8
18+
19+
6: ; preds = %1
20+
%7 = call i32 @bar()
21+
br label %10
22+
23+
8: ; preds = %1
24+
%9 = call i32 @baz()
25+
br label %10
26+
27+
10: ; preds = %8, %6
28+
ret void
29+
}
30+
31+
declare i32 @bar() #1
32+
33+
declare i32 @baz() #1
34+
35+
; CHECK: .section .text.foo,"ax",@progbits
36+
; CHECK: callq baz
37+
; CHECK: retq
38+
; CHECK: .section .text.split.foo,"ax",@progbits
39+
; CHECK: callq bar
40+

llvm/test/CodeGen/X86/basic-block-sections-clusters-error.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@
5757
; RUN: echo 'p 1 2 3 2' >> %t13
5858
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t13 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR13
5959
; CHECK-ERROR13: LLVM ERROR: invalid profile {{.*}} at line 4: duplicate cloned block in path: '2'
60+
; RUN: echo 'v1' > %t14
61+
; RUN: echo 'f dummy1' >> %t14
62+
; RUN: echo 'c 0 1' >> %t14
63+
; RUN: echo 'g 0,1:2' >> %t14
64+
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t14 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR14
65+
; CHECK-ERROR14: LLVM ERROR: invalid profile {{.*}} at line 4: unsigned integer expected: ''
66+
; RUN: echo 'v1' > %t15
67+
; RUN: echo 'f dummy1' >> %t15
68+
; RUN: echo 'c 0 1' >> %t15
69+
; RUN: echo 'g 0:4,1:2:3' >> %t15
70+
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t15 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR15
71+
; CHECK-ERROR15: LLVM ERROR: invalid profile {{.*}} at line 4: unsigned integer expected: '2:3'
72+
6073

6174
define i32 @dummy1(i32 %x, i32 %y, i32 %z) {
6275
entry:

0 commit comments

Comments
 (0)