| ! Test unstructured code adjacent to and inside OpenMP constructs. |
| |
| ! RUN: bbc %s -fopenmp -emit-hlfir -o "-" | 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 { |
| ! 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: omp.terminator |
| ! 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: omp.terminator |
| ! 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 { |
| ! 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: } else { |
| ! CHECK: } |
| ! CHECK-NEXT: omp.yield |
| ! CHECK-NEXT: } |
| ! CHECK-NEXT: omp.terminator |
| ! 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 { |
| ! 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: omp.terminator |
| ! 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 { |
| ! 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: omp.terminator |
| ! 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: omp.terminator |
| ! 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: omp.terminator |
| ! 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 { |
| ! 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 |