[clang] [OpenMP][Clang] Add support for OMP6.1 fb_nullify and fb_preserve in need_device_ptr modifier (PR #168905)
Zahira Ammarguellat via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 21 11:43:03 PST 2025
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/168905
>From b5fe4bc6a3882bf7f3e7cb759c354cf4f73da0df Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 20 Nov 2025 08:56:04 -0800
Subject: [PATCH 1/3] [OpenMP][Clang] Add support for OpenMP6.0 fb_nullify and
fb_preserve in need_device_ptr modifier
---
.../clang/Basic/DiagnosticParseKinds.td | 3 ++
clang/include/clang/Basic/OpenMPKinds.def | 8 +++++
clang/include/clang/Basic/OpenMPKinds.h | 7 +++++
clang/include/clang/Sema/SemaOpenMP.h | 2 ++
clang/lib/Parse/ParseOpenMP.cpp | 31 +++++++++++++++++++
.../OpenMP/need_device_modifier_ast_print.cpp | 23 ++++++++++++++
.../OpenMP/need_device_modifier_messages.cpp | 15 +++++++++
7 files changed, 89 insertions(+)
create mode 100644 clang/test/OpenMP/need_device_modifier_ast_print.cpp
create mode 100644 clang/test/OpenMP/need_device_modifier_messages.cpp
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index aa0ccb0c05101..caf4b228eb53c 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1724,6 +1724,9 @@ def warn_omp_invalid_attribute_for_ompx_attributes : Warning<"'ompx_attribute' c
"%0 is ignored">, InGroup<OpenMPExtensions>;
def err_omp_duplicate_modifier : Error<"duplicate modifier '%0' in '%1' clause">;
def err_omp_expected_modifier : Error<"expected modifier in '%0' clause">;
+def err_omp_unknown_need_device_ptr_modifier
+ : Error<"unknown modifier in 'need_device_ptr' clause%select{| (OpenMP 6.1 or later only)}0">;
+
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 328a0747a82a8..8e20288ccbec7 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -101,6 +101,9 @@
#ifndef OPENMP_THREADSET_KIND
#define OPENMP_THREADSET_KIND(Name)
#endif
+#ifndef OPENMP_NEEDDEVICE_MODIFIER
+#define OPENMP_NEEDDEVICE_MODIFIER(Name)
+#endif
// Static attributes for 'schedule' clause.
OPENMP_SCHEDULE_KIND(static)
@@ -261,6 +264,10 @@ OPENMP_DOACROSS_MODIFIER(source_omp_cur_iteration)
OPENMP_THREADSET_KIND(omp_pool)
OPENMP_THREADSET_KIND(omp_team)
+// OpenMP 6.1 modifiers for 'adjust_args' clause.
+OPENMP_NEEDDEVICE_MODIFIER(fp_nullify)
+OPENMP_NEEDDEVICE_MODIFIER(fp_preserve)
+
#undef OPENMP_NUMTASKS_MODIFIER
#undef OPENMP_NUMTHREADS_MODIFIER
#undef OPENMP_GRAINSIZE_MODIFIER
@@ -291,3 +298,4 @@ OPENMP_THREADSET_KIND(omp_team)
#undef OPENMP_DOACROSS_MODIFIER
#undef OPENMP_ALLOCATE_MODIFIER
#undef OPENMP_THREADSET_KIND
+#undef OPENMP_NEEDDEVICE_MODIFIER
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index c9ddbcd6d46c1..436868d467963 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -211,6 +211,13 @@ enum OpenMPAdjustArgsOpKind {
OMPC_ADJUST_ARGS_unknown,
};
+/// OpenMP 6.1 need_device modifier
+enum OpenMPNeedDeviceModifier {
+#define OPENMP_NEEDDEVICE_MODIFIER(Name) OMPC_NEEDDEVICE_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_NEEDDEVICE_unknown,
+};
+
/// OpenMP bindings for the 'bind' clause.
enum OpenMPBindClauseKind {
#define OPENMP_BIND_KIND(Name) OMPC_BIND_##Name,
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index ba12b403d9b9a..d277636ad77ea 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -1174,6 +1174,8 @@ class SemaOpenMP : public SemaBase {
int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or
///< lastprivate clause.
int OriginalSharingModifier = 0; // Default is shared
+ int NeedDevicePtrModifier = 0;
+ SourceLocation NeedDevicePtrModifierLoc;
SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
MapTypeModifiers;
SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 31bc941e6a015..be6ed746a28ec 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4932,6 +4932,37 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ConsumeToken();
if (Tok.is(tok::colon))
Data.ColonLoc = Tok.getLocation();
+ if (getLangOpts().OpenMP >= 61) {
+ // Handle optional need_device_ptr modifier.
+ if (Tok.is(tok::l_paren)) {
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+ if (Tok.is(tok::identifier)) {
+ std::string Modifier = PP.getSpelling(Tok);
+ if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
+ Data.NeedDevicePtrModifier = Modifier == "fb_nullify"
+ ? OMPC_NEEDDEVICE_fp_nullify
+ : OMPC_NEEDDEVICE_fp_preserve;
+ } else {
+ Diag(Tok, diag::err_omp_unknown_need_device_ptr_modifier)
+ << (getLangOpts().OpenMP >= 60 ? 1 : 0);
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ return false;
+ }
+ ConsumeToken();
+ if (Tok.is(tok::r_paren)) {
+ Data.NeedDevicePtrModifierLoc = Tok.getLocation();
+ ConsumeAnyToken();
+ } else {
+ Diag(Tok, diag::err_expected) << tok::r_paren;
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ return false;
+ }
+ }
+ }
+ }
ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
"adjust-op");
}
diff --git a/clang/test/OpenMP/need_device_modifier_ast_print.cpp b/clang/test/OpenMP/need_device_modifier_ast_print.cpp
new file mode 100644
index 0000000000000..9d25a1290af44
--- /dev/null
+++ b/clang/test/OpenMP/need_device_modifier_ast_print.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 -ast-print %s | FileCheck %s
+
+// expected-no-diagnostics
+
+void __attribute__((noinline)) device_impl(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_nullify) : xp, xpref)
+void __attribute__((noinline)) host_entry_a(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_preserve) : xp, xpref)
+void __attribute__((noinline)) host_entry_b(int *xp, int *&xpref, int n) {}
+
+// CHECK-LABEL: int main()
+int main() {
+ int x;
+ int *xp = &x;
+
+ host_entry_a(xp, xp, 1);
+ host_entry_b(xp, xp, 1);
+ return 0;
+}
diff --git a/clang/test/OpenMP/need_device_modifier_messages.cpp b/clang/test/OpenMP/need_device_modifier_messages.cpp
new file mode 100644
index 0000000000000..491266b9ea331
--- /dev/null
+++ b/clang/test/OpenMP/need_device_modifier_messages.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s
+
+void __attribute__((noinline)) device_impl(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(foo) : xp, xpref) // expected-error{{unknown modifier in 'need_device_ptr' clause (OpenMP 6.1 or later only)}} // expected-error{{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
+void __attribute__((noinline)) host_entry_a(int *xp, int *&xpref, int n) {}
+
+int main() {
+ int x;
+ int *xp = &x;
+
+ host_entry_a(xp, xp, 1);
+ return 0;
+}
>From 1b7983d1e05b609c2abfed2ab1c8a76bafb5d50a Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 21 Nov 2025 11:37:56 -0800
Subject: [PATCH 2/3] Addressed review comments
---
.../clang/Basic/DiagnosticParseKinds.td | 5 ++--
clang/include/clang/Basic/OpenMPKinds.def | 10 +++----
clang/include/clang/Basic/OpenMPKinds.h | 6 ++---
clang/lib/Parse/ParseOpenMP.cpp | 10 +++----
.../OpenMP/need_device_modifier_messages.cpp | 15 -----------
...=> need_device_ptr_modifier_ast_print.cpp} | 11 ++++----
.../need_device_ptr_modifier_messages.cpp | 26 +++++++++++++++++++
7 files changed, 48 insertions(+), 35 deletions(-)
delete mode 100644 clang/test/OpenMP/need_device_modifier_messages.cpp
rename clang/test/OpenMP/{need_device_modifier_ast_print.cpp => need_device_ptr_modifier_ast_print.cpp} (60%)
create mode 100644 clang/test/OpenMP/need_device_ptr_modifier_messages.cpp
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index caf4b228eb53c..63b77858481f5 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1725,8 +1725,9 @@ def warn_omp_invalid_attribute_for_ompx_attributes : Warning<"'ompx_attribute' c
def err_omp_duplicate_modifier : Error<"duplicate modifier '%0' in '%1' clause">;
def err_omp_expected_modifier : Error<"expected modifier in '%0' clause">;
def err_omp_unknown_need_device_ptr_modifier
- : Error<"unknown modifier in 'need_device_ptr' clause%select{| (OpenMP 6.1 or later only)}0">;
-
+ : Error<
+ "invalid argument for 'need_device_ptr' modifier in 'adjust_args' clause. "
+ "Expected 'fp_nullify' or 'fb_preserve'">;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 8e20288ccbec7..23f4df7ec4215 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -101,8 +101,8 @@
#ifndef OPENMP_THREADSET_KIND
#define OPENMP_THREADSET_KIND(Name)
#endif
-#ifndef OPENMP_NEEDDEVICE_MODIFIER
-#define OPENMP_NEEDDEVICE_MODIFIER(Name)
+#ifndef OPENMP_NEED_DEVICE_PTR_MODIFIER
+#define OPENMP_NEED_DEVICE_PTR_MODIFIER(Name)
#endif
// Static attributes for 'schedule' clause.
@@ -265,8 +265,8 @@ OPENMP_THREADSET_KIND(omp_pool)
OPENMP_THREADSET_KIND(omp_team)
// OpenMP 6.1 modifiers for 'adjust_args' clause.
-OPENMP_NEEDDEVICE_MODIFIER(fp_nullify)
-OPENMP_NEEDDEVICE_MODIFIER(fp_preserve)
+OPENMP_NEED_DEVICE_PTR_MODIFIER(fb_nullify)
+OPENMP_NEED_DEVICE_PTR_MODIFIER(fb_preserve)
#undef OPENMP_NUMTASKS_MODIFIER
#undef OPENMP_NUMTHREADS_MODIFIER
@@ -298,4 +298,4 @@ OPENMP_NEEDDEVICE_MODIFIER(fp_preserve)
#undef OPENMP_DOACROSS_MODIFIER
#undef OPENMP_ALLOCATE_MODIFIER
#undef OPENMP_THREADSET_KIND
-#undef OPENMP_NEEDDEVICE_MODIFIER
+#undef OPENMP_NEED_DEVICE_PTR_MODIFIER
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index 436868d467963..b9905b250ebc2 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -212,10 +212,10 @@ enum OpenMPAdjustArgsOpKind {
};
/// OpenMP 6.1 need_device modifier
-enum OpenMPNeedDeviceModifier {
-#define OPENMP_NEEDDEVICE_MODIFIER(Name) OMPC_NEEDDEVICE_##Name,
+enum OpenMPNeedDevicePtrModifier {
+#define OPENMP_NEED_DEVICE_PTR_MODIFIER(Name) OMPC_NEED_DEVICE_PTR_##Name,
#include "clang/Basic/OpenMPKinds.def"
- OMPC_NEEDDEVICE_unknown,
+ OMPC_NEED_DEVICE_PTR_unknown,
};
/// OpenMP bindings for the 'bind' clause.
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index be6ed746a28ec..6ce4ee12fda6c 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4933,7 +4933,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Tok.is(tok::colon))
Data.ColonLoc = Tok.getLocation();
if (getLangOpts().OpenMP >= 61) {
- // Handle optional need_device_ptr modifier.
+ // Handle the optional fallback argument for the need_device_ptr
+ // modifier.
if (Tok.is(tok::l_paren)) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -4941,11 +4942,10 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
std::string Modifier = PP.getSpelling(Tok);
if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
Data.NeedDevicePtrModifier = Modifier == "fb_nullify"
- ? OMPC_NEEDDEVICE_fp_nullify
- : OMPC_NEEDDEVICE_fp_preserve;
+ ? OMPC_NEED_DEVICE_PTR_fb_nullify
+ : OMPC_NEED_DEVICE_PTR_fb_preserve;
} else {
- Diag(Tok, diag::err_omp_unknown_need_device_ptr_modifier)
- << (getLangOpts().OpenMP >= 60 ? 1 : 0);
+ Diag(Tok, diag::err_omp_unknown_need_device_ptr_modifier);
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
return false;
diff --git a/clang/test/OpenMP/need_device_modifier_messages.cpp b/clang/test/OpenMP/need_device_modifier_messages.cpp
deleted file mode 100644
index 491266b9ea331..0000000000000
--- a/clang/test/OpenMP/need_device_modifier_messages.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s
-
-void __attribute__((noinline)) device_impl(int *xp, int *&xpref, int n) {}
-
-#pragma omp declare variant(device_impl) \
- adjust_args(need_device_ptr(foo) : xp, xpref) // expected-error{{unknown modifier in 'need_device_ptr' clause (OpenMP 6.1 or later only)}} // expected-error{{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
-void __attribute__((noinline)) host_entry_a(int *xp, int *&xpref, int n) {}
-
-int main() {
- int x;
- int *xp = &x;
-
- host_entry_a(xp, xp, 1);
- return 0;
-}
diff --git a/clang/test/OpenMP/need_device_modifier_ast_print.cpp b/clang/test/OpenMP/need_device_ptr_modifier_ast_print.cpp
similarity index 60%
rename from clang/test/OpenMP/need_device_modifier_ast_print.cpp
rename to clang/test/OpenMP/need_device_ptr_modifier_ast_print.cpp
index 9d25a1290af44..ae8c5550ed6ab 100644
--- a/clang/test/OpenMP/need_device_modifier_ast_print.cpp
+++ b/clang/test/OpenMP/need_device_ptr_modifier_ast_print.cpp
@@ -1,15 +1,16 @@
-// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 -ast-print %s \
+// RUN: | FileCheck %s
// expected-no-diagnostics
void __attribute__((noinline)) device_impl(int *xp, int *&xpref, int n) {}
-#pragma omp declare variant(device_impl) \
- adjust_args(need_device_ptr(fb_nullify) : xp, xpref)
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_nullify) : xp, xpref)
void __attribute__((noinline)) host_entry_a(int *xp, int *&xpref, int n) {}
-#pragma omp declare variant(device_impl) \
- adjust_args(need_device_ptr(fb_preserve) : xp, xpref)
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_preserve) : xp, xpref)
void __attribute__((noinline)) host_entry_b(int *xp, int *&xpref, int n) {}
// CHECK-LABEL: int main()
diff --git a/clang/test/OpenMP/need_device_ptr_modifier_messages.cpp b/clang/test/OpenMP/need_device_ptr_modifier_messages.cpp
new file mode 100644
index 0000000000000..0ac1a7e95b81f
--- /dev/null
+++ b/clang/test/OpenMP/need_device_ptr_modifier_messages.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -verify=omp61 -fopenmp -fopenmp-version=61 %s
+
+void __attribute__((noinline)) device_impl(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(foo) : xp, xpref) // omp61-error{{invalid argument for 'need_device_ptr' modifier in 'adjust_args' clause. Expected 'fp_nullify' or 'fb_preserve'}} // omp61-error{{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
+void __attribute__((noinline)) host_entry_a(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_nullify) : xp, xpref)
+void __attribute__((noinline)) host_entry_b(int *xp, int *&xpref, int n) {}
+
+#pragma omp declare variant(device_impl) \
+ adjust_args(need_device_ptr(fb_preserve) : xp, xpref)
+void __attribute__((noinline)) host_entry_c(int *xp, int *&xpref, int n) {}
+
+
+int main() {
+ int x;
+ int *xp = &x;
+
+ host_entry_a(xp, xp, 1);
+ host_entry_b(xp, xp, 1);
+ host_entry_c(xp, xp, 1);
+ return 0;
+}
>From 4cb7b79008c0d4dc9a9a15db2c5fdf44a26116ae Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 21 Nov 2025 11:42:50 -0800
Subject: [PATCH 3/3] Fix format
---
clang/lib/Parse/ParseOpenMP.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 6ce4ee12fda6c..04fad70b24123 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4941,9 +4941,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Tok.is(tok::identifier)) {
std::string Modifier = PP.getSpelling(Tok);
if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
- Data.NeedDevicePtrModifier = Modifier == "fb_nullify"
- ? OMPC_NEED_DEVICE_PTR_fb_nullify
- : OMPC_NEED_DEVICE_PTR_fb_preserve;
+ Data.NeedDevicePtrModifier =
+ Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
+ : OMPC_NEED_DEVICE_PTR_fb_preserve;
} else {
Diag(Tok, diag::err_omp_unknown_need_device_ptr_modifier);
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
More information about the cfe-commits
mailing list