Skip to content

Commit 686a206

Browse files
authored
[SampleProfileLoader] Fix integer overflow in generateMDProfMetadata (#90217)
This patch fixes an integer overflow in the SampleProfileLoader pass. The issue occurs when weights are saturated and Profi isn't being used. This patch also adds a newline to a debug message to make it more readable.
1 parent c84c74e commit 686a206

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

llvm/lib/Transforms/IPO/SampleProfile.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,13 +1715,15 @@ void SampleProfileLoader::generateMDProfMetadata(Function &F) {
17151715
// if needed. Sample counts in profiles are 64-bit unsigned values,
17161716
// but internally branch weights are expressed as 32-bit values.
17171717
if (Weight > std::numeric_limits<uint32_t>::max()) {
1718-
LLVM_DEBUG(dbgs() << " (saturated due to uint32_t overflow)");
1718+
LLVM_DEBUG(dbgs() << " (saturated due to uint32_t overflow)\n");
17191719
Weight = std::numeric_limits<uint32_t>::max();
17201720
}
17211721
if (!SampleProfileUseProfi) {
17221722
// Weight is added by one to avoid propagation errors introduced by
17231723
// 0 weights.
1724-
Weights.push_back(static_cast<uint32_t>(Weight + 1));
1724+
Weights.push_back(static_cast<uint32_t>(
1725+
Weight == std::numeric_limits<uint32_t>::max() ? Weight
1726+
: Weight + 1));
17251727
} else {
17261728
// Profi creates proper weights that do not require "+1" adjustments but
17271729
// we evenly split the weight among branches with the same destination.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
_Z3testi:29600000000:29600000000
2+
5: 29600000000
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4
2+
3+
; Checks that we are able to handle overflowing counters correctly.
4+
5+
; RUN: opt < %s -passes='sample-profile,print<branch-prob>' -sample-profile-file=%S/Inputs/overflow.proftext -disable-output 2>&1 | FileCheck %s
6+
7+
; Original Source:
8+
; int sqrt(int);
9+
; int test(int i) {
10+
; if (i == 5) {
11+
; return 42;
12+
; }
13+
; else {
14+
; return sqrt(i);
15+
; }
16+
;}
17+
18+
define dso_local noundef i32 @_Z3testi(i32 noundef %i) local_unnamed_addr #0 !dbg !10 {
19+
; CHECK-LABEL: '_Z3testi'
20+
; CHECK-NEXT: ---- Branch Probabilities ----
21+
; CHECK-NEXT: edge %entry -> %return probability is 0x00000000 / 0x80000000 = 0.00%
22+
; CHECK-NEXT: edge %entry -> %if.else probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
23+
; CHECK-NEXT: edge %if.else -> %return probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
24+
;
25+
entry:
26+
tail call void @llvm.dbg.value(metadata i32 %i, metadata !16, metadata !DIExpression()), !dbg !17
27+
%cmp = icmp eq i32 %i, 5, !dbg !18
28+
br i1 %cmp, label %return, label %if.else, !dbg !20
29+
30+
if.else: ; preds = %entry
31+
%call = tail call noundef i32 @_Z4sqrti(i32 noundef %i), !dbg !21
32+
br label %return, !dbg !23
33+
34+
return: ; preds = %entry, %if.else
35+
%retval.0 = phi i32 [ %call, %if.else ], [ 42, %entry ], !dbg !24
36+
ret i32 %retval.0, !dbg !25
37+
}
38+
39+
declare !dbg !26 noundef i32 @_Z4sqrti(i32 noundef)
40+
41+
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
42+
declare void @llvm.dbg.value(metadata, metadata, metadata)
43+
44+
attributes #0 = { "use-sample-profile" }
45+
46+
!llvm.dbg.cu = !{!0}
47+
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
48+
!llvm.ident = !{!9}
49+
50+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
51+
!1 = !DIFile(filename: "test.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "cb38d90153a7ebdd6ecf3058eb0524c7")
52+
!2 = !{i32 7, !"Dwarf Version", i32 5}
53+
!3 = !{i32 2, !"Debug Info Version", i32 3}
54+
!4 = !{i32 1, !"wchar_size", i32 4}
55+
!5 = !{i32 8, !"PIC Level", i32 2}
56+
!6 = !{i32 7, !"PIE Level", i32 2}
57+
!7 = !{i32 7, !"uwtable", i32 2}
58+
!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
59+
!9 = !{!"clang"}
60+
!10 = distinct !DISubprogram(name: "test", linkageName: "_Z3loli", scope: !11, file: !11, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15)
61+
!11 = !DIFile(filename: "./test.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "cb38d90153a7ebdd6ecf3058eb0524c7")
62+
!12 = !DISubroutineType(types: !13)
63+
!13 = !{!14, !14}
64+
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
65+
!15 = !{!16}
66+
!16 = !DILocalVariable(name: "i", arg: 1, scope: !10, file: !11, line: 3, type: !14)
67+
!17 = !DILocation(line: 0, scope: !10)
68+
!18 = !DILocation(line: 4, column: 11, scope: !19)
69+
!19 = distinct !DILexicalBlock(scope: !10, file: !11, line: 4, column: 9)
70+
!20 = !DILocation(line: 4, column: 9, scope: !10)
71+
!21 = !DILocation(line: 8, column: 16, scope: !22)
72+
!22 = distinct !DILexicalBlock(scope: !19, file: !11, line: 7, column: 10)
73+
!23 = !DILocation(line: 8, column: 9, scope: !22)
74+
!24 = !DILocation(line: 0, scope: !19)
75+
!25 = !DILocation(line: 10, column: 1, scope: !10)
76+
!26 = !DISubprogram(name: "sqrt", linkageName: "_Z4sqrti", scope: !11, file: !11, line: 1, type: !12, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
77+

0 commit comments

Comments
 (0)