Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Generate imported symbol files in sycl-post-link #14189

Merged
merged 23 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10702,6 +10702,7 @@ getTripleBasedSYCLPostLinkOpts(const ToolChain &TC, const JobAction &JA,
// add options unconditionally
addArgs(PostLinkArgs, TCArgs, {"-symbols"});
addArgs(PostLinkArgs, TCArgs, {"-emit-exported-symbols"});
addArgs(PostLinkArgs, TCArgs, {"-emit-imported-symbols"});
if (SplitEsimd)
addArgs(PostLinkArgs, TCArgs, {"-split-esimd"});
addArgs(PostLinkArgs, TCArgs, {"-lower-esimd"});
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/sycl-device-lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
// RUN: | FileCheck %s -check-prefix=SYCL_LLVM_LINK_NO_DEVICE_LIB
// SYCL_LLVM_LINK_NO_DEVICE_LIB: clang{{.*}} "-cc1" {{.*}} "-fsycl-is-device"
// SYCL_LLVM_LINK_NO_DEVICE_LIB-NOT: llvm-link{{.*}} "-only-needed"
// SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-emit-exported-symbols"{{.*}} "-o" "{{.*}}.table" "{{.*}}.bc"
// SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-emit-exported-symbols" "-emit-imported-symbols"{{.*}} "-o" "{{.*}}.table" "{{.*}}.bc"

/// ###########################################################################
/// test llvm-link behavior for special user input whose filename resembles SYCL device library
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/sycl-offload-new-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl --offload-new-driver \
// RUN: -Xdevice-post-link -post-link-opt -### %s 2>&1 \
// RUN: | FileCheck -check-prefix WRAPPER_OPTIONS_POSTLINK %s
// 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"
// 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"

// -fsycl-device-only behavior
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl --offload-new-driver \
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Support/PropertySetIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class PropertySetRegistry {
static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties";
static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used";
static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols";
static constexpr char SYCL_IMPORTED_SYMBOLS[] = "SYCL/imported symbols";
static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals";
static constexpr char SYCL_DEVICE_REQUIREMENTS[] = "SYCL/device requirements";
static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes";
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Support/PropertySetIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ constexpr char PropertySetRegistry::SYCL_PROGRAM_METADATA[];
constexpr char PropertySetRegistry::SYCL_MISC_PROP[];
constexpr char PropertySetRegistry::SYCL_ASSERT_USED[];
constexpr char PropertySetRegistry::SYCL_EXPORTED_SYMBOLS[];
constexpr char PropertySetRegistry::SYCL_IMPORTED_SYMBOLS[];
constexpr char PropertySetRegistry::SYCL_DEVICE_GLOBALS[];
constexpr char PropertySetRegistry::SYCL_DEVICE_REQUIREMENTS[];
constexpr char PropertySetRegistry::SYCL_HOST_PIPES[];
Expand Down
113 changes: 113 additions & 0 deletions llvm/test/tools/sycl-post-link/emit_imported_symbols.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
; This test checks that the -emit-imported-symbols option generates a list of imported symbols
; Function names were chosen so that no function with a 'inside' in their function name is imported
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Test with -split=kernel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; RUN: sycl-post-link -symbols -emit-imported-symbols -split=kernel -S < %s -o %t_kernel.table

; RUN: FileCheck %s -input-file=%t_kernel_0.sym --check-prefixes CHECK-KERNEL-SYM-0
; RUN: FileCheck %s -input-file=%t_kernel_1.sym --check-prefixes CHECK-KERNEL-SYM-1
; RUN: FileCheck %s -input-file=%t_kernel_2.sym --check-prefixes CHECK-KERNEL-SYM-2

; RUN: FileCheck %s -input-file=%t_kernel_0.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-0
; RUN: FileCheck %s -input-file=%t_kernel_1.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-1
; RUN: FileCheck %s -input-file=%t_kernel_2.prop --check-prefixes CHECK-KERNEL-IMPORTED-SYM-2

; CHECK-KERNEL-SYM-0: middle
; CHECK-KERNEL-IMPORTED-SYM-0: [SYCL/imported symbols]
; CHECK-KERNEL-IMPORTED-SYM-0-NEXT: childD
; CHECK-KERNEL-IMPORTED-SYM-0-EMPTY:

; CHECK-KERNEL-SYM-1: foo
; CHECK-KERNEL-IMPORTED-SYM-1: [SYCL/imported symbols]
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childA
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childC
; CHECK-KERNEL-IMPORTED-SYM-1-NEXT: childD
; CHECK-KERNEL-IMPORTED-SYM-1-EMPTY:


; CHECK-KERNEL-SYM-2: bar
; CHECK-KERNEL-IMPORTED-SYM-2: [SYCL/imported symbols]
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childB
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childC
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: childD
; CHECK-KERNEL-IMPORTED-SYM-2-NEXT: _Z7outsidev
; CHECK-KERNEL-IMPORTED-SYM-2-EMPTY:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Test with -split=source
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; RUN: sycl-post-link -symbols -emit-imported-symbols -split=source -S < %s -o %t_source.table
; RUN: FileCheck %s -input-file=%t_source_0.sym --check-prefixes CHECK-SOURCE-SYM-0
; RUN: FileCheck %s -input-file=%t_source_0.prop --check-prefixes CHECK-SOURCE-IMPORTED-SYM-0

; RUN: sycl-post-link -symbols -emit-imported-symbols -split=source -S < %s -o %t_source.table -O0
; RUN: FileCheck %s -input-file=%t_source_0.sym --check-prefixes CHECK-SOURCE-SYM-0
; RUN: FileCheck %s -input-file=%t_source_0.prop --check-prefixes CHECK-SOURCE-IMPORTED-SYM-0

; CHECK-SOURCE-SYM-0-DAG: foo
; CHECK-SOURCE-SYM-0-DAG: bar
; CHECK-SOURCE-SYM-0-DAG: middle

; CHECK-SOURCE-IMPORTED-SYM-0: [SYCL/imported symbols]
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childA
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childB
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childC
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: childD
; CHECK-SOURCE-IMPORTED-SYM-0-NEXT: _Z7outsidev
; CHECK-SOURCE-IMPORTED-SYM-0-EMPTY:

target triple = "spir64-unknown-unknown"

@llvm.used = appending global [2 x ptr] [ptr @foo, ptr @bar], section "llvm.metadata"

define weak_odr spir_kernel void @foo() #0 {
call void @childA()
call void @childC()
call void @middle()
ret void
}

define weak_odr spir_kernel void @bar() #0 {
;; Functions that are not SYCL External (i.e. they have no sycl-module-id) cannot be imported
call spir_func void @__itt_offload_wi_start_wrapper()

call void @childB()
call void @childC()
call void @middle()
;; LLVM intrinsics cannot be imported
%dummy = call i8 @llvm.bitreverse.i8(i8 0)
;; Functions with a demangled name prefixed with a '__' are not imported
call void @_Z8__insidev()
call void @_Z7outsidev()

;; Functions that are not SYCL External (i.e. they have no sycl-module-id) cannot be imported
call spir_func void @__itt_offload_wi_finish_wrapper()
ret void
}

