[Flang][OpenMP] Add semantic checks for OpenMP copyin clause.

Add the semantic checks for the OpenMP 4.5 - 2.15.4.1 copyin clause.

Resolve OpenMPThreadprivate directive since the list of items specified
in copyin clause should be threadprivate.

Test cases : omp-copyin01.f90, omp-copyin02.f90, omp-copyin03.f90,
             omp-copyin04.f90, omp-copyin05.f90

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D89385
This commit is contained in:
Praveen G 2020-11-04 02:52:04 -05:00
parent 0314dff051
commit a4a4c50370
8 changed files with 197 additions and 13 deletions

View file

@ -503,6 +503,8 @@ public:
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
// OpenMP data-mapping attribute
OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete,
// OpenMP data-copying attribute
OmpCopyIn,
// OpenMP miscellaneous flags
OmpCommonBlock, OmpReduction, OmpAllocate, OmpDeclareSimd,
OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction, OmpFlushed,

View file

@ -223,7 +223,7 @@ public:
bool Pre(const parser::SpecificationPart &x) {
Walk(std::get<std::list<parser::OpenMPDeclarativeConstruct>>(x.t));
return false;
return true;
}
bool Pre(const parser::OpenMPBlockConstruct &);
@ -269,6 +269,10 @@ public:
ResolveOmpObjectList(x.v, Symbol::Flag::OmpLastPrivate);
return false;
}
bool Pre(const parser::OmpClause::Copyin &x) {
ResolveOmpObjectList(x.v, Symbol::Flag::OmpCopyIn);
return false;
}
void Post(const parser::Name &);
@ -292,6 +296,9 @@ private:
static constexpr Symbol::Flags ompFlagsRequireMark{
Symbol::Flag::OmpThreadprivate};
static constexpr Symbol::Flags dataCopyingAttributeFlags{
Symbol::Flag::OmpCopyIn};
std::vector<const parser::Name *> allocateNames_; // on one directive
SymbolSet privateDataSharingAttributeObjects_; // on one directive
@ -320,6 +327,9 @@ private:
Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
void CheckMultipleAppearances(
const parser::Name &, const Symbol &, Symbol::Flag);
void CheckDataCopyingClause(
const parser::Name &, const Symbol &, Symbol::Flag);
};
template <typename T>
@ -869,7 +879,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
const auto &list{std::get<parser::OmpObjectList>(x.t)};
ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate);
return false;
return true;
}
void OmpAttributeVisitor::Post(const parser::OmpDefaultClause &x) {
@ -922,9 +932,14 @@ Symbol *OmpAttributeVisitor::ResolveOmpCommonBlockName(
: nullptr}) {
name->symbol = prev;
return prev;
} else {
return nullptr;
}
// Check if the Common Block is declared in the current scope
if (auto *commonBlockSymbol{
name ? GetContext().scope.FindCommonBlock(name->source) : nullptr}) {
name->symbol = commonBlockSymbol;
return commonBlockSymbol;
}
return nullptr;
}
void OmpAttributeVisitor::ResolveOmpObjectList(
@ -941,6 +956,9 @@ void OmpAttributeVisitor::ResolveOmpObject(
[&](const parser::Designator &designator) {
if (const auto *name{GetDesignatorNameIfDataRef(designator)}) {
if (auto *symbol{ResolveOmp(*name, ompFlag, currScope())}) {
if (dataCopyingAttributeFlags.test(ompFlag)) {
CheckDataCopyingClause(*name, *symbol, ompFlag);
} else {
AddToContextObjectWithDSA(*symbol, ompFlag);
if (dataSharingAttributeFlags.test(ompFlag)) {
CheckMultipleAppearances(*name, *symbol, ompFlag);
@ -949,6 +967,7 @@ void OmpAttributeVisitor::ResolveOmpObject(
AddAllocateName(name);
}
}
}
} else {
// Array sections to be changed to substrings as needed
if (AnalyzeExpr(context_, designator)) {
@ -963,17 +982,23 @@ void OmpAttributeVisitor::ResolveOmpObject(
},
[&](const parser::Name &name) { // common block
if (auto *symbol{ResolveOmpCommonBlockName(&name)}) {
if (!dataCopyingAttributeFlags.test(ompFlag)) {
CheckMultipleAppearances(
name, *symbol, Symbol::Flag::OmpCommonBlock);
}
// 2.15.3 When a named common block appears in a list, it has the
// same meaning as if every explicit member of the common block
// appeared in the list
for (auto &object : symbol->get<CommonBlockDetails>().objects()) {
if (auto *resolvedObject{
ResolveOmp(*object, ompFlag, currScope())}) {
if (dataCopyingAttributeFlags.test(ompFlag)) {
CheckDataCopyingClause(name, *resolvedObject, ompFlag);
} else {
AddToContextObjectWithDSA(*resolvedObject, ompFlag);
}
}
}
} else {
context_.Say(name.source, // 2.15.3
"COMMON block must be declared in the same scoping unit "
@ -1073,4 +1098,20 @@ void ResolveOmpParts(
}
}
void OmpAttributeVisitor::CheckDataCopyingClause(
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
const auto *checkSymbol{&symbol};
if (ompFlag == Symbol::Flag::OmpCopyIn) {
if (const auto *details{symbol.detailsIf<HostAssocDetails>()})
checkSymbol = &details->symbol();
// List of items/objects that can appear in a 'copyin' clause must be
// 'threadprivate'
if (!checkSymbol->test(Symbol::Flag::OmpThreadprivate))
context_.Say(name.source,
"Non-THREADPRIVATE object '%s' in COPYIN clause"_err_en_US,
checkSymbol->name());
}
}
} // namespace Fortran::semantics

View file

@ -53,6 +53,7 @@ program main
!$omp end target parallel
!ERROR: COPYIN clause is not allowed on the TARGET PARALLEL directive
!ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause
!$omp target parallel copyin(a)
do i = 1, N
a(i) = 3.14
@ -98,6 +99,7 @@ program main
enddo
!$omp end target parallel do
!ERROR: Non-THREADPRIVATE object 'a' in COPYIN clause
!$omp target parallel do copyin(a)
do i = 1, N
a(i) = 3.14

View file

@ -0,0 +1,34 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! 2.15.4.1 copyin Clause
! A list item that appears in a copyin clause must be threadprivate
program omp_copyin
integer :: i
integer, save :: k
integer :: a(10), b(10)
common /cmn/ j
k = 10
!ERROR: Non-THREADPRIVATE object 'k' in COPYIN clause
!$omp parallel do copyin(k)
do i = 1, 10
a(i) = k + i
j = j + a(i)
end do
!$omp end parallel do
print *, a
!ERROR: Non-THREADPRIVATE object 'j' in COPYIN clause
!$omp parallel do copyin(/cmn/)
do i = 1, 10
b(i) = a(i) + j
end do
!$omp end parallel do
print *, b
end program omp_copyin

View file

@ -0,0 +1,23 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! 2.15.4.1 copyin Clause
! A common block name that appears in a copyin clause must be declared to be
! a common block in the same scoping unit in which the copyin clause appears.
subroutine copyin()
integer :: a = 10
common /cmn/ a
!$omp threadprivate(/cmn/)
call copyin_clause()
contains
subroutine copyin_clause()
!ERROR: COMMON block must be declared in the same scoping unit in which the OpenMP directive or clause appears
!$omp parallel copyin(/cmn/)
print *, a
!$omp end parallel
end subroutine copyin_clause
end subroutine copyin

View file

@ -0,0 +1,33 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! 2.15.4.1 copyin Clause
! A list item that appears in a copyin clause must be threadprivate.
! Named variables appearing in a threadprivate common block may be specified
! It is not necessary to specify the whole common block.
program omp_copyin
integer :: a(10), b(10)
common /cmn/ j, k
!$omp threadprivate(/cmn/)
j = 20
k = 10
!$omp parallel copyin(/cmn/)
a(:5) = k
b(:5) = j
!$omp end parallel
j = j + k
k = k * j
!$omp parallel copyin(j, k)
a(6:) = j
b(6:) = k
!$omp end parallel
print *, a, b
end program omp_copyin

View file

@ -0,0 +1,26 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! 2.15.4.1 copyin Clause
! A list item that appears in a copyin clause must be threadprivate
program omp_copyin
integer :: i
integer, save :: j, k
integer :: a(10), b(10)
!$omp threadprivate(j, k)
j = 20
k = 10
!$omp parallel do copyin(j, k)
do i = 1, 10
a(i) = k + i
b(i) = j + i
end do
!$omp end parallel do
print *, a, b
end program omp_copyin

View file

@ -0,0 +1,23 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! 2.15.4.1 copyin Clause
! A common block name that appears in a copyin clause must be declared to be
! a common block in the same scoping unit in which the copyin clause appears.
subroutine copyin()
call copyin_clause()
contains
subroutine copyin_clause()
integer :: a = 20
common /cmn/ a
!$omp threadprivate(/cmn/)
!$omp parallel copyin(/cmn/)
print *, a
!$omp end parallel
end subroutine copyin_clause
end subroutine copyin