|
101 | 101 | #include <cstdlib> // ::getenv
|
102 | 102 | #include <map>
|
103 | 103 | #include <memory>
|
| 104 | +#include <regex> |
| 105 | +#include <sstream> |
104 | 106 | #include <utility>
|
105 | 107 | #if LLVM_ON_UNIX
|
106 | 108 | #include <unistd.h> // getpid
|
@@ -5064,6 +5066,76 @@ class OffloadingActionBuilder final {
|
5064 | 5066 | }
|
5065 | 5067 | }
|
5066 | 5068 |
|
| 5069 | + // Return whether to use native bfloat16 library. |
| 5070 | + bool selectBfloatLibs(const ToolChain *TC, bool &useNative) { |
| 5071 | + const OptTable &Opts = C.getDriver().getOpts(); |
| 5072 | + const char *TargetOpt = nullptr; |
| 5073 | + const char *DeviceOpt = nullptr; |
| 5074 | + bool needLibs = false; |
| 5075 | + for (auto *A : Args) { |
| 5076 | + llvm::Triple *TargetBE = nullptr; |
| 5077 | + |
| 5078 | + auto GetTripleIt = [&, this](llvm::StringRef Triple) { |
| 5079 | + llvm::Triple TargetTriple{Triple}; |
| 5080 | + auto TripleIt = llvm::find_if(SYCLTripleList, [&](auto &SYCLTriple) { |
| 5081 | + return SYCLTriple == TargetTriple; |
| 5082 | + }); |
| 5083 | + return TripleIt != SYCLTripleList.end() ? &*TripleIt : nullptr; |
| 5084 | + }; |
| 5085 | + |
| 5086 | + if (A->getOption().matches(options::OPT_fsycl_targets_EQ)) { |
| 5087 | + // spir64 target is actually JIT compilation, so we defer selection of |
| 5088 | + // bfloat16 libraries to runtime. For AOT we need libraries. |
| 5089 | + needLibs = TC->getTriple().getSubArch() != llvm::Triple::NoSubArch; |
| 5090 | + TargetBE = GetTripleIt(A->getValue(0)); |
| 5091 | + if (TargetBE) |
| 5092 | + TargetOpt = A->getValue(0); |
| 5093 | + else |
| 5094 | + continue; |
| 5095 | + } else if (A->getOption().matches(options::OPT_Xsycl_backend_EQ)) { |
| 5096 | + // Passing device args: -Xsycl-target-backend=<triple> <opt> |
| 5097 | + TargetBE = GetTripleIt(A->getValue(0)); |
| 5098 | + if (TargetBE) |
| 5099 | + DeviceOpt = A->getValue(1); |
| 5100 | + else |
| 5101 | + continue; |
| 5102 | + } else if (A->getOption().matches(options::OPT_Xsycl_backend)) { |
| 5103 | + // Passing device args: -Xsycl-target-backend <opt> |
| 5104 | + TargetBE = &SYCLTripleList.front(); |
| 5105 | + DeviceOpt = A->getValue(0); |
| 5106 | + } else if (A->getOption().matches(options::OPT_Xs_separate)) { |
| 5107 | + // Passing device args: -Xs <opt> |
| 5108 | + DeviceOpt = A->getValue(0); |
| 5109 | + } else { |
| 5110 | + continue; |
| 5111 | + }; |
| 5112 | + } |
| 5113 | + useNative = false; |
| 5114 | + if (needLibs) |
| 5115 | + if (TC->getTriple().getSubArch() == llvm::Triple::SPIRSubArch_gen && |
| 5116 | + TargetOpt && DeviceOpt) { |
| 5117 | + |
| 5118 | + auto checkBF = [=](std::string &Dev) { |
| 5119 | + static const std::regex BFFs("pvc.*|ats.*"); |
| 5120 | + return std::regex_match(Dev, BFFs); |
| 5121 | + }; |
| 5122 | + |
| 5123 | + needLibs = true; |
| 5124 | + std::string Params{DeviceOpt}; |
| 5125 | + size_t DevicesPos = Params.find("-device "); |
| 5126 | + useNative = false; |
| 5127 | + if (DevicesPos != std::string::npos) { |
| 5128 | + useNative = true; |
| 5129 | + std::istringstream Devices(Params.substr(DevicesPos + 8)); |
| 5130 | + for (std::string S; std::getline(Devices, S, ',');) { |
| 5131 | + useNative &= checkBF(S); |
| 5132 | + } |
| 5133 | + } |
| 5134 | + } |
| 5135 | + |
| 5136 | + return needLibs; |
| 5137 | + } |
| 5138 | + |
5067 | 5139 | bool addSYCLDeviceLibs(const ToolChain *TC, ActionList &DeviceLinkObjects,
|
5068 | 5140 | bool isSpirvAOT, bool isMSVCEnv) {
|
5069 | 5141 | struct DeviceLibOptInfo {
|
@@ -5139,6 +5211,10 @@ class OffloadingActionBuilder final {
|
5139 | 5211 | {"libsycl-fallback-imf", "libimf-fp32"},
|
5140 | 5212 | {"libsycl-fallback-imf-fp64", "libimf-fp64"},
|
5141 | 5213 | {"libsycl-fallback-imf-bf16", "libimf-bf16"}};
|
| 5214 | + const SYCLDeviceLibsList sycl_device_bfloat16_fallback_lib = { |
| 5215 | + {"libsycl-fallback-bfloat16", "libm-bfloat16"}}; |
| 5216 | + const SYCLDeviceLibsList sycl_device_bfloat16_native_lib = { |
| 5217 | + {"libsycl-native-bfloat16", "libm-bfloat16"}}; |
5142 | 5218 | // ITT annotation libraries are linked in separately whenever the device
|
5143 | 5219 | // code instrumentation is enabled.
|
5144 | 5220 | const SYCLDeviceLibsList sycl_device_annotation_libs = {
|
@@ -5188,6 +5264,17 @@ class OffloadingActionBuilder final {
|
5188 | 5264 | addInputs(sycl_device_wrapper_libs);
|
5189 | 5265 | if (isSpirvAOT || TC->getTriple().isNVPTX())
|
5190 | 5266 | addInputs(sycl_device_fallback_libs);
|
| 5267 | + |
| 5268 | + bool nativeBfloatLibs; |
| 5269 | + bool needBfloatLibs = selectBfloatLibs(TC, nativeBfloatLibs); |
| 5270 | + if (needBfloatLibs) { |
| 5271 | + // Add native or fallback bfloat16 library. |
| 5272 | + if (nativeBfloatLibs) |
| 5273 | + addInputs(sycl_device_bfloat16_native_lib); |
| 5274 | + else |
| 5275 | + addInputs(sycl_device_bfloat16_fallback_lib); |
| 5276 | + } |
| 5277 | + |
5191 | 5278 | if (Args.hasFlag(options::OPT_fsycl_instrument_device_code,
|
5192 | 5279 | options::OPT_fno_sycl_instrument_device_code, true))
|
5193 | 5280 | addInputs(sycl_device_annotation_libs);
|
|
0 commit comments