Skip to content

Commit 82aaf27

Browse files
authored
[SYCL][Driver] Refactor device config parsing to better match HIP and CUDA targets (#13617)
Refactors the device config parsing by making it agnostic of the way the SYCL device is targeted, either by passing a device triple plus arch special string to `-fsycl-targets` or a just the device arch to `--offload-arch` (mostly for CUDA and HIP). This is achieved by also moving the parsing logic into `SYCLActionBuilder`, in order to make use of the device architecture bound to the offloading toolchain to lookup in the DeviceConfig file's TargetTable accordingly. This PR also introduces HIP and CUDA target info in the `DeviceConfigFile.td` which is currently not complete but a starting point to build on.
1 parent b4e0450 commit 82aaf27

File tree

6 files changed

+564
-96
lines changed

6 files changed

+564
-96
lines changed

clang/include/clang/Driver/Driver.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -973,12 +973,12 @@ class Driver {
973973
return SYCLUniqueIDList[FileName];
974974
}
975975

976-
/// Reads device config file to find information about the SYCL targets in
977-
/// UniqueSYCLTriplesVec, and defines device traits macros accordingly.
978-
void populateSYCLDeviceTraitsMacrosArgs(
979-
const llvm::opt::ArgList &Args,
980-
const llvm::SmallVector<llvm::Triple, 4> &UniqueSYCLTriplesVec);
981-
976+
/// SYCLDeviceTraitMacroArg - Add the given macro to the vector of args to be
977+
/// added to the device compilation step.
978+
void addSYCLDeviceTraitsMacroArg(const llvm::opt::ArgList &Args,
979+
StringRef Macro) const {
980+
SYCLDeviceTraitsMacrosArgs.push_back(Args.MakeArgString(Macro));
981+
}
982982
llvm::opt::ArgStringList getDeviceTraitsMacrosArgs() const {
983983
return SYCLDeviceTraitsMacrosArgs;
984984
}

clang/lib/Driver/Driver.cpp

Lines changed: 100 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,9 +1311,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
13111311
}
13121312
}
13131313
}
1314-
// Define macros associated with `any_device_has/all_devices_have` according
1315-
// to the aspects defined in the DeviceConfigFile for the SYCL targets.
1316-
populateSYCLDeviceTraitsMacrosArgs(C.getInputArgs(), UniqueSYCLTriplesVec);
13171314
// We'll need to use the SYCL and host triples as the key into
13181315
// getOffloadingDeviceToolChain, because the device toolchains we're
13191316
// going to create will depend on both.
@@ -6277,6 +6274,101 @@ class OffloadingActionBuilder final {
62776274
return FinalDeviceSections;
62786275
}
62796276

