Skip to content
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

[OpenMP] Respect LLVM per-target install directories #83282

Merged
merged 1 commit into from
Feb 28, 2024

Conversation

jhuber6
Copy link
Contributor

@jhuber6 jhuber6 commented Feb 28, 2024

Summary:
One recurring problem we have with the OpenMP libraries is that they are
potentially conflicting with ones found on the system, this occurs when
there are two copies and one is used for linking that it not attached to
the correspoding clang compiler. LLVM already uses target specific
directories for this, like with libc++, which are always searched first.
This patch changes the install directory to be
lib/x86_64-unknown-linux-gnu for example.

Notable changes would be that users will need to change their
LD_LIBRARY_PATH settings optionally, or use default rt-rpath options.
This should fix problems were users are linking the wrong versions of
static libraries

Summary:
One recurring problem we have with the OpenMP libraries is that they are
potentially conflicting with ones found on the system, this occurs when
there are two copies and one is used for linking that it not attached to
the correspoding clang compiler. LLVM already uses target specific
directories for this, like with libc++, which are always searched first.
This patch changes the install directory to be
`lib/x86_64-unknown-linux-gnu` for example.

Notable changes would be that users will need to change their
LD_LIBRARY_PATH settings optionally, or use default rt-rpath options.
This should fix problems were users are linking the wrong versions of
static libraries
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' openmp:libomp OpenMP host runtime openmp:libomptarget OpenMP offload runtime labels Feb 28, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Feb 28, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Joseph Huber (jhuber6)

Changes

Summary:
One recurring problem we have with the OpenMP libraries is that they are
potentially conflicting with ones found on the system, this occurs when
there are two copies and one is used for linking that it not attached to
the correspoding clang compiler. LLVM already uses target specific
directories for this, like with libc++, which are always searched first.
This patch changes the install directory to be
lib/x86_64-unknown-linux-gnu for example.

Notable changes would be that users will need to change their
LD_LIBRARY_PATH settings optionally, or use default rt-rpath options.
This should fix problems were users are linking the wrong versions of
static libraries


Full diff: https://github.com/llvm/llvm-project/pull/83282.diff

4 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+5-5)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.h (+2-1)
  • (modified) clang/lib/Driver/ToolChains/Cuda.cpp (+1-1)
  • (modified) openmp/CMakeLists.txt (+9-3)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index faceee85a2f8dc..382c8b3612a0af 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2763,13 +2763,13 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
                                const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args,
                                StringRef BitcodeSuffix,
-                               const llvm::Triple &Triple) {
+                               const llvm::Triple &Triple,
+                               const ToolChain &HostTC) {
   SmallVector<StringRef, 8> LibraryPaths;
 
-  // Add path to clang lib / lib64 folder.
-  SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
-  llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
-  LibraryPaths.emplace_back(DefaultLibPath.c_str());
+  // Check all of the standard library search paths used by the compiler.
+  for (const auto &LibPath : HostTC.getFilePaths())
+    LibraryPaths.emplace_back(LibPath);
 
   // Add user defined library paths from LIBRARY_PATH.
   std::optional<std::string> LibPath =
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 2db0f889ca8209..b8f649aab4bdd2 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -214,7 +214,8 @@ void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args,
 
 void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
                         llvm::opt::ArgStringList &CC1Args,
-                        StringRef BitcodeSuffix, const llvm::Triple &Triple);
+                        StringRef BitcodeSuffix, const llvm::Triple &Triple,
+                        const ToolChain &HostTC);
 
 void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
                            const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index ff3687ca7dae33..177fd6310e7ee2 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -903,7 +903,7 @@ void CudaToolChain::addClangTargetOptions(
       return;
 
     addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
-                       getTriple());
+                       getTriple(), HostTC);
   }
 }
 
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index 03068af22629f7..3c4ff76ad6d161 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -46,9 +46,15 @@ if (OPENMP_STANDALONE_BUILD)
   set(CMAKE_CXX_EXTENSIONS NO)
 else()
   set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
-  # If building in tree, we honor the same install suffix LLVM uses.
-  set(OPENMP_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}" CACHE STRING
-      "Path where built OpenMP libraries should be installed.")
+
+  # When building in tree we install the runtime according to the LLVM settings.
+  if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
+    set(OPENMP_INSTALL_LIBDIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING
+        "Path where built openmp libraries should be installed.")
+  else()
+    set(OPENMP_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}" CACHE STRING
+        "Path where built OpenMP libraries should be installed.")
+  endif()
 
   if (NOT MSVC)
     set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)

SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
LibraryPaths.emplace_back(DefaultLibPath.c_str());
// Check all of the standard library search paths used by the compiler.
Copy link
Member

Choose a reason for hiding this comment

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

clang/test/Driver/linux-cross.cpp has examples how to test -L.

@jhuber6 jhuber6 merged commit 1977404 into llvm:main Feb 28, 2024
9 checks passed
@bjope
Copy link
Collaborator

bjope commented Mar 1, 2024

Hi @jhuber6, @MaskRay

We are having some problems with this patch on a server where the file /lib64/libomptarget-nvptx-sm_52.bc exists.
The test case that fails is clang/test/Driver/openmp-offload-gpu.c.

Problem 1
I think one problem is related to this check line
// CHK-ENV-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|\\\\}}libomptarget-nvptx-sm_52.bc
That test is using env LIBRARY_PATH but your changes in tools::addOpenMPDeviceRTL makes it prioritize the standard library paths before the environment. Not sure if that is how it should be or if env should have higher prio (i.e. added to LibraryPaths before the paths found in HostTC).

Problem 2
This check line also started failing:
// CHK-BCLIB-WARN: no library 'libomptarget-nvptx-sm_52.bc' found in the default clang lib directory or in LIBRARY_PATH; use '--libomptarget-nvptx-bc-path' to specify nvptx bitcode library

Now, with your path, I guess it starts picking up the /lib64/libomptarget-nvptx-sm_52.bc file from the system. So we no longer get the warning. Is that the intention with your patch? Regardless, I think you need to do something with that test case because I think the "should never exist" part in

/// Check that the warning is thrown when the libomptarget bitcode library is not found.
/// Libomptarget requires sm_52 or newer so an sm_52 bitcode library should never exist.

no longer holds with your patch.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 1, 2024

Hi @jhuber6, @MaskRay

We are having some problems with this patch on a server where the file /lib64/libomptarget-nvptx-sm_52.bc exists. The test case that fails is clang/test/Driver/openmp-offload-gpu.c.

Problem 1 I think one problem is related to this check line // CHK-ENV-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|\\\\}}libomptarget-nvptx-sm_52.bc That test is using env LIBRARY_PATH but your changes in tools::addOpenMPDeviceRTL makes it prioritize the standard library paths before the environment. Not sure if that is how it should be or if env should have higher prio (i.e. added to LibraryPaths before the paths found in HostTC).

Problem 2 This check line also started failing: // CHK-BCLIB-WARN: no library 'libomptarget-nvptx-sm_52.bc' found in the default clang lib directory or in LIBRARY_PATH; use '--libomptarget-nvptx-bc-path' to specify nvptx bitcode library

Now, with your path, I guess it starts picking up the /lib64/libomptarget-nvptx-sm_52.bc file from the system. So we no longer get the warning. Is that the intention with your patch? Regardless, I think you need to do something with that test case because I think the "should never exist" part in

/// Check that the warning is thrown when the libomptarget bitcode library is not found.
/// Libomptarget requires sm_52 or newer so an sm_52 bitcode library should never exist.

no longer holds with your patch.

I think it's standard to prioritize library path stuff. Does this work if you just flip the order we fill the library search path? I think the behavioral change here is that we didn't used to look in the system directory.

@bjope
Copy link
Collaborator

bjope commented Mar 1, 2024

Problem 1 can be solved by flipping the order.
But Problem 2 would remain as it doesn't depend on the order.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 1, 2024

Problem 1 can be solved by flipping the order. But Problem 2 would remain as it doesn't depend on the order.

Honestly, we should just remove the second test. We just treat these things as libraries and it doesn't make sense for a test to ensure that -lstdc++ doesn't exist on the user's system or whatever.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 1, 2024

Problem 1 can be solved by flipping the order. But Problem 2 would remain as it doesn't depend on the order.

#83573 I made a patch to fix it.

@ye-luo
Copy link
Contributor

ye-luo commented Mar 1, 2024

