diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /flang/test/Semantics/OpenMP | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'flang/test/Semantics/OpenMP')
| -rw-r--r-- | flang/test/Semantics/OpenMP/declare-mapper02.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/depend01.f90 | 2 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/depend07.f90 | 11 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/do-collapse.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/do07.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/invalid-branch.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/missing-end-directive.f90 | 17 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/nontemporal.f90 | 1 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/ordered01.f90 | 17 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/simd-aligned.f90 | 7 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/simd-only.f90 | 30 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/workdistribute01.f90 | 16 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/workdistribute02.f90 | 34 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/workdistribute03.f90 | 34 | ||||
| -rw-r--r-- | flang/test/Semantics/OpenMP/workdistribute04.f90 | 15 |
16 files changed, 155 insertions, 34 deletions
diff --git a/flang/test/Semantics/OpenMP/declare-mapper02.f90 b/flang/test/Semantics/OpenMP/declare-mapper02.f90 index a62a7f8d0a39..2ad87c914bc7 100644 --- a/flang/test/Semantics/OpenMP/declare-mapper02.f90 +++ b/flang/test/Semantics/OpenMP/declare-mapper02.f90 @@ -6,5 +6,6 @@ type, abstract :: t1 end type t1 !ERROR: ABSTRACT derived type may not be used here +!ERROR: Reference to object with abstract derived type 't1' must be polymorphic !$omp declare mapper(mm : t1::x) map(x, x%y) end diff --git a/flang/test/Semantics/OpenMP/depend01.f90 b/flang/test/Semantics/OpenMP/depend01.f90 index 19fcfbf64beb..6c6cc16bcc5f 100644 --- a/flang/test/Semantics/OpenMP/depend01.f90 +++ b/flang/test/Semantics/OpenMP/depend01.f90 @@ -20,7 +20,7 @@ program omp_depend !ERROR: 'a' in DEPEND clause must have a positive stride !ERROR: 'b' in DEPEND clause must have a positive stride !ERROR: 'b' in DEPEND clause is a zero size array section - !$omp task shared(x) depend(in: a(10:5:-1)) depend(in: b(5:10:-1)) + !$omp task shared(x) depend(in: a(10:5:-1)) depend(in: b(5:10:-1, 2)) print *, a(5:10), b !$omp end task diff --git a/flang/test/Semantics/OpenMP/depend07.f90 b/flang/test/Semantics/OpenMP/depend07.f90 new file mode 100644 index 000000000000..53c98b079f34 --- /dev/null +++ b/flang/test/Semantics/OpenMP/depend07.f90 @@ -0,0 +1,11 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 + +subroutine foo(x) + integer :: x(3, *) + !$omp task depend(in:x(:,5)) + !$omp end task + !ERROR: Assumed-size array 'x' must have explicit final subscript upper bound value + !$omp task depend(in:x(5,:)) + !$omp end task +end + diff --git a/flang/test/Semantics/OpenMP/do-collapse.f90 b/flang/test/Semantics/OpenMP/do-collapse.f90 index 480bd45b79b8..ec6a3bdad368 100644 --- a/flang/test/Semantics/OpenMP/do-collapse.f90 +++ b/flang/test/Semantics/OpenMP/do-collapse.f90 @@ -31,6 +31,7 @@ program omp_doCollapse end do end do + !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct. !ERROR: At most one COLLAPSE clause can appear on the SIMD directive !$omp simd collapse(2) collapse(1) do i = 1, 4 diff --git a/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 b/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 index bb1929249183..355626f6e73b 100644 --- a/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 +++ b/flang/test/Semantics/OpenMP/do-concurrent-collapse.f90 @@ -1,6 +1,7 @@ !RUN: %python %S/../test_errors.py %s %flang -fopenmp integer :: i, j +! ERROR: DO CONCURRENT loops cannot be used with the COLLAPSE clause. !$omp parallel do collapse(2) do i = 1, 1 ! ERROR: DO CONCURRENT loops cannot form part of a loop nest. diff --git a/flang/test/Semantics/OpenMP/do07.f90 b/flang/test/Semantics/OpenMP/do07.f90 index 44fe5f86045a..5b3eb28c17e7 100644 --- a/flang/test/Semantics/OpenMP/do07.f90 +++ b/flang/test/Semantics/OpenMP/do07.f90 @@ -1,5 +1,4 @@ ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s -! REQUIRES: shell ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! No statement in the associated loops other than the DO statements diff --git a/flang/test/Semantics/OpenMP/invalid-branch.f90 b/flang/test/Semantics/OpenMP/invalid-branch.f90 index 28aab8b122f3..581103d927bf 100644 --- a/flang/test/Semantics/OpenMP/invalid-branch.f90 +++ b/flang/test/Semantics/OpenMP/invalid-branch.f90 @@ -1,5 +1,4 @@ ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s -! REQUIRES: shell ! OpenMP Version 4.5 ! Check invalid branches into or out of OpenMP structured blocks. diff --git a/flang/test/Semantics/OpenMP/missing-end-directive.f90 b/flang/test/Semantics/OpenMP/missing-end-directive.f90 new file mode 100644 index 000000000000..6068740999ed --- /dev/null +++ b/flang/test/Semantics/OpenMP/missing-end-directive.f90 @@ -0,0 +1,17 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp + +! Test that we can diagnose missing end directives without an explosion of errors + +! ERROR: Expected OpenMP END PARALLEL directive +!$omp parallel +! ERROR: Expected OpenMP END TASK directive +!$omp task +! ERROR: Expected OpenMP END SECTIONS directive +!$omp sections +! ERROR: Expected OpenMP END PARALLEL directive +!$omp parallel +! ERROR: Expected OpenMP END TASK directive +!$omp task +! ERROR: Expected OpenMP END SECTIONS directive +!$omp sections +end diff --git a/flang/test/Semantics/OpenMP/nontemporal.f90 b/flang/test/Semantics/OpenMP/nontemporal.f90 index ad0ebc85b5ce..ac662bf28df0 100644 --- a/flang/test/Semantics/OpenMP/nontemporal.f90 +++ b/flang/test/Semantics/OpenMP/nontemporal.f90 @@ -1,5 +1,4 @@ ! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -! REQUIRES: shell ! Check OpenMP clause validity for NONTEMPORAL clause program omp_simd diff --git a/flang/test/Semantics/OpenMP/ordered01.f90 b/flang/test/Semantics/OpenMP/ordered01.f90 index 12543acb2916..75968a6f5ee4 100644 --- a/flang/test/Semantics/OpenMP/ordered01.f90 +++ b/flang/test/Semantics/OpenMP/ordered01.f90 @@ -52,27 +52,14 @@ program main end do !$omp end do - !$omp do ordered(1) - do i = 2, N - !ERROR: DEPEND clauses are not allowed when ORDERED construct is a block construct with an ORDERED region - !$omp ordered depend(source) - arrayA(i) = foo(i) - !$omp end ordered - !ERROR: DEPEND clauses are not allowed when ORDERED construct is a block construct with an ORDERED region - !$omp ordered depend(sink: i - 1) - arrayB(i) = bar(arrayA(i), arrayB(i-1)) - !$omp end ordered - end do - !$omp end do - contains subroutine work1() - !ERROR: THREADS and SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region + !ERROR: Expected OpenMP END ORDERED directive !$omp ordered simd end subroutine work1 subroutine work2() - !ERROR: THREADS and SIMD clauses are not allowed when ORDERED construct is a standalone construct with no ORDERED region + !ERROR: Expected OpenMP END ORDERED directive !$omp ordered threads end subroutine work2 diff --git a/flang/test/Semantics/OpenMP/simd-aligned.f90 b/flang/test/Semantics/OpenMP/simd-aligned.f90 index 0a9f95833e22..4c410a7c4631 100644 --- a/flang/test/Semantics/OpenMP/simd-aligned.f90 +++ b/flang/test/Semantics/OpenMP/simd-aligned.f90 @@ -60,9 +60,16 @@ program omp_simd !$omp end simd !ERROR: 'd' in ALIGNED clause must be of type C_PTR, POINTER or ALLOCATABLE + !WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage] !$omp simd aligned(d:100) do i = 1, 100 d(i) = i end do + !WARNING: Alignment is not a power of 2, Aligned clause will be ignored [-Wopen-mp-usage] + !$omp simd aligned(b:65) + do i = 1, 100 + b(i) = i + end do + end program omp_simd diff --git a/flang/test/Semantics/OpenMP/simd-only.f90 b/flang/test/Semantics/OpenMP/simd-only.f90 index da42b10d73be..33ab3d62c98e 100644 --- a/flang/test/Semantics/OpenMP/simd-only.f90 +++ b/flang/test/Semantics/OpenMP/simd-only.f90 @@ -131,7 +131,7 @@ end subroutine ! CHECK-LABEL: Name = 'test_target_data' subroutine test_target_data() - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpLoopDirective -> llvm::omp::Directive = target data ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp target data map(to: A) map(tofrom: B) @@ -174,7 +174,7 @@ subroutine test_do_ordered() ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct !$omp do ordered do i = 1, 100 - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpLoopDirective -> llvm::omp::Directive = ordered !$omp ordered x = x + 1 @@ -224,7 +224,7 @@ end subroutine subroutine test_target_map() integer :: array(10) - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpLoopDirective -> llvm::omp::Directive = target !$omp target map(tofrom: array(2:10)) array(2) = array(2) * 2 @@ -288,15 +288,15 @@ end subroutine ! CHECK-LABEL: Name = 'test_task_single_taskwait' subroutine test_task_single_taskwait() integer :: x - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = parallel !$omp parallel - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = single !$omp single ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct do i = 1, 5 - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = task ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'x=i' !$omp task @@ -313,16 +313,16 @@ end subroutine ! CHECK-LABEL: Name = 'test_task_taskyield_flush_barrier' subroutine test_task_taskyield_flush_barrier() integer :: x, i - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = parallel !$omp parallel ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = barrier !$omp barrier - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = single !$omp single - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = task !$omp task ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification @@ -333,7 +333,7 @@ subroutine test_task_taskyield_flush_barrier() ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPFlushConstruct -> OmpDirectiveSpecification !$omp flush !$omp end task - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = task !$omp task ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPFlushConstruct -> OmpDirectiveSpecification @@ -348,16 +348,16 @@ end subroutine ! CHECK-LABEL: Name = 'test_master_masked' subroutine test_master_masked() - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = parallel !$omp parallel private(tid) - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = masked !$omp masked ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'x=y' x = y !$omp end masked - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = master !$omp master ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'y=x' @@ -368,7 +368,7 @@ end subroutine ! CHECK-LABEL: Name = 'test_critical' subroutine test_critical() - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = parallel !$omp parallel do private(i) do i = 1, 4 @@ -385,7 +385,7 @@ subroutine test_target_enter_exit_update_data() ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = target enter data !$omp target enter data map(to: A) - ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPBlockConstruct + ! CHECK-NOT: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct ! CHECK-NOT: OmpDirectiveName -> llvm::omp::Directive = target teams distribute parallel do !$omp target teams distribute parallel do ! CHECK: ExecutionPartConstruct -> ExecutableConstruct -> DoConstruct diff --git a/flang/test/Semantics/OpenMP/workdistribute01.f90 b/flang/test/Semantics/OpenMP/workdistribute01.f90 new file mode 100644 index 000000000000..f7e36976dfb6 --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute01.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 +! OpenMP Version 6.0 +! workdistribute Construct +! Invalid do construct inside !$omp workdistribute + +subroutine workdistribute() + integer n, i + !ERROR: A WORKDISTRIBUTE region must be nested inside TEAMS region only. + !ERROR: The structured block in a WORKDISTRIBUTE construct may consist of only SCALAR or ARRAY assignments + !$omp workdistribute + do i = 1, n + print *, "omp workdistribute" + end do + !$omp end workdistribute + +end subroutine workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute02.f90 b/flang/test/Semantics/OpenMP/workdistribute02.f90 new file mode 100644 index 000000000000..6de3a55f545b --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute02.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 +! OpenMP Version 6.0 +! workdistribute Construct +! The !omp workdistribute construct must not contain any user defined +! function calls unless the function is ELEMENTAL. + +module my_mod + contains + integer function my_func() + my_func = 10 + end function my_func + + impure integer function impure_my_func() + impure_my_func = 20 + end function impure_my_func + + impure elemental integer function impure_ele_my_func() + impure_ele_my_func = 20 + end function impure_ele_my_func +end module my_mod + +subroutine workdistribute(aa, bb, cc, n) + use my_mod + integer n + real aa(n), bb(n), cc(n) + !$omp teams + !$omp workdistribute + !ERROR: User defined non-ELEMENTAL function 'my_func' is not allowed in a WORKDISTRIBUTE construct + aa = my_func() + aa = bb * cc + !$omp end workdistribute + !$omp end teams + +end subroutine workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute03.f90 b/flang/test/Semantics/OpenMP/workdistribute03.f90 new file mode 100644 index 000000000000..828170a016ed --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute03.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 +! OpenMP Version 6.0 +! workdistribute Construct +! All array assignments, scalar assignments, and masked array assignments +! must be intrinsic assignments. + +module defined_assign + interface assignment(=) + module procedure work_assign + end interface + + contains + subroutine work_assign(a,b) + integer, intent(out) :: a + logical, intent(in) :: b(:) + end subroutine work_assign +end module defined_assign + +program omp_workdistribute + use defined_assign + + integer :: a, aa(10), bb(10) + logical :: l(10) + l = .TRUE. + + !$omp teams + !$omp workdistribute + !ERROR: Defined assignment statement is not allowed in a WORKDISTRIBUTE construct + a = l + aa = bb + !$omp end workdistribute + !$omp end teams + +end program omp_workdistribute diff --git a/flang/test/Semantics/OpenMP/workdistribute04.f90 b/flang/test/Semantics/OpenMP/workdistribute04.f90 new file mode 100644 index 000000000000..d407e8a073ae --- /dev/null +++ b/flang/test/Semantics/OpenMP/workdistribute04.f90 @@ -0,0 +1,15 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! OpenMP Version 6.0 +! workdistribute Construct +! Unsuported OpenMP version + +subroutine teams_workdistribute() + use iso_fortran_env + real(kind=real32) :: a + real(kind=real32), dimension(10) :: x + real(kind=real32), dimension(10) :: y + !ERROR: WORKDISTRIBUTE construct is not allowed in OpenMP v5.0, try -fopenmp-version=60 + !$omp teams workdistribute + y = a * x + y + !$omp end teams workdistribute +end subroutine teams_workdistribute |
