Skip to content

Commit abbba55

Browse files
authored
[Driver][SYCL][New offload] Support external host compiler (#19505)
Use of -fsycl-host-compiler allows for users to use an external compiler to perform the host compilation when performing offload builds. The new model has the expectation for the device 'object' to be embedded within the host object via the `clang-offload-packager`. These fat objects are consumed by the `clang-linker-wrapper`. External host compilers do not have the ability to embed the device binary when creating the host object. Fortunately, the `clang-linker-wrapper` allows for consumption of bundled fat objects. Update the driver when using -fsycl-host-compiler and the new offloading model to generate bundled files instead of embedded objects. This support is for object generation only at this time. Preprocessing and assembly file intermediates are not yet supported.
1 parent c452de4 commit abbba55

File tree

2 files changed

+132
-2
lines changed

2 files changed

+132
-2
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7748,9 +7748,17 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
77487748
return HostAction;
77497749
}
77507750

7751+
// For SYCL offloading with -fsycl-host-compiler enabled, we do not have the
7752+
// ability to embed the packaged file.
7753+
bool SYCLBundleFile = C.isOffloadingHostKind(Action::OFK_SYCL) &&
7754+
Args.hasArg(options::OPT_fsycl_host_compiler_EQ) &&
7755+
isa<AssembleJobAction>(HostAction);
7756+
77517757
// Don't build offloading actions if we do not have a compile action. If
7752-
// preprocessing only ignore embedding.
7753-
if (!(isa<CompileJobAction>(HostAction) ||
7758+
// preprocessing only ignore embedding. When needing to do bundling for
7759+
// SYCL, allow the building of offloading actions to add the device side to
7760+
// the bundle.
7761+
if (!(isa<CompileJobAction>(HostAction) || SYCLBundleFile ||
77547762
getFinalPhase(Args) == phases::Preprocess))
77557763
return HostAction;
77567764

@@ -7888,6 +7896,17 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
78887896
tools::SYCL::populateSYCLDeviceTraitsMacrosArgs(C, Args, TCAndArchs);
78897897
}
78907898

7899+
// Now that we have all of the offload actions populated, we special case
7900+
// SYCL -fsycl-host-compiler to perform a bundling action instead of a
7901+
// packaging action.
7902+
if (SYCLBundleFile) {
7903+
ActionList BundlingActions(OffloadActions);
7904+
BundlingActions.push_back(HostAction);
7905+
Action *BundlingAction =
7906+
C.MakeAction<OffloadBundlingJobAction>(BundlingActions);
7907+
return BundlingAction;
7908+
}
7909+
78917910
// HIP code in device-only non-RDC mode will bundle the output if it invoked
78927911
// the linker.
78937912
bool ShouldBundleHIP =
@@ -7933,6 +7952,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
79337952
DDep.add(*LinkAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
79347953
nullptr, C.getActiveOffloadKinds());
79357954
return C.MakeAction<OffloadAction>(DDep, types::TY_Nothing);
7955+
} else if (C.isOffloadingHostKind(Action::OFK_SYCL) &&
7956+
Args.hasArg(options::OPT_fsycl_host_compiler_EQ)) {
7957+
// -fsycl-host-compiler will create a bundled object instead of an
7958+
// embedded packaged object. Effectively avoid doing the packaging.
7959+
return HostAction;
79367960
} else {
79377961
// Package all the offloading actions into a single output that can be
79387962
// embedded in the host and linked.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Tests the abilities involved with using an external host compiler
2+
// with the new offload model.
3+
4+
/// Enabling with -fsycl-host-compiler
5+
// RUN: %clangxx -fsycl --offload-new-driver -fsycl-host-compiler=/some/dir/g++ %s -### 2>&1 \
6+
// RUN: | FileCheck -check-prefix=HOST_COMPILER %s
7+
// HOST_COMPILER: clang{{.*}} "-fsycl-is-device"
8+
// HOST_COMPILER-SAME: "-fsycl-int-header=[[INTHEADER:.+\.h]]" "-fsycl-int-footer=[[INTFOOTER:.+\.h]]"
9+
// HOST_COMPILER-SAME: "-o" "[[DEVICEBC:.+\.bc]]"
10+
// HOST_COMPILER: append-file{{.*}} "--append=[[INTFOOTER]]"
11+
// HOST_COMPILER-SAME: "--output=[[APPENDFILESRC:.+\.cpp]]" "--use-include"
12+
// HOST_COMPILER: g++{{.*}} "[[APPENDFILESRC]]"
13+
// HOST_COMPILER-SAME: "-c" "-include" "[[INTHEADER]]"
14+
// HOST_COMPILER-SAME: "-iquote"
15+
// HOST_COMPILER-SAME: "-isystem" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}sycl"
16+
// HOST_COMPILER-SAME: "-isystem" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}sycl{{[/\\]+}}stl_wrappers"
17+
// HOST_COMPILER-SAME: "-isystem" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include"
18+
// HOST_COMPILER-SAME: "-o" "[[HOSTOBJ:.+\.o]]"
19+
// HOST_COMPILER: clang-offload-bundler{{.*}} "-output=[[BUNDLEOBJ:.+\.o]]" "-input=[[DEVICEBC]]" "-input=[[HOSTOBJ]]"
20+
// HOST_COMPILER: clang-linker-wrapper{{.*}} "[[BUNDLEOBJ]]"
21+
22+
// RUN: %clang_cl -fsycl --offload-new-driver -fsycl-host-compiler=/some/dir/cl %s -### 2>&1 \
23+
// RUN: | FileCheck -check-prefix=HOST_COMPILER_CL %s
24+
// HOST_COMPILER_CL: clang{{.*}} "-fsycl-is-device"
25+
// HOST_COMPILER_CL-SAME: "-fsycl-int-header=[[INTHEADER:.+\.h]]" "-fsycl-int-footer=[[INTFOOTER:.+\.h]]"
26+
// HOST_COMPILER_CL-SAME: "-o" "[[DEVICEBC:.+\.bc]]"
27+
// HOST_COMPILER_CL: append-file{{.*}} "--append=[[INTFOOTER]]"
28+
// HOST_COMPILER_CL-SAME: "--output=[[APPENDFILESRC:.+\.cpp]]" "--use-include"
29+
// HOST_COMPILER_CL: cl{{.*}} "[[APPENDFILESRC]]"
30+
// HOST_COMPILER_CL-SAME: "-c" "-Fo[[HOSTOBJ:.+\.obj]]" "-FI" "[[INTHEADER]]"
31+
// HOST_COMPILER_CL-SAME: "/external:W0"
32+
// HOST_COMPILER_CL-SAME: "/external:I" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}sycl"
33+
// HOST_COMPILER_CL-SAME: "/external:I" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}sycl{{[/\\]+}}stl_wrappers"
34+
// HOST_COMPILER_CL-SAME: "/external:I" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include"
35+
// HOST_COMPILER_CL: clang-offload-bundler{{.*}} "-output=[[BUNDLEOBJ:.+\.obj]]" "-input=[[DEVICEBC]]" "-input=[[HOSTOBJ]]"
36+
// HOST_COMPILER_CL: clang-linker-wrapper{{.*}} "[[BUNDLEOBJ]]"
37+
38+
/// Check for additional host options.
39+
// RUN: %clangxx -fsycl --offload-new-driver -fsycl-host-compiler=g++ -fsycl-host-compiler-options="-DFOO -DBAR" %s -### 2>&1 \
40+
// RUN: | FileCheck -check-prefix=HOST_OPTIONS %s
41+
// HOST_OPTIONS: g++{{.*}} "-o" "[[HOSTOBJ:.+\.o]]"{{.*}} "-DFOO" "-DBAR"
42+
43+
// RUN: %clang_cl -fsycl --offload-new-driver -fsycl-host-compiler=cl -fsycl-host-compiler-options="/DFOO /DBAR /O2" %s -### 2>&1 \
44+
// RUN: | FileCheck -check-prefix=HOST_OPTIONS_CL %s
45+
// HOST_OPTIONS_CL: cl{{.*}} "-Fo[[HOSTOBJ:.+\.obj]]"{{.*}} "/DFOO" "/DBAR" "/O2"
46+
47+
/// Object output check.
48+
// RUN: %clangxx -fsycl --offload-new-driver -fsycl-host-compiler=g++ -c %s -### 2>&1 \
49+
// RUN: | FileCheck -check-prefix=HOST_OBJECT %s
50+
// HOST_OBJECT: g++{{.*}} "-c"{{.*}} "-o" "[[OBJOUT:.+\.o]]"
51+
// HOST_OBJECT: clang-offload-bundler{{.*}} "-input={{.*}}.bc" "-input=[[OBJOUT]]"
52+
53+
// RUN: %clang_cl -fsycl --offload-new-driver -fsycl-host-compiler=cl -c %s -### 2>&1 \
54+
// RUN: | FileCheck -check-prefix=HOST_OBJECT_CL %s
55+
// HOST_OBJECT_CL: cl{{.*}} "-c"{{.*}} "-Fo[[OBJOUT:.+\.obj]]"
56+
// HOST_OBJECT_CL: clang-offload-bundler{{.*}} "-input={{.*}}.bc" "-input=[[OBJOUT]]"
57+
58+
/// Missing argument error -fsycl-host-compiler=.
59+
// RUN: not %clangxx -fsycl --offload-new-driver -fsycl-host-compiler= -c -### %s 2>&1 \
60+
// RUN: | FileCheck -check-prefix=HOST_COMPILER_NOARG %s
61+
// HOST_COMPILER_NOARG: missing argument to '-fsycl-host-compiler='
62+
63+
/// Error for -fsycl-host-compiler and -fsycl-unnamed-lambda combination.
64+
// RUN: not %clangxx -fsycl --offload-new-driver -fsycl-host-compiler=g++ -fsycl-unnamed-lambda -c -### %s 2>&1 \
65+
// RUN: | FileCheck -check-prefix=HOST_COMPILER_AND_UNNAMED_LAMBDA %s
66+
// HOST_COMPILER_AND_UNNAMED_LAMBDA: error: cannot specify '-fsycl-unnamed-lambda' along with '-fsycl-host-compiler'
67+
68+
// -fsycl-host-compiler implies -fno-sycl-unnamed-lambda.
69+
// RUN: %clangxx -### -fsycl --offload-new-driver -fsycl-host-compiler=g++ -c -### %s 2>&1 \
70+
// RUN: | FileCheck -check-prefix=IMPLY-NO-SYCL-UNNAMED-LAMBDA %s
71+
// IMPLY-NO-SYCL-UNNAMED-LAMBDA: clang{{.*}} "-fno-sycl-unnamed-lambda"
72+
73+
// Zc:__cplusplus, Zc:__cplusplus- check.
74+
// RUN: %clang_cl -### -fsycl-host-compiler=cl -fsycl --offload-new-driver %s 2>&1 | FileCheck -check-prefix=CHECK-ZC-CPLUSPLUS %s
75+
// RUN: %clang_cl -### -fsycl-host-compiler=cl -fsycl --offload-new-driver -fsycl-host-compiler-options=/Zc:__cplusplus- %s 2>&1 | FileCheck -check-prefix=CHECK-ZC-CPLUSPLUS-MINUS %s
76+
// RUN: %clang_cl -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-ZC-CPLUSPLUS %s
77+
// RUN: %clang_cl -### -fsycl-host-compiler=g++ -fsycl --offload-new-driver %s 2>&1 | FileCheck -check-prefix=CHECK-NO-ZC-CPLUSPLUS %s
78+
// CHECK-ZC-CPLUSPLUS: "/Zc:__cplusplus"
79+
// CHECK-ZC-CPLUSPLUS-MINUS: "/Zc:__cplusplus-"
80+
// CHECK-NO-ZC-CPLUSPLUS-NOT: "/Zc:__cplusplus"
81+
82+
/// -fsycl-host-compiler -save-temps behavior
83+
// RUN: %clangxx -### -fsycl-host-compiler=g++ -fsycl --offload-new-driver \
84+
// RUN: -save-temps -c %s 2>&1 \
85+
// RUN: | FileCheck -check-prefix=CHECK_SAVE_TEMPS %s
86+
// CHECK_SAVE_TEMPS-NOT: error: unsupported output type when using external host compiler
87+
// CHECK_SAVE_TEMPS: clang{{.*}} "-fsycl-is-device"
88+
// CHECK_SAVE_TEMPS-SAME: "-E" {{.*}} "-o" "[[PREPROC_OUT:.+sycl-spir64-unknown-unknown.ii]]"
89+
// CHECK_SAVE_TEMPS-NEXT: clang{{.*}} "-fsycl-is-device"
90+
// CHECK_SAVE_TEMPS-SAME: "-emit-llvm-bc"{{.*}} "-o" "[[DEVICE_BC1:.+\.bc]]"{{.*}} "[[PREPROC_OUT]]"
91+
// CHECK_SAVE_TEMPS-NEXT: clang{{.*}} "-fsycl-is-device"
92+
// CHECK_SAVE_TEMPS-SAME: "-emit-llvm-bc"{{.*}} "-o" "[[DEVICE_BC2:.+\.bc]]"{{.*}} "[[DEVICE_BC1]]"
93+
// CHECK_SAVE_TEMPS-NEXT: append-file{{.*}} "--output=[[APPEND_CPP:.+\.cpp]]
94+
// CHECK_SAVE_TEMPS-NEXT: g++{{.*}} "[[APPEND_CPP]]" "-c"
95+
// CHECK_SAVE_TEMPS-SAME: "-o" "[[HOST_OBJ:.+\.o]]"
96+
// CHECK_SAVE_TEMPS-NEXT: clang-offload-bundler{{.*}} "-input=[[DEVICE_BC2]]" "-input=[[HOST_OBJ]]"
97+
98+
/// Test to verify binary from PATH is used
99+
// RUN: rm -rf %t && mkdir -p %t/test_path
100+
// RUN: touch %t/test_path/clang++ && chmod +x %t/test_path/clang++
101+
// RUN: env "PATH=%t/test_path%{pathsep}%PATH%" \
102+
// RUN: %clangxx -### -fsycl -fsycl-host-compiler=clang++ \
103+
// RUN: -fsycl-host-compiler-options=-DDUMMY_OPT --offload-new-driver \
104+
// RUN: %s 2>&1 \
105+
// RUN: | FileCheck -check-prefix=PATH_CHECK %s
106+
// PATH_CHECK: {{(/|\\\\)}}test_path{{(/|\\\\)}}clang++{{.*}} "-DDUMMY_OPT"

0 commit comments

Comments
 (0)