yeluo@epyc-server:/soft/llvm/main-20240301/lib$ ls libomp* -l
lrwxrwxrwx 1 yeluo yeluo       34 Mar  1 11:18 libomptarget.rtl.amdgpu.so -> libomptarget.rtl.amdgpu.so.19.0git
-r--r--r-- 1 yeluo yeluo 67532024 Mar  1 11:04 libomptarget.rtl.amdgpu.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       32 Mar  1 11:18 libomptarget.rtl.cuda.so -> libomptarget.rtl.cuda.so.19.0git
-r--r--r-- 1 yeluo yeluo 67440504 Mar  1 11:04 libomptarget.rtl.cuda.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       34 Mar  1 11:18 libomptarget.rtl.x86_64.so -> libomptarget.rtl.x86_64.so.19.0git
-r--r--r-- 1 yeluo yeluo 67349472 Mar  1 11:04 libomptarget.rtl.x86_64.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       23 Mar  1 11:18 libomptarget.so -> libomptarget.so.19.0git
-r--r--r-- 1 yeluo yeluo  2686592 Mar  1 11:04 libomptarget.so.19.0git

Should libomptarget follow the relocation of libomp?

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 1, 2024

yeluo@epyc-server:/soft/llvm/main-20240301/lib$ ls libomp* -l
lrwxrwxrwx 1 yeluo yeluo       34 Mar  1 11:18 libomptarget.rtl.amdgpu.so -> libomptarget.rtl.amdgpu.so.19.0git
-r--r--r-- 1 yeluo yeluo 67532024 Mar  1 11:04 libomptarget.rtl.amdgpu.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       32 Mar  1 11:18 libomptarget.rtl.cuda.so -> libomptarget.rtl.cuda.so.19.0git
-r--r--r-- 1 yeluo yeluo 67440504 Mar  1 11:04 libomptarget.rtl.cuda.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       34 Mar  1 11:18 libomptarget.rtl.x86_64.so -> libomptarget.rtl.x86_64.so.19.0git
-r--r--r-- 1 yeluo yeluo 67349472 Mar  1 11:04 libomptarget.rtl.x86_64.so.19.0git
lrwxrwxrwx 1 yeluo yeluo       23 Mar  1 11:18 libomptarget.so -> libomptarget.so.19.0git
-r--r--r-- 1 yeluo yeluo  2686592 Mar  1 11:04 libomptarget.so.19.0git

Should libomptarget follow the relocation of libomp?

That's surprising. Maybe this is interacting incorrectly with the fact that we build these as LLVM libs?

@ye-luo
Copy link
Contributor

ye-luo commented Mar 1, 2024

It seems being installed twice both under lib and lib/x86_64-unknown-linux-gnu. files are the identical as diff show nothing.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 1, 2024

It seems being installed twice both under lib and lib/x86_64-unknown-linux-gnu. files are the identical as diff show nothing.

Makes sense, like add_llvm_library is implicitly installing it there, then our subsequent install call is doing it again. I wonder if there's a way to change that.

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

@jhuber6 unfortunately after 2fb764d

ls /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl*
/soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so          /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.x86_64.so
/soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so.19.0git  /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.x86_64.so.19.0git

amdgpu plut is missing.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 5, 2024

@jhuber6 unfortunately after 2fb764d

ls /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl*
/soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so          /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.x86_64.so
/soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so.19.0git  /soft/compilers/llvm/master-nightly/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.x86_64.so.19.0git

amdgpu plut is missing.

This is confusing. I have it in my local install no problem and the install code is pretty much the exact same between the CUDA and AMDGPU plugins. Can you share what CMake you're using?

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

Still a myth on my side, I saw

[ 89%] Linking CXX shared library ../../../../../lib/libomptarget.rtl.cuda.so
[ 90%] Linking CXX shared library ../../../../../lib/libomptarget.rtl.amdgpu.so
...
-- Installing: /soft/compilers/llvm/main-20240305/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so.19.0git
-- Set runtime path of "/soft/compilers/llvm/main-20240305/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so.19.0git" to "$ORIGIN"
-- Installing: /soft/compilers/llvm/main-20240305/lib/x86_64-unknown-linux-gnu/libomptarget.rtl.cuda.so

but there is no installing of the rtl.amdgpu.so. I'm building llvm on a different machine.

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

@jhuber6 could you build openmp as a project instead of runtime?

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 5, 2024

@jhuber6 could you build openmp as a project instead of runtime?

Ah, I could try that. Though I believe that Johannes is going to completely deprecate the projects build once moving to llvm/offload.

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

@jhuber6 could you build openmp as a project instead of runtime?

Ah, I could try that. Though I believe that Johannes is going to completely deprecate the projects build once moving to llvm/offload.

@jdoerfert I would like to see the device code compilation (on device runtime) and host runtime compilation fully separate. Then I can build the runtime with gcc or sanitizer without disturbing device code compilation.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 5, 2024

