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