[PATCH] D91920: [Flang] [OpenMP] Add semantic checks for OpenMP firstprivate , lastprivate and copyprivate clauses

Praveen G via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 11 06:17:24 PST 2021


praveen marked 4 inline comments as done.
praveen added inline comments.


================
Comment at: flang/lib/Semantics/check-omp-structure.cpp:857
+
+void OmpStructureChecker::CheckPrivateSymbolsInOuterCxt(
+    SymbolSourceMap &currSymbols, const OmpDirectiveSet &currDirSet,
----------------
kiranchandramohan wrote:
> praveen wrote:
> > kiranchandramohan wrote:
> > > Can you check why we cannot catch the error in the following test. gfortran seems able to.
> > > ```
> > > program mn
> > > integer :: a(10), b(10), c(10)
> > > !$omp parallel private(a,b)
> > > call tmp()
> > > !$omp end parallel
> > > contains
> > >   subroutine tmp()
> > >   !$omp do firstprivate(b)
> > >   do i = 1, 10
> > >     c(i) = a(i) + b(i) + i
> > >   end do
> > >   !$omp end do
> > >   end subroutine
> > > end program
> > > ```
> > @kiranchandramohan We are not able to catch the error in the above case since the context information is cleared in the ResetPartialContext() after the OpenMP End construct is encountered. 
> > 
> > Hence, when checking the enclosing directives for firstprivate(b), it returns null. 
> > I tried to keep track of the context information past the execution of the construct , but it ran into other issues for cases which expects the context information to be cleared. 
> What did you finally do for this case? If it is not handled can you add an entry into the spreadsheet for this case?
@kiranchandramohan I will add an entry to the spreadsheet for this case. 
I guess we may have to explore to check if a separate parse-tree walk would help for such cases . 

I am not sure if I am missing something or gfortran (gcc 9.3.0) does not catch the above mentioned error as expected . 

firstprivate01.f90
```
program mn
integer :: a(10), b(10), c(10)
!$omp parallel shared(a,b)
call tmp()
!$omp end parallel
contains
  subroutine tmp()
  !$omp do firstprivate(b)
  do i = 1, 10
    c(i) = a(i) + b(i) + i
  end do
  !$omp end do
  end subroutine
end program
```

firstprivate02.f90
```
program mn
integer :: a(10), b(10), c(10)
!$omp parallel
call tmp()
!$omp end parallel
contains
  subroutine tmp()
  !$omp do firstprivate(a)
  do i = 1, 10
    c(i) = a(i) + b(i) + i
  end do
  !$omp end do
  end subroutine
end program
```

firstprivate03.f90
```
program mn
integer :: a(10), b(10), c(10), i
!$omp do firstprivate(a)
do i = 1, 10
  c(i) = a(i) + b(i) + i
end do
!$omp end do
end program
```

In the above test cases firstprivate01.f90, firstprivate02.f90 and firstprivate03.f90 , the firstprivate symbol is not added as private in the enclosing context. 

But //**gfortran identifies the above cases as errors**//.  In gfortran , it seems that if the variable is not explicitly specified in any of the clauses , then it is assumed as **private** implicity.

Please let me know if it is the expected behaviour?


nesting.f90
```
program mn
integer :: a(10), b(10), c(10)
!$omp parallel
!$omp single
call tmp()
!$omp end single
!$omp end parallel
contains
  subroutine tmp()
  !$omp do
  do i = 1, 10
    c(i) = a(i) + b(i) + i
  end do
  !$omp end do
  end subroutine
end program
```

In the above program nesting.f90, should there be an "//**invalid nesting of worksharing regions**//" error ?


copyprivate.f90
```
program mn
integer :: a(10), b(10), c(10)
!$omp parallel
call tmp()
!$omp end parallel
contains
  subroutine tmp()
  !$omp single
   c = a + b
  !$omp end single copyprivate(a)
  end subroutine
end program
```

For the above case copyprivate.f90, we are identifying this as an error since "**//copyprivate variable is not private or thread-private in outer context//**" , but gfortran does not throw the error similar to the above cases.


================
Comment at: flang/lib/Semantics/check-omp-structure.cpp:864
+  if (currDirSet.test(GetContext().directive)) {
+    if (auto *enclosingContext{GetEnclosingDirContext()}) {
+      if (enclosingDirSet.test(enclosingContext->directive)) {
----------------
praveen wrote:
> kiranchandramohan wrote:
> > Is there an assumption here that the enclosing directive is the parallel/teams region?
> > 
> > Can it happen that the enclosing immediate directive is not the parallel/teams region to which the worksharing construct binds? Something like the following? 
> > ```
> > parallel private(x)
> >   some_omp_construct
> >     worksharing_construct firstprivate(x)
> > ```
> @kiranchandramohan I am not sure if there can be any immediate enclosing directives for workshare constructs . 
> 
> Since we already check 'HasInvalidWorksharingNesting' , do we need to check for the '//firstprivate/lastprivate variables that are private in enclosing context//' for the variables on the worksharing constructs?
> 
> The task construct can contain directives other than parallel such as the following.
> 
>   !$omp parallel reduction (+:a)
>     !$omp single
>       !$omp task firstprivate (a)
>         a = a + b
>       !$omp end task
>     !$omp end single
>   !$omp end parallel
> 
> Should we thrown an error for the cases such as the one above ?
@kiranchandramohan Have updated the code to identify the enclosing constructs that are not immediate enclosing directives and binds to the current directive.


================
Comment at: flang/lib/Semantics/check-omp-structure.cpp:864
+  if (currDirSet.test(GetContext().directive)) {
+    if (auto *enclosingContext{GetEnclosingDirContext()}) {
+      if (enclosingDirSet.test(enclosingContext->directive)) {
----------------
kiranchandramohan wrote:
> praveen wrote:
> > praveen wrote:
> > > kiranchandramohan wrote:
> > > > Is there an assumption here that the enclosing directive is the parallel/teams region?
> > > > 
> > > > Can it happen that the enclosing immediate directive is not the parallel/teams region to which the worksharing construct binds? Something like the following? 
> > > > ```
> > > > parallel private(x)
> > > >   some_omp_construct
> > > >     worksharing_construct firstprivate(x)
> > > > ```
> > > @kiranchandramohan I am not sure if there can be any immediate enclosing directives for workshare constructs . 
> > > 
> > > Since we already check 'HasInvalidWorksharingNesting' , do we need to check for the '//firstprivate/lastprivate variables that are private in enclosing context//' for the variables on the worksharing constructs?
> > > 
> > > The task construct can contain directives other than parallel such as the following.
> > > 
> > >   !$omp parallel reduction (+:a)
> > >     !$omp single
> > >       !$omp task firstprivate (a)
> > >         a = a + b
> > >       !$omp end task
> > >     !$omp end single
> > >   !$omp end parallel
> > > 
> > > Should we thrown an error for the cases such as the one above ?
> > @kiranchandramohan Have updated the code to identify the enclosing constructs that are not immediate enclosing directives and binds to the current directive.
> ```
> A list item that appears in a reduction clause of a parallel construct must not appear in a
> firstprivate clause on a worksharing, task, or taskloop construct if any of the
> worksharing or task regions arising from the worksharing, task, or taskloop construct ever
> bind to any of the parallel regions arising from the parallel construct.
> ```
> 
> As per the above statement from the standard, yes it has to be flagged. If there are issues in handling this then please let me know.
@kiranchandramohan I have updated the code to handle cases such as the above example where the binding region may  not be the immediate enclosing directive.


================
Comment at: flang/lib/Semantics/check-omp-structure.cpp:865
+    if (auto *enclosingContext{GetEnclosingDirContext()}) {
+      if (enclosingDirSet.test(enclosingContext->directive)) {
+        for (auto it{enclosingContext->clauseInfo.begin()};
----------------
praveen wrote:
> kiranchandramohan wrote:
> > I think whether this check should be performed is dependent on the triple enclosing_dir, enclosing_clause, cur_dir.
> > 
> > So there should be no error for the following code.
> > 
> > ```
> > program omp_firstprivate
> > 
> >   integer :: i, a(10), b(10), c(10)
> > 
> >   a = 10
> >   b = 20
> > 
> >   !$omp parallel private(a, b)
> >   !$omp task firstprivate(a)
> >   do i = 1, 10
> >     a(i) = a(i) + b(i) - i
> >   end do
> >   !$omp end task
> >   !$omp end parallel
> > end program
> > ```
> > 
> > But there should be an error for the following code.
> > ```
> > program omp_firstprivate
> >   integer :: i, a
> >   a = 10
> >   i = 2
> >   !$omp parallel reduction(+:a)
> >   !$omp task firstprivate(a)
> >     a = a + i
> >   !$omp end task
> >   !$omp end parallel
> > end program
> > ```
> @kiranchandramohan Thanks . Will handle this check 
Updated the logic to check based on the triple.


================
Comment at: flang/test/Semantics/omp-copyprivate03.f90:27
+
+  !$omp parallel sections private(k)
+  !$omp section
----------------
kiranchandramohan wrote:
> A threadprivate variable cannot appear in a private clause.
> A threadprivate variable cannot appear in a private clause.




================
Comment at: flang/test/Semantics/omp-copyprivate03.f90:27
+
+  !$omp parallel sections private(k)
+  !$omp section
----------------
praveen wrote:
> kiranchandramohan wrote:
> > A threadprivate variable cannot appear in a private clause.
> > A threadprivate variable cannot appear in a private clause.
> 
> 
Done


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D91920/new/

https://reviews.llvm.org/D91920



More information about the llvm-commits mailing list