6277+
/// Reads device config file to find information about the SYCL targets in
6278+
/// `Targets`, and defines device traits macros accordingly.
6279+
void populateSYCLDeviceTraitsMacrosArgs(
6280+
Compilation &C, const DerivedArgList &Args,
6281+
const SmallVector<DeviceTargetInfo, 4> &Targets) const {
6282+
if (Targets.empty())
6283+
return;
6284+
6285+
const auto &TargetTable = DeviceConfigFile::TargetTable;
6286+
std::map<StringRef, unsigned int> AllDevicesHave;
6287+
std::map<StringRef, bool> AnyDeviceHas;
6288+
bool AnyDeviceHasAnyAspect = false;
6289+
unsigned int ValidTargets = 0;
6290+
for (const auto &[TC, BoundArch] : Targets) {
6291+
assert(TC && "Invalid SYCL Offload Toolchain");
6292+
// Try and find the device arch, if it's empty, try to search for either
6293+
// the whole Triple or just the 'ArchName' string.
6294+
auto TargetIt = TargetTable.end();
6295+
const llvm::Triple &TargetTriple = TC->getTriple();
6296+
const StringRef TargetArch{BoundArch};
6297+
if (!TargetArch.empty()) {
6298+
TargetIt = llvm::find_if(TargetTable, [&](const auto &Value) {
6299+
using namespace tools::SYCL;
6300+
StringRef Device{Value.first};
6301+
if (Device.consume_front(gen::AmdGPU))
6302+
return TargetArch.equals(Device) && TargetTriple.isAMDGCN();
6303+
if (Device.consume_front(gen::NvidiaGPU))
6304+
return TargetArch.equals(Device) && TargetTriple.isNVPTX();
6305+
if (Device.consume_front(gen::IntelGPU))
6306+
return TargetArch.equals(Device) && TargetTriple.isSPIRAOT();
6307+
return TargetArch.equals(Device) && isValidSYCLTriple(TargetTriple);
6308+
});
6309+
} else {
6310+
TargetIt = TargetTable.find(TargetTriple.str());
6311+
if (TargetIt == TargetTable.end())
6312+
TargetIt = TargetTable.find(TargetTriple.getArchName().str());
6313+
}
6314+
6315+
if (TargetIt != TargetTable.end()) {
6316+
const DeviceConfigFile::TargetInfo &Info = (*TargetIt).second;
6317+
++ValidTargets;
6318+
const auto &AspectList = Info.aspects;
6319+
const auto &MaySupportOtherAspects = Info.maySupportOtherAspects;
6320+
if (!AnyDeviceHasAnyAspect)
6321+
AnyDeviceHasAnyAspect = MaySupportOtherAspects;
6322+
for (const auto &Aspect : AspectList) {
6323+
// If target has an entry in the config file, the set of aspects
6324+
// supported by all devices supporting the target is 'AspectList'.
6325+
// If there's no entry, such set is empty.
6326+
const auto &AspectIt = AllDevicesHave.find(Aspect);
6327+
if (AspectIt != AllDevicesHave.end())
6328+
++AllDevicesHave[Aspect];
6329+
else
6330+
AllDevicesHave[Aspect] = 1;
6331+
// If target has an entry in the config file AND
6332+
// 'MaySupportOtherAspects' is false, the set of aspects supported
6333+
// by any device supporting the target is 'AspectList'. If there's
6334+
// no entry OR 'MaySupportOtherAspects' is true, such set contains
6335+
// all the aspects.
6336+
AnyDeviceHas[Aspect] = true;
6337+
}
6338+
}
6339+
}
6340+
6341+
// If there's no entry for the target in the device config file, the set
6342+
// of aspects supported by any device supporting the target contains all
6343+
// the aspects.
6344+
if (ValidTargets == 0)
6345+
AnyDeviceHasAnyAspect = true;
6346+
6347+
const Driver &D = C.getDriver();
6348+
if (AnyDeviceHasAnyAspect) {
6349+
// There exists some target that supports any given aspect.
6350+
constexpr static StringRef MacroAnyDeviceAnyAspect{
6351+
"-D__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__=1"};
6352+
D.addSYCLDeviceTraitsMacroArg(Args, MacroAnyDeviceAnyAspect);
6353+
} else {
6354+
// Some of the aspects are not supported at all by any of the targets.
6355+
// Thus, we need to define individual macros for each supported aspect.
6356+
for (const auto &[TargetKey, SupportedTarget] : AnyDeviceHas) {
6357+
assert(SupportedTarget);
6358+
const SmallString<64> MacroAnyDevice{
6359+
{"-D__SYCL_ANY_DEVICE_HAS_", TargetKey, "__=1"}};
6360+
D.addSYCLDeviceTraitsMacroArg(Args, MacroAnyDevice);
6361+
}
6362+
}
6363+
for (const auto &[TargetKey, SupportedTargets] : AllDevicesHave) {
6364+
if (SupportedTargets != ValidTargets)
6365+
continue;
6366+
const SmallString<64> MacroAllDevices{
6367+
{"-D__SYCL_ALL_DEVICES_HAVE_", TargetKey, "__=1"}};
6368+
D.addSYCLDeviceTraitsMacroArg(Args, MacroAllDevices);
6369+
}
6370+
}
6371+
62806372
bool initialize() override {
62816373
using namespace tools::SYCL;
62826374
// Get the SYCL toolchains. If we don't get any, the action builder will
@@ -6536,6 +6628,11 @@ class OffloadingActionBuilder final {
65366628
checkForOffloadMismatch(C, Args, SYCLTargetInfoList);
65376629
checkForMisusedAddDefaultSpecConstsImageFlag(C, Args, SYCLTargetInfoList);
65386630

6631+
// Define macros associated with `any_device_has/all_devices_have`
6632+
// according to the aspects defined in the DeviceConfigFile for the SYCL
6633+
// targets.
6634+
populateSYCLDeviceTraitsMacrosArgs(C, Args, SYCLTargetInfoList);
6635+
65396636
DeviceLinkerInputs.resize(SYCLTargetInfoList.size());
65406637
return false;
65416638
}
@@ -10444,92 +10541,6 @@ llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args,
1044410541
return llvm::Error::success();
1044510542
}
1044610543

