Skip to content

Commit 83ddfa0

Browse files
committed
[OpenMP][OpenACC] Implement ompx_hold map type modifier extension in 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
1 parent dc37f53 commit 83ddfa0

34 files changed

+2171
-176
lines changed

clang/docs/ClangCommandLineReference.rst

+5
Original file line numberDiff line numberDiff line change
@@ -2039,6 +2039,11 @@ Emit OpenMP code only for SIMD-based constructs.
20392039

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

2042+
.. option:: -fopenmp-extensions, -fno-openmp-extensions
2043+
2044+
Enable or disable all Clang extensions for OpenMP directives and clauses. By
2045+
default, they are enabled.
2046+
20422047
.. program:: clang1
20432048
.. option:: -fopenmp=<arg>
20442049
.. program:: clang

clang/docs/OpenMPSupport.rst

+17
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,20 @@ want to help with the implementation.
360360
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
361361
| task extension | nowait clause on taskwait | :none:`unclaimed` | |
362362
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
363+
364+
OpenMP Extensions
365+
=================
366+
367+
The following table provides a quick overview over various OpenMP
368+
extensions and their implementation status. These extensions are not
369+
currently defined by any standard, so links to associated LLVM
370+
documentation are provided. As these extensions mature, they will be
371+
considered for standardization. Please contact *openmp-dev* at
372+
*lists.llvm.org* to provide feedback.
373+
374+
+------------------------------+---------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+
375+
|Category | Feature | Status | Reviews |
376+
+==============================+===========================================================================+==========================+========================================================+
377+
| device extension | `'ompx_hold' map type modifier | :good:`prototyped` | D106509, D106510 |
378+
| | <https://openmp.llvm.org/docs/openacc/OpenMPExtensions.html#ompx-hold>`_ | | |
379+
+------------------------------+---------------------------------------------------------------------------+--------------------------+--------------------------------------------------------+

clang/include/clang/AST/OpenMPClause.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -5606,7 +5606,8 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
56065606
/// Map-type-modifiers for the 'map' clause.
56075607
OpenMPMapModifierKind MapTypeModifiers[NumberOfOMPMapClauseModifiers] = {
56085608
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
5609-
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown};
5609+
OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown,
5610+
OMPC_MAP_MODIFIER_unknown};
56105611

56115612
/// Location of map-type-modifiers for the 'map' clause.
56125613
SourceLocation MapTypeModifiersLoc[NumberOfOMPMapClauseModifiers];

clang/include/clang/Basic/DiagnosticParseKinds.td

+2-2
Original file line numberDiff line numberDiff line change
@@ -1303,8 +1303,8 @@ def err_omp_decl_in_declare_simd_variant : Error<
13031303
def err_omp_unknown_map_type : Error<
13041304
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
13051305
def err_omp_unknown_map_type_modifier : Error<
1306-
"incorrect map type modifier, expected 'always', 'close', "
1307-
"%select{or 'mapper'|'mapper', or 'present'}0">;
1306+
"incorrect map type modifier, expected one of: 'always', 'close', 'mapper'"
1307+
"%select{|, 'present'}0%select{|, 'ompx_hold'}1">;
13081308
def err_omp_map_type_missing : Error<
13091309
"missing map type">;
13101310
def err_omp_map_type_modifier_missing : Error<

clang/include/clang/Basic/DiagnosticSemaKinds.td

+2
Original file line numberDiff line numberDiff line change
@@ -10534,6 +10534,8 @@ def err_omp_map_shared_storage : Error<
1053410534
"variable already marked as mapped in current construct">;
1053510535
def err_omp_invalid_map_type_for_directive : Error<
1053610536
"%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">;
10537+
def err_omp_invalid_map_type_modifier_for_directive : Error<
10538+
"map type modifier '%0' is not allowed for '#pragma omp %1'">;
1053710539
def err_omp_no_clause_for_directive : Error<
1053810540
"expected at least one %0 clause for '#pragma omp %1'">;
1053910541
def err_omp_threadprivate_in_clause : Error<