@jdoerfert I would like to see the device code compilation (on device runtime) and host runtime compilation fully separate. Then I can build the runtime with gcc or sanitizer without disturbing device code compilation.

Could you elaborate on this? One of my long-term goals is to build the OpenMP device runtime similarly to how I build the GPU C library. That is, we have a runtimes build that simply does --target=amdgcn-amd-amdhsa on C/C++ source using standard clang. We could maybe split this out into a separate runtime and declare the offloading runtime on the CPU to be a project instead?

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

@jdoerfert I would like to see the device code compilation (on device runtime) and host runtime compilation fully separate. Then I can build the runtime with gcc or sanitizer without disturbing device code compilation.

Could you elaborate on this? One of my long-term goals is to build the OpenMP device runtime similarly to how I build the GPU C library. That is, we have a runtimes build that simply does --target=amdgcn-amd-amdhsa on C/C++ source using standard clang. We could maybe split this out into a separate runtime and declare the offloading runtime on the CPU to be a project instead?

I need a clean way to add -fsantize=address to the libomptarget host runtime and plugins compilation without disturbing the device compilation. So if you move all the device compilation to a separate runtime, it also achieves my goal I guess.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 5, 2024

@jdoerfert I would like to see the device code compilation (on device runtime) and host runtime compilation fully separate. Then I can build the runtime with gcc or sanitizer without disturbing device code compilation.

Could you elaborate on this? One of my long-term goals is to build the OpenMP device runtime similarly to how I build the GPU C library. That is, we have a runtimes build that simply does --target=amdgcn-amd-amdhsa on C/C++ source using standard clang. We could maybe split this out into a separate runtime and declare the offloading runtime on the CPU to be a project instead?

I need a clean way to add -fsantize=address to the libomptarget host runtime and plugins compilation without disturbing the device compilation. So if you move all the device compilation to a separate runtime, it also achieves my goal I guess.

We could potentially do what I do with the libc target and treat it as cross compiling. So we'd have the "CPU" and "GPU" runtimes that go off of a switch depending on the architecture. CMake would look something like

   -DLLVM_ENABLE_RUNTIMES="openmp"                                      \
   -DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=openmp             \
   -DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=openmp               \
   -DLLVM_RUNTIME_TARGETS=default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

Could you explain what each line does exactly?

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 5, 2024

Could you explain what each line does exactly?

This is hypothetical, but it's a potential way to keep it from having a separate project
-DLLVM_RUNTIME_TARGETS=default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda
Enables the runtimes for the target triples, default is what you get without specifying anything

-DLLVM_ENABLE_RUNTIMES="openmp"
This specifies the default target builds the openmp runtime.

-DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=openmp
This specifies that the amdgcn-amd-amdhsa target builds the openmp runtime.

Theoretically this would let us treat these as separate builds so you could pass totally different things to them. Just throwing ideas around.

@ye-luo
Copy link
Contributor

ye-luo commented Mar 5, 2024

I'm OK with the first two

-DLLVM_RUNTIME_TARGETS=default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda
Enables the runtimes for the target triples, default is what you get without specifying anything

I actually think default should automatically include amdgcn and nvptx when I have amdgcn and nvptx backend turned on.

-DLLVM_ENABLE_RUNTIMES="openmp"
This specifies the default target builds the openmp runtime.

Then openmp cmake can react to the contents of LLVM_RUNTIME_TARGETS by adding device runtime for x86,amdgcn,nvptx

@ye-luo
Copy link
Contributor

ye-luo commented Mar 6, 2024

Fixed the issue 0fa04b6
Unrelated to building as projects.

@jhuber6
Copy link
Contributor Author

jhuber6 commented Mar 6, 2024

Fixed the issue 0fa04b6 Unrelated to building as projects.

Hah, I probably should've noticed that. Explains why I didn't notice because I always have tests enabled.

SquallATF pushed a commit to SquallATF/llvm-project that referenced this pull request May 21, 2024
Summary:
One recurring problem we have with the OpenMP libraries is that they are
potentially conflicting with ones found on the system, this occurs when
there are two copies and one is used for linking that it not attached to
the correspoding clang compiler. LLVM already uses target specific
directories for this, like with libc++, which are always searched first.
This patch changes the install directory to be
`lib/x86_64-unknown-linux-gnu` for example.

Notable changes would be that users will need to change their
LD_LIBRARY_PATH settings optionally, or use default rt-rpath options.
This should fix problems were users are linking the wrong versions of
static libraries
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category openmp:libomp OpenMP host runtime openmp:libomptarget OpenMP offload runtime
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants