Skip to content

Commit 461a183

Browse files
author
Wael Yehia
committed
[PGO][AIX] Improve dummy var retention and allow -bcdtors:csect linking.
1) Use a static array of pointer to retain the dummy vars. 2) Associate liveness of the array with that of the runtime hook variable __llvm_profile_runtime. 3) Perform the runtime initialization through the runtime hook variable. 4) Preserve the runtime hook variable using the -u linker flag. Reviewed By: hubert.reinterpretcast Differential Revision: https://reviews.llvm.org/D136192
1 parent 4fd2b49 commit 461a183

File tree

9 files changed

+68
-32
lines changed

9 files changed

+68
-32
lines changed

clang/lib/Driver/ToolChains/AIX.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/Driver/Options.h"
1414
#include "clang/Driver/SanitizerArgs.h"
1515
#include "llvm/Option/ArgList.h"
16+
#include "llvm/ProfileData/InstrProf.h"
1617
#include "llvm/Support/Path.h"
1718

1819
using AIX = clang::driver::toolchains::AIX;
@@ -348,6 +349,16 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
348349
llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
349350
}
350351

352+
void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args,
353+
llvm::opt::ArgStringList &CmdArgs) const {
354+
// Add linker option -u__llvm_profile_runtime to cause runtime
355+
// initialization to occur.
356+
if (needsProfileRT(Args))
357+
CmdArgs.push_back(Args.MakeArgString(
358+
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
359+
ToolChain::addProfileRTLibs(Args, CmdArgs);
360+
}
361+
351362
ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const {
352363
return ToolChain::CST_Libcxx;
353364
}

clang/lib/Driver/ToolChains/AIX.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
8080
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
8181
llvm::opt::ArgStringList &CmdArgs) const override;
8282

83+
void addProfileRTLibs(const llvm::opt::ArgList &Args,
84+
llvm::opt::ArgStringList &CmdArgs) const override;
85+
8386
CXXStdlibType GetDefaultCXXStdlibType() const override;
8487

8588
RuntimeLibType GetDefaultRuntimeLibType() const override;

compiler-rt/lib/profile/InstrProfilingPlatformLinux.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -250,23 +250,21 @@ void __llvm_profile_register_names_function(void *NamesStart,
250250
// section exists. So for the scenario where the user objects have no such
251251
// section (i.e. when they are compiled with -fno-profile-generate), we always
252252
// define these zero length variables in each of the above 4 sections.
253-
COMPILER_RT_VISIBILITY int dummy_cnts[0] COMPILER_RT_SECTION(
253+
static int dummy_cnts[0] COMPILER_RT_SECTION(
254254
COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME);
255-
COMPILER_RT_VISIBILITY int dummy_data[0] COMPILER_RT_SECTION(
255+
static int dummy_data[0] COMPILER_RT_SECTION(
256256
COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME);
257-
COMPILER_RT_VISIBILITY const int dummy_name[0] COMPILER_RT_SECTION(
257+
static const int dummy_name[0] COMPILER_RT_SECTION(
258258
COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME);
259-
COMPILER_RT_VISIBILITY int dummy_vnds[0] COMPILER_RT_SECTION(
259+
static int dummy_vnds[0] COMPILER_RT_SECTION(
260260
COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME);
261261

262-
// Create a fake reference to avoid GC'ing of the dummy variables by the linker.
263-
// Ideally, we create a ".ref" of each variable inside the function
264-
// __llvm_profile_begin_counters(), but there's no source level construct
265-
// that allows us to generate that.
266-
__attribute__((destructor)) void keep() {
267-
int volatile use = &dummy_cnts < &dummy_data && &dummy_name < &dummy_vnds;
268-
(void)use;
269-
}
262+
// To avoid GC'ing of the dummy variables by the linker, reference them in an
263+
// array and reference the array in the runtime registration code
264+
// (InstrProfilingRuntime.cpp)
265+
COMPILER_RT_VISIBILITY
266+
void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_data,
267+
(void *)&dummy_name, (void *)&dummy_vnds};
270268
#endif
271269

272270
#endif

compiler-rt/lib/profile/InstrProfilingRuntime.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,23 @@ extern "C" {
1010

1111
#include "InstrProfiling.h"
1212

13-
/* int __llvm_profile_runtime */
14-
COMPILER_RT_VISIBILITY int INSTR_PROF_PROFILE_RUNTIME_VAR;
13+
static int RegisterRuntime() {
14+
__llvm_profile_initialize();
15+
return 0;
1516
}
1617

17-
namespace {
18-
19-
class RegisterRuntime {
20-
public:
21-
RegisterRuntime() {
22-
__llvm_profile_initialize();
23-
}
24-
};
25-
26-
RegisterRuntime Registration;
18+
#ifndef _AIX
19+
/* int __llvm_profile_runtime */
20+
COMPILER_RT_VISIBILITY int INSTR_PROF_PROFILE_RUNTIME_VAR;
2721

22+
static int Registration = RegisterRuntime();
23+
#else
24+
extern COMPILER_RT_VISIBILITY void *__llvm_profile_keep[];
25+
/* On AIX, when linking with -bcdtors:csect, the variable whose constructor does
26+
* the registration needs to be explicitly kept, hence we reuse the runtime hook
27+
* variable to do the registration since it'll be kept via the -u linker flag.
28+
* Create a volatile reference to __llvm_profile_keep to keep the array alive.*/
29+
COMPILER_RT_VISIBILITY int INSTR_PROF_PROFILE_RUNTIME_VAR =
30+
((void)*(void *volatile *)__llvm_profile_keep, RegisterRuntime());
31+
#endif
2832
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def getRoot(config):
2+
if not config.parent:
3+
return config
4+
return getRoot(config.parent)
5+
6+
root = getRoot(config)
7+
8+
if root.host_os not in ['AIX']:
9+
config.unsupported = True
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: split-file %s %t
2+
// RUN: cd %t
3+
//
4+
// RUN: %clang_pgogen foo.c -c -o foo.o
5+
// RUN: %clang_pgogen -shared foo.o -o libfoo.so -bexpall
6+
// RUN: %clang_pgogen -L%t user.c libfoo.so -o user1
7+
// RUN: ./user1
8+
9+
//--- foo.c
10+
void foo() {}
11+
12+
//--- user.c
13+
void foo();
14+
int main() { foo(); }

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1199,7 +1199,7 @@ void InstrProfiling::emitRegistration() {
11991199
bool InstrProfiling::emitRuntimeHook() {
12001200
// We expect the linker to be invoked with -u<hook_var> flag for Linux
12011201
// in which case there is no need to emit the external variable.
1202-
if (TT.isOSLinux())
1202+
if (TT.isOSLinux() || TT.isOSAIX())
12031203
return false;
12041204

12051205
// If the module's provided its own runtime, we don't need to do anything.

llvm/test/Instrumentation/InstrProfiling/no-counters.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s -check-prefixes=ALL,DARWIN
44
; RUN: opt < %s -mtriple=x86_64-linux-unknown -passes=instrprof -S | FileCheck %s -check-prefixes=ALL,LINUX
5-
; RUN: opt < %s -mtriple=powerpc64-ibm-aix-xcoff -passes=instrprof -S | FileCheck %s -check-prefixes=ALL,DARWIN
5+
; RUN: opt < %s -mtriple=powerpc64-ibm-aix-xcoff -passes=instrprof -S | FileCheck %s -check-prefixes=ALL,LINUX
66
; ALL-NOT: @__profc
77
; ALL-NOT: @__profd
88
; DARWIN: @__llvm_profile_runtime

llvm/test/Instrumentation/InstrProfiling/profiling.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
; MACHO: @__llvm_profile_runtime = external hidden global i32
1414
; ELF_GENERIC: @__llvm_profile_runtime = external hidden global i32
1515
; ELF-NOT: @__llvm_profile_runtime = external global i32
16-
; XCOFF: @__llvm_profile_runtime = external hidden global i32
16+
; XCOFF-NOT: @__llvm_profile_runtime = external hidden global i32
1717
; COFF: @__llvm_profile_runtime = external hidden global i32
1818

1919
; ELF: $__profc_foo = comdat nodeduplicate
@@ -101,7 +101,7 @@ declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
101101
; ELF_GENERIC: @llvm.compiler.used = appending global [6 x ptr] [ptr @__llvm_profile_runtime, ptr @__profd_foo, ptr @__profd_foo_weak, ptr @"__profd_linkage.ll:foo_internal", ptr @__profd_foo_inline, ptr @__profd_foo_extern]
102102
; MACHO: @llvm.compiler.used = appending global [6 x ptr] [ptr @__llvm_profile_runtime_user, ptr @__profd_foo, {{.*}}
103103
; COFF: @llvm.compiler.used = appending global [6 x ptr] [ptr @__llvm_profile_runtime_user, ptr @__profd_foo, ptr @__profd_foo_weak, ptr @"__profd_linkage.ll:foo_internal", ptr @__profd_foo_inline, ptr @__profd_foo_extern]
104-
; XCOFF: @llvm.used = appending global [7 x ptr] [ptr @__llvm_profile_runtime_user, ptr @__profd_foo, ptr @__profd_foo_weak, ptr @"__profd_linkage.ll:foo_internal", ptr @__profd_foo_inline, ptr @__profd_foo_extern, ptr @__llvm_prf_nm]
104+
; XCOFF: @llvm.used = appending global [6 x ptr] [ptr @__profd_foo, ptr @__profd_foo_weak, ptr @"__profd_linkage.ll:foo_internal", ptr @__profd_foo_inline, ptr @__profd_foo_extern, ptr @__llvm_prf_nm]
105105

106106
; MACHO: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} {
107107
; MACHO: %[[REG:.*]] = load i32, ptr @__llvm_profile_runtime
@@ -112,10 +112,7 @@ declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
112112
; ELFRT-NOT: %[[REG:.*]] = load i32, ptr @__llvm_profile_runtime
113113
; PS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} {
114114
; PS: %[[REG:.*]] = load i32, ptr @__llvm_profile_runtime
115-
; XCOFF: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} {
116-
; XCOFF: %[[REG:.*]] = load i32, ptr @__llvm_profile_runtime
117-
; XCOFF: ret i32 %[[REG]]
118-
; XCOFF: }
115+
; XCOFF-NOT: define .* __llvm_profile_runtime_user
119116

120117
; ELF_GENERIC: define internal void @__llvm_profile_register_functions() unnamed_addr {
121118
; ELF_GENERIC-NEXT: call void @__llvm_profile_register_function(ptr @__llvm_profile_runtime)

0 commit comments

Comments
 (0)