Skip to content

Commit 453e02c

Browse files
Ritanya-B-BharadwajSandeep Kosuri
authored andcommitted
[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
1 parent eb764a7 commit 453e02c

File tree

6 files changed

+209
-1
lines changed

6 files changed

+209
-1
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11324,6 +11324,11 @@ class Sema final {
1132411324
void
1132511325
checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
1132611326
SourceLocation IdLoc = SourceLocation());
11327+
11328+
/// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
11329+
/// directive.
11330+
void ActOnOpenMPDeclareTargetInitializer(Decl *D);
11331+
1132711332
/// Finishes analysis of the deferred functions calls that may be declared as
1132811333
/// host/nohost during device/host compilation.
1132911334
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14476,6 +14476,12 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
1447614476

1447714477
for (unsigned i = 0, e = Group.size(); i != e; ++i) {
1447814478
if (Decl *D = Group[i]) {
14479+
// Check if the Decl has been declared in '#pragma omp declare target'
14480+
// directive and has static storage duration.
14481+
if (auto *VD = dyn_cast<VarDecl>(D);
14482+
LangOpts.OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
14483+
VD->hasGlobalStorage())
14484+
ActOnOpenMPDeclareTargetInitializer(D);
1447914485
// For declarators, there are some additional syntactic-ish checks we need
1448014486
// to perform.
1448114487
if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23100,6 +23100,55 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
2310023100
checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
2310123101
}
2310223102

23103+
/// This class visits every VarDecl that the initializer references and adds
23104+
/// OMPDeclareTargetDeclAttr to each of them.
23105+
class GlobalDeclRefChecker final
23106+
: public StmtVisitor<GlobalDeclRefChecker> {
23107+
SmallVector<VarDecl *> DeclVector;
23108+
Attr *A;
23109+
23110+
public:
23111+
/// A StmtVisitor class function that visits all DeclRefExpr and adds
23112+
/// OMPDeclareTargetDeclAttr to them.
23113+
void VisitDeclRefExpr(DeclRefExpr *Node) {
23114+
if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23115+
VD->addAttr(A);
23116+
DeclVector.push_back(VD);
23117+
}
23118+
}
23119+
/// A function that iterates across each of the Expr's children.
23120+
void VisitExpr(Expr *Ex) {
23121+
for (auto *Child : Ex->children()) {
23122+
Visit(Child);
23123+
}
23124+
}
23125+
/// A function that keeps a record of all the Decls that are variables, has
23126+
/// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23127+
/// each Decl one at a time and use the inherited 'visit' functions to look
23128+
/// for DeclRefExpr.
23129+
void declareTargetInitializer(Decl *TD) {
23130+
A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23131+
DeclVector.push_back(cast<VarDecl>(TD));
23132+
while (!DeclVector.empty()) {
23133+
VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23134+
if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23135+
TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23136+
if (Expr *Ex = TargetVarDecl->getInit())
23137+
Visit(Ex);
23138+
}
23139+
}
23140+
}
23141+
};
23142+
23143+
/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23144+
/// duration that are referenced in the initializer expression list of
23145+
/// variables with static storage duration in declare target directive.
23146+
void Sema::ActOnOpenMPDeclareTargetInitializer(Decl *TargetDecl) {
23147+
GlobalDeclRefChecker Checker;
23148+
if (auto *TargetVarDecl = dyn_cast_or_null<VarDecl>(TargetDecl))
23149+
Checker.declareTargetInitializer(TargetDecl);
23150+
}
23151+
2310323152
OMPClause *Sema::ActOnOpenMPToClause(
2310423153
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
2310523154
ArrayRef<SourceLocation> MotionModifiersLoc,

clang/test/OpenMP/declare_target_messages.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,42 @@ int MultiDevTy;
233233
#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}}
234234
#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}}
235235

236+
static int variable = 100; //expected-warning {{declaration is not declared in any declare target region}}
237+
static float variable1 = 200;
238+
static float variable2 = variable1; //expected-warning {{declaration is not declared in any declare target region}}
239+
240+
static int var = 1; //expected-warning {{declaration is not declared in any declare target region}}
241+
242+
static int var1 = 10;
243+
static int *var2 = &var1;
244+
static int **ptr1 = &var2; //expected-warning {{declaration is not declared in any declare target region}}
245+
246+
int arr[2] = {1,2};
247+
int (*arrptr)[2] = &arr; //expected-warning {{declaration is not declared in any declare target region}}
248+
249+
class declare{
250+
public: int x;
251+
void print();
252+
};
253+
declare obj1;
254+
declare *obj2 = &obj1; //expected-warning {{declaration is not declared in any declare target region}}
255+
256+
struct target{
257+
int x;
258+
void print();
259+
};
260+
static target S; //expected-warning {{declaration is not declared in any declare target region}}
261+
262+
#pragma omp declare target
263+
int target_var = variable; //expected-note {{used here}}
264+
float target_var1 = variable2; //expected-note {{used here}}
265+
int *ptr = &var; //expected-note {{used here}}
266+
int ***ptr2 = &ptr1; //expected-note {{used here}}
267+
int (**ptr3)[2] = &arrptr; //expected-note {{used here}}
268+
declare **obj3 = &obj2; //expected-note {{used here}}
269+
target *S1 = &S; //expected-note {{used here}}
270+
#pragma omp end declare target
271+
236272
#if TESTENDINC
237273
#include "unterminated_declare_target_include.h"
238274
#elif TESTEND
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// RUN: %clang_cc1 -w -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK
2+
// expected-no-diagnostics
3+
4+
static int variable = 100;
5+
static float variable1 = 200;
6+
static float variable2 = variable1;
7+
8+
static int var = 1;
9+
10+
static int var1 = 10;
11+
static int *var2 = &var1;
12+
static int **ptr1 = &var2;
13+
14+
int arr[2] = {1,2};
15+
int (*arrptr)[2] = &arr;
16+
17+
class declare{
18+
public: int x;
19+
void print();
20+
};
21+
declare obj1;
22+
declare *obj2 = &obj1;
23+
24+
struct target{
25+
int x;
26+
void print();
27+
};
28+
static target S;
29+
30+
#pragma omp declare target
31+
int target_var = variable;
32+
float target_var1 = variable2;
33+
int *ptr = &var;
34+
int ***ptr2 = &ptr1;
35+
int (**ptr3)[2] = &arrptr;
36+
declare **obj3 = &obj2;
37+
target *S1 = &S;
38+
#pragma omp end declare target
39+
// CHECK: #pragma omp declare target
40+
// CHECK-NEXT: static int variable = 100;
41+
// CHECK-NEXT: #pragma omp end declare target
42+
43+
// CHECK-NEXT: #pragma omp declare target
44+
// CHECK-NEXT: static float variable1 = 200;
45+
// CHECK-NEXT: #pragma omp end declare target
46+
// CHECK-NEXT: #pragma omp declare target
47+
// CHECK-NEXT: static float variable2 = variable1;
48+
// CHECK-NEXT: #pragma omp end declare target
49+
50+
// CHECK: #pragma omp declare target
51+
// CHECK-NEXT: static int var = 1;
52+
// CHECK-NEXT: #pragma omp end declare target
53+
54+
// CHECK-NEXT: #pragma omp declare target
55+
// CHECK-NEXT: static int var1 = 10;
56+
// CHECK-NEXT: #pragma omp end declare target
57+
// CHECK-NEXT: #pragma omp declare target
58+
// CHECK-NEXT: static int *var2 = &var1;
59+
// CHECK-NEXT: #pragma omp end declare target
60+
// CHECK-NEXT: #pragma omp declare target
61+
// CHECK-NEXT: static int **ptr1 = &var2;
62+
// CHECK-NEXT: #pragma omp end declare target
63+
64+
// CHECK-NEXT: #pragma omp declare target
65+
// CHECK-NEXT: int arr[2] = {1, 2};
66+
// CHECK-NEXT: #pragma omp end declare target
67+
// CHECK-NEXT: #pragma omp declare target
68+
// CHECK-NEXT: int (*arrptr)[2] = &arr;
69+
// CHECK-NEXT: #pragma omp end declare target
70+
71+
// CHECK-NEXT: class declare {
72+
// CHECK-NEXT: public:
73+
// CHECK-NEXT: int x;
74+
// CHECK-NEXT: void print();
75+
// CHECK-NEXT: };
76+
// CHECK-NEXT: #pragma omp declare target
77+
// CHECK-NEXT: declare obj1;
78+
// CHECK-NEXT: #pragma omp end declare target
79+
// CHECK-NEXT: #pragma omp declare target
80+
// CHECK-NEXT: declare *obj2 = &obj1;
81+
// CHECK-NEXT: #pragma omp end declare target
82+
83+
// CHECK-NEXT: struct target {
84+
// CHECK-NEXT: int x;
85+
// CHECK-NEXT: void print();
86+
// CHECK-NEXT: };
87+
// CHECK-NEXT: #pragma omp declare target
88+
// CHECK-NEXT: static target S;
89+
// CHECK-NEXT: #pragma omp end declare target
90+
91+
// CHECK-NEXT: #pragma omp declare target
92+
// CHECK-NEXT: int target_var = variable;
93+
// CHECK-NEXT: #pragma omp end declare target
94+
// CHECK-NEXT: #pragma omp declare target
95+
// CHECK-NEXT: float target_var1 = variable2;
96+
// CHECK-NEXT: #pragma omp end declare target
97+
// CHECK-NEXT: #pragma omp declare target
98+
// CHECK-NEXT: int *ptr = &var;
99+
// CHECK-NEXT: #pragma omp end declare target
100+
// CHECK-NEXT: #pragma omp declare target
101+
// CHECK-NEXT: int ***ptr2 = &ptr1;
102+
// CHECK-NEXT: #pragma omp end declare target
103+
// CHECK-NEXT: #pragma omp declare target
104+
// CHECK-NEXT: int (**ptr3)[2] = &arrptr;
105+
// CHECK-NEXT: #pragma omp end declare target
106+
// CHECK-NEXT: #pragma omp declare target
107+
// CHECK-NEXT: declare **obj3 = &obj2;
108+
// CHECK-NEXT: #pragma omp end declare target
109+
// CHECK-NEXT: #pragma omp declare target
110+
// CHECK-NEXT: target *S1 = &S;
111+
// CHECK-NEXT: #pragma omp end declare target
112+

clang/test/OpenMP/nvptx_target_exceptions_messages.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ int (*C)() = &foobar3; // expected-warning {{declaration is not declared in any
9595
int (*D)() = C; // expected-note {{used here}}
9696
// host-note@-1 {{used here}}
9797
#pragma omp end declare target
98-
int foobar3() { throw 1; }
98+
int foobar3() { throw 1; } // expected-error {{cannot use 'throw' with exceptions disabled}}
9999

100100
// Check no infinite recursion in deferred diagnostic emitter.
101101
long E = (long)&E;

0 commit comments

Comments
 (0)