Skip to content

Commit

Permalink
[OpenMP][OpenACC] Implement ompx_hold map type modifier extension i…
Browse files Browse the repository at this point in the history
…n Clang (1/2)

This patch implements Clang support for an original OpenMP extension
we have developed to support OpenACC: the `ompx_hold` map type
modifier.  The next patch in this series, D106510, implements OpenMP
runtime support.

Consider the following example:

```
 #pragma omp target data map(ompx_hold, tofrom: x) // holds onto mapping of x
 {
   foo(); // might have map(delete: x)
   #pragma omp target map(present, alloc: x) // x is guaranteed to be present
   printf("%d\n", x);
 }
```

The `ompx_hold` map type modifier above specifies that the `target
data` directive holds onto the mapping for `x` throughout the
associated region regardless of any `target exit data` directives
executed during the call to `foo`.  Thus, the presence assertion for
`x` at the enclosed `target` construct cannot fail.  (As usual, the
standard OpenMP reference count for `x` must also reach zero before
the data is unmapped.)

Justification for inclusion in Clang and LLVM's OpenMP runtime:

* The `ompx_hold` modifier supports OpenACC functionality (structured
  reference count) that cannot be achieved in standard OpenMP, as of
  5.1.
* The runtime implementation for `ompx_hold` (next patch) will thus be
  used by Flang's OpenACC support.
* The Clang implementation for `ompx_hold` (this patch) as well as the
  runtime implementation are required for the Clang OpenACC support
  being developed as part of the ECP Clacc project, which translates
  OpenACC to OpenMP at the directive AST level.  These patches are the
  first step in upstreaming OpenACC functionality from Clacc.
* The Clang implementation for `ompx_hold` is also used by the tests
  in the runtime implementation.  That syntactic support makes the
  tests more readable than low-level runtime calls can.  Moreover,
  upstream Flang and Clang do not yet support OpenACC syntax
  sufficiently for writing the tests.
* More generally, the Clang implementation enables a clean separation
  of concerns between OpenACC and OpenMP development in LLVM.  That
  is, LLVM's OpenMP developers can discuss, modify, and debug LLVM's
  extended OpenMP implementation and test suite without directly
  considering OpenACC's language and execution model, which can be
  handled by LLVM's OpenACC developers.
* OpenMP users might find the `ompx_hold` modifier useful, as in the
  above example.

See new documentation introduced by this patch in `openmp/docs` for
more detail on the functionality of this extension and its
relationship with OpenACC.  For example, it explains how the runtime
must support two reference counts, as specified by OpenACC.

Clang recognizes `ompx_hold` unless `-fno-openmp-extensions`, a new
command-line option introduced by this patch, is specified.

Reviewed By: ABataev, jdoerfert, protze.joachim, grokos

Differential Revision: https://reviews.llvm.org/D106509
  • Loading branch information
jdenny-ornl committed Aug 31, 2021
1 parent dc37f53 commit 83ddfa0
Show file tree
Hide file tree
Showing 34 changed files with 2,171 additions and 176 deletions.
5 changes: 5 additions & 0 deletions clang/docs/ClangCommandLineReference.rst
Expand Up @@ -2039,6 +2039,11 @@ Emit OpenMP code only for SIMD-based constructs.

.. option:: -fopenmp-version=<arg>

.. option:: -fopenmp-extensions, -fno-openmp-extensions

Enable or disable all Clang extensions for OpenMP directives and clauses. By
default, they are enabled.

.. program:: clang1
.. option:: -fopenmp=<arg>
.. program:: clang
Expand Down
17 changes: 17 additions & 0 deletions clang/docs/OpenMPSupport.rst
Expand Up @@ -360,3 +360,20 @@ want to help with the implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | nowait clause on taskwait | :none:`unclaimed` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+

OpenMP Extensions
=================

The following table provides a quick overview over various OpenMP
extensions and their implementation status. These extensions are not
currently defined by any standard, so links to associated LLVM
documentation are provided. As these extensions mature, they will be
considered for standardization. Please contact *openmp-dev* at
*lists.llvm.org* to provide feedback.

