Skip to content

Commit

Permalink
[flang][OpenMP] Add semantic check for declare target (#72770)
Browse files Browse the repository at this point in the history
  • Loading branch information
shraiysh committed Nov 22, 2023
1 parent 7f215b1 commit 8840eb3
Show file tree
Hide file tree
Showing 24 changed files with 817 additions and 22 deletions.
1 change: 1 addition & 0 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3369,6 +3369,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_exclusive:
case OMPC_affinity:
case OMPC_doacross:
case OMPC_enter:
if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
CKind == OMPC_depend)
Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
Expand Down
14 changes: 13 additions & 1 deletion clang/test/OpenMP/target_enter_data_nowait_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,26 @@ int main(int argc, char **argv) {
int i;

#pragma omp nowait target enter data map(to: i) // expected-error {{expected an OpenMP directive}}
#pragma omp target nowait enter data map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}}
{}
#pragma omp target nowait foo data map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}}
{}
#pragma omp target nowait enter data map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} expected-error {{unexpected OpenMP clause 'enter' in directive '#pragma omp target'}} expected-error {{expected '(' after 'enter'}}
{}
#pragma omp target enter nowait data map(to: i) // expected-error {{expected an OpenMP directive}}
{}
#pragma omp target enter data nowait() map(to: i) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}} expected-error {{expected at least one 'map' clause for '#pragma omp target enter data'}}
{}
#pragma omp target enter data map(to: i) nowait( // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}}
{}
#pragma omp target enter data map(to: i) nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}}
{}
#pragma omp target enter data map(to: i) nowait device (-10u)
{}
#pragma omp target enter data map(to: i) nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target enter data' are ignored}}
{}
#pragma omp target enter data map(to: i) nowait nowait // expected-error {{directive '#pragma omp target enter data' cannot contain more than one 'nowait' clause}}
{}
#pragma omp target enter data nowait map(to: i) nowait // expected-error {{directive '#pragma omp target enter data' cannot contain more than one 'nowait' clause}}
{}
return 0;
}
15 changes: 15 additions & 0 deletions flang/lib/Lower/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ class ClauseProcessor {
bool processDepend(llvm::SmallVectorImpl<mlir::Attribute> &dependTypeOperands,
llvm::SmallVectorImpl<mlir::Value> &dependOperands) const;
bool
processEnter(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
bool
processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName,
mlir::Value &result) const;
bool
Expand Down Expand Up @@ -1851,6 +1853,18 @@ bool ClauseProcessor::processTo(
});
}

