Files
clang-p2996/flang/test/Lower/OpenMP/unstructured.f90
Sergio Afonso 0a17bdfc36 [MLIR][OpenMP] Remove terminators from loop wrappers (#112229)
This patch simplifies the representation of OpenMP loop wrapper
operations by introducing the `NoTerminator` trait and updating
accordingly the verifier for the `LoopWrapperInterface`.

Since loop wrappers are already limited to having exactly one region
containing exactly one block, and this block can only hold a single
`omp.loop_nest` or loop wrapper and an `omp.terminator` that does not
return any values, it makes sense to simplify the representation of loop
wrappers by removing the terminator.

There is an extensive list of Lit tests that needed updating to remove
the `omp.terminator`s adding some noise to this patch, but actual
changes are limited to the definition of the `omp.wsloop`, `omp.simd`,
`omp.distribute` and `omp.taskloop` loop wrapper ops, Flang lowering for
those, `LoopWrapperInterface::verifyImpl()`, SCF to OpenMP conversion
and OpenMP dialect documentation.
2024-10-15 11:28:39 +01:00

367 lines
11 KiB
Fortran

! Test unstructured code adjacent to and inside OpenMP constructs.
! RUN: bbc %s -fopenmp -emit-hlfir -o "-" \
! RUN: | FileCheck %s
! CHECK-LABEL: func @_QPss1{{.*}} {
! CHECK: br ^bb1
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb4
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb5
! CHECK: ^bb2: // pred: ^bb1
! CHECK: cond_br %{{[0-9]*}}, ^bb3, ^bb4
! CHECK: ^bb4: // pred: ^bb2
! CHECK: fir.call @_FortranAioBeginExternalListOutput
! CHECK: br ^bb1
! CHECK: ^bb5: // 2 preds: ^bb1, ^bb3
! CHECK: omp.master {
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: omp.terminator
! CHECK: }
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: }
subroutine ss1(n) ! unstructured code followed by a structured OpenMP construct
do i = 1, 3
if (i .eq. n) exit
print*, 'ss1-A', i
enddo
!$omp master
print*, 'ss1-B', i
!$omp end master
print*
end
! CHECK-LABEL: func @_QPss2{{.*}} {
! CHECK: omp.master {
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: br ^bb1
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb4
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb5
! CHECK: ^bb2: // pred: ^bb1
! CHECK: cond_br %{{[0-9]*}}, ^bb3, ^bb4
! CHECK: ^bb3: // pred: ^bb2
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: br ^bb1
! CHECK: ^bb5: // 2 preds: ^bb1, ^bb3
! CHECK: omp.terminator
! CHECK: }
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: }
subroutine ss2(n) ! unstructured OpenMP construct; loop exit inside construct
!$omp master
print*, 'ss2-A', n
do i = 1, 3
if (i .eq. n) exit
print*, 'ss2-B', i
enddo
!$omp end master
print*, 'ss2-C', i
print*
end
! CHECK-LABEL: func @_QPss3{{.*}} {
! CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: %[[ALLOCA_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned}
! CHECK: %[[K_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_K]] {uniq_name = "_QFss3Ek"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: br ^bb1
! CHECK: ^bb1: // 2 preds: ^bb0, ^bb3
! CHECK: cond_br %{{[0-9]*}}, ^bb2, ^bb4
! CHECK: ^bb2: // pred: ^bb1
! CHECK: %[[ALLOCA_2:.*]] = fir.alloca i32 {{{.*}}, pinned, {{.*}}}
! CHECK: %[[OMP_LOOP_K_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_2]] {uniq_name = "_QFss3Ek"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest (%[[ARG1:.*]]) : {{.*}} {
! CHECK: fir.store %[[ARG1]] to %[[OMP_LOOP_K_DECL]]#1 : !fir.ref<i32>
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: %[[LOAD_1:.*]] = fir.load %[[OMP_LOOP_K_DECL]]#0 : !fir.ref<i32>
! CHECK: @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD_1]])
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: %[[ALLOCA_1:.*]] = fir.alloca i32 {{{.*}}, pinned, {{.*}}}
! CHECK: %[[OMP_LOOP_J_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_1]] {uniq_name = "_QFss3Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest (%[[ARG2:.*]]) : {{.*}} {
! CHECK: fir.store %[[ARG2]] to %[[OMP_LOOP_J_DECL]]#1 : !fir.ref<i32>
! CHECK: br ^bb1
! CHECK: ^bb2: // 2 preds: ^bb1, ^bb5
! CHECK: cond_br %{{[0-9]*}}, ^bb3, ^bb6
! CHECK: ^bb3: // pred: ^bb2
! CHECK: cond_br %{{[0-9]*}}, ^bb4, ^bb5
! CHECK: ^bb4: // pred: ^bb3
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: %[[LOAD_2:.*]] = fir.load %[[K_DECL]]#0 : !fir.ref<i32>
! CHECK: @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD_2]])
! CHECK: br ^bb2
! CHECK: ^bb6: // 2 preds: ^bb2, ^bb4
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: br ^bb1
! CHECK: ^bb4: // pred: ^bb1
! CHECK: omp.terminator
! CHECK: }
! CHECK: }
subroutine ss3(n) ! nested unstructured OpenMP constructs
!$omp parallel
do i = 1, 3
!$omp do
do k = 1, 3
print*, 'ss3-A', k
enddo
!$omp end do
!$omp do
do j = 1, 3
do k = 1, 3
if (k .eq. n) exit
print*, 'ss3-B', k
enddo
enddo
!$omp end do
enddo
!$omp end parallel
end
! CHECK-LABEL: func @_QPss4{{.*}} {
! CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 {{{.*}}, pinned, uniq_name = "_QFss4Ej"}
! CHECK: %[[OMP_LOOP_J_DECL:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFss4Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: omp.wsloop {
! CHECK-NEXT: omp.loop_nest (%[[ARG:.*]]) : {{.*}} {
! CHECK: fir.store %[[ARG]] to %[[OMP_LOOP_J_DECL]]#1 : !fir.ref<i32>
! CHECK: %[[COND:.*]] = arith.cmpi eq, %{{.*}}, %{{.*}}
! CHECK: %[[COND_XOR:.*]] = arith.xori %[[COND]], %{{.*}}
! CHECK: fir.if %[[COND_XOR]] {
! CHECK: @_FortranAioBeginExternalListOutput
! CHECK: %[[LOAD:.*]] = fir.load %[[OMP_LOOP_J_DECL]]#0 : !fir.ref<i32>
! CHECK: @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD]])
! CHECK: }
! CHECK-NEXT: omp.yield
! CHECK-NEXT: }
! CHECK-NEXT: }
! CHECK: omp.terminator
! CHECK-NEXT: }
subroutine ss4(n) ! CYCLE in OpenMP wsloop constructs
!$omp parallel
do i = 1, 3
!$omp do
do j = 1, 3
if (j .eq. n) cycle
print*, 'ss4', j
enddo
!$omp end do
enddo
!$omp end parallel
end
! CHECK-LABEL: func @_QPss5() {
! CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest {{.*}} {
! CHECK: br ^[[BB1:.*]]
! CHECK: ^[[BB1]]:
! CHECK: br ^[[BB2:.*]]
! CHECK: ^[[BB2]]:
! CHECK: cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
! CHECK: ^[[BB3]]:
! CHECK: cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB3:.*]]
! CHECK: ^[[BB4]]:
! CHECK: br ^[[BB6]]
! CHECK: ^[[BB3]]:
! CHECK: br ^[[BB2]]
! CHECK: ^[[BB6]]:
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: omp.terminator
! CHECK: }
subroutine ss5() ! EXIT inside OpenMP wsloop (inside parallel)
integer :: x
!$omp parallel private(x)
!$omp do
do j = 1, 3
x = j * i
do k = 1, 3
if (k .eq. n) exit
x = k
x = x + k
enddo
x = j - 222
enddo
!$omp end do
!$omp end parallel
end
! CHECK-LABEL: func @_QPss6() {
! CHECK: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: br ^[[BB1_OUTER:.*]]
! CHECK: ^[[BB1_OUTER]]:
! CHECK: cond_br %{{.*}}, ^[[BB2_OUTER:.*]], ^[[BB3_OUTER:.*]]
! CHECK: ^[[BB2_OUTER]]:
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest {{.*}} {
! CHECK: br ^[[BB1:.*]]
! CHECK: ^[[BB1]]:
! CHECK: br ^[[BB2:.*]]
! CHECK: ^[[BB2]]:
! CHECK: cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
! CHECK: ^[[BB3]]:
! CHECK: cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
! CHECK: ^[[BB4]]:
! CHECK: br ^[[BB6]]
! CHECK: ^[[BB5]]
! CHECK: br ^[[BB2]]
! CHECK: ^[[BB6]]:
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: br ^[[BB1_OUTER]]
! CHECK: ^[[BB3_OUTER]]:
! CHECK: omp.terminator
! CHECK: }
subroutine ss6() ! EXIT inside OpenMP wsloop in a do loop (inside parallel)
integer :: x
!$omp parallel private(x)
do i = 1, 3
!$omp do
do j = 1, 3
x = j * i
do k = 1, 3
if (k .eq. n) exit
x = k
x = x + k
enddo
x = j - 222
enddo
!$omp end do
enddo
!$omp end parallel
end
! CHECK-LABEL: func @_QPss7() {
! CHECK: br ^[[BB1_OUTER:.*]]
! CHECK: ^[[BB1_OUTER]]:
! CHECK: cond_br %{{.*}}, ^[[BB2_OUTER:.*]], ^[[BB3_OUTER:.*]]
! CHECK-NEXT: ^[[BB2_OUTER:.*]]:
! CHECK: omp.parallel {
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest {{.*}} {
! CHECK: br ^[[BB1:.*]]
! CHECK-NEXT: ^[[BB1]]:
! CHECK: br ^[[BB2:.*]]
! CHECK-NEXT: ^[[BB2]]:
! CHECK: cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
! CHECK-NEXT: ^[[BB3]]:
! CHECK: cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
! CHECK-NEXT: ^[[BB4]]:
! CHECK: br ^[[BB6]]
! CHECK-NEXT: ^[[BB5]]:
! CHECK: br ^[[BB2]]
! CHECK-NEXT: ^[[BB6]]:
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: omp.terminator
! CHECK: }
! CHECK: br ^[[BB1_OUTER]]
! CHECK-NEXT: ^[[BB3_OUTER]]:
! CHECK-NEXT: return
subroutine ss7() ! EXIT inside OpenMP parallel do (inside do loop)
integer :: x
do i = 1, 3
!$omp parallel do private(x)
do j = 1, 3
x = j * i
do k = 1, 3
if (k .eq. n) exit
x = k
x = x + k
enddo
enddo
!$omp end parallel do
enddo
end
! CHECK-LABEL: func @_QPss8() {
! CHECK: omp.parallel {
! CHECK: omp.wsloop {
! CHECK: omp.loop_nest {{.*}} {
! CHECK: br ^[[BB1:.*]]
! CHECK-NEXT: ^[[BB1]]:
! CHECK: br ^[[BB2:.*]]
! CHECK: ^[[BB2]]:
! CHECK: cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
! CHECK: ^[[BB3]]:
! CHECK: cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
! CHECK: ^[[BB4]]:
! CHECK-NEXT: br ^[[BB6]]
! CHECK: ^[[BB5]]:
! CHECK: br ^[[BB2]]
! CHECK-NEXT: ^[[BB6]]:
! CHECK: omp.yield
! CHECK: }
! CHECK: }
! CHECK: omp.terminator
! CHECK: }
subroutine ss8() ! EXIT inside OpenMP parallel do
integer :: x
!$omp parallel do private(x)
do j = 1, 3
x = j * i
do k = 1, 3
if (k .eq. n) exit
x = k
x = x + k
enddo
enddo
!$omp end parallel do
end
! CHECK-LABEL: func @_QPss9() {
! CHECK: omp.parallel {
! CHECK-NEXT: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: br ^[[BB1:.*]]
! CHECK: ^[[BB1]]:
! CHECK: cond_br %{{.*}}, ^[[BB2:.*]], ^[[BB5:.*]]
! CHECK-NEXT: ^[[BB2]]:
! CHECK: cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB4:.*]]
! CHECK-NEXT: ^[[BB3]]:
! CHECK-NEXT: br ^[[BB5]]
! CHECK-NEXT: ^[[BB4]]:
! CHECK: br ^[[BB1]]
! CHECK-NEXT: ^[[BB5]]:
! CHECK: omp.terminator
! CHECK-NEXT: }
! CHECK: omp.terminator
! CHECK-NEXT }
! CHECK: }
subroutine ss9() ! EXIT inside OpenMP parallel (inside parallel)
integer :: x
!$omp parallel
!$omp parallel private(x)
do k = 1, 3
if (k .eq. n) exit
x = k
x = x + k
end do
!$omp end parallel
!$omp end parallel
end
! CHECK-LABEL: func @_QQmain
program p
call ss1(2)
call ss2(2)
call ss3(2)
call ss4(2)
call ss5()
call ss6()
call ss7()
call ss8()
call ss9()
end