From e7219557e61e03d59db89346cf43a53e103973ed Mon Sep 17 00:00:00 2001 From: "Toguchi, Michael D" Date: Wed, 6 Feb 2019 16:48:06 +0300 Subject: [PATCH] [SYCL] Add support for -fsycl-use-bitcode -fsycl-use-bitcode is used to generate .bc files during device code generation instead of the default SPIR-V binary. The .bc files will also be bundled into the fat object, so -fsycl-use-bitcode is required upon usage of those objects. Used with -fsycl compilations. Signed-off-by: Toguchi, Michael D Signed-off-by: Vladimir Lazarev --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 4 ++++ clang/lib/CodeGen/BackendUtil.cpp | 7 ++++++- clang/lib/Driver/ToolChains/Clang.cpp | 4 ++++ clang/lib/Driver/ToolChains/SYCL.cpp | 16 ++++++++++++---- clang/lib/Frontend/CompilerInvocation.cpp | 2 ++ clang/test/CodeGenSYCL/spir-no-deref-attr.cpp | 2 +- clang/test/Driver/sycl-offload.c | 18 ++++++++++++++++-- sycl/doc/GetStartedWithSYCLCompiler.md | 2 +- sycl/test/aot/with-llvm-bc.cpp | 1 - sycl/test/separate-compile/test.cpp | 4 ++-- 11 files changed, 49 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index e4a7988967a6d..5862c3bf5c6ca 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -216,6 +216,7 @@ LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code") LANGOPT(SYCL , 1, 0, "Generate code for SYCL device") +LANGOPT(SYCLUseBitcode , 1, 0, "Generate bitcode for SYCL") LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f48702718637c..e149448de0e3c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1701,6 +1701,10 @@ def fsycl_add_targets_EQ : CommaJoined<["-"], "fsycl-add-targets=">, Flags<[Driv HelpText<"Specify comma-separated list of triple and device binary image pairs to add to the final SYCL binary">; def fsycl_link_targets_EQ : CommaJoined<["-"], "fsycl-link-targets=">, Flags<[DriverOption, CC1Option]>, HelpText<"Specify comma-separated list of triples SYCL offloading targets to produce linked device images">; +def fsycl_use_bitcode : Flag<["-"], "fsycl-use-bitcode">, + Flags<[CC1Option]>, HelpText<"Use LLVM bitcode instead of SPIR-V in fat objects">; +def fno_sycl_use_bitcode : Flag<["-"], "fno-sycl-use-bitcode">, + Flags<[CC1Option]>, HelpText<"Use SPIR-V instead of LLVM bitcode in fat objects">; def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[DriverOption,CoreOption,CC1Option]>, Group; def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index b6ff9044f8251..365d96ead65e8 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -855,6 +855,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, case Backend_EmitSPIRV: if (LangOpts.SYCL) { + // TODO: SPIRVNoDerefAttr is not modeled when using the bitcode pass SPIRV::SPIRVNoDerefAttr = true; // TODO: this pass added to work around missing linkonce_odr in SPIR-V PerModulePasses.add( @@ -862,7 +863,11 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, PerModulePasses.add(createASFixerPass()); PerModulePasses.add(createDeadCodeEliminationPass()); } - PerModulePasses.add(createSPIRVWriterPass(*OS)); + if (LangOpts.SYCLUseBitcode) + PerModulePasses.add( + createBitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, false)); + else + PerModulePasses.add(createSPIRVWriterPass(*OS)); break; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 11bf7ab7d433a..dd2e214175f73 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3523,6 +3523,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-aux-triple"); CmdArgs.push_back(Args.MakeArgString(NormalizedTriple)); CmdArgs.push_back("-disable-llvm-passes"); + if (Args.hasFlag(options::OPT_fsycl_use_bitcode, + options::OPT_fno_sycl_use_bitcode, true)) { + CmdArgs.push_back("-fsycl-use-bitcode"); + } } if (IsOpenMPDevice) { diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp index d0b0ca40bfb8d..644641ef45cbe 100644 --- a/clang/lib/Driver/ToolChains/SYCL.cpp +++ b/clang/lib/Driver/ToolChains/SYCL.cpp @@ -40,6 +40,7 @@ const char *SYCL::Linker::constructLLVMSpirvCommand(Compilation &C, CmdArgs.push_back("-o"); CmdArgs.push_back(OutputFileName); } else { + CmdArgs.push_back("-spirv-no-deref-attr"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } @@ -87,7 +88,8 @@ void SYCL::Linker::constructLlcCommand(Compilation &C, const JobAction &JA, } // For SYCL the inputs of the linker job are SPIR-V binaries and output is -// a single SPIR-V binary. +// a single SPIR-V binary. Input can also be bitcode when specified by +// the user void SYCL::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -110,9 +112,15 @@ void SYCL::Linker::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &II : Inputs) { if (!II.isFilename()) continue; - const char *LLVMSpirvOutputFile = - constructLLVMSpirvCommand(C, JA, Output, Prefix, true, II.getFilename()); - SpirvInputs.push_back(LLVMSpirvOutputFile); + if (Args.hasFlag(options::OPT_fsycl_use_bitcode, + options::OPT_fno_sycl_use_bitcode, true)) + SpirvInputs.push_back(II.getFilename()); + else { + const char *LLVMSpirvOutputFile = + constructLLVMSpirvCommand(C, JA, Output, Prefix, true, + II.getFilename()); + SpirvInputs.push_back(LLVMSpirvOutputFile); + } } const char *LLVMLinkOutputFile = constructLLVMLinkCommand(C, JA, SubArchName, Prefix, SpirvInputs); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d85a05ca5b3ca..a30c034f5eea6 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2883,6 +2883,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } Opts.SYCL = Args.hasArg(options::OPT_fsycl_is_device); + Opts.SYCLUseBitcode = Args.hasFlag(options::OPT_fsycl_use_bitcode, + options::OPT_fno_sycl_use_bitcode, false); // Set CUDA mode for OpenMP target NVPTX if specified in options Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() && diff --git a/clang/test/CodeGenSYCL/spir-no-deref-attr.cpp b/clang/test/CodeGenSYCL/spir-no-deref-attr.cpp index 0fe8af83a6ad8..c87230d281525 100644 --- a/clang/test/CodeGenSYCL/spir-no-deref-attr.cpp +++ b/clang/test/CodeGenSYCL/spir-no-deref-attr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -disable-llvm-passes -S -emit-spirv -x c++ %s -o %t.spv +// RUN: %clang_cc1 -fno-sycl-use-bitcode -triple spir64-unknown-linux-sycldevice -std=c++11 -fsycl-is-device -disable-llvm-passes -S -emit-spirv -x c++ %s -o %t.spv // RUN: llvm-spirv %t.spv -to-text -o %t.txt // RUN: FileCheck < %t.txt %s --check-prefix=CHECK diff --git a/clang/test/Driver/sycl-offload.c b/clang/test/Driver/sycl-offload.c index 24587615b854f..8708569f7e4ef 100644 --- a/clang/test/Driver/sycl-offload.c +++ b/clang/test/Driver/sycl-offload.c @@ -69,9 +69,12 @@ /// We should have an offload action joining the host compile and device /// preprocessor and another one joining the device linking outputs to the host /// action. The same graph should be generated when no -fsycl-targets is used +/// The same phase graph will be used with -fsycl-use-bitcode // RUN: %clang -ccc-print-phases -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=spir64-unknown-linux-sycldevice %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES %s -// RUN: %clang -ccc-print-phases -target x86_64-unknown-linux-gnu -fsycl %s 2>&1 \ +// RUN: %clang -ccc-print-phases -target x86_64-unknown-linux-gnu -fsycl -fno-sycl-use-bitcode %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-PHASES %s +// RUN: %clang -ccc-print-phases -target x86_64-unknown-linux-gnu -fsycl -fsycl-use-bitcode %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-PHASES %s // CHK-PHASES: 0: input, "[[INPUT:.+\.c]]", c, (host-sycl) // CHK-PHASES: 1: preprocessor, {0}, cpp-output, (host-sycl) @@ -214,10 +217,20 @@ /// ########################################################################### /// Check -fsycl-is-device is passed when compiling for the device. +/// also check for SPIR-V binary creation // RUN: %clang -### -no-canonical-prefixes -fsycl -fsycl-targets=spir64-unknown-linux-sycldevice %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FSYCL-IS-DEVICE %s -// CHK-FSYCL-IS-DEVICE: clang{{.*}} "-fsycl-is-device" {{.*}}.c +// CHK-FSYCL-IS-DEVICE: clang{{.*}} "-fsycl-is-device" {{.*}} "-emit-spirv" {{.*}}.c + +/// ########################################################################### + +/// Check -fsycl-is-device and emitting to .spv when compiling for the device +/// when using -fno-sycl-use-bitcode +// RUN: %clang -### -fno-sycl-use-bitcode -fsycl -fsycl-targets=spir64-unknown-linux-sycldevice %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-FSYCL-IS-DEVICE-NO-BITCODE %s + +// CHK-FSYCL-IS-DEVICE-NO-BITCODE: clang{{.*}} "-fsycl-is-device" {{.*}} "-emit-spirv" {{.*}}.c /// ########################################################################### @@ -257,3 +270,4 @@ // CHK-ADD-TARGETS-UB: 3: input, "dummy.spv", sycl-fatbin, (device-sycl) // CHK-ADD-TARGETS-UB: 4: clang-offload-wrapper, {3}, object, (device-sycl) // CHK-ADD-TARGETS-UB: 5: offload, "host-sycl (x86_64-unknown-linux-gnu)" {2}, "device-sycl (spir64-unknown-linux-sycldevice)" {4}, image + diff --git a/sycl/doc/GetStartedWithSYCLCompiler.md b/sycl/doc/GetStartedWithSYCLCompiler.md index 8fe8613a342f2..2b749cd62c6a9 100644 --- a/sycl/doc/GetStartedWithSYCLCompiler.md +++ b/sycl/doc/GetStartedWithSYCLCompiler.md @@ -132,7 +132,7 @@ The SYCL Compiler supports two types of compilation: a. Compile the device code from the C++ file into the SPIR-V file: ```bash - clang++ --sycl -Xclang -fsycl-int-header=simple-sycl-app-int-header.h -c simple-sycl-app.cpp -o kernel.spv + clang++ --sycl -fno-sycl-use-bitcode -Xclang -fsycl-int-header=simple-sycl-app-int-header.h -c simple-sycl-app.cpp -o kernel.spv # NOTE: The section "-Xclang -fsycl-int-header=simple-sycl-app-int-header.h" # generates `integration header` file. # This file must be included for the host side compilation. diff --git a/sycl/test/aot/with-llvm-bc.cpp b/sycl/test/aot/with-llvm-bc.cpp index 730876d99de56..e2994eab5172b 100644 --- a/sycl/test/aot/with-llvm-bc.cpp +++ b/sycl/test/aot/with-llvm-bc.cpp @@ -5,7 +5,6 @@ // // Only CPU supports LLVM IR bitcode as a binary // RUN: %CPU_RUN_PLACEHOLDER %t.out -// XFAIL: * //==----- with-llvm-bc.cpp - SYCL kernel with LLVM IR bitcode as binary ----==// // diff --git a/sycl/test/separate-compile/test.cpp b/sycl/test/separate-compile/test.cpp index fb1d108e5cc91..a647131f54d20 100755 --- a/sycl/test/separate-compile/test.cpp +++ b/sycl/test/separate-compile/test.cpp @@ -1,12 +1,12 @@ // >> ---- compile src1 // >> device compilation... -// RUN: %clang -std=c++11 --sycl -Xclang -fsycl-int-header=sycl_ihdr_a.h %s -c -o a_kernel.spv +// RUN: %clang -std=c++11 -fno-sycl-use-bitcode --sycl -Xclang -fsycl-int-header=sycl_ihdr_a.h %s -c -o a_kernel.spv // >> host compilation... // RUN: %clang -std=c++11 -include sycl_ihdr_a.h -g -c %s -o a.o // // >> ---- compile src2 // >> device compilation... -// RUN: %clang -DB_CPP=1 -std=c++11 --sycl -Xclang -fsycl-int-header=sycl_ihdr_b.h %s -c -o b_kernel.spv +// RUN: %clang -DB_CPP=1 -std=c++11 -fno-sycl-use-bitcode --sycl -Xclang -fsycl-int-header=sycl_ihdr_b.h %s -c -o b_kernel.spv // >> host compilation... // RUN: %clang -DB_CPP=1 -std=c++11 -include sycl_ihdr_b.h -g -c %s -o b.o //