Skip to content

[Driver][SYCL] Improvements to -fsycl-device-only behaviors #2597

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
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
15 changes: 3 additions & 12 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1263,17 +1263,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
T.setObjectFormat(llvm::Triple::COFF);
TargetTriple = T.str();
}
if (Args.hasArg(options::OPT_fsycl_device_only)) {
// -fsycl-device-only implies spir arch and SYCL Device
llvm::Triple T(TargetTriple);
// FIXME: defaults to spir64, should probably have a way to set spir
// possibly new -sycl-target option
T.setArch(llvm::Triple::spir64);
T.setVendor(llvm::Triple::UnknownVendor);
T.setOS(llvm::Triple(llvm::sys::getProcessTriple()).getOS());
T.setEnvironment(llvm::Triple::SYCLDevice);
TargetTriple = T.str();
}
if (const Arg *A = Args.getLastArg(options::OPT_target))
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
Expand Down Expand Up @@ -2384,7 +2373,9 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
// actually use it, so we warn about unused -x arguments.
types::ID InputType = types::TY_Nothing;
Arg *InputTypeArg = nullptr;
bool IsSYCL = Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false);
bool IsSYCL =
Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) ||
Args.hasArg(options::OPT_fsycl_device_only);

// The last /TC or /TP option sets the input type to C or C++ globally.
if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
Expand Down
33 changes: 25 additions & 8 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3978,14 +3978,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args, const char *LinkingOutput) const {
const auto &TC = getToolChain();
const llvm::Triple &RawTriple = TC.getTriple();
const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
llvm::Triple Triple = TC.getEffectiveTriple();

bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
const Driver &D = TC.getDriver();
ArgStringList CmdArgs;

// -fsycl-device-only implies a SPIRV arch triple. Do not set if current
// effective triple is SYCLDevice
if (Args.hasArg(options::OPT_fsycl_device_only) &&
Triple.getEnvironment() != llvm::Triple::SYCLDevice) {
const char *SYCLTargetArch = "spir64";
if (C.getDefaultToolChain().getTriple().getArch() == llvm::Triple::x86)
SYCLTargetArch = "spir";
Triple = C.getDriver().MakeSYCLDeviceTriple(SYCLTargetArch);
}
const std::string &TripleStr = Triple.getTriple();

// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
// CUDA/HIP compilation may have multiple inputs (source file + results of
Expand All @@ -4000,7 +4010,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsSYCLOffloadDevice = JA.isDeviceOffloading(Action::OFK_SYCL);
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL);
bool IsSYCL = JA.isOffloading(Action::OFK_SYCL) ||
Args.hasArg(options::OPT_fsycl_device_only);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || IsSYCL ||
IsHeaderModulePrecompile || Inputs.size() == 1) &&
Expand Down Expand Up @@ -4048,14 +4059,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
(IsSYCL || IsCuda || IsHIP) ? TC.getAuxTriple() : nullptr;
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
bool IsIAMCU = RawTriple.isOSIAMCU();
bool IsSYCLDevice = (RawTriple.getEnvironment() == llvm::Triple::SYCLDevice);
bool IsSYCLDevice = (RawTriple.getEnvironment() == llvm::Triple::SYCLDevice ||
Triple.getEnvironment() == llvm::Triple::SYCLDevice);
// Using just the sycldevice environment is not enough to determine usage
// of the device triple when considering fat static archives. The
// compilation path requires the host object to be fed into the partial link
// step, and being part of the SYCL tool chain causes the incorrect target.
// FIXME - Is it possible to retain host environment when on a target
// device toolchain.
bool UseSYCLTriple = IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice);
bool UseSYCLTriple =
IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice ||
Args.hasArg(options::OPT_fsycl_device_only));