10447-
void Driver::populateSYCLDeviceTraitsMacrosArgs(
10448-
const llvm::opt::ArgList &Args,
10449-
const llvm::SmallVector<llvm::Triple, 4> &UniqueSYCLTriplesVec) {
10450-
const auto &TargetTable = DeviceConfigFile::TargetTable;
10451-
std::map<StringRef, unsigned int> AllDevicesHave;
10452-
std::map<StringRef, bool> AnyDeviceHas;
10453-
bool AnyDeviceHasAnyAspect = false;
10454-
unsigned int ValidTargets = 0;
10455-
for (const auto &TargetTriple : UniqueSYCLTriplesVec) {
10456-
// Try and find the whole triple, if there's no match, remove parts of the
10457-
// triple from the end to find partial matches.
10458-
auto TargetTripleStr = TargetTriple.getTriple();
10459-
bool Found = false;
10460-
bool EmptyTriple = false;
10461-
auto TripleIt = TargetTable.end();
10462-
while (!Found && !EmptyTriple) {
10463-
TripleIt = TargetTable.find(TargetTripleStr);
10464-
Found = (TripleIt != TargetTable.end());
10465-
if (!Found) {
10466-
auto Pos = TargetTripleStr.find_last_of('-');
10467-
EmptyTriple = (Pos == std::string::npos);
10468-
TargetTripleStr =
10469-
EmptyTriple ? TargetTripleStr : TargetTripleStr.substr(0, Pos);
10470-
}
10471-
}
10472-
if (Found) {
10473-
assert(TripleIt != TargetTable.end());
10474-
const auto &TargetInfo = (*TripleIt).second;
10475-
++ValidTargets;
10476-
const auto &AspectList = TargetInfo.aspects;
10477-
const auto &MaySupportOtherAspects = TargetInfo.maySupportOtherAspects;
10478-
if (!AnyDeviceHasAnyAspect)
10479-
AnyDeviceHasAnyAspect = MaySupportOtherAspects;
10480-
for (const auto &aspect : AspectList) {
10481-
// If target has an entry in the config file, the set of aspects
10482-
// supported by all devices supporting the target is 'AspectList'. If
10483-
// there's no entry, such set is empty.
10484-
const auto &AspectIt = AllDevicesHave.find(aspect);
10485-
if (AspectIt != AllDevicesHave.end())
10486-
++AllDevicesHave[aspect];
10487-
else
10488-
AllDevicesHave[aspect] = 1;
10489-
// If target has an entry in the config file AND
10490-
// 'MaySupportOtherAspects' is false, the set of aspects supported by
10491-
// any device supporting the target is 'AspectList'. If there's no
10492-
// entry OR 'MaySupportOtherAspects' is true, such set contains all
10493-
// the aspects.
10494-
AnyDeviceHas[aspect] = true;
10495-
}
10496-
}
10497-
}
10498-
10499-
if (ValidTargets == 0) {
10500-
// If there's no entry for the target in the device config file, the set
10501-
// of aspects supported by any device supporting the target contains all
10502-
// the aspects.
10503-
AnyDeviceHasAnyAspect = true;
10504-
}
10505-
10506-
if (AnyDeviceHasAnyAspect) {
10507-
// There exists some target that supports any given aspect.
10508-
SmallString<64> MacroAnyDeviceAnyAspect(
10509-
"-D__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__=1");
10510-
SYCLDeviceTraitsMacrosArgs.push_back(
10511-
Args.MakeArgString(MacroAnyDeviceAnyAspect));
10512-
} else {
10513-
// Some of the aspects are not supported at all by any of the targets.
10514-
// Thus, we need to define individual macros for each supported aspect.
10515-
for (const auto &[TargetKey, SupportedTarget] : AnyDeviceHas) {
10516-
assert(SupportedTarget);
10517-
SmallString<64> MacroAnyDevice("-D__SYCL_ANY_DEVICE_HAS_");
10518-
MacroAnyDevice += TargetKey;
10519-
MacroAnyDevice += "__=1";
10520-
SYCLDeviceTraitsMacrosArgs.push_back(Args.MakeArgString(MacroAnyDevice));
10521-
}
10522-
}
10523-
for (const auto &[TargetKey, SupportedTargets] : AllDevicesHave) {
10524-
if (SupportedTargets != ValidTargets)
10525-
continue;
10526-
SmallString<64> MacroAllDevices("-D__SYCL_ALL_DEVICES_HAVE_");
10527-
MacroAllDevices += TargetKey;
10528-
MacroAllDevices += "__=1";
10529-
SYCLDeviceTraitsMacrosArgs.push_back(Args.MakeArgString(MacroAllDevices));
10530-
}
10531-
}
10532-
1053310544
static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) {
1053410545
return SavedStrings.insert(S).first->getKeyData();
1053510546
}

0 commit comments

Comments
 (0)