[clang] 453e02c - [OpenMP] Add support for declare target initializer expressions

Sandeep Kosuri via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 1 03:28:51 PDT 2023


Author: Ritanya B Bharadwaj
Date: 2023-06-01T05:27:23-05:00
New Revision: 453e02ca0903c9f65529d21c513925ab0fdea1e1

URL: https://github.com/llvm/llvm-project/commit/453e02ca0903c9f65529d21c513925ab0fdea1e1
DIFF: https://github.com/llvm/llvm-project/commit/453e02ca0903c9f65529d21c513925ab0fdea1e1.diff

LOG: [OpenMP] Add support for declare target initializer expressions

Initial support for OpenMP 5.0 declare target "as if" behavior for "initializer expressions".
OpenMP 5.0, 2.12.7 declare target.

Reviewed By: Alexey

Differential Revision: https://reviews.llvm.org/D146418

Added: 
    clang/test/OpenMP/declare_target_variables_ast_print.cpp

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/test/OpenMP/declare_target_messages.cpp
    clang/test/OpenMP/nvptx_target_exceptions_messages.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index afbc895cfd28..d2cb0ef261fb 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11324,6 +11324,11 @@ class Sema final {
   void
   checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
                                    SourceLocation IdLoc = SourceLocation());
+
+  /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
+  /// directive.
+  void ActOnOpenMPDeclareTargetInitializer(Decl *D);
+
   /// Finishes analysis of the deferred functions calls that may be declared as
   /// host/nohost during device/host compilation.
   void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d7c595b4201f..b8aba816283d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14476,6 +14476,12 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
 
   for (unsigned i = 0, e = Group.size(); i != e; ++i) {
     if (Decl *D = Group[i]) {
+      // Check if the Decl has been declared in '#pragma omp declare target'
+      // directive and has static storage duration.
+      if (auto *VD = dyn_cast<VarDecl>(D);
+          LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
+          VD->hasGlobalStorage())
+        ActOnOpenMPDeclareTargetInitializer(D);
       // For declarators, there are some additional syntactic-ish checks we need
       // to perform.
       if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 45cbfa6eeff1..6e83e20d96d5 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23100,6 +23100,55 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
   checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
 }
 
+/// This class visits every VarDecl that the initializer references and adds
+/// OMPDeclareTargetDeclAttr to each of them.
+class GlobalDeclRefChecker final
+    : public StmtVisitor<GlobalDeclRefChecker> {
+  SmallVector<VarDecl *> DeclVector;
+  Attr *A;
+
+public:
+  /// A StmtVisitor class function that visits all DeclRefExpr and adds
+  /// OMPDeclareTargetDeclAttr to them.
+  void VisitDeclRefExpr(DeclRefExpr *Node) {
+    if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
+      VD->addAttr(A);
+      DeclVector.push_back(VD);
+    }
+  }
+  /// A function that iterates across each of the Expr's children.
+  void VisitExpr(Expr *Ex) {
+    for (auto *Child : Ex->children()) {
+      Visit(Child);
+    }
+  }
+  /// A function that keeps a record of all the Decls that are variables, has
+  /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
+  /// each Decl one at a time and use the inherited 'visit' functions to look
+  /// for DeclRefExpr.
+  void declareTargetInitializer(Decl *TD) {
+    A = TD->getAttr<OMPDeclareTargetDeclAttr>();
+    DeclVector.push_back(cast<VarDecl>(TD));
+    while (!DeclVector.empty()) {
+      VarDecl *TargetVarDecl = DeclVector.pop_back_val();
+      if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
+          TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
+        if (Expr *Ex = TargetVarDecl->getInit())
+          Visit(Ex);
+      }
+    }
+  }
+};
+
+/// Adding OMPDeclareTargetDeclAttr to variables with static storage
+/// duration that are referenced in the initializer expression list of
+/// variables with static storage duration in declare target directive.
+void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
+  GlobalDeclRefChecker Checker;
+  if (auto *TargetVarDecl = dyn_cast_or_null<VarDecl>(TargetDecl))
+    Checker.declareTargetInitializer(TargetDecl);
+}
+
 OMPClause *Sema::ActOnOpenMPToClause(
     ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
     ArrayRef<SourceLocation> MotionModifiersLoc,

diff  --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp
index ed011a8c3a59..482d3dc8cff3 100644
--- a/clang/test/OpenMP/declare_target_messages.cpp
+++ b/clang/test/OpenMP/declare_target_messages.cpp
@@ -233,6 +233,42 @@ int MultiDevTy;
 #pragma omp declare target to(MultiDevTy) device_type(host)   // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}} omp51-error {{'device_type(host)' does not match previously specified 'device_type(any)' for the same declaration}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
 #pragma omp declare target to(MultiDevTy) device_type(nohost) // omp45-error {{unexpected 'device_type' clause, only 'to' or 'link' clauses expected}} omp5-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}} // omp51-error {{'device_type(nohost)' does not match previously specified 'device_type(any)' for the same declaration}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
 
+static int variable = 100;  //expected-warning {{declaration is not declared in any declare target region}}
+static float variable1 = 200;
+static float variable2 = variable1;  //expected-warning {{declaration is not declared in any declare target region}}
+
+static int var = 1;  //expected-warning {{declaration is not declared in any declare target region}}
+
+static int var1 = 10;
+static int *var2 = &var1;
+static int **ptr1 = &var2;  //expected-warning {{declaration is not declared in any declare target region}}
+
+int arr[2] = {1,2};
+int (*arrptr)[2] = &arr;  //expected-warning {{declaration is not declared in any declare target region}}
+
+class declare{
+  public: int x;
+          void print();
+};
+declare obj1;
+declare *obj2 = &obj1;  //expected-warning {{declaration is not declared in any declare target region}}
+
+struct target{
+  int x;
+  void print();
+};
+static target S;  //expected-warning {{declaration is not declared in any declare target region}}
+
+#pragma omp declare target
+int target_var = variable;  //expected-note {{used here}}
+float target_var1 = variable2;  //expected-note {{used here}}
+int *ptr = &var;  //expected-note {{used here}}
+int ***ptr2 = &ptr1;  //expected-note {{used here}}
+int (**ptr3)[2] = &arrptr;  //expected-note {{used here}}
+declare **obj3 = &obj2;  //expected-note {{used here}}
+target *S1 = &S; //expected-note {{used here}}
+#pragma omp end declare target
+
 #if TESTENDINC
 #include "unterminated_declare_target_include.h"
 #elif TESTEND

diff  --git a/clang/test/OpenMP/declare_target_variables_ast_print.cpp b/clang/test/OpenMP/declare_target_variables_ast_print.cpp
new file mode 100644
index 000000000000..1e37efe20989
--- /dev/null
+++ b/clang/test/OpenMP/declare_target_variables_ast_print.cpp
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 -w -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK
+// expected-no-diagnostics
+
+static int variable = 100;
+static float variable1 = 200;
+static float variable2 = variable1;
+
+static int var = 1;
+
+static int var1 = 10;
+static int *var2 = &var1;
+static int **ptr1 = &var2;
+
+int arr[2] = {1,2};
+int (*arrptr)[2] = &arr;
+
+class declare{
+  public: int x;
+          void print();
+};
+declare obj1;
+declare *obj2 = &obj1;
+
+struct target{
+  int x;
+  void print();
+};
+static target S;
+
+#pragma omp declare target
+int target_var = variable;
+float target_var1 = variable2;
+int *ptr = &var;
+int ***ptr2 = &ptr1;
+int (**ptr3)[2] = &arrptr;
+declare **obj3 = &obj2;
+target *S1 = &S;
+#pragma omp end declare target
+// CHECK: #pragma omp declare target
+// CHECK-NEXT: static int variable = 100;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static float variable1 = 200;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static float variable2 = variable1;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK: #pragma omp declare target
+// CHECK-NEXT: static int var = 1;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static int var1 = 10;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static int *var2 = &var1;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static int **ptr1 = &var2;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int arr[2] = {1, 2};
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int (*arrptr)[2] = &arr;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: class declare {
+// CHECK-NEXT: public:
+// CHECK-NEXT:  int x;
+// CHECK-NEXT:  void print();
+// CHECK-NEXT: };
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: declare obj1;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: declare *obj2 = &obj1;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: struct target {
+// CHECK-NEXT:  int x;
+// CHECK-NEXT:  void print();
+// CHECK-NEXT: };
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: static target S;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int target_var = variable;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: float target_var1 = variable2;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int *ptr = &var;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int ***ptr2 = &ptr1;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: int (**ptr3)[2] = &arrptr;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: declare **obj3 = &obj2;
+// CHECK-NEXT: #pragma omp end declare target
+// CHECK-NEXT: #pragma omp declare target
+// CHECK-NEXT: target *S1 = &S;
+// CHECK-NEXT: #pragma omp end declare target
+

diff  --git a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
index 87ea00a90822..a0e9b98d837a 100644
--- a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
+++ b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp
@@ -95,7 +95,7 @@ int (*C)() = &foobar3; // expected-warning {{declaration is not declared in any
 int (*D)() = C; // expected-note {{used here}}
                 // host-note at -1 {{used here}}
 #pragma omp end declare target
-int foobar3() { throw 1; }
+int foobar3() { throw 1; } // expected-error {{cannot use 'throw' with exceptions disabled}}
 
 // Check no infinite recursion in deferred diagnostic emitter.
 long E = (long)&E;


        


More information about the cfe-commits mailing list