clang/include/clang/Basic/LangOptions.def

+1
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
231231
LANGOPT(CUDA , 1, 0, "CUDA")
232232
LANGOPT(HIP , 1, 0, "HIP")
233233
LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)")
234+
LANGOPT(OpenMPExtensions , 1, 1, "Enable all Clang extensions for OpenMP directives and clauses")
234235
LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.")
235236
LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
236237
LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")

clang/include/clang/Basic/OpenMPKinds.def

+2
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ OPENMP_MAP_MODIFIER_KIND(always)
123123
OPENMP_MAP_MODIFIER_KIND(close)
124124
OPENMP_MAP_MODIFIER_KIND(mapper)
125125
OPENMP_MAP_MODIFIER_KIND(present)
126+
// This is an OpenMP extension for the sake of OpenACC support.
127+
OPENMP_MAP_MODIFIER_KIND(ompx_hold)
126128

127129
// Modifiers for 'to' or 'from' clause.
128130
OPENMP_MOTION_MODIFIER_KIND(mapper)

clang/include/clang/Basic/OpenMPKinds.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
1515
#define LLVM_CLANG_BASIC_OPENMPKINDS_H
1616

17+
#include "clang/Basic/LangOptions.h"
1718
#include "llvm/ADT/StringRef.h"
1819
#include "llvm/Frontend/OpenMP/OMPConstants.h"
1920

@@ -167,7 +168,7 @@ enum OpenMPReductionClauseModifier {
167168
};
168169

169170
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str,
170-
unsigned OpenMPVersion);
171+
const LangOptions &LangOpts);
171172
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
172173

173174
/// Checks if the specified directive is a directive with an associated

clang/include/clang/Driver/Options.td

+6
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,12 @@ def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgume
23792379
HelpText<"Parse OpenMP pragmas and generate parallel code.">;
23802380
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
23812381
def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
2382+
defm openmp_extensions: BoolFOption<"openmp-extensions",
2383+
LangOpts<"OpenMPExtensions">, DefaultTrue,
2384+
PosFlag<SetTrue, [CC1Option, NoArgumentUnused],
2385+
"Enable all Clang extensions for OpenMP directives and clauses">,
2386+
NegFlag<SetFalse, [CC1Option, NoArgumentUnused],
2387+
"Disable all Clang extensions for OpenMP directives and clauses">>;
23822388
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
23832389
def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>,
23842390
Flags<[NoArgumentUnused, HelpHidden]>;

clang/lib/Basic/OpenMPKinds.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ using namespace clang;
2121
using namespace llvm::omp;
2222

