Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions llvm/include/llvm/CodeGen/BasicBlockSectionsProfileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ struct FunctionPathAndClusterInfo {
// the edge a -> b (a is not cloned). The index of the path in this vector
// determines the `UniqueBBID::CloneID` of the cloned blocks in that path.
SmallVector<SmallVector<unsigned>> ClonePaths;
// Node counts for each basic block.
DenseMap<UniqueBBID, uint64_t> NodeCounts;
// Edge counts for each edge, stored as a nested map.
DenseMap<UniqueBBID, DenseMap<UniqueBBID, uint64_t>> EdgeCounts;
};

class BasicBlockSectionsProfileReader {
Expand Down Expand Up @@ -77,6 +81,11 @@ class BasicBlockSectionsProfileReader {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;

// Returns the profile count for the edge from `SrcBBID` to `SinkBBID` in
// function `FuncName` or zero if it does not exist.
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
const UniqueBBID &SinkBBID) const;

private:
StringRef getAliasName(StringRef FuncName) const {
auto R = FuncAliasMap.find(FuncName);
Expand Down Expand Up @@ -183,6 +192,9 @@ class BasicBlockSectionsProfileReaderWrapperPass : public ImmutablePass {
SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const;

uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID,
const UniqueBBID &DestBBID) const;

// Initializes the FunctionNameToDIFilename map for the current module and
// then reads the profile for the matching functions.
bool doInitialization(Module &M) override;
Expand Down
53 changes: 53 additions & 0 deletions llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ BasicBlockSectionsProfileReader::getClonePathsForFunction(
return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
}

uint64_t BasicBlockSectionsProfileReader::getEdgeCount(
StringRef FuncName, const UniqueBBID &SrcBBID,
const UniqueBBID &SinkBBID) const {
auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
if (It == ProgramPathAndClusterInfo.end())
return 0;
auto NodeIt = It->second.EdgeCounts.find(SrcBBID);
if (NodeIt == It->second.EdgeCounts.end())
return 0;
auto EdgeIt = NodeIt->second.find(SinkBBID);
if (EdgeIt == NodeIt->second.end())
return 0;
return EdgeIt->second;
}

// Reads the version 1 basic block sections profile. Profile for each function
// is encoded as follows:
// m <module_name>
Expand Down Expand Up @@ -240,6 +255,38 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
}
continue;
}
case 'g': { // CFG profile specifier.
// Skip the profile when we the profile iterator (FI) refers to the
// past-the-end element.
if (FI == ProgramPathAndClusterInfo.end())
continue;
// For each node, its CFG profile is encoded as
// <src>:<count>,<sink_1>:<count_1>,<sink_2>:<count_2>,...
for (auto BasicBlockEdgeProfile : Values) {
if (BasicBlockEdgeProfile.empty())
continue;
SmallVector<StringRef, 4> NodeEdgeCounts;
BasicBlockEdgeProfile.split(NodeEdgeCounts, ',');
UniqueBBID SrcBBID;
for (size_t i = 0; i < NodeEdgeCounts.size(); ++i) {
auto [BBIDStr, CountStr] = NodeEdgeCounts[i].split(':');
auto BBID = parseUniqueBBID(BBIDStr);
if (!BBID)
return BBID.takeError();
unsigned long long Count = 0;
if (getAsUnsignedInteger(CountStr, 10, Count))
return createProfileParseError(
Twine("unsigned integer expected: '") + CountStr + "'");
if (i == 0) {
// The first element represents the source and its total count.
FI->second.NodeCounts[SrcBBID = *BBID] = Count;
continue;
}
FI->second.EdgeCounts[SrcBBID][*BBID] = Count;
}
}
continue;
}
default:
return createProfileParseError(Twine("invalid specifier: '") +
Twine(Specifier) + "'");
Expand Down Expand Up @@ -440,6 +487,12 @@ BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
return BBSPR.getClonePathsForFunction(FuncName);
}

uint64_t BasicBlockSectionsProfileReaderWrapperPass::getEdgeCount(
StringRef FuncName, const UniqueBBID &SrcBBID,
const UniqueBBID &SinkBBID) const {
return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
}

BasicBlockSectionsProfileReader &
BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
return BBSPR;
Expand Down
40 changes: 40 additions & 0 deletions llvm/test/CodeGen/X86/basic-block-sections-cfg.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
; BB section test with CFG.
;
;; Profile for version 1:
; RUN: echo 'v1' > %t
; RUN: echo 'f foo' >> %t
; RUN: echo 'g 0:10,1:9,2:1 1:8,3:8 2:2,3:2 3:11' >> %t
; RUN: echo 'c 0 2 3' >> %t
;
; RUN: llc < %s -O0 -mtriple=x86_64-pc-linux -function-sections -basic-block-sections=%t | FileCheck %s
;
define void @foo(i1 zeroext) nounwind {
%2 = alloca i8, align 1
%3 = zext i1 %0 to i8
store i8 %3, ptr %2, align 1
%4 = load i8, ptr %2, align 1
%5 = trunc i8 %4 to i1
br i1 %5, label %6, label %8

6: ; preds = %1
%7 = call i32 @bar()
br label %10

8: ; preds = %1
%9 = call i32 @baz()
br label %10

10: ; preds = %8, %6
ret void
}

declare i32 @bar() #1

declare i32 @baz() #1

; CHECK: .section .text.foo,"ax",@progbits
; CHECK: callq baz
; CHECK: retq
; CHECK: .section .text.split.foo,"ax",@progbits
; CHECK: callq bar

13 changes: 13 additions & 0 deletions llvm/test/CodeGen/X86/basic-block-sections-clusters-error.ll
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@
; RUN: echo 'p 1 2 3 2' >> %t13
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t13 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR13
; CHECK-ERROR13: LLVM ERROR: invalid profile {{.*}} at line 4: duplicate cloned block in path: '2'
; RUN: echo 'v1' > %t14
; RUN: echo 'f dummy1' >> %t14
; RUN: echo 'c 0 1' >> %t14
; RUN: echo 'g 0,1:2' >> %t14
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t14 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR14
; CHECK-ERROR14: LLVM ERROR: invalid profile {{.*}} at line 4: unsigned integer expected: ''
; RUN: echo 'v1' > %t15
; RUN: echo 'f dummy1' >> %t15
; RUN: echo 'c 0 1' >> %t15
; RUN: echo 'g 0:4,1:2:3' >> %t15
; RUN: not --crash llc < %s -O0 -mtriple=x86_64 -function-sections -basic-block-sections=%t15 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR15
; CHECK-ERROR15: LLVM ERROR: invalid profile {{.*}} at line 4: unsigned integer expected: '2:3'


define i32 @dummy1(i32 %x, i32 %y, i32 %z) {
entry:
Expand Down