// Adjust IsWindowsXYZ for CUDA/HIP/SYCL compilations. Even when compiling in
// device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
Expand Down Expand Up @@ -4144,7 +4158,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_sycl_early_optimizations,
Triple.getSubArch() != llvm::Triple::SPIRSubArch_fpga))
CmdArgs.push_back("-fno-sycl-early-optimizations");
else if (RawTriple.isSPIR()) {
else if (IsSYCLDevice) {
// Set `sycl-opt` option to configure LLVM passes for SPIR target
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-sycl-opt");
Expand All @@ -4157,7 +4171,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,

// Pass the triple of host when doing SYCL
llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
if (Args.hasFlag(options::OPT_fsycl_device_only, OptSpecifier(), false))
if (Args.hasArg(options::OPT_fsycl_device_only) &&
RawTriple.getEnvironment() == llvm::Triple::SYCLDevice)
AuxT = llvm::Triple(llvm::sys::getProcessTriple());
std::string NormalizedTriple = AuxT.normalize();
CmdArgs.push_back("-aux-triple");
Expand Down Expand Up @@ -6812,6 +6827,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
unsigned RTOptionID = options::OPT__SLASH_MT;
bool isNVPTX = getToolChain().getTriple().isNVPTX();
bool isSYCLDevice =
Args.hasArg(options::OPT_fsycl_device_only) ||
getToolChain().getTriple().getEnvironment() == llvm::Triple::SYCLDevice;
bool isSYCL = Args.hasArg(options::OPT_fsycl) || isSYCLDevice;
// For SYCL Windows, /MD is the default.
Expand Down Expand Up @@ -7823,7 +7839,8 @@ void SPIRVTranslator::ConstructJob(Compilation &C, const JobAction &JA,

TranslatorArgs.push_back("-o");
TranslatorArgs.push_back(Output.getFilename());
if (getToolChain().getTriple().isSYCLDeviceEnvironment()) {
if (getToolChain().getTriple().isSYCLDeviceEnvironment() ||
TCArgs.hasArg(options::OPT_fsycl_device_only)) {
TranslatorArgs.push_back("-spirv-max-version=1.1");
TranslatorArgs.push_back("-spirv-debug-info-version=legacy");
// Prevent crash in the translator if input IR contains DIExpression
Expand Down
18 changes: 16 additions & 2 deletions clang/test/Driver/sycl.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
// DEFAULT: "-triple" "spir64-unknown-{{.*}}-sycldevice{{.*}}" "-fsycl-is-device"{{.*}} "-emit-llvm-bc"
// DEFAULT: "-internal-isystem" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}sycl"
// DEFAULT: "-internal-isystem" "{{.*lib.*clang.*include}}"
// DEFAULT: "-std=c++17"
// DEFAULT-NOT: "{{.*}}llvm-spirv"{{.*}} "-spirv-max-version=1.1"{{.*}} "-spirv-ext=+all,-SPV_INTEL_usm_storage_classes"
// DEFAULT-NOT: "-std=c++11"
// DEFAULT-NOT: "-std=c++14"
Expand All @@ -49,15 +50,28 @@
// COMBINED: "-triple" "spir64-unknown-{{.*}}-sycldevice"{{.*}} "-fsycl-is-device"{{.*}} "-emit-llvm-bc"
// TEXTUAL: "-triple" "spir64-unknown-{{.*}}-sycldevice{{.*}}" "-fsycl-is-device"{{.*}} "-emit-llvm"

/// -fsycl-device-only triple checks
// RUN: %clang -fsycl-device-only -target x86_64-unknown-linux-gnu -### %s 2>&1 \
// RUN: | FileCheck --check-prefix=DEVICE-64 %s
// RUN: %clang_cl -fsycl-device-only --target=x86_64-unknown-linux-gnu -### %s 2>&1 \
// RUN: | FileCheck --check-prefix=DEVICE-64 %s
// DEVICE-64: clang{{.*}} "-triple" "spir64-unknown-unknown-sycldevice" {{.*}} "-aux-triple" "x86_64-unknown-linux-gnu"

// RUN: %clang -fsycl-device-only -target i386-unknown-linux-gnu -### %s 2>&1 \
// RUN: | FileCheck --check-prefix=DEVICE-32 %s
// RUN: %clang_cl -fsycl-device-only --target=i386-unknown-linux-gnu -### %s 2>&1 \
// RUN: | FileCheck --check-prefix=DEVICE-32 %s
// DEVICE-32: clang{{.*}} "-triple" "spir-unknown-unknown-sycldevice" {{.*}} "-aux-triple" "i386-unknown-linux-gnu"

/// Verify that the sycl header directory is before /usr/include
// RUN: %clangxx -### -fsycl-device-only %s 2>&1 | FileCheck %s --check-prefix=HEADER_ORDER
// RUN: %clangxx -### -fsycl %s 2>&1 | FileCheck %s --check-prefix=HEADER_ORDER
// HEADER_ORDER-NOT: clang{{.*}} "/usr/include"{{.*}} "-internal-isystem" "{{.*}}bin{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}

/// Verify -fsycl-device-only phases
// RUN: %clang -### -ccc-print-phases -fsycl-device-only %s 2>&1 | FileCheck %s --check-prefix=DEFAULT-PHASES
// DEFAULT-PHASES: 0: input, "{{.*}}", c
// DEFAULT-PHASES: 1: preprocessor, {0}, cpp-output
// DEFAULT-PHASES: 0: input, "{{.*}}", c++
// DEFAULT-PHASES: 1: preprocessor, {0}, c++-cpp-output
// DEFAULT-PHASES: 2: compiler, {1}, ir
// DEFAULT-PHASES: 3: backend, {2}, ir
// DEFAULT-PHASES-NOT: linker
Expand Down