2323
unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
24-
unsigned OpenMPVersion) {
24+
const LangOptions &LangOpts) {
2525
switch (Kind) {
2626
case OMPC_default:
2727
return llvm::StringSwitch<unsigned>(Str)
@@ -59,7 +59,9 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
5959
.Case(#Name, static_cast<unsigned>(OMPC_MAP_MODIFIER_##Name))
6060
#include "clang/Basic/OpenMPKinds.def"
6161
.Default(OMPC_MAP_unknown);
62-
if (OpenMPVersion < 51 && Type == OMPC_MAP_MODIFIER_present)
62+
if (LangOpts.OpenMP < 51 && Type == OMPC_MAP_MODIFIER_present)
63+
return OMPC_MAP_MODIFIER_unknown;
64+
if (!LangOpts.OpenMPExtensions && Type == OMPC_MAP_MODIFIER_ompx_hold)
6365
return OMPC_MAP_MODIFIER_unknown;
6466
return Type;
6567
}
@@ -70,7 +72,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
7072
.Case(#Name, static_cast<unsigned>(OMPC_MOTION_MODIFIER_##Name))
7173
#include "clang/Basic/OpenMPKinds.def"
7274
.Default(OMPC_MOTION_MODIFIER_unknown);
73-
if (OpenMPVersion < 51 && Type == OMPC_MOTION_MODIFIER_present)
75+
if (LangOpts.OpenMP < 51 && Type == OMPC_MOTION_MODIFIER_present)
7476
return OMPC_MOTION_MODIFIER_unknown;
7577
return Type;
7678
}

clang/lib/CodeGen/CGOpenMPRuntime.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -7269,6 +7269,14 @@ class MappableExprsHandler {
72697269
/// 0x800 is reserved for compatibility with XLC.
72707270
/// Produce a runtime error if the data is not already allocated.
72717271
OMP_MAP_PRESENT = 0x1000,
7272+
// Increment and decrement a separate reference counter so that the data
7273+
// cannot be unmapped within the associated region. Thus, this flag is
7274+
// intended to be used on 'target' and 'target data' directives because they
7275+
// are inherently structured. It is not intended to be used on 'target
7276+
// enter data' and 'target exit data' directives because they are inherently
7277+
// dynamic.
7278+
// This is an OpenMP extension for the sake of OpenACC support.
7279+
OMP_MAP_OMPX_HOLD = 0x2000,
72727280
/// Signal that the runtime library should use args as an array of
72737281
/// descriptor_dim pointers and use args_size as dims. Used when we have
72747282
/// non-contiguous list items in target update directive
@@ -7570,6 +7578,9 @@ class MappableExprsHandler {
75707578
llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) !=
75717579
MotionModifiers.end())
75727580
Bits |= OMP_MAP_PRESENT;
7581+
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold) !=
7582+
MapModifiers.end())
7583+
Bits |= OMP_MAP_OMPX_HOLD;
75737584
if (IsNonContiguous)
75747585
Bits |= OMP_MAP_NON_CONTIG;
75757586
return Bits;
@@ -8923,6 +8934,20 @@ class MappableExprsHandler {
89238934
CombinedInfo.Types.back() |= OMP_MAP_PRESENT;
89248935
// Remove TARGET_PARAM flag from the first element
89258936
(*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
8937+
// If any element has the ompx_hold modifier, then make sure the runtime
8938+
// uses the hold reference count for the struct as a whole so that it won't
8939+
// be unmapped by an extra dynamic reference count decrement. Add it to all
8940+
// elements as well so the runtime knows which reference count to check
8941+
// when determining whether it's time for device-to-host transfers of
8942+
// individual elements.
8943+
if (CurTypes.end() !=
8944+
llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) {
8945+
return Type & OMP_MAP_OMPX_HOLD;
8946+
})) {
8947+
CombinedInfo.Types.back() |= OMP_MAP_OMPX_HOLD;
8948+
for (auto &M : CurTypes)
8949+
M |= OMP_MAP_OMPX_HOLD;
8950+
}
89268951

89278952
// All other current entries will be MEMBER_OF the combined entry
89288953
// (except for PTR_AND_OBJ entries which do not have a placeholder value

clang/lib/Driver/ToolChains/Clang.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -5765,6 +5765,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
57655765
options::OPT_fno_openmp_simd);
57665766
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_enable_irbuilder);
57675767
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
5768+
if (!Args.hasFlag(options::OPT_fopenmp_extensions,
5769+
options::OPT_fno_openmp_extensions, /*Default=*/true))
5770+
CmdArgs.push_back("-fno-openmp-extensions");
57685771
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
57695772
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
57705773
Args.AddAllArgs(CmdArgs,
@@ -5800,6 +5803,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
58005803
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
58015804
options::OPT_fno_openmp_simd);
58025805
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
5806+
if (!Args.hasFlag(options::OPT_fopenmp_extensions,
5807+
options::OPT_fno_openmp_extensions, /*Default=*/true))
5808+
CmdArgs.push_back("-fno-openmp-extensions");
58035809
}
58045810

58055811
const SanitizerArgs &Sanitize = TC.getSanitizerArgs();

0 commit comments

Comments
 (0)