bool ClauseProcessor::processEnter(
llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const {
return findRepeatableClause<ClauseTy::Enter>(
[&](const ClauseTy::Enter *enterClause,
const Fortran::parser::CharBlock &) {
// Case: declare target enter(func, var1, var2)...
gatherFuncAndVarSyms(enterClause->v,
mlir::omp::DeclareTargetCaptureClause::enter,
result);
});
}

bool ClauseProcessor::processUseDeviceAddr(
llvm::SmallVectorImpl<mlir::Value> &operands,
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
Expand Down Expand Up @@ -2792,6 +2806,7 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo(

ClauseProcessor cp(converter, *clauseList);
cp.processTo(symbolAndClause);
cp.processEnter(symbolAndClause);
cp.processLink(symbolAndClause);
cp.processDeviceType(deviceType);
cp.processTODO<Fortran::parser::OmpClause::Indirect>(
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ TYPE_PARSER(
parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
"DYNAMIC_ALLOCATORS" >>
construct<OmpClause>(construct<OmpClause::DynamicAllocators>()) ||
"ENTER" >> construct<OmpClause>(construct<OmpClause::Enter>(
parenthesized(Parser<OmpObjectList>{}))) ||
"FINAL" >> construct<OmpClause>(construct<OmpClause::Final>(
parenthesized(scalarLogicalExpr))) ||
"FULL" >> construct<OmpClause>(construct<OmpClause::Full>()) ||
Expand Down
51 changes: 39 additions & 12 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,13 +1165,31 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
}
}

void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithClause &x) {
SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
}

void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
if (x.v.v.size() > 0) {
const parser::OmpClause *enterClause =
FindClause(llvm::omp::Clause::OMPC_enter);
const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
const parser::OmpClause *linkClause =
FindClause(llvm::omp::Clause::OMPC_link);
if (!enterClause && !toClause && !linkClause) {
context_.Say(x.source,
"If the DECLARE TARGET directive has a clause, it must contain at lease one ENTER clause or LINK clause"_err_en_US);
}
if (toClause) {
context_.Say(toClause->source,
"The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
}
}
}

void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
if (std::holds_alternative<parser::OmpDeclareTargetWithClause>(spec.u)) {
SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
}
}

void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
Expand Down Expand Up @@ -1245,7 +1263,8 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
CheckThreadprivateOrDeclareTargetVar(*objectList);
} else if (const auto *clauseList{
parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
bool toClauseFound{false}, deviceTypeClauseFound{false};
bool toClauseFound{false}, deviceTypeClauseFound{false},
enterClauseFound{false};
for (const auto &clause : clauseList->v) {
common::visit(
common::visitors{
Expand All @@ -1260,6 +1279,12 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
CheckIsVarPartOfAnotherVar(dir.source, linkClause.v);
CheckThreadprivateOrDeclareTargetVar(linkClause.v);
},
[&](const parser::OmpClause::Enter &enterClause) {
enterClauseFound = true;
CheckSymbolNames(dir.source, enterClause.v);
CheckIsVarPartOfAnotherVar(dir.source, enterClause.v);
CheckThreadprivateOrDeclareTargetVar(enterClause.v);
},
[&](const parser::OmpClause::DeviceType &deviceTypeClause) {
deviceTypeClauseFound = true;
if (deviceTypeClause.v.v !=
Expand All @@ -1273,7 +1298,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
},
clause.u);

if (toClauseFound && !deviceTypeClauseFound) {
if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
deviceConstructFound_ = true;
}
}
Expand Down Expand Up @@ -2228,6 +2253,7 @@ CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)
CHECK_SIMPLE_CLAUSE(Doacross, OMPC_doacross)
CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute)
CHECK_SIMPLE_CLAUSE(OmpxBare, OMPC_ompx_bare)
CHECK_SIMPLE_CLAUSE(Enter, OMPC_enter)

CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)
Expand Down Expand Up @@ -3240,12 +3266,13 @@ const parser::OmpObjectList *OmpStructureChecker::GetOmpObjectList(
const parser::OmpClause &clause) {

// Clauses with OmpObjectList as its data member
using MemberObjectListClauses = std::tuple<parser::OmpClause::Copyprivate,
parser::OmpClause::Copyin, parser::OmpClause::Firstprivate,
parser::OmpClause::From, parser::OmpClause::Lastprivate,
parser::OmpClause::Link, parser::OmpClause::Private,
parser::OmpClause::Shared, parser::OmpClause::To,
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;
using MemberObjectListClauses =
std::tuple<parser::OmpClause::Copyprivate, parser::OmpClause::Copyin,
parser::OmpClause::Firstprivate, parser::OmpClause::From,
parser::OmpClause::Lastprivate, parser::OmpClause::Link,
parser::OmpClause::Private, parser::OmpClause::Shared,
parser::OmpClause::To, parser::OmpClause::Enter,
parser::OmpClause::UseDevicePtr, parser::OmpClause::UseDeviceAddr>;

// Clauses with OmpObjectList in the tuple
using TupleObjectListClauses =
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Semantics/check-omp-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class OmpStructureChecker
void Enter(const parser::OpenMPDeclareTargetConstruct &);
void Leave(const parser::OpenMPDeclareTargetConstruct &);
void Enter(const parser::OmpDeclareTargetWithList &);
void Enter(const parser::OmpDeclareTargetWithClause &);
void Leave(const parser::OmpDeclareTargetWithClause &);
void Enter(const parser::OpenMPExecutableAllocate &);
void Leave(const parser::OpenMPExecutableAllocate &);
void Enter(const parser::OpenMPAllocatorsConstruct &);
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,9 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) {
} else if (const auto *linkClause{
std::get_if<parser::OmpClause::Link>(&clause.u)}) {
ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget);
} else if (const auto *enterClause{
std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
ResolveOmpObjectList(enterClause->v, Symbol::Flag::OmpDeclareTarget);
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions flang/test/Lower/OpenMP/FIR/declare-target-data.f90
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ module test_0
INTEGER :: data_int_to = 5
!$omp declare target to(data_int_to)

!CHECK-DAG: fir.global @_QMtest_0Edata_int_enter {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} : i32
INTEGER :: data_int_enter = 5
!$omp declare target enter(data_int_enter)

!CHECK-DAG: fir.global @_QMtest_0Edata_int_clauseless {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} : i32
INTEGER :: data_int_clauseless = 1
!$omp declare target(data_int_clauseless)
Expand All @@ -42,6 +46,12 @@ module test_0
REAL :: data_extended_to_2 = 3
!$omp declare target to(data_extended_to_1, data_extended_to_2)

!CHECK-DAG: fir.global @_QMtest_0Edata_extended_enter_1 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} : f32
!CHECK-DAG: fir.global @_QMtest_0Edata_extended_enter_2 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} : f32
REAL :: data_extended_enter_1 = 2
REAL :: data_extended_enter_2 = 3
!$omp declare target enter(data_extended_enter_1, data_extended_enter_2)

!CHECK-DAG: fir.global @_QMtest_0Edata_extended_link_1 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : f32
!CHECK-DAG: fir.global @_QMtest_0Edata_extended_link_2 {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (link)>} : f32
REAL :: data_extended_link_1 = 2
Expand Down Expand Up @@ -69,4 +79,10 @@ PROGRAM commons
REAL :: two_to = 2
COMMON /numbers_to/ one_to, two_to
!$omp declare target to(/numbers_to/)

!CHECK-DAG: fir.global @numbers_enter_ {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>} : tuple<f32, f32> {
REAL :: one_enter = 1
REAL :: two_enter = 2
COMMON /numbers_enter/ one_enter, two_enter
!$omp declare target enter(/numbers_enter/)
END
68 changes: 68 additions & 0 deletions flang/test/Lower/OpenMP/FIR/declare-target-func-and-subr.f90
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ FUNCTION FUNC_T_DEVICE() RESULT(I)
I = 1
END FUNCTION FUNC_T_DEVICE

! DEVICE-LABEL: func.func @_QPfunc_enter_device()
! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>{{.*}}
FUNCTION FUNC_ENTER_DEVICE() RESULT(I)
!$omp declare target enter(FUNC_ENTER_DEVICE) device_type(nohost)
INTEGER :: I
I = 1
END FUNCTION FUNC_ENTER_DEVICE

! HOST-LABEL: func.func @_QPfunc_t_host()
! HOST-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>{{.*}}
FUNCTION FUNC_T_HOST() RESULT(I)
Expand All @@ -21,6 +29,14 @@ FUNCTION FUNC_T_HOST() RESULT(I)
I = 1
END FUNCTION FUNC_T_HOST

! HOST-LABEL: func.func @_QPfunc_enter_host()
! HOST-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter)>{{.*}}
FUNCTION FUNC_ENTER_HOST() RESULT(I)
!$omp declare target enter(FUNC_ENTER_HOST) device_type(host)
INTEGER :: I
I = 1
END FUNCTION FUNC_ENTER_HOST

! ALL-LABEL: func.func @_QPfunc_t_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
FUNCTION FUNC_T_ANY() RESULT(I)
Expand All @@ -29,6 +45,14 @@ FUNCTION FUNC_T_ANY() RESULT(I)
I = 1
END FUNCTION FUNC_T_ANY

