5
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
-
9
8
#include " clang/Driver/Driver.h"
10
9
#include " InputInfo.h"
11
10
#include " ToolChains/AIX.h"
@@ -1788,20 +1787,21 @@ llvm::Triple Driver::MakeSYCLDeviceTriple(StringRef TargetArch) const {
1788
1787
// Print the help from any of the given tools which are used for AOT
1789
1788
// compilation for SYCL
1790
1789
void Driver::PrintSYCLToolHelp (const Compilation &C) const {
1791
- SmallVector<std::tuple<llvm::Triple, StringRef, StringRef>, 4 > HelpArgs;
1790
+ SmallVector<std::tuple<llvm::Triple, StringRef, StringRef, StringRef>, 4 >
1791
+ HelpArgs;
1792
1792
// Populate the vector with the tools and help options
1793
1793
if (Arg *A = C.getArgs ().getLastArg (options::OPT_fsycl_help_EQ)) {
1794
1794
StringRef AV (A->getValue ());
1795
1795
llvm::Triple T;
1796
1796
if (AV == " gen" || AV == " all" )
1797
1797
HelpArgs.push_back (std::make_tuple (MakeSYCLDeviceTriple (" spir64_gen" ),
1798
- " ocloc" , " --help" ));
1798
+ " ocloc" , " --help" , " " ));
1799
1799
if (AV == " fpga" || AV == " all" )
1800
- HelpArgs.push_back (
1801
- std::make_tuple ( MakeSYCLDeviceTriple ( " spir64_fpga " ) , " aoc " , " -help " ));
1800
+ HelpArgs.push_back (std::make_tuple ( MakeSYCLDeviceTriple ( " spir64_fpga " ),
1801
+ " aoc " , " -help " , " -sycl " ));
1802
1802
if (AV == " x86_64" || AV == " all" )
1803
1803
HelpArgs.push_back (std::make_tuple (MakeSYCLDeviceTriple (" spir64_x86_64" ),
1804
- " opencl-aot" , " --help" ));
1804
+ " opencl-aot" , " --help" , " " ));
1805
1805
if (HelpArgs.empty ()) {
1806
1806
C.getDriver ().Diag (diag::err_drv_unsupported_option_argument)
1807
1807
<< A->getOption ().getName () << AV;
@@ -1814,7 +1814,8 @@ void Driver::PrintSYCLToolHelp(const Compilation &C) const {
1814
1814
llvm::outs () << " Emitting help information for " << std::get<1 >(HA) << ' \n '
1815
1815
<< " Use triple of '" << std::get<0 >(HA).normalize () <<
1816
1816
" ' to enable ahead of time compilation\n " ;
1817
- std::vector<StringRef> ToolArgs = { std::get<1 >(HA), std::get<2 >(HA) };
1817
+ std::vector<StringRef> ToolArgs = {std::get<1 >(HA), std::get<2 >(HA),
1818
+ std::get<3 >(HA)};
1818
1819
SmallString<128 > ExecPath (
1819
1820
C.getDefaultToolChain ().GetProgramPath (std::get<1 >(HA).data ()));
1820
1821
auto ToolBinary = llvm::sys::findProgramByName (ExecPath);
@@ -1824,7 +1825,10 @@ void Driver::PrintSYCLToolHelp(const Compilation &C) const {
1824
1825
}
1825
1826
// do not run the tools with -###.
1826
1827
if (C.getArgs ().hasArg (options::OPT__HASH_HASH_HASH)) {
1827
- llvm::errs () << " \" " << ExecPath << " \" \" " << ToolArgs[1 ] << " \"\n " ;
1828
+ llvm::errs () << " \" " << ExecPath << " \" \" " << ToolArgs[1 ] << " \" " ;
1829
+ if (!ToolArgs[2 ].empty ())
1830
+ llvm::errs () << " \" " << ToolArgs[2 ] << " \" " ;
1831
+ llvm::errs () << " \n " ;
1828
1832
continue ;
1829
1833
}
1830
1834
// Run the Tool.
@@ -2715,6 +2719,16 @@ static SmallVector<const char *, 16> getLinkerArgs(Compilation &C,
2715
2719
return LibArgs;
2716
2720
}
2717
2721
2722
+ static bool IsSYCLDeviceLibObj (std::string ObjFilePath, bool isMSVCEnv) {
2723
+ StringRef ObjFileName = llvm::sys::path::filename (ObjFilePath);
2724
+ StringRef ObjSuffix = isMSVCEnv ? " .obj" : " .o" ;
2725
+ bool Ret =
2726
+ (ObjFileName.startswith (" libsycl-" ) && ObjFileName.endswith (ObjSuffix))
2727
+ ? true
2728
+ : false ;
2729
+ return Ret;
2730
+ }
2731
+
2718
2732
// Goes through all of the arguments, including inputs expected for the
2719
2733
// linker directly, to determine if we need to perform additional work for
2720
2734
// static offload libraries.
@@ -3793,7 +3807,13 @@ class OffloadingActionBuilder final {
3793
3807
if (IA->getType () == types::TY_Object) {
3794
3808
if (!isObjectFile (FileName))
3795
3809
return ABRT_Inactive;
3796
- if (Args.hasArg (options::OPT_fintelfpga))
3810
+ // For SYCL device libraries, don't need to add them to
3811
+ // FPGAObjectInputs as there is no FPGA dep files inside.
3812
+
3813
+ if (Args.hasArg (options::OPT_fintelfpga) &&
3814
+ !IsSYCLDeviceLibObj (FileName, C.getDefaultToolChain ()
3815
+ .getTriple ()
3816
+ .isWindowsMSVCEnvironment ()))
3797
3817
FPGAObjectInputs.push_back (IA);
3798
3818
}
3799
3819
// When creating FPGA device fat objects, all host objects are
@@ -3857,6 +3877,92 @@ class OffloadingActionBuilder final {
3857
3877
SYCLDeviceActions.clear ();
3858
3878
}
3859
3879
3880
+ void addSYCLDeviceLibs (const ToolChain *TC, ActionList &DeviceLinkObjects,
3881
+ bool isSpirvAOT, bool isMSVCEnv) {
3882
+ enum SYCLDeviceLibType {
3883
+ sycl_devicelib_wrapper,
3884
+ sycl_devicelib_fallback
3885
+ };
3886
+ struct DeviceLibOptInfo {
3887
+ StringRef devicelib_name;
3888
+ StringRef devicelib_option;
3889
+ };
3890
+
3891
+ bool NoDeviceLibs = false ;
3892
+ // Currently, libc, libm-fp32 will be linked in by default. In order
3893
+ // to use libm-fp64, -fsycl-device-lib=libm-fp64/all should be used.
3894
+ llvm::StringMap<bool > devicelib_link_info = {
3895
+ {" libc" , true }, {" libm-fp32" , true }, {" libm-fp64" , false }};
3896
+ if (Arg *A = Args.getLastArg (options::OPT_fsycl_device_lib_EQ,
3897
+ options::OPT_fno_sycl_device_lib_EQ)) {
3898
+ if (A->getValues ().size () == 0 )
3899
+ C.getDriver ().Diag (diag::warn_drv_empty_joined_argument)
3900
+ << A->getAsString (Args);
3901
+ else {
3902
+ if (A->getOption ().matches (options::OPT_fno_sycl_device_lib_EQ))
3903
+ NoDeviceLibs = true ;
3904
+
3905
+ for (StringRef Val : A->getValues ()) {
3906
+ if (Val == " all" ) {
3907
+ for (auto &K : devicelib_link_info.keys ())
3908
+ devicelib_link_info[K] = true && !NoDeviceLibs;
3909
+ break ;
3910
+ }
3911
+ auto LinkInfoIter = devicelib_link_info.find (Val);
3912
+ if (LinkInfoIter == devicelib_link_info.end ()) {
3913
+ C.getDriver ().Diag (diag::err_drv_unsupported_option_argument)
3914
+ << A->getOption ().getName () << Val;
3915
+ }
3916
+ devicelib_link_info[Val] = true && !NoDeviceLibs;
3917
+ }
3918
+ }
3919
+ }
3920
+
3921
+ SmallString<128 > LibLoc (TC->getDriver ().Dir );
3922
+ llvm::sys::path::append (LibLoc, " /../lib" );
3923
+ StringRef LibSuffix = isMSVCEnv ? " .obj" : " .o" ;
3924
+ SmallVector<DeviceLibOptInfo, 5 > sycl_device_wrapper_libs = {
3925
+ {" libsycl-crt" , " libc" },
3926
+ {" libsycl-complex" , " libm-fp32" },
3927
+ {" libsycl-complex-fp64" , " libm-fp64" },
3928
+ {" libsycl-cmath" , " libm-fp32" },
3929
+ {" libsycl-cmath-fp64" , " libm-fp64" }};
3930
+ // For AOT compilation, we need to link sycl_device_fallback_libs as
3931
+ // default too.
3932
+ SmallVector<DeviceLibOptInfo, 5 > sycl_device_fallback_libs = {
3933
+ {" libsycl-fallback-cassert" , " libc" },
3934
+ {" libsycl-fallback-complex" , " libm-fp32" },
3935
+ {" libsycl-fallback-complex-fp64" , " libm-fp64" },
3936
+ {" libsycl-fallback-cmath" , " libm-fp32" },
3937
+ {" libsycl-fallback-cmath-fp64" , " libm-fp64" }};
3938
+ auto addInputs = [&](SYCLDeviceLibType t) {
3939
+ auto sycl_libs = (t == sycl_devicelib_wrapper)
3940
+ ? sycl_device_wrapper_libs
3941
+ : sycl_device_fallback_libs;
3942
+ for (const DeviceLibOptInfo &Lib : sycl_libs) {
3943
+ if (!devicelib_link_info[Lib.devicelib_option ])
3944
+ continue ;
3945
+ SmallString<128 > LibName (LibLoc);
3946
+ llvm::sys::path::append (LibName, Lib.devicelib_name );
3947
+ llvm::sys::path::replace_extension (LibName, LibSuffix);
3948
+ if (llvm::sys::fs::exists (LibName)) {
3949
+ Arg *InputArg = MakeInputArg (Args, C.getDriver ().getOpts (),
3950
+ Args.MakeArgString (LibName));
3951
+ auto *SYCLDeviceLibsInputAction =
3952
+ C.MakeAction <InputAction>(*InputArg, types::TY_Object);
3953
+ auto *SYCLDeviceLibsUnbundleAction =
3954
+ C.MakeAction <OffloadUnbundlingJobAction>(
3955
+ SYCLDeviceLibsInputAction);
3956
+ addDeviceDepences (SYCLDeviceLibsUnbundleAction);
3957
+ DeviceLinkObjects.push_back (SYCLDeviceLibsUnbundleAction);
3958
+ }
3959
+ }
3960
+ };
3961
+ addInputs (sycl_devicelib_wrapper);
3962
+ if (isSpirvAOT)
3963
+ addInputs (sycl_devicelib_fallback);
3964
+ }
3965
+
3860
3966
void appendLinkDependences (OffloadAction::DeviceDependences &DA) override {
3861
3967
assert (ToolChains.size () == DeviceLinkerInputs.size () &&
3862
3968
" Toolchains and linker inputs sizes do not match." );
@@ -3936,13 +4042,27 @@ class OffloadingActionBuilder final {
3936
4042
}
3937
4043
ActionList DeviceLibObjects;
3938
4044
ActionList LinkObjects;
4045
+ auto TT = SYCLTripleList[I];
4046
+ auto isNVPTX = (*TC)->getTriple ().isNVPTX ();
4047
+ bool isSpirvAOT = TT.getSubArch () == llvm::Triple::SPIRSubArch_fpga ||
4048
+ TT.getSubArch () == llvm::Triple::SPIRSubArch_gen ||
4049
+ TT.getSubArch () == llvm::Triple::SPIRSubArch_x86_64;
3939
4050
for (const auto &Input : LI) {
3940
4051
// FPGA aoco does not go through the link, everything else does.
3941
4052
if (Input->getType () == types::TY_FPGA_AOCO)
3942
4053
DeviceLibObjects.push_back (Input);
3943
4054
else
3944
4055
LinkObjects.push_back (Input);
3945
4056
}
4057
+ // FIXME: Link all wrapper and fallback device libraries as default,
4058
+ // When spv online link is supported by all backends, the fallback
4059
+ // device libraries are only needed when current toolchain is using
4060
+ // AOT compilation.
4061
+ if (!isNVPTX) {
4062
+ addSYCLDeviceLibs (
4063
+ *TC, LinkObjects, true ,
4064
+ C.getDefaultToolChain ().getTriple ().isWindowsMSVCEnvironment ());
4065
+ }
3946
4066
// The linkage actions subgraph leading to the offload wrapper.
3947
4067
// [cond] Means incoming/outgoing dependence is created only when cond
3948
4068
// is true. A function of:
@@ -3997,7 +4117,6 @@ class OffloadingActionBuilder final {
3997
4117
Action *DeviceLinkAction =
3998
4118
C.MakeAction <LinkJobAction>(LinkObjects, types::TY_LLVM_BC);
3999
4119
// setup some flags upfront
4000
- auto isNVPTX = (*TC)->getTriple ().isNVPTX ();
4001
4120
4002
4121
if (isNVPTX && DeviceCodeSplit) {
4003
4122
// TODO Temporary limitation, need to support code splitting for PTX
@@ -4009,10 +4128,6 @@ class OffloadingActionBuilder final {
4009
4128
D.Diag (diag::err_drv_unsupported_opt_for_target)
4010
4129
<< OptName << (*TC)->getTriple ().str ();
4011
4130
}
4012
- auto TT = SYCLTripleList[I];
4013
- bool isSpirvAOT = TT.getSubArch () == llvm::Triple::SPIRSubArch_fpga ||
4014
- TT.getSubArch () == llvm::Triple::SPIRSubArch_gen ||
4015
- TT.getSubArch () == llvm::Triple::SPIRSubArch_x86_64;
4016
4131
// reflects whether current target is ahead-of-time and can't support
4017
4132
// runtime setting of specialization constants
4018
4133
bool isAOT = isNVPTX || isSpirvAOT;
0 commit comments