Skip to content

Commit 19fe31a

Browse files
author
LU-JOHN
authored
[SYCL] Generate imported symbol files in sycl-post-link (#13965)
Add sycl-post-link option "-emit-imported-symbols" to generate a property set listing imported symbols for each device image. This work is part of adding dynamic linking support for SYCL. Design document: https://github.com/intel/llvm/blob/sycl/sycl/doc/design/SharedLibraries.md --------- Signed-off-by: Lu, John <[email protected]>
1 parent 50bf201 commit 19fe31a

File tree

7 files changed

+165
-6
lines changed

7 files changed

+165
-6
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10702,6 +10702,7 @@ getTripleBasedSYCLPostLinkOpts(const ToolChain &TC, const JobAction &JA,
1070210702
// add options unconditionally
1070310703
addArgs(PostLinkArgs, TCArgs, {"-symbols"});
1070410704
addArgs(PostLinkArgs, TCArgs, {"-emit-exported-symbols"});
10705+
addArgs(PostLinkArgs, TCArgs, {"-emit-imported-symbols"});
1070510706
if (SplitEsimd)
1070610707
addArgs(PostLinkArgs, TCArgs, {"-split-esimd"});
1070710708
addArgs(PostLinkArgs, TCArgs, {"-lower-esimd"});

clang/test/Driver/sycl-device-lib.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@
185185
// RUN: | FileCheck %s -check-prefix=SYCL_LLVM_LINK_NO_DEVICE_LIB
186186
// SYCL_LLVM_LINK_NO_DEVICE_LIB: clang{{.*}} "-cc1" {{.*}} "-fsycl-is-device"
187187
// SYCL_LLVM_LINK_NO_DEVICE_LIB-NOT: llvm-link{{.*}} "-only-needed"
188-
// SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-emit-exported-symbols"{{.*}} "-o" "{{.*}}.table" "{{.*}}.bc"
188+
// SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-emit-exported-symbols" "-emit-imported-symbols"{{.*}} "-o" "{{.*}}.table" "{{.*}}.bc"
189189

190190
/// ###########################################################################
191191
/// test llvm-link behavior for special user input whose filename resembles SYCL device library

clang/test/Driver/sycl-offload-new-driver.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl --offload-new-driver \
6161
// RUN: -Xdevice-post-link -post-link-opt -### %s 2>&1 \
6262
// RUN: | FileCheck -check-prefix WRAPPER_OPTIONS_POSTLINK %s
63-
// WRAPPER_OPTIONS_POSTLINK: clang-linker-wrapper{{.*}} "--sycl-post-link-options=-post-link-opt -O2 -device-globals -spec-const=native -split=auto -emit-only-kernels-as-entry-points -symbols -emit-exported-symbols -lower-esimd"
63+
// WRAPPER_OPTIONS_POSTLINK: clang-linker-wrapper{{.*}} "--sycl-post-link-options=-post-link-opt -O2 -device-globals -spec-const=native -split=auto -emit-only-kernels-as-entry-points -symbols -emit-exported-symbols -emit-imported-symbols -lower-esimd"
6464

6565
// -fsycl-device-only behavior
6666
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl --offload-new-driver \

llvm/include/llvm/Support/PropertySetIO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class PropertySetRegistry {
205205
static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties";
206206
static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used";
207207
static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols";
208+
static constexpr char SYCL_IMPORTED_SYMBOLS[] = "SYCL/imported symbols";
208209
static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals";
209210
static constexpr char SYCL_DEVICE_REQUIREMENTS[] = "SYCL/device requirements";
210211
static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes";

llvm/lib/Support/PropertySetIO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ constexpr char PropertySetRegistry::SYCL_PROGRAM_METADATA[];
202202
constexpr char PropertySetRegistry::SYCL_MISC_PROP[];
203203
constexpr char PropertySetRegistry::SYCL_ASSERT_USED[];
204204
constexpr char PropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
205+
constexpr char PropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
205206
constexpr char PropertySetRegistry::SYCL_DEVICE_GLOBALS[];
206207
constexpr char PropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
207208
constexpr char PropertySetRegistry::SYCL_HOST_PIPES[];
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
; This test checks that the -emit-imported-symbols option generates a list of imported symbols
2+
; Function names were chosen so that no function with a 'inside' in their function name is imported
3+
;
4+
5+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6+
; Test with -split=kernel
7+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8+
9+
; RUN: sycl-post-link -symbols -emit-imported-symbols -split=kernel -S < %s -o %t_kernel.table
10+
11+
; RUN: FileCheck %s -input-file=%t_kernel_0.sym --check-prefixes CHECK-KERNEL-SYM-0
12+
; RUN: FileCheck %s -input-file=%t_kernel_1.sym --check-prefixes CHECK-KERNEL-SYM-1
13+
; RUN: FileCheck %s -input-file=%t_kernel_2.sym --check-prefixes CHECK-KERNEL-SYM-2
14+
15+
; RUN: FileCheck %s -input-file=%t_kernel_0.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-0
16+
; RUN: FileCheck %s -input-file=%t_kernel_1.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-1
17+
; RUN: FileCheck %s -input-file=%t_kernel_2.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-2
18+
19+
; CHECK-KERNEL-SYM-0: middle
20+
; CHECK-KERNEL-IMPORTED-SYM-0: [SYCL/imported symbols]
21+
; CHECK-KERNEL-IMPORTED-SYM-0-NEXT: childD
22+
; CHECK-KERNEL-IMPORTED-SYM-0-EMPTY:
23+
24+
; CHECK-KERNEL-SYM-1: foo
25+
; CHECK-KERNEL-IMPORTED-SYM-1: [SYCL/imported symbols]
26+
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childA
27+
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childC
28+
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childD
29+
; CHECK-KERNEL-IMPORTED-SYM-1-EMPTY:
30+
31+
32+
; CHECK-KERNEL-SYM-2: bar
33+
; CHECK-KERNEL-IMPORTED-SYM-2: [SYCL/imported symbols]
34+
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childB
35+
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childC
36+
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childD
37+
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: _Z7outsidev
38+
; CHECK-KERNEL-IMPORTED-SYM-2-EMPTY:
39+
40+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41+
; Test with -split=source
42+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43+
44+
; RUN: sycl-post-link -symbols -emit-imported-symbols -split=source -S < %s -o %t_source.table
45+
; RUN: FileCheck %s -input-file=%t_source_0.sym --check-prefixes CHECK-SOURCE-SYM-0
46+
; RUN: FileCheck %s -input-file=%t_source_0.prop --check-prefixes CHECK-SOURCE-IMPORTED-SYM-0
47+
48+
; RUN: sycl-post-link -symbols -emit-imported-symbols -split=source -S < %s -o %t_source.table -O0
49+
; RUN: FileCheck %s -input-file=%t_source_0.sym --check-prefixes CHECK-SOURCE-SYM-0
50+
; RUN: FileCheck %s -input-file=%t_source_0.prop --check-prefixes CHECK-SOURCE-IMPORTED-SYM-0
51+
52+
; CHECK-SOURCE-SYM-0-DAG: foo
53+
; CHECK-SOURCE-SYM-0-DAG: bar
54+
; CHECK-SOURCE-SYM-0-DAG: middle
55+
56+
; CHECK-SOURCE-IMPORTED-SYM-0: [SYCL/imported symbols]
57+
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childA
58+
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childB
59+
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childC
60+
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childD
61+
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: _Z7outsidev
62+
; CHECK-SOURCE-IMPORTED-SYM-0-EMPTY:
63+
64+
target triple = "spir64-unknown-unknown"
65+
66+
@llvm.used = appending global [2 x ptr] [ptr @foo, ptr @bar], section "llvm.metadata"
67+
68+
define weak_odr spir_kernel void @foo() #0 {
69+
call void @childA()
70+
call void @childC()
71+
call void @middle()
72+
ret void
73+
}
74+
75+
define weak_odr spir_kernel void @bar() #0 {
76+
;; Functions that are not SYCL External (i.e. they have no sycl-module-id) cannot be imported
77+
call spir_func void @__itt_offload_wi_start_wrapper()
78+
79+
call void @childB()
80+
call void @childC()
81+
call void @middle()
82+
;; LLVM intrinsics cannot be imported
83+
%dummy = call i8 @llvm.bitreverse.i8(i8 0)
84+
;; Functions with a demangled name prefixed with a '__' are not imported
85+
call void @_Z8__insidev()
86+
call void @_Z7outsidev()
87+
88+
;; Functions that are not SYCL External (i.e. they have no sycl-module-id) cannot be imported
89+
call spir_func void @__itt_offload_wi_finish_wrapper()
90+
ret void
91+
}
92+
93+
define void @middle() #0 {
94+
call void @childD()
95+
ret void
96+
}
97+
98+
declare void @childA() #1
99+
declare void @childB() #1
100+
declare void @childC() #1
101+
declare void @childD() #1
102+
103+
declare void @_Z7outsidev() #1
104+
;; Verify unused functions are not imported
105+
declare void @insideUnusedFunction() #1
106+
declare void @_Z8__insidev() #1
107+
declare i8 @llvm.bitreverse.i8(i8)
108+
109+
declare spir_func void @__itt_offload_wi_start_wrapper()
110+
declare spir_func void @__itt_offload_wi_finish_wrapper()
111+
112+
attributes #0 = { "sycl-module-id"="a.cpp" }
113+
attributes #1 = { "sycl-module-id"="external.cpp" }

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/Analysis/TargetLibraryInfo.h"
2626
#include "llvm/Analysis/TargetTransformInfo.h"
2727
#include "llvm/Bitcode/BitcodeWriterPass.h"
28+
#include "llvm/Demangle/Demangle.h"
2829
#include "llvm/GenXIntrinsics/GenXSPIRVWriterAdaptor.h"
2930
#include "llvm/IR/Dominators.h"
3031
#include "llvm/IR/LLVMContext.h"
@@ -228,6 +229,10 @@ cl::opt<bool> EmitExportedSymbols{"emit-exported-symbols",
228229
cl::desc("emit exported symbols"),
229230
cl::cat(PostLinkCat)};
230231

