Skip to content

[SYCL][Driver] Move offload mismatch warning into SYCLActionBuilder #7434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 65 additions & 78 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1731,9 +1731,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
if (checkForSYCLDefaultDevice(*C, *TranslatedArgs))
setSYCLDefaultTriple(true);

// Check missing targets in archives/objects based on inputs from the user.
checkForOffloadMismatch(*C, *TranslatedArgs);

// Populate the tool chains for the offloading devices, if any.
CreateOffloadingDeviceToolChains(*C, Inputs);

Expand Down Expand Up @@ -3606,81 +3603,6 @@ bool Driver::checkForOffloadStaticLib(Compilation &C,
return false;
}

// Goes through all of the arguments, including inputs expected for the
// linker directly, to determine if the targets contained in the objects and
// archives match target expectations being performed.
void Driver::checkForOffloadMismatch(Compilation &C,
DerivedArgList &Args) const {
// Check only if enabled with -fsycl
if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false))
return;

SmallVector<const char *, 16> OffloadLibArgs(getLinkerArgs(C, Args, true));
// Gather all of the sections seen in the offload objects/archives
SmallVector<std::string, 4> UniqueSections;
for (StringRef OLArg : OffloadLibArgs) {
SmallVector<std::string, 4> Sections(getOffloadSections(C, OLArg));
for (auto Section : Sections) {
// We only care about sections that start with 'sycl-'. Also remove
// the prefix before adding it.
std::string Prefix("sycl-");
if (Section.compare(0, Prefix.length(), Prefix) != 0)
continue;
std::string Arch = Section.substr(Prefix.length());
// There are a few different variants for FPGA, if we see one, just
// use the default FPGA triple to reduce possible match confusion.
if (Arch.compare(0, 4, "fpga") == 0)
Arch = C.getDriver().MakeSYCLDeviceTriple("spir64_fpga").str();
if (std::find(UniqueSections.begin(), UniqueSections.end(), Arch) ==
UniqueSections.end())
UniqueSections.push_back(Arch);
}
}

if (!UniqueSections.size())
return;

// Put together list of user defined and implied targets, we will diagnose
// each target individually.
SmallVector<StringRef, 4> Targets;
if (const Arg *A = Args.getLastArg(options::OPT_fsycl_targets_EQ)) {
for (StringRef Val : A->getValues()) {
if (auto ValidDevice = isIntelGPUTarget(Val)) {
if (!ValidDevice->empty())
Targets.push_back(Args.MakeArgString(
C.getDriver().MakeSYCLDeviceTriple("spir64_gen").str() + "-" +
*ValidDevice));
continue;
}
Targets.push_back(Val);
}
} else { // Implied targets
// No -fsycl-targets given, check based on -fintelfpga or default device
bool SYCLfpga = C.getInputArgs().hasArg(options::OPT_fintelfpga);
// -fsycl -fintelfpga implies spir64_fpga
Targets.push_back(SYCLfpga ? "spir64_fpga" : getDefaultSYCLArch(C));
}

for (auto SyclTarget : Targets) {
// Match found sections with user and implied targets.
llvm::Triple TT(C.getDriver().MakeSYCLDeviceTriple(SyclTarget));
// If any matching section is found, we are good.
if (std::find(UniqueSections.begin(), UniqueSections.end(), TT.str()) !=
UniqueSections.end())
continue;
// Didn't find any matches, return the full list for the diagnostic.
SmallString<128> ArchListStr;
int Cnt = 0;
for (std::string Section : UniqueSections) {
if (Cnt)
ArchListStr += ", ";
ArchListStr += Section;
Cnt++;
}
Diag(diag::warn_drv_sycl_target_missing) << SyclTarget << ArchListStr;
}
}

