Skip to content

Commit 7008ce3

Browse files
committed
[profile] value profiling bug fix -- missing icall targets in profile-use
Inline virtual functions has linkeonceodr linkage (emitted in comdat on supporting targets). If the vtable for the class is not emitted in the defining module, function won't be address taken thus its address is not recorded. At the mercy of the linker, if the per-func prf_data from this module (in comdat) is picked at link time, we will lose mapping from function address to its hash val. This leads to missing icall promotion. The second test case (currently disabled) in compiler_rt (r271528): instrprof-icall-prom.test demostrates the bug. The first profile-use subtest is fine due to linker order difference. With this change, no missing icall targets is found in instrumented clang's raw profile. llvm-svn: 271532
1 parent fd7ddf1 commit 7008ce3

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,13 @@ static inline bool shouldRecordFunctionAddr(Function *F) {
258258
if (F->hasLocalLinkage() && F->hasComdat())
259259
return false;
260260
// Check uses of this function for other than direct calls or invokes to it.
261-
return F->hasAddressTaken();
261+
// Inline virtual functions have linkeOnceODR linkage. When a key method
262+
// exists, the vtable will only be emitted in the TU where the key method
263+
// is defined. In a TU where vtable is not available, the function won't
264+
// be 'addresstaken'. If its address is not recorded here, the profile counter
265+
// comdat group with missing address may be picked by the linker leading
266+
// to missing indirect call target info.
267+
return F->hasAddressTaken() || (F->hasLinkOnceLinkage() && F->hasComdat());
262268
}
263269

264270
static inline bool needsComdatForCounter(Function &F, Module &M) {

llvm/test/Instrumentation/InstrProfiling/PR23499.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ $_Z3barIvEvv = comdat any
1515

1616
; CHECK: @__profn__Z3barIvEvv = private constant [11 x i8] c"_Z3barIvEvv", align 1
1717
; CHECK: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat($__profv__Z3barIvEvv), align 8
18-
; CHECK: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [1 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8* null, i8* null, i32 1, [1 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data", comdat($__profv__Z3barIvEvv), align 8
18+
; CHECK: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [1 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [1 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data", comdat($__profv__Z3barIvEvv), align 8
1919
; CHECK: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}__llvm_prf_names"
2020

2121

2222
; COFF: @__profn__Z3barIvEvv = private constant [11 x i8] c"_Z3barIvEvv", align 1
2323
; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat, align 8
24-
; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [1 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8* null, i8* null, i32 1, [1 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data", comdat($__profc__Z3barIvEvv), align 8
24+
; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [1 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [1 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data", comdat($__profc__Z3barIvEvv), align 8
2525

2626

2727
declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1

llvm/test/Transforms/PGOProfile/indirect_call_profile.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
22
; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
3+
; RUN: opt < %s -passes=pgo-instr-gen,instrprof -S | FileCheck %s --check-prefix=LOWER
4+
35
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
46
target triple = "x86_64-unknown-linux-gnu"
57

8+
$foo3 = comdat any
9+
610
@bar = external global void ()*, align 8
711
; GEN: @__profn_foo = private constant [3 x i8] c"foo"
812

@@ -49,6 +53,13 @@ bb11: ; preds = %bb2
4953
resume { i8*, i32 } %tmp3
5054
}
5155

56+
; Test that comdat function's address is recorded.
57+
; LOWER: @__profd_foo3 = linkonce_odr{{.*}}@foo3
58+
; Function Attrs: nounwind uwtable
59+
define linkonce_odr i32 @foo3() comdat {
60+
ret i32 1
61+
}
62+
5263
declare i32 @__gxx_personality_v0(...)
5364

5465
; Function Attrs: nounwind readnone

0 commit comments

Comments
 (0)