232+
cl::opt<bool> EmitImportedSymbols{"emit-imported-symbols",
233+
cl::desc("emit imported symbols"),
234+
cl::cat(PostLinkCat)};
235+
231236
cl::opt<bool> EmitOnlyKernelsAsEntryPoints{
232237
"emit-only-kernels-as-entry-points",
233238
cl::desc("Consider only sycl_kernel functions as entry points for "
@@ -250,6 +255,7 @@ struct GlobalBinImageProps {
250255
bool EmitKernelParamInfo;
251256
bool EmitProgramMetadata;
252257
bool EmitExportedSymbols;
258+
bool EmitImportedSymbols;
253259
bool EmitDeviceGlobalPropSet;
254260
};
255261

@@ -411,6 +417,25 @@ std::string saveModuleIR(Module &M, int I, StringRef Suff) {
411417
return OutFilename;
412418
}
413419

420+
bool isImportedFunction(const Function &F) {
421+
if (!F.isDeclaration() || F.isIntrinsic() ||
422+
!llvm::sycl::utils::isSYCLExternalFunction(&F))
423+
return false;
424+
425+
// StripDeadPrototypes is called during module splitting
426+
// cleanup. At this point all function decls should have uses.
427+
assert(!F.use_empty() && "Function F has no uses");
428+
429+
bool ReturnValue = true;
430+
if (char *NameStr = itaniumDemangle(F.getName())) {
431+
StringRef DemangledName(NameStr);
432+
if (DemangledName.starts_with("__"))
433+
ReturnValue = false;
434+
free(NameStr);
435+
}
436+
return ReturnValue;
437+
}
438+
414439
std::string saveModuleProperties(module_split::ModuleDesc &MD,
415440
const GlobalBinImageProps &GlobProps, int I,
416441
StringRef Suff) {
@@ -474,10 +499,21 @@ std::string saveModuleProperties(module_split::ModuleDesc &MD,
474499
// so they won't make it into the export list. Should the check be
475500
// F->getCallingConv() != CallingConv::SPIR_KERNEL?
476501
if (F->getCallingConv() == CallingConv::SPIR_FUNC) {
477-
PropSet.add(PropSetRegTy::SYCL_EXPORTED_SYMBOLS, F->getName(), true);
502+
PropSet.add(PropSetRegTy::SYCL_EXPORTED_SYMBOLS, F->getName(),
503+
/*PropVal=*/true);
478504
}
479505
}
480506
}
507+
508+
if (GlobProps.EmitImportedSymbols) {
509+
// record imported functions in the property set
510+
for (const auto &F : M) {
511+
if (isImportedFunction(F))
512+
PropSet.add(PropSetRegTy::SYCL_IMPORTED_SYMBOLS, F.getName(),
513+
/*PropVal=*/true);
514+
}
515+
}
516+
481517
// Metadata names may be composite so we keep them alive until the
482518
// properties have been written.
483519
SmallVector<std::string, 4> MetadataNames;
@@ -730,7 +766,8 @@ IrPropSymFilenameTriple saveModule(module_split::ModuleDesc &MD, int I,
730766
Res.Ir = saveModuleIR(MD.getModule(), I, Suffix);
731767
}
732768
GlobalBinImageProps Props = {EmitKernelParamInfo, EmitProgramMetadata,
733-
EmitExportedSymbols, DeviceGlobals};
769+
EmitExportedSymbols, EmitImportedSymbols,
770+
DeviceGlobals};
734771
Res.Prop = saveModuleProperties(MD, Props, I, Suffix);
735772

736773
if (DoSymGen) {
@@ -1249,13 +1286,14 @@ int main(int argc, char **argv) {
12491286
bool DoParamInfo = EmitKernelParamInfo.getNumOccurrences() > 0;
12501287
bool DoProgMetadata = EmitProgramMetadata.getNumOccurrences() > 0;
12511288
bool DoExportedSyms = EmitExportedSymbols.getNumOccurrences() > 0;
1289+
bool DoImportedSyms = EmitImportedSymbols.getNumOccurrences() > 0;
12521290
bool DoDeviceGlobals = DeviceGlobals.getNumOccurrences() > 0;
12531291
bool DoGenerateDeviceImageWithDefaulValues =
12541292
GenerateDeviceImageWithDefaultSpecConsts.getNumOccurrences() > 0;
12551293

12561294
if (!DoSplit && !DoSpecConst && !DoSymGen && !DoParamInfo &&
1257-
!DoProgMetadata && !DoSplitEsimd && !DoExportedSyms && !DoDeviceGlobals &&
1258-
!DoLowerEsimd) {
1295+
!DoProgMetadata && !DoSplitEsimd && !DoExportedSyms && !DoImportedSyms &&
1296+
!DoDeviceGlobals && !DoLowerEsimd) {
12591297
errs() << "no actions specified; try --help for usage info\n";
12601298
return 1;
12611299
}
@@ -1289,6 +1327,11 @@ int main(int argc, char **argv) {
12891327
<< " -" << IROutputOnly.ArgStr << "\n";
12901328
return 1;
12911329
}
1330+
if (IROutputOnly && DoImportedSyms) {
1331+
errs() << "error: -" << EmitImportedSymbols.ArgStr << " can't be used with"
1332+
<< " -" << IROutputOnly.ArgStr << "\n";
1333+
return 1;
1334+
}
12921335
if (IROutputOnly && DoGenerateDeviceImageWithDefaulValues) {
12931336
errs() << "error: -" << GenerateDeviceImageWithDefaultSpecConsts.ArgStr
12941337
<< " can't be used with -" << IROutputOnly.ArgStr << "\n";

0 commit comments

Comments
 (0)