/// Check whether the given input tree contains any clang-offload-dependency
/// actions.
static bool ContainsOffloadDepsAction(const Action *A) {
Expand Down Expand Up @@ -5718,6 +5640,68 @@ class OffloadingActionBuilder final {
return false;
}

// Goes through all of the arguments, including inputs expected for the
// linker directly, to determine if the targets contained in the objects and
// archives match target expectations being performed.
void
checkForOffloadMismatch(Compilation &C, DerivedArgList &Args,
SmallVector<DeviceTargetInfo, 4> &Targets) const {
if (Targets.empty())
return;

SmallVector<const char *, 16> OffloadLibArgs(
getLinkerArgs(C, Args, true));
// Gather all of the sections seen in the offload objects/archives
SmallVector<std::string, 4> UniqueSections;
for (StringRef OLArg : OffloadLibArgs) {
SmallVector<std::string, 4> Sections(getOffloadSections(C, OLArg));
for (auto Section : Sections) {
// We only care about sections that start with 'sycl-'. Also remove
// the prefix before adding it.
std::string Prefix("sycl-");
if (Section.compare(0, Prefix.length(), Prefix) != 0)
continue;

std::string Arch = Section.substr(Prefix.length());

// There are a few different variants for FPGA, if we see one, just
// use the default FPGA triple to reduce possible match confusion.
if (Arch.compare(0, 4, "fpga") == 0)
Arch = C.getDriver().MakeSYCLDeviceTriple("spir64_fpga").str();
if (std::find(UniqueSections.begin(), UniqueSections.end(), Arch) ==
UniqueSections.end())
UniqueSections.push_back(Arch);
}
}

if (!UniqueSections.size())
return;

for (auto SyclTarget : Targets) {
std::string SectionTriple = SyclTarget.TC->getTriple().str();
if (SyclTarget.BoundArch) {
SectionTriple += "-";
SectionTriple += SyclTarget.BoundArch;
}

// If any matching section is found, we are good.
if (std::find(UniqueSections.begin(), UniqueSections.end(),
SectionTriple) != UniqueSections.end())
continue;
// Didn't find any matches, return the full list for the diagnostic.
SmallString<128> ArchListStr;
int Cnt = 0;
for (std::string Section : UniqueSections) {
if (Cnt)
ArchListStr += ", ";
ArchListStr += Section;
Cnt++;
}
C.getDriver().Diag(diag::warn_drv_sycl_target_missing)
<< SectionTriple << ArchListStr;
}
}

bool initialize() override {
// Get the SYCL toolchains. If we don't get any, the action builder will
// know there is nothing to do related to SYCL offloading.
Expand Down Expand Up @@ -5914,6 +5898,9 @@ class OffloadingActionBuilder final {
const auto *TC = ToolChains.front();
SYCLTargetInfoList.emplace_back(TC, nullptr);
}

checkForOffloadMismatch(C, Args, SYCLTargetInfoList);

DeviceLinkerInputs.resize(SYCLTargetInfoList.size());
return false;
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
55 changes: 54 additions & 1 deletion clang/test/Driver/sycl-target-mismatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// RUN: %clangxx -fsycl -fsycl-targets=spir64_gen %S/Inputs/SYCL/objlin64.o \
// RUN: -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=SPIR64_GEN_DIAG
// SPIR64_GEN_DIAG: linked binaries do not contain expected 'spir64_gen' target; found targets: 'spir64-unknown-unknown{{.*}}, spir64-unknown-unknown{{.*}}' [-Wsycl-target]
// SPIR64_GEN_DIAG: linked binaries do not contain expected 'spir64_gen-unknown-unknown' target; found targets: 'spir64-unknown-unknown{{.*}}, spir64-unknown-unknown{{.*}}' [-Wsycl-target]

// RUN: %clangxx -fsycl -fsycl-targets=spir64 %S/Inputs/SYCL/liblin64.a \
// RUN: -### %s 2>&1 \
Expand All @@ -23,3 +23,56 @@
// RUN: -Wno-sycl-target -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=SPIR64_DIAG
// SPIR64_DIAG-NOT: linked binaries do not contain expected

// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_60 \
// RUN: %S/Inputs/SYCL/libnvptx64-sm_50.a -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_60 \
// RUN: -L%S/Inputs/SYCL -lnvptx64-sm_50 -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_60 \
// RUN: %S/Inputs/SYCL/objnvptx64-sm_50.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_DIAG
// NVPTX64_DIAG: linked binaries do not contain expected 'nvptx64-nvidia-cuda-sm_60' target; found targets: 'nvptx64-nvidia-cuda-sm_50' [-Wsycl-target]

// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_50 \
// RUN: %S/Inputs/SYCL/libnvptx64-sm_50.a -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_50 \
// RUN: -L%S/Inputs/SYCL -lnvptx64-sm_50 -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_50 \
// RUN: %S/Inputs/SYCL/objnvptx64-sm_50.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda \
// RUN: %S/Inputs/SYCL/objnvptx64-sm_50.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend --cuda-gpu-arch=sm_60 \
// RUN: -Wno-sycl-target %S/Inputs/SYCL/objnvptx64-sm_50.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=NVPTX64_MATCH_DIAG
// NVPTX64_MATCH_DIAG-NOT: linked binaries do not contain expected

// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx906 \
// RUN: %S/Inputs/SYCL/libamdgcn-gfx908.a -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx906 \
// RUN: -L%S/Inputs/SYCL -lamdgcn-gfx908 -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx906 \
// RUN: %S/Inputs/SYCL/objamdgcn-gfx908.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_DIAG
// AMDGCN_DIAG: linked binaries do not contain expected 'amdgcn-amd-amdhsa-gfx906' target; found targets: 'amdgcn-amd-amdhsa-gfx908' [-Wsycl-target]

// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 \
// RUN: %S/Inputs/SYCL/libamdgcn-gfx908.a -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 \
// RUN: -L%S/Inputs/SYCL -lamdgcn-gfx908 -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx908 \
// RUN: %S/Inputs/SYCL/objamdgcn-gfx908.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_MATCH_DIAG
// RUN: %clangxx -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=gfx906 \
// RUN: -Wno-sycl-target %S/Inputs/SYCL/objamdgcn-gfx908.o -### %s 2>&1 \
// RUN: | FileCheck %s -check-prefix=AMDGCN_MATCH_DIAG
// AMDGCN_MATCH_DIAG-NOT: linked binaries do not contain expected