define void @middle() #0 {
call void @childD()
ret void
}

declare void @childA() #1
declare void @childB() #1
declare void @childC() #1
declare void @childD() #1

declare void @_Z7outsidev() #1
;; Verify unused functions are not imported
declare void @insideUnusedFunction() #1
declare void @_Z8__insidev() #1
declare i8 @llvm.bitreverse.i8(i8)

declare spir_func void @__itt_offload_wi_start_wrapper()
declare spir_func void @__itt_offload_wi_finish_wrapper()

attributes #0 = { "sycl-module-id"="a.cpp" }
attributes #1 = { "sycl-module-id"="external.cpp" }
1 change: 1 addition & 0 deletions llvm/tools/sycl-post-link/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
BitWriter
Core
Demangle
IPO
IRPrinter
IRReader
Expand Down
51 changes: 47 additions & 4 deletions llvm/tools/sycl-post-link/sycl-post-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/GenXIntrinsics/GenXSPIRVWriterAdaptor.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/LLVMContext.h"
Expand Down Expand Up @@ -228,6 +229,10 @@ cl::opt<bool> EmitExportedSymbols{"emit-exported-symbols",
cl::desc("emit exported symbols"),
cl::cat(PostLinkCat)};

cl::opt<bool> EmitImportedSymbols{"emit-imported-symbols",
cl::desc("emit imported symbols"),
cl::cat(PostLinkCat)};

