Skip to content

Commit f930a01

Browse files
authored
[SYCL] Enhance device libraries filename check when constructing llvm-link commands (#2944)
We check input files' name when constructing "llvm-link -only-needed" for linking SYCL device libraries. Currently, the criteria is: 1. has the prefix 'libsycl-' 2. has the postfix '.o' Such check is too fragile, this PR aims to enhance the check, input SYCL device libraries' filename pattern is "libsycl-${pure-name}-$random.o" where ${pure-name} is in list {'crt', 'cmath', 'cmath-fp64', 'complex', 'complex-fp64', 'fallback-cassert', 'fallback-cmath', 'fallback-cmath-fp64', 'fallback-complex', 'fallback-complex-fp64'} and ${random} is a random string, so the updated criteria is: 1. has the prefix 'libsycl-' 2. has the postfix '.o' 3. includes at least 2 '-' character in the filename 4. the 'pure name' extracted from the input filename should be in sycl device library 'pure name' list. 5. Input file list includes 2 files at least(when using llvm-link -only-needed, we will put user's device code and several sycl device libraries into input list which means there are 2 input files at least) This enhancement can only mitigate the fragility since the check is still based on filename. If we switch to approach of "-mlink-builtin-bitcode" for SYCL device library link in the future, this problem will be gone automatically. Signed-off-by: gejin <[email protected]>
1 parent 6132ad1 commit f930a01

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

clang/lib/Driver/ToolChains/SYCL.cpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ void SYCL::constructLLVMForeachCommand(Compilation &C, const JobAction &JA,
9595
Foreach, ForeachArgs, None));
9696
}
9797

98+
// The list should match pre-built SYCL device library files located in
99+
// compiler package. Once we add or remove any SYCL device library files,
100+
// the list should be updated accordingly.
101+
static llvm::SmallVector<StringRef, 10> SYCLDeviceLibList{
102+
"crt",
103+
"cmath",
104+
"cmath-fp64",
105+
"complex",
106+
"complex-fp64",
107+
"fallback-cassert",
108+
"fallback-cmath",
109+
"fallback-cmath-fp64",
110+
"fallback-complex",
111+
"fallback-complex-fp64"};
112+
98113
const char *SYCL::Linker::constructLLVMLinkCommand(
99114
Compilation &C, const JobAction &JA, const InputInfo &Output,
100115
const ArgList &Args, StringRef SubArchName, StringRef OutputFilePrefix,
@@ -116,16 +131,32 @@ const char *SYCL::Linker::constructLLVMLinkCommand(
116131
// an actual object/archive. Take that list and pass those to the linker
117132
// instead of the original object.
118133
if (JA.isDeviceOffloading(Action::OFK_SYCL)) {
119-
auto SYCLDeviceLibIter =
120-
std::find_if(InputFiles.begin(), InputFiles.end(), [](const auto &II) {
121-
StringRef InputFilename =
122-
llvm::sys::path::filename(StringRef(II.getFilename()));
123-
if (InputFilename.startswith("libsycl-") &&
124-
InputFilename.endswith(".o"))
125-
return true;
126-
return false;
127-
});
128-
bool LinkSYCLDeviceLibs = (SYCLDeviceLibIter != InputFiles.end());
134+
auto isSYCLDeviceLib = [&C](const InputInfo &II) {
135+
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
136+
StringRef LibPostfix = ".o";
137+
if (HostTC->getTriple().isWindowsMSVCEnvironment() &&
138+
C.getDriver().IsCLMode())
139+
LibPostfix = ".obj";
140+
StringRef InputFilename =
141+
llvm::sys::path::filename(StringRef(II.getFilename()));
142+
if (!InputFilename.startswith("libsycl-") ||
143+
!InputFilename.endswith(LibPostfix) || (InputFilename.count('-') < 2))
144+
return false;
145+
size_t PureLibNameLen = InputFilename.find_last_of('-');
146+
// Skip the prefix "libsycl-"
147+
StringRef PureLibName = InputFilename.substr(8, PureLibNameLen - 8);
148+
for (const auto &L : SYCLDeviceLibList) {
149+
if (PureLibName.compare(L) == 0)
150+
return true;
151+
}
152+
return false;
153+
};
154+
size_t InputFileNum = InputFiles.size();
155+
bool LinkSYCLDeviceLibs = (InputFileNum >= 2);
156+
LinkSYCLDeviceLibs = LinkSYCLDeviceLibs && !isSYCLDeviceLib(InputFiles[0]);
157+
for (size_t Idx = 1; Idx < InputFileNum; ++Idx)
158+
LinkSYCLDeviceLibs =
159+
LinkSYCLDeviceLibs && isSYCLDeviceLib(InputFiles[Idx]);
129160
// Go through the Inputs to the link. When a listfile is encountered, we
130161
// know it is an unbundled generated list.
131162
if (LinkSYCLDeviceLibs)

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,11 @@
122122
// SYCL_LLVM_LINK_NO_DEVICE_LIB: clang{{.*}} "-cc1" {{.*}} "-fsycl-is-device"
123123
// SYCL_LLVM_LINK_NO_DEVICE_LIB-NOT: llvm-link{{.*}} "-only-needed"
124124
// SYCL_LLVM_LINK_NO_DEVICE_LIB: sycl-post-link{{.*}} "-symbols" "-spec-const=rt" "-o" "{{.*}}.table" "{{.*}}.bc"
125+
126+
/// ###########################################################################
127+
/// test llvm-link behavior for special user input whose filename resembles SYCL device library
128+
// RUN: touch libsycl-crt.o
129+
// RUN: %clangxx -fsycl libsycl-crt.o -### 2>&1 \
130+
// RUN: | FileCheck %s -check-prefix=SYCL_LLVM_LINK_USER_ONLY_NEEDED
131+
// SYCL_LLVM_LINK_USER_ONLY_NEEDED: llvm-link{{.*}} "{{.*}}.o" "-o" "{{.*}}.bc" "--suppress-warnings"
132+
// SYCL_LLVM_LINK_USER_ONLY_NEEDED: llvm-link{{.*}} "-only-needed" "{{.*}}" "-o" "{{.*}}.bc" "--suppress-warnings"

0 commit comments

Comments
 (0)