Browse Source

Merge topic 'enable-intel-llvm-ipo-3'

c633bd76d8 Add linker prefix for "-stack" flag on MSVC builds
6823db0c5a Enable IPO for IntelLLVM compilers on Linux and Windows
adbffd204d Propagate OpenMP compiler flags to linker for IntelLLVM
3640842df2 Tests: Update ModuleDefinition for IntelLLVM MSVC Frontend Variant
5d5a712303 IntelLLVM: Pass linker flags to the compiler when used as linker

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !7533
Brad King 3 years ago
parent
commit
52dec3f11f

+ 1 - 1
CompileFlags.cmake

@@ -23,7 +23,7 @@ else()
 endif()
 
 if(MSVC)
-  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stack:10000000")
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}-stack:10000000")
 endif()
 
 # MSVC 14.28 enables C5105, but the Windows SDK 10.0.18362.0 triggers it.

+ 45 - 0
Modules/Compiler/IntelLLVM-FindBinUtils.cmake

@@ -0,0 +1,45 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+  message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+# Ubuntu:
+# * /usr/bin/llvm-ar-9
+# * /usr/bin/llvm-ranlib-9
+string(REGEX MATCH "^([0-9]+)" __version_x
+    "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+# Debian:
+# * /usr/bin/llvm-ar-4.0
+# * /usr/bin/llvm-ranlib-4.0
+string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y
+    "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}")
+
+# Try to find tools in the IntelLLVM Clang tools directory
+get_filename_component(__intel_llvm_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+get_filename_component(__intel_llvm_hint_1 "${__intel_llvm_hint_1}/../bin-llvm" REALPATH)
+
+get_filename_component(__intel_llvm_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+set(__intel_llvm_hints ${__intel_llvm_hint_1} ${__intel_llvm_hint_2})
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x_y}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar"
+    HINTS ${__intel_llvm_hints}
+    NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH
+    DOC "LLVM archiver"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR)
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x_y}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x}"
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib"
+    HINTS ${__intel_llvm_hints}
+    NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH
+    DOC "Generate index for LLVM archive"
+)
+mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB)

+ 15 - 6
Modules/Compiler/IntelLLVM.cmake

@@ -15,6 +15,15 @@ set(__pch_header_CXX "c++-header")
 set(__pch_header_OBJC "objective-c-header")
 set(__pch_header_OBJCXX "objective-c++-header")
 
+# Variables that are common across front-end variants
+macro(__compiler_intel_llvm_common lang)
+  set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+  set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+  set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>")
+  set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>")
+  set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>")
+endmacro()
+
 if(CMAKE_HOST_WIN32)
   # MSVC-like
   macro(__compiler_intel_llvm lang)
@@ -22,6 +31,9 @@ if(CMAKE_HOST_WIN32)
       set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch)
       set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX")
     endif()
+    __compiler_intel_llvm_common(${lang})
+    set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-Qipo")
+    set(CMAKE_${lang}_LINK_OPTIONS_IPO "-Qipo")
   endmacro()
 else()
   # GNU-like
@@ -60,12 +72,9 @@ else()
     set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
     set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP)
 
-    set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
-    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
-    set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
-    set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>")
-    set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>")
-    set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>")
+    __compiler_intel_llvm_common(${lang})
+    set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-ipo")
+    set(CMAKE_${lang}_LINK_OPTIONS_IPO "-ipo")
 
     set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
     set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")

+ 2 - 1
Modules/FindOpenMP.cmake

@@ -601,7 +601,8 @@ foreach(LANG IN LISTS OpenMP_FINDLIST)
         separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
         set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
           INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
-        if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu")
+        if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu"
+          OR ${CMAKE_${LANG}_COMPILER_ID} STREQUAL "IntelLLVM")
           set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
             INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}")
         endif()

+ 0 - 26
Modules/Platform/Linux-IntelLLVM.cmake

@@ -8,18 +8,6 @@ if(__LINUX_COMPILER_INTEL_LLVM)
 endif()
 set(__LINUX_COMPILER_INTEL_LLVM 1)
 
-if(NOT XIAR)
-  set(_intel_xiar_hints)
-  foreach(lang C CXX Fortran)
-    if(IS_ABSOLUTE "${CMAKE_${lang}_COMPILER}")
-      get_filename_component(_hint "${CMAKE_${lang}_COMPILER}" PATH)
-      list(APPEND _intel_xiar_hints ${_hint})
-    endif()
-  endforeach()
-  find_program(XIAR NAMES xiar HINTS ${_intel_xiar_hints})
-  mark_as_advanced(XIAR)
-endif()
-
 macro(__linux_compiler_intel_llvm lang)
   set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
   set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
