Skip to content

Conversation

@YixingZhang007
Copy link
Contributor

@YixingZhang007 YixingZhang007 commented Nov 19, 2025

In another patch #19579, compilation and linking options used in ClangLinkerWrapper are changed to be consumed from the SYCLImage, instead of sycl_backend_compile_options_EQ and sycl_target_link_options_EQ that are passed as argument to the ClangLinkerWrapper. Since the compiler option and linker option passed into ClangLinkerWrapper are no longer useful, this PR remove them to be passed into ClangLinkerWrapper. The specific changes are listed below.

  1. The code for constructing the BackendOptString and LinkOptString and append to the argument for calling ClangLinkerWrapper are removed in Clang.cpp.
  2. Remove gpu_tool_arg_EQ and cpu_tool_arg_EQ options specification in LinkerWrapperOpts.td. We are now passing the link time backend compile option for GPU and CPU through OPT_device_compiler_args_EQ to ClangLinkerWrapper, as coded in Clang.cpp.
  3. In ClangLinkerWrapper.cpp, the option in OPT_device_compiler_args_EQ are added to SYCLBackendOptions and handled together with other compiler option passed through SYCLImage.
  4. Modify the tests that are associated with these changes, such as those that are checking the compiler backend option and linker option passed into ClangLinkerWrapper.

With this patch, the following SYCL E2E tests pass with the new offloading model:

  1. KernelAndProgram/kernel-bundle-merge-options-env.cpp
  2. KernelAndProgram/level-zero-link-flags.cpp
  3. ESIMD/private_memory/pm_access_1.cpp
  4. ESIMD/private_memory/pm_access_2.cpp
  5. ESIMD/private_memory/pm_access_3.cpp

