! The "thread_limit" clause was added to the "target" construct in OpenMP 5.1. ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s --check-prefixes=BOTH,HOST ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefixes=BOTH,DEVICE ! BOTH-LABEL: func.func @_QPteams subroutine teams() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[NUM_TEAMS:.*]], %{{.*}} -> %[[THREAD_LIMIT:.*]] : i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { !$omp target ! BOTH: omp.teams ! HOST-SAME: num_teams( to %[[NUM_TEAMS]] : i32) thread_limit(%[[THREAD_LIMIT]] : i32) ! DEVICE-SAME: num_teams({{.*}}) thread_limit({{.*}}) !$omp teams num_teams(1) thread_limit(2) call foo() !$omp end teams !$omp end target ! HOST: omp.teams ! HOST-SAME: num_teams({{.*}}) thread_limit({{.*}}) { ! DEVICE-NOT: omp.teams !$omp teams num_teams(1) thread_limit(2) call foo() !$omp end teams end subroutine teams ! BOTH-LABEL: func.func @_QPdistribute_parallel_do subroutine distribute_parallel_do() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]], %{{.*}} -> %[[NUM_THREADS:.*]] : i32, i32, i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { ! BOTH: omp.teams !$omp target teams ! BOTH: omp.parallel ! HOST-SAME: num_threads(%[[NUM_THREADS]] : i32) ! DEVICE-SAME: num_threads({{.*}}) ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop ! BOTH-NEXT: omp.loop_nest ! HOST-SAME: (%{{.*}}) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) !$omp distribute parallel do num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do !$omp end target teams ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams call foo() !< Prevents this from being SPMD. ! BOTH: omp.parallel ! BOTH-SAME: num_threads({{.*}}) ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop !$omp distribute parallel do num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do !$omp end target teams ! HOST: omp.teams ! DEVICE-NOT: omp.teams !$omp teams ! HOST: omp.parallel ! HOST-SAME: num_threads({{.*}}) ! HOST: omp.distribute ! HOST-NEXT: omp.wsloop ! DEVICE-NOT: omp.parallel ! DEVICE-NOT: omp.distribute ! DEVICE-NOT: omp.wsloop !$omp distribute parallel do num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do !$omp end teams end subroutine distribute_parallel_do ! BOTH-LABEL: func.func @_QPdistribute_parallel_do_simd subroutine distribute_parallel_do_simd() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]], %{{.*}} -> %[[NUM_THREADS:.*]] : i32, i32, i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { ! BOTH: omp.teams !$omp target teams ! BOTH: omp.parallel ! HOST-SAME: num_threads(%[[NUM_THREADS]] : i32) ! DEVICE-SAME: num_threads({{.*}}) ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop ! BOTH-NEXT: omp.simd ! BOTH-NEXT: omp.loop_nest ! HOST-SAME: (%{{.*}}) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) !$omp distribute parallel do simd num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do simd !$omp end target teams ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams call foo() !< Prevents this from being SPMD. ! BOTH: omp.parallel ! BOTH-SAME: num_threads({{.*}}) ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop ! BOTH-NEXT: omp.simd !$omp distribute parallel do simd num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do simd !$omp end target teams ! HOST: omp.teams ! DEVICE-NOT: omp.teams !$omp teams ! HOST: omp.parallel ! HOST-SAME: num_threads({{.*}}) ! HOST: omp.distribute ! HOST-NEXT: omp.wsloop ! HOST-NEXT: omp.simd ! DEVICE-NOT: omp.parallel ! DEVICE-NOT: omp.distribute ! DEVICE-NOT: omp.wsloop ! DEVICE-NOT: omp.simd !$omp distribute parallel do simd num_threads(1) do i=1,10 call foo() end do !$omp end distribute parallel do simd !$omp end teams end subroutine distribute_parallel_do_simd ! BOTH-LABEL: func.func @_QPdistribute subroutine distribute() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { ! BOTH: omp.teams !$omp target teams ! BOTH: omp.distribute ! BOTH-NEXT: omp.loop_nest ! HOST-SAME: (%{{.*}}) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) !$omp distribute do i=1,10 call foo() end do !$omp end distribute !$omp end target teams ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams call foo() !< Prevents this from being Generic-SPMD. ! BOTH: omp.distribute !$omp distribute do i=1,10 call foo() end do !$omp end distribute !$omp end target teams ! HOST: omp.teams ! DEVICE-NOT: omp.teams !$omp teams ! HOST: omp.distribute ! DEVICE-NOT: omp.distribute !$omp distribute do i=1,10 call foo() end do !$omp end distribute !$omp end teams end subroutine distribute ! BOTH-LABEL: func.func @_QPdistribute_simd subroutine distribute_simd() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { ! BOTH: omp.teams !$omp target teams ! BOTH: omp.distribute ! BOTH-NEXT: omp.simd ! BOTH-NEXT: omp.loop_nest ! HOST-SAME: (%{{.*}}) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) !$omp distribute simd do i=1,10 call foo() end do !$omp end distribute simd !$omp end target teams ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams call foo() !< Prevents this from being Generic-SPMD. ! BOTH: omp.distribute ! BOTH-NEXT: omp.simd !$omp distribute simd do i=1,10 call foo() end do !$omp end distribute simd !$omp end target teams ! HOST: omp.teams ! DEVICE-NOT: omp.teams !$omp teams ! HOST: omp.distribute ! HOST-NEXT: omp.simd ! DEVICE-NOT: omp.distribute ! DEVICE-NOT: omp.simd !$omp distribute simd do i=1,10 call foo() end do !$omp end distribute simd !$omp end teams end subroutine distribute_simd ! BOTH-LABEL: func.func @_QPloop subroutine loop() ! BOTH: omp.target ! HOST-SAME: host_eval(%{{.*}} -> %[[LB:.*]], %{{.*}} -> %[[UB:.*]], %{{.*}} -> %[[STEP:.*]] : i32, i32, i32) ! DEVICE-NOT: host_eval({{.*}}) ! DEVICE-SAME: { ! BOTH: omp.teams !$omp target teams ! BOTH: omp.parallel ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop ! BOTH-NEXT: omp.loop_nest ! HOST-SAME: (%{{.*}}) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) !$omp loop do i=1,10 end do !$omp end target teams end subroutine loop ! BOTH-LABEL: func.func @_QPdistribute_parallel_do_with_modified_trip subroutine distribute_parallel_do_with_modified_trip() integer :: i, x integer :: m(1) integer :: res(10) m(1) = 10 x = 1000000 ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams map(res) x = 1 ! BOTH: omp.parallel ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop !$omp distribute parallel do do i = 1, m(x) res(i) = 5 + i end do !$omp end distribute parallel do !$omp end target teams end subroutine distribute_parallel_do_with_modified_trip ! BOTH-LABEL: func.func @_QPdistribute_parallel_do_with_assignment subroutine distribute_parallel_do_with_assignment() integer :: i, m integer :: res(10) ! BOTH: omp.target ! BOTH-NOT: host_eval({{.*}}) ! BOTH-SAME: { ! BOTH: omp.teams !$omp target teams map(from:m,res) private(m) m = 5 ! BOTH: omp.parallel ! BOTH: omp.distribute ! BOTH-NEXT: omp.wsloop !$omp distribute parallel do do i = 1, 10 res(i) = 5 + i end do !$omp end distribute parallel do !$omp end target teams end subroutine distribute_parallel_do_with_assignment