+------------------------------+---------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
|Category | Feature | Status | Reviews |
+==============================+===========================================================================+==========================+========================================================+
| device extension | `'ompx_hold' map type modifier | :good:`prototyped` | D106509, D106510 |
| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#ompx-hold>`_ | | |
+------------------------------+---------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
3 changes: 2 additions & 1 deletion clang/include/clang/AST/OpenMPClause.h
Expand Up @@ -5606,7 +5606,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
/// Map-type-modifiers for the 'map' clause.
OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = {
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
OMPC_MAP_MODIFIER_unknown};

/// Location of map-type-modifiers for the 'map' clause.
SourceLocation MapTypeModifiersLoc[NumberOfOMPMapClauseModifiers];
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Expand Up @@ -1303,8 +1303,8 @@ def err_omp_decl_in_declare_simd_variant : Error<
def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
def err_omp_unknown_map_type_modifier : Error<
"incorrect map type modifier, expected 'always', 'close', "
"%select{or 'mapper'|'mapper', or 'present'}0">;
"incorrect map type modifier, expected one of: 'always', 'close', 'mapper'"
"%select{|, 'present'}0%select{|, 'ompx_hold'}1">;
def err_omp_map_type_missing : Error<
"missing map type">;
def err_omp_map_type_modifier_missing : Error<
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -10534,6 +10534,8 @@ def err_omp_map_shared_storage : Error<
"variable already marked as mapped in current construct">;
def err_omp_invalid_map_type_for_directive : Error<
"%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">;
def err_omp_invalid_map_type_modifier_for_directive : Error<
"map type modifier '%0' is not allowed for '#pragma omp %1'">;
def err_omp_no_clause_for_directive : Error<
"expected at least one %0 clause for '#pragma omp %1'">;
def err_omp_threadprivate_in_clause : Error<
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Expand Up @@ -231,6 +231,7 @@ LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
LANGOPT(CUDA , 1, 0, "CUDA")
LANGOPT(HIP , 1, 0, "HIP")
LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)")
LANGOPT(OpenMPExtensions , 1, 1, "Enable all Clang extensions for OpenMP directives and clauses")
LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/OpenMPKinds.def
Expand Up @@ -123,6 +123,8 @@ OPENMP_MAP_MODIFIER_KIND(always)
OPENMP_MAP_MODIFIER_KIND(close)
OPENMP_MAP_MODIFIER_KIND(mapper)
OPENMP_MAP_MODIFIER_KIND(present)
// This is an OpenMP extension for the sake of OpenACC support.
OPENMP_MAP_MODIFIER_KIND(ompx_hold)

// Modifiers for 'to' or 'from' clause.
OPENMP_MOTION_MODIFIER_KIND(mapper)
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/OpenMPKinds.h
Expand Up @@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
#define LLVM_CLANG_BASIC_OPENMPKINDS_H

#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"

Expand Down Expand Up @@ -167,7 +168,7 @@ enum OpenMPReductionClauseModifier {
};

unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str,
unsigned OpenMPVersion);
const LangOptions &LangOpts);
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);

/// Checks if the specified directive is a directive with an associated
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -2379,6 +2379,12 @@ def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgume
HelpText<"Parse OpenMP pragmas and generate parallel code.">;
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
defm openmp_extensions: BoolFOption<"openmp-extensions",
LangOpts<"OpenMPExtensions">, DefaultTrue,
PosFlag<SetTrue, [CC1Option, NoArgumentUnused],
"Enable all Clang extensions for OpenMP directives and clauses">,
NegFlag<SetFalse, [CC1Option, NoArgumentUnused],
"Disable all Clang extensions for OpenMP directives and clauses">>;
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Basic/OpenMPKinds.cpp
Expand Up @@ -21,7 +21,7 @@ using namespace clang;
using namespace llvm::omp;

unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
unsigned OpenMPVersion) {
const LangOptions &LangOpts) {
switch (Kind) {
case OMPC_default:
return llvm::StringSwitch<unsigned>(Str)
Expand Down Expand Up @@ -59,7 +59,9 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
.Case(#Name, static_cast<unsigned>(OMPC_MAP_MODIFIER_##Name))
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_MAP_unknown);
if (OpenMPVersion < 51 && Type == OMPC_MAP_MODIFIER_present)
if (LangOpts.OpenMP < 51 && Type == OMPC_MAP_MODIFIER_present)
return OMPC_MAP_MODIFIER_unknown;
if (!LangOpts.OpenMPExtensions && Type == OMPC_MAP_MODIFIER_ompx_hold)
return OMPC_MAP_MODIFIER_unknown;
return Type;
}
Expand All @@ -70,7 +72,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
.Case(#Name, static_cast<unsigned>(OMPC_MOTION_MODIFIER_##Name))
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_MOTION_MODIFIER_unknown);
if (OpenMPVersion < 51 && Type == OMPC_MOTION_MODIFIER_present)
if (LangOpts.OpenMP < 51 && Type == OMPC_MOTION_MODIFIER_present)
return OMPC_MOTION_MODIFIER_unknown;
return Type;
}
Expand Down
25 changes: 25 additions & 0 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Expand Up @@ -7269,6 +7269,14 @@ class MappableExprsHandler {
/// 0x800 is reserved for compatibility with XLC.
/// Produce a runtime error if the data is not already allocated.
OMP_MAP_PRESENT = 0x1000,
// Increment and decrement a separate reference counter so that the data
// cannot be unmapped within the associated region. Thus, this flag is
// intended to be used on 'target' and 'target data' directives because they
// are inherently structured. It is not intended to be used on 'target
// enter data' and 'target exit data' directives because they are inherently
// dynamic.
// This is an OpenMP extension for the sake of OpenACC support.
OMP_MAP_OMPX_HOLD = 0x2000,
/// Signal that the runtime library should use args as an array of
/// descriptor_dim pointers and use args_size as dims. Used when we have
/// non-contiguous list items in target update directive
Expand Down Expand Up @@ -7570,6 +7578,9 @@ class MappableExprsHandler {
llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) !=
MotionModifiers.end())
Bits |= OMP_MAP_PRESENT;
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold) !=
MapModifiers.end())
Bits |= OMP_MAP_OMPX_HOLD;
if (IsNonContiguous)
Bits |= OMP_MAP_NON_CONTIG;
return Bits;
Expand Down Expand Up @@ -8923,6 +8934,20 @@ class MappableExprsHandler {
CombinedInfo.Types.back() |= OMP_MAP_PRESENT;
// Remove TARGET_PARAM flag from the first element
(*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
// If any element has the ompx_hold modifier, then make sure the runtime
// uses the hold reference count for the struct as a whole so that it won't
// be unmapped by an extra dynamic reference count decrement. Add it to all
// elements as well so the runtime knows which reference count to check
// when determining whether it's time for device-to-host transfers of
// individual elements.
if (CurTypes.end() !=
llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
return Type & OMP_MAP_OMPX_HOLD;
})) {
CombinedInfo.Types.back() |= OMP_MAP_OMPX_HOLD;
for (auto &M : CurTypes)
M |= OMP_MAP_OMPX_HOLD;
}

// All other current entries will be MEMBER_OF the combined entry
// (except for PTR_AND_OBJ entries which do not have a placeholder value
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -5765,6 +5765,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_enable_irbuilder);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
if (!Args.hasFlag(options::OPT_fopenmp_extensions,
options::OPT_fno_openmp_extensions, /*Default=*/true))
CmdArgs.push_back("-fno-openmp-extensions");
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
Args.AddAllArgs(CmdArgs,
Expand Down Expand Up @@ -5800,6 +5803,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
if (!Args.hasFlag(options::OPT_fopenmp_extensions,
options::OPT_fno_openmp_extensions, /*Default=*/true))
CmdArgs.push_back("-fno-openmp-extensions");
}

const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
Expand Down

0 comments on commit 83ddfa0

Please sign in to comment.