! ALL-LABEL: func.func @_QPfunc_enter_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}
FUNCTION FUNC_ENTER_ANY() RESULT(I)
!$omp declare target enter(FUNC_ENTER_ANY) device_type(any)
INTEGER :: I
I = 1
END FUNCTION FUNC_ENTER_ANY

! ALL-LABEL: func.func @_QPfunc_default_t_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
FUNCTION FUNC_DEFAULT_T_ANY() RESULT(I)
Expand All @@ -37,6 +61,14 @@ FUNCTION FUNC_DEFAULT_T_ANY() RESULT(I)
I = 1
END FUNCTION FUNC_DEFAULT_T_ANY

! ALL-LABEL: func.func @_QPfunc_default_enter_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}
FUNCTION FUNC_DEFAULT_ENTER_ANY() RESULT(I)
!$omp declare target enter(FUNC_DEFAULT_ENTER_ANY)
INTEGER :: I
I = 1
END FUNCTION FUNC_DEFAULT_ENTER_ANY

! ALL-LABEL: func.func @_QPfunc_default_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
FUNCTION FUNC_DEFAULT_ANY() RESULT(I)
Expand Down Expand Up @@ -65,24 +97,48 @@ SUBROUTINE SUBR_T_DEVICE()
!$omp declare target to(SUBR_T_DEVICE) device_type(nohost)
END

! DEVICE-LABEL: func.func @_QPsubr_enter_device()
! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>{{.*}}
SUBROUTINE SUBR_ENTER_DEVICE()
!$omp declare target enter(SUBR_ENTER_DEVICE) device_type(nohost)
END

! HOST-LABEL: func.func @_QPsubr_t_host()
! HOST-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>{{.*}}
SUBROUTINE SUBR_T_HOST()
!$omp declare target to(SUBR_T_HOST) device_type(host)
END

! HOST-LABEL: func.func @_QPsubr_enter_host()
! HOST-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter)>{{.*}}
SUBROUTINE SUBR_ENTER_HOST()
!$omp declare target enter(SUBR_ENTER_HOST) device_type(host)
END

! ALL-LABEL: func.func @_QPsubr_t_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
SUBROUTINE SUBR_T_ANY()
!$omp declare target to(SUBR_T_ANY) device_type(any)
END

! ALL-LABEL: func.func @_QPsubr_enter_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}
SUBROUTINE SUBR_ENTER_ANY()
!$omp declare target enter(SUBR_ENTER_ANY) device_type(any)
END

! ALL-LABEL: func.func @_QPsubr_default_t_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
SUBROUTINE SUBR_DEFAULT_T_ANY()
!$omp declare target to(SUBR_DEFAULT_T_ANY)
END

! ALL-LABEL: func.func @_QPsubr_default_enter_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}
SUBROUTINE SUBR_DEFAULT_ENTER_ANY()
!$omp declare target enter(SUBR_DEFAULT_ENTER_ANY)
END

! ALL-LABEL: func.func @_QPsubr_default_any()
! ALL-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>{{.*}}
SUBROUTINE SUBR_DEFAULT_ANY()
Expand All @@ -108,3 +164,15 @@ RECURSIVE FUNCTION RECURSIVE_DECLARE_TARGET(INCREMENT) RESULT(K)
K = RECURSIVE_DECLARE_TARGET(INCREMENT + 1)
END IF
END FUNCTION RECURSIVE_DECLARE_TARGET

! DEVICE-LABEL: func.func @_QPrecursive_declare_target_enter
! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>{{.*}}
RECURSIVE FUNCTION RECURSIVE_DECLARE_TARGET_ENTER(INCREMENT) RESULT(K)
!$omp declare target enter(RECURSIVE_DECLARE_TARGET_ENTER) device_type(nohost)
INTEGER :: INCREMENT, K
IF (INCREMENT == 10) THEN
K = INCREMENT
ELSE
K = RECURSIVE_DECLARE_TARGET_ENTER(INCREMENT + 1)
END IF
END FUNCTION RECURSIVE_DECLARE_TARGET_ENTER

0 comments on commit 8840eb3

Please sign in to comment.