https://github.com/jtb20 created https://github.com/llvm/llvm-project/pull/92731

This is a minimal patch to support parsing for "omp assume" directives. These 
are meant to be hints to a compiler' optimisers: as such, it is legitimate (if 
not very useful) to ignore them.  The patch builds on top of the existing 
support for "omp assumes" directives (note spelling!).

Unlike the "omp [begin/end] assumes" directives, "omp assume" is associated 
with a compound statement, i.e. it can appear within a function.  The "holds" 
assumption could (theoretically) be mapped onto the existing builtin 
"__builtin_assume", though the latter applies to a single point in the program, 
and the former to a range (i.e. the whole of the associated compound statement).

This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests.

>From 1d2bd6b8083a1220fc6f59cc7c139f0a5e0f84c3 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.br...@amd.com>
Date: Wed, 1 May 2024 06:35:59 -0500
Subject: [PATCH] [OpenMP] OpenMP 5.1 "assume" directive parsing support

This is a minimal patch to support parsing for "omp assume" directives.
These are meant to be hints to a compiler' optimisers: as such, it is
legitimate (if not very useful) to ignore them.  The patch builds on top
of the existing support for "omp assumes" directives (note spelling!).

Unlike the "omp [begin/end] assumes" directives, "omp assume" is
associated with a compound statement, i.e. it can appear within a
function.  The "holds" assumption could (theoretically) be mapped onto
the existing builtin "__builtin_assume", though the latter applies to a
single point in the program, and the former to a range (i.e. the whole
of the associated compound statement).

This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests.

Change-Id: Ibd4a0e2af82c4ac818eaa3de8867a006307361ec
---
 clang/lib/Parse/ParseOpenMP.cpp          | 22 +++++++++++++
 clang/lib/Sema/SemaOpenMP.cpp            |  3 +-
 clang/test/OpenMP/assume_lambda.cpp      | 31 +++++++++++++++++
 clang/test/OpenMP/assume_messages.c      | 23 +++++++++++++
 clang/test/OpenMP/assume_messages_attr.c | 23 +++++++++++++
 clang/test/OpenMP/assume_template.cpp    | 42 ++++++++++++++++++++++++
 llvm/include/llvm/Frontend/OpenMP/OMP.td |  3 ++
 7 files changed, 146 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/OpenMP/assume_lambda.cpp
 create mode 100644 clang/test/OpenMP/assume_messages.c
 create mode 100644 clang/test/OpenMP/assume_messages_attr.c
 create mode 100644 clang/test/OpenMP/assume_template.cpp

diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index e959dd6378f46..5c1bb58227fde 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2450,6 +2450,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
   case OMPD_target_teams_loop:
   case OMPD_parallel_loop:
   case OMPD_target_parallel_loop:
+  case OMPD_assume:
     Diag(Tok, diag::err_omp_unexpected_directive)
         << 1 << getOpenMPDirectiveName(DKind);
     break;
@@ -3035,6 +3036,27 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
         << 1 << getOpenMPDirectiveName(DKind);
     SkipUntil(tok::annot_pragma_openmp_end);
     break;
+  case OMPD_assume: {
+    ParseScope OMPDirectiveScope(this, Scope::FnScope | Scope::DeclScope |
+                                 Scope::CompoundStmtScope);
+    ParseOpenMPAssumesDirective(DKind, ConsumeToken());
+
+    SkipUntil(tok::annot_pragma_openmp_end);
+
+    ParsingOpenMPDirectiveRAII NormalScope(*this);
+    StmtResult AssociatedStmt;
+    {
+      Sema::CompoundScopeRAII Scope(Actions);
+      AssociatedStmt = ParseStatement();
+      EndLoc = Tok.getLocation();
+      Directive = Actions.ActOnCompoundStmt(Loc, EndLoc,
+                                            AssociatedStmt.get(),
+                                            /*isStmtExpr=*/false);
+    }
+    ParseOpenMPEndAssumesDirective(Loc);
+    OMPDirectiveScope.Exit();
+    break;
+  }
   case OMPD_unknown:
   default:
     Diag(Tok, diag::err_omp_unknown_directive);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 6110e5229b076..9ec2bd9c3b802 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3511,7 +3511,8 @@ void 
SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
 
   auto *AA =
       OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), 
Loc);
-  if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
+  if (DKind == llvm::omp::Directive::OMPD_begin_assumes ||
+      DKind == llvm::omp::Directive::OMPD_assume) {
     OMPAssumeScoped.push_back(AA);
     return;
   }