@YixingZhang007 YixingZhang007 requested review from a team as code owners November 19, 2025 18:59
@YixingZhang007 YixingZhang007 marked this pull request as draft November 19, 2025 18:59
@YixingZhang007 YixingZhang007 force-pushed the fix_linker_unrecognized_option_issue branch from 43ec9a6 to 2c3b7bc Compare November 25, 2025 22:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the passing of backend compiler and linker options via --gpu-tool-arg and --cpu-tool-arg arguments to ClangLinkerWrapper. Instead, these options are now consumed directly from SYCLImage metadata using the --device-compiler argument format. The change simplifies the option passing mechanism by consolidating all backend compile options through a single path.

  • Remove obsolete gpu_tool_arg_EQ and cpu_tool_arg_EQ option definitions
  • Refactor option handling in ClangLinkerWrapper to use --device-compiler format instead
  • Update runSYCLPostLinkTool to accept HasGPUTool boolean parameter instead of checking removed option

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td Removes gpu_tool_arg_EQ and cpu_tool_arg_EQ option definitions
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp Updates option processing to use HasGPUTool parameter and adds handling for OPT_device_compiler_args_EQ
clang/lib/Driver/ToolChains/Clang.cpp Refactors argument construction to pass backend options via --device-compiler instead of removed wrapper options
clang/lib/Driver/Driver.cpp Adds GetUseNewOffloadDriverForSYCLOffload utility function to determine when to use new offload driver
clang/include/clang/Driver/Driver.h Declares GetUseNewOffloadDriverForSYCLOffload function
clang/test/Driver/*.cpp Updates test expectations to check for new --device-compiler argument format

@YixingZhang007
Copy link
Contributor Author

YixingZhang007 commented Dec 2, 2025

5 SYCL E2E tests passed (test names are listed in the PR description, and 3 pm_access_n test were only failing in Self Build CI before), and no SYCL E2E test or driver test regression occurred when the new offloading model was enabled as default together with my changes (the CI before removing new offloading changes from this PR can be found at https://github.com/intel/llvm/actions/runs/19864471834/job/56923211306?pr=20691)

@intel intel deleted a comment from Copilot AI Dec 2, 2025
"--device-linker=" + TC->getTripleString() + "=" + Arg));
// SYCL offload toolchains handle device compiler and linker argument forwarding using SYCLImage.
// Therefore, we skip forwarding these arguments here when a SYCL offload toolchain is present.
if (!C.hasOffloadToolChain<Action::OFK_SYCL>()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to avoid this SYCL-specific customization? What happens if we keep this for SYCL as well?
If I understand correctly @mdtoguchi : "The expected behavior is for any device options to be handled at both compile and link time. ", we need to keep this code and pass user-specified options to clang-linker-wrapper same as for any other programming model.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does CompilerArgs and LinkerArgs come from? I mean, is it from some clang++ arguments?


/// Test option passing behavior for clang-offload-wrapper options.
// RUN: %clangxx --target=x86_64-unknown-linux-gnu -fsycl --offload-new-driver \
// RUN: -Xsycl-target-backend -backend-opt -### %s 2>&1 \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my understanding, we still need to pass -backend-opt to clang-linker-wrapper through device-compiler option.
so this test should be just updated to use proper clang-linker-wrapper option.
Similar for linker options.

Copy link
Contributor Author

@YixingZhang007 YixingZhang007 Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out!

I think for backend option and linker option that are passed at compile time, they are stored in the SYCLImage like --image=file=... compile-opts=... -backend-opt. The option that are stored in the SYCLImage got directly extracted in clang-linker-wrapper (this is done is another PR #19579 and extractSYCLCompileLinkOptions function found at https://github.com/YixingZhang007/llvm/blob/fe390ac353c65ec85ccd2b3bf7883a1efca55a5e/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp#L2218).

Only the -backend-opt that are passed at link time for AOT, which should be through format clang++ ... -fsycl-targets=spir64_gen -Xsycl-target-backend=spir64_gen -backend-gen-opt will added to device-compiler and passed to the clang-linker-wrapper.

Therefore, for this test and the one got deleted below, -backend-opt and -link-opt are passed through the SYCLImage but not directly added as argument for clang-linker-wrapper :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I understand how it works with your implementation. And I challenge that. Despite we extracted and put options to SYCLImage on compile stage, we still want to pass these options to link stage as well.
Example of when this is needed is if we provide both source and object files as an input to clang++.


// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl --offload-new-driver -fsycl-targets=spir64-unknown-unknown -Xsycl-target-backend "-DFOO1 -DFOO2" %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-TOOLS-OPTS %s
// CHK-TOOLS-OPTS: clang-linker-wrapper{{.*}} "--sycl-backend-compile-options=-DFOO1 -DFOO2"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar here, per my understanding, need to pass options using device-compiler


// RUN: %clang -### -target x86_64-unknown-linux-gnu -fsycl --offload-new-driver -fsycl-targets=spir64-unknown-unknown -Xsycl-target-linker "-DFOO1 -DFOO2" %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-TOOLS-OPTS2 %s
// CHK-TOOLS-OPTS2: clang-linker-wrapper{{.*}} "--sycl-target-link-options=-DFOO1 -DFOO2"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, but for device-linker

// RUN: | FileCheck -check-prefixes=SYCL_TARGET_OPT %s
// RUN: %clangxx -### -target x86_64-unknown-linux-gnu -fsycl --offload-new-driver -Xsycl-target-backend=spir64 -DFOO -Xsycl-target-linker=spir64 -DFOO2 %S/Inputs/SYCL/objlin64.o 2>&1 \
// RUN: | FileCheck -check-prefixes=SYCL_TARGET_OPT %s
// SYCL_TARGET_OPT: clang-linker-wrapper{{.*}} "--sycl-backend-compile-options=-DFOO" "--sycl-target-link-options=-DFOO2"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here...


SmallVector<StringRef, 16> Args;
StringRef(CompileLinkOptionsOrErr->first).split(Args, ' ');
bool HasGPUTool =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of the variable is a bit confusing to me. Would something like this be better?
IsDevicePassedWithSyclTargetBackend. Maybe a little bit verbose, but maybe it is OK.

static Expected<std::vector<module_split::SplitModule>>
runSYCLPostLinkTool(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
runSYCLPostLinkTool(ArrayRef<StringRef> InputFiles, const ArgList &Args,
bool HasGPUTool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new parameter needs to be documented in comments above

StringRef OptTool = (IsCPU) ? Args.getLastArgValue(OPT_cpu_tool_arg_EQ)
: Args.getLastArgValue(OPT_gpu_tool_arg_EQ);
OptTool.split(CmdArgs, " ", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this return is also unnecessary, right?

}
}

StringRef OptTool = (IsCPU) ? Args.getLastArgValue(OPT_cpu_tool_arg_EQ)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Args parameter is not used anymore in this function and can be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe we need to handle OPT_device_compiler_args_EQ here.
I think it depends on how such options are handled for other programming models. We need to try to be as close as possible to upstream...

Copy link
Contributor Author

@YixingZhang007 YixingZhang007 Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion!

The reason I didn't move the handling of OPT_device_compiler_args_EQ to here is that -device xxx may be passed as a link-time backend argument, and we need to check for that in linkAndWrapDeviceFiles (found at https://github.com/YixingZhang007/llvm/blob/fe390ac353c65ec85ccd2b3bf7883a1efca55a5e/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp#L2250) so that we can determine whether we need to add the device name in front of the output table.

Therefore, to avoid processing OPT_device_compiler_args_EQ twice, I add OPT_device_compiler_args_EQ to CompileLinkOptionsOrErr in linkAndWrapDeviceFiles, and CompileLinkOptionsOrErr is later passed as BackendOptions to this function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, now I see that order of options did not change. So, I guess, just remove the Args param as not used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants