https://github.com/macurtis-amd created
https://github.com/llvm/llvm-project/pull/215532
When linking with `-fopenmp`, `-fopenmp-implicit-rpath` records rpath entries
for the libomp runtime, rather than relying on the runtime being on the default
loader search path. Runtimes selected via `-fopenmp=` are unaffected, as they
are not shipped alongside the compiler.
Feature is off by default (i.e. `-fno-openmp-implicit-rpath`).
`-fopenmp-runtimelib={lib,lib-perf,lib-debug}` is also added which selects an
alternate runtime build and is reflected in the rpath. The selected directory
is added unconditionally; if it is not present, `lib` is added as well, rather
than in its place.
`-fopenmp-runtimelib` is ignored, and its argument is not validated, unless
`-fopenmp-implicit-rpath` is also specified.
>From 32363d00d57c8ba50953e6cf90fae090b87bcc5e Mon Sep 17 00:00:00 2001
From: Matthew Curtis <[email protected]>
Date: Mon, 10 Aug 2026 14:11:59 -0500
Subject: [PATCH] [clang][Driver][OpenMP] Add -f[no-]openmp-implicit-rpath flag
When linking with `-fopenmp`, `-fopenmp-implicit-rpath` records rpath entries
for the libomp runtime, rather than relying on the runtime being on the default
loader search path. Runtimes selected via `-fopenmp=` are unaffected, as they
are not shipped alongside the compiler.
Feature is off by default (i.e. `-fno-openmp-implicit-rpath`).
`-fopenmp-runtimelib={lib,lib-perf,lib-debug}` is also added which selects an
alternate runtime build and is reflected in the rpath. The selected directory
is added unconditionally; if it is not present, `lib` is added as well, rather
than in its place.
`-fopenmp-runtimelib` is ignored, and its argument is not validated, unless
`-fopenmp-implicit-rpath` is also specified.
Co-authored-by: Cursor <[email protected]>
---
clang/include/clang/Driver/CommonArgs.h | 3 +
clang/include/clang/Options/Options.td | 8 +++
clang/lib/Driver/ToolChains/CommonArgs.cpp | 79 ++++++++++++++++++++++
clang/test/Driver/openmp-runtimelib.c | 51 ++++++++++++++
4 files changed, 141 insertions(+)
create mode 100644 clang/test/Driver/openmp-runtimelib.c
diff --git a/clang/include/clang/Driver/CommonArgs.h
b/clang/include/clang/Driver/CommonArgs.h
index 01e358a1d0717..166e093f3e5a4 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -143,6 +143,9 @@ void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
void addOpenMPRuntimeLibraryPath(const ToolChain &TC,
diff --git a/clang/include/clang/Options/Options.td
b/clang/include/clang/Options/Options.td
index b354a475346df..968d0402b5bf3 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4208,6 +4208,10 @@ def fopenmp_cuda_teams_reduction_recs_num_EQ :
Joined<["-"], "fopenmp-cuda-teams
"teams; this flag is accepted for backwards compatibility only "
"and emits a deprecation warning when used.">;
+def fopenmp_runtimelib_EQ : Joined<["-"], "fopenmp-runtimelib=">,
Group<f_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
Flags<[NoArgumentUnused]>,
+ HelpText<"Select lib, lib-perf, or lib-debug openmp runtime"
+ " <arg> must be: lib, lib-perf or lib-debug.">;
+
//===----------------------------------------------------------------------===//
// Shared cc1 + fc1 OpenMP Target Options
//===----------------------------------------------------------------------===//
@@ -6742,6 +6746,10 @@ def no_offload_add_rpath: Flag<["--"],
"no-offload-add-rpath">,
Alias<frtlib_add_rpath>;
def r : Flag<["-"], "r">, Flags<[LinkerInput, NoArgumentUnused]>,
Group<Link_Group>;
+defm openmp_implicit_rpath : BoolOptionWithoutMarshalling<"f",
"openmp-implicit-rpath",
+ PosFlag<SetTrue, [], [ClangOption], "Set rpath implicitly on OpenMP
executables">,
+ NegFlag<SetFalse, [], [ClangOption], "Do not set rpath implicitly on OpenMP
executables">,
+ BothFlags<[NoArgumentUnused]>>, Group<f_Group>;
def regcall4 : Flag<["-"], "regcall4">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Set __regcall4 as a default calling convention to respect
__regcall ABI v.4">,
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 883296e43111b..0e462b92a514f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -68,6 +68,23 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+static bool addRPathCmdArg(const llvm::opt::ArgList &Args,
+ ArgStringList &CmdArgs,
+ const std::string pathCandidate,
+ bool onlyIfPathExists = true) {
+ SmallString<0> simplifiedPathCandidate(pathCandidate);
+ llvm::sys::path::remove_dots(simplifiedPathCandidate, true);
+
+ bool pathExists = llvm::sys::fs::exists(simplifiedPathCandidate);
+
+ if (onlyIfPathExists && !pathExists)
+ return false;
+
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back(Args.MakeArgString(simplifiedPathCandidate));
+ return pathExists;
+}
+
OffloadJobsOpt tools::parseOffloadJobs(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_offload_jobs_EQ);
if (!A)
@@ -1452,6 +1469,65 @@ void tools::addLTOOptions(const ToolChain &ToolChain,
const ArgList &Args,
addDTLTOOptions(ToolChain, Args, CmdArgs);
}
+void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!Args.hasFlag(options::OPT_fopenmp_implicit_rpath,
+ options::OPT_fno_openmp_implicit_rpath, false))
+ return;
+
+ const Driver &D = TC.getDriver();
+ std::string LibSuffix = "lib";
+ if (TC.getSanitizerArgs(Args).needsAsanRt())
+ LibSuffix.append("/asan");
+ if (Arg *A = Args.getLastArg(options::OPT_fopenmp_runtimelib_EQ)) {
+ LibSuffix = A->getValue();
+ if (LibSuffix != "lib-perf" && LibSuffix != "lib-debug" &&
+ LibSuffix != "lib")
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << LibSuffix;
+ if (TC.getSanitizerArgs(Args).needsAsanRt())
+ LibSuffix.append("/asan");
+ }
+
+ // Add an rpath entry for each existing LIBRARY_PATH directory.
+ ArgStringList EnvLibraryPaths;
+ addDirectoryList(Args, EnvLibraryPaths, "", "LIBRARY_PATH");
+ for (auto &EnvLibraryPath : EnvLibraryPaths)
+ addRPathCmdArg(Args, CmdArgs, EnvLibraryPath);
+
+ // Default to clang lib / lib64 folder, i.e. the same location as device
+ // runtime
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
+ if (TC.getSanitizerArgs(Args).needsAsanRt())
+ addRPathCmdArg(Args, CmdArgs, TC.getCompilerRTPath(),
+ /*onlyIfPathExists=*/false);
+
+ // In case LibSuffix was not built, try lib
+ std::string CandidateRPath_suf = D.Dir + "/../" + LibSuffix;
+ // Add lib directory in case LibSuffix does not exist
+ std::string CandidateRPath_lib = D.Dir + "/../lib";
+ if (!addRPathCmdArg(Args, CmdArgs, CandidateRPath_suf,
+ /*onlyIfPathExists=*/false))
+ addRPathCmdArg(Args, CmdArgs, CandidateRPath_lib);
+
+ std::string rocmPath =
+ Args.getLastArgValue(clang::options::OPT_rocm_path_EQ).str();
+ if (rocmPath.size() != 0) {
+ std::string rocmPath_lib = rocmPath + "/lib";
+ std::string rocmPath_suf = rocmPath + "/" + LibSuffix;
+ if (!addRPathCmdArg(Args, CmdArgs, rocmPath_suf))
+ addRPathCmdArg(Args, CmdArgs, rocmPath_lib);
+ }
+
+ // Add Default lib path to ensure llvm dynamic library is picked up for
+ // lib-debug/lib-perf
+ if (LibSuffix != "lib")
+ addRPathCmdArg(Args, CmdArgs, DefaultLibPath.c_str());
+}
+
void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
const ArgList &Args,
ArgStringList &CmdArgs) {
@@ -1538,6 +1614,9 @@ bool tools::addOpenMPRuntime(const Compilation &C,
ArgStringList &CmdArgs,
addArchSpecificRPath(TC, Args, CmdArgs);
+ if (RTKind == Driver::OMPRT_OMP)
+ addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
+
addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
return true;
diff --git a/clang/test/Driver/openmp-runtimelib.c
b/clang/test/Driver/openmp-runtimelib.c
new file mode 100644
index 0000000000000..2d7d09029d050
--- /dev/null
+++ b/clang/test/Driver/openmp-runtimelib.c
@@ -0,0 +1,51 @@
+// REQUIRES: amdgpu-registered-target
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib-debug %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Debug,Debug-Rel %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib-perf %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Perf,Perf-Rel %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Devel,Devel-Rel %s
+
+// RUN: not %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a
-fopenmp-implicit-rpath -fopenmp-runtimelib=oopsy %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Error %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a:xnack+
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib-debug -fsanitize=address
-shared-libasan %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Asan-Debug,Asan-Debug-Rel %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a:xnack+
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib -fsanitize=address
-shared-libasan %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Asan-Devel,Asan-Devel-Rel %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a:xnack+
-fopenmp-implicit-rpath -fopenmp-runtimelib=lib-perf -fsanitize=address
-shared-libasan %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=Asan-Perf,Asan-Perf-Rel %s
+
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a
-fno-openmp-implicit-rpath %s -O3 2>&1 \
+// RUN: | FileCheck -check-prefixes=No-Rpath %s
+
+// Default is -fno-openmp-implicit-rpath
+// RUN: %clang -### -fopenmp -nogpuinc -nogpulib --offload-arch=gfx90a %s -O3
2>&1 \
+// RUN: | FileCheck -check-prefixes=No-Rpath %s
+
+// Devel: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib]]"
+// Devel-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// Debug: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib-debug]]"
+// Debug-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// Perf: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib-perf]]"
+// Perf-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// Asan-Devel: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib(/|\\\\)asan]]"
+// Asan-Devel-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// Asan-Debug: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib-debug(/|\\\\)asan]]"
+// Asan-Debug-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// Asan-Perf: "-rpath" "{{[^"]*}}[[LIB:(/|\\\\)lib-perf(/|\\\\)asan]]"
+// Asan-Perf-Rel-NOT: "-rpath" "{{[^"]*(/|\\\\)\.\.}}[[LIB]]"
+
+// No-Rpath-NOT: "-rpath"
+
+// Error: clang: error: unsupported argument 'oopsy' to option
'-fopenmp-runtimelib='
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits