r238389 - [omp] Re-work Clang's handling of -fopenmp and undo r237769.

Justin Bogner mail at justinbogner.com
Thu May 28 00:36:50 PDT 2015


Chandler Carruth <chandlerc at gmail.com> writes:
> Author: chandlerc
> Date: Wed May 27 20:52:38 2015
> New Revision: 238389
>
> URL: http://llvm.org/viewvc/llvm-project?rev=238389&view=rev
> Log:
> [omp] Re-work Clang's handling of -fopenmp and undo r237769.
>
> This isn't an actual revert of r237769, it just restores the behavior of
> the Clang driver prior to it while completely re-implementing how that
> behavior works.
>
> This also re-does the work of making the default OpenMP runtime
> selectable at CMake (or configure) time to work in the way all of our
> other such hooks do (config.h, configure and cmake hooks, etc.).
>
> I've re-implemented how we manage the '-fopenmp' flagset in an important
> way. Now, the "default" hook just makes '-fopenmp' equivalent to
> '-fopenmp=<default>' rather than a separate special beast. Also, there
> is an '-fno-openmp' flag which does the obvious thing. Also, the code is
> shared between all the places to select a known OpenMP runtime and act
> on it.
>
> Finally, and most significantly, I've taught the driver to inspect the
> selected runtime when choosing whether to propagate the '-fopenmp' flag
> to the frontend in the CC1 commandline. Without this, it isn't possible
> to use Clang with libgomp, even if you were happy with the serial,
> boring way in which it worked previously (ignoring all #pragmas but
> linking in the library to satisfy direct calls into the runtime).
>
> While I'm here, I've gone ahead and sketched out a path for the future
> name of LLVM's OpenMP runtime (libomp) and the legacy support for its
> current name (libiomp5) in what seems a more reasonable way.
>
> To re-enable LLVM's OpenMP runtime (which I think should wait until the
> normal getting started instructions are a reasonable way for falks to
> check out, build, and install Clang with the runtime) all that needs to
> change is the default string in the CMakeLists.txt and configure.ac
> file. No code changes necessary.
>
> I also added a test for the driver's behavior around OpenMP since it was
> *completely missing* previously. Makes it unsurprising that we got it
> wrong.
>
> Added:
>     cfe/trunk/test/Driver/fopenmp.c
> Modified:
>     cfe/trunk/CMakeLists.txt
>     cfe/trunk/include/clang/Config/config.h.cmake
>     cfe/trunk/include/clang/Config/config.h.in
>     cfe/trunk/include/clang/Driver/Options.td
>     cfe/trunk/lib/Driver/Tools.cpp
>
> Modified: cfe/trunk/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/CMakeLists.txt?rev=238389&r1=238388&r2=238389&view=diff
> ==============================================================================
> --- cfe/trunk/CMakeLists.txt (original)
> +++ cfe/trunk/CMakeLists.txt Wed May 27 20:52:38 2015
> @@ -182,6 +182,9 @@ set(GCC_INSTALL_PREFIX "" CACHE PATH "Di
>  set(DEFAULT_SYSROOT "" CACHE PATH
>    "Default <path> to all compiler invocations for --sysroot=<path>." )
>  
> +set(CLANG_DEFAULT_OPENMP_RUNTIME "libgomp" CACHE STRING
> +  "Default OpenMP runtime used by -fopenmp.")
> +
>  set(CLANG_VENDOR "" CACHE STRING
>    "Vendor-specific text for showing with version information.")
>  
> @@ -441,11 +444,6 @@ if(CLANG_ENABLE_STATIC_ANALYZER)
>    add_definitions(-DCLANG_ENABLE_STATIC_ANALYZER)
>  endif()
>  
> -set(OPENMP_DEFAULT_LIB "" CACHE STRING "OpenMP library used by default for -fopenmp.")
> -if(OPENMP_DEFAULT_LIB)
> -  add_definitions(-DOPENMP_DEFAULT_LIB=${OPENMP_DEFAULT_LIB})
> -endif()
> -
>  # Clang version information
>  set(CLANG_EXECUTABLE_VERSION
>       "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING
>
> Modified: cfe/trunk/include/clang/Config/config.h.cmake
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Config/config.h.cmake?rev=238389&r1=238388&r2=238389&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Config/config.h.cmake (original)
> +++ cfe/trunk/include/clang/Config/config.h.cmake Wed May 27 20:52:38 2015
> @@ -8,6 +8,9 @@
>  /* Bug report URL. */
>  #define BUG_REPORT_URL "${BUG_REPORT_URL}"
>  
> +/* Default OpenMP runtime used by -fopenmp. */
> +#define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}"
> +
>  /* Multilib suffix for libdir. */
>  #define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}"
>  
>
> Modified: cfe/trunk/include/clang/Config/config.h.in
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Config/config.h.in?rev=238389&r1=238388&r2=238389&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Config/config.h.in (original)
> +++ cfe/trunk/include/clang/Config/config.h.in Wed May 27 20:52:38 2015
> @@ -8,6 +8,9 @@
>  /* Bug report URL. */
>  #undef BUG_REPORT_URL
>  
> +/* Default OpenMP runtime used by -fopenmp. */
> +#undef CLANG_DEFAULT_OPENMP_RUNTIME
> +
>  /* Multilib suffix for libdir. */
>  #undef CLANG_LIBDIR_SUFFIX
>  
>
> Modified: cfe/trunk/include/clang/Driver/Options.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=238389&r1=238388&r2=238389&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/Options.td (original)
> +++ cfe/trunk/include/clang/Driver/Options.td Wed May 27 20:52:38 2015
> @@ -876,6 +876,7 @@ def fno_objc_nonfragile_abi : Flag<["-"]
>  def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
>  def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
>  def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
> +def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
>  def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
>  def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
>  def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
>
> Modified: cfe/trunk/lib/Driver/Tools.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=238389&r1=238388&r2=238389&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/Tools.cpp (original)
> +++ cfe/trunk/lib/Driver/Tools.cpp Wed May 27 20:52:38 2015
> @@ -2278,6 +2278,54 @@ static void addProfileRT(const ToolChain
>    CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
>  }
>  
> +namespace {
> +enum OpenMPRuntimeKind {
> +  /// An unknown OpenMP runtime. We can't generate effective OpenMP code
> +  /// without knowing what runtime to target.
> +  OMPRT_Unknown,
> +
> +  /// The LLVM OpenMP runtime. When completed and integrated, this will become
> +  /// the default for Clang.
> +  OMPRT_OMP,
> +
> +  /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
> +  /// this runtime but can swallow the pragmas, and find and link against the
> +  /// runtime library itself.
> +  OMPRT_GOMP,
> +
> +  /// The legacy name for the LLVM OpenMP runtim from when it was the Intel
                                             ^~~~~~
Typo.

> +  /// OpenMP runtime. We support this mode for users with existing dependencies
> +  /// on this runtime library name.
> +  OMPRT_IOMP5
> +};
> +}
> +
> +/// Compute the desired OpenMP runtime from the flag provided.
> +static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC, const ArgList &Args) {

Long line?

> +  StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
> +
> +  const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
> +  if (A)
> +    RuntimeName = A->getValue();
> +
> +  auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
> +      .Case("libomp", OMPRT_OMP)
> +      .Case("libgomp", OMPRT_GOMP)
> +      .Case("libiomp5", OMPRT_IOMP5)
> +      .Default(OMPRT_Unknown);
> +
> +  if (RT == OMPRT_Unknown) {
> +    if (A)
> +      TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
> +        << A->getOption().getName() << A->getValue();
> +    else
> +      // FIXME: We could use a nicer diagnostic here.
> +      TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp";

Is this even reachable in a meaningful way? CLANG_DEFAULT_OPENMP_RUNTIME
has to be something we don't understand. If we can somehow get here, the
error is really "You're using a version of LLVM that was configured
wrong, get a better one".

> +  }
> +
> +  return RT;
> +}
> +
>  static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
>                                  ArgStringList &CmdArgs, StringRef Sanitizer,
>                                  bool IsShared) {
> @@ -3804,10 +3852,23 @@ void Clang::ConstructJob(Compilation &C,
>    Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
>  
>    // Forward flags for OpenMP
> -  if (Args.hasArg(options::OPT_fopenmp_EQ) ||
> -      Args.hasArg(options::OPT_fopenmp)) {
> -    CmdArgs.push_back("-fopenmp");
> -  }
> +  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
> +                   options::OPT_fno_openmp, false))
> +    switch (getOpenMPRuntime(getToolChain(), Args)) {
> +    case OMPRT_OMP:
> +    case OMPRT_IOMP5:
> +      // Clang can generate useful OpenMP code for these two runtime libraries.
> +      CmdArgs.push_back("-fopenmp");
> +      break;
> +    default:
> +      // By default, if Clang doesn't know how to generate useful OpenMP code
> +      // for a specific runtime library, we just don't pass the '-fopenmp' flag
> +      // down to the actual compilation.
> +      // FIXME: It would be better to have a mode which *only* omits IR
> +      // generation based on the OpenMP support so that we get consistent
> +      // semantic analysis, etc.
> +      break;
> +    }
>  
>    const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
>    Sanitize.addArgs(Args, CmdArgs);
> @@ -6238,33 +6299,6 @@ void darwin::Link::AddLinkArgs(Compilati
>    Args.AddLastArg(CmdArgs, options::OPT_Mach);
>  }
>  
> -enum LibOpenMP {
> -  LibUnknown,
> -  LibGOMP,
> -  LibIOMP5
> -};
> -
> -/// Map a -fopenmp=<blah> macro to the corresponding library.
> -static LibOpenMP getOpenMPLibByName(StringRef Name) {
> -  return llvm::StringSwitch<LibOpenMP>(Name).Case("libgomp", LibGOMP)
> -                                            .Case("libiomp5", LibIOMP5)
> -                                            .Default(LibUnknown);
> -}
> -
> -/// Get the default -l<blah> flag to use for -fopenmp, if no library is
> -/// specified. This can be overridden at configure time.
> -static const char *getDefaultOpenMPLibFlag() {
> -#ifndef OPENMP_DEFAULT_LIB
> -#define OPENMP_DEFAULT_LIB iomp5
> -#endif
> -
> -#define STR2(lib) #lib
> -#define STR(lib) STR2(lib)
> -  return "-l" STR(OPENMP_DEFAULT_LIB);
> -#undef STR
> -#undef STR2
> -}
> -
>  void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
>                                  const InputInfo &Output,
>                                  const InputInfoList &Inputs,
> @@ -6322,21 +6356,22 @@ void darwin::Link::ConstructJob(Compilat
>  
>    Args.AddAllArgs(CmdArgs, options::OPT_L);
>  
> -  if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
> -    switch (getOpenMPLibByName(A->getValue())) {
> -    case LibGOMP:
> +  if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
> +                   options::OPT_fno_openmp, false)) {
> +    switch (getOpenMPRuntime(getToolChain(), Args)) {
> +    case OMPRT_OMP:
> +      CmdArgs.push_back("-lomp");
> +      break;
> +    case OMPRT_GOMP:
>        CmdArgs.push_back("-lgomp");
>        break;
> -    case LibIOMP5:
> +    case OMPRT_IOMP5:
>        CmdArgs.push_back("-liomp5");
>        break;
> -    case LibUnknown:
> -      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
> -        << A->getOption().getName() << A->getValue();
> +    case OMPRT_Unknown:
> +      // Already diagnosed.
>        break;
>      }
> -  } else if (Args.hasArg(options::OPT_fopenmp)) {
> -    CmdArgs.push_back(getDefaultOpenMPLibFlag());
>    }
>  
>    AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
> @@ -8043,30 +8078,36 @@ void gnutools::Link::ConstructJob(Compil
>        if (NeedsSanitizerDeps)
>          linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
>  
> -      bool WantPthread = true;
> -      if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) {
> -        switch (getOpenMPLibByName(A->getValue())) {
> -        case LibGOMP:
> +      bool WantPthread = Args.hasArg(options::OPT_pthread) ||
> +                         Args.hasArg(options::OPT_pthreads);
> +
> +      if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
> +                       options::OPT_fno_openmp, false)) {
> +        // OpenMP runtimes implies pthreads when using the GNU toolchain.
> +        // FIXME: Does this really make sense for all GNU toolchains?
> +        WantPthread = true;
> +
> +        // Also link the particular OpenMP runtimes.
> +        switch (getOpenMPRuntime(ToolChain, Args)) {
> +        case OMPRT_OMP:
> +          CmdArgs.push_back("-lomp");
> +          break;
> +        case OMPRT_GOMP:
>            CmdArgs.push_back("-lgomp");
>  
>            // FIXME: Exclude this for platforms with libgomp that don't require
>            // librt. Most modern Linux platforms require it, but some may not.
>            CmdArgs.push_back("-lrt");
>            break;
> -        case LibIOMP5:
> +        case OMPRT_IOMP5:
>            CmdArgs.push_back("-liomp5");
>            break;
> -        case LibUnknown:
> -          D.Diag(diag::err_drv_unsupported_option_argument)
> -              << A->getOption().getName() << A->getValue();
> +        case OMPRT_Unknown:
> +          // Already diagnosed.
>            break;
>          }
> -      } else if (Args.hasArg(options::OPT_fopenmp)) {
> -        CmdArgs.push_back(getDefaultOpenMPLibFlag());
> -      } else {
> -        WantPthread = Args.hasArg(options::OPT_pthread) ||
> -                      Args.hasArg(options::OPT_pthreads);
>        }
> +
>        AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
>  
>        if (WantPthread && !isAndroid)
>
> Added: cfe/trunk/test/Driver/fopenmp.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fopenmp.c?rev=238389&view=auto
> ==============================================================================
> --- cfe/trunk/test/Driver/fopenmp.c (added)
> +++ cfe/trunk/test/Driver/fopenmp.c Wed May 27 20:52:38 2015
> @@ -0,0 +1,24 @@
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
> +//
> +// CHECK-CC1-OPENMP: "-cc1"
> +// CHECK-CC1-OPENMP: "-fopenmp"
> +//
> +// CHECK-CC1-NO-OPENMP: "-cc1"
> +// CHECK-CC1-NO-OPENMP-NOT: "-fopenmp"
> +//
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-OMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP
> +// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5
> +//
> +// CHECK-LD-OMP: "{{.*}}ld{{(.exe)?}}"
> +// CHECK-LD-OMP: "-lomp"
> +//
> +// CHECK-LD-GOMP: "{{.*}}ld{{(.exe)?}}"
> +// CHECK-LD-GOMP: "-lgomp"
> +//
> +// CHECK-LD-IOMP5: "{{.*}}ld{{(.exe)?}}"
> +// CHECK-LD-IOMP5: "-liomp5"
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list