diff --git a/clang/test/OpenMP/assume_lambda.cpp 
b/clang/test/OpenMP/assume_lambda.cpp
new file mode 100644
index 0000000000000..a38380ed4482a
--- /dev/null
+++ b/clang/test/OpenMP/assume_lambda.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -ast-print %s | FileCheck %s
+// expected-no-diagnostics
+
+extern int bar(int);
+
+int foo(int arg)
+{
+  #pragma omp assume no_openmp_routines
+  {
+    auto fn = [](int x) { return bar(x); };
+// CHECK: auto fn = [](int x) {
+    return fn(5);
+  }
+}
+
+class C {
+public:
+  int foo(int a);
+};
+
+// We're really just checking that this parses.  All the assumptions are thrown
+// away immediately for now.
+int C::foo(int a)
+{
+  #pragma omp assume holds(sizeof(T) == 8) absent(parallel)
+  {
+    auto fn = [](int x) { return bar(x); };
+// CHECK: auto fn = [](int x) {
+    return fn(5);
+  }
+}
\ No newline at end of file
diff --git a/clang/test/OpenMP/assume_messages.c 
b/clang/test/OpenMP/assume_messages.c
new file mode 100644
index 0000000000000..33c1c6f7c51e7
--- /dev/null
+++ b/clang/test/OpenMP/assume_messages.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c 
-std=c99 %s
+
+#pragma omp assume no_openmp // expected-error {{unexpected OpenMP directive 
'#pragma omp assume'}}
+
+void foo(void) {
+  #pragma omp assume hold(1==1) // expected-warning {{valid assume clauses 
start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 
'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note 
{{the ignored tokens spans until here}}
+  {}
+}
+
+void bar(void) {
+  #pragma omp assume absent(target)
+} // expected-error {{expected statement}}
+
+void qux(void) {
+  #pragma omp assume extra_bits // expected-warning {{valid assume clauses 
start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 
'no_openmp_routines', 'no_parallelism'; token will be ignored}}
+  {}
+}
+
+void quux(void) {
+  #pragma omp assume ext_spelled_properly
+  {}
+}
diff --git a/clang/test/OpenMP/assume_messages_attr.c 
b/clang/test/OpenMP/assume_messages_attr.c
new file mode 100644
index 0000000000000..47504cc6308ea
--- /dev/null
+++ b/clang/test/OpenMP/assume_messages_attr.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c 
-std=c99 %s
+
+[[omp::directive(assume no_openmp)]] // expected-error {{unexpected OpenMP 
directive '#pragma omp assume'}}
+
+void foo(void) {
+  [[omp::directive(assume hold(1==1))]] // expected-warning {{valid assume 
clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 
'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note 
{{the ignored tokens spans until here}}
+  {}
+}
+
+void bar(void) {
+  [[omp::directive(assume absent(target))]]
+} // expected-error {{expected statement}}
+
+void qux(void) {
+  [[omp::directive(assume extra_bits)]] // expected-warning {{valid assume 
clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 
'no_openmp_routines', 'no_parallelism'; token will be ignored}}
+  {}
+}
+
+void quux(void) {
+  [[omp::directive(assume ext_spelled_properly)]]
+  {}
+}
diff --git a/clang/test/OpenMP/assume_template.cpp 
b/clang/test/OpenMP/assume_template.cpp
new file mode 100644
index 0000000000000..b0591bffb20a6
--- /dev/null
+++ b/clang/test/OpenMP/assume_template.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -verify %s -ast-print | 
FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+extern int qux(int);
+
+template<typename T>
+int foo(T arg)
+{
+  #pragma omp assume no_openmp_routines
+  {
+    auto fn = [](int x) { return qux(x); };
+// CHECK: auto fn = [](int x) {
+    return fn(5);
+  }
+}
+
+template<typename T>
+class C {
+  T m;
+
+public:
+  T bar(T a);
+};
+
+// We're really just checking this parses.  All the assumptions are thrown
+// away immediately for now.
+template<typename T>
+T C<T>::bar(T a)
+{
+  #pragma omp assume holds(sizeof(T) == 8) absent(parallel)
+  {
+    return (T)qux((int)a);
+// CHECK: return (T)qux((int)a);
+  }
+}
+
+#endif
\ No newline at end of file
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td 
b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e91169e8da1aa..3660917e3e176 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -2089,6 +2089,9 @@ def OMP_Scan : Directive<"scan"> {
   ];
   let association = AS_Separating;
 }
+def OMP_Assume : Directive<"assume"> {
+  let association = AS_Block;
+}
 def OMP_Assumes : Directive<"assumes"> {
   let association = AS_None;
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to