cl::opt<bool> EmitOnlyKernelsAsEntryPoints{
"emit-only-kernels-as-entry-points",
cl::desc("Consider only sycl_kernel functions as entry points for "
Expand All @@ -250,6 +255,7 @@ struct GlobalBinImageProps {
bool EmitKernelParamInfo;
bool EmitProgramMetadata;
bool EmitExportedSymbols;
bool EmitImportedSymbols;
bool EmitDeviceGlobalPropSet;
};

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

bool isImportedFunction(const Function &F) {
if (!F.isDeclaration() || F.isIntrinsic() ||
!llvm::sycl::utils::isSYCLExternalFunction(&F))
return false;

// StripDeadPrototypes is called during module splitting
// cleanup. At this point all function decls should have uses.
assert(!F.use_empty() && "Function F has no uses");

bool ReturnValue = true;
if (char *NameStr = itaniumDemangle(F.getName())) {
StringRef DemangledName(NameStr);
if (DemangledName.starts_with("__"))
ReturnValue = false;
free(NameStr);
}
return ReturnValue;
}

std::string saveModuleProperties(module_split::ModuleDesc &MD,
const GlobalBinImageProps &GlobProps, int I,
StringRef Suff) {
Expand Down Expand Up @@ -474,10 +499,21 @@ std::string saveModuleProperties(module_split::ModuleDesc &MD,
// so they won't make it into the export list. Should the check be
// F->getCallingConv() != CallingConv::SPIR_KERNEL?
if (F->getCallingConv() == CallingConv::SPIR_FUNC) {
PropSet.add(PropSetRegTy::SYCL_EXPORTED_SYMBOLS, F->getName(), true);
PropSet.add(PropSetRegTy::SYCL_EXPORTED_SYMBOLS, F->getName(),
/*PropVal=*/true);
}
}
}

if (GlobProps.EmitImportedSymbols) {
// record imported functions in the property set
for (const auto &F : M) {
if (isImportedFunction(F))
PropSet.add(PropSetRegTy::SYCL_IMPORTED_SYMBOLS, F.getName(),
/*PropVal=*/true);
}
}

// Metadata names may be composite so we keep them alive until the
// properties have been written.
SmallVector<std::string, 4> MetadataNames;
Expand Down Expand Up @@ -730,7 +766,8 @@ IrPropSymFilenameTriple saveModule(module_split::ModuleDesc &MD, int I,
Res.Ir = saveModuleIR(MD.getModule(), I, Suffix);
}
GlobalBinImageProps Props = {EmitKernelParamInfo, EmitProgramMetadata,
EmitExportedSymbols, DeviceGlobals};
EmitExportedSymbols, EmitImportedSymbols,
DeviceGlobals};
Res.Prop = saveModuleProperties(MD, Props, I, Suffix);

if (DoSymGen) {
Expand Down Expand Up @@ -1249,13 +1286,14 @@ int main(int argc, char **argv) {
bool DoParamInfo = EmitKernelParamInfo.getNumOccurrences() > 0;
bool DoProgMetadata = EmitProgramMetadata.getNumOccurrences() > 0;
bool DoExportedSyms = EmitExportedSymbols.getNumOccurrences() > 0;
bool DoImportedSyms = EmitImportedSymbols.getNumOccurrences() > 0;
bool DoDeviceGlobals = DeviceGlobals.getNumOccurrences() > 0;
bool DoGenerateDeviceImageWithDefaulValues =
GenerateDeviceImageWithDefaultSpecConsts.getNumOccurrences() > 0;

if (!DoSplit && !DoSpecConst && !DoSymGen && !DoParamInfo &&
!DoProgMetadata && !DoSplitEsimd && !DoExportedSyms && !DoDeviceGlobals &&
!DoLowerEsimd) {
!DoProgMetadata && !DoSplitEsimd && !DoExportedSyms && !DoImportedSyms &&
!DoDeviceGlobals && !DoLowerEsimd) {
errs() << "no actions specified; try --help for usage info\n";
return 1;
}
Expand Down Expand Up @@ -1289,6 +1327,11 @@ int main(int argc, char **argv) {
<< " -" << IROutputOnly.ArgStr << "\n";
return 1;
}
if (IROutputOnly && DoImportedSyms) {
errs() << "error: -" << EmitImportedSymbols.ArgStr << " can't be used with"
<< " -" << IROutputOnly.ArgStr << "\n";
return 1;
}
if (IROutputOnly && DoGenerateDeviceImageWithDefaulValues) {
errs() << "error: -" << GenerateDeviceImageWithDefaultSpecConsts.ArgStr
<< " can't be used with -" << IROutputOnly.ArgStr << "\n";
Expand Down
Loading