@@ -37,19 +25,5 @@ macro(__linux_compiler_intel_llvm lang)
   set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
   set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
 
-  set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
-
-  if(XIAR)
-    # INTERPROCEDURAL_OPTIMIZATION
-    set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo)
-    set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO
-      "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> "
-      "${XIAR} -s <TARGET> ")
-    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
-    set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES)
-  else()
-    set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
-  endif()
-
   set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
 endmacro()

+ 43 - 8
Modules/Platform/Windows-IntelLLVM.cmake

@@ -3,26 +3,61 @@
 
 
 # This module is shared by multiple languages; use include blocker.
-if(__WINDOWS_INTEL)
+if(__WINDOWS_INTEL_LLVM)
   return()
 endif()
-set(__WINDOWS_INTEL 1)
+set(__WINDOWS_INTEL_LLVM 1)
 
+# Platform/Windows-MSVC adds some linking options icx/ifx do not understand,
+# but that need to be passed to the linker.  Wrap all the linking options from
+# Platform/Windows-MSVC so that the compiler will hand them off to the linker
+# without interpreting them.
+
+# Save original CMAKE_${t}_LINKER_FLAGS_INIT
+foreach(t EXE SHARED MODULE STATIC)
+  set(_saved_cmake_${t}_linker_flags_init ${CMAKE_${t}_LINKER_FLAGS_INIT})
+  set(CMAKE_${t}_LINKER_FLAGS_INIT "")
+endforeach()
 include(Platform/Windows-MSVC)
+# Wrap linker flags from Windows-MSVC
+set(_IntelLLVM_LINKER_WRAPPER_FLAG "/Qoption,link,")
+set(_IntelLLVM_LINKER_WRAPPER_FLAG_SEP ",")
+foreach(t EXE SHARED MODULE STATIC)
+  set(_wrapped_linker_flags "")
+  foreach(flag ${CMAKE_${t}_LINKER_FLAGS_INIT})
+    string(STRIP ${flag} flag)
+    list(APPEND _wrapped_linker_flags "${_IntelLLVM_LINKER_WRAPPER_FLAG}${flag}")
+  endforeach()
+  set(CMAKE_${t}_LINKER_FLAGS_INIT "")
+  list(APPEND CMAKE_${t}_LINKER_FLAGS_INIT
+    ${_saved_cmake_${t}_linker_flags_init} ${_wrapped_linker_flags})
+endforeach()
+
 macro(__windows_compiler_intel lang)
   __windows_compiler_msvc(${lang})
 
-  # For DPCPP other offload cases, some link flags need to go to the compiler
-  # driver and others need to go to the linker.  Pass the compiler linking flags
-  # in CMAKE_${lang}_LINK_FLAGS and linker flags in LINK_FLAGS
+  set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "${_IntelLLVM_LINKER_WRAPPER_FLAG}")
+  set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP "${_IntelLLVM_LINKER_WRAPPER_FLAG_SEP}")
+  set(CMAKE_${lang}_CREATE_WIN32_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:windows")
+  set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:console")
+  set(CMAKE_LINK_DEF_FILE_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/DEF:")
+  set(CMAKE_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/LIBPATH:")
+
+  # Features for LINK_LIBRARY generator expression
+  if(MSVC_VERSION GREATER "1900")
+    ## WHOLE_ARCHIVE: Force loading all members of an archive
+    set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>")
+    set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE)
+  endif()
+
   set(CMAKE_${lang}_LINK_EXECUTABLE
-    "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
+    "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <LINK_LIBRARIES> /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
   set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
-    "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+    "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD <LINK_FLAGS> <LINK_LIBRARIES> -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
   if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1)
     # The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1
     set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
-      "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> -link <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
+      "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
   endif()
 
   set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")

+ 11 - 1
Tests/ModuleDefinition/CMakeLists.txt

@@ -15,7 +15,17 @@ add_custom_command(OUTPUT example_dll_gen.def
 add_library(example_dll_gen SHARED example_dll_gen.c example_dll_gen.def)
 
 # Test /DEF:<file> flag recognition for VS.
-if(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
+if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM")
+  # IntelLLVM for MSVC frontend variant needs the /DEF flag wrapped to be sent
+  # to the linker, which happens automatically when the DEF file is added
+  # to the sources.
+  add_library(example_dll_2 SHARED
+    example_dll_2.c
+    "${ModuleDefinition_SOURCE_DIR}/example_dll_2.def"
+    )
+  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS EXAMPLE_DLL_2)
+  set(example_dll_2 example_dll_2)
+elseif(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel")
   add_library(example_dll_2 SHARED example_dll_2.c)
   set_property(TARGET example_dll_2 PROPERTY LINK_FLAGS
     /DEF:"${ModuleDefinition_SOURCE_DIR}/example_dll_2.def")