mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-01 15:21:00 +00:00
[InstrProf] Implement static profdata registration
Summary: The motivating use case is eliminating duplicate profile data registered for the same inline function in two object files. Before this change, users would observe multiple symbol definition errors with VC link, but links with LLD would succeed. Users (Mozilla) have reported that PGO works well with clang-cl and LLD, but when using LLD without this static registration, we would get into a "relocation against a discarded section" situation. I'm not sure what happens in that situation, but I suspect that duplicate, unused profile information was retained. If so, this change will reduce the size of such binaries with LLD. Now, Windows uses static registration and is in line with all the other platforms. Reviewers: davidxl, wmi, inglorion, void, calixte Subscribers: mgorny, krytarowski, eraman, fedor.sergeev, hiraditya, #sanitizers, dmajor, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D57929 llvm-svn: 353547
This commit is contained in:
parent
9dc95b1f60
commit
9cb616246a
@ -249,22 +249,22 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
|
||||
#define INSTR_PROF_DATA_DEFINED
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_data, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,")
|
||||
INSTR_PROF_DATA_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,")
|
||||
INSTR_PROF_CNTS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_name, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,")
|
||||
INSTR_PROF_NAME_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_vals, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,")
|
||||
INSTR_PROF_VALS_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,")
|
||||
INSTR_PROF_VNODES_COFF, "__DATA,")
|
||||
INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,")
|
||||
INSTR_PROF_COVMAP_COFF, "__LLVM_COV,")
|
||||
|
||||
#undef INSTR_PROF_SECT_ENTRY
|
||||
#endif
|
||||
@ -654,13 +654,15 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
|
||||
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
|
||||
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
|
||||
/* Win32 */
|
||||
#define INSTR_PROF_DATA_COFF .lprfd
|
||||
#define INSTR_PROF_NAME_COFF .lprfn
|
||||
#define INSTR_PROF_CNTS_COFF .lprfc
|
||||
#define INSTR_PROF_VALS_COFF .lprfv
|
||||
#define INSTR_PROF_VNODES_COFF .lprfnd
|
||||
#define INSTR_PROF_COVMAP_COFF .lcovmap
|
||||
/* Windows section names. Because these section names contain dollar characters,
|
||||
* they must be quoted.
|
||||
*/
|
||||
#define INSTR_PROF_DATA_COFF ".lprfd$M"
|
||||
#define INSTR_PROF_NAME_COFF ".lprfn$M"
|
||||
#define INSTR_PROF_CNTS_COFF ".lprfc$M"
|
||||
#define INSTR_PROF_VALS_COFF ".lprfv$M"
|
||||
#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
|
||||
#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Runtime section names and name strings. */
|
||||
@ -676,31 +678,18 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
|
||||
#else
|
||||
/* Runtime section names and name strings. */
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON
|
||||
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
|
||||
#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON)
|
||||
#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON)
|
||||
/* Array of pointers. Each pointer points to a list
|
||||
* of value nodes associated with one value site.
|
||||
*/
|
||||
#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON
|
||||
#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON)
|
||||
/* Value profile nodes section. */
|
||||
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON
|
||||
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON)
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON)
|
||||
#endif
|
||||
|
||||
#define INSTR_PROF_DATA_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME)
|
||||
#define INSTR_PROF_NAME_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_NAME_SECT_NAME)
|
||||
#define INSTR_PROF_CNTS_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME)
|
||||
#define INSTR_PROF_COVMAP_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_SECT_NAME)
|
||||
#define INSTR_PROF_VALS_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VALS_SECT_NAME)
|
||||
#define INSTR_PROF_VNODES_SECT_NAME_STR \
|
||||
INSTR_PROF_QUOTE(INSTR_PROF_VNODES_SECT_NAME)
|
||||
|
||||
/* Macros to define start/stop section symbol for a given
|
||||
* section on Linux. For instance
|
||||
* INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will
|
||||
|
@ -677,22 +677,6 @@ static inline bool shouldRecordFunctionAddr(Function *F) {
|
||||
return F->hasAddressTaken() || F->hasLinkOnceLinkage();
|
||||
}
|
||||
|
||||
static inline Comdat *getOrCreateProfileComdat(Module &M, Function &F,
|
||||
InstrProfIncrementInst *Inc,
|
||||
const Triple &TT) {
|
||||
if (!needsComdatForCounter(F, M))
|
||||
return nullptr;
|
||||
|
||||
// COFF format requires a COMDAT section to have a key symbol with the same
|
||||
// name. The linker targeting COFF also requires that the COMDAT
|
||||
// a section is associated to must precede the associating section. For this
|
||||
// reason, we must choose the counter var's name as the name of the comdat.
|
||||
StringRef ComdatPrefix =
|
||||
(TT.isOSBinFormatCOFF() ? getInstrProfCountersVarPrefix()
|
||||
: getInstrProfComdatPrefix());
|
||||
return M.getOrInsertComdat(StringRef(getVarName(Inc, ComdatPrefix)));
|
||||
}
|
||||
|
||||
static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
|
||||
// Don't do this for Darwin. compiler-rt uses linker magic.
|
||||
if (TT.isOSDarwin())
|
||||
@ -700,7 +684,7 @@ static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
|
||||
|
||||
// Use linker script magic to get data/cnts/name start/end.
|
||||
if (TT.isOSLinux() || TT.isOSFreeBSD() || TT.isOSNetBSD() ||
|
||||
TT.isOSFuchsia() || TT.isPS4CPU())
|
||||
TT.isOSFuchsia() || TT.isPS4CPU() || TT.isOSWindows())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -717,13 +701,44 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
|
||||
PD = It->second;
|
||||
}
|
||||
|
||||
// Move the name variable to the right section. Place them in a COMDAT group
|
||||
// if the associated function is a COMDAT. This will make sure that
|
||||
// only one copy of counters of the COMDAT function will be emitted after
|
||||
// linking.
|
||||
// Match the linkage and visibility of the name global, except on COFF, where
|
||||
// the linkage must be local and consequentially the visibility must be
|
||||
// default.
|
||||
Function *Fn = Inc->getParent()->getParent();
|
||||
Comdat *ProfileVarsComdat = nullptr;
|
||||
ProfileVarsComdat = getOrCreateProfileComdat(*M, *Fn, Inc, TT);
|
||||
GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
|
||||
GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
|
||||
if (TT.isOSBinFormatCOFF()) {
|
||||
Linkage = GlobalValue::InternalLinkage;
|
||||
Visibility = GlobalValue::DefaultVisibility;
|
||||
}
|
||||
|
||||
// Move the name variable to the right section. Place them in a COMDAT group
|
||||
// if the associated function is a COMDAT. This will make sure that only one
|
||||
// copy of counters of the COMDAT function will be emitted after linking.
|
||||
Comdat *Cmdt = nullptr;
|
||||
GlobalValue::LinkageTypes CounterLinkage = Linkage;
|
||||
if (needsComdatForCounter(*Fn, *M)) {
|
||||
if (TT.isOSBinFormatCOFF()) {
|
||||
// There are two cases that need a comdat on COFF:
|
||||
// 1. Functions that already have comdats (standard case)
|
||||
// 2. available_externally functions (dllimport and C99 inline)
|
||||
// In the first case, put all the data in the original function comdat. In
|
||||
// the second case, create a new comdat group using the counter as the
|
||||
// leader. It's linkage must be external, so use linkonce_odr linkage in
|
||||
// that case.
|
||||
if (Comdat *C = Fn->getComdat()) {
|
||||
Cmdt = C;
|
||||
} else {
|
||||
Cmdt = M->getOrInsertComdat(
|
||||
getVarName(Inc, getInstrProfCountersVarPrefix()));
|
||||
CounterLinkage = GlobalValue::LinkOnceODRLinkage;
|
||||
}
|
||||
} else {
|
||||
// For other platforms that use comdats (ELF), make a new comdat group for
|
||||
// all the profile data. It will be deduplicated within the current DSO.
|
||||
Cmdt = M->getOrInsertComdat(getVarName(Inc, getInstrProfComdatPrefix()));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
|
||||
LLVMContext &Ctx = M->getContext();
|
||||
@ -731,14 +746,15 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
|
||||
|
||||
// Create the counters variable.
|
||||
auto *CounterPtr =
|
||||
new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(),
|
||||
new GlobalVariable(*M, CounterTy, false, Linkage,
|
||||
Constant::getNullValue(CounterTy),
|
||||
getVarName(Inc, getInstrProfCountersVarPrefix()));
|
||||
CounterPtr->setVisibility(NamePtr->getVisibility());
|
||||
CounterPtr->setVisibility(Visibility);
|
||||
CounterPtr->setSection(
|
||||
getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
|
||||
CounterPtr->setAlignment(8);
|
||||
CounterPtr->setComdat(ProfileVarsComdat);
|
||||
CounterPtr->setComdat(Cmdt);
|
||||
CounterPtr->setLinkage(CounterLinkage);
|
||||
|
||||
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
|
||||
// Allocate statically the array of pointers to value profile nodes for
|
||||
@ -752,14 +768,14 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
|
||||
ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
|
||||
|
||||
auto *ValuesVar =
|
||||
new GlobalVariable(*M, ValuesTy, false, NamePtr->getLinkage(),
|
||||
new GlobalVariable(*M, ValuesTy, false, Linkage,
|
||||
Constant::getNullValue(ValuesTy),
|
||||
getVarName(Inc, getInstrProfValuesVarPrefix()));
|
||||
ValuesVar->setVisibility(NamePtr->getVisibility());
|
||||
ValuesVar->setVisibility(Visibility);
|
||||
ValuesVar->setSection(
|
||||
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
|
||||
ValuesVar->setAlignment(8);
|
||||
ValuesVar->setComdat(ProfileVarsComdat);
|
||||
ValuesVar->setComdat(Cmdt);
|
||||
ValuesPtrExpr =
|
||||
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
|
||||
}
|
||||
@ -786,13 +802,13 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
|
||||
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
|
||||
#include "llvm/ProfileData/InstrProfData.inc"
|
||||
};
|
||||
auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(),
|
||||
auto *Data = new GlobalVariable(*M, DataTy, false, Linkage,
|
||||
ConstantStruct::get(DataTy, DataVals),
|
||||
getVarName(Inc, getInstrProfDataVarPrefix()));
|
||||
Data->setVisibility(NamePtr->getVisibility());
|
||||
Data->setVisibility(Visibility);
|
||||
Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat()));
|
||||
Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT);
|
||||
Data->setComdat(ProfileVarsComdat);
|
||||
Data->setComdat(Cmdt);
|
||||
|
||||
PD.RegionCounters = CounterPtr;
|
||||
PD.DataVar = Data;
|
||||
@ -878,6 +894,10 @@ void InstrProfiling::emitNameData() {
|
||||
NamesSize = CompressedNameStr.size();
|
||||
NamesVar->setSection(
|
||||
getInstrProfSectionName(IPSK_name, TT.getObjectFormat()));
|
||||
// On COFF, it's important to reduce the alignment down to 1 to prevent the
|
||||
// linker from inserting padding before the start of the names section or
|
||||
// between names entries.
|
||||
NamesVar->setAlignment(1);
|
||||
UsedVars.push_back(NamesVar);
|
||||
|
||||
for (auto *NamePtr : ReferencedNames)
|
||||
|
@ -20,8 +20,8 @@ $_Z3barIvEvv = comdat any
|
||||
|
||||
|
||||
; COFF-NOT: __profn__Z3barIvEvv
|
||||
; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}prfc", comdat, align 8
|
||||
; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 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, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($__profc__Z3barIvEvv), align 8
|
||||
; COFF: @__profc__Z3barIvEvv = internal global [1 x i64] zeroinitializer, section "{{.*}}prfc$M", comdat($_Z3barIvEvv), align 8
|
||||
; COFF: @__profd__Z3barIvEvv = internal global { i64, i64, i64*, i8*, i8*, i32, [2 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, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($_Z3barIvEvv), align 8
|
||||
|
||||
|
||||
declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1
|
||||
|
38
test/Instrumentation/InstrProfiling/comdat.ll
Normal file
38
test/Instrumentation/InstrProfiling/comdat.ll
Normal file
@ -0,0 +1,38 @@
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s --check-prefixes=ELF
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -instrprof -S | FileCheck %s --check-prefixes=COFF
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s --check-prefixes=ELF
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF
|
||||
|
||||
; There are two main cases where comdats are necessary:
|
||||
; 1. standard inline functions (weak_odr / linkonce_odr)
|
||||
; 2. available externally functions (C99 inline / extern template / dllimport)
|
||||
; Check that we do the right thing for the two object formats with comdats, ELF
|
||||
; and COFF.
|
||||
|
||||
declare void @llvm.instrprof.increment(i8*, i64, i32, i32)
|
||||
|
||||
$foo_inline = comdat any
|
||||
|
||||
@__profn_foo_inline = linkonce_odr hidden constant [10 x i8] c"foo_inline"
|
||||
|
||||
; ELF: @__profc_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($__profv_foo_inline), align 8
|
||||
; ELF: @__profd_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profv_foo_inline), align 8
|
||||
; COFF: @__profc_foo_inline = internal global{{.*}}, section ".lprfc$M", comdat($foo_inline), align 8
|
||||
; COFF: @__profd_foo_inline = internal global{{.*}}, section ".lprfd$M", comdat($foo_inline), align 8
|
||||
define weak_odr void @foo_inline() comdat {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
$foo_extern = comdat any
|
||||
|
||||
@__profn_foo_extern = linkonce_odr hidden constant [10 x i8] c"foo_extern"
|
||||
|
||||
; ELF: @__profc_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($__profv_foo_extern)
|
||||
; ELF: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profv_foo_extern)
|
||||
; COFF: @__profc_foo_extern = linkonce_odr dso_local global{{.*}}, section ".lprfc$M", comdat, align 8
|
||||
; COFF: @__profd_foo_extern = internal global{{.*}}, section ".lprfd$M", comdat($__profc_foo_extern), align 8
|
||||
define available_externally void @foo_extern() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_extern, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
;; Check that runtime symbols get appropriate linkage.
|
||||
|
||||
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s --check-prefixes=COMMON,MACHO
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s --check-prefixes=COMMON,LINUX
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -instrprof -S | FileCheck %s --check-prefixes=COMMON,COFF
|
||||
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s --check-prefixes=COMMON,MACHO
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s --check-prefixes=COMMON,LINUX
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COMMON,COFF
|
||||
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -S | FileCheck %s --check-prefixes=POSIX,MACHO
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -S | FileCheck %s --check-prefixes=POSIX,LINUX
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -instrprof -S | FileCheck %s --check-prefixes=COFF
|
||||
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -passes=instrprof -S | FileCheck %s --check-prefixes=POSIX,MACHO
|
||||
; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s --check-prefixes=POSIX,LINUX
|
||||
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF
|
||||
|
||||
; MACHO: @__llvm_profile_runtime = external global i32
|
||||
; LINUX-NOT: @__llvm_profile_runtime = external global i32
|
||||
@ -16,31 +16,38 @@
|
||||
@__profn_foo_inline = linkonce_odr hidden constant [10 x i8] c"foo_inline"
|
||||
@__profn_foo_extern = linkonce_odr hidden constant [10 x i8] c"foo_extern"
|
||||
|
||||
; COMMON: @__profc_foo = hidden global
|
||||
; COMMON: @__profd_foo = hidden global
|
||||
; POSIX: @__profc_foo = hidden global
|
||||
; POSIX: @__profd_foo = hidden global
|
||||
; COFF: @__profc_foo = internal global
|
||||
; COFF-NOT: comdat
|
||||
; COFF: @__profd_foo = internal global
|
||||
define void @foo() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; COMMON: @__profc_foo_weak = weak hidden global
|
||||
; COMMON: @__profd_foo_weak = weak hidden global
|
||||
; POSIX: @__profc_foo_weak = weak hidden global
|
||||
; POSIX: @__profd_foo_weak = weak hidden global
|
||||
; COFF: @__profc_foo_weak = internal global
|
||||
; COFF: @__profd_foo_weak = internal global
|
||||
define weak void @foo_weak() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @__profn_foo_weak, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; COMMON: @"__profc_linkage.ll:foo_internal" = internal global
|
||||
; COMMON: @"__profd_linkage.ll:foo_internal" = internal global
|
||||
; POSIX: @"__profc_linkage.ll:foo_internal" = internal global
|
||||
; POSIX: @"__profd_linkage.ll:foo_internal" = internal global
|
||||
; COFF: @"__profc_linkage.ll:foo_internal" = internal global
|
||||
; COFF: @"__profd_linkage.ll:foo_internal" = internal global
|
||||
define internal void @foo_internal() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @"__profn_linkage.ll:foo_internal", i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
}
|
||||
|
||||
; COMMON: @__profc_foo_inline = linkonce_odr hidden global
|
||||
; COFF-SAME: section ".lprfc", align 8
|
||||
; COMMON: @__profd_foo_inline = linkonce_odr hidden global
|
||||
; COFF-SAME: section ".lprfd", align 8
|
||||
; POSIX: @__profc_foo_inline = linkonce_odr hidden global
|
||||
; POSIX: @__profd_foo_inline = linkonce_odr hidden global
|
||||
; COFF: @__profc_foo_inline = internal global{{.*}} section ".lprfc$M", align 8
|
||||
; COFF: @__profd_foo_inline = internal global{{.*}} section ".lprfd$M", align 8
|
||||
define linkonce_odr void @foo_inline() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
@ -50,8 +57,8 @@ define linkonce_odr void @foo_inline() {
|
||||
; LINUX: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_data", comdat($__profv_foo_extern), align 8
|
||||
; MACHO: @__profc_foo_extern = linkonce_odr hidden global
|
||||
; MACHO: @__profd_foo_extern = linkonce_odr hidden global
|
||||
; COFF: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfc", comdat, align 8
|
||||
; COFF: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfd", comdat($__profc_foo_extern), align 8
|
||||
; COFF: @__profc_foo_extern = linkonce_odr dso_local global {{.*}}section ".lprfc$M", comdat, align 8
|
||||
; COFF: @__profd_foo_extern = internal global {{.*}}section ".lprfd$M", comdat($__profc_foo_extern), align 8
|
||||
define available_externally void @foo_extern() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_extern, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
ret void
|
||||
|
@ -20,13 +20,14 @@
|
||||
|
||||
; MACHO: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
; ELF: @__profc_foo = hidden global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8
|
||||
; WINDOWS: @__profc_foo = hidden global [1 x i64] zeroinitializer, section ".lprfc", align 8
|
||||
; WINDOWS: @__profc_foo = internal global [1 x i64] zeroinitializer, section ".lprfc$M", align 8
|
||||
|
||||
; MACHO: @__profd_foo = hidden {{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8
|
||||
; ELF: @__profd_foo = hidden {{.*}}, section "__llvm_prf_data", align 8
|
||||
; WINDOWS: @__profd_foo = hidden {{.*}}, section ".lprfd", align 8
|
||||
; WINDOWS: @__profd_foo = internal global {{.*}}, section ".lprfd$M", align 8
|
||||
|
||||
; ELF: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}__llvm_prf_names"
|
||||
; ELF: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}__llvm_prf_names", align 1
|
||||
; WINDOWS: @__llvm_prf_nm = private constant [{{.*}} x i8] c"{{.*}}", section "{{.*}}lprfn$M", align 1
|
||||
|
||||
define void @foo() {
|
||||
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0)
|
||||
@ -42,14 +43,11 @@ declare void @llvm.instrprof.increment(i8*, i64, i32, i32)
|
||||
; LINUX-NOT: define internal void @__llvm_profile_register_functions
|
||||
; FREEBSD-NOT: define internal void @__llvm_profile_register_functions
|
||||
; PS4-NOT: define internal void @__llvm_profile_register_functions
|
||||
; WINDOWS-NOT: define internal void @__llvm_profile_register_functions
|
||||
|
||||
;; PR38340: When dynamic registration is used, we had a bug where we'd register
|
||||
;; something that's not a __profd_* variable.
|
||||
|
||||
; WINDOWS: define internal void @__llvm_profile_register_functions()
|
||||
; WINDOWS-NOT: __llvm_profile_runtime_user
|
||||
; WINDOWS: ret void
|
||||
|
||||
; SOLARIS: define internal void @__llvm_profile_register_functions
|
||||
; SOLARIS-NOT: __llvm_profile_runtime_user
|
||||
; SOLARIS: ret void
|
||||
@ -58,5 +56,5 @@ declare void @llvm.instrprof.increment(i8*, i64, i32, i32)
|
||||
; LINUX-NOT: define internal void @__llvm_profile_init
|
||||
; FREEBSD-NOT: define internal void @__llvm_profile_init
|
||||
; PS4-NOT: define internal void @__llvm_profile_init
|
||||
; WINDOWS-NOT: define internal void @__llvm_profile_init
|
||||
; SOLARIS: define internal void @__llvm_profile_init
|
||||
; WINDOWS: define internal void @__llvm_profile_init
|
||||
|
Loading…
Reference in New Issue
Block a user