================
@@ -0,0 +1,180 @@
+! RUN: %flang_fc1 -fopenmp -fopenmp-version=52 -emit-hlfir %s -o - | \
+! RUN:   FileCheck %s
+
+module loop_context
+contains
+  pure integer function parallel_bound(n)
+    integer, intent(in) :: n
+    parallel_bound = n
+  end function
+
+  pure integer function do_bound(n)
+    integer, intent(in) :: n
+    do_bound = n
+  end function
+
+  pure integer function bound(n)
+    integer, intent(in) :: n
+    !$omp declare variant(parallel_bound) match(construct={parallel})
+    !$omp declare variant(do_bound) match(construct={do})
+    bound = n
+  end function
+
+  ! NUM_THREADS is evaluated outside PARALLEL. The DO bound is inside
+  ! PARALLEL but outside DO, and the loop body is inside both constructs.
+  ! CHECK-LABEL: func.func @_QMloop_contextPcombined(
+  ! CHECK: fir.call @_QMloop_contextPbound(
+  ! CHECK: omp.parallel
+  ! CHECK-NOT: fir.call @_QMloop_contextPbound(
+  ! CHECK-NOT: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: fir.call @_QMloop_contextPparallel_bound(
+  ! CHECK: omp.wsloop
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine combined(n, a)
+    integer, intent(in) :: n
+    integer :: a(n), i
+    !$omp parallel do num_threads(bound(n))
+    do i = 1, bound(n)
+      a(i) = bound(n)
+    end do
+  end subroutine
+
+  ! Explicit nesting must select the same variants as the combined spelling.
+  ! CHECK-LABEL: func.func @_QMloop_contextPexplicit_nest(
+  ! CHECK: fir.call @_QMloop_contextPbound(
+  ! CHECK: omp.parallel
+  ! CHECK-NOT: fir.call @_QMloop_contextPbound(
+  ! CHECK-NOT: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: fir.call @_QMloop_contextPparallel_bound(
+  ! CHECK: omp.wsloop
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine explicit_nest(n, a)
+    integer, intent(in) :: n
+    integer :: a(n), i
+    !$omp parallel num_threads(bound(n))
+      !$omp do
+      do i = 1, bound(n)
+        a(i) = bound(n)
+      end do
+    !$omp end parallel
+  end subroutine
+
+  ! Composite lowering creates PARALLEL separately from the loop wrappers.
+  ! CHECK-LABEL: func.func @_QMloop_contextPcomposite(
+  ! CHECK: omp.teams
+  ! CHECK: omp.parallel
+  ! CHECK-NOT: fir.call @_QMloop_contextPbound(
+  ! CHECK-NOT: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: fir.call @_QMloop_contextPparallel_bound(
+  ! CHECK: omp.distribute
+  ! CHECK: omp.wsloop
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine composite(n, a)
+    integer, intent(in) :: n
+    integer :: a(n), i
+    !$omp teams distribute parallel do
+    do i = 1, bound(n)
+      a(i) = bound(n)
+    end do
+  end subroutine
+
+  ! The SIMD composite follows a separate lowering path.
+  ! CHECK-LABEL: func.func @_QMloop_contextPcomposite_simd(
+  ! CHECK: omp.teams
+  ! CHECK: omp.parallel
+  ! CHECK-NOT: fir.call @_QMloop_contextPbound(
+  ! CHECK-NOT: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: fir.call @_QMloop_contextPparallel_bound(
+  ! CHECK: omp.distribute
+  ! CHECK: omp.wsloop
+  ! CHECK: omp.simd
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine composite_simd(n, a)
+    integer, intent(in) :: n
+    integer :: a(n), i
+    !$omp teams distribute parallel do simd
+    do i = 1, bound(n)
+      a(i) = bound(n)
+    end do
+  end subroutine
+
+  ! A standalone DO does not contribute its own context to its bounds.
+  ! CHECK-LABEL: func.func @_QMloop_contextPstandalone_do(
+  ! CHECK-NOT: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: fir.call @_QMloop_contextPbound(
+  ! CHECK: omp.wsloop
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine standalone_do(n, a)
+    integer, intent(in) :: n
+    integer :: a(n), i
+    !$omp do
+    do i = 1, bound(n)
+      a(i) = bound(n)
+    end do
+  end subroutine
+
+  pure integer function cpu_count(n)
+    integer, intent(in) :: n
+    cpu_count = n
+  end function
+
+  pure integer function scored_count(n)
+    integer, intent(in) :: n
+    scored_count = n + 1
+  end function
+
+  pure integer function thread_count(n)
+    integer, intent(in) :: n
+    !$omp declare variant(cpu_count) match(device={kind(cpu)})
+    !$omp declare variant(scored_count) &
+    !$omp& match(implementation={vendor(score(3): llvm)})
+    thread_count = n
+  end function
+
+  ! DIST_SCHEDULE sees only TEAMS. NUM_THREADS sees TEAMS, DISTRIBUTE, so
+  ! CPU scores 5 and beats the vendor score of 4. The bound also sees PARALLEL.
+  ! CHECK-LABEL: func.func @_QMloop_contextPcomposite_clauses(
+  ! CHECK: omp.teams
+  ! CHECK: fir.call @_QMloop_contextPbound(
+  ! CHECK: fir.call @_QMloop_contextPcpu_count(
+  ! CHECK: omp.parallel
+  ! CHECK: fir.call @_QMloop_contextPparallel_bound(
+  ! CHECK: omp.distribute
+  ! CHECK: omp.wsloop
+  ! CHECK: fir.call @_QMloop_contextPdo_bound(
+  ! CHECK: return
+  subroutine composite_clauses(n, a)
+    integer :: n, a(n), i
+    !$omp teams distribute parallel do dist_schedule(static, bound(n)) &
+    !$omp& num_threads(thread_count(n))
----------------
MattPD wrote:

Confirmed at 1aa333a: The `num_threads` check now fails if PARALLEL is active 
for its operand.

https://github.com/llvm/llvm-project/pull/224431
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to