Index: llvm/include/llvm/ProfileData/SampleProf.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProf.h +++ llvm/include/llvm/ProfileData/SampleProf.h @@ -416,21 +416,21 @@ /// Return the sample count of the first instruction of the function. /// The function can be either a standalone symbol or an inlined function. uint64_t getEntrySamples() const { + uint64_t Count = 0; // Use either BodySamples or CallsiteSamples which ever has the smaller // lineno. if (!BodySamples.empty() && (CallsiteSamples.empty() || BodySamples.begin()->first < CallsiteSamples.begin()->first)) - return BodySamples.begin()->second.getSamples(); - if (!CallsiteSamples.empty()) { - uint64_t T = 0; + Count = BodySamples.begin()->second.getSamples(); + else if (!CallsiteSamples.empty()) { // An indirect callsite may be promoted to several inlined direct calls. // We need to get the sum of them. for (const auto &N_FS : CallsiteSamples.begin()->second) - T += N_FS.second.getEntrySamples(); - return T; + Count += N_FS.second.getEntrySamples(); } - return 0; + // Return at least 1 if total sample is not 0. + return Count ? Count : TotalSamples > 0; } /// Return all the samples collected in the body of the function. Index: llvm/test/Transforms/SampleProfile/Inputs/indirect-call.prof =================================================================== --- llvm/test/Transforms/SampleProfile/Inputs/indirect-call.prof +++ llvm/test/Transforms/SampleProfile/Inputs/indirect-call.prof @@ -29,3 +29,8 @@ 11: 3000 2: return_arg:3000 1: 3000 +branch_prof_valid:4000:0 + 1: 1000 + 2: foo_inline3:3000 + 1: 0 + 2: 3000 Index: llvm/test/Transforms/SampleProfile/indirect-call.ll =================================================================== --- llvm/test/Transforms/SampleProfile/indirect-call.ll +++ llvm/test/Transforms/SampleProfile/indirect-call.ll @@ -121,6 +121,17 @@ ret i32* null } +; CHECK-LABEL: @branch_prof_valid +define void @branch_prof_valid(void ()* %t0) !dbg !33 { + %t1 = alloca void ()* + store void ()* %t0, void ()** %t1 + %t2 = load void ()*, void ()** %t1 + ; CHECK-NOT: call {{.*}} + ; CHECK: br i1 {{.*}}, label %if.true.direct_targ, label %if.false.orig_indirect, {{.*}}, !prof ![[BR3:[0-9]+]] + call void %t2(), !dbg !34 + ret void +} + @x = global i32 0, align 4 @y = global void ()* null, align 8 @@ -148,6 +159,10 @@ ret i32* %x } +define void @foo_inline3() !dbg !35 { + ret void +} + define i32 @foo_noinline(i32 %x) !dbg !20 { ret i32 %x } @@ -184,6 +199,7 @@ ; CHECK: ![[BR1]] = !{!"branch_weights", i32 4000, i32 4000} ; CHECK: ![[BR2]] = !{!"branch_weights", i32 3000, i32 1000} ; CHECK: ![[VP]] = !{!"VP", i32 0, i64 8000, i64 -6391416044382067764, i64 1000} +; CHECK: ![[BR3]] = !{!"branch_weights", i32 1, i32 0} !6 = distinct !DISubprogram(name: "test_inline", scope: !1, file: !1, line: 6, unit: !0) !7 = !DILocation(line: 7, scope: !6) !8 = distinct !DISubprogram(name: "test_inline_strip", scope: !1, file: !1, line: 8, unit: !0) @@ -211,3 +227,6 @@ !30 = distinct !DISubprogram(name: "return_arg_caller", scope: !1, file: !1, line: 11, unit: !0) !31 = !DILocation(line: 12, scope: !30) !32 = !DILocation(line: 13, scope: !30) +!33 = distinct !DISubprogram(name: "branch_prof_valid", scope: !1, file: !1, line: 25, unit: !0) +!34 = !DILocation(line: 27, scope: !33) +!35 = distinct !DISubprogram(name: "foo_inline3", scope: !1, file: !1, line: 29, unit: !0)