Open pawosm-arm opened 6 years ago
The nasty workaround is to move !$OMP PARALLEL before IF statement setting pack_func and to specify pack_func as private, !$OMP PARALLEL PRIVATE(pack_func)
The best fireworks this bug causes when one builds this code with -O0 (along with -fopenmp)
Seems similar to #345 which was already closed. I guess the fix does not cover all the possible cases.
Turns out, call ptr
is not considered as using ptr
variable, hence as unused, this variable is not captured.
This leads to a simpler workaround: put pack_func = pack_func
anywhere inside of the parallel region.
Simple test case:
! RUN: %flang -O0 -fopenmp -S -emit-llvm %s -o - 2>&1 | FileCheck %s
program subcallx
implicit none
call sub2
contains
subroutine sub1(x)
implicit none
integer :: x
print *, "Hello from sub1", x
end subroutine sub1
! CHECK: define internal void @subcallx_sub2
subroutine sub2
implicit none
interface
subroutine simple_sub(x)
implicit none
integer :: x
end subroutine
end interface
procedure(simple_sub), pointer :: pptr => null() ! CHECK: %"pptr$p_{{[0-9]+}}" = alloca void
pptr => sub1
! CHECK: @subcallx__{{.+}}_ to i64*
! CHECK: @__kmpc_fork_call
! CHECK: define internal void @subcallx__{{.+}}_
!$OMP PARALLEL
call pptr(123) ! CHECK-NOT: %"pptr${{.+}}_{{[0-9]+}}" = alloca
!$OMP END PARALLEL
end subroutine sub2
end program subcallx
Simple fix:
--- a/tools/flang1/flang1exe/semant3.c
+++ b/tools/flang1/flang1exe/semant3.c
@@ -1364,8 +1364,10 @@ end_stmt:
sptr = SST_SYMG(RHS(1));
if (!is_procedure_ptr(sptr)) {
subr_call(RHS(1), itemp);
- } else
+ } else {
+ (void)mkarg(RHS(1), &dum);
ptrsubr_call(RHS(1), itemp);
+ }
} else {
ptrsubr_call(RHS(1), itemp);
}
Unfortunately, mkarg() couldn't handle correctly a case with a pointer to a procedure that does not take any arguments. Example test case that fails CHECK-NOT test even with above patch applied:
! RUN: %flang -O0 -fopenmp -S -emit-llvm %s -o - 2>&1 | FileCheck %s
program subcall
implicit none
call sub2
contains
subroutine sub1
implicit none
print *, "Hello from sub1"
end subroutine sub1
! CHECK: define internal void @subcall_sub2
subroutine sub2
implicit none
interface
subroutine simple_sub
implicit none
end subroutine
end interface
procedure(simple_sub), pointer :: pptr => null() ! CHECK: %"pptr$p_{{[0-9]+}}" = alloca void
pptr => sub1
! CHECK: @subcall__{{.+}}_ to i64*
! CHECK: @__kmpc_fork_call
! CHECK: define internal void @subcall__{{.+}}_
!$OMP PARALLEL
call pptr ! CHECK-NOT: %"pptr${{.+}}_{{[0-9]+}}" = alloca
!$OMP END PARALLEL
end subroutine sub2
end program subcall
Simple test case 1 above still causes segfault when executed. Internally, we're patching semant3 as described above.
While running TeaLeaf_ref on larger number of threads unexpected behavior resulting in results validation errors were observed. It turned out (by analyzing LLVM-IR built with -O0), one of local variables (a pointer to a function) instead of being captured, became allocated on stack in the outlined function for the parallel region and then used uninitialized causing either segfault or wrong subroutine being called.
Outer region:
pack_all subroutine and its pack_func local variable (pack_kernel.f90 file):
Inner parallel region further in pack_all subroutine:
The same compiled by gfortran does not fail, even if I link it against libomp.so instead of GOMP.