From 0294556f38fd43861c0666857d94d01cdf06dedd Mon Sep 17 00:00:00 2001 From: ronlieb Date: Tue, 29 Oct 2024 15:35:08 -0400 Subject: [PATCH] Revert "Remove OpenACC tests (#189)" This reverts commit b29b41368dd56a3632c2a9a85097d36caec22b82. --- .../test/Lower/OpenACC/acc-atomic-capture.f90 | 219 +++ flang/test/Lower/OpenACC/acc-atomic-read.f90 | 59 + .../Lower/OpenACC/acc-atomic-update-array.f90 | 92 ++ .../Lower/OpenACC/acc-atomic-update-hlfir.f90 | 52 + .../test/Lower/OpenACC/acc-atomic-update.f90 | 73 + flang/test/Lower/OpenACC/acc-atomic-write.f90 | 58 + flang/test/Lower/OpenACC/acc-bounds.f90 | 185 +++ .../test/Lower/OpenACC/acc-data-operands.f90 | 201 +++ flang/test/Lower/OpenACC/acc-data.f90 | 202 +++ .../Lower/OpenACC/acc-declare-globals.f90 | 78 ++ flang/test/Lower/OpenACC/acc-declare.f90 | 474 +++++++ flang/test/Lower/OpenACC/acc-device-type.f90 | 48 + flang/test/Lower/OpenACC/acc-enter-data.f90 | 818 +++++++++++ flang/test/Lower/OpenACC/acc-exit-data.f90 | 107 ++ flang/test/Lower/OpenACC/acc-fixed-form.f | 35 + flang/test/Lower/OpenACC/acc-host-data.f90 | 52 + flang/test/Lower/OpenACC/acc-init.f90 | 38 + flang/test/Lower/OpenACC/acc-kernels-loop.f90 | 707 ++++++++++ flang/test/Lower/OpenACC/acc-kernels.f90 | 298 ++++ .../Lower/OpenACC/acc-loop-and-cpu-dir.f90 | 75 + flang/test/Lower/OpenACC/acc-loop-exit.f90 | 41 + flang/test/Lower/OpenACC/acc-loop.f90 | 328 +++++ .../test/Lower/OpenACC/acc-parallel-loop.f90 | 733 ++++++++++ flang/test/Lower/OpenACC/acc-parallel.f90 | 356 +++++ flang/test/Lower/OpenACC/acc-private.f90 | 403 ++++++ flang/test/Lower/OpenACC/acc-reduction.f90 | 1213 +++++++++++++++++ .../test/Lower/OpenACC/acc-routine-named.f90 | 25 + flang/test/Lower/OpenACC/acc-routine.f90 | 127 ++ flang/test/Lower/OpenACC/acc-routine02.f90 | 20 + flang/test/Lower/OpenACC/acc-routine03.f90 | 35 + flang/test/Lower/OpenACC/acc-routine04.f90 | 34 + flang/test/Lower/OpenACC/acc-serial-loop.f90 | 665 +++++++++ flang/test/Lower/OpenACC/acc-serial.f90 | 291 ++++ flang/test/Lower/OpenACC/acc-set.f90 | 40 + .../Lower/OpenACC/acc-shortloop-ignore.f90 | 57 + flang/test/Lower/OpenACC/acc-shutdown.f90 | 28 + flang/test/Lower/OpenACC/acc-unstructured.f90 | 85 ++ flang/test/Lower/OpenACC/acc-update.f90 | 112 ++ flang/test/Lower/OpenACC/acc-wait.f90 | 41 + flang/test/Lower/OpenACC/locations.f90 | 176 +++ flang/test/Lower/OpenACC/pre-fir-tree01.f90 | 18 + .../Lower/OpenACC/stop-stmt-in-region.f90 | 41 + flang/test/Lower/branching-directive.f90 | 31 +- flang/test/Lower/pre-fir-tree05.f90 | 50 + flang/test/Lower/pre-fir-tree07.f90 | 11 + flang/test/Lower/pre-fir-tree08.f | 21 + flang/test/Parser/acc-unparse.f90 | 88 ++ .../continuation-in-conditional-compilation.f | 7 +- flang/test/Preprocessing/pp132.f90 | 7 +- .../test/Preprocessing/preprocessed-dirs.F90 | 8 + .../Preprocessing/sentinel-after-semi.F90 | 7 + .../Semantics/OpenACC/acc-atomic-validity.f90 | 49 + flang/test/Semantics/OpenACC/acc-branch.f90 | 199 +++ .../Semantics/OpenACC/acc-cache-validity.f90 | 46 + .../OpenACC/acc-canonicalization-validity.f90 | 103 ++ .../Semantics/OpenACC/acc-combined-loop.f90 | 33 + flang/test/Semantics/OpenACC/acc-data.f90 | 232 ++++ .../OpenACC/acc-declare-validity.f90 | 74 + flang/test/Semantics/OpenACC/acc-error.f90 | 29 + .../test/Semantics/OpenACC/acc-host-data.f90 | 41 + .../Semantics/OpenACC/acc-init-validity.f90 | 102 ++ .../Semantics/OpenACC/acc-kernels-loop.f90 | 298 ++++ flang/test/Semantics/OpenACC/acc-kernels.f90 | 160 +++ .../Semantics/OpenACC/acc-loop-validity.f90 | 19 + flang/test/Semantics/OpenACC/acc-loop.f90 | 358 +++++ flang/test/Semantics/OpenACC/acc-module.f90 | 123 ++ .../OpenACC/acc-parallel-loop-validity.f90 | 144 ++ flang/test/Semantics/OpenACC/acc-parallel.f90 | 191 +++ .../OpenACC/acc-reduction-validity.f90 | 172 +++ .../test/Semantics/OpenACC/acc-resolve01.f90 | 22 + .../test/Semantics/OpenACC/acc-resolve02.f90 | 17 + .../test/Semantics/OpenACC/acc-resolve03.f90 | 21 + .../test/Semantics/OpenACC/acc-resolve04.f90 | 34 + .../OpenACC/acc-routine-validity.f90 | 82 ++ .../OpenACC/acc-routine-validity02.f90 | 17 + flang/test/Semantics/OpenACC/acc-routine.f90 | 136 ++ .../Semantics/OpenACC/acc-serial-loop.f90 | 114 ++ flang/test/Semantics/OpenACC/acc-serial.f90 | 182 +++ .../Semantics/OpenACC/acc-set-validity.f90 | 108 ++ .../OpenACC/acc-shutdown-validity.f90 | 96 ++ .../test/Semantics/OpenACC/acc-symbols01.f90 | 26 + .../test/Semantics/OpenACC/acc-symbols02.f90 | 21 + .../Semantics/OpenACC/acc-update-validity.f90 | 67 + .../Semantics/OpenACC/acc-wait-validity.f90 | 42 + flang/test/Semantics/cuf10.cuf | 26 + flang/test/Semantics/loop-directives.f90 | 1 + 86 files changed, 12352 insertions(+), 3 deletions(-) create mode 100644 flang/test/Lower/OpenACC/acc-atomic-capture.f90 create mode 100644 flang/test/Lower/OpenACC/acc-atomic-read.f90 create mode 100644 flang/test/Lower/OpenACC/acc-atomic-update-array.f90 create mode 100644 flang/test/Lower/OpenACC/acc-atomic-update-hlfir.f90 create mode 100644 flang/test/Lower/OpenACC/acc-atomic-update.f90 create mode 100644 flang/test/Lower/OpenACC/acc-atomic-write.f90 create mode 100644 flang/test/Lower/OpenACC/acc-bounds.f90 create mode 100644 flang/test/Lower/OpenACC/acc-data-operands.f90 create mode 100644 flang/test/Lower/OpenACC/acc-data.f90 create mode 100644 flang/test/Lower/OpenACC/acc-declare-globals.f90 create mode 100644 flang/test/Lower/OpenACC/acc-declare.f90 create mode 100644 flang/test/Lower/OpenACC/acc-device-type.f90 create mode 100644 flang/test/Lower/OpenACC/acc-enter-data.f90 create mode 100644 flang/test/Lower/OpenACC/acc-exit-data.f90 create mode 100644 flang/test/Lower/OpenACC/acc-fixed-form.f create mode 100644 flang/test/Lower/OpenACC/acc-host-data.f90 create mode 100644 flang/test/Lower/OpenACC/acc-init.f90 create mode 100644 flang/test/Lower/OpenACC/acc-kernels-loop.f90 create mode 100644 flang/test/Lower/OpenACC/acc-kernels.f90 create mode 100644 flang/test/Lower/OpenACC/acc-loop-and-cpu-dir.f90 create mode 100644 flang/test/Lower/OpenACC/acc-loop-exit.f90 create mode 100644 flang/test/Lower/OpenACC/acc-loop.f90 create mode 100644 flang/test/Lower/OpenACC/acc-parallel-loop.f90 create mode 100644 flang/test/Lower/OpenACC/acc-parallel.f90 create mode 100644 flang/test/Lower/OpenACC/acc-private.f90 create mode 100644 flang/test/Lower/OpenACC/acc-reduction.f90 create mode 100644 flang/test/Lower/OpenACC/acc-routine-named.f90 create mode 100644 flang/test/Lower/OpenACC/acc-routine.f90 create mode 100644 flang/test/Lower/OpenACC/acc-routine02.f90 create mode 100644 flang/test/Lower/OpenACC/acc-routine03.f90 create mode 100644 flang/test/Lower/OpenACC/acc-routine04.f90 create mode 100644 flang/test/Lower/OpenACC/acc-serial-loop.f90 create mode 100644 flang/test/Lower/OpenACC/acc-serial.f90 create mode 100644 flang/test/Lower/OpenACC/acc-set.f90 create mode 100644 flang/test/Lower/OpenACC/acc-shortloop-ignore.f90 create mode 100644 flang/test/Lower/OpenACC/acc-shutdown.f90 create mode 100644 flang/test/Lower/OpenACC/acc-unstructured.f90 create mode 100644 flang/test/Lower/OpenACC/acc-update.f90 create mode 100644 flang/test/Lower/OpenACC/acc-wait.f90 create mode 100644 flang/test/Lower/OpenACC/locations.f90 create mode 100644 flang/test/Lower/OpenACC/pre-fir-tree01.f90 create mode 100644 flang/test/Lower/OpenACC/stop-stmt-in-region.f90 create mode 100644 flang/test/Lower/pre-fir-tree05.f90 create mode 100644 flang/test/Lower/pre-fir-tree07.f90 create mode 100755 flang/test/Lower/pre-fir-tree08.f create mode 100644 flang/test/Parser/acc-unparse.f90 create mode 100644 flang/test/Preprocessing/preprocessed-dirs.F90 create mode 100644 flang/test/Preprocessing/sentinel-after-semi.F90 create mode 100644 flang/test/Semantics/OpenACC/acc-atomic-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-branch.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-cache-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-combined-loop.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-data.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-declare-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-error.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-host-data.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-init-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-kernels-loop.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-kernels.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-loop-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-loop.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-module.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-parallel.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-reduction-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-resolve01.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-resolve02.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-resolve03.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-resolve04.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-routine-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-routine-validity02.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-routine.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-serial-loop.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-serial.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-set-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-shutdown-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-symbols01.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-symbols02.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-update-validity.f90 create mode 100644 flang/test/Semantics/OpenACC/acc-wait-validity.f90 create mode 100644 flang/test/Semantics/cuf10.cuf diff --git a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 new file mode 100644 index 00000000000000..373683386fda90 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 @@ -0,0 +1,219 @@ +! RUN: %flang_fc1 -I nowhere -emit-hlfir -fopenacc %s -o - | FileCheck %s + +! This test checks the lowering of atomic capture + +program acc_atomic_capture_test + integer :: x, y + +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %2 {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[temp:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.capture { +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: acc.atomic.update %[[Y_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG:.*]]: i32): +!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[ARG]] : i32 +!CHECK: acc.yield %[[result]] : i32 +!CHECK: } +!CHECK: } + + !$acc atomic capture + x = y + y = x + y + !$acc end atomic + + +!CHECK: %[[temp:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.capture { +!CHECK: acc.atomic.update %[[Y_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG:.*]]: i32): +!CHECK: %[[result:.*]] = arith.muli %[[temp]], %[[ARG]] : i32 +!CHECK: acc.yield %[[result]] : i32 +!CHECK: } +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: } + + !$acc atomic capture + y = x * y + x = y + !$acc end atomic + +!CHECK: %[[constant_20:.*]] = arith.constant 20 : i32 +!CHECK: %[[constant_8:.*]] = arith.constant 8 : i32 +!CHECK: %[[temp:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: %[[result:.*]] = arith.subi %[[constant_8]], %[[temp]] : i32 +!CHECK: %[[result_noreassoc:.*]] = hlfir.no_reassoc %[[result]] : i32 +!CHECK: %[[result:.*]] = arith.addi %[[constant_20]], %[[result_noreassoc]] : i32 +!CHECK: acc.atomic.capture { +!CHECK: acc.atomic.read %[[X_DECL]]#1 = %[[Y_DECL]]#1 : !fir.ref +!CHECK: acc.atomic.write %[[Y_DECL]]#1 = %[[result]] : !fir.ref, i32 +!CHECK: } + + !$acc atomic capture + x = y + y = 2 * 10 + (8 - x) + !$acc end atomic +end program + + + +subroutine pointers_in_atomic_capture() +!CHECK: %[[A:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFpointers_in_atomic_captureEa"} +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointers_in_atomic_captureEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +!CHECK: %[[B:.*]] = fir.alloca !fir.box> {bindc_name = "b", uniq_name = "_QFpointers_in_atomic_captureEb"} +!CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointers_in_atomic_captureEb"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +!CHECK: %[[C:.*]] = fir.alloca i32 {bindc_name = "c", fir.target, uniq_name = "_QFpointers_in_atomic_captureEc"} +!CHECK: %[[C_DECL:.*]]:2 = hlfir.declare %[[C]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointers_in_atomic_captureEc"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[D:.*]] = fir.alloca i32 {bindc_name = "d", fir.target, uniq_name = "_QFpointers_in_atomic_captureEd"} +!CHECK: %[[D_DECL:.*]]:2 = hlfir.declare %[[D]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointers_in_atomic_captureEd"} : (!fir.ref) -> (!fir.ref, !fir.ref) + +!CHECK: %[[loaded_A:.*]] = fir.load %[[A_DECL]]#0 : !fir.ref>> +!CHECK: %[[loaded_A_addr:.*]] = fir.box_addr %[[loaded_A]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[loaded_B:.*]] = fir.load %[[B_DECL]]#0 : !fir.ref>> +!CHECK: %[[loaded_B_addr:.*]] = fir.box_addr %[[loaded_B]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[PRIVATE_LOADED_B:.*]] = fir.load %[[B_DECL]]#0 : !fir.ref>> +!CHECK: %[[PRIVATE_LOADED_B_addr:.*]] = fir.box_addr %[[PRIVATE_LOADED_B]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[loaded_value:.*]] = fir.load %[[PRIVATE_LOADED_B_addr]] : !fir.ptr +!CHECK: acc.atomic.capture { +!CHECK: acc.atomic.update %[[loaded_A_addr]] : !fir.ptr { +!CHECK: ^bb0(%[[ARG:.*]]: i32): +!CHECK: %[[result:.*]] = arith.addi %[[ARG]], %[[loaded_value]] : i32 +!CHECK: acc.yield %[[result]] : i32 +!CHECK: } +!CHECK: acc.atomic.read %[[loaded_B_addr]] = %[[loaded_A_addr]] : !fir.ptr, i32 +!CHECK: } + integer, pointer :: a, b + integer, target :: c, d + a=>c + b=>d + + !$acc atomic capture + a = a + b + b = a + !$acc end atomic +end subroutine + + +subroutine capture_with_convert_f32_to_i32() + implicit none + integer :: k, v, i + + k = 1 + v = 0 + + !$acc atomic capture + v = k + k = (i + 1) * 3.14 + !$acc end atomic +end subroutine + +! CHECK-LABEL: func.func @_QPcapture_with_convert_f32_to_i32() +! CHECK: %[[K:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFcapture_with_convert_f32_to_i32Ek"} +! CHECK: %[[K_DECL:.*]]:2 = hlfir.declare %[[K]] {uniq_name = "_QFcapture_with_convert_f32_to_i32Ek"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcapture_with_convert_f32_to_i32Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcapture_with_convert_f32_to_i32Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[CST:.*]] = arith.constant 3.140000e+00 : f32 +! CHECK: %[[MUL:.*]] = arith.mulf %{{.*}}, %[[CST]] fastmath : f32 +! CHECK: %[[CONV:.*]] = fir.convert %[[MUL]] : (f32) -> i32 +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[K_DECL]]#1 : !fir.ref, i32 +! CHECK: acc.atomic.write %[[K_DECL]]#1 = %[[CONV]] : !fir.ref, i32 +! CHECK: } + +subroutine array_ref_in_atomic_capture1 + integer :: x(10), v + !$acc atomic capture + v = x(7) + x(7) = x(7) + 1 + !$acc end atomic +end subroutine array_ref_in_atomic_capture1 +! CHECK-LABEL: func.func @_QParray_ref_in_atomic_capture1() { +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFarray_ref_in_atomic_capture1Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFarray_ref_in_atomic_capture1Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "x", uniq_name = "_QFarray_ref_in_atomic_capture1Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]](%{{.*}}) {uniq_name = "_QFarray_ref_in_atomic_capture1Ex"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[X_REF:.*]] = hlfir.designate %[[X_DECL]]#0 (%{{.*}}) : (!fir.ref>, index) -> !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, i32 +! CHECK: acc.atomic.update %[[X_REF]] : !fir.ref { +! CHECK: ^bb0(%[[VAL_7:.*]]: i32): +! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %{{.*}} : i32 +! CHECK: acc.yield %[[VAL_8]] : i32 +! CHECK: } +! CHECK: } + +subroutine array_ref_in_atomic_capture2 + integer :: x(10), v + !$acc atomic capture + x(7) = x(7) + 1 + v = x(7) + !$acc end atomic +end subroutine array_ref_in_atomic_capture2 +! CHECK-LABEL: func.func @_QParray_ref_in_atomic_capture2() { +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFarray_ref_in_atomic_capture2Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFarray_ref_in_atomic_capture2Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "x", uniq_name = "_QFarray_ref_in_atomic_capture2Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]](%{{.*}}) {uniq_name = "_QFarray_ref_in_atomic_capture2Ex"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[X_REF:.*]] = hlfir.designate %[[X_DECL]]#0 (%{{.*}}) : (!fir.ref>, index) -> !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.update %[[X_REF]] : !fir.ref { +! CHECK: ^bb0(%[[VAL_7:.*]]: i32): +! CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_7]], %{{.*}} : i32 +! CHECK: acc.yield %[[VAL_8]] : i32 +! CHECK: } +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[X_REF]] : !fir.ref, i32 +! CHECK: } + +subroutine comp_ref_in_atomic_capture1 + type t1 + integer :: c + end type t1 + integer :: v + type(t1) :: x + !$acc atomic capture + v = x%c + x%c = x%c + 1 + !$acc end atomic +end subroutine comp_ref_in_atomic_capture1 +! CHECK-LABEL: func.func @_QPcomp_ref_in_atomic_capture1() { +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcomp_ref_in_atomic_capture1Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcomp_ref_in_atomic_capture1Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca !fir.type<_QFcomp_ref_in_atomic_capture1Tt1{c:i32}> {bindc_name = "x", uniq_name = "_QFcomp_ref_in_atomic_capture1Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcomp_ref_in_atomic_capture1Ex"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[C:.*]] = hlfir.designate %[[X_DECL]]#0{"c"} : (!fir.ref>) -> !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, i32 +! CHECK: acc.atomic.update %[[C]] : !fir.ref { +! CHECK: ^bb0(%[[VAL_5:.*]]: i32): +! CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %{{.*}} : i32 +! CHECK: acc.yield %[[VAL_6]] : i32 +! CHECK: } +! CHECK: } + +subroutine comp_ref_in_atomic_capture2 + type t1 + integer :: c + end type t1 + integer :: v + type(t1) :: x + !$acc atomic capture + x%c = x%c + 1 + v = x%c + !$acc end atomic +end subroutine comp_ref_in_atomic_capture2 +! CHECK-LABEL: func.func @_QPcomp_ref_in_atomic_capture2() { +! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcomp_ref_in_atomic_capture2Ev"} +! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcomp_ref_in_atomic_capture2Ev"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[X:.*]] = fir.alloca !fir.type<_QFcomp_ref_in_atomic_capture2Tt1{c:i32}> {bindc_name = "x", uniq_name = "_QFcomp_ref_in_atomic_capture2Ex"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcomp_ref_in_atomic_capture2Ex"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[C:.*]] = hlfir.designate %[[X_DECL]]#0{"c"} : (!fir.ref>) -> !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.update %[[C]] : !fir.ref { +! CHECK: ^bb0(%[[VAL_5:.*]]: i32): +! CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %{{.*}} : i32 +! CHECK: acc.yield %[[VAL_6]] : i32 +! CHECK: } +! CHECK: acc.atomic.read %[[V_DECL]]#1 = %[[C]] : !fir.ref, i32 +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-atomic-read.f90 b/flang/test/Lower/OpenACC/acc-atomic-read.f90 new file mode 100644 index 00000000000000..c1a97a9e5f74f3 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-read.f90 @@ -0,0 +1,59 @@ +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! This test checks the lowering of atomic read + +program acc_atomic_test + real g, h + !$acc atomic read + g = h +end program acc_atomic_test + +! CHECK: func @_QQmain() attributes {fir.bindc_name = "acc_atomic_test"} { +! CHECK: %[[VAR_G:.*]] = fir.alloca f32 {bindc_name = "g", uniq_name = "_QFEg"} +! CHECK: %[[G_DECL:.*]]:2 = hlfir.declare %[[VAR_G]] {uniq_name = "_QFEg"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAR_H:.*]] = fir.alloca f32 {bindc_name = "h", uniq_name = "_QFEh"} +! CHECK: %[[H_DECL:.*]]:2 = hlfir.declare %[[VAR_H]] {uniq_name = "_QFEh"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.atomic.read %[[G_DECL]]#1 = %[[H_DECL]]#1 : !fir.ref, f32 +! CHECK: return +! CHECK: } + +! Test lowering atomic read for pointer variables. +! Please notice to use %[[VAL_4]] and %[[VAL_1]] for operands of atomic +! operation, instead of %[[VAL_3]] and %[[VAL_0]]. + +subroutine atomic_read_pointer() + integer, pointer :: x, y + + !$acc atomic read + y = x + + x = y +end + +! CHECK-LABEL: func.func @_QPatomic_read_pointer() { +! CHECK: %[[X:.*]] = fir.alloca !fir.box> {bindc_name = "x", uniq_name = "_QFatomic_read_pointerEx"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFatomic_read_pointerEx"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[Y:.*]] = fir.alloca !fir.box> {bindc_name = "y", uniq_name = "_QFatomic_read_pointerEy"} +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFatomic_read_pointerEy"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[LOAD_X:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_X:.*]] = fir.box_addr %[[LOAD_X]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[LOAD_Y:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_Y:.*]] = fir.box_addr %[[LOAD_Y]] : (!fir.box>) -> !fir.ptr +! CHECK: acc.atomic.read %[[BOX_ADDR_Y]] = %[[BOX_ADDR_X]] : !fir.ptr, i32 +! CHECK: } + +subroutine atomic_read_with_convert() + integer(4) :: x + integer(8) :: y + + !$acc atomic read + y = x +end + +! CHECK-LABEL: func.func @_QPatomic_read_with_convert() { +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFatomic_read_with_convertEx"} +! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFatomic_read_with_convertEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[Y:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFatomic_read_with_convertEy"} +! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFatomic_read_with_convertEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[CONV:.*]] = fir.convert %[[X_DECL]]#1 : (!fir.ref) -> !fir.ref +! CHECK: acc.atomic.read %[[Y_DECL]]#1 = %[[CONV]] : !fir.ref, i32 diff --git a/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 new file mode 100644 index 00000000000000..eeb7ea29940862 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-update-array.f90 @@ -0,0 +1,92 @@ +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine atomic_update_array1(r, n, x) + implicit none + integer :: n + real :: r(n), x + integer :: i + + !$acc data copy(r) + + !$acc parallel loop + do i = 1, n + !$acc atomic update + r(i) = r(i) + x + !$acc end atomic + end do + + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QPatomic_update_array1( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref {fir.bindc_name = "x"}) { +! CHECK: %[[DECL_ARG2:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_update_array1Ex"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_update_array1Er"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[ARRAY_REF:.*]] = hlfir.designate %[[DECL_ARG0]]#0 (%{{.*}}) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[LOAD_X:.*]] = fir.load %[[DECL_ARG2]]#0 : !fir.ref +! CHECK: acc.atomic.update %[[ARRAY_REF]] : !fir.ref { +! CHECK: ^bb0(%[[ARG:.*]]: f32): +! CHECK: %[[ATOMIC:.*]] = arith.addf %[[ARG]], %[[LOAD_X]] fastmath : f32 +! CHECK: acc.yield %[[ATOMIC]] : f32 +! CHECK: } + + +subroutine atomic_read_array1(r, n, x) + implicit none + integer :: n + real :: r(n), x + + !$acc atomic read + x = r(n) +end subroutine + +! CHECK-LABEL: func.func @_QPatomic_read_array1( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref {fir.bindc_name = "x"}) { +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Ex"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_read_array1Er"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[DES:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box>, i64) -> !fir.ref +! CHECK: acc.atomic.read %[[DECL_X]]#1 = %[[DES]] : !fir.ref, f32 + +subroutine atomic_write_array1(r, n, x) + implicit none + integer :: n + real :: r(n), x + + !$acc atomic write + x = r(n) +end subroutine + +! CHECK-LABEL: func.func @_QPatomic_write_array1( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref {fir.bindc_name = "x"}) { +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_write_array1Ex"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_write_array1Er"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[DES:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[LOAD:.*]] = fir.load %[[DES]] : !fir.ref +! CHECK: acc.atomic.write %[[DECL_X]]#1 = %[[LOAD]] : !fir.ref, f32 + +subroutine atomic_capture_array1(r, n, x, y) + implicit none + integer :: n, i + real :: r(n), x, y + + !$acc atomic capture + r(i) = r(i) + x + y = r(i) + !$acc end atomic +end subroutine + +! CHECK-LABEL: func.func @_QPatomic_capture_array1( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "r"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[ARG2:.*]]: !fir.ref {fir.bindc_name = "x"}, %[[ARG3:.*]]: !fir.ref {fir.bindc_name = "y"}) { +! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ex"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_Y:.*]]:2 = hlfir.declare %[[ARG3]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Ey"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_R:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFatomic_capture_array1Er"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[R_I:.*]] = hlfir.designate %[[DECL_R]]#0 (%{{.*}}) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[LOAD:.*]] = fir.load %[[DECL_X]]#0 : !fir.ref +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.update %[[R_I]] : !fir.ref { +! CHECK: ^bb0(%[[ARG:.*]]: f32): +! CHECK: %[[ADD:.*]] = arith.addf %[[ARG]], %[[LOAD]] fastmath : f32 +! CHECK: acc.yield %[[ADD]] : f32 +! CHECK: } +! CHECK: acc.atomic.read %[[DECL_Y]]#1 = %[[R_I]] : !fir.ref, f32 +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-atomic-update-hlfir.f90 b/flang/test/Lower/OpenACC/acc-atomic-update-hlfir.f90 new file mode 100644 index 00000000000000..3d5374aff41a07 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-update-hlfir.f90 @@ -0,0 +1,52 @@ +! This test checks lowering of atomic and atomic update constructs with HLFIR +! RUN: bbc -hlfir -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenacc %s -o - | FileCheck %s + +!CHECK-LABEL: @_QPsb +subroutine sb +!CHECK: %[[W_REF:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFsbEw"} +!CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W_REF]] {uniq_name = "_QFsbEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsbEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFsbEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y_REF:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFsbEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_REF]] {uniq_name = "_QFsbEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Z_REF:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFsbEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z_REF]] {uniq_name = "_QFsbEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) + integer :: w, x, y, z + +!CHECK: %[[Y_VAL:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.update %[[X_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG_X:.*]]: i32): +!CHECK: %[[X_UPDATE_VAL:.*]] = arith.addi %[[ARG_X]], %[[Y_VAL]] : i32 +!CHECK: acc.yield %[[X_UPDATE_VAL]] : i32 +!CHECK: } + !$acc atomic update + x = x + y + +!CHECK: %[[Y_VAL:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.update %[[X_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG_X:.*]]: i32): +!CHECK: %[[X_UPDATE_VAL:.*]] = arith.ori %[[ARG_X]], %[[Y_VAL]] : i32 +!CHECK: acc.yield %[[X_UPDATE_VAL]] : i32 +!CHECK: } + !$acc atomic update + x = ior(x,y) + +!CHECK: %[[W_VAL:.*]] = fir.load %[[W_DECL]]#0 : !fir.ref +!CHECK: %[[X_VAL:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: %[[Y_VAL:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.update %[[Z_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG_Z:.*]]: i32): +!CHECK: %[[WX_CMP:.*]] = arith.cmpi slt, %[[W_VAL]], %[[X_VAL]] : i32 +!CHECK: %[[WX_MIN:.*]] = arith.select %[[WX_CMP]], %[[W_VAL]], %[[X_VAL]] : i32 +!CHECK: %[[WXY_CMP:.*]] = arith.cmpi slt, %[[WX_MIN]], %[[Y_VAL]] : i32 +!CHECK: %[[WXY_MIN:.*]] = arith.select %[[WXY_CMP]], %[[WX_MIN]], %[[Y_VAL]] : i32 +!CHECK: %[[WXYZ_CMP:.*]] = arith.cmpi slt, %[[WXY_MIN]], %[[ARG_Z]] : i32 +!CHECK: %[[WXYZ_MIN:.*]] = arith.select %[[WXYZ_CMP]], %[[WXY_MIN]], %[[ARG_Z]] : i32 +!CHECK: acc.yield %[[WXYZ_MIN]] : i32 +!CHECK: } + !$acc atomic update + z = min(w,x,y,z) + +!CHECK: return +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-atomic-update.f90 b/flang/test/Lower/OpenACC/acc-atomic-update.f90 new file mode 100644 index 00000000000000..6571c9b1f05522 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-update.f90 @@ -0,0 +1,73 @@ +! This test checks lowering of atomic and atomic update constructs +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - | FileCheck %s + +program acc_atomic_update_test + integer :: x, y, z + integer, pointer :: a, b + integer, target :: c, d + integer(1) :: i1 + + a=>c + b=>d + +!CHECK: %[[A:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFEa"} +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +!CHECK: %[[B:.*]] = fir.alloca !fir.box> {bindc_name = "b", uniq_name = "_QFEb"} +!CHECK: %[[B_DECL:.*]]:2 = hlfir.declare %[[B]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFEb"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +!CHECK: %[[C_ADDR:.*]] = fir.address_of(@_QFEc) : !fir.ref +!CHECK: %[[D_ADDR:.*]] = fir.address_of(@_QFEd) : !fir.ref +!CHECK: %[[I1:.*]] = fir.alloca i8 {bindc_name = "i1", uniq_name = "_QFEi1"} +!CHECK: %[[I1_DECL:.*]]:2 = hlfir.declare %[[I1]] {uniq_name = "_QFEi1"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[LOAD_A:.*]] = fir.load %[[A_DECL]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR_A:.*]] = fir.box_addr %[[LOAD_A]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[LOAD_B:.*]] = fir.load %[[B_DECL]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR_B:.*]] = fir.box_addr %[[LOAD_B]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[LOAD_BOX_ADDR_B:.*]] = fir.load %[[BOX_ADDR_B]] : !fir.ptr +!CHECK: acc.atomic.update %[[BOX_ADDR_A]] : !fir.ptr { +!CHECK: ^bb0(%[[ARG0:.*]]: i32): +!CHECK: %[[ADD:.*]] = arith.addi %[[ARG0]], %[[LOAD_BOX_ADDR_B]] : i32 +!CHECK: acc.yield %[[ADD]] : i32 +!CHECK: } + + !$acc atomic update + a = a + b + +!CHECK: {{.*}} = arith.constant 1 : i32 +!CHECK: acc.atomic.update %[[Y_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG:.*]]: i32): +!CHECK: %[[RESULT:.*]] = arith.addi %[[ARG]], {{.*}} : i32 +!CHECK: acc.yield %[[RESULT]] : i32 +!CHECK: } +!CHECK: %[[LOADED_X:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: acc.atomic.update %[[Z_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[ARG:.*]]: i32): +!CHECK: %[[RESULT:.*]] = arith.muli %[[LOADED_X]], %[[ARG]] : i32 +!CHECK: acc.yield %[[RESULT]] : i32 +!CHECK: } + !$acc atomic + y = y + 1 + !$acc atomic update + z = x * z + +!CHECK: %[[C1_VAL:.*]] = arith.constant 1 : i32 +!CHECK: acc.atomic.update %[[I1_DECL]]#1 : !fir.ref { +!CHECK: ^bb0(%[[VAL:.*]]: i8): +!CHECK: %[[CVT_VAL:.*]] = fir.convert %[[VAL]] : (i8) -> i32 +!CHECK: %[[ADD_VAL:.*]] = arith.addi %[[CVT_VAL]], %[[C1_VAL]] : i32 +!CHECK: %[[UPDATED_VAL:.*]] = fir.convert %[[ADD_VAL]] : (i32) -> i8 +!CHECK: acc.yield %[[UPDATED_VAL]] : i8 +!CHECK: } + !$acc atomic + i1 = i1 + 1 + !$acc end atomic +!CHECK: return +!CHECK: } +end program acc_atomic_update_test + diff --git a/flang/test/Lower/OpenACC/acc-atomic-write.f90 b/flang/test/Lower/OpenACC/acc-atomic-write.f90 new file mode 100644 index 00000000000000..7d1551c85bc304 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-atomic-write.f90 @@ -0,0 +1,58 @@ +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! This test checks the lowering of atomic write + +!CHECK: func @_QQmain() attributes {fir.bindc_name = "acc_atomic_write_test"} { +!CHECK: %[[VAR_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[VAR_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[VAR_Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[VAR_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[CONST_7:.*]] = arith.constant 7 : i32 +!CHECK: {{.*}} = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: %[[VAR_7y:.*]] = arith.muli %[[CONST_7]], {{.*}} : i32 +!CHECK: acc.atomic.write %[[X_DECL]]#1 = %[[VAR_7y]] : !fir.ref, i32 +!CHECK: return +!CHECK: } + +program acc_atomic_write_test + integer :: x, y + + !$acc atomic write + x = 7 * y + +end program acc_atomic_write_test + +! Test lowering atomic read for pointer variables. + +!CHECK-LABEL: func.func @_QPatomic_write_pointer() { +!CHECK: %[[X:.*]] = fir.alloca !fir.box> {bindc_name = "x", uniq_name = "_QFatomic_write_pointerEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFatomic_write_pointerEx"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +!CHECK: %[[C1:.*]] = arith.constant 1 : i32 +!CHECK: %[[LOAD_X:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR_X:.*]] = fir.box_addr %[[LOAD_X]] : (!fir.box>) -> !fir.ptr +!CHECK: acc.atomic.write %[[BOX_ADDR_X]] = %[[C1]] : !fir.ptr, i32 +!CHECK: %[[C2:.*]] = arith.constant 2 : i32 +!CHECK: %[[LOAD_X:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR_X:.*]] = fir.box_addr %[[LOAD_X]] : (!fir.box>) -> !fir.ptr +!CHECK: hlfir.assign %[[C2]] to %[[BOX_ADDR_X]] : i32, !fir.ptr + +subroutine atomic_write_pointer() + integer, pointer :: x + + !$acc atomic write + x = 1 + + x = 2 +end subroutine + +!CHECK-LABEL: func.func @_QPatomic_write_typed_assign +!CHECK: %[[R2:.*]] = fir.alloca f32 {bindc_name = "r2", uniq_name = "{{.*}}r2"} +!CHECK: %[[R2_DECL:.*]]:2 = hlfir.declare %[[R2]] {uniq_name = "_QFatomic_write_typed_assignEr2"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: acc.atomic.write %[[R2_DECL]]#1 = %[[CST]] : !fir.ref, f32 + +subroutine atomic_write_typed_assign + real :: r2 + !$acc atomic write + r2 = 0 +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-bounds.f90 b/flang/test/Lower/OpenACC/acc-bounds.f90 new file mode 100644 index 00000000000000..e44c786e629645 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-bounds.f90 @@ -0,0 +1,185 @@ +! This test checks lowering of OpenACC data bounds operation. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module openacc_bounds + +type t1 + integer, pointer, dimension(:) :: array_comp +end type + +type t2 + integer, dimension(10) :: array_comp +end type + +type t3 + integer, allocatable, dimension(:) :: array_comp +end type + +contains + subroutine acc_derived_type_component_pointer_array() + type(t1) :: d + !$acc enter data create(d%array_comp) + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_derived_type_component_pointer_array() { +! CHECK: %[[D:.*]] = fir.alloca !fir.type<_QMopenacc_boundsTt1{array_comp:!fir.box>>}> {bindc_name = "d", uniq_name = "_QMopenacc_boundsFacc_derived_type_component_pointer_arrayEd"} +! CHECK: %[[DECL_D:.*]]:2 = hlfir.declare %[[D]] {uniq_name = "_QMopenacc_boundsFacc_derived_type_component_pointer_arrayEd"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[COORD:.*]] = hlfir.designate %[[DECL_D]]#0{"array_comp"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[LOAD:.*]] = fir.load %[[COORD]] : !fir.ref>>> +! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[LOAD]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS1:.*]]:3 = fir.box_dims %[[LOAD]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[UB:.*]] = arith.subi %[[BOX_DIMS1]]#1, %[[C1]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[BOX_DIMS1]]#1 : index) stride(%[[BOX_DIMS1]]#2 : index) startIdx(%[[BOX_DIMS0]]#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.ptr> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%[[BOUND]]) -> !fir.ptr> {name = "d%array_comp", structured = false} +! CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ptr>) +! CHECK: return +! CHECK: } + + subroutine acc_derived_type_component_array() + type(t2) :: d + !$acc enter data create(d%array_comp) + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_derived_type_component_array() +! CHECK: %[[D:.*]] = fir.alloca !fir.type<_QMopenacc_boundsTt2{array_comp:!fir.array<10xi32>}> {bindc_name = "d", uniq_name = "_QMopenacc_boundsFacc_derived_type_component_arrayEd"} +! CHECK: %[[DECL_D:.*]]:2 = hlfir.declare %[[D]] {uniq_name = "_QMopenacc_boundsFacc_derived_type_component_arrayEd"} : (!fir.ref}>>) -> (!fir.ref}>>, !fir.ref}>>) +! CHECK: %[[C10:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C10]] : (index) -> !fir.shape<1> +! CHECK: %[[COORD:.*]] = hlfir.designate %[[DECL_D]]#0{"array_comp"} shape %[[SHAPE]] : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[C1]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[C0]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "d%array_comp", structured = false} +! CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: return +! CHECK: } + + subroutine acc_derived_type_component_allocatable_array() + type(t3) :: d + !$acc enter data create(d%array_comp) + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_derived_type_component_allocatable_array() { +! CHECK: %[[D:.*]] = fir.alloca !fir.type<_QMopenacc_boundsTt3{array_comp:!fir.box>>}> {bindc_name = "d", uniq_name = "_QMopenacc_boundsFacc_derived_type_component_allocatable_arrayEd"} +! CHECK: %[[DECL_D:.*]]:2 = hlfir.declare %[[D]] {uniq_name = "_QMopenacc_boundsFacc_derived_type_component_allocatable_arrayEd"} : (!fir.ref>>}>>) -> (!fir.ref>>}>>, !fir.ref>>}>>) +! CHECK: %[[COORD:.*]] = hlfir.designate %[[DECL_D]]#0{"array_comp"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[LOAD:.*]] = fir.load %[[COORD]] : !fir.ref>>> +! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[LOAD]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[BOX_DIMS1:.*]]:3 = fir.box_dims %[[LOAD]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[UB:.*]] = arith.subi %[[BOX_DIMS1]]#1, %[[C1]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[BOX_DIMS1]]#1 : index) stride(%[[BOX_DIMS1]]#2 : index) startIdx(%[[BOX_DIMS0]]#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "d%array_comp", structured = false} +! CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) +! CHECK: return +! CHECK: } + + subroutine acc_undefined_extent(a) + real, dimension(1:*) :: a + + !$acc kernels present(a) + !$acc end kernels + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_undefined_extent( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) { +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_undefined_extentEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %c1{{.*}} : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%c1{{.*}} : index) {strideInBytes = true} +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref>) + + subroutine acc_multi_strides(a) + real, dimension(:,:,:) :: a + + !$acc kernels present(a) + !$acc end kernels + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_multi_strides( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMopenacc_boundsFacc_multi_stridesEa"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[BOX_DIMS0:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[BOUNDS0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS0]]#1 : index) stride(%[[BOX_DIMS0]]#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true} +! CHECK: %[[STRIDE1:.*]] = arith.muli %[[BOX_DIMS0]]#2, %[[BOX_DIMS0]]#1 : index +! CHECK: %[[BOX_DIMS1:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c1{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[BOUNDS1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS1]]#1 : index) stride(%[[STRIDE1]] : index) startIdx(%{{.*}} : index) {strideInBytes = true} +! CHECK: %[[STRIDE2:.*]] = arith.muli %[[STRIDE1]], %[[BOX_DIMS1]]#1 : index +! CHECK: %[[BOX_DIMS2:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c2{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[BOUNDS2:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS2]]#1 : index) stride(%[[STRIDE2]] : index) startIdx(%{{.*}} : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUNDS0]], %[[BOUNDS1]], %[[BOUNDS2]]) -> !fir.ref> {name = "a"} +! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref>) { + + subroutine acc_optional_data(a) + real, pointer, optional :: a(:) + !$acc data attach(a) + !$acc end data + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a", fir.optional}) { +! CHECK: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QMopenacc_boundsFacc_optional_dataEa"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[ARG0_DECL]]#1 : (!fir.ref>>>) -> i1 +! CHECK: %[[RES:.*]]:5 = fir.if %[[IS_PRESENT]] -> (index, index, index, index, index) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref>>> +! CHECK: fir.result %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : index, index, index, index, index +! CHECK: } else { +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[CM1:.*]] = arith.constant -1 : index +! CHECK: fir.result %[[C0]], %[[CM1]], %[[C0]], %[[C0]], %[[C0]] : index, index, index, index, index +! CHECK: } +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[RES]]#0 : index) upperbound(%[[RES]]#1 : index) extent(%[[RES]]#2 : index) stride(%[[RES]]#3 : index) startIdx(%[[RES]]#4 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.if %[[IS_PRESENT]] -> (!fir.ptr>) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0_DECL]]#0 : !fir.ref>>> +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.ptr> +! CHECK: fir.result %[[ADDR]] : !fir.ptr> +! CHECK: } else { +! CHECK: %[[ABSENT:.*]] = fir.absent !fir.ptr> +! CHECK: fir.result %[[ABSENT]] : !fir.ptr> +! CHECK: } +! CHECK: %[[ATTACH:.*]] = acc.attach varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%[[BOUND]]) -> !fir.ptr> {name = "a"} +! CHECK: acc.data dataOperands(%[[ATTACH]] : !fir.ptr>) + + subroutine acc_optional_data2(a, n) + integer :: n + real, optional :: a(n) + !$acc data no_create(a) + !$acc end data + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data2( +! CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a", fir.optional}, %[[N:.*]]: !fir.ref {fir.bindc_name = "n"}) { +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QMopenacc_boundsFacc_optional_data2Ea"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[NO_CREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref>) bounds(%{{[0-9]+}}) -> !fir.ref> {name = "a"} +! CHECK: acc.data dataOperands(%[[NO_CREATE]] : !fir.ref>) { + + subroutine acc_optional_data3(a, n) + integer :: n + real, optional :: a(n) + !$acc data no_create(a(1:n)) + !$acc end data + end subroutine + +! CHECK-LABEL: func.func @_QMopenacc_boundsPacc_optional_data3( +! CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a", fir.optional}, %[[N:.*]]: !fir.ref {fir.bindc_name = "n"}) { +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QMopenacc_boundsFacc_optional_data3Ea"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[PRES:.*]] = fir.is_present %[[DECL_A]]#1 : (!fir.ref>) -> i1 +! CHECK: %[[STRIDE:.*]] = fir.if %[[PRES]] -> (index) { +! CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECL_A]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: fir.result %[[DIMS]]#2 : index +! CHECK: } else { +! CHECK: fir.result %c0{{.*}} : index +! CHECK: } +! CHECK: %[[BOUNDS:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[STRIDE]] : index) startIdx(%c1 : index) {strideInBytes = true} +! CHECK: %[[NOCREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref>) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "a(1:n)"} +! CHECK: acc.data dataOperands(%[[NOCREATE]] : !fir.ref>) { + +end module diff --git a/flang/test/Lower/OpenACC/acc-data-operands.f90 b/flang/test/Lower/OpenACC/acc-data-operands.f90 new file mode 100644 index 00000000000000..5151e8f6a135cd --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-data-operands.f90 @@ -0,0 +1,201 @@ +! This test checks lowering of complex OpenACC data operands. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module acc_data_operand + + type wrapper + real :: data(100) + end type + +contains + +! Testing array sections as operands +subroutine acc_operand_array_section() + real, dimension(100) :: a + + !$acc data copyin(a(1:50)) copyout(a(51:100)) + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section +! CHECK: %[[EXT:.*]] = arith.constant 100 : index +! CHECK: %[[ARR:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARR]] +! CHECK: %[[ONE:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 49 : index +! CHECK: %[[BOUND_1_50:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND_1_50]]) -> !fir.ref> {name = "a(1:50)"} +! CHECK: %[[ONE:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 50 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[BOUND_51_100:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +! CHECK: %[[COPYOUT_CREATE:.*]] = acc.create varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND_51_100]]) -> !fir.ref> {dataClause = #acc, name = "a(51:100)"} +! CHECK: acc.data dataOperands(%[[COPYIN]], %[[COPYOUT_CREATE]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK: } +! CHECK: acc.copyout accPtr(%[[COPYOUT_CREATE]] : !fir.ref>) bounds(%[[BOUND_51_100]]) to varPtr(%[[DECL]]#0 : !fir.ref>) {name = "a(51:100)"} + +! Testing array sections of a derived-type component +subroutine acc_operand_array_section_component() + + type(wrapper) :: w + + !$acc data copy(w%data(1:20)) + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section_component() { +! CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> {bindc_name = "w", uniq_name = "_QMacc_data_operandFacc_operand_array_section_componentEw"} +! CHECK: %[[DECLW:.*]]:2 = hlfir.declare %[[W]] +! CHECK: %[[EXT:.*]] = arith.constant 100 : index +! CHECK: %[[COORD_DATA:.*]] = hlfir.designate %[[DECLW]]#0{"data"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[ONE:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 19 : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +! CHECK: %[[COPY_COPYIN:.*]] = acc.copyin varPtr(%[[COORD_DATA]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "w%data(1:20)"} +! CHECK: acc.data dataOperands(%[[COPY_COPYIN]] : !fir.ref>) { +! CHECK: acc.terminator +! CHECK: } +! CHECK: acc.copyout accPtr(%[[COPY_COPYIN]] : !fir.ref>) bounds(%[[BOUND]]) to varPtr(%[[COORD_DATA]] : !fir.ref>) {dataClause = #acc, name = "w%data(1:20)"} + +! Testing derived-type component without section +subroutine acc_operand_derived_type_component() + type(wrapper) :: w + + !$acc data copy(w%data) + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_derived_type_component() { +! CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> {bindc_name = "w", uniq_name = "_QMacc_data_operandFacc_operand_derived_type_componentEw"} +! CHECK: %[[DECLW:.*]]:2 = hlfir.declare %[[W]] +! CHECK: %[[EXT:.*]] = arith.constant 100 : index +! CHECK: %[[COORD_DATA:.*]] = hlfir.designate %[[DECLW]]#0{"data"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[ONE:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %[[EXT]], %[[ONE]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +! CHECK: %[[COPY_COPYIN:.*]] = acc.copyin varPtr(%[[COORD_DATA]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "w%data"} +! CHECK: acc.data dataOperands(%[[COPY_COPYIN]] : !fir.ref>) { +! CHECK: acc.terminator +! CHECK: } +! CHECK: acc.copyout accPtr(%[[COPY_COPYIN]] : !fir.ref>) bounds(%[[BOUND]]) to varPtr(%[[COORD_DATA]] : !fir.ref>) {dataClause = #acc, name = "w%data"} + + +! Testing array of derived-type component without section +subroutine acc_operand_array_derived_type_component() + type(wrapper) :: w(10) + + !$acc data copy(w(1)%data) + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_derived_type_component() { +! CHECK: %[[W:.*]] = fir.alloca !fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>> {bindc_name = "w", uniq_name = "_QMacc_data_operandFacc_operand_array_derived_type_componentEw"} +! CHECK: %[[DECLW:.*]]:2 = hlfir.declare %[[W]] +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[W_1:.*]] = hlfir.designate %[[DECLW]]#0 (%[[C1]]) : (!fir.ref}>>>, index) -> !fir.ref}>> +! CHECK: %[[EXT:.*]] = arith.constant 100 : index +! CHECK: %[[COORD_W1_DATA:.*]] = hlfir.designate %[[W_1]]{"data"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[ONE:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %[[EXT]], %[[ONE]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +! CHECK: %[[COPY_COPYIN:.*]] = acc.copyin varPtr(%[[COORD_W1_DATA]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "w(1_8)%data"} +! CHECK: acc.data dataOperands(%[[COPY_COPYIN]] : !fir.ref>) { +! CHECK: acc.terminator +! CHECK: } +! CHECK: acc.copyout accPtr(%[[COPY_COPYIN]] : !fir.ref>) bounds(%[[BOUND]]) to varPtr(%[[COORD_W1_DATA]] : !fir.ref>) {dataClause = #acc, name = "w(1_8)%data"} + +! Testing array sections on allocatable array +subroutine acc_operand_array_section_allocatable() + real, allocatable :: a(:) + + allocate(a(100)) + + !$acc data copyin(a(1:50)) copyout(a(51:100)) + !$acc end data + + deallocate(a) +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section_allocatable() { +! CHECK: %[[A:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QMacc_data_operandFacc_operand_array_section_allocatableEa"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] {fortran_attrs = #fir.var_attrs +! CHECK: %[[LOAD_BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +! CHECK: %[[LOAD_BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_0:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_1:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.subi %[[C1]], %[[DIMS0_0]]#0 : index +! CHECK: %[[C50:.*]] = arith.constant 50 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C50]], %[[DIMS0_0]]#0 : index +! CHECK: %[[LOAD_BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_2:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS0_2]]#1 : index) stride(%[[DIMS0_1]]#2 : index) startIdx(%[[DIMS0_0]]#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD_BOX_A_0]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(1:50)"} +! CHECK: %[[LOAD_BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +! CHECK: %[[LOAD_BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_0:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_1:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C51:.*]] = arith.constant 51 : index +! CHECK: %[[LB:.*]] = arith.subi %[[C51]], %[[DIMS0_0]]#0 : index +! CHECK: %[[C100:.*]] = arith.constant 100 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C100]], %[[DIMS0_0]]#0 : index +! CHECK: %[[LOAD_BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_2:.*]]:3 = fir.box_dims %[[LOAD_BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS0_2]]#1 : index) stride(%[[DIMS0_1]]#2 : index) startIdx(%[[DIMS0_0]]#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD_BOX_A_0]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[COPYOUT_CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {dataClause = #acc, name = "a(51:100)"} +! CHECK: acc.data dataOperands(%[[COPYIN]], %[[COPYOUT_CREATE]] : !fir.heap>, !fir.heap>) { +! CHECK: acc.terminator +! CHECK: } +! CHECK: acc.copyout accPtr(%[[COPYOUT_CREATE]] : !fir.heap>) bounds(%[[BOUND]]) to varPtr(%[[BOX_ADDR]] : !fir.heap>) {name = "a(51:100)"} + + +! Testing array sections on pointer array +subroutine acc_operand_array_section_pointer() + real, target :: a(100) + real, pointer :: p(:) + + p => a + + !$acc data copyin(p(1:50)) + !$acc end data +end subroutine + +! CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section_pointer() { +! CHECK: %[[P:.*]] = fir.alloca !fir.box>> {bindc_name = "p", uniq_name = "_QMacc_data_operandFacc_operand_array_section_pointerEp"} +! CHECK: %[[DECLP:.*]]:2 = hlfir.declare %[[P]] {fortran_attrs = #fir.var_attrs +! CHECK: %[[LOAD_BOX_P_0:.*]] = fir.load %[[DECLP]]#0 : !fir.ref>>> +! CHECK: %[[LOAD_BOX_P_1:.*]] = fir.load %[[DECLP]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_0:.*]]:3 = fir.box_dims %[[LOAD_BOX_P_1]], %[[C0:.*]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_1:.*]]:3 = fir.box_dims %[[LOAD_BOX_P_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.subi %[[C1]], %[[DIMS0_0]]#0 : index +! CHECK: %[[C50:.*]] = arith.constant 50 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C50]], %[[DIMS0_0]]#0 : index +! CHECK: %[[LOAD_BOX_P_2:.*]] = fir.load %[[DECLP]]#1 : !fir.ref>>> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS0_2:.*]]:3 = fir.box_dims %[[LOAD_BOX_P_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS0_2]]#1 : index) stride(%[[DIMS0_1]]#2 : index) startIdx(%[[DIMS0_0]]#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD_BOX_P_0]] : (!fir.box>>) -> !fir.ptr> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%[[BOUND]]) -> !fir.ptr> {name = "p(1:50)"} +! CHECK: acc.data dataOperands(%[[COPYIN]] : !fir.ptr>) { +! CHECK: acc.terminator +! CHECK: } + + +end module diff --git a/flang/test/Lower/OpenACC/acc-data.f90 b/flang/test/Lower/OpenACC/acc-data.f90 new file mode 100644 index 00000000000000..6e0ecb9129061c --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-data.f90 @@ -0,0 +1,202 @@ +! This test checks lowering of OpenACC data directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_data + real, dimension(10, 10) :: a, b, c + real, pointer :: d, e + logical :: ifCondition = .TRUE. + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK:%[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK:%[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK:%[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK:%[[DECLD:.*]]:2 = hlfir.declare %[[D]] +! CHECK: %[[E:.*]] = fir.alloca !fir.box> {bindc_name = "e", uniq_name = "{{.*}}Ee"} +! CHECK:%[[DECLE:.*]]:2 = hlfir.declare %[[E]] + + !$acc data if(.TRUE.) copy(a) + !$acc end data + +! CHECK: %[[IF1:.*]] = arith.constant true +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.data if(%[[IF1]]) dataOperands(%[[COPYIN]] : !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK:acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} + + !$acc data copy(a) if(ifCondition) + !$acc end data + +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[IFCOND:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: %[[IF2:.*]] = fir.convert %[[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.data if(%[[IF2]]) dataOperands(%[[COPYIN]] : !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK:acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} + + !$acc data copy(a, b, c) + !$acc end data + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK:acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK:acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK:acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc data copy(a) copy(b) copy(c) + !$acc end data + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK:acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK:acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK:acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc data copyin(a) copyin(readonly: b, c) + !$acc end data + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc data copyout(a) copyout(zero: b) copyout(c) + !$acc end data + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK:acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK:acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK:acc.copyout accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {name = "c"} + + !$acc data create(a, b) create(zero: c) + !$acc end data + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + !$acc data create(c) copy(b) create(a) + !$acc end data +! CHECK:%[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK:%[[COPY_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK:%[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.data dataOperands(%[[CREATE_C]], %[[COPY_B]], %[[CREATE_A]] : !fir.ref>, !fir.ref>, !fir.ref>) { + + !$acc data no_create(a, b) create(zero: c) + !$acc end data + +! CHECK: %[[NO_CREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NO_CREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.data dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + !$acc data present(a, b, c) + !$acc end data + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[PRESENT_C:.*]] = acc.present varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.data dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc data deviceptr(b, c) + !$acc end data + +! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[DEVICEPTR_C:.*]] = acc.deviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.data dataOperands(%[[DEVICEPTR_B]], %[[DEVICEPTR_C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc data attach(d, e) + !$acc end data + +! CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%{{.*}} : !fir.ptr) -> !fir.ptr {name = "d"} +! CHECK: %[[ATTACH_E:.*]] = acc.attach varPtr(%{{.*}} : !fir.ptr) -> !fir.ptr {name = "e"} +! CHECK: acc.data dataOperands(%[[ATTACH_D]], %[[ATTACH_E]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.detach accPtr(%[[ATTACH_D]] : !fir.ptr) {dataClause = #acc, name = "d"} +! CHECK: acc.detach accPtr(%[[ATTACH_E]] : !fir.ptr) {dataClause = #acc, name = "e"} + + !$acc data present(a) async + !$acc end data + +! CHECK: acc.data dataOperands(%{{.*}}) { +! CHECK: } attributes {asyncOnly = [#acc.device_type]} + + !$acc data copy(a) async(1) + !$acc end data + +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC:.*]] : i32) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.data async(%[[ASYNC]] : i32) dataOperands(%[[COPYIN]] : !fir.ref>) { +! CHECK: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC]] : i32) to varPtr(%{{.*}} : !fir.ref>) {dataClause = #acc, name = "a"} + + !$acc data present(a) wait + !$acc end data + +! CHECK: acc.data dataOperands(%{{.*}}) wait { +! CHECK: } + + !$acc data present(a) wait(1) + !$acc end data + +! CHECK: acc.data dataOperands(%{{.*}}) wait({%{{.*}} : i32}) { +! CHECK: }{{$}} + + !$acc data present(a) wait(devnum: 0: 1) + !$acc end data + +! CHECK: acc.data dataOperands(%{{.*}}) wait({devnum: %{{.*}} : i32, %{{.*}} : i32}) { +! CHECK: }{{$}} + + !$acc data default(none) + !$acc end data + +! CHECK: acc.data { +! CHECK: acc.terminator +! CHECK: } attributes {defaultAttr = #acc} + + !$acc data default(present) + !$acc end data + +! CHECK: acc.data { +! CHECK: acc.terminator +! CHECK: } attributes {defaultAttr = #acc} + + !$acc data + !$acc end data +! CHECK-NOT: acc.data + +end subroutine acc_data diff --git a/flang/test/Lower/OpenACC/acc-declare-globals.f90 b/flang/test/Lower/OpenACC/acc-declare-globals.f90 new file mode 100644 index 00000000000000..1c54010dc108a2 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-declare-globals.f90 @@ -0,0 +1,78 @@ +! This test checks lowering of OpenACC declare directive in module specification +! part. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module acc_declare_test + integer, parameter :: n = 100000 + real, dimension(n) :: data1 + !$acc declare create(data1) +end module + +! CHECK-LABEL: fir.global @_QMacc_declare_testEdata1 {acc.declare = #acc.declare} : !fir.array<100000xf32> + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_testEdata1_acc_dtor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.terminator +! CHECK: } + +module acc_declare_copyin_test + integer, parameter :: n = 100000 + real, dimension(n) :: data1 + !$acc declare copyin(data1) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_copyin_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_copyin_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } + +module acc_declare_device_resident_test + integer, parameter :: n = 5000 + integer, dimension(n) :: data1 + !$acc declare device_resident(data1) +end module + +! CHECK-LABEL: fir.global @_QMacc_declare_device_resident_testEdata1 {acc.declare = #acc.declare} : !fir.array<5000xi32> + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_device_resident_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_device_resident_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICERESIDENT:.*]] = acc.declare_device_resident varPtr(%0 : !fir.ref>) -> !fir.ref> {name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[DEVICERESIDENT]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_device_resident_testEdata1_acc_dtor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_device_resident_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.terminator +! CHECK: } + +module acc_declare_device_link_test + integer, parameter :: n = 5000 + integer, dimension(n) :: data1 + !$acc declare link(data1) +end module + +! CHECK-LABEL: fir.global @_QMacc_declare_device_link_testEdata1 {acc.declare = #acc.declare} : !fir.array<5000xi32> { + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_device_link_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_device_link_testEdata1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[LINK:.*]] = acc.declare_link varPtr(%[[GLOBAL_ADDR]] : !fir.ref>) -> !fir.ref> {name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[LINK]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90 new file mode 100644 index 00000000000000..0066e712fbdcce --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-declare.f90 @@ -0,0 +1,474 @@ +! This test checks lowering of OpenACC declare directive in function and +! subroutine specification parts. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module acc_declare + contains + + subroutine acc_declare_copy() + integer :: a(100), i + !$acc declare copy(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_copy() +! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index +! CHECK-DAG: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_copyEa"} +! CHECK-DAG: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_copyEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) { +! CHECK: } +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[COPYIN]] : !fir.ref>) +! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%[[BOUND]]) to varPtr(%[[DECL]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: return + + subroutine acc_declare_create() + integer :: a(100), i + !$acc declare create(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_create() { +! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index +! CHECK-DAG: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_createEa"} +! CHECK-DAG: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_createEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) { +! CHECK: } +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[CREATE]] : !fir.ref>) bounds(%[[BOUND]]) {dataClause = #acc, name = "a"} +! CHECK: return + + subroutine acc_declare_present(a) + integer :: a(100), i + !$acc declare present(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_present( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) +! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index +! CHECK-DAG: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%[[C1]] : index) +! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) + + subroutine acc_declare_copyin() + integer :: a(100), b(10), i + !$acc declare copyin(a) copyin(readonly: b) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_copyin() +! CHECK: %[[A:.*]] = fir.alloca !fir.array<100xi32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_copyinEa"} +! CHECK: %[[ADECL:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_copyinEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "b", uniq_name = "_QMacc_declareFacc_declare_copyinEb"} +! CHECK: %[[BDECL:.*]]:2 = hlfir.declare %[[B]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_copyinEb"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[ADECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[BDECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) + + subroutine acc_declare_copyout() + integer :: a(100), i + !$acc declare copyout(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_copyout() +! CHECK: %[[A:.*]] = fir.alloca !fir.array<100xi32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_copyoutEa"} +! CHECK: %[[ADECL:.*]]:2 = hlfir.declare %[[A]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_copyoutEa"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.copyout accPtr(%[[CREATE]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[ADECL]]#0 : !fir.ref>) {name = "a"} +! CHECK: return + + subroutine acc_declare_deviceptr(a) + integer :: a(100), i + !$acc declare deviceptr(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_deviceptr( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) { +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_deviceptrEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DEVICEPTR:.*]] = acc.deviceptr varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.declare_enter dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) + + subroutine acc_declare_link(a) + integer :: a(100), i + !$acc declare link(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_link( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_linkEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[LINK:.*]] = acc.declare_link varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.declare_enter dataOperands(%[[LINK]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) + + subroutine acc_declare_device_resident(a) + integer :: a(100), i + !$acc declare device_resident(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_device_resident( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_device_residentEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICERES]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICERES]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "a"} + + subroutine acc_declare_device_resident2() + integer, parameter :: n = 100 + real, dimension(n) :: dataparam + !$acc declare device_resident(dataparam) + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_device_resident2() +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> {bindc_name = "dataparam", uniq_name = "_QMacc_declareFacc_declare_device_resident2Edataparam"} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_device_resident2Edataparam"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DEVICERES:.*]] = acc.declare_device_resident varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "dataparam"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICERES]] : !fir.ref>) +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICERES]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICERES]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "dataparam"} + + subroutine acc_declare_link2() + integer, parameter :: n = 100 + real, dimension(n) :: dataparam + !$acc declare link(dataparam) + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_link2() +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> {bindc_name = "dataparam", uniq_name = "_QMacc_declareFacc_declare_link2Edataparam"} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_link2Edataparam"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[LINK:.*]] = acc.declare_link varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "dataparam"} +! CHECK: acc.declare_enter dataOperands(%[[LINK]] : !fir.ref>) + + subroutine acc_declare_deviceptr2() + integer, parameter :: n = 100 + real, dimension(n) :: dataparam + !$acc declare deviceptr(dataparam) + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_deviceptr2() +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> {bindc_name = "dataparam", uniq_name = "_QMacc_declareFacc_declare_deviceptr2Edataparam"} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_deviceptr2Edataparam"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DEVICEPTR:.*]] = acc.deviceptr varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "dataparam"} +! CHECK: acc.declare_enter dataOperands(%[[DEVICEPTR]] : !fir.ref>) + + function acc_declare_in_func() + real :: a(1024) + !$acc declare device_resident(a) + end function + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_in_func() -> f32 { +! CHECK: %[[DEVICE_RESIDENT:.*]] = acc.declare_device_resident varPtr(%{{.*}}#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref>) +! CHECK: %[[LOAD:.*]] = fir.load %{{.*}}#1 : !fir.ref +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[DEVICE_RESIDENT]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICE_RESIDENT]] : !fir.ref>) bounds(%6) {dataClause = #acc, name = "a"} +! CHECK: return %[[LOAD]] : f32 +! CHECK: } + + function acc_declare_in_func2(i) + real :: a(1024) + integer :: i + !$acc declare create(a) + return + end function + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_in_func2(%arg0: !fir.ref {fir.bindc_name = "i"}) -> f32 { +! CHECK: %[[ALLOCA_A:.*]] = fir.alloca !fir.array<1024xf32> {bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_in_func2Ea"} +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ALLOCA_A]](%{{.*}}) {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_in_func2Ea"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL_A]]#0 : !fir.ref>) bounds(%{{[0-9]+}}) -> !fir.ref> {name = "a"} +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: cf.br ^bb1 +! CHECK: ^bb1: +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[CREATE]] : !fir.ref>) bounds(%{{[0-9]+}}) {dataClause = #acc, name = "a"} +! CHECK: return %{{.*}} : f32 +! CHECK: } + + subroutine acc_declare_allocate() + integer, allocatable :: a(:) + !$acc declare create(a) + + allocate(a(100)) + +! CHECK: %{{.*}} = fir.allocmem !fir.array, %{{.*}} {fir.must_be_heap = true, uniq_name = "_QMacc_declareFacc_declare_allocateEa.alloc"} +! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action} : !fir.ref>>> + + deallocate(a) + +! CHECK: %{{.*}} = fir.box_addr %{{.*}} {acc.declare_action = #acc.declare_action} : (!fir.box>>) -> !fir.heap> + +! CHECK: fir.freemem %{{.*}} : !fir.heap> +! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action} : !fir.ref>>> + +! CHECK: fir.if +! CHECK: fir.freemem %{{.*}} : !fir.heap> +! CHECK: fir.store %{{.*}} to %{{.*}}#1 {acc.declare_action = #acc.declare_action} : !fir.ref>>> +! CHECK: } + + end subroutine + +! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_post_alloc( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>>) { +! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[ARG0]] : !fir.ref>>>) -> !fir.ref>>> {implicit = true, name = "a_desc", structured = false} +! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.ref>>>) +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare} : (!fir.box>>) -> !fir.heap> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) -> !fir.heap> {name = "a", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.heap>) +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_pre_dealloc( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>>) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare} : (!fir.box>>) -> !fir.heap> +! CHECK: %[[GETDEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[BOX_ADDR]] : !fir.heap>) -> !fir.heap> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[GETDEVICEPTR]] : !fir.heap>) +! CHECK: acc.delete accPtr(%[[GETDEVICEPTR]] : !fir.heap>) {dataClause = #acc, name = "a", structured = false} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func private @_QMacc_declareFacc_declare_allocateEa_acc_declare_update_desc_post_dealloc( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>>) { +! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[BOX_ADDR]] : !fir.heap>) -> !fir.heap> {implicit = true, name = "a_desc", structured = false} +! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.heap>) +! CHECK: return +! CHECK: } + + subroutine acc_declare_multiple_directive(a, b) + integer :: a(100), b(100), i + !$acc declare copy(a) + !$acc declare copyout(b) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_multiple_directive( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) { +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DECL_B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_multiple_directiveEb"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[DECL_A]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECL_B]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN]], %[[CREATE]] : !fir.ref>, !fir.ref>) +! CHECK: %{{.*}}:{{.*}} = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) { + + +! CHECK: acc.copyout accPtr(%[[CREATE]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECL_B]]#0 : !fir.ref>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECL_A]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} + + subroutine acc_declare_array_section(a) + integer :: a(:) + !$acc declare copy(a(1:10)) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_array_section( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) { +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QMacc_declareFacc_declare_array_sectionEa"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 {acc.declare = #acc.declare} : (!fir.box>) -> !fir.ref> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a(1:10)"} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>) + +! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[BOX_ADDR]] : !fir.ref>) {dataClause = #acc, name = "a(1:10)"} + + subroutine acc_declare_allocate_with_stat() + integer :: status + real, pointer, dimension(:) :: localptr + !$acc declare create(localptr) + allocate(localptr(n), stat=status) + + deallocate(localptr, stat=status) + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_allocate_with_stat() +! CHECK: fir.call @_FortranAPointerAllocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} {acc.declare_action = #acc.declare_action} +! CHECK: fir.call @_FortranAPointerDeallocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} {acc.declare_action = #acc.declare_action} +end module + +module acc_declare_allocatable_test + integer, allocatable :: data1(:) + !$acc declare create(data1) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_allocatable_testEdata1_acc_ctor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) {acc.declare = #acc.declare} : !fir.ref>>> +! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, implicit = true, name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>>>) +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_post_alloc() { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref>>> +! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {implicit = true, name = "data1_desc", structured = false} +! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.ref>>>) +! CHECK: %[[LOAD:.*]] = fir.load %[[GLOBAL_ADDR]] : !fir.ref>>> +! CHECK: %[[BOXADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare} : (!fir.box>>) -> !fir.heap> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOXADDR]] : !fir.heap>) -> !fir.heap> {name = "data1", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.heap>) +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_pre_dealloc() { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref>>> +! CHECK: %[[LOAD:.*]] = fir.load %[[GLOBAL_ADDR]] : !fir.ref>>> +! CHECK: %[[BOXADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare} : (!fir.box>>) -> !fir.heap> +! CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[BOXADDR]] : !fir.heap>) -> !fir.heap> {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVPTR]] : !fir.heap>) +! CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.heap>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_post_dealloc() { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref>>> +! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {implicit = true, name = "data1_desc", structured = false} +! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.ref>>>) +! CHECK: return +! CHECK: } + +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_allocatable_testEdata1_acc_dtor { +! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) {acc.declare = #acc.declare} : !fir.ref>>> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref>>>) -> !fir.ref>>> {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>>>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>>>) {dataClause = #acc, name = "data1", structured = false} +! CHECK: acc.terminator +! CHECK: } + + +module acc_declare_equivalent + integer, parameter :: n = 10 + real :: v1(n) + real :: v2(n) + equivalence(v1(1), v2(1)) + !$acc declare create(v2) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_equivalentEv2_acc_ctor { +! CHECK: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {name = "v2", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_equivalentEv2_acc_dtor { +! CHECK: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalentEv1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "v2", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "v2", structured = false} +! CHECK: acc.terminator +! CHECK: } + +module acc_declare_equivalent2 + real :: v1(10) + real :: v2(5) + equivalence(v1(6), v2(1)) + !$acc declare create(v2) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_equivalent2Ev2_acc_ctor { +! CHECK: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {name = "v2", structured = false} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.terminator +! CHECK: } +! CHECK-LABEL: acc.global_dtor @_QMacc_declare_equivalent2Ev2_acc_dtor { +! CHECK: %[[ADDR:.*]] = fir.address_of(@_QMacc_declare_equivalent2Ev1) {acc.declare = #acc.declare} : !fir.ref> +! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[ADDR]] : !fir.ref>) -> !fir.ref> {dataClause = #acc, name = "v2", structured = false} +! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[DEVICEPTR]] : !fir.ref>) {dataClause = #acc, name = "v2", structured = false} +! CHECK: acc.terminator +! CHECK: } + +! Test that the pre/post alloc/dealloc attributes are set when the +! allocate/deallocate statement are in a different module. +module acc_declare_allocatable_test2 +contains + subroutine init() + use acc_declare_allocatable_test + allocate(data1(100)) +! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action} : !fir.ref>>> + end subroutine + + subroutine finalize() + use acc_declare_allocatable_test + deallocate(data1) +! CHECK: %{{.*}} = fir.box_addr %{{.*}} {acc.declare_action = #acc.declare_action} : (!fir.box>>) -> !fir.heap> +! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action} : !fir.ref>>> + end subroutine +end module + +module acc_declare_allocatable_test3 + integer, allocatable :: data1(:) + integer, allocatable :: data2(:) + !$acc declare create(data1, data2, data1) +end module + +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_allocatable_test3Edata1_acc_ctor +! CHECK-LABEL: acc.global_ctor @_QMacc_declare_allocatable_test3Edata2_acc_ctor + +module acc_declare_post_action_stat + real, dimension(:), allocatable :: x, y + !$acc declare create(x,y) + +contains + + subroutine init() + integer :: stat + allocate(x(10), y(10), stat=stat) + end subroutine +end module + +! CHECK-LABEL: func.func @_QMacc_declare_post_action_statPinit() +! CHECK: fir.call @_FortranAAllocatableAllocate({{.*}}) fastmath {acc.declare_action = #acc.declare_action} : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 +! CHECK: fir.if +! CHECK: fir.call @_FortranAAllocatableAllocate({{.*}}) fastmath {acc.declare_action = #acc.declare_action} : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 diff --git a/flang/test/Lower/OpenACC/acc-device-type.f90 b/flang/test/Lower/OpenACC/acc-device-type.f90 new file mode 100644 index 00000000000000..ae01d0dc5fcde3 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-device-type.f90 @@ -0,0 +1,48 @@ +! This test checks lowering of OpenACC device_type clause on directive where its +! position and the clauses that follow have special semantic + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine sub1() + + !$acc parallel num_workers(16) + !$acc end parallel + +! CHECK: acc.parallel num_workers(%c16{{.*}} : i32) { + + !$acc parallel num_workers(1) device_type(nvidia) num_workers(16) + !$acc end parallel + +! CHECK: acc.parallel num_workers(%c1{{.*}} : i32, %c16{{.*}} : i32 [#acc.device_type]) + + !$acc parallel device_type(*) num_workers(1) device_type(nvidia) num_workers(16) + !$acc end parallel + +! CHECK: acc.parallel num_workers(%c1{{.*}} : i32 [#acc.device_type], %c16{{.*}} : i32 [#acc.device_type]) + + !$acc parallel vector_length(1) + !$acc end parallel + +! CHECK: acc.parallel vector_length(%c1{{.*}} : i32) + + !$acc parallel device_type(multicore) vector_length(1) + !$acc end parallel + +! CHECK: acc.parallel vector_length(%c1{{.*}} : i32 [#acc.device_type]) + + !$acc parallel num_gangs(2) device_type(nvidia) num_gangs(4) + !$acc end parallel + +! CHECK: acc.parallel num_gangs({%c2{{.*}} : i32}, {%c4{{.*}} : i32} [#acc.device_type]) + + !$acc parallel num_gangs(2) device_type(nvidia) num_gangs(1, 1, 1) + !$acc end parallel + +! CHECK: acc.parallel num_gangs({%c2{{.*}} : i32}, {%c1{{.*}} : i32, %c1{{.*}} : i32, %c1{{.*}} : i32} [#acc.device_type]) + + !$acc parallel device_type(nvidia, default) num_gangs(1, 1, 1) + !$acc end parallel + +! CHECK: acc.parallel num_gangs({%c1{{.*}} : i32, %c1{{.*}} : i32, %c1{{.*}} : i32} [#acc.device_type], {%c1{{.*}} : i32, %c1{{.*}} : i32, %c1{{.*}} : i32} [#acc.device_type]) + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90 new file mode 100644 index 00000000000000..ee33e0304f290e --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-enter-data.f90 @@ -0,0 +1,818 @@ +! This test checks lowering of OpenACC enter data directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_enter_data + integer :: async = 1 + real, dimension(10, 10) :: a, b, c + real, pointer :: d + logical :: ifCondition = .TRUE. + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[EXTENT_C10:.*]] = arith.constant 10 : index +!CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +!CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +!CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +!CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +!CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] + + !$acc enter data create(a) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[ONE]] : index +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT_C10]], %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXTENT_C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} + + !$acc enter data create(a) if(.true.) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[ONE]] : index +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT_C10]], %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXTENT_C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: [[IF1:%.*]] = arith.constant true +!CHECK: acc.enter_data if([[IF1]]) dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} + + !$acc enter data create(a) if(ifCondition) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[ONE]] : index +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT_C10]], %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXTENT_C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.enter_data if([[IF2]]) dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} + + !$acc enter data create(a) create(b) create(c) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "c", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} + + !$acc enter data create(a) create(b) create(zero: c) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {dataClause = #acc, name = "c", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} + + !$acc enter data copyin(a) create(b) attach(d) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10_{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: %[[BOX_D:.*]] = fir.load %[[DECLD]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[BOX_ADDR_D]] : !fir.ptr) -> !fir.ptr {name = "d", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]], %[[ATTACH_D]] : !fir.ref>, !fir.ref>, !fir.ptr){{$}} + + !$acc enter data create(a) async +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {asyncOnly = [#acc.device_type], name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {async} + + !$acc enter data create(a) wait +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {wait} + + !$acc enter data create(a) async wait +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {asyncOnly = [#acc.device_type], name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {async, wait} + + !$acc enter data create(a) async(1) +!CHECK: %[[ASYNC1:.*]] = arith.constant 1 : i32 +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) async(%[[ASYNC1]] : i32) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data async(%[[ASYNC1]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) + + !$acc enter data create(a) async(async) +!CHECK: %[[ASYNC2:.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) + +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) async(%[[ASYNC2]] : i32) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data async(%[[ASYNC2]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) + + !$acc enter data create(a) wait(1) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[WAIT1:.*]] = arith.constant 1 : i32 +!CHECK: acc.enter_data wait(%[[WAIT1]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) + + !$acc enter data create(a) wait(queues: 1, 2) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[WAIT2:.*]] = arith.constant 1 : i32 +!CHECK: %[[WAIT3:.*]] = arith.constant 2 : i32 +!CHECK: acc.enter_data wait(%[[WAIT2]], %[[WAIT3]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref>) + + !$acc enter data create(a) wait(devnum: 1: queues: 1, 2) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[WAIT4:.*]] = arith.constant 1 : i32 +!CHECK: %[[WAIT5:.*]] = arith.constant 2 : i32 +!CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32 +!CHECK: acc.enter_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref>) + + !$acc enter data copyin(a(1:10,1:5)) +!CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[EXTENT_C10]] : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a(1:10,1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) + + !$acc enter data copyin(a(1:,1:5)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB1:.*]] = arith.constant 0 : index +!CHECK: %[[UB1:.*]] = arith.subi %c10{{.*}}, %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : index) upperbound(%[[UB1]] : index) extent(%c10{{.*}} : index) stride(%[[ONE]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[LB2:.*]] = arith.constant 0 : index +!CHECK: %[[UB2:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : index) upperbound(%[[UB2]] : index) extent(%[[EXTENT_C10]] : index) stride(%[[ONE]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(1:,1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) + + !$acc enter data copyin(a(:10,1:5)) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[UB1:.*]] = arith.constant 9 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB1]] : index) extent(%[[C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB2:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB2]] : index) extent(%[[EXTENT_C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(:10,1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) + + !$acc enter data copyin(a(:,:)) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[UB:.*]] = arith.subi %c10{{.*}}, %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%c10{{.*}} : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[UB:.*]] = arith.subi %c10{{.*}}, %[[ONE]] : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%c10{{.*}} : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(:,:)", structured = false} +end subroutine acc_enter_data + +subroutine acc_enter_data_dummy(a, b, n, m) + integer :: n, m + real :: a(1:10) + real :: b(n:m) + +!CHECK-LABEL: func.func @_QPacc_enter_data_dummy +!CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}, %[[N:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[M:.*]]: !fir.ref {fir.bindc_name = "m"} +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[DECLN:.*]]:2 = hlfir.declare %[[N]] +!CHECK: %[[DECLM:.*]]:2 = hlfir.declare %[[M]] +!CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref +!CHECK: %[[N_I64:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[N_IDX:.*]] = fir.convert %[[N_I64]] : (i64) -> index +!CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref +!CHECK: %[[M_I64:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[M_IDX:.*]] = fir.convert %[[M_I64]] : (i64) -> index +!CHECK: %[[M_N:.*]] = arith.subi %[[M_IDX]], %[[N_IDX]] : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[M_N_1:.*]] = arith.addi %[[M_N]], %[[C1]] : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[M_N_1]], %[[C0]] : index +!CHECK: %[[EXT_B:.*]] = arith.select %[[CMP]], %[[M_N_1]], %[[C0]] : index +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] + + !$acc enter data create(a) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%c10{{.*}} : index) stride(%c1{{.*}} : index) startIdx(%{{.*}} : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(b) +!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[DIMS]]#1 : index) stride(%[[DIMS]]#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true} +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(5:10)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB1:.*]] = arith.constant 4 : index +!CHECK: %[[UB1:.*]] = arith.constant 9 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : index) upperbound(%[[UB1]] : index) extent(%c10{{.*}} : index) stride(%[[ONE]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "a(5:10)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + + !$acc enter data create(b(n:m)) +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref +!CHECK: %[[N_CONV1:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[N_CONV2:.*]] = fir.convert %[[N_CONV1]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[N_CONV2]], %[[N_IDX]] : index +!CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref +!CHECK: %[[M_CONV1:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[M_CONV2:.*]] = fir.convert %[[M_CONV1]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[M_CONV2]], %[[N_IDX]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true} +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(n:m)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + + !$acc enter data create(b(n:)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0_8 : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[N_IDX]] : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXT_B]], %c1{{.*}} : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true} +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(n:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + + !$acc enter data create(b(:)) +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[EXT_B]], %[[ONE]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true} +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + +end subroutine + +! Test lowering of array section for non default lower bound. +subroutine acc_enter_data_non_default_lb() + integer :: a(0:9) + integer :: b(11:20) + +!CHECK-LABEL: func.func @_QPacc_enter_data_non_default_lb() { +!CHECK: %[[BASELB:.*]] = arith.constant 0 : index +!CHECK: %[[EXTENT_C10:.*]] = arith.constant 10 : index +!CHECK: %[[A:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "a", uniq_name = "_QFacc_enter_data_non_default_lbEa"} +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[B:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "b", uniq_name = "_QFacc_enter_data_non_default_lbEb"} +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] + + !$acc enter data create(a(5:9)) +!CHECK: %[[SECTIONLB:.*]] = arith.constant 5 : index +!CHECK: %[[LB:.*]] = arith.subi %[[SECTIONLB]], %[[BASELB]] : index +!CHECK: %[[SECTIONUB:.*]] = arith.constant 9 : index +!CHECK: %[[UB:.*]] = arith.subi %[[SECTIONUB]], %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%c10{{.*}} : index) stride(%{{.*}} : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(5:9)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:)) +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT_C10]], %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[EXTENT_C10]] : index) stride(%{{.*}} : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:6)) +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index +!CHECK: %[[SECTIONUB:.*]] = arith.constant 6 : index +!CHECK: %[[UB:.*]] = arith.subi %[[SECTIONUB]], %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%c10{{.*}} : index) stride(%{{.*}} : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:6)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(4:)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[SECTIONLB:.*]] = arith.constant 4 : index +!CHECK: %[[LB:.*]] = arith.subi %[[SECTIONLB]], %[[BASELB]] : index +!CHECK: %[[UB:.*]] = arith.subi %[[EXTENT_C10]], %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXTENT_C10]] : index) stride(%{{.*}} : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(4:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(b) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%{{.*}} : index) startIdx(%c11{{.*}} : index) {strideInBytes = true} +!CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +end subroutine + +! Test lowering of assumed size arrays. +subroutine acc_enter_data_assumed(a, b, n, m) + integer :: n, m + real :: a(:) + real :: b(10:) + +!CHECK-LABEL: func.func @_QPacc_enter_data_assumed( +!CHECK-SAME: %[[A:.*]]: !fir.box> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.box> {fir.bindc_name = "b"}, %[[N:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[M:.*]]: !fir.ref {fir.bindc_name = "m"}) { +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[LB_C10:.*]] = arith.constant 10 : i64 +!CHECK: %[[LB_C10_IDX:.*]] = fir.convert %[[LB_C10]] : (i64) -> index +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +!CHECK: %[[DECLM:.*]]:2 = hlfir.declare %[[M]] +!CHECK: %[[DECLN:.*]]:2 = hlfir.declare %[[N]] + + !$acc enter data create(a) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS]]#1, %[[C1]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS]]#1 : index) stride(%[[DIMS]]#2 : index) startIdx(%[[C1]] : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:)) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS1]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(2:)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LB:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS1]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(2:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:4)) +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.constant 3 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:4)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(6:10)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[LB:.*]] = arith.constant 5 : index +!CHECK: %[[UB:.*]] = arith.constant 9 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(6:10)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(n:)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) + +!CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECLA]]#1, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(n:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:m)) +!CHECK: %[[BASELB:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) + +!CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[BASELB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:m)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(n:m)) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) + +!CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index + +!CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLA]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(n:m)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(b(:m)) +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) + +!CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[LB_C10_IDX]] : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLB]]#1, %{{.*}} : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b(:m)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(b) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index + +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS0]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[C0]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true} + +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box>) -> !fir.ref> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +end subroutine + +subroutine acc_enter_data_allocatable() + real, allocatable :: a(:) + integer, allocatable :: i + +!CHECK-LABEL: func.func @_QPacc_enter_data_allocatable() { +!CHECK: %[[A:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QFacc_enter_data_allocatableEa"} +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[I:.*]] = fir.alloca !fir.box> {bindc_name = "i", uniq_name = "_QFacc_enter_data_allocatableEi"} +!CHECK: %[[DECLI:.*]]:2 = hlfir.declare %[[I]] + + !$acc enter data create(a) + +!CHECK: %[[BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +!CHECK: %[[C0_0:.*]] = arith.constant 0 : index +!CHECK: %[[BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0_1:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %c0{{.*}} : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS1]]#1, %c1{{.*}} : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create(a(:)) + +!CHECK: %[[BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index +!CHECK: %[[ONE:.*]] = arith.constant 1 : index + +!CHECK: %[[BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) + +!CHECK: %[[BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS2]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB:.*]] : index) extent(%[[DIMS2]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create(a(2:5)) + +!CHECK: %[[BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> + +!CHECK: %[[BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C2:.*]] = arith.constant 2 : index +!CHECK: %[[LB:.*]] = arith.subi %[[C2]], %[[DIMS0]]#0 : index +!CHECK: %[[C5:.*]] = arith.constant 5 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C5]], %[[DIMS0]]#0 : index +!CHECK: %[[BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS2]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(2:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create(a(3:)) + +!CHECK: %[[BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +!CHECK: %[[ONE:.*]] = arith.constant 1 : index + +!CHECK: %[[BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C3:.*]] = arith.constant 3 : index +!CHECK: %[[LB:.*]] = arith.subi %[[C3]], %[[DIMS0]]#0 : index + +!CHECK: %[[BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS2]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS2]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(3:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create(a(:7)) + +!CHECK: %[[BOX_A_0:.*]] = fir.load %[[DECLA]]#0 : !fir.ref>>> +!CHECK: %[[ZERO:.*]] = arith.constant 0 : index + +!CHECK: %[[BOX_A_1:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[C7:.*]] = arith.constant 7 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C7]], %[[DIMS0]]#0 : index +!CHECK: %[[BOX_A_2:.*]] = fir.load %[[DECLA]]#1 : !fir.ref>>> +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS2]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:7)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create(i) + +!CHECK: %[[BOX_I:.*]] = fir.load %[[DECLI]]#0 : !fir.ref>> +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_I]] : (!fir.box>) -> !fir.heap +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap) -> !fir.heap {name = "i", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap) + +end subroutine + +subroutine acc_enter_data_derived_type() + type :: dt + real :: data + real :: array(1:10) + end type + + type :: t + type(dt) :: d + end type + + type :: z + integer, allocatable :: data(:) + end type + + type :: tt + type(dt) :: d(10) + end type + + type(dt) :: a + type(t) :: b + type(dt) :: aa(10) + type(z) :: c + type(tt) :: d + +!CHECK-LABEL: func.func @_QPacc_enter_data_derived_type() { +!CHECK: %[[A:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> {bindc_name = "a", uniq_name = "_QFacc_enter_data_derived_typeEa"} +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[AA:.*]] = fir.alloca !fir.array<10x!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>> {bindc_name = "aa", uniq_name = "_QFacc_enter_data_derived_typeEaa"} +!CHECK: %[[DECLAA:.*]]:2 = hlfir.declare %[[AA]] +!CHECK: %[[B:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTt{d:!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>}> {bindc_name = "b", uniq_name = "_QFacc_enter_data_derived_typeEb"} +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +!CHECK: %[[C:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTz{data:!fir.box>>}> {bindc_name = "c", uniq_name = "_QFacc_enter_data_derived_typeEc"} +!CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +!CHECK: %[[D:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTtt{d:!fir.array<10x!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>>}> {bindc_name = "d", uniq_name = "_QFacc_enter_data_derived_typeEd"} +!CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] + + !$acc enter data create(a%data) + + +!CHECK: %[[DATA_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"data"} : (!fir.ref}>>) -> !fir.ref +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DATA_COORD]] : !fir.ref) -> !fir.ref {name = "a%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref) + + !$acc enter data create(b%d%data) + + + +!CHECK: %[[D_COORD:.*]] = hlfir.designate %[[DECLB]]#0{"d"} : (!fir.ref}>}>>) -> !fir.ref}>> +!CHECK: %[[DATA_COORD:.*]] = hlfir.designate %[[D_COORD]]{"data"} : (!fir.ref}>>) -> !fir.ref +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DATA_COORD]] : !fir.ref) -> !fir.ref {name = "b%d%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref) + + !$acc enter data create(a%array) + + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[C1]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(:)) + + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[C1]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(1:5)) + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[C4:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[C0]] : index) upperbound(%[[C4]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(:5)) + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[C4:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[C4]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(2:)) + + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[DECLA]]#0{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 1 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[ONE]] : index) startIdx(%[[ONE]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(2:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +!$acc enter data create(b%d%array) + + + +!CHECK: %[[D_COORD:.*]] = hlfir.designate %[[DECLB]]#0{"d"} : (!fir.ref}>}>>) -> !fir.ref}>> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[D_COORD]]{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[C1]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b%d%array", structured = false} + + !$acc enter data create(c%data) + + +!CHECK: %[[DATA_COORD:.*]] = hlfir.designate %[[DECLC]]#0{"data"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>) -> !fir.ref>>> +!CHECK: %[[DATA_BOX:.*]] = fir.load %[[DATA_COORD]] : !fir.ref>>> +!CHECK: %[[DIM0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DATA_BOX]], %[[DIM0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[DIM0_1:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0_1:.*]]:3 = fir.box_dims %[[DATA_BOX]], %[[DIM0_1]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[UB:.*]] = arith.subi %[[DIMS0_1]]#1, %[[ONE]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%[[UB]] : index) extent(%[[DIMS0_1]]#1 : index) stride(%[[DIMS0_1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DATA_BOX]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "c%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create (d%d(1)%array) + + + + + + +!CHECK: %[[ONE:.*]] = arith.constant 1 : index +!CHECK: %[[D1_COORD:.*]] = hlfir.designate %[[DECLD]]#0{"d"} <%{{.*}}> (%[[ONE]]) : (!fir.ref}>>}>>, !fir.shape<1>, index) -> !fir.ref}>> + + +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[ARRAY_COORD:.*]] = hlfir.designate %[[D1_COORD]]{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 0 : index +!CHECK: %[[UB:.*]] = arith.subi %[[C10]], %[[C1]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "d%d(1_8)%array", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +end subroutine + +subroutine acc_enter_data_single_array_element() + type t1 + real, allocatable :: a(:, :) + end type t1 + type(t1), allocatable :: e(:) + allocate(e(10)%a(5,5)) + + !$acc enter data create(e(2)%a(1,2)) + +!CHECK-LABEL: func.func @_QPacc_enter_data_single_array_element() { +!CHECK-DAG: %[[VAL_38:.*]]:3 = fir.box_dims %[[BOX:.*]], %[[VAL_37:.*]] : (!fir.box>>, index) -> (index, index, index) +!CHECK-DAG: %[[VAL_37]] = arith.constant 0 : index +!CHECK-DAG: %[[VAL_40:.*]]:3 = fir.box_dims %[[BOX]], %[[VAL_39:.*]] : (!fir.box>>, index) -> (index, index, index) +!CHECK-DAG: %[[VAL_39]] = arith.constant 1 : index +!CHECK-DAG: %[[VAL_41:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[VAL_42:.*]] = arith.constant 1 : index +!CHECK: %[[VAL_43:.*]] = arith.constant 1 : index +!CHECK: %[[VAL_44:.*]] = arith.subi %[[VAL_43]], %[[VAL_38]]#0 : index +!CHECK: %[[VAL_45:.*]] = acc.bounds lowerbound(%[[VAL_44]] : index) upperbound(%[[VAL_44]] : index) extent(%[[VAL_38]]#1 : index) stride(%[[VAL_42]] : index) startIdx(%[[VAL_38]]#0 : index) +!CHECK: %[[VAL_46:.*]] = arith.constant 2 : index +!CHECK: %[[VAL_47:.*]] = arith.subi %[[VAL_46]], %[[VAL_40]]#0 : index +!CHECK: %[[VAL_48:.*]] = acc.bounds lowerbound(%[[VAL_47]] : index) upperbound(%[[VAL_47]] : index) extent(%[[VAL_40]]#1 : index) stride(%[[VAL_42]] : index) startIdx(%[[VAL_40]]#0 : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[VAL_41]] : !fir.heap>) bounds(%[[VAL_45]], %[[VAL_48]]) -> !fir.heap> {name = "e(2_8)%a(1,2)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-exit-data.f90 b/flang/test/Lower/OpenACC/acc-exit-data.f90 new file mode 100644 index 00000000000000..017f1f38f83974 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-exit-data.f90 @@ -0,0 +1,107 @@ +! This test checks lowering of OpenACC exit data directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_exit_data + integer :: async = 1 + real, dimension(10, 10) :: a, b, c + real, pointer :: d + logical :: ifCondition = .TRUE. + +!CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +!CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +!CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +!CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +!CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +!CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +!CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +!CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] + + !$acc exit data delete(a) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) if(.true.) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[IF1:.*]] = arith.constant true +!CHECK: acc.exit_data if(%[[IF1]]) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) if(ifCondition) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[IFCOND:.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: %[[IF2:.*]] = fir.convert %[[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.exit_data if(%[[IF2]]) dataOperands(%[[DEVPTR]] : !fir.ref>){{$}} +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) delete(b) delete(c) +!CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b", structured = false} +!CHECK: %[[DEVPTR_C:.*]] = acc.getdeviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR_A]], %[[DEVPTR_B]], %[[DEVPTR_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} +!CHECK: acc.delete accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} +!CHECK: acc.delete accPtr(%[[DEVPTR_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "b", structured = false} +!CHECK: acc.delete accPtr(%[[DEVPTR_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "c", structured = false} + + !$acc exit data copyout(a) delete(b) detach(d) +!CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b", structured = false} +!CHECK: %[[BOX_D:.*]] = fir.load %[[DECLD]]#0 : !fir.ref>> +!CHECK: %[[D_ADDR:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[DEVPTR_D:.*]] = acc.getdeviceptr varPtr(%[[D_ADDR]] : !fir.ptr) -> !fir.ptr {dataClause = #acc, name = "d", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR_A]], %[[DEVPTR_B]], %[[DEVPTR_D]] : !fir.ref>, !fir.ref>, !fir.ptr) +!CHECK: acc.copyout accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} +!CHECK: acc.delete accPtr(%[[DEVPTR_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "b", structured = false} +!CHECK: acc.detach accPtr(%[[DEVPTR_D]] : !fir.ptr) {name = "d", structured = false} + + !$acc exit data delete(a) async +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {asyncOnly = [#acc.device_type], dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref>) attributes {async} +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {asyncOnly = [#acc.device_type], name = "a", structured = false} + + !$acc exit data delete(a) wait +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref>) attributes {wait} +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) async wait +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {asyncOnly = [#acc.device_type], dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data dataOperands(%[[DEVPTR]] : !fir.ref>) attributes {async, wait} +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {asyncOnly = [#acc.device_type], name = "a", structured = false} + + !$acc exit data delete(a) async(1) +!CHECK: %[[ASYNC1:.*]] = arith.constant 1 : i32 +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC1]] : i32) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data async(%[[ASYNC1]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC1]] : i32) {name = "a", structured = false} + + + !$acc exit data delete(a) async(async) +!CHECK: %[[ASYNC2:.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC2]] : i32) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: acc.exit_data async(%[[ASYNC2]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async(%[[ASYNC2]] : i32) {name = "a", structured = false} + + !$acc exit data delete(a) wait(1) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[WAIT1:.*]] = arith.constant 1 : i32 +!CHECK: acc.exit_data wait(%[[WAIT1]] : i32) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) wait(queues: 1, 2) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[WAIT2:.*]] = arith.constant 1 : i32 +!CHECK: %[[WAIT3:.*]] = arith.constant 2 : i32 +!CHECK: acc.exit_data wait(%[[WAIT2]], %[[WAIT3]] : i32, i32) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + + !$acc exit data delete(a) wait(devnum: 1: queues: 1, 2) +!CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +!CHECK: %[[WAIT4:.*]] = arith.constant 1 : i32 +!CHECK: %[[WAIT5:.*]] = arith.constant 2 : i32 +!CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32 +!CHECK: acc.exit_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[DEVPTR]] : !fir.ref>) +!CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {name = "a", structured = false} + +end subroutine acc_exit_data diff --git a/flang/test/Lower/OpenACC/acc-fixed-form.f b/flang/test/Lower/OpenACC/acc-fixed-form.f new file mode 100644 index 00000000000000..14391ebce59582 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-fixed-form.f @@ -0,0 +1,35 @@ +! RUN: bbc -ffixed-form -fopenacc -emit-hlfir %s -o - | FileCheck %s + + subroutine sub1() + real :: a(10, 10) + integer :: i, j + + a = 0.0 + +c$acc parallel + do j = 1, 10 + do i = 1, 10 + a(i,j) = i*j + end do + end do +c$acc end parallel + +*$acc parallel + do j = 1, 10 + do i = 1, 10 + a(i,j) = i*j + end do + end do +*$acc end parallel + +!$acc parallel + do j = 1, 10 + do i = 1, 10 + a(i,j) = i*j + end do + end do +!$acc end parallel + + end subroutine + +! CHECK-COUNT-3: acc.parallel diff --git a/flang/test/Lower/OpenACC/acc-host-data.f90 b/flang/test/Lower/OpenACC/acc-host-data.f90 new file mode 100644 index 00000000000000..bcce84dc7dca42 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-host-data.f90 @@ -0,0 +1,52 @@ +! This test checks lowering of OpenACC host_data directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_host_data() + real, dimension(10) :: a + logical :: ifCondition = .TRUE. + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10xf32> {bindc_name = "a", uniq_name = "_QFacc_host_dataEa"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[IFCOND:.*]] = fir.address_of(@_QFacc_host_dataEifcondition) : !fir.ref> +! CHECK: %[[DECLIFCOND:.*]]:2 = hlfir.declare %[[IFCOND]] + + !$acc host_data use_device(a) + !$acc end host_data + +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) + + !$acc host_data use_device(a) if_present + !$acc end host_data + +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) { +! CHECK: } attributes {ifPresent} + + !$acc host_data use_device(a) if(ifCondition) + !$acc end host_data + +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: %[[LOAD_IFCOND:.*]] = fir.load %[[DECLIFCOND]]#0 : !fir.ref> +! CHECK: %[[IFCOND_I1:.*]] = fir.convert %[[LOAD_IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.host_data if(%[[IFCOND_I1]]) dataOperands(%[[DA]] : !fir.ref>) + + !$acc host_data use_device(a) if(.true.) + !$acc end host_data + +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%{{.*}} : index) +! CHECK: %[[DA:.*]] = acc.use_device varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} +! CHECK: acc.host_data dataOperands(%[[DA]] : !fir.ref>) + + !$acc host_data use_device(a) if(.false.) + a = 1.0 + !$acc end host_data + +! CHECK-NOT: acc.host_data +! CHECK: hlfir.assign %{{.*}} to %[[DECLA]]#0 + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-init.f90 b/flang/test/Lower/OpenACC/acc-init.f90 new file mode 100644 index 00000000000000..2fbb9550548a9b --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-init.f90 @@ -0,0 +1,38 @@ +! This test checks lowering of OpenACC init directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_init + implicit none + logical :: ifCondition = .TRUE. + integer :: ifInt = 1 + + !$acc init +!CHECK: acc.init{{ *}}{{$}} + + !$acc init if(.true.) +!CHECK: [[IF1:%.*]] = arith.constant true +!CHECK: acc.init if([[IF1]]){{$}} + + !$acc init if(ifCondition) +!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.init if([[IF2]]){{$}} + + !$acc init device_num(1) +!CHECK: [[DEVNUM:%.*]] = arith.constant 1 : i32 +!CHECK: acc.init device_num([[DEVNUM]] : i32){{$}} + + !$acc init device_num(1) device_type(host, multicore) +!CHECK: [[DEVNUM:%.*]] = arith.constant 1 : i32 +!CHECK: acc.init device_num([[DEVNUM]] : i32) attributes {device_types = [#acc.device_type, #acc.device_type]} + + !$acc init if(ifInt) +!CHECK: %[[IFINT:.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: %[[CONV:.*]] = fir.convert %[[IFINT]] : (i32) -> i1 +!CHECK: acc.init if(%[[CONV]]) + + !$acc init device_type(nvidia) +!CHECK: acc.init attributes {device_types = [#acc.device_type]} + +end subroutine acc_init diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 new file mode 100644 index 00000000000000..e5791f0e5b3921 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -0,0 +1,707 @@ +! This test checks lowering of OpenACC kernels loop combined directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_kernels_loop + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + integer, parameter :: n = 10 + real, dimension(n) :: a, b, c + real, dimension(n, n) :: d, e + real, pointer :: f, g + integer :: reduction_i + real :: reduction_r + + integer :: gangNum = 8 + integer :: gangStatic = 8 + integer :: vectorNum = 128 + integer, parameter :: tileSize = 2 + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[F:.*]] = fir.alloca !fir.box> {bindc_name = "f", uniq_name = "{{.*}}Ef"} +! CHECK: %[[DECLF:.*]]:2 = hlfir.declare %[[F]] +! CHECK: %[[G:.*]] = fir.alloca !fir.box> {bindc_name = "g", uniq_name = "{{.*}}Eg"} +! CHECK: %[[DECLG:.*]]:2 = hlfir.declare %[[G]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc kernels + !$acc loop + DO i = 1, n + a(i) = b(i) + END DO + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels combined(loop) { +! CHECK: acc.loop combined(kernels) private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop async + DO i = 1, n + a(i) = b(i) + END DO + !$acc end kernels loop + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc kernels loop async(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels {{.*}} async([[ASYNC1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop async(async) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels {{.*}} async([[ASYNC2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop wait + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} wait { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: } + + !$acc kernels loop wait(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels {{.*}} wait({[[WAIT1]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop wait(1, 2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.kernels {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop wait(wait1, wait2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop num_gangs(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels {{.*}} num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop num_gangs(numGangs) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels {{.*}} num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop num_workers(10) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 +! CHECK: acc.kernels {{.*}} num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop num_workers(numWorkers) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels {{.*}} num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop vector_length(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 +! CHECK: acc.kernels {{.*}} vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop vector_length(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels {{.*}} vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop if(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.kernels {{.*}} if([[IF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop if(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.kernels {{.*}} if([[IF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop self(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.kernels {{.*}} self([[SELF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop self + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}}{ +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: } attributes {selfAttr} + + !$acc kernels loop self(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.kernels {{.*}} self(%[[SELF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop copy(a, b) + DO i = 1, n + a(i) = b(i) + END DO + + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc kernels loop copy(a) copy(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc kernels loop copyin(a) copyin(readonly: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop copyout(a) copyout(zero: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} + + !$acc kernels loop create(b) create(zero: a) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "a"} + + !$acc kernels loop no_create(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop present(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop deviceptr(a) deviceptr(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop attach(f, g) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[BOX_F:.*]] = fir.load %[[DECLF]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_F:.*]] = fir.box_addr %[[BOX_F]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_F:.*]] = acc.attach varPtr(%[[BOX_ADDR_F]] : !fir.ptr) -> !fir.ptr {name = "f"} +! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr) -> !fir.ptr {name = "g"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop seq + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, seq = [#acc.device_type]} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop auto + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop independent + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop gang + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} gang {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop gang(num: 8) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop gang(num: gangNum) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop gang(num: gangNum, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop vector + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} vector {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop vector(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop vector(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop worker + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop worker(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop collapse(2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop + DO i = 1, n + !$acc loop + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop tile(2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop tile(*) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop tile(2, 2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 +! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop tile(tileSize) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop tile(tileSize, tileSize) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_i"} +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref, !fir.ref) { +! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_i"} + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-kernels.f90 b/flang/test/Lower/OpenACC/acc-kernels.f90 new file mode 100644 index 00000000000000..ff4f1d3b545911 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-kernels.f90 @@ -0,0 +1,298 @@ +! This test checks lowering of OpenACC kernels construct. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_kernels + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + real, dimension(10, 10) :: a, b, c + real, pointer :: d, e + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] +! CHECK: %[[E:.*]] = fir.alloca !fir.box> {bindc_name = "e", uniq_name = "{{.*}}Ee"} +! CHECK: %[[DECLE:.*]]:2 = hlfir.declare %[[E]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc kernels + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels async + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.terminator +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc kernels async(1) + !$acc end kernels + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels async([[ASYNC1]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels async(async) + !$acc end kernels + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels async([[ASYNC2]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels wait + !$acc end kernels + +! CHECK: acc.kernels wait { +! CHECK: acc.terminator +! CHECK-NEXT: } + + !$acc kernels wait(1) + !$acc end kernels + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels wait({[[WAIT1]] : i32}) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels wait(1, 2) + !$acc end kernels + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.kernels wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels wait(wait1, wait2) + !$acc end kernels + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels num_gangs(1) + !$acc end kernels + +! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.kernels num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels num_gangs(numGangs) + !$acc end kernels + +! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels num_workers(10) + !$acc end kernels + +! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 +! CHECK: acc.kernels num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels num_workers(numWorkers) + !$acc end kernels + +! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels vector_length(128) + !$acc end kernels + +! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 +! CHECK: acc.kernels vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels vector_length(vectorLength) + !$acc end kernels + +! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.kernels vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels if(.TRUE.) + !$acc end kernels + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.kernels if([[IF1]]) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels if(ifCondition) + !$acc end kernels + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.kernels if([[IF2]]) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels self(.TRUE.) + !$acc end kernels + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.kernels self([[SELF1]]) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels self + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.terminator +! CHECK-NEXT: } attributes {selfAttr} + + !$acc kernels self(ifCondition) + !$acc end kernels + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.kernels self(%[[SELF2]]) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels copy(a, b, c) + !$acc end kernels + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc kernels copy(a) copy(b) copy(c) + !$acc end kernels + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc kernels copyin(a) copyin(readonly: b, c) + !$acc end kernels + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels copyout(a) copyout(zero: b) copyout(c) + !$acc end kernels + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {name = "c"} + + !$acc kernels create(a, b) create(zero: c) + !$acc end kernels + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + !$acc kernels no_create(a, b) create(zero: c) + !$acc end kernels + +! CHECK: %[[NO_CREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NO_CREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.kernels dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels present(a, b, c) + !$acc end kernels + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[PRESENT_C:.*]] = acc.present varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.kernels dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels deviceptr(a) deviceptr(c) + !$acc end kernels + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_C:.*]] = acc.deviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.kernels dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels attach(d, e) + !$acc end kernels + +! CHECK: %[[BOX_D:.*]] = fir.load %[[DECLD]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[BOX_ADDR_D]] : !fir.ptr) -> !fir.ptr {name = "d"} +! CHECK: %[[BOX_E:.*]] = fir.load %[[DECLE]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_E:.*]] = fir.box_addr %[[BOX_E]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_E:.*]] = acc.attach varPtr(%[[BOX_ADDR_E]] : !fir.ptr) -> !fir.ptr {name = "e"} +! CHECK: acc.kernels dataOperands(%[[ATTACH_D]], %[[ATTACH_E]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + +!$acc kernels default(none) +!$acc end kernels + +! CHECK: acc.kernels { +! CHECK: } attributes {defaultAttr = #acc} + +!$acc kernels default(present) +!$acc end kernels + +! CHECK: acc.kernels { +! CHECK: } attributes {defaultAttr = #acc} + +end subroutine acc_kernels diff --git a/flang/test/Lower/OpenACC/acc-loop-and-cpu-dir.f90 b/flang/test/Lower/OpenACC/acc-loop-and-cpu-dir.f90 new file mode 100644 index 00000000000000..51c6c367d653e0 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-loop-and-cpu-dir.f90 @@ -0,0 +1,75 @@ +! Test that $dir loop directives (known or unknown) are not clashing +! with $acc lowering. + +! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine test_before_acc_loop(a, b, c) + real, dimension(10) :: a,b,c + !dir$ myloop_directive_1 + !dir$ myloop_directive_2 + !$acc loop + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_before_acc_loop +! CHECK: acc.loop + +subroutine test_after_acc_loop(a, b, c) + real, dimension(10) :: a,b,c + !$acc loop + !dir$ myloop_directive_1 + !dir$ myloop_directive_2 + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_after_acc_loop +! CHECK: acc.loop + +subroutine test_before_acc_combined(a, b, c) + real, dimension(10) :: a,b,c + !dir$ myloop_directive_1 + !dir$ myloop_directive_2 + !$acc parallel loop + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_before_acc_combined +! CHECK: acc.parallel combined(loop) + +subroutine test_after_acc_combined(a, b, c) + real, dimension(10) :: a,b,c + !$acc parallel loop + !dir$ myloop_directive_1 + !dir$ myloop_directive_2 + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_after_acc_combined +! CHECK: acc.parallel combined(loop) + + +subroutine test_vector_always_after_acc(a, b, c) + real, dimension(10) :: a,b,c + !$acc loop + !dir$ vector always + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_vector_always_after_acc +! CHECK: acc.loop + +subroutine test_vector_always_before_acc(a, b, c) + real, dimension(10) :: a,b,c + !dir$ vector always + !$acc loop + do i=1,N + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_vector_always_before_acc +! CHECK: acc.loop diff --git a/flang/test/Lower/OpenACC/acc-loop-exit.f90 b/flang/test/Lower/OpenACC/acc-loop-exit.f90 new file mode 100644 index 00000000000000..85394e4a5b74c7 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-loop-exit.f90 @@ -0,0 +1,41 @@ +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine sub1(x, a) + real :: x(200) + integer :: a + + !$acc loop + do i = 100, 200 + x(i) = 1.0 + if (i == a) return + end do + + i = 2 +end + +! CHECK-LABEL: func.func @_QPsub1 +! CHECK: %[[A:.*]]:2 = hlfir.declare %arg1 dummy_scope %{{[0-9]+}} {uniq_name = "_QFsub1Ea"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[I:.*]]:2 = hlfir.declare %{{[0-9]+}} {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[EXIT_COND:.*]] = acc.loop +! CHECK: ^bb{{.*}}: +! CHECK: ^bb{{.*}}: +! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref +! CHECK: %[[LOAD_I:.*]] = fir.load %[[I]]#0 : !fir.ref +! CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[LOAD_I]], %[[LOAD_A]] : i32 +! CHECK: cf.cond_br %[[CMP]], ^[[EARLY_RET:.*]], ^[[NO_RET:.*]] +! CHECK: ^[[EARLY_RET]]: +! CHECK: acc.yield %true : i1 +! CHECK: ^[[NO_RET]]: +! CHECK: cf.br ^bb{{.*}} +! CHECK: ^bb{{.*}}: +! CHECK: acc.yield %false : i1 +! CHECK: }(i1) +! CHECK: cf.cond_br %[[EXIT_COND]], ^[[EXIT_BLOCK:.*]], ^[[CONTINUE_BLOCK:.*]] +! CHECK: ^[[CONTINUE_BLOCK]]: +! CHECK: hlfir.assign +! CHECK: cf.br ^[[EXIT_BLOCK]] +! CHECK: ^[[EXIT_BLOCK]]: +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 new file mode 100644 index 00000000000000..0d2594c86a6eba --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -0,0 +1,328 @@ +! This test checks lowering of OpenACC loop directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.private.recipe @privatization_ref_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: acc.yield %{{.*}} : !fir.ref> +! CHECK: } + +program acc_loop + + integer :: i, j + integer, parameter :: n = 10 + real, dimension(n) :: a, b + real, dimension(n, n) :: c, d + integer :: gangNum = 8 + integer :: gangDim = 1 + integer :: gangStatic = 8 + integer :: vectorLength = 128 + integer, parameter :: tileSize = 2 + integer :: reduction_i + real :: reduction_r + + + !$acc loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} + + !$acc loop seq + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, seq = [#acc.device_type]} + + !$acc loop auto + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} + + !$acc loop independent + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} + + !$acc loop gang + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop gang private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop gang(num: 8) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 +! CHECK-NEXT: acc.loop gang({num=[[GANGNUM1]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop gang(num: gangNum) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.loop gang({num=[[GANGNUM2]] : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop gang(num: gangNum, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop vector + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop vector private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop vector(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop vector([[CONSTANT128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc loop vector(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + +!$acc loop worker + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop worker private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop worker(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop worker([[WORKER128]] : i32) private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop private(c) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop private(c, d) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop private(c) private(d) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>, @privatization_ref_10x10xf32 -> %{{.*}} : !fir.ref>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop tile(2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop tile(*) + DO i = 1, n + a(i) = b(i) + END DO +! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop tile(2, 2) + DO i = 1, n + DO j = 1, n + c(i, j) = d(i, j) + END DO + END DO + +! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 +! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop tile(tileSize) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop tile(tileSize, tileSize) + DO i = 1, n + DO j = 1, n + c(i, j) = d(i, j) + END DO + END DO + +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop collapse(2) + DO i = 1, n + DO j = 1, n + c(i, j) = d(i, j) + END DO + END DO + +! CHECK: acc.loop {{.*}} control(%arg0 : i32, %arg1 : i32) = (%{{.*}} : i32, i32) to (%{{.*}} : i32, i32) step (%{{.*}} : i32, i32) { +! CHECK: fir.store %arg0 to %{{.*}} : !fir.ref +! CHECK: fir.store %arg1 to %{{.*}} : !fir.ref +! CHECK: acc.yield +! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} + + !$acc loop + DO i = 1, n + !$acc loop + DO j = 1, n + c(i, j) = d(i, j) + END DO + END DO + +! CHECK: acc.loop {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.loop {{.*}} control(%arg1 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: acc.loop private(@privatization_ref_i32 -> %{{.*}} : !fir.ref) reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop gang(dim: gangDim, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop gang({dim=%{{.*}}, static=%{{.*}} : i32}) {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop gang(dim: 1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.loop gang({dim={{.*}} : i32}) {{.*}} control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array} + + !$acc loop + DO i = 1, n + !$acc cache(b) + a(i) = b(i) + END DO + +! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} cache(%[[CACHE]] : !fir.ref>) + + !$acc loop + do 100 i=0, n + 100 continue +! CHECK: acc.loop + + !$acc loop gang device_type(nvidia) gang(8) + DO i = 1, n + END DO + +! CHECK: acc.loop gang([#acc.device_type], {num=%c8{{.*}} : i32} [#acc.device_type]) + + !$acc loop device_type(nvidia, default) gang + DO i = 1, n + END DO + +! CHECK: acc.loop gang([#acc.device_type, #acc.device_type]) + +end program + +subroutine sub1(i, j, k) + integer :: i,j,k + integer :: a(i,j,k) + !$acc parallel loop + do concurrent (i=1:10,j=1:100,k=1:200) + a(i,j,k) = a(i,j,k) + 1 + end do +end subroutine + +! CHECK: func.func @_QPsub1 +! CHECK: acc.parallel +! CHECK: %[[DC_K:.*]] = fir.alloca i32 {bindc_name = "k"} +! CHECK: %[[DC_J:.*]] = fir.alloca i32 {bindc_name = "j"} +! CHECK: %[[DC_I:.*]] = fir.alloca i32 {bindc_name = "i"} +! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref, @privatization_ref_i32 -> %[[P_J]] : !fir.ref, @privatization_ref_i32 -> %[[P_K]] : !fir.ref) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) +! CHECK: } attributes {inclusiveUpperbound = array} diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 new file mode 100644 index 00000000000000..48ceda0710e8db --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -0,0 +1,733 @@ +! This test checks lowering of OpenACC parallel loop combined directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPacc_parallel_loop() + +subroutine acc_parallel_loop + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + integer, parameter :: n = 10 + real, dimension(n) :: a, b, c + real, dimension(n, n) :: d, e + real, pointer :: f, g + integer :: reduction_i + real :: reduction_r + + integer :: gangNum = 8 + integer :: gangStatic = 8 + integer :: vectorNum = 128 + integer, parameter :: tileSize = 2 + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[F:.*]] = fir.alloca !fir.box> {bindc_name = "f", uniq_name = "{{.*}}Ef"} +! CHECK: %[[DECLF:.*]]:2 = hlfir.declare %[[F]] +! CHECK: %[[G:.*]] = fir.alloca !fir.box> {bindc_name = "g", uniq_name = "{{.*}}Eg"} +! CHECK: %[[DECLG:.*]]:2 = hlfir.declare %[[G]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc parallel + !$acc loop + DO i = 1, n + a(i) = b(i) + END DO + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel combined(loop) { +! CHECK: acc.loop combined(parallel) private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop async + DO i = 1, n + a(i) = b(i) + END DO + !$acc end parallel loop + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc parallel loop async(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel {{.*}} async([[ASYNC1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop async(async) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel {{.*}} async([[ASYNC2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop wait + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} wait { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } + + !$acc parallel loop wait(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel {{.*}} wait({[[WAIT1]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop wait(1, 2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.parallel {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop wait(wait1, wait2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop num_gangs(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel {{.*}} num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop num_gangs(numGangs) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel {{.*}} num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop num_workers(10) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 +! CHECK: acc.parallel {{.*}} num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop num_workers(numWorkers) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel {{.*}} num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop vector_length(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 +! CHECK: acc.parallel {{.*}} vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop vector_length(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel {{.*}} vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop if(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.parallel {{.*}} if([[IF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop if(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.parallel {{.*}} if([[IF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop self(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.parallel {{.*}} self([[SELF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop self + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } attributes {selfAttr} + + !$acc parallel loop self(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.parallel {{.*}} self(%[[SELF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop copy(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc parallel loop copy(a) copy(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc parallel loop copyin(a) copyin(readonly: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop copyout(a) copyout(zero: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} + + !$acc parallel loop create(b) create(zero: a) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "a"} + + !$acc parallel loop no_create(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop present(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop deviceptr(a) deviceptr(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop attach(f, g) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[BOX_F:.*]] = fir.load %[[DECLF]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_F:.*]] = fir.box_addr %[[BOX_F]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_F:.*]] = acc.attach varPtr(%[[BOX_ADDR_F]] : !fir.ptr) -> !fir.ptr {name = "f"} +! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr) -> !fir.ptr {name = "g"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop private(a) firstprivate(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref>) +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop seq + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, seq = [#acc.device_type]} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop auto + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop independent + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop gang + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} gang +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop gang(num: 8) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop gang(num: gangNum) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop gang(num: gangNum, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop vector + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} vector +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop vector(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop vector(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop worker + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop worker(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}}{ +! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop collapse(2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop + DO i = 1, n + !$acc loop + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop tile(2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop tile(*) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop tile(2, 2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 +! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop tile(tileSize) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop tile(tileSize, tileSize) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_i"} +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref, !fir.ref) { +! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) {{.*}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_i"} + + + !$acc parallel loop + do 10 i=0, n + 10 continue +! CHECK: acc.parallel +! CHECK: acc.loop +! CHECK-NOT: fir.do_loop + +end subroutine acc_parallel_loop diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 new file mode 100644 index 00000000000000..5197e2b0bee091 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -0,0 +1,356 @@ +! This test checks lowering of OpenACC parallel directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10xext10_ref_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } copy { +! CHECK: ^bb0(%arg0: !fir.ref>, %arg1: !fir.ref>): +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_parallel() + +subroutine acc_parallel + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + real, dimension(10, 10) :: a, b, c + real, pointer :: d, e + integer :: reduction_i + real :: reduction_r + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] +! CHECK: %[[E:.*]] = fir.alloca !fir.box> {bindc_name = "e", uniq_name = "{{.*}}Ee"} +! CHECK: %[[DECLE:.*]]:2 = hlfir.declare %[[E]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc parallel + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel async + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc parallel async(1) + !$acc end parallel + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel async([[ASYNC1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel async(async) + !$acc end parallel + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.parallel async([[ASYNC2]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel wait + !$acc end parallel + +! CHECK: acc.parallel wait { +! CHECK: acc.yield +! CHECK-NEXT: } + + !$acc parallel wait(1) + !$acc end parallel + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel wait({[[WAIT1]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel wait(1, 2) + !$acc end parallel + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.parallel wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel wait(wait1, wait2) + !$acc end parallel + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel num_gangs(1) + !$acc end parallel + +! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.parallel num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel num_gangs(numGangs) + !$acc end parallel + +! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel num_gangs(1, 1, 1) + !$acc end parallel + +! CHECK: acc.parallel num_gangs({%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel num_workers(10) + !$acc end parallel + +! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 +! CHECK: acc.parallel num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel num_workers(numWorkers) + !$acc end parallel + +! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel vector_length(128) + !$acc end parallel + +! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 +! CHECK: acc.parallel vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel vector_length(vectorLength) + !$acc end parallel + +! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.parallel vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel if(.TRUE.) + !$acc end parallel + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.parallel if([[IF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel if(ifCondition) + !$acc end parallel + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.parallel if([[IF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel self(.TRUE.) + !$acc end parallel + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.parallel self([[SELF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel self + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {selfAttr} + + !$acc parallel self(ifCondition) + !$acc end parallel + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.parallel self(%[[SELF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel copy(a, b, c) + !$acc end parallel + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc parallel copy(a) copy(b) copy(c) + !$acc end parallel + + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc parallel copyin(a) copyin(readonly: b, c) + !$acc end parallel + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel copyout(a) copyout(zero: b) copyout(c) + !$acc end parallel + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {name = "c"} + + !$acc parallel create(a, b) create(zero: c) + !$acc end parallel + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + !$acc parallel create(c) copy(b) create(a) + !$acc end parallel +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: %[[COPY_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel dataOperands(%[[CREATE_C]], %[[COPY_B]], %[[CREATE_A]] : !fir.ref>, !fir.ref>, !fir.ref>) { + + !$acc parallel no_create(a, b) create(zero: c) + !$acc end parallel + +! CHECK: %[[NO_CREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NO_CREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.parallel dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + + !$acc parallel present(a, b, c) + !$acc end parallel + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[PRESENT_C:.*]] = acc.present varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.parallel dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel deviceptr(a) deviceptr(c) + !$acc end parallel + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_C:.*]] = acc.deviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.parallel dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel attach(d, e) + !$acc end parallel + +! CHECK: %[[BOX_D:.*]] = fir.load %[[DECLD]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[BOX_ADDR_D]] : !fir.ptr) -> !fir.ptr {name = "d"} +! CHECK: %[[BOX_E:.*]] = fir.load %[[DECLE]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_E:.*]] = fir.box_addr %[[BOX_E]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_E:.*]] = acc.attach varPtr(%[[BOX_ADDR_E]] : !fir.ptr) -> !fir.ptr {name = "e"} +! CHECK: acc.parallel dataOperands(%[[ATTACH_D]], %[[ATTACH_E]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.detach accPtr(%[[ATTACH_D]] : !fir.ptr) {dataClause = #acc, name = "d"} +! CHECK: acc.detach accPtr(%[[ATTACH_E]] : !fir.ptr) {dataClause = #acc, name = "e"} + +!$acc parallel private(a) firstprivate(b) private(c) async(1) +!$acc end parallel + +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC3:%.*]]) -> !fir.ref> {name = "a"} +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC3]]) -> !fir.ref> {name = "b"} +! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC3]]) -> !fir.ref> {name = "c"} +! CHECK: acc.parallel async([[ASYNC3]]) firstprivate(@firstprivatization_section_ext10xext10_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + +!$acc parallel reduction(+:reduction_r) reduction(*:reduction_i) +!$acc end parallel + +! CHECK: acc.parallel reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + +!$acc parallel default(none) +!$acc end parallel + +! CHECK: acc.parallel { +! CHECK: } attributes {defaultAttr = #acc} + +!$acc parallel default(present) +!$acc end parallel + +! CHECK: acc.parallel { +! CHECK: } attributes {defaultAttr = #acc} + +end subroutine acc_parallel diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 new file mode 100644 index 00000000000000..a299a7486c3ba2 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -0,0 +1,403 @@ +! This test checks lowering of OpenACC loop directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.private.recipe @privatization_ref_10xf32 : !fir.ref> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>): +! CHECK: %[[C10:.*]] = arith.constant 10 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C10]] : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_box_UxUx2xi32 : !fir.box> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[DIM0:.*]]:3 = fir.box_dims %arg0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[DIM1:.*]]:3 = fir.box_dims %arg0, %c1{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[DIM0]]#1, %[[DIM1]]#1, %c2{{.*}} : (index, index, index) -> !fir.shape<3> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[DIM0]]#1, %[[DIM1]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<3>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } copy { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>, %[[ARG1:.*]]: !fir.box>, %[[LB0:.*]]: index, %[[UB0:.*]]: index, %[[STEP0:.*]]: index, %[[LB1:.*]]: index, %[[UB1:.*]]: index, %[[STEP1:.*]]: index, %[[LB2:.*]]: index, %[[UB2:.*]]: index, %[[STEP2:.*]]: index): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> +! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[ARG0]] (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box> +! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[ARG1]] (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]], %[[LB2]]:%[[UB2]]:%[[STEP2]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box> +! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.box>, !fir.box> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb4.ub9_box_Uxi32 : !fir.box> init { +! CHECK: ^bb0(%{{.*}}: !fir.box>): +! CHECK: } copy { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>, %[[ARG1:.*]]: !fir.box>): +! CHECK: %[[LB:.*]] = arith.constant 4 : index +! CHECK: %[[UB:.*]] = arith.constant 9 : index +! CHECK: %[[STEP:.*]] = arith.constant 1 : index +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[EXT0:.*]] = arith.subi %[[UB]], %[[LB]] : index +! CHECK: %[[EXT1:.*]] = arith.addi %[[EXT0]], %[[C1]] : index +! CHECK: %[[EXT2:.*]] = arith.divsi %[[EXT1]], %[[STEP]] : index +! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[EXT2]], %[[C0]] : index +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[EXT2]], %[[C0]] : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[SELECT]] : (index) -> !fir.shape<1> +! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box>, !fir.shape<1>) -> !fir.box> +! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box>, !fir.shape<1>) -> !fir.box> +! CHECK: hlfir.assign %[[LEFT]] to %[[RIGHT]] : !fir.box>, !fir.box> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_box_Uxi32 : !fir.box> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %c0 : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } copy { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>, %[[ARG1:.*]]: !fir.box>, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index, %[[ARG4:.*]]: index): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[ARG0]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %[[SHAPE]] : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[ARG1]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %[[SHAPE]] : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: hlfir.assign %[[DES_V1]] to %[[DES_V2]] : !fir.box>, !fir.box> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_box_UxUx2xi32 : !fir.box> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[DIM0:.*]]:3 = fir.box_dims %arg0, %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[DIM1:.*]]:3 = fir.box_dims %arg0, %c1{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[DIM0]]#1, %[[DIM1]]#1, %c2{{.*}} : (index, index, index) -> !fir.shape<3> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[DIM0]]#1, %[[DIM1]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<3>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_box_ptr_Uxi32 : !fir.box>> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>>): +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %arg0, %c0 : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %0#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_box_heap_Uxi32 : !fir.box>> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>>): +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_box_Uxi32 : !fir.box> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %0#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: acc.yield %[[DECLARE:.*]]#0 : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb50.ub99_ref_50xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } copy { +! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE:.*]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE:.*]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref>, !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext100_ref_100xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } copy { +! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref>, %[[DST:.*]]: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[DECL_SRC:.*]]:2 = hlfir.declare %[[SRC]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DECL_DST:.*]]:2 = hlfir.declare %[[DST]](%[[SHAPE]]) {uniq_name = ""} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE]] : (!fir.ref>, !fir.shape<1>) -> !fir.ref> +! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref>, !fir.ref> +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_i32 : !fir.ref init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } copy { +! CHECK: ^bb0(%[[SRC:.*]]: !fir.ref, %[[DST:.*]]: !fir.ref): +! CHECK: %[[VALUE:.*]] = fir.load %[[SRC]] : !fir.ref +! CHECK: fir.store %[[VALUE]] to %[[DST]] : !fir.ref +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_50xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_100xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_i32 : !fir.ref init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.private.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } + +program acc_private + integer :: i, c + integer, parameter :: n = 100 + real, dimension(n) :: a, b + +! CHECK: %[[B:.*]] = fir.address_of(@_QFEb) : !fir.ref> +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca i32 {bindc_name = "c", uniq_name = "_QFEc"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] + + !$acc loop private(c) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C_PRIVATE:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref) -> !fir.ref {name = "c"} +! CHECK: acc.loop private({{.*}}@privatization_ref_i32 -> %[[C_PRIVATE]] : !fir.ref) +! CHECK: acc.yield + + !$acc loop private(b) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %{{.*}}, %[[C1]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b"} +! CHECK: acc.loop private({{.*}}@privatization_ref_100xf32 -> %[[B_PRIVATE]] : !fir.ref>) +! CHECK: acc.yield + + !$acc loop private(b(1:50)) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 49 : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[B_PRIVATE:.*]] = acc.private varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b(1:50)"} +! CHECK: acc.loop private({{.*}}@privatization_ref_50xf32 -> %[[B_PRIVATE]] : !fir.ref>) + + !$acc parallel loop firstprivate(c) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[FP_C:.*]] = acc.firstprivate varPtr(%[[DECLC]]#0 : !fir.ref) -> !fir.ref {name = "c"} +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_ref_i32 -> %[[FP_C]] : !fir.ref) +! CHECK: acc.yield + + !$acc parallel loop firstprivate(b) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %{{.*}}, %[[C1]] : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b"} +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_ext100_ref_100xf32 -> %[[FP_B]] : !fir.ref>) +! CHECK: acc.yield + + !$acc parallel loop firstprivate(b(51:100)) + DO i = 1, n + c = i + a(i) = b(i) + c + END DO + +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 50 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b(51:100)"} +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_lb50.ub99_ref_50xf32 -> %[[FP_B]] : !fir.ref>) + +end program + +subroutine acc_private_assumed_shape(a, n) + integer :: a(:), i, n + + !$acc parallel loop private(a) + do i = 1, n + a(i) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_assumed_shape( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"} +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: acc.parallel {{.*}} { +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[ADDR]] : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_Uxi32 -> %[[PRIVATE]] : !fir.ref>) + +subroutine acc_private_allocatable_array(a, n) + integer, allocatable :: a(:) + integer :: i, n + + !$acc parallel loop private(a) + do i = 1, n + a(i) = i + end do + + !$acc serial private(a) + a(i) = 1 + !$acc end serial +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_allocatable_array( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"} +! CHECK: %[[DECLA_A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFacc_private_allocatable_arrayEa"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: acc.parallel {{.*}} { +! CHECK: %[[BOX:.*]] = fir.load %[[DECLA_A]]#0 : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%{{.*}}) -> !fir.heap> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_heap_Uxi32 -> %[[PRIVATE]] : !fir.heap>) +! CHECK: acc.serial private(@privatization_box_heap_Uxi32 -> %{{.*}} : !fir.heap>) + +subroutine acc_private_pointer_array(a, n) + integer, pointer :: a(:) + integer :: i, n + + !$acc parallel loop private(a) + do i = 1, n + a(i) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_pointer_array( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}, %arg1: !fir.ref {fir.bindc_name = "n"}) { +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFacc_private_pointer_arrayEa"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: acc.parallel {{.*}} { +! CHECK: %[[BOX:.*]] = fir.load %[[DECLA_A]]#0 : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.ptr> +! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%{{.*}}) -> !fir.ptr> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ptr>) + +subroutine acc_private_dynamic_extent(a, n) + integer :: n, i + integer :: a(n, n, 2) + + !$acc parallel loop private(a) + do i = 1, n + a(i, i, 1) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_dynamic_extent( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}) { +! CHECK: %[[DECL_N:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEn"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_private_dynamic_extentEa"} : (!fir.ref>, !fir.shape<3>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: acc.parallel {{.*}} { +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[PRIV:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_UxUx2xi32 -> %[[PRIV]] : !fir.ref>) + +subroutine acc_firstprivate_assumed_shape(a, n) + integer :: a(:), i, n + + !$acc parallel loop firstprivate(a) + do i = 1, n + a(i) = i + end do +end subroutine + +subroutine acc_firstprivate_assumed_shape_with_section(a, n) + integer :: a(:), i, n + + !$acc parallel loop firstprivate(a(5:10)) + do i = 1, n + a(i) = i + end do +end subroutine + +subroutine acc_firstprivate_dynamic_extent(a, n) + integer :: n, i + integer :: a(n, n, 2) + + !$acc parallel loop firstprivate(a) + do i = 1, n + a(i, i, 1) = i + end do +end subroutine + +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_box_UxUx2xi32 -> %{{.*}} : !fir.ref>) + +module acc_declare_equivalent + integer, parameter :: n = 10 + real :: v1(n) + real :: v2(n) + equivalence(v1(1), v2(1)) +contains + subroutine sub1() + !$acc parallel private(v2) + !$acc end parallel + end subroutine +end module + +! CHECK: acc.parallel private(@privatization_ref_10xf32 -> %{{.*}} : !fir.ref>) + +subroutine acc_private_use() + integer :: i, j + + !$acc parallel loop + do i = 1, 10 + j = i + end do +end + +! CHECK-LABEL: func.func @_QPacc_private_use() +! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFacc_private_useEi"} +! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.parallel +! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) +! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref +! CHECK: %{{.*}} = fir.load %[[DECL_PRIV_I]]#0 : !fir.ref diff --git a/flang/test/Lower/OpenACC/acc-reduction.f90 b/flang/test/Lower/OpenACC/acc-reduction.f90 new file mode 100644 index 00000000000000..88c60a22b0fe8b --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-reduction.f90 @@ -0,0 +1,1213 @@ +! This test checks lowering of OpenACC reduction clause. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_UxUxf32 : !fir.box> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0]], %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[ARG0]], %c1 : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[DIMS0]]#1, %[[DIMS1]]#1 : (index, index) -> !fir.shape<2> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[DIMS0]]#1, %[[DIMS1]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<2>) -> (!fir.box>, !fir.heap>) +! CHECK: hlfir.assign %[[CST]] to %[[DECL]]#0 : f32, !fir.box> +! CHECK: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[V1:.*]]: !fir.box>, %[[V2:.*]]: !fir.box>, %[[LB0:.*]]: index, %[[UB0:.*]]: index, %[[STEP0:.*]]: index, %[[LB1:.*]]: index, %[[UB1:.*]]: index, %[[STEP1:.*]]: index): + +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[V1]] (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box> +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[V2]] (%[[LB0]]:%[[UB0]]:%[[STEP0]], %[[LB1]]:%[[UB1]]:%[[STEP1]]) shape %[[SHAPE]] : (!fir.box>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box> +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<2>) -> !hlfir.expr { +! CHECK: ^bb0(%[[ARG0:.*]]: index, %[[ARG1:.*]]: index): +! CHECK: %[[D1:.*]] = hlfir.designate %[[DES_V1]] (%[[ARG0]], %[[ARG1]]) : (!fir.box>, index, index) -> !fir.ref +! CHECK: %[[D2:.*]] = hlfir.designate %[[DES_V2]] (%[[ARG0]], %[[ARG1]]) : (!fir.box>, index, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[D1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[D2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 +! CHECK: hlfir.yield_element %[[SELECT]] : f32 +! CHECK: } +! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[V1]] : !hlfir.expr, !fir.box> +! CHECK: acc.yield %[[V1]] : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_ptr_Uxf32 : !fir.box>> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.box>>): +! CHECK: } combiner { +! CHECK: ^bb0(%{{.*}}: !fir.box>>, %{{.*}}: !fir.box>>, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index): +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_heap_Uxf32 : !fir.box>> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>>): +! CHECK: %[[CST:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %2(%1) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: hlfir.assign %[[CST]] to %[[DECLARE]]#0 : f32, !fir.box> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>>, %[[ARG1:.*]]: !fir.box>>, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index, %[[ARG4:.*]]: index): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[ARG0]] (%[[ARG2]]:%[[ARG3]]:%[[ARG4]]) shape %[[SHAPE]] : (!fir.box>>, index, index, index, !fir.shape<1>) -> !fir.box>> +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[ARG1]] (%[[ARG2]]:%[[ARG3]]:%[[ARG4]]) shape %[[SHAPE]] : (!fir.box>>, index, index, index, !fir.shape<1>) -> !fir.box>> +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%[[IV:.*]]: index): +! CHECK: %[[V1:.*]] = hlfir.designate %[[DES_V1]] (%[[IV]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: %[[V2:.*]] = hlfir.designate %[[DES_V2]] (%[[IV]]) : (!fir.box>>, index) -> !fir.ref +! CHECK: %[[LOAD_V1:.*]] = fir.load %[[V1]] : !fir.ref +! CHECK: %[[LOAD_V2:.*]] = fir.load %[[V2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD_V1]], %[[LOAD_V2]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD_V1]], %[[LOAD_V2]] : f32 +! CHECK: hlfir.yield_element %[[SELECT]] : f32 +! CHECK: } +! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr, !fir.box>> +! CHECK: acc.yield %[[ARG0]] : !fir.box>> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_lb1.ub3_box_Uxi32 : !fir.box> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %c0{{.*}} : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %0#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: hlfir.assign %c0{{.*}} to %[[DECLARE]]#0 : i32, !fir.box> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>, %[[ARG1:.*]]: !fir.box>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[DES1:.*]] = hlfir.designate %[[ARG0]] shape %[[SHAPE]] : (!fir.box>, !fir.shape<1>) -> !fir.box> +! CHECK: %[[DES2:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box>, !fir.shape<1>) -> !fir.box> +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %[[SHAPE]] unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%[[IV:.*]]: index): +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[DES1]] (%[[IV]]) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[DES2]] (%[[IV]]) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref +! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD_V1]], %[[LOAD_V2]] : i32 +! CHECK: hlfir.yield_element %[[COMBINED]] : i32 +! CHECK: } +! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr, !fir.box> +! CHECK: acc.yield %[[ARG0]] : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_box_Uxf32 : !fir.box> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[INIT_VALUE:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %0#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: hlfir.assign %[[INIT_VALUE]] to %[[DECLARE]]#0 : f32, !fir.box> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>, %[[ARG1:.*]]: !fir.box> +! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%{{.*}}: index): +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[LEFT]] (%{{.*}}) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[RIGHT]] (%{{.*}}) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref +! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref +! CHECK: %[[CMPF:.*]] = arith.cmpf ogt, %[[LOAD_V1]], %[[LOAD_V2]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMPF]], %[[LOAD_V1]], %[[LOAD_V2]] : f32 +! CHECK: hlfir.yield_element %[[SELECT]] : f32 +! CHECK: } +! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[ARG0]] : !hlfir.expr, !fir.box> +! CHECK: acc.yield %[[ARG0]] : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_box_Uxi32 : !fir.box> reduction_operator init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>): +! CHECK: %[[INIT_VALUE:.*]] = arith.constant 0 : i32 +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[BOX_DIMS:.*]]:3 = fir.box_dims %[[ARG0]], %[[C0]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[SHAPE:.*]] = fir.shape %[[BOX_DIMS]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array, %[[BOX_DIMS]]#1 {bindc_name = ".tmp", uniq_name = ""} +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap>, !fir.shape<1>) -> (!fir.box>, !fir.heap>) +! CHECK: hlfir.assign %[[INIT_VALUE]] to %[[DECLARE]]#0 : i32, !fir.box> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.box> +! CHECK: } combiner { +! CHECK: ^bb0(%[[V1:.*]]: !fir.box>, %[[V2:.*]]: !fir.box> +! CHECK: %[[LEFT:.*]] = hlfir.designate %[[ARG0]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box>, index, index, index, !fir.shape<1>) -> !fir.box> +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! CHECK: ^bb0(%{{.*}}: index): +! CHECK: %[[DES_V1:.*]] = hlfir.designate %[[LEFT]] (%{{.*}}) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[RIGHT]] (%{{.*}}) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[LOAD_V1:.*]] = fir.load %[[DES_V1]] : !fir.ref +! CHECK: %[[LOAD_V2:.*]] = fir.load %[[DES_V2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD_V1]], %[[LOAD_V2]] : i32 +! CHECK: hlfir.yield_element %[[COMBINED]] : i32 +! CHECK: } +! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[V1]] : !hlfir.expr, !fir.box> +! CHECK: acc.yield %arg0 : !fir.box> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_z32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[REAL:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[IMAG:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[UNDEF:.*]] = fir.undefined complex +! CHECK: %[[UNDEF1:.*]] = fir.insert_value %[[UNDEF]], %[[REAL]], [0 : index] : (complex, f32) -> complex +! CHECK: %[[UNDEF2:.*]] = fir.insert_value %[[UNDEF1]], %[[IMAG]], [1 : index] : (complex, f32) -> complex +! CHECK: %[[ALLOCA:.*]] = fir.alloca complex +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.store %[[UNDEF2]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[COMBINED:.*]] = fir.mulc %[[LOAD0]], %[[LOAD1]] {fastmath = #arith.fastmath} : complex +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_z32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[REAL:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[IMAG:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[UNDEF:.*]] = fir.undefined complex +! CHECK: %[[UNDEF1:.*]] = fir.insert_value %[[UNDEF]], %[[REAL]], [0 : index] : (complex, f32) -> complex +! CHECK: %[[UNDEF2:.*]] = fir.insert_value %[[UNDEF1]], %[[IMAG]], [1 : index] : (complex, f32) -> complex +! CHECK: %[[ALLOCA:.*]] = fir.alloca complex +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.store %[[UNDEF2]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[COMBINED:.*]] = fir.addc %[[LOAD0]], %[[LOAD1]] {fastmath = #arith.fastmath} : complex +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_neqv_ref_l32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[CST:.*]] = arith.constant false +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMP:.*]] = arith.cmpi ne, %[[CONV0]], %[[CONV1]] : i1 +! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_eqv_ref_l32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[CST:.*]] = arith.constant true +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[CONV0]], %[[CONV1]] : i1 +! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_lor_ref_l32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[CST:.*]] = arith.constant false +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMP:.*]] = arith.ori %[[CONV0]], %[[CONV1]] : i1 +! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_land_ref_l32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[CST:.*]] = arith.constant true +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[CONVERT:.*]] = fir.convert %[[CST]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CONVERT]] to %[[DECLARE]]#0 : !fir.ref> +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[CONV0:.*]] = fir.convert %[[LOAD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CONV1:.*]] = fir.convert %[[LOAD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[CMP:.*]] = arith.andi %[[CONV0]], %[[CONV1]] : i1 +! CHECK: %[[CMP_CONV:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[CMP_CONV]] to %[[ARG0]] : !fir.ref> +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_xor_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[CST:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[CST]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.xori %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_ior_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[CST:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[CST]] to %[[DECLARE:.*]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE:.*]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.ori %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_iand_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[CST:.*]] = arith.constant -1 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[CST]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.andi %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_section_ext100_ref_100xf32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[STEP:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { +! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[DECLARE]]#0, %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: fir.store %[[INIT]] to %[[COORD]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 99 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 +! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_f32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant -1.401300e-45 : f32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %0 {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf ogt, %[[LOAD0]], %[[LOAD1]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : f32 +! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_section_ext100xext10_ref_100x10xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%arg0: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 9 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[LB1:.*]] = arith.constant 0 : index +! CHECK: %[[UB1:.*]] = arith.constant 99 : index +! CHECK: %[[STEP1:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0:.*]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1:.*]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_max_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%arg0: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_section_ext100xext10_ref_100x10xf32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 9 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[LB1:.*]] = arith.constant 0 : index +! CHECK: %[[UB1:.*]] = arith.constant 99 : index +! CHECK: %[[STEP1:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf olt, %[[LOAD1]], %[[LOAD2]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : f32 +! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_f32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 3.40282347E+38 : f32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpf olt, %[[LOAD0]], %[[LOAD1]] {{.*}} : f32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : f32 +! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 99 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[SELECT]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_min_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 2147483647 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: %[[SELECT:.*]] = arith.select %[[CMP]], %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[SELECT]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_f32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.mulf %[[LOAD0]], %[[LOAD1]] fastmath : f32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 1 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[STEP:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.muli %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_mul_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 1 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.muli %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100_ref_100xf32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[STEP:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addf %[[LOAD1]], %[[LOAD2]] fastmath : f32 +! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_f32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca f32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addf %[[LOAD0]], %[[LOAD1]] fastmath : f32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100xext10xext2_ref_100x10x2xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}}, %{{.*}} : (index, index, index) -> !fir.shape<3> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10x2xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<3>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 1 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[LB1:.*]] = arith.constant 0 : index +! CHECK: %[[UB1:.*]] = arith.constant 9 : index +! CHECK: %[[STEP1:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { +! CHECK: %[[LB2:.*]] = arith.constant 0 : index +! CHECK: %[[UB2:.*]] = arith.constant 99 : index +! CHECK: %[[STEP2:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV2:.*]] = %[[LB2]] to %[[UB2]] step %[[STEP2]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]], %[[IV1]], %[[IV2]] : (!fir.ref>, index, index, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]], %[[IV1]], %[[IV2]] : (!fir.ref>, index, index, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100xext10_ref_100x10xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100x10xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.constant 9 : index +! CHECK: %[[STEP0:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV0:.*]] = %[[LB0]] to %[[UB0]] step %[[STEP0]] { +! CHECK: %[[LB1:.*]] = arith.constant 0 : index +! CHECK: %[[UB1:.*]] = arith.constant 99 : index +! CHECK: %[[STEP1:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV1:.*]] = %[[LB1]] to %[[UB1]] step %[[STEP1]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV0]], %[[IV1]] : (!fir.ref>, index, index) -> !fir.ref +! CHECK: %[[LOAD1]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_section_ext100_ref_100xi32 : !fir.ref> reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xi32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.reduction.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! HFLIR: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LB:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.constant 99 : index +! CHECK: %[[STEP:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[IV:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] { +! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %[[IV]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[COORD1]] : !fir.ref +! CHECK: %[[LOAD2:.*]] = fir.load %[[COORD2]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD1]], %[[LOAD2]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[COORD1]] : !fir.ref +! CHECK: } +! CHECK: acc.yield %[[ARG0]] : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.reduction.recipe @reduction_add_ref_i32 : !fir.ref reduction_operator init { +! CHECK: ^bb0(%{{.*}}: !fir.ref): +! CHECK: %[[INIT:.*]] = arith.constant 0 : i32 +! CHECK: %[[ALLOCA:.*]] = fir.alloca i32 +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "acc.reduction.init"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.store %[[INIT]] to %[[DECLARE]]#0 : !fir.ref +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref +! CHECK: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LOAD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LOAD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[COMBINED:.*]] = arith.addi %[[LOAD0]], %[[LOAD1]] : i32 +! CHECK: fir.store %[[COMBINED]] to %[[ARG0]] : !fir.ref +! CHECK: acc.yield %[[ARG0]] : !fir.ref +! CHECK: } + +subroutine acc_reduction_add_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(+:b) + do i = 1, 100 + b = b + a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_i32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_add_int_array_1d(a, b) + integer :: a(100) + integer :: i, b(100) + + !$acc loop reduction(+:b) + do i = 1, 100 + b(i) = b(i) + a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_section_ext100_ref_100xi32 -> %[[RED_B]] : !fir.ref>) + +subroutine acc_reduction_add_int_array_2d(a, b) + integer :: a(100, 10), b(100, 10) + integer :: i, j + + !$acc loop collapse(2) reduction(+:b) + do i = 1, 100 + do j = 1, 10 + b(i, j) = b(i, j) + a(i, j) + end do + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_2d( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) { +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_section_ext100xext10_ref_100x10xi32 -> %[[RED_ARG1]] : !fir.ref>) +! CHECK: } attributes {collapse = [2]{{.*}} + +subroutine acc_reduction_add_int_array_3d(a, b) + integer :: a(100, 10, 2), b(100, 10, 2) + integer :: i, j, k + + !$acc loop collapse(3) reduction(+:b) + do i = 1, 100 + do j = 1, 10 + do k = 1, 2 + b(i, j, k) = b(i, j, k) + a(i, j, k) + end do + end do + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_int_array_3d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_section_ext100xext10xext2_ref_100x10x2xi32 -> %[[RED_ARG1]] : !fir.ref>) +! CHECK: } attributes {collapse = [3]{{.*}} + +subroutine acc_reduction_add_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(+:b) + do i = 1, 100 + b = b + a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_add_float_array_1d(a, b) + real :: a(100), b(100) + integer :: i + + !$acc loop reduction(+:b) + do i = 1, 100 + b(i) = b(i) + a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_float_array_1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_add_section_ext100_ref_100xf32 -> %[[RED_B]] : !fir.ref>) + +subroutine acc_reduction_mul_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(*:b) + do i = 1, 100 + b = b * a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_mul_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_i32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_mul_int_array_1d(a, b) + integer :: a(100) + integer :: i, b(100) + + !$acc loop reduction(*:b) + do i = 1, 100 + b(i) = b(i) * a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_mul_int_array_1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_mul_section_ext100_ref_100xi32 -> %[[RED_B]] : !fir.ref>) + +subroutine acc_reduction_mul_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(*:b) + do i = 1, 100 + b = b * a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_mul_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_mul_ref_f32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_mul_float_array_1d(a, b) + real :: a(100), b(100) + integer :: i + + !$acc loop reduction(*:b) + do i = 1, 100 + b(i) = b(i) * a(i) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_mul_float_array_1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_mul_section_ext100_ref_100xf32 -> %[[RED_B]] : !fir.ref>) + +subroutine acc_reduction_min_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(min:b) + do i = 1, 100 + b = min(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_i32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_min_int_array_1d(a, b) + integer :: a(100), b(100) + integer :: i + + !$acc loop reduction(min:b) + do i = 1, 100 + b(i) = min(b(i), a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_int_array_1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_min_section_ext100_ref_100xi32 -> %[[RED_ARG1]] : !fir.ref>) + +subroutine acc_reduction_min_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(min:b) + do i = 1, 100 + b = min(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_min_ref_f32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_min_float_array2d(a, b) + real :: a(100, 10), b(100, 10) + integer :: i, j + + !$acc loop reduction(min:b) collapse(2) + do i = 1, 100 + do j = 1, 10 + b(i, j) = min(b(i, j), a(i, j)) + end do + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_min_float_array2d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_min_section_ext100xext10_ref_100x10xf32 -> %[[RED_ARG1]] : !fir.ref>) +! CHECK: attributes {collapse = [2]{{.*}} + +subroutine acc_reduction_max_int(a, b) + integer :: a(100) + integer :: i, b + + !$acc loop reduction(max:b) + do i = 1, 100 + b = max(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_int( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_i32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_max_int_array2d(a, b) + integer :: a(100, 10), b(100, 10) + integer :: i, j + + !$acc loop reduction(max:b) collapse(2) + do i = 1, 100 + do j = 1, 10 + b(i, j) = max(b(i, j), a(i, j)) + end do + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_int_array2d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_max_section_ext100xext10_ref_100x10xi32 -> %[[RED_ARG1]] : !fir.ref>) + +subroutine acc_reduction_max_float(a, b) + real :: a(100), b + integer :: i + + !$acc loop reduction(max:b) + do i = 1, 100 + b = max(b, a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_float( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref {fir.bindc_name = "b"}) +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[RED_B:.*]] = acc.reduction varPtr(%[[DECLB]]#0 : !fir.ref) -> !fir.ref {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_max_ref_f32 -> %[[RED_B]] : !fir.ref) + +subroutine acc_reduction_max_float_array1d(a, b) + real :: a(100), b(100) + integer :: i + + !$acc loop reduction(max:b) + do i = 1, 100 + b(i) = max(b(i), a(i)) + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_float_array1d( +! CHECK-SAME: %{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref> {fir.bindc_name = "b"}) +! CHECK: %[[DECLARG1:.*]]:2 = hlfir.declare %[[ARG1]] +! CHECK: %[[RED_ARG1:.*]] = acc.reduction varPtr(%[[DECLARG1]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop {{.*}} reduction(@reduction_max_section_ext100_ref_100xf32 -> %[[RED_ARG1]] : !fir.ref>) + +subroutine acc_reduction_iand() + integer :: i + !$acc parallel reduction(iand:i) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_iand() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref) -> !fir.ref {name = "i"} +! CHECK: acc.parallel reduction(@reduction_iand_ref_i32 -> %[[RED]] : !fir.ref) + +subroutine acc_reduction_ior() + integer :: i + !$acc parallel reduction(ior:i) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_ior() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref) -> !fir.ref {name = "i"} +! CHECK: acc.parallel reduction(@reduction_ior_ref_i32 -> %[[RED]] : !fir.ref) + +subroutine acc_reduction_ieor() + integer :: i + !$acc parallel reduction(ieor:i) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_ieor() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref) -> !fir.ref {name = "i"} +! CHECK: acc.parallel reduction(@reduction_xor_ref_i32 -> %[[RED]] : !fir.ref) + +subroutine acc_reduction_and() + logical :: l + !$acc parallel reduction(.and.:l) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_and() +! CHECK: %[[L:.*]] = fir.alloca !fir.logical<4> {bindc_name = "l", uniq_name = "_QFacc_reduction_andEl"} +! CHECK: %[[DECLL:.*]]:2 = hlfir.declare %[[L]] +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLL]]#0 : !fir.ref>) -> !fir.ref> {name = "l"} +! CHECK: acc.parallel reduction(@reduction_land_ref_l32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_or() + logical :: l + !$acc parallel reduction(.or.:l) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_or() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {name = "l"} +! CHECK: acc.parallel reduction(@reduction_lor_ref_l32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_eqv() + logical :: l + !$acc parallel reduction(.eqv.:l) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_eqv() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {name = "l"} +! CHECK: acc.parallel reduction(@reduction_eqv_ref_l32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_neqv() + logical :: l + !$acc parallel reduction(.neqv.:l) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_neqv() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {name = "l"} +! CHECK: acc.parallel reduction(@reduction_neqv_ref_l32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_add_cmplx() + complex :: c + !$acc parallel reduction(+:c) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_cmplx() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {name = "c"} +! CHECK: acc.parallel reduction(@reduction_add_ref_z32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_mul_cmplx() + complex :: c + !$acc parallel reduction(*:c) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_mul_cmplx() +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) -> !fir.ref> {name = "c"} +! CHECK: acc.parallel reduction(@reduction_mul_ref_z32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_add_alloc() + integer, allocatable :: i + allocate(i) + !$acc parallel reduction(+:i) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_alloc() +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box> {bindc_name = "i", uniq_name = "_QFacc_reduction_add_allocEi"} +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]] +! CHECK: %[[LOAD:.*]] = fir.load %[[DECL]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>) -> !fir.heap +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.heap) -> !fir.heap {name = "i"} +! CHECK: acc.parallel reduction(@reduction_add_heap_i32 -> %[[RED]] : !fir.heap) + +subroutine acc_reduction_add_pointer(i) + integer, pointer :: i + !$acc parallel reduction(+:i) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_pointer( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>> {fir.bindc_name = "i"}) +! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] +! CHECK: %[[LOAD:.*]] = fir.load %[[DECLARG0]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.ptr) -> !fir.ptr {name = "i"} +! CHECK: acc.parallel reduction(@reduction_add_ptr_i32 -> %[[RED]] : !fir.ptr) + +subroutine acc_reduction_add_static_slice(a) + integer :: a(100) + !$acc parallel reduction(+:a(11:20)) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_static_slice( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) +! CHECK: %[[C100:.*]] = arith.constant 100 : index +! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[LB:.*]] = arith.constant 10 : index +! CHECK: %[[UB:.*]] = arith.constant 19 : index +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[C100]] : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[DECLARG0]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(11:20)"} +! CHECK: acc.parallel reduction(@reduction_add_section_lb10.ub19_ref_100xi32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_add_dynamic_extent_add(a) + integer :: a(:) + !$acc parallel reduction(+:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_dynamic_extent_add( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) +! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel reduction(@reduction_add_box_Uxi32 -> %[[RED:.*]] : !fir.ref>) + +subroutine acc_reduction_add_assumed_shape_max(a) + real :: a(:) + !$acc parallel reduction(max:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_assumed_shape_max( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) +! CHECK: %[[DECLARG0:.*]]:2 = hlfir.declare %[[ARG0]] +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel reduction(@reduction_max_box_Uxf32 -> %[[RED]] : !fir.ref>) { + +subroutine acc_reduction_add_dynamic_extent_add_with_section(a) + integer :: a(:) + !$acc parallel reduction(+:a(2:4)) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_dynamic_extent_add_with_section( +! CHECK-SAME: %[[ARG0:.*]]: !fir.box> {fir.bindc_name = "a"}) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_reduction_add_dynamic_extent_add_with_sectionEa"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c1{{.*}} : index) upperbound(%c3{{.*}} : index) extent(%{{.*}}#1 : index) stride(%{{.*}}#2 : index) startIdx(%{{.*}} : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(2:4)"} +! CHECK: acc.parallel reduction(@reduction_add_section_lb1.ub3_box_Uxi32 -> %[[RED]] : !fir.ref>) + +subroutine acc_reduction_add_allocatable(a) + real, allocatable :: a(:) + !$acc parallel reduction(max:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_allocatable( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFacc_reduction_add_allocatableEa"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>> +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}}#1 : index) stride(%{{.*}}#2 : index) startIdx(%{{.*}}#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%{{[0-9]+}}) -> !fir.heap> {name = "a"} +! CHECK: acc.parallel reduction(@reduction_max_box_heap_Uxf32 -> %[[RED]] : !fir.heap>) + +subroutine acc_reduction_add_pointer_array(a) + real, pointer :: a(:) + !$acc parallel reduction(max:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_add_pointer_array( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) +! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{[0-9]+}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFacc_reduction_add_pointer_arrayEa"} : (!fir.ref>>>, !fir.dscope) -> (!fir.ref>>>, !fir.ref>>>) +! CHECK: %[[BOX:.*]] = fir.load %[[DECL]]#0 : !fir.ref>>> +! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}}#1 : index) stride(%{{.*}}#2 : index) startIdx(%{{.*}}#0 : index) {strideInBytes = true} +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.ptr> +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%[[BOUND]]) -> !fir.ptr> {name = "a"} +! CHECK: acc.parallel reduction(@reduction_max_box_ptr_Uxf32 -> %[[RED]] : !fir.ptr>) + +subroutine acc_reduction_max_dynamic_extent_max(a, n) + integer :: n + real :: a(n, n) + !$acc parallel reduction(max:a) + !$acc end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPacc_reduction_max_dynamic_extent_max( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %{{.*}}: !fir.ref {fir.bindc_name = "n"}) +! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {uniq_name = "_QFacc_reduction_max_dynamic_extent_maxEa"} : (!fir.ref>, !fir.shape<2>, !fir.dscope) -> (!fir.box>, !fir.ref>) +! CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: %[[RED:.*]] = acc.reduction varPtr(%[[ADDR]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.parallel reduction(@reduction_max_box_UxUxf32 -> %[[RED]] : !fir.ref>) diff --git a/flang/test/Lower/OpenACC/acc-routine-named.f90 b/flang/test/Lower/OpenACC/acc-routine-named.f90 new file mode 100644 index 00000000000000..2cf6bf8b2bc06d --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-routine-named.f90 @@ -0,0 +1,25 @@ +! This test checks lowering of OpenACC routine directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module acc_routines + +! CHECK: acc.routine @acc_routine_1 func(@_QMacc_routinesPacc2) +! CHECK: acc.routine @acc_routine_0 func(@_QMacc_routinesPacc1) seq + +!$acc routine(acc1) seq + +contains + + subroutine acc1() + end subroutine + +! CHECK-LABEL: func.func @_QMacc_routinesPacc1() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} + + subroutine acc2() + !$acc routine(acc2) + end subroutine + +! CHECK-LABEL: func.func @_QMacc_routinesPacc2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>} + +end module diff --git a/flang/test/Lower/OpenACC/acc-routine.f90 b/flang/test/Lower/OpenACC/acc-routine.f90 new file mode 100644 index 00000000000000..1170af18bc3341 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-routine.f90 @@ -0,0 +1,127 @@ +! This test checks lowering of OpenACC routine directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK: acc.routine @acc_routine_17 func(@_QPacc_routine19) bind("_QPacc_routine17" [#acc.device_type], "_QPacc_routine17" [#acc.device_type], "_QPacc_routine16" [#acc.device_type]) +! CHECK: acc.routine @acc_routine_16 func(@_QPacc_routine18) bind("_QPacc_routine17" [#acc.device_type], "_QPacc_routine16" [#acc.device_type]) +! CHECK: acc.routine @acc_routine_15 func(@_QPacc_routine17) worker ([#acc.device_type]) vector ([#acc.device_type]) +! CHECK: acc.routine @acc_routine_14 func(@_QPacc_routine16) gang([#acc.device_type]) seq ([#acc.device_type]) +! CHECK: acc.routine @acc_routine_10 func(@_QPacc_routine11) seq +! CHECK: acc.routine @acc_routine_9 func(@_QPacc_routine10) seq +! CHECK: acc.routine @acc_routine_8 func(@_QPacc_routine9) bind("_QPacc_routine9a") +! CHECK: acc.routine @acc_routine_7 func(@_QPacc_routine8) bind("routine8_") +! CHECK: acc.routine @acc_routine_6 func(@_QPacc_routine7) gang(dim: 1 : i64) +! CHECK: acc.routine @acc_routine_5 func(@_QPacc_routine6) nohost +! CHECK: acc.routine @acc_routine_4 func(@_QPacc_routine5) worker +! CHECK: acc.routine @acc_routine_3 func(@_QPacc_routine4) vector +! CHECK: acc.routine @acc_routine_2 func(@_QPacc_routine3) gang +! CHECK: acc.routine @acc_routine_1 func(@_QPacc_routine2) seq +! CHECK: acc.routine @acc_routine_0 func(@_QPacc_routine1) + +subroutine acc_routine1() + !$acc routine +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine1() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} + +subroutine acc_routine2() + !$acc routine seq +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>} + +subroutine acc_routine3() + !$acc routine gang +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine3() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_2]>} + +subroutine acc_routine4() + !$acc routine vector +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine4() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_3]>} + +subroutine acc_routine5() + !$acc routine worker +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine5() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_4]>} + +subroutine acc_routine6() + !$acc routine nohost +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine6() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_5]>} + +subroutine acc_routine7() + !$acc routine gang(dim:1) +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine7() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_6]>} + +subroutine acc_routine8() + !$acc routine bind("routine8_") +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine8() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_7]>} + +subroutine acc_routine9a() +end subroutine + +subroutine acc_routine9() + !$acc routine bind(acc_routine9a) +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine9() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_8]>} + +function acc_routine10() + !$acc routine(acc_routine10) seq +end function + +! CHECK-LABEL: func.func @_QPacc_routine10() -> f32 attributes {acc.routine_info = #acc.routine_info<[@acc_routine_9]>} + +subroutine acc_routine11(a) + real :: a + !$acc routine(acc_routine11) seq +end subroutine + +! CHECK-LABEL: func.func @_QPacc_routine11(%arg0: !fir.ref {fir.bindc_name = "a"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_10]>} + +subroutine acc_routine12() + + interface + subroutine acc_routine11(a) + real :: a + !$acc routine(acc_routine11) seq + end subroutine + end interface + +end subroutine + +subroutine acc_routine13() + !$acc routine bind(acc_routine14) +end subroutine + +subroutine acc_routine14() +end subroutine + +subroutine acc_routine15() + !$acc routine bind(acc_routine16) +end subroutine + +subroutine acc_routine16() + !$acc routine device_type(host) seq dtype(nvidia) gang +end subroutine + +subroutine acc_routine17() + !$acc routine device_type(host) worker dtype(multicore) vector +end subroutine + +subroutine acc_routine18() + !$acc routine device_type(host) bind(acc_routine17) dtype(multicore) bind(acc_routine16) +end subroutine + +subroutine acc_routine19() + !$acc routine device_type(host,default) bind(acc_routine17) dtype(multicore) bind(acc_routine16) +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-routine02.f90 b/flang/test/Lower/OpenACC/acc-routine02.f90 new file mode 100644 index 00000000000000..1c15cb409e634d --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-routine02.f90 @@ -0,0 +1,20 @@ +! This test checks lowering of OpenACC routine directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine sub1(a, n) + integer :: n + real :: a(n) +end subroutine sub1 + +!$acc routine(sub1) + +program test + integer, parameter :: N = 10 + real :: a(N) + call sub1(a, N) +end program + +! CHECK-LABEL: acc.routine @acc_routine_0 func(@_QPsub1) + +! CHECK: func.func @_QPsub1(%ar{{.*}}: !fir.ref> {fir.bindc_name = "a"}, %arg1: !fir.ref {fir.bindc_name = "n"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} diff --git a/flang/test/Lower/OpenACC/acc-routine03.f90 b/flang/test/Lower/OpenACC/acc-routine03.f90 new file mode 100644 index 00000000000000..85e4ef580f9837 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-routine03.f90 @@ -0,0 +1,35 @@ +! This test checks lowering of OpenACC routine directive in interfaces. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + + +subroutine sub1(a) + !$acc routine worker bind(sub2) + real :: a(:) +end subroutine + +subroutine sub2(a) + !$acc routine worker nohost + real :: a(:) +end subroutine + +subroutine test + +interface + subroutine sub1(a) + !$acc routine worker bind(sub2) + real :: a(:) + end subroutine + + subroutine sub2(a) + !$acc routine worker nohost + real :: a(:) + end subroutine +end interface + +end subroutine + +! CHECK: acc.routine @acc_routine_1 func(@_QPsub2) worker nohost +! CHECK: acc.routine @acc_routine_0 func(@_QPsub1) bind("_QPsub2") worker +! CHECK: func.func @_QPsub1(%arg0: !fir.box> {fir.bindc_name = "a"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} +! CHECK: func.func @_QPsub2(%arg0: !fir.box> {fir.bindc_name = "a"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>} diff --git a/flang/test/Lower/OpenACC/acc-routine04.f90 b/flang/test/Lower/OpenACC/acc-routine04.f90 new file mode 100644 index 00000000000000..f6033761639013 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-routine04.f90 @@ -0,0 +1,34 @@ +! This test checks correct lowering when OpenACC routine directive is placed +! before implicit none. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +module dummy_mod +contains + + subroutine sub1(i) + !$acc routine seq + integer :: i + end subroutine +end module + +program test_acc_routine + use dummy_mod + + !$acc routine(sub2) seq + + implicit none + + integer :: i + +contains + subroutine sub2() + end subroutine + +end program + +! CHECK: acc.routine @acc_routine_1 func(@_QFPsub2) seq +! CHECK: acc.routine @acc_routine_0 func(@_QMdummy_modPsub1) seq +! CHECK: func.func @_QMdummy_modPsub1(%arg0: !fir.ref {fir.bindc_name = "i"}) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>} +! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "test_acc_routine"} +! CHECK: func.func private @_QFPsub2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>, fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage} diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 new file mode 100644 index 00000000000000..fa3b3f758908ce --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -0,0 +1,665 @@ +! This test checks lowering of Openacc serial loop combined directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.private.recipe @privatization_ref_10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10_ref_10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } copy { +! CHECK: ^bb0(%arg0: !fir.ref>, %arg1: !fir.ref>): +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_serial_loop() + +subroutine acc_serial_loop + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + integer, parameter :: n = 10 + real, dimension(n) :: a, b, c + real, dimension(n, n) :: d, e + real, pointer :: f, g + integer :: reduction_i + real :: reduction_r + + integer :: gangNum = 8 + integer :: gangStatic = 8 + integer :: vectorNum = 128 + integer, parameter :: tileSize = 2 + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[F:.*]] = fir.alloca !fir.box> {bindc_name = "f", uniq_name = "{{.*}}Ef"} +! CHECK: %[[DECLF:.*]]:2 = hlfir.declare %[[F]] +! CHECK: %[[G:.*]] = fir.alloca !fir.box> {bindc_name = "g", uniq_name = "{{.*}}Eg"} +! CHECK: %[[DECLG:.*]]:2 = hlfir.declare %[[G]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc serial + !$acc loop + DO i = 1, n + a(i) = b(i) + END DO + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial combined(loop) { +! CHECK: acc.loop combined(serial) private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop async + DO i = 1, n + a(i) = b(i) + END DO + !$acc end serial loop + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc serial loop async(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial {{.*}} async([[ASYNC1]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop async(async) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.serial {{.*}} async([[ASYNC2]] : i32) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop wait + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} wait { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } + + !$acc serial loop wait(1) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial {{.*}} wait({[[WAIT1]] : i32}) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop wait(1, 2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.serial {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop wait(wait1, wait2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.serial {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop if(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.serial {{.*}} if([[IF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop if(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.serial {{.*}} if([[IF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop self(.TRUE.) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.serial {{.*}} self([[SELF1]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop self + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: } attributes {selfAttr} + + !$acc serial loop self(ifCondition) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.serial {{.*}} self(%[[SELF2]]) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop copy(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc serial loop copy(a) copy(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} + + !$acc serial loop copyin(a) copyin(readonly: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop copyout(a) copyout(zero: b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} + + !$acc serial loop create(b) create(zero: a) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.serial {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}) {dataClause = #acc, name = "a"} + + !$acc serial loop no_create(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop present(a, b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop deviceptr(a) deviceptr(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.serial {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop attach(f, g) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[BOX_F:.*]] = fir.load %[[DECLF]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_F:.*]] = fir.box_addr %[[BOX_F]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_F:.*]] = acc.attach varPtr(%[[BOX_ADDR_F]] : !fir.ptr) -> !fir.ptr {name = "f"} +! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr) -> !fir.ptr {name = "g"} +! CHECK: acc.serial {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop private(a) firstprivate(b) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.serial {{.*}} firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref>) { +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref>) +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop seq + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, seq = [#acc.device_type]} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop auto + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {auto_ = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop independent + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array, independent = [#acc.device_type]} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop gang + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} gang {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: 8) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: gangNum) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop gang(num: gangNum, static: gangStatic) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop vector + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} vector {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop vector(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop vector(vectorLength) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop worker + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {inclusiveUpperbound = array}{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop worker(128) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop collapse(2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type], inclusiveUpperbound = array} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop + DO i = 1, n + !$acc loop + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop tile(2) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop tile(*) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop tile(2, 2) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 +! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 +! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop tile(tileSize) + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop tile(tileSize, tileSize) + DO i = 1, n + DO j = 1, n + d(i, j) = e(i, j) + END DO + END DO + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop reduction(+:reduction_r) reduction(*:reduction_i) + do i = 1, n + reduction_r = reduction_r + a(i) + reduction_i = 1 + end do + +! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref) -> !fir.ref {dataClause = #acc, implicit = true, name = "reduction_i"} +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref, !fir.ref) { +! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) +! CHECK-NOT: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_r"} +! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref) to varPtr(%{{.*}} : !fir.ref) {dataClause = #acc, implicit = true, name = "reduction_i"} + +end subroutine acc_serial_loop diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 new file mode 100644 index 00000000000000..284f61976a46d4 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -0,0 +1,291 @@ +! This test checks lowering of OpenACC serial directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_ext10xext10_ref_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } copy { +! CHECK: ^bb0(%arg0: !fir.ref>, %arg1: !fir.ref>): +! CHECK: acc.terminator +! CHECK: } + +! CHECK-LABEL: acc.private.recipe @privatization_ref_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) +! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_serial() + +subroutine acc_serial + integer :: i, j + + integer :: async = 1 + integer :: wait1 = 1 + integer :: wait2 = 2 + integer :: numGangs = 1 + integer :: numWorkers = 10 + integer :: vectorLength = 128 + logical :: ifCondition = .TRUE. + real, dimension(10, 10) :: a, b, c + real, pointer :: d, e + integer :: reduction_i + real :: reduction_r + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] +! CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +! CHECK: %[[DECLD:.*]]:2 = hlfir.declare %[[D]] +! CHECK: %[[E:.*]] = fir.alloca !fir.box> {bindc_name = "e", uniq_name = "{{.*}}Ee"} +! CHECK: %[[DECLE:.*]]:2 = hlfir.declare %[[E]] +! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref> +! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] + + !$acc serial + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial async + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {asyncOnly = [#acc.device_type]} + + !$acc serial async(1) + !$acc end serial + +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial async([[ASYNC1]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial async(async) + !$acc end serial + +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK-NEXT: acc.serial async([[ASYNC2]] : i32) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait + !$acc end serial + +! CHECK: acc.serial wait { +! CHECK: acc.yield +! CHECK-NEXT: } + + !$acc serial wait(1) + !$acc end serial + +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: acc.serial wait({[[WAIT1]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait(1, 2) + !$acc end serial + +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: acc.serial wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial wait(wait1, wait2) + !$acc end serial + +! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: acc.serial wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial if(.TRUE.) + !$acc end serial + +! CHECK: [[IF1:%.*]] = arith.constant true +! CHECK: acc.serial if([[IF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial if(ifCondition) + !$acc end serial + +! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.serial if([[IF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial self(.TRUE.) + !$acc end serial + +! CHECK: [[SELF1:%.*]] = arith.constant true +! CHECK: acc.serial self([[SELF1]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial self + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.yield +! CHECK-NEXT: } attributes {selfAttr} + + !$acc serial self(ifCondition) + !$acc end serial + +! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref>) -> i1 +! CHECK: acc.serial self(%[[SELF2]]) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copy(a, b, c) + !$acc end serial + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc serial copy(a) copy(b) copy(c) + !$acc end serial + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[COPYIN_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.copyout accPtr(%[[COPYIN_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.copyout accPtr(%[[COPYIN_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {dataClause = #acc, name = "c"} + + !$acc serial copyin(a) copyin(readonly: b, c) + !$acc end serial + +! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[COPYIN_C:.*]] = acc.copyin varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]], %[[COPYIN_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial copyout(a) copyout(zero: b) copyout(c) + !$acc end serial + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.copyout accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a"} +! CHECK: acc.copyout accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b"} +! CHECK: acc.copyout accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {name = "c"} + + !$acc serial create(a, b) create(zero: c) + !$acc end serial + +! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[CREATE_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) {dataClause = #acc, name = "c"} + + !$acc serial no_create(a, b) create(zero: c) + !$acc end serial + +! CHECK: %[[NO_CREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[NO_CREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c"} +! CHECK: acc.serial dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial present(a, b, c) + !$acc end serial + +! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[PRESENT_C:.*]] = acc.present varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.serial dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial deviceptr(a) deviceptr(c) + !$acc end serial + +! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[DEVICEPTR_C:.*]] = acc.deviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.serial dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_C]] : !fir.ref>, !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial attach(d, e) + !$acc end serial + +! CHECK: %[[BOX_D:.*]] = fir.load %[[DECLD]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[BOX_ADDR_D]] : !fir.ptr) -> !fir.ptr {name = "d"} +! CHECK: %[[BOX_E:.*]] = fir.load %[[DECLE]]#0 : !fir.ref>> +! CHECK: %[[BOX_ADDR_E:.*]] = fir.box_addr %[[BOX_E]] : (!fir.box>) -> !fir.ptr +! CHECK: %[[ATTACH_E:.*]] = acc.attach varPtr(%[[BOX_ADDR_E]] : !fir.ptr) -> !fir.ptr {name = "e"} +! CHECK: acc.serial dataOperands(%[[ATTACH_D]], %[[ATTACH_E]] : !fir.ptr, !fir.ptr) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.detach accPtr(%[[ATTACH_D]] : !fir.ptr) {dataClause = #acc, name = "d"} +! CHECK: acc.detach accPtr(%[[ATTACH_E]] : !fir.ptr) {dataClause = #acc, name = "e"} + + !$acc serial private(a) firstprivate(b) private(c) + !$acc end serial + +! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: %[[ACC_PRIVATE_C:.*]] = acc.private varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c"} +! CHECK: acc.serial firstprivate(@firstprivatization_section_ext10xext10_ref_10x10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref>) private(@privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref>, @privatization_ref_10x10xf32 -> %[[ACC_PRIVATE_C]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + +!$acc serial reduction(+:reduction_r) reduction(*:reduction_i) +!$acc end serial + +! CHECK: acc.serial reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + +!$acc serial default(none) +!$acc end serial + +! CHECK: acc.serial { +! CHECK: } attributes {defaultAttr = #acc} + +!$acc serial default(present) +!$acc end serial + +! CHECK: acc.serial { +! CHECK: } attributes {defaultAttr = #acc} + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-set.f90 b/flang/test/Lower/OpenACC/acc-set.f90 new file mode 100644 index 00000000000000..31c1912a87f57e --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-set.f90 @@ -0,0 +1,40 @@ +! This test checks lowering of OpenACC set directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR + +program test_acc_set + logical :: l + +!$acc set default_async(1) + +!$acc set default_async(1) if(l) + +!$acc set device_num(0) + +!$acc set device_type(*) + +!$acc set device_type(multicore) + +end + +! CHECK-LABEL: func.func @_QQmain() +! CHECK: %[[L:.*]] = fir.alloca !fir.logical<4> {bindc_name = "l", uniq_name = "_QFEl"} +! HLFIR: %[[DECLL:.*]]:2 = hlfir.declare %[[L]] {uniq_name = "_QFEl"} + +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! CHECK: acc.set default_async(%[[C1]] : i32) + +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! FIR: %[[LOAD_L:.*]] = fir.load %[[L]] : !fir.ref> +! HLFIR: %[[LOAD_L:.*]] = fir.load %[[DECLL]]#0 : !fir.ref> +! CHECK: %[[CONV_L:.*]] = fir.convert %[[LOAD_L]] : (!fir.logical<4>) -> i1 +! CHECK: acc.set default_async(%[[C1]] : i32) if(%[[CONV_L]]) + +! CHECK: %[[C0:.*]] = arith.constant 0 : i32 +! CHECK: acc.set device_num(%[[C0]] : i32) + +! CHECK: acc.set attributes {device_type = #acc.device_type} + +! CHECK: acc.set attributes {device_type = #acc.device_type} + + diff --git a/flang/test/Lower/OpenACC/acc-shortloop-ignore.f90 b/flang/test/Lower/OpenACC/acc-shortloop-ignore.f90 new file mode 100644 index 00000000000000..c1d58131938494 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-shortloop-ignore.f90 @@ -0,0 +1,57 @@ +! Test that non-standard shortloop clause is accepted and ignored with a +! warning. + +! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - 2>&1 | FileCheck %s + +! CHECK: warning: Non-standard shortloop clause ignored +! CHECK: warning: Non-standard shortloop clause ignored +! CHECK: warning: Non-standard shortloop clause ignored +! CHECK: warning: Non-standard shortloop clause ignored + +subroutine test_loop(a, b, c) + implicit none + real, dimension(100) :: a,b,c + integer :: i + !$acc loop vector shortloop + do i=1,100 + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_loop +! CHECK: acc.loop vector + +subroutine test_kernels_loop(a, b, c) + implicit none + real, dimension(100) :: a,b,c + integer :: i + !$acc kernels loop vector shortloop + do i=1,100 + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_kernels_loop +! CHECK: acc.loop combined(kernels) vector + +subroutine test_parallel_loop(a, b, c) + implicit none + real, dimension(100) :: a,b,c + integer :: i + !$acc parallel loop vector shortloop + do i=1,100 + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_parallel_loop +! CHECK: acc.loop combined(parallel) vector + +subroutine test_serial_loop(a, b, c) + implicit none + real, dimension(100) :: a,b,c + integer :: i + !$acc serial loop vector shortloop + do i=1,100 + a(i) = b(i) + c(i) + enddo +end subroutine +! CHECK-LABEL: test_serial_loop +! CHECK: acc.loop combined(serial) vector diff --git a/flang/test/Lower/OpenACC/acc-shutdown.f90 b/flang/test/Lower/OpenACC/acc-shutdown.f90 new file mode 100644 index 00000000000000..6c080b932f92ee --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-shutdown.f90 @@ -0,0 +1,28 @@ +! This test checks lowering of OpenACC shutdown directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_shutdown + logical :: ifCondition = .TRUE. + + !$acc shutdown +!CHECK: acc.shutdown{{ *}}{{$}} + + !$acc shutdown if(.true.) +!CHECK: [[IF1:%.*]] = arith.constant true +!CHECK: acc.shutdown if([[IF1]]){{$}} + + !$acc shutdown if(ifCondition) +!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.shutdown if([[IF2]]){{$}} + + !$acc shutdown device_num(1) +!CHECK: [[DEVNUM:%.*]] = arith.constant 1 : i32 +!CHECK: acc.shutdown device_num([[DEVNUM]] : i32){{$}} + + !$acc shutdown device_num(1) device_type(default, nvidia) +!CHECK: [[DEVNUM:%.*]] = arith.constant 1 : i32 +!CHECK: acc.shutdown device_num([[DEVNUM]] : i32) attributes {device_types = [#acc.device_type, #acc.device_type]} + +end subroutine acc_shutdown diff --git a/flang/test/Lower/OpenACC/acc-unstructured.f90 b/flang/test/Lower/OpenACC/acc-unstructured.f90 new file mode 100644 index 00000000000000..c57af98770cf50 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-unstructured.f90 @@ -0,0 +1,85 @@ +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine test_unstructured1(a, b, c) + integer :: i, j, k + real :: a(:,:,:), b(:,:,:), c(:,:,:) + + !$acc data copy(a, b, c) + + !$acc kernels + a(:,:,:) = 0.0 + !$acc end kernels + + !$acc kernels + do i = 1, 10 + do j = 1, 10 + do k = 1, 10 + end do + end do + end do + !$acc end kernels + + do i = 1, 10 + do j = 1, 10 + do k = 1, 10 + end do + end do + + if (a(1,2,3) > 10) stop 'just to be unstructured' + end do + + !$acc end data + +end subroutine + +! CHECK-LABEL: func.func @_QPtest_unstructured1 +! CHECK: acc.data +! CHECK: acc.kernels +! CHECK: acc.kernels +! CHECK: fir.call @_FortranAStopStatementText + + +subroutine test_unstructured2(a, b, c) + integer :: i, j, k + real :: a(:,:,:), b(:,:,:), c(:,:,:) + + !$acc parallel loop + do i = 1, 10 + do j = 1, 10 + do k = 1, 10 + if (a(1,2,3) > 10) stop 'just to be unstructured' + end do + end do + end do + +! CHECK-LABEL: func.func @_QPtest_unstructured2 +! CHECK: acc.parallel +! CHECK: acc.loop +! CHECK: fir.call @_FortranAStopStatementText +! CHECK: acc.yield +! CHECK: acc.yield +! CHECK: acc.yield + +end subroutine + +subroutine test_unstructured3(a, b, c) + integer :: i, j, k + real :: a(:,:,:), b(:,:,:), c(:,:,:) + + !$acc parallel + do i = 1, 10 + do j = 1, 10 + do k = 1, 10 + if (a(1,2,3) > 10) stop 'just to be unstructured' + end do + end do + end do + !$acc end parallel + +! CHECK-LABEL: func.func @_QPtest_unstructured3 +! CHECK: acc.parallel +! CHECK: fir.call @_FortranAStopStatementText +! CHECK: acc.yield +! CHECK: acc.yield + +end subroutine diff --git a/flang/test/Lower/OpenACC/acc-update.f90 b/flang/test/Lower/OpenACC/acc-update.f90 new file mode 100644 index 00000000000000..0964fd91457f91 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-update.f90 @@ -0,0 +1,112 @@ +! This test checks lowering of OpenACC update directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_update + integer :: async = 1 + real, dimension(10, 10) :: a, b, c + logical :: ifCondition = .TRUE. + +! CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +! CHECK: %[[DECLA:.*]]:2 = hlfir.declare %[[A]] +! CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +! CHECK: %[[DECLB:.*]]:2 = hlfir.declare %[[B]] +! CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +! CHECK: %[[DECLC:.*]]:2 = hlfir.declare %[[C]] + + !$acc update host(a) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update dataOperands(%[[DEVPTR_A]] : !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) if_present +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update dataOperands(%[[DEVPTR_A]] : !fir.ref>) attributes {ifPresent}{{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update self(a) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update dataOperands(%[[DEVPTR_A]] : !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {dataClause = #acc, name = "a", structured = false} + + !$acc update host(a) if(.true.) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: %[[IF1:.*]] = arith.constant true +! CHECK: acc.update if(%[[IF1]]) dataOperands(%[[DEVPTR_A]] : !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) if(ifCondition) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: %[[IFCOND:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK: %[[IF2:.*]] = fir.convert %[[IFCOND]] : (!fir.logical<4>) -> i1 +! CHECK: acc.update if(%[[IF2]]) dataOperands(%[[DEVPTR_A]] : !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) host(b) host(c) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b", structured = false} +! CHECK: %[[DEVPTR_C:.*]] = acc.getdeviceptr varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "c", structured = false} +! CHECK: acc.update dataOperands(%[[DEVPTR_A]], %[[DEVPTR_B]], %[[DEVPTR_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} +! CHECK: acc.update_host accPtr(%[[DEVPTR_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b", structured = false} +! CHECK: acc.update_host accPtr(%[[DEVPTR_C]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLC]]#0 : !fir.ref>) {name = "c", structured = false} + + !$acc update host(a) host(b) device(c) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: %[[DEVPTR_B:.*]] = acc.getdeviceptr varPtr(%[[DECLB]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "b", structured = false} +! CHECK: %[[DEVPTR_C:.*]] = acc.update_device varPtr(%[[DECLC]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {name = "c", structured = false} +! CHECK: acc.update dataOperands(%[[DEVPTR_C]], %[[DEVPTR_A]], %[[DEVPTR_B]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} +! CHECK: acc.update_host accPtr(%[[DEVPTR_B]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLB]]#0 : !fir.ref>) {name = "b", structured = false} + + !$acc update host(a) async +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {asyncOnly = [#acc.device_type], dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update async dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {asyncOnly = [#acc.device_type], name = "a", structured = false} + + !$acc update host(a) wait +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update wait dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) async wait +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {asyncOnly = [#acc.device_type], dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update async wait dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {asyncOnly = [#acc.device_type], name = "a", structured = false} + + !$acc update host(a) async(1) +! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC1]] : i32) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update async([[ASYNC1]] : i32) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC1]] : i32) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) async(async) +! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC2]] : i32) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update async([[ASYNC2]] : i32) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) async([[ASYNC2]] : i32) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) wait(1) +! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update wait({[[WAIT1]] : i32}) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) wait(queues: 1, 2) +! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 +! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) wait(devnum: 1: queues: 1, 2) +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update wait({devnum: %c1{{.*}} : i32, %c1{{.*}} : i32, %c2{{.*}} : i32}) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {name = "a", structured = false} + + !$acc update host(a) device_type(host, nvidia) async +! CHECK: %[[DEVPTR_A:.*]] = acc.getdeviceptr varPtr(%[[DECLA]]#0 : !fir.ref>) bounds(%{{.*}}, %{{.*}}) -> !fir.ref> {asyncOnly = [#acc.device_type, #acc.device_type], dataClause = #acc, name = "a", structured = false} +! CHECK: acc.update async([#acc.device_type, #acc.device_type]) dataOperands(%[[DEVPTR_A]] : !fir.ref>) +! CHECK: acc.update_host accPtr(%[[DEVPTR_A]] : !fir.ref>) bounds(%{{.*}}, %{{.*}}) to varPtr(%[[DECLA]]#0 : !fir.ref>) {asyncOnly = [#acc.device_type, #acc.device_type], name = "a", structured = false} + +end subroutine acc_update diff --git a/flang/test/Lower/OpenACC/acc-wait.f90 b/flang/test/Lower/OpenACC/acc-wait.f90 new file mode 100644 index 00000000000000..8a42c97a12811e --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-wait.f90 @@ -0,0 +1,41 @@ +! This test checks lowering of OpenACC wait directive. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +subroutine acc_update + integer :: async = 1 + logical :: ifCondition = .TRUE. + + !$acc wait +!CHECK: acc.wait{{ *}}{{$}} + + !$acc wait if(.true.) +!CHECK: [[IF1:%.*]] = arith.constant true +!CHECK: acc.wait if([[IF1]]){{$}} + + !$acc wait if(ifCondition) +!CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> +!CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 +!CHECK: acc.wait if([[IF2]]){{$}} + + !$acc wait(1, 2) +!CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +!CHECK: [[WAIT2:%.*]] = arith.constant 2 : i32 +!CHECK: acc.wait([[WAIT1]], [[WAIT2]] : i32, i32){{ *}}{{$}} + + !$acc wait(1) async +!CHECK: [[WAIT3:%.*]] = arith.constant 1 : i32 +!CHECK: acc.wait([[WAIT3]] : i32) attributes {async} + + !$acc wait(1) async(async) +!CHECK: [[WAIT3:%.*]] = arith.constant 1 : i32 +!CHECK: [[ASYNC1:%.*]] = fir.load %{{.*}} : !fir.ref +!CHECK: acc.wait([[WAIT3]] : i32) async([[ASYNC1]] : i32){{$}} + + !$acc wait(devnum: 3: queues: 1, 2) +!CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 +!CHECK: [[WAIT2:%.*]] = arith.constant 2 : i32 +!CHECK: [[DEVNUM:%.*]] = arith.constant 3 : i32 +!CHECK: acc.wait([[WAIT1]], [[WAIT2]] : i32, i32) wait_devnum([[DEVNUM]] : i32){{$}} + +end subroutine acc_update diff --git a/flang/test/Lower/OpenACC/locations.f90 b/flang/test/Lower/OpenACC/locations.f90 new file mode 100644 index 00000000000000..84dd512a5d43fd --- /dev/null +++ b/flang/test/Lower/OpenACC/locations.f90 @@ -0,0 +1,176 @@ +! This test checks correct propagation of location information in OpenACC +! operations. + + +! RUN: bbc -fopenacc -emit-hlfir --mlir-print-debuginfo --mlir-print-local-scope %s -o - | FileCheck %s +module acc_locations + implicit none + + contains + + subroutine standalone_data_directive_locations(arr) + real, dimension(10) :: arr + + !$acc enter data create(arr) + !CHECK-LABEL: acc.enter_data + !CHECK-SAME: loc("{{.*}}locations.f90":14:11) + + !$acc update device(arr) + !CHECK-LABEL: acc.update_device varPtr + !CHECK-SAME: loc("{{.*}}locations.f90":18:25) + !CHECK-LABEL: acc.update dataOperands + !CHECK-SAME: loc("{{.*}}locations.f90":18:11) + + !$acc update host(arr) + !CHECK-LABEL: acc.getdeviceptr varPtr + !CHECK-SAME: loc("{{.*}}locations.f90":24:23) + !CHECK-LABEL: acc.update dataOperands + !CHECK-SAME: loc("{{.*}}locations.f90":24:11) + !CHECK-LABEL: acc.update_host + !CHECK-SAME: loc("{{.*}}locations.f90":24:23) + + !$acc exit data delete(arr) + !CHECK-LABEL: acc.exit_data + !CHECK-SAME: loc("{{.*}}locations.f90":32:11) + + end subroutine + + subroutine nested_acc_locations(arr1d) + real, dimension(10) :: arr1d + integer :: i + + !$acc data copy(arr1d) + !$acc parallel + !$acc loop + do i = 1, 10 + arr1d(i) = arr1d(i) * 2 + end do + !$acc end parallel + !$acc end data + + !CHECK: acc.data + !CHECK: acc.parallel + !CHECK: acc.loop + + !CHECK: acc.yield loc("{{.*}}locations.f90":44:11) + !CHECK-NEXT: } attributes {{.*}} loc(fused["{{.*}}locations.f90":44:11, "{{.*}}locations.f90":45:5]) + + !CHECK: acc.yield loc("{{.*}}locations.f90":43:11) + !CHECK-NEXT: } loc("{{.*}}locations.f90":43:11) + + !CHECK-NEXT: acc.terminator loc("{{.*}}locations.f90":42:11) + !CHECK-NEXT: } loc("{{.*}}locations.f90":42:11) + + end subroutine + + subroutine runtime_directive() + + !$acc init + !CHECK-LABEL: acc.init + !CHECK-SAME: loc("{{.*}}locations.f90":68:11) + + !$acc shutdown + !CHECK-LABEL: acc.shutdown + !CHECK-SAME: loc("{{.*}}locations.f90":72:11) + + end subroutine + + subroutine combined_directive_locations(arr) + real :: arr(:) + integer :: i + + !$acc parallel loop + do i = 1, size(arr) + arr(i) = arr(i) * arr(i) + end do + + !CHECK: acc.parallel + !CHECK: acc.loop + !CHECK: acc.yield loc("{{.*}}locations.f90":82:11) + !CHECK-NEXT: } {{.*}} loc(fused["{{.*}}locations.f90":82:11, "{{.*}}locations.f90":83:5]) + !CHECK: acc.yield loc("{{.*}}locations.f90":82:11) + !CHECK-NEXT: } loc("{{.*}}locations.f90":82:11) + end subroutine + + subroutine if_clause_expr_location(arr) + real :: arr(:) + integer :: i + + !$acc parallel loop if(.true.) + do i = 1, size(arr) + arr(i) = arr(i) * arr(i) + end do + + !CHECK: %{{.*}} = arith.constant true loc("{{.*}}locations.f90":99:25) + + !CHECK: acc.parallel + !CHECK: acc.loop + !CHECK: acc.yield loc("{{.*}}locations.f90":99:11) + !CHECK-NEXT: } {{.*}} loc(fused["{{.*}}locations.f90":99:11, "{{.*}}locations.f90":100:5]) + !CHECK: acc.yield loc("{{.*}}locations.f90":99:11) + !CHECK-NEXT: } loc("{{.*}}locations.f90":99:11) + end subroutine + + subroutine atomic_read_loc() + integer(4) :: x + integer(8) :: y + + !$acc atomic read + y = x + end + !CHECK: acc.atomic.read {{.*}} loc("{{.*}}locations.f90":118:11) + + subroutine atomic_capture_loc() + implicit none + integer :: k, v, i + + k = 1 + v = 0 + + !$acc atomic capture + v = k + k = (i + 1) * 3.14 + !$acc end atomic + +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read {{.*}} loc("{{.*}}locations.f90":130:11) +! CHECK: acc.atomic.write {{.*}} loc("{{.*}}locations.f90":130:11) +! CHECK: } loc("{{.*}}locations.f90":130:11) + + end subroutine + + subroutine atomic_update_loc() + implicit none + integer :: x, y, z + + !$acc atomic + y = y + 1 +! CHECK: acc.atomic.update %{{.*}} : !fir.ref { +! CHECK: ^bb0(%{{.*}}: i32 loc("{{.*}}locations.f90":142:3)): +! CHECK: } loc("{{.*}}locations.f90":142:3) + + !$acc atomic update + z = x * z + end subroutine + + subroutine acc_loop_fused_locations(arr) + real, dimension(10,10,10) :: arr + integer :: i, j, k + + !$acc loop collapse(3) + do i = 1, 10 + do j = 1, 10 + do k = 1, 10 + arr(i,j,k) = arr(i,j,k) * 2 + end do + end do + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_locationsPacc_loop_fused_locations +! CHECK: acc.loop +! CHECK: } attributes {collapse = [3]{{.*}}} loc(fused["{{.*}}locations.f90":160:11, "{{.*}}locations.f90":161:5, "{{.*}}locations.f90":162:7, "{{.*}}locations.f90":163:9]) + +end module + + diff --git a/flang/test/Lower/OpenACC/pre-fir-tree01.f90 b/flang/test/Lower/OpenACC/pre-fir-tree01.f90 new file mode 100644 index 00000000000000..b1b4205856dbcf --- /dev/null +++ b/flang/test/Lower/OpenACC/pre-fir-tree01.f90 @@ -0,0 +1,18 @@ +! RUN: bbc -fopenacc -pft-test -o %t %s | FileCheck %s +! RUN: %flang_fc1 -fopenacc -fdebug-dump-pft -o %t %s | FileCheck %s + +! Test structure of the Pre-FIR tree with OpenACC + +subroutine sub1(a, b, n) + real :: a(:), b(:) + integer :: n, i + !$acc parallel loop present(a, b) + do i = 1, n + b(i) = exp(a(i)) + end do +end subroutine + +! CHECK-LABEL: Subroutine sub1 +! CHECK: <> +! CHECK: <> +! CHECK: <> diff --git a/flang/test/Lower/OpenACC/stop-stmt-in-region.f90 b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90 new file mode 100644 index 00000000000000..2694a1531d1693 --- /dev/null +++ b/flang/test/Lower/OpenACC/stop-stmt-in-region.f90 @@ -0,0 +1,41 @@ +! This test checks lowering of stop statement in OpenACC region. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenacc %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPtest_stop_in_region1() { +! CHECK: acc.parallel { +! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = arith.constant false +! CHECK: %[[VAL_3:.*]] = fir.call @_FortranAStopStatement(%[[VAL_0]], %[[VAL_1]], %[[VAL_2]]) {{.*}} : (i32, i1, i1) -> none +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine test_stop_in_region1() + !$acc parallel + stop 1 + !$acc end parallel +end + +! CHECK-LABEL: func.func @_QPtest_stop_in_region2() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtest_stop_in_region2Ex"} +! CHECK: acc.parallel { +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_2:.*]] = arith.constant false +! CHECK: %[[VAL_3:.*]] = arith.constant false +! CHECK: %[[VAL_4:.*]] = fir.call @_FortranAStopStatement(%[[VAL_1]], %[[VAL_2]], %[[VAL_3]]) {{.*}} : (i32, i1, i1) -> none +! CHECK: acc.yield +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine test_stop_in_region2() + integer :: x + !$acc parallel + stop 1 + x = 2 + !$acc end parallel +end diff --git a/flang/test/Lower/branching-directive.f90 b/flang/test/Lower/branching-directive.f90 index 983c8b3701fbd8..69270d7bcbe96c 100644 --- a/flang/test/Lower/branching-directive.f90 +++ b/flang/test/Lower/branching-directive.f90 @@ -1,4 +1,4 @@ -!RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +!RUN: bbc -emit-hlfir -fopenacc -fopenmp -o - %s | FileCheck %s !https://github.com/llvm/llvm-project/issues/91526 @@ -57,3 +57,32 @@ subroutine simple2(x, yn) print *, E end subroutine +!CHECK-LABEL: func.func @_QPacccase +!CHECK: fir.select_case %{{[0-9]+}} : i32 [{{.*}}, ^bb[[CASE1:[0-9]+]], {{.*}}, ^bb[[CASE2:[0-9]+]], {{.*}}, ^bb[[CASE3:[0-9]+]]] +!CHECK: ^bb[[CASE1]]: +!CHECK: acc.serial +!CHECK: cf.br ^bb[[EXIT:[0-9]+]] +!CHECK: ^bb[[CASE2]]: +!CHECK: fir.call @_FortranAioOutputAscii +!CHECK: cf.br ^bb[[EXIT]] +!CHECK: ^bb[[CASE3]]: +!CHECK: fir.call @_FortranAioOutputAscii +!CHECK: cf.br ^bb[[EXIT]] +!CHECK: ^bb[[EXIT]]: +!CHECK: return +subroutine acccase(var) + integer :: var + integer :: res(10) + select case (var) + case (1) + print *, "case 1" + !$acc serial + res(1) = 1 + !$acc end serial + case (2) + print *, "case 2" + case default + print *, "case default" + end select +end subroutine + diff --git a/flang/test/Lower/pre-fir-tree05.f90 b/flang/test/Lower/pre-fir-tree05.f90 new file mode 100644 index 00000000000000..aeca3ab79ac9fd --- /dev/null +++ b/flang/test/Lower/pre-fir-tree05.f90 @@ -0,0 +1,50 @@ +! RUN: %flang_fc1 -fdebug-pre-fir-tree -fopenacc %s | FileCheck %s + +! Test structure of the Pre-FIR tree with OpenACC construct + +! CHECK: Subroutine foo +subroutine foo() + ! CHECK-NEXT: <> + ! CHECK-NEXT: <> + !$acc parallel + !$acc loop + ! CHECK-NEXT: <> + ! CHECK-NEXT: NonLabelDoStmt + do i=1,5 + ! CHECK-NEXT: PrintStmt + print *, "hey" + ! CHECK-NEXT: <> + ! CHECK-NEXT: NonLabelDoStmt + do j=1,5 + ! CHECK-NEXT: PrintStmt + print *, "hello", i, j + ! CHECK-NEXT: EndDoStmt + ! CHECK-NEXT: <> + end do + ! CHECK-NEXT: EndDoStmt + ! CHECK-NEXT: <> + end do + ! CHECK-NEXT: ContinueStmt + !$acc end parallel + ! CHECK-NEXT: <> + ! CHECK-NEXT: <> + ! CHECK-NEXT: EndSubroutineStmt +end subroutine +! CHECK-NEXT: End Subroutine foo + +! CHECK: Subroutine foo2 +subroutine foo2() + ! CHECK-NEXT: <> + !$acc parallel loop + ! CHECK-NEXT: <> + ! CHECK-NEXT: NonLabelDoStmt + do i=1,5 + ! CHECK-NEXT: EndDoStmt + ! CHECK-NEXT: <> + end do + ! CHECK-NEXT: ContinueStmt + !$acc end parallel loop + ! CHECK-NEXT: <> + ! CHECK-NEXT: EndSubroutineStmt +end subroutine +! CHECK-NEXT: End Subroutine foo2 diff --git a/flang/test/Lower/pre-fir-tree07.f90 b/flang/test/Lower/pre-fir-tree07.f90 new file mode 100644 index 00000000000000..2c61e2b9b76c35 --- /dev/null +++ b/flang/test/Lower/pre-fir-tree07.f90 @@ -0,0 +1,11 @@ +! RUN: %flang_fc1 -fdebug-pre-fir-tree -fopenacc %s | FileCheck %s + +! Test structure of the Pre-FIR tree with OpenACC declarative construct + +! CHECK: Module m: module m +module m + real, dimension(10) :: x + ! CHECK-NEXT: OpenACCDeclarativeConstruct + !$acc declare create(x) +end +! CHECK: End Module m diff --git a/flang/test/Lower/pre-fir-tree08.f b/flang/test/Lower/pre-fir-tree08.f new file mode 100755 index 00000000000000..a7ee4eb23fc0de --- /dev/null +++ b/flang/test/Lower/pre-fir-tree08.f @@ -0,0 +1,21 @@ +! RUN: %flang_fc1 -fdebug-pre-fir-tree -fopenacc %s | FileCheck %s + program rewrite_goto + integer b + + b = dummy(10) + + end + function dummy(a) + integer, a + + do 10 i=1,10 + 10 if(i .EQ. 1) GOTO 11 + i=0 + 11 dummy = a + i + return + end + +! CHECK: <> -> 5 +! CHECK: 2 ^IfStmt -> 5: 10if(i.eq.1)goto11 +! CHECK: 3 ^GotoStmt! -> 7: goto11 + diff --git a/flang/test/Parser/acc-unparse.f90 b/flang/test/Parser/acc-unparse.f90 new file mode 100644 index 00000000000000..62e0d4487f3f74 --- /dev/null +++ b/flang/test/Parser/acc-unparse.f90 @@ -0,0 +1,88 @@ +! RUN: %flang_fc1 -fopenacc -fdebug-unparse %s | FileCheck %s + +! Test unparse does not crash with OpenACC directives. + +! Test bug 47659 +program bug47659 + integer :: i, j + label1: do i = 1, 10 + !$acc parallel loop + do j = 1, 10 + if (j == 2) then + stop 1 + end if + end do + end do label1 +end program + +!CHECK-LABEL: PROGRAM bug47659 +!CHECK: !$ACC PARALLEL LOOP + + +subroutine acc_loop() + integer :: i, j + real :: a(10) + integer :: gangNum, gangDim, gangStatic + +!CHECK-LABEL: SUBROUTINE acc_loop + + !$acc loop collapse(force: 2) + do i = 1, 10 + do j = 1, 10 + end do + end do +!CHECK: !$ACC LOOP COLLAPSE(FORCE:2_4) + + !$acc loop gang + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG + + !$acc loop gang(gangNum) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(NUM:gangnum) + + !$acc loop gang(num: gangNum) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(NUM:gangnum) + + !$acc loop gang(dim: gangDim) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(DIM:gangdim) + + !$acc loop gang(static:gangStatic) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:gangstatic) + + !$acc loop gang(static:*) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:*) + + !$acc loop gang(static:gangStatic, dim: gangDim) + do i = 1, 10 + a(i) = i + end do +! CHECK: !$ACC LOOP GANG(STATIC:gangstatic,DIM:gangdim) + +end subroutine + +subroutine routine1() + !$acc routine bind("routine1_") +! CHECK: !$ACC ROUTINE BIND("routine1_") +end subroutine + +subroutine routine2() + !$acc routine(routine2) bind(routine2) +! CHECK: !$ACC ROUTINE(routine2) BIND(routine2) +end subroutine diff --git a/flang/test/Parser/continuation-in-conditional-compilation.f b/flang/test/Parser/continuation-in-conditional-compilation.f index 89617742c7cd25..987112301e335c 100644 --- a/flang/test/Parser/continuation-in-conditional-compilation.f +++ b/flang/test/Parser/continuation-in-conditional-compilation.f @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fopenmp -E %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fopenmp -fopenacc -E %s 2>&1 | FileCheck %s program main ! CHECK: k01=1+ 1 k01=1+ @@ -7,5 +7,10 @@ program main ! CHECK: !$omp parallel private(k01) !$omp parallel !$omp+ private(k01) +!$omp end parallel + +! CHECK-NOT: comment +!$omp parallel +!$acc+comment !$omp end parallel end diff --git a/flang/test/Preprocessing/pp132.f90 b/flang/test/Preprocessing/pp132.f90 index e53ea87c0f089e..418defb2d553ce 100644 --- a/flang/test/Preprocessing/pp132.f90 +++ b/flang/test/Preprocessing/pp132.f90 @@ -1,6 +1,8 @@ -! RUN: %flang -E -fopenmp %s 2>&1 | FileCheck %s +! RUN: %flang -E -fopenmp -fopenacc %s 2>&1 | FileCheck %s ! CHECK: !$OMP parallel default(shared) private(super_very_long_name_for_the_va& ! CHECK: !$OMP&riable) +! CHECK: !$acc data copyin(super_very_long_name_for_the_variable, another_super& +! CHECK: !$acc&_wordy_variable_to_test) ! Test correct continuations in compiler directives subroutine foo integer :: super_very_long_name_for_the_variable @@ -10,4 +12,7 @@ subroutine foo another_super_wordy_variable_to_test = super_very_long_name_for_the_variable * 2 !$OMP parallel default(shared) private(super_very_long_name_for_the_variable) !$omp end parallel + + !$acc data copyin(super_very_long_name_for_the_variable, another_super_wordy_variable_to_test) + !$acc end data end subroutine foo diff --git a/flang/test/Preprocessing/preprocessed-dirs.F90 b/flang/test/Preprocessing/preprocessed-dirs.F90 new file mode 100644 index 00000000000000..26253b62ff22c5 --- /dev/null +++ b/flang/test/Preprocessing/preprocessed-dirs.F90 @@ -0,0 +1,8 @@ +! RUN: %flang_fc1 -E -fopenacc %s 2>&1 | FileCheck %s +!CHECK: subroutine r4(x) Z real :: x Z !$acc routine Z print *, x Z end +#define SUB(s, t) subroutine s(x) Z\ + t :: x Z\ + !$acc routine Z\ + print *, x Z\ + end subroutine s +SUB(r4, real) diff --git a/flang/test/Preprocessing/sentinel-after-semi.F90 b/flang/test/Preprocessing/sentinel-after-semi.F90 new file mode 100644 index 00000000000000..75060ac1db0328 --- /dev/null +++ b/flang/test/Preprocessing/sentinel-after-semi.F90 @@ -0,0 +1,7 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenacc %s 2>&1 | FileCheck %s +! CHECK: !$ACC DECLARE COPYIN(var) +#define ACCDECLARE(var) integer :: var; \ + !$acc declare copyin(var) +program main + ACCDECLARE(var) +end program diff --git a/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 new file mode 100644 index 00000000000000..ba68031b0f18bc --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 @@ -0,0 +1,49 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.12 Atomic + +program openacc_atomic_validity + + implicit none + + integer :: i + integer, parameter :: N = 256 + integer, dimension(N) :: c + + + !$acc parallel + !$acc atomic update + c(i) = c(i) + 1 + + !$acc atomic update + c(i) = c(i) + 1 + !$acc end atomic + + !$acc atomic write + c(i) = 10 + + !$acc atomic write + c(i) = 10 + !$acc end atomic + + !$acc atomic read + i = c(i) + + !$acc atomic read + i = c(i) + !$acc end atomic + + !$acc atomic capture + c(i) = i + i = i + 1 + !$acc end atomic + + !$acc atomic update + !ERROR: RHS of atomic update statement must be scalar + !ERROR: LHS of atomic update statement must be scalar + c = c + 1 + + !$acc end parallel + +end program openacc_atomic_validity diff --git a/flang/test/Semantics/OpenACC/acc-branch.f90 b/flang/test/Semantics/OpenACC/acc-branch.f90 new file mode 100644 index 00000000000000..b3692d01658906 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-branch.f90 @@ -0,0 +1,199 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc -pedantic + +! Check OpenACC restruction in branch in and out of some construct +! +subroutine openacc_clause_validity + + implicit none + + integer :: i, j, k + integer :: N = 256 + real(8) :: a(256) + + !$acc parallel + !$acc loop + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a PARALLEL construct + return + end do + !$acc end parallel + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a PARALLEL LOOP construct + return + end do + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a SERIAL LOOP construct + return + end do + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a KERNELS LOOP construct + return + end do + + !$acc parallel + !$acc loop + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + exit + end if + end do + !$acc end parallel + + ! Exit branches out of parallel construct, not attached to an OpenACC parallel construct. + name1: do k=1, N + !$acc parallel + !$acc loop + outer: do i=1, N + inner: do j=1, N + ifname: if (j == 2) then + ! These are allowed. + exit + exit inner + exit outer + !ERROR: EXIT to construct 'name1' outside of PARALLEL construct is not allowed + exit name1 + ! Exit to construct other than loops. + exit ifname + end if ifname + end do inner + end do outer + !$acc end parallel + end do name1 + + ! Exit branches out of parallel construct, attached to an OpenACC parallel construct. + thisblk: BLOCK + fortname: if (.true.) then + !PORTABILITY: The construct name 'name1' should be distinct at the subprogram level + name1: do k = 1, N + !$acc parallel + !ERROR: EXIT to construct 'fortname' outside of PARALLEL construct is not allowed + exit fortname + !$acc loop + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + !ERROR: EXIT to construct 'name1' outside of PARALLEL construct is not allowed + exit name1 + end if + end do + + loop2: do i = 1, N + a(i) = 3.33 + !ERROR: EXIT to construct 'thisblk' outside of PARALLEL construct is not allowed + exit thisblk + end do loop2 + !$acc end parallel + end do name1 + end if fortname + end BLOCK thisblk + + !Exit branches inside OpenACC construct. + !$acc parallel + !$acc loop + do i = 1, N + a(i) = 3.14 + ifname: if (i == 2) then + ! This is allowed. + exit ifname + end if ifname + end do + !$acc end parallel + + !$acc parallel + !$acc loop + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + stop 999 ! no error + end if + end do + !$acc end parallel + + !$acc kernels + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a KERNELS construct + return + end do + !$acc end kernels + + !$acc kernels + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + exit + end if + end do + !$acc end kernels + + !$acc kernels + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + stop 999 ! no error + end if + end do + !$acc end kernels + + !$acc serial + do i = 1, N + a(i) = 3.14 + !ERROR: RETURN statement is not allowed in a SERIAL construct + return + end do + !$acc end serial + + !$acc serial + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + exit + end if + end do + !$acc end serial + + name2: do k=1, N + !$acc serial + do i = 1, N + ifname: if (.true.) then + print *, "LGTM" + a(i) = 3.14 + if(i == N-1) THEN + !ERROR: EXIT to construct 'name2' outside of SERIAL construct is not allowed + exit name2 + exit ifname + end if + end if ifname + end do + !$acc end serial + end do name2 + + !$acc serial + do i = 1, N + a(i) = 3.14 + if(i == N-1) THEN + stop 999 ! no error + end if + end do + !$acc end serial + + + !$acc data create(a) + + !ERROR: RETURN statement is not allowed in a DATA construct + if (size(a) == 10) return + + !$acc end data + +end subroutine openacc_clause_validity diff --git a/flang/test/Semantics/OpenACC/acc-cache-validity.f90 b/flang/test/Semantics/OpenACC/acc-cache-validity.f90 new file mode 100644 index 00000000000000..49f400e763bfb5 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-cache-validity.f90 @@ -0,0 +1,46 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.10 Cache + +program openacc_cache_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + end type atype + + integer :: i + integer, parameter :: N = 256 + real(8), dimension(N, N) :: aa + type(atype) :: t + type(atype), dimension(10) :: ta + real(8), dimension(N) :: a + + do i = 1, N + + !$acc cache(a(i)) + !$acc cache(a(1:2,3:4)) + !$acc cache(a) + !$acc cache(readonly: a, aa) + !$acc cache(readonly: a(i), aa(i, i)) + !$acc cache(t%arr) + !$acc cache(ta(1:2)%arr) + !$acc cache(ta(1:2)%arr(1:4)) + !$acc cache(i) + !$acc cache(t%s) + + !ERROR: Only array element or subarray are allowed in CACHE directive + !$acc cache(t) + + !ERROR: Only array element or subarray are allowed in CACHE directive + !$acc cache(/i/) + + end do + + !ERROR: The CACHE directive must be inside a loop + !$acc cache(a) + +end program openacc_cache_validity diff --git a/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 b/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 new file mode 100644 index 00000000000000..ced7dd46803eef --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 @@ -0,0 +1,103 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC canonalization validity for the construct defined below: +! 2.9 Loop +! 2.11 Parallel Loop +! 2.11 Kernels Loop +! 2.11 Serial Loop + +program openacc_clause_validity + + implicit none + + integer :: i, j + integer :: N = 256 + real(8) :: a(256) + real(8) :: aa(256, 256) + + i = 0 + + !ERROR: DO loop after the LOOP directive must have loop control + !$acc loop + do + end do + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel loop + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels loop + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial loop + + !ERROR: DO loop after the PARALLEL LOOP directive must have loop control + !$acc parallel loop + do + end do + + !ERROR: DO loop after the KERNELS LOOP directive must have loop control + !$acc kernels loop + do + end do + + !ERROR: DO loop after the SERIAL LOOP directive must have loop control + !$acc serial loop + do + end do + + !$acc parallel + !ERROR: The loop construct with the TILE clause must be followed by 2 tightly-nested loops + !$acc loop tile(2, 2) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !ERROR: The loop construct with the TILE clause must be followed by 2 tightly-nested loops + !$acc parallel loop tile(2, 2) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel + !ERROR: TILE and COLLAPSE clause may not appear on loop construct associated with DO CONCURRENT + !$acc loop collapse(2) + do concurrent (i = 1:N, j = 1:N) + aa(i, j) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: TILE and COLLAPSE clause may not appear on loop construct associated with DO CONCURRENT + !$acc loop tile(2, 2) + do concurrent (i = 1:N, j = 1:N) + aa(i, j) = 3.14 + end do + !$acc end parallel + +end program openacc_clause_validity diff --git a/flang/test/Semantics/OpenACC/acc-combined-loop.f90 b/flang/test/Semantics/OpenACC/acc-combined-loop.f90 new file mode 100644 index 00000000000000..77ff8e1cc603c8 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-combined-loop.f90 @@ -0,0 +1,33 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +program openacc_combined_loop + implicit none + integer :: i + + i = 1 + + !ERROR: A DO loop must follow the PARALLEL LOOP directive + !$acc parallel loop + i = 1 + + !ERROR: A DO loop must follow the KERNELS LOOP directive + !$acc kernels loop + i = 1 + + !ERROR: A DO loop must follow the SERIAL LOOP directive + !$acc serial loop + i = 1 + + !$acc parallel loop + do 10 i=0, n + 10 continue + + !$acc kernels loop + do 20 i=0, n + 20 continue + + !$acc serial loop + do 30 i=0, n + 30 continue + +end diff --git a/flang/test/Semantics/OpenACC/acc-data.f90 b/flang/test/Semantics/OpenACC/acc-data.f90 new file mode 100644 index 00000000000000..84eb72825b34cd --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-data.f90 @@ -0,0 +1,232 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc -pedantic + +! Check OpenACC clause validity for the following construct and directive: +! 2.6.5 Data +! 2.14.6 Enter Data +! 2.14.7 Exit Data + +program openacc_data_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + end type atype + + integer :: i, j, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + + real(8), dimension(N) :: a, f, g, h + + !ERROR: At least one of ATTACH, COPYIN, CREATE clause must appear on the ENTER DATA directive + !$acc enter data + + !ERROR: Modifier is not allowed for the COPYIN clause on the ENTER DATA directive + !$acc enter data copyin(zero: i) + + !ERROR: Only the ZERO modifier is allowed for the CREATE clause on the ENTER DATA directive + !$acc enter data create(readonly: i) + + !ERROR: COPYOUT clause is not allowed on the ENTER DATA directive + !$acc enter data copyin(i) copyout(i) + + !$acc enter data create(aa) if(.TRUE.) + + !$acc enter data create(a(1:10)) + + !$acc enter data create(t%arr) + + !$acc enter data create(t%arr(2:4)) + + !ERROR: At most one IF clause can appear on the ENTER DATA directive + !$acc enter data create(aa) if(.TRUE.) if(ifCondition) + + !$acc enter data create(aa) if(ifCondition) + + !$acc enter data create(aa) async + + !ERROR: At most one ASYNC clause can appear on the ENTER DATA directive + !$acc enter data create(aa) async async + + !$acc enter data create(aa) async(async1) + + !$acc enter data create(aa) async(1) + + !$acc enter data create(aa) wait(1) + + !$acc enter data create(aa) wait(wait1) + + !$acc enter data create(aa) wait(wait1, wait2) + + !$acc enter data create(aa) wait(wait1) wait(wait2) + + !ERROR: Argument `bb` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc enter data attach(bb) + + !ERROR: At least one of COPYOUT, DELETE, DETACH clause must appear on the EXIT DATA directive + !$acc exit data + + !ERROR: Modifier is not allowed for the COPYOUT clause on the EXIT DATA directive + !$acc exit data copyout(zero: i) + + !$acc exit data delete(aa) + + !$acc exit data delete(aa) finalize + + !ERROR: At most one FINALIZE clause can appear on the EXIT DATA directive + !$acc exit data delete(aa) finalize finalize + + !ERROR: Argument `cc` on the DETACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc exit data detach(cc) + + !ERROR: Argument on the DETACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc exit data detach(/i/) + + !$acc exit data copyout(bb) + + !$acc exit data delete(aa) if(.TRUE.) + + !$acc exit data delete(aa) if(ifCondition) + + !ERROR: At most one IF clause can appear on the EXIT DATA directive + !$acc exit data delete(aa) if(ifCondition) if(.TRUE.) + + !$acc exit data delete(aa) async + + !ERROR: At most one ASYNC clause can appear on the EXIT DATA directive + !$acc exit data delete(aa) async async + + !$acc exit data delete(aa) async(async1) + + !$acc exit data delete(aa) async(1) + + !$acc exit data delete(aa) wait(1) + + !$acc exit data delete(aa) wait(wait1) + + !$acc exit data delete(aa) wait(wait1, wait2) + + !$acc exit data delete(aa) wait(wait1) wait(wait2) + + !ERROR: Only the ZERO modifier is allowed for the COPYOUT clause on the DATA directive + !$acc data copyout(readonly: i) + !$acc end data + + !ERROR: At most one IF clause can appear on the DATA directive + !$acc data copy(i) if(.true.) if(.true.) + !$acc end data + + !ERROR: At least one of COPYOUT, DELETE, DETACH clause must appear on the EXIT DATA directive + !$acc exit data + + !PORTABILITY: At least one of ATTACH, COPY, COPYIN, COPYOUT, CREATE, DEFAULT, DEVICEPTR, NO_CREATE, PRESENT clause should appear on the DATA directive + !$acc data + !$acc end data + + !$acc data copy(aa) if(.true.) + !$acc end data + + !$acc data copy(aa) if(ifCondition) + !$acc end data + + !$acc data copy(aa, bb, cc) + !$acc end data + + !$acc data copyin(aa) copyin(readonly: bb) copyout(cc) + !$acc end data + + !$acc data copyin(readonly: aa, bb) copyout(zero: cc) + !$acc end data + + !$acc data create(aa, bb(:,:)) create(zero: cc(:,:)) + !$acc end data + + !$acc data no_create(aa) present(bb, cc) + !$acc end data + + !$acc data deviceptr(aa) attach(dd, p) + !$acc end data + + !$acc data copy(aa, bb) default(none) + !$acc end data + + !$acc data copy(aa, bb) default(present) + !$acc end data + + !ERROR: At most one DEFAULT clause can appear on the DATA directive + !$acc data copy(aa, bb) default(none) default(present) + !$acc end data + + !ERROR: At most one IF clause can appear on the DATA directive + !$acc data copy(aa) if(.true.) if(ifCondition) + !$acc end data + + !$acc data copyin(i) + !ERROR: Unmatched PARALLEL directive + !$acc end parallel + + !$acc data copy(aa) async + !$acc end data + + !$acc data copy(aa) wait + !$acc end data + + !$acc data copy(aa) device_type(default) wait + !$acc end data + + do i = 1, 100 + !$acc data copy(aa) + !ERROR: CYCLE to construct outside of DATA construct is not allowed + if (i == 10) cycle + !$acc end data + end do + + !$acc data copy(aa) + do i = 1, 100 + if (i == 10) cycle + end do + !$acc end data + +end program openacc_data_validity + +module mod1 + type :: t1 + integer :: a + contains + procedure :: t1_proc + end type + +contains + + + subroutine t1_proc(this) + class(t1) :: this + end subroutine + + subroutine sub4(t) + type(t1) :: t + + !ERROR: Only variables are allowed in data clauses on the DATA directive + !$acc data copy(t%t1_proc) + !$acc end data + end subroutine + + subroutine sub5() + integer, parameter :: iparam = 1024 + !$acc data copyin(iparam) + !$acc end data + end subroutine +end module diff --git a/flang/test/Semantics/OpenACC/acc-declare-validity.f90 b/flang/test/Semantics/OpenACC/acc-declare-validity.f90 new file mode 100644 index 00000000000000..2e7e651815d4a3 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-declare-validity.f90 @@ -0,0 +1,74 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.13 Declare + +module openacc_declare_validity + + implicit none + + real(8), dimension(10) :: aa, bb, ab, ac, ad, ae, af, cc, dd + + !ERROR: At least one clause is required on the DECLARE directive + !$acc declare + + !$acc declare create(aa, bb) + + !WARNING: 'aa' in the CREATE clause is already present in the same clause in this module + !$acc declare create(aa) + + !$acc declare link(ab) + + !$acc declare device_resident(cc) + + !ERROR: COPYOUT clause is not allowed on the DECLARE directive in module declaration section + !$acc declare copyout(ac) + + !ERROR: COPY clause is not allowed on the DECLARE directive in module declaration section + !$acc declare copy(af) + + !ERROR: PRESENT clause is not allowed on the DECLARE directive in module declaration section + !$acc declare present(ad) + + !ERROR: DEVICEPTR clause is not allowed on the DECLARE directive in module declaration section + !$acc declare deviceptr(ae) + + !ERROR: The ZERO modifier is not allowed for the CREATE clause on the DECLARE directive + !$acc declare create(zero: dd) + + !ERROR: 'bb' in the COPYIN clause is already present in another CREATE clause in this module + !$acc declare copyin(bb) + +contains + + subroutine sub1(cc, dd) + real(8) :: cc(:) + real(8) :: dd(:) + !$acc declare present(cc, dd) + !ERROR: 'cc' in the CREATE clause is already present in another PRESENT clause in this module + !$acc declare create(cc) + end subroutine sub1 + + function fct1(ee, ff, gg, hh, ii) + integer :: fct1 + real(8), intent(in) :: ee(:) + !$acc declare copyin(readonly: ee) + real(8) :: ff(:), hh(:), ii(:,:) + !$acc declare link(hh) device_resident(ii) + real(8), intent(out) :: gg(:) + !$acc declare copy(ff) copyout(gg) + end function fct1 + + subroutine sub2(cc) + real(8), dimension(*) :: cc + !ERROR: Assumed-size dummy arrays may not appear on the DECLARE directive + !$acc declare present(cc) + end subroutine sub2 + + subroutine sub3() + real :: aa(100) + !ERROR: The ZERO modifier is not allowed for the COPYOUT clause on the DECLARE directive + !$acc declare copyout(zero: aa) + end subroutine + +end module openacc_declare_validity diff --git a/flang/test/Semantics/OpenACC/acc-error.f90 b/flang/test/Semantics/OpenACC/acc-error.f90 new file mode 100644 index 00000000000000..69ee59f97ec6b3 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-error.f90 @@ -0,0 +1,29 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check parser specific error for OpenACC + + +subroutine test(a, n) + integer :: a(n) + !ERROR: expected OpenACC directive + !$acc p + integer :: i,j + + i = 0 + !ERROR: expected OpenACC directive + !$acc p + end subroutine + +subroutine test2(a, n) + integer :: a(n) + integer :: i + + !$acc parallel + !$acc loop + DO i = 1, n + END DO + !$acc end parallel + !WARN: Misplaced OpenACC end directive + !$acc end loop + +end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-host-data.f90 b/flang/test/Semantics/OpenACC/acc-host-data.f90 new file mode 100644 index 00000000000000..4e9167722a228b --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-host-data.f90 @@ -0,0 +1,41 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.8 host_data + +program openacc_host_data_validity + + implicit none + + integer, parameter :: N = 256 + real(8), dimension(N, N) :: aa, bb + logical :: ifCondition = .TRUE. + + !ERROR: At least one of USE_DEVICE clause must appear on the HOST_DATA directive + !$acc host_data + !$acc end host_data + + !$acc host_data use_device(aa) + !$acc end host_data + + !$acc host_data use_device(aa) if(.true.) + !$acc end host_data + + !$acc host_data use_device(aa) if(ifCondition) + !$acc end host_data + + !$acc host_data use_device(aa, bb) if_present + !$acc end host_data + + !ERROR: At most one IF_PRESENT clause can appear on the HOST_DATA directive + !$acc host_data use_device(aa, bb) if_present if_present + !$acc end host_data + + !$acc host_data use_device(aa, bb) if(.true.) if_present + !$acc end host_data + + !ERROR: At most one IF clause can appear on the HOST_DATA directive + !$acc host_data use_device(aa, bb) if(.true.) if(ifCondition) + !$acc end host_data + +end program openacc_host_data_validity diff --git a/flang/test/Semantics/OpenACC/acc-init-validity.f90 b/flang/test/Semantics/OpenACC/acc-init-validity.f90 new file mode 100644 index 00000000000000..3b594a25217c09 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-init-validity.f90 @@ -0,0 +1,102 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.14.1 Init + +program openacc_init_validity + + implicit none + + integer :: i, j + integer, parameter :: N = 256 + logical :: ifCondition = .TRUE. + integer :: ifInt + real :: ifReal + real(8), dimension(N) :: a + + !$acc init + !$acc init if(.TRUE.) + !$acc init if(ifCondition) + !$acc init if(ifInt) + !$acc init device_num(1) + !$acc init device_num(i) + !$acc init device_type(default) + !$acc init device_type(nvidia, radeon) + !$acc init device_num(i) device_type(host, multicore) if(ifCondition) + + !$acc parallel + !ERROR: Directive INIT may not be called within a compute region + !$acc init + !$acc end parallel + + !$acc serial + !ERROR: Directive INIT may not be called within a compute region + !$acc init + !$acc end serial + + !$acc kernels + !ERROR: Directive INIT may not be called within a compute region + !$acc init + !$acc end kernels + + !$acc parallel + !$acc loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + !$acc end parallel + + !$acc serial + !$acc loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + !$acc end serial + + !$acc kernels + !$acc loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + !$acc end kernels + + !$acc parallel loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + + !$acc serial loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + !ERROR: Directive INIT may not be called within a compute region + !$acc init + a(i) = 3.14 + end do + + !ERROR: At most one IF clause can appear on the INIT directive + !$acc init if(.TRUE.) if(ifCondition) + + !ERROR: At most one DEVICE_NUM clause can appear on the INIT directive + !$acc init device_num(1) device_num(i) + + !ERROR: At most one DEVICE_TYPE clause can appear on the INIT directive + !$acc init device_type(nvidia) device_type(default, *) + + !ERROR: Must have LOGICAL or INTEGER type + !$acc init if(ifReal) + +end program openacc_init_validity diff --git a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 new file mode 100644 index 00000000000000..8653978fb6249d --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 @@ -0,0 +1,298 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.11 Kernels Loop + +program openacc_kernels_loop_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + end type atype + + integer :: i, j, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + + real(8), dimension(N) :: a, f, g, h + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels loop + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels loop + + !$acc kernels loop num_gangs(8) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_gangs(gang_size) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_gangs(8) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_workers(worker_size) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_workers(8) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop vector_length(vector_size) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop vector_length(128) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_gangs(gang_size) + do i = 1, N + a(i) = 3.14 + end do + + + !$acc kernels loop if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop if(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + !ERROR: Unmatched END SERIAL LOOP directive + !$acc end serial loop + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the KERNELS LOOP directive + !$acc kernels loop device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels loop + + !$acc kernels loop async + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop async(1) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop async(async1) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(wait1) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(wait1, wait2) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(wait1) wait(wait2) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(1, 2) async(3) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(queues: 1, 2) async(3) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(devnum: 1: 1, 2) async(3) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop wait(devnum: 1: queues: 1, 2) async(3) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_gangs(8) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop num_workers(8) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop vector_length(128) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop if(.true.) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop if(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: At most one IF clause can appear on the KERNELS LOOP directive + !$acc kernels loop if(.true.) if(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop self + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop self(.true.) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop self(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop copy(aa) copyin(bb) copyout(cc) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop copy(aa, bb) copyout(zero: cc) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop present(aa, bb) create(cc) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop copyin(readonly: aa, bb) create(zero: cc) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop deviceptr(aa, bb) no_create(cc) + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: Argument `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc kernels loop attach(aa, dd, p) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop private(aa, bb, cc) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop default(none) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop default(present) + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: At most one DEFAULT clause can appear on the KERNELS LOOP directive + !$acc kernels loop default(none) default(present) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop device_type(*) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop device_type(multicore) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop device_type(host, multicore) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop device_type(*) async wait num_gangs(8) num_workers(8) vector_length(128) + do i = 1, N + a(i) = 3.14 + end do + + !$acc kernels loop device_type(*) async + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the KERNELS LOOP directive + !$acc kernels loop device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop + do i = 1, N + if(i == 10) cycle + end do + +end program openacc_kernels_loop_validity diff --git a/flang/test/Semantics/OpenACC/acc-kernels.f90 b/flang/test/Semantics/OpenACC/acc-kernels.f90 new file mode 100644 index 00000000000000..8a209040a77936 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-kernels.f90 @@ -0,0 +1,160 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.5.3 Kernels + +program openacc_kernels_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + end type atype + + integer :: i, j, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + real(8), dimension(N) :: a, f, g, h + + !$acc kernels async + !$acc end kernels + + !$acc kernels async(1) + !$acc end kernels + + !$acc kernels async(async1) + !$acc end kernels + + !$acc kernels wait(wait1) + !$acc end kernels + + !$acc kernels wait(wait1, wait2) + !$acc end kernels + + !$acc kernels wait(1, 2) async(3) + !$acc end kernels + + !$acc kernels wait(queues: 1, 2) async(3) + !$acc end kernels + + !$acc kernels wait(1) wait(2) async(3) + !$acc end kernels + + !$acc kernels wait(devnum: 1: 1, 2) async(3) + !$acc end kernels + + !$acc kernels wait(devnum: 1: queues: 1, 2) async(3) + !$acc end kernels + + !$acc kernels num_gangs(8) + !$acc end kernels + + !$acc kernels num_workers(8) + !$acc end kernels + + !$acc kernels vector_length(128) + !$acc end kernels + + !$acc kernels if(.true.) + !$acc end kernels + + !$acc kernels if(ifCondition) + !$acc end kernels + + !ERROR: At most one IF clause can appear on the KERNELS directive + !$acc kernels if(.true.) if(ifCondition) + !$acc end kernels + + !$acc kernels self + !$acc end kernels + + !$acc kernels self(.true.) + !$acc end kernels + + !$acc kernels self(ifCondition) + !$acc end kernels + + !$acc kernels copy(aa) copyin(bb) copyout(cc) + !$acc end kernels + + !$acc kernels copy(aa, bb) copyout(zero: cc) + !$acc end kernels + + !$acc kernels present(aa, bb) create(cc) + !$acc end kernels + + !$acc kernels copyin(readonly: aa, bb) create(zero: cc) + !$acc end kernels + + !$acc kernels deviceptr(aa, bb) no_create(cc) + !$acc end kernels + + !ERROR: Argument `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc kernels attach(dd, p, aa) + !$acc end kernels + + !ERROR: PRIVATE clause is not allowed on the KERNELS directive + !$acc kernels private(aa, bb, cc) + !$acc end kernels + + !$acc kernels default(none) + !$acc end kernels + + !$acc kernels default(present) + !$acc end kernels + + !ERROR: At most one DEFAULT clause can appear on the KERNELS directive + !$acc kernels default(none) default(present) + !$acc end kernels + + !$acc kernels device_type(*) + !$acc end kernels + + !$acc kernels device_type(default) + !$acc end kernels + + !$acc kernels device_type(default, host) + !$acc end kernels + + !$acc kernels device_type(*) async wait num_gangs(8) num_workers(8) vector_length(128) + !$acc end kernels + + !$acc kernels device_type(*) async + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the KERNELS directive + !$acc kernels device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + !$acc end kernels + + do i = 1, 100 + !$acc kernels + !ERROR: CYCLE to construct outside of KERNELS construct is not allowed + if (i == 10) cycle + !$acc end kernels + end do + + !$acc kernels + do i = 1, 100 + if (i == 10) cycle + end do + !$acc end kernels + +end program openacc_kernels_validity diff --git a/flang/test/Semantics/OpenACC/acc-loop-validity.f90 b/flang/test/Semantics/OpenACC/acc-loop-validity.f90 new file mode 100644 index 00000000000000..205e67a4728fcb --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-loop-validity.f90 @@ -0,0 +1,19 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +program openacc_clause_validity + + implicit none + + integer :: i, n + + i = 0 + + !ERROR: A DO loop must follow the LOOP directive + !$acc loop + i = 1 + + !$acc loop + do 100 i=0, n + 100 continue + +end diff --git a/flang/test/Semantics/OpenACC/acc-loop.f90 b/flang/test/Semantics/OpenACC/acc-loop.f90 new file mode 100644 index 00000000000000..859cf3feec0d67 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-loop.f90 @@ -0,0 +1,358 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.9 Loop + +program openacc_loop_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + integer :: n + end type atype + + integer :: i, j, k, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + + real(8), dimension(N) :: a, f, g, h + + !$acc parallel + !$acc loop tile(2) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel device_type(*) num_gangs(2) + !$acc loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop seq + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop independent + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop auto + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: At most one VECTOR clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !$acc loop vector vector(128) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop vector + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop vector(10) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop vector(vector_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop vector(length: vector_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: At most one WORKER clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !$acc loop worker worker(10) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop worker + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop worker(10) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop worker(worker_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop worker(num: worker_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: At most one GANG clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !$acc loop gang gang(gang_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc loop gang device_type(default) gang(gang_size) + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: At most one GANG clause can appear on the PARALLEL LOOP directive or in group separated by the DEVICE_TYPE clause + !$acc parallel loop gang gang(gang_size) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop gang device_type(default) gang(gang_size) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel + !$acc loop gang(gang_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop gang(num: gang_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop gang(gang_size, static:*) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop gang(num: gang_size, static:*) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop gang(num: gang_size, static: gang_size) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !$acc loop private(b, a(:)) + do i = 1, N + a(i) = b + end do + !$acc end parallel + + !$acc parallel + !$acc loop tile(*) + do i = 1, N + a(i) = b + end do + !$acc end parallel + + !$acc parallel + !$acc loop tile(2, 2) + do i = 1, N + do j = 1, N + a(i) = b + end do + end do + !$acc end parallel + + !$acc parallel + !ERROR: The parameter of the COLLAPSE clause must be a constant positive integer expression + !$acc loop collapse(-1) + do i = 1, N + do j = 1, N + a(i) = 3.14 + j + end do + end do + !$acc end parallel + + !$acc parallel + !ERROR: Clause PRIVATE is not allowed after clause DEVICE_TYPE on the LOOP directive + !$acc loop device_type(*) private(i) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: Clause GANG is not allowed if clause SEQ appears on the LOOP directive + !$acc loop gang seq + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: Clause WORKER is not allowed if clause SEQ appears on the LOOP directive + !$acc loop worker seq + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel + !ERROR: Clause VECTOR is not allowed if clause SEQ appears on the LOOP directive + !$acc loop vector seq + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the PARALLEL directive + !$acc parallel device_type(*) if(.TRUE.) + !$acc loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc loop collapse(2) + do i = 1, N + !ERROR: Loop control is not present in the DO LOOP + do + a(i) = 3.14 + end do + end do + + !ERROR: The num argument is not allowed when dim is specified + !$acc loop gang(1, dim: 2) + do i = 1, N + end do + + !$acc loop + do i = 1, N + end do + !$acc end loop + + !$acc loop collapse(2) + do i = 1, 10 + !ERROR: LOOP directive not expected in COLLAPSE loop nest + !$acc loop + do j = 1, 10 + end do + end do + + !$acc parallel + !$acc loop + do i = 1, n + if(i == 10) cycle + end do + !$acc end parallel + + !$acc loop gang device_type(nvidia) gang(num: 8) + DO i = 1, n + END DO + + !$acc loop vector device_type(default) vector(16) + DO i = 1, n + END DO + + !$acc loop worker device_type(*) worker(8) + DO i = 1, n + END DO + + !$acc loop device_type(multicore) collapse(2) + DO i = 1, n + DO j = 1, n + END DO + END DO + + !ERROR: Trip count must be computable and invariant + !$acc loop collapse(2) + DO i = 1, n + DO j = 1, c(i) + END DO + END DO + + !ERROR: Trip count must be computable and invariant + !$acc loop collapse(2) + DO i = 1, n + DO j = 1, i + END DO + END DO + + !ERROR: Trip count must be computable and invariant + !$acc loop collapse(2) + DO i = 1, n + DO j = 1, ta(i)%n + END DO + END DO + + !ERROR: Trip count must be computable and invariant + !$acc parallel loop collapse(2) + DO i = 1, n + DO j = 1, ta(i)%n + END DO + END DO + + !ERROR: Trip count must be computable and invariant + !$acc loop collapse(3) + DO i = 1, n + DO j = 1, n + DO k = 1, i + END DO + END DO + END DO + +end program openacc_loop_validity diff --git a/flang/test/Semantics/OpenACC/acc-module.f90 b/flang/test/Semantics/OpenACC/acc-module.f90 new file mode 100644 index 00000000000000..7f034d8ae54f0a --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-module.f90 @@ -0,0 +1,123 @@ +! RUN: %python %S/../test_modfile.py %s %flang_fc1 -fopenacc + +module acc_mod + real :: data_create(100) + !$acc declare create(data_create) + + real :: data_copyin(10) + !$acc declare copyin(data_copyin) + + real :: data_copyinro(10) + !$acc declare copyin(readonly: data_copyinro) + + real :: data_device_resident(20) + !$acc declare device_resident(data_device_resident) + + integer :: data_link(50) + !$acc declare link(data_link) + + !$acc routine(sub10) seq + +contains + subroutine sub1() + !$acc routine + end subroutine + + subroutine sub2() + !$acc routine seq + end subroutine + + subroutine sub3() + !$acc routine gang + end subroutine + + subroutine sub4() + !$acc routine vector + end subroutine + + subroutine sub5() + !$acc routine worker + end subroutine + + subroutine sub6() + !$acc routine gang(dim:2) + end subroutine + + subroutine sub7() + !$acc routine bind("sub7_") + end subroutine + + subroutine sub8() + !$acc routine bind(sub7) + end subroutine + + subroutine sub9() + !$acc routine vector + !$acc routine seq bind(sub7) + !$acc routine gang bind(sub8) + end subroutine + + subroutine sub10() + end subroutine + + subroutine sub11() + !$acc routine device_type(nvidia) gang device_type(*) seq + end subroutine + + subroutine sub12() + !$acc routine device_type(host) bind(sub7) device_type(multicore) bind(sub8) + end subroutine +end module + +!Expect: acc_mod.mod +! module acc_mod +! real(4)::data_create(1_8:100_8) +! !$acc declare create(data_create) +! real(4)::data_copyin(1_8:10_8) +! !$acc declare copyin(data_copyin) +! real(4)::data_copyinro(1_8:10_8) +! !$acc declare copyin(readonly: data_copyinro) +! real(4)::data_device_resident(1_8:20_8) +! !$acc declare device_resident(data_device_resident) +! integer(4)::data_link(1_8:50_8) +! !$acc declare link(data_link) +! contains +! subroutine sub1() +! !$acc routine +! end +! subroutine sub2() +! !$acc routine seq +! end +! subroutine sub3() +! !$acc routine gang +! end +! subroutine sub4() +! !$acc routine vector +! end +! subroutine sub5() +! !$acc routine worker +! end +! subroutine sub6() +! !$acc routine gang(dim:2) +! end +! subroutine sub7() +! !$acc routine bind("sub7_") +! end +! subroutine sub8() +! !$acc routine bind(sub7) +! end +! subroutine sub9() +! !$acc routine vector +! !$acc routine seq bind(sub7) +! !$acc routine gang bind(sub8) +! end +! subroutine sub10() +! !$acc routine seq +! end +! subroutinesub11() +! !$acc routine device_type(nvidia) gang device_type(*) seq +! end +! subroutinesub12() +! !$acc routine device_type(host) bind(sub7) device_type(multicore) bind(sub8) +! end +! end diff --git a/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 b/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 new file mode 100644 index 00000000000000..7f33f9e145110c --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 @@ -0,0 +1,144 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.11 Parallel Loop + +program openacc_parallel_loop_validity + + implicit none + + integer :: i, j, b + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + real :: reduction_r + logical :: reduction_l + logical :: ifCondition = .TRUE. + real(8), dimension(N) :: a, f, g, h + real(8), dimension(N, N) :: aa, bb, cc + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel loop + + !$acc parallel loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel loop tile(2) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop self + do i = 1, N + a(i) = 3.14 + end do + + !ERROR: SELF clause on the PARALLEL LOOP directive only accepts optional scalar logical expression + !$acc parallel loop self(bb, cc(:,:)) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop self(.true.) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop self(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + + !$acc parallel loop tile(2, 2) + do i = 1, N + do j = 1, N + aa(i, j) = 3.14 + end do + end do + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the PARALLEL LOOP directive + !$acc parallel loop device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel loop + + !$acc kernels loop + do i = 1, N + a(i) = 3.14 + end do + !ERROR: Unmatched END PARALLEL LOOP directive + !$acc end parallel loop + + !$acc parallel loop reduction(+: reduction_r) + do i = 1, N + reduction_r = a(i) + i + end do + + !$acc parallel loop reduction(*: reduction_r) + do i = 1, N + reduction_r = reduction_r * (a(i) + i) + end do + + !$acc parallel loop reduction(min: reduction_r) + do i = 1, N + reduction_r = min(reduction_r, a(i) * i) + end do + + !$acc parallel loop reduction(max: reduction_r) + do i = 1, N + reduction_r = max(reduction_r, a(i) * i) + end do + + !$acc parallel loop reduction(iand: b) + do i = 1, N + b = iand(b, c(i)) + end do + + !$acc parallel loop reduction(ior: b) + do i = 1, N + b = ior(b, c(i)) + end do + + !$acc parallel loop reduction(ieor: b) + do i = 1, N + b = ieor(b, c(i)) + end do + + !$acc parallel loop reduction(.and.: reduction_l) + do i = 1, N + reduction_l = d(i) .and. e(i) + end do + + !$acc parallel loop reduction(.or.: reduction_l) + do i = 1, N + reduction_l = d(i) .or. e(i) + end do + + !$acc parallel loop reduction(.eqv.: reduction_l) + do i = 1, N + reduction_l = d(i) .eqv. e(i) + end do + + !$acc parallel loop reduction(.neqv.: reduction_l) + do i = 1, N + reduction_l = d(i) .neqv. e(i) + end do + + !$acc parallel loop + do i = 1, N + if(i == 10) cycle + end do + +end program openacc_parallel_loop_validity diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90 new file mode 100644 index 00000000000000..3f17d8fc862a67 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-parallel.f90 @@ -0,0 +1,191 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.5.1 Parallel + +program openacc_parallel_validity + + implicit none + + integer :: i, j, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p + logical :: ifCondition = .TRUE. + real(8), dimension(N) :: a, f, g, h + + !$acc parallel device_type(*) num_gangs(2) + !$acc loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + !$acc parallel async + !$acc end parallel + + !$acc parallel async(1) + !$acc end parallel + + !$acc parallel async(async1) + !$acc end parallel + + !$acc parallel wait + !$acc end parallel + + !$acc parallel wait(1) + !$acc end parallel + + !$acc parallel wait(wait1) + !$acc end parallel + + !$acc parallel wait(1,2) + !$acc end parallel + + !$acc parallel wait(wait1, wait2) + !$acc end parallel + + !$acc parallel num_gangs(8) + !$acc end parallel + + !ERROR: NUM_GANGS clause accepts a maximum of 3 arguments + !$acc parallel num_gangs(1, 1, 1, 1) + !$acc end parallel + + !$acc parallel num_workers(8) + !$acc end parallel + + !$acc parallel vector_length(128) + !$acc end parallel + + !$acc parallel if(.true.) + !$acc end parallel + + !$acc parallel if(ifCondition) + !$acc end parallel + + !$acc parallel self + !$acc end parallel + + !$acc parallel self(.true.) + !$acc end parallel + + !$acc parallel self(ifCondition) + !$acc end parallel + + !$acc parallel copy(aa) copyin(bb) copyout(cc) + !$acc end parallel + + !$acc parallel copy(aa, bb) copyout(zero: cc) + !$acc end parallel + + !$acc parallel present(aa, bb) create(cc) + !$acc end parallel + + !$acc parallel copyin(readonly: aa, bb) create(zero: cc) + !$acc end parallel + + !$acc parallel deviceptr(aa, bb) no_create(cc) + !$acc end parallel + + !ERROR: Argument `cc` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc parallel attach(dd, p, cc) + !$acc end parallel + + !$acc parallel private(aa) firstprivate(bb, cc) + !$acc end parallel + + !$acc parallel default(none) + !$acc end parallel + + !$acc parallel default(present) + !$acc end parallel + + !$acc parallel device_type(*) + !$acc end parallel + + !$acc parallel device_type(default) + !$acc end parallel + + !$acc parallel device_type(default, host) + !$acc end parallel + + !ERROR: Clause PRIVATE is not allowed after clause DEVICE_TYPE on the PARALLEL directive + !ERROR: Clause FIRSTPRIVATE is not allowed after clause DEVICE_TYPE on the PARALLEL directive + !$acc parallel device_type(*) private(aa) firstprivate(bb) + !$acc end parallel + + !$acc parallel device_type(*) async + !$acc end parallel + + !$acc parallel device_type(*) wait + !$acc end parallel + + !$acc parallel device_type(*) num_gangs(8) + !$acc end parallel + + !$acc parallel device_type(*) async device_type(host) wait + !$acc end parallel + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the PARALLEL directive + !$acc parallel device_type(*) if(.TRUE.) + !$acc loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end parallel + + do i = 1, 100 + !$acc parallel + !ERROR: CYCLE to construct outside of PARALLEL construct is not allowed + if (i == 10) cycle + !$acc end parallel + end do + + !$acc parallel + do i = 1, 100 + if (i == 10) cycle + end do + !$acc end parallel + + !ERROR: At most one NUM_GANGS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel num_gangs(400) num_gangs(400) + !$acc end parallel + + !ERROR: At most one NUM_GANGS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel device_type(nvidia) num_gangs(400) num_gangs(200) + !$acc end parallel + + !$acc parallel device_type(nvidia) num_gangs(400) device_type(radeon) num_gangs(200) + !$acc end parallel + + !ERROR: At most one NUM_WORKERS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel num_workers(8) num_workers(4) + !$acc end parallel + + !ERROR: At most one NUM_WORKERS clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel device_type(nvidia) num_workers(8) num_workers(4) + !$acc end parallel + + !$acc parallel device_type(nvidia) num_workers(8) device_type(radeon) num_workers(4) + !$acc end parallel + + !ERROR: At most one VECTOR_LENGTH clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel vector_length(128) vector_length(124) + !$acc end parallel + + !ERROR: At most one VECTOR_LENGTH clause can appear on the PARALLEL directive or in group separated by the DEVICE_TYPE clause + !$acc parallel device_type(nvidia) vector_length(256) vector_length(128) + !$acc end parallel + + !$acc parallel device_type(nvidia) vector_length(256) device_type(radeon) vector_length(128) + !$acc end parallel + +end program openacc_parallel_validity diff --git a/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 new file mode 100644 index 00000000000000..ccd009bffa2e24 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-reduction-validity.f90 @@ -0,0 +1,172 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC reduction validity. + +program openacc_reduction_validity + + integer :: i + real :: r + complex :: c + logical :: l + + !$acc parallel reduction(+:i) + !$acc end parallel + + !$acc parallel reduction(*:i) + !$acc end parallel + + !$acc parallel reduction(min:i) + !$acc end parallel + + !$acc parallel reduction(max:i) + !$acc end parallel + + !$acc parallel reduction(iand:i) + !$acc end parallel + + !$acc parallel reduction(ior:i) + !$acc end parallel + + !$acc parallel reduction(ieor:i) + !$acc end parallel + + !ERROR: reduction operator not supported for integer type + !$acc parallel reduction(.and.:i) + !$acc end parallel + + !ERROR: reduction operator not supported for integer type + !$acc parallel reduction(.or.:i) + !$acc end parallel + + !ERROR: reduction operator not supported for integer type + !$acc parallel reduction(.eqv.:i) + !$acc end parallel + + !ERROR: reduction operator not supported for integer type + !$acc parallel reduction(.neqv.:i) + !$acc end parallel + + !$acc parallel reduction(+:r) + !$acc end parallel + + !$acc parallel reduction(*:r) + !$acc end parallel + + !$acc parallel reduction(min:r) + !$acc end parallel + + !$acc parallel reduction(max:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(iand:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(ior:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(ieor:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(.and.:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(.or.:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(.eqv.:r) + !$acc end parallel + + !ERROR: reduction operator not supported for real type + !$acc parallel reduction(.neqv.:r) + !$acc end parallel + + !$acc parallel reduction(+:c) + !$acc end parallel + + !$acc parallel reduction(*:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(min:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(max:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(iand:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(ior:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(ieor:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(.and.:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(.or.:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(.eqv.:c) + !$acc end parallel + + !ERROR: reduction operator not supported for complex type + !$acc parallel reduction(.neqv.:c) + !$acc end parallel + + !$acc parallel reduction(.and.:l) + !$acc end parallel + + !$acc parallel reduction(.or.:l) + !$acc end parallel + + !$acc parallel reduction(.eqv.:l) + !$acc end parallel + + !$acc parallel reduction(.neqv.:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(+:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(*:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(min:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(max:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(iand:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(ior:l) + !$acc end parallel + + !ERROR: reduction operator not supported for logical type + !$acc parallel reduction(ieor:l) + !$acc end parallel + + +end program diff --git a/flang/test/Semantics/OpenACC/acc-resolve01.f90 b/flang/test/Semantics/OpenACC/acc-resolve01.f90 new file mode 100644 index 00000000000000..4d85c26990c1c1 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-resolve01.f90 @@ -0,0 +1,22 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Data-Mapping Attribute Clauses +! 2.15.14 default Clause + +subroutine default_none() + integer a(3) + + A = 1 + B = 2 + !$acc parallel default(none) private(c) + !ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-mapping clause + A(1:2) = 3 + !ERROR: The DEFAULT(NONE) clause requires that 'b' must be listed in a data-mapping clause + B = 4 + C = 5 + !$acc end parallel +end subroutine default_none + +program mm + call default_none() +end diff --git a/flang/test/Semantics/OpenACC/acc-resolve02.f90 b/flang/test/Semantics/OpenACC/acc-resolve02.f90 new file mode 100644 index 00000000000000..861cb26e31a30b --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-resolve02.f90 @@ -0,0 +1,17 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +subroutine compute() + integer :: a(3), c, i + + a = 1 + !ERROR: 'c' appears in more than one data-sharing clause on the same OpenACC directive + !$acc parallel firstprivate(c) private(c) + do i = 1, 3 + a(i) = c + end do + !$acc end parallel +end subroutine compute + +program mm + call compute() +end diff --git a/flang/test/Semantics/OpenACC/acc-resolve03.f90 b/flang/test/Semantics/OpenACC/acc-resolve03.f90 new file mode 100644 index 00000000000000..341e9d2ce68b2e --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-resolve03.f90 @@ -0,0 +1,21 @@ +! RUN: %flang_fc1 -fopenacc %s +! A regression test to check that +! arbitrary compiler directives do not generate errors +! inside OpenACC collapsed loops +subroutine foo + integer, parameter :: loop_bound = 42 + integer :: a + integer :: b + integer :: c + + !$acc parallel + do a = 0, loop_bound + !$acc loop collapse(2) + do b = 0, loop_bound + !dir$ ivdep + do c = 0, loop_bound + enddo + enddo + enddo + !$acc end parallel +end subroutine foo diff --git a/flang/test/Semantics/OpenACC/acc-resolve04.f90 b/flang/test/Semantics/OpenACC/acc-resolve04.f90 new file mode 100644 index 00000000000000..8a72630a2ec9ff --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-resolve04.f90 @@ -0,0 +1,34 @@ +! RUN: %flang_fc1 -fopenacc %s + +! Check common block resolution. +! Check that symbol are correctly resolved in device, host and self clause. + +subroutine sub(a) + implicit none + real :: a(10) + real :: b(10), c(10), d + common/foo/ b, d, c + integer :: i, n + + !$acc declare present(/foo/) + !$acc parallel loop gang vector + do i = 1, n + b(i) = a(i) + c(i) * d + end do +end subroutine + +program test_resolve04 + real :: a(10), b(10) + common /foo/ b, c + +!$acc data create(/foo/) +!$acc update device(/foo/) +!$acc update host(/foo/) +!$acc update self(/foo/) +!$acc end data + +!$acc data copy(/foo/) +!$acc end data + +end + diff --git a/flang/test/Semantics/OpenACC/acc-routine-validity.f90 b/flang/test/Semantics/OpenACC/acc-routine-validity.f90 new file mode 100644 index 00000000000000..ecb8610d8e6845 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-routine-validity.f90 @@ -0,0 +1,82 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.15.1 routine + +module openacc_routine_validity + implicit none + + !$acc routine(sub3) seq + + !$acc routine(fct2) vector + + !$acc routine(sub3) + + !ERROR: ROUTINE directive without name must appear within the specification part of a subroutine or function definition, or within an interface body for a subroutine or function in an interface block + !$acc routine seq + + !$acc routine(dummy) seq + +contains + + subroutine sub1(a) + real :: a(:) + !$acc routine + end subroutine sub1 + + subroutine sub2(a) + real :: a(:) + !ERROR: Clause NOHOST is not allowed after clause DEVICE_TYPE on the ROUTINE directive + !$acc routine seq device_type(*) nohost + end subroutine sub2 + + subroutine sub3(a) + real :: a(:) + end subroutine sub3 + + subroutine sub4(a) + real :: a(:) + !$acc routine seq + end subroutine sub4 + + subroutine sub5(a) + real :: a(:) + !$acc routine(sub5) seq + end subroutine sub5 + + function fct1(a) + integer :: fct1 + real :: a(:) + !$acc routine vector nohost + end function fct1 + + function fct2(a) + integer :: fct2 + real :: a(:) + end function fct2 + + function fct3(a) + integer :: fct3 + real :: a(:) + !$acc routine seq bind(fct2) + end function fct3 + + function fct4(a) + integer :: fct4 + real :: a(:) + !$acc routine seq bind("_fct4") + end function fct4 + + subroutine sub6(a) + real :: a(:) + !$acc routine seq bind(dummy_sub) + end subroutine sub6 + + subroutine sub7(a) + real :: a(:) + !ERROR: SHORTLOOP clause is not allowed on the KERNELS directive + !$acc kernels shortloop + !$acc end kernels + end subroutine sub7 + +end module openacc_routine_validity diff --git a/flang/test/Semantics/OpenACC/acc-routine-validity02.f90 b/flang/test/Semantics/OpenACC/acc-routine-validity02.f90 new file mode 100644 index 00000000000000..9410a5b17745dd --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-routine-validity02.f90 @@ -0,0 +1,17 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check acc routine in the top level. + +subroutine sub1(a, n) + integer :: n + real :: a(n) +end subroutine sub1 + +!$acc routine(sub1) + +!dir$ value=1 +program test + integer, parameter :: N = 10 + real :: a(N) + call sub1(a, N) +end program diff --git a/flang/test/Semantics/OpenACC/acc-routine.f90 b/flang/test/Semantics/OpenACC/acc-routine.f90 new file mode 100644 index 00000000000000..8281822ca01d0c --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-routine.f90 @@ -0,0 +1,136 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +subroutine sub1(a) + real, dimension(10) :: a +end subroutine + +subroutine sub2(a) + !$acc routine(sub1) gang(dim:1) + real, dimension(10) :: a + call sub1(a) +end subroutine + +subroutine sub3() + !$acc routine bind(sub1) +end subroutine + +subroutine sub4() + !ERROR: Only the dim argument is allowed on the GANG clause on the ROUTINE directive + !$acc routine gang(num: 1) +end subroutine + +subroutine sub5() + !ERROR: Only the dim argument is allowed on the GANG clause on the ROUTINE directive + !$acc routine gang(static: 1) +end subroutine + +subroutine sub6() + !ERROR: Clause GANG is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang gang + + !ERROR: Clause GANG is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker gang + + !ERROR: Clause GANG is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector gang + + !ERROR: Clause GANG is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq gang + + !ERROR: Clause WORKER is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker worker + + !ERROR: Clause WORKER is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang worker + + !ERROR: Clause WORKER is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector worker + + !ERROR: Clause WORKER is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq worker + + !ERROR: Clause VECTOR is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector vector + + !ERROR: Clause VECTOR is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang vector + + !ERROR: Clause VECTOR is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker vector + + !ERROR: Clause VECTOR is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq vector + + !ERROR: Clause SEQ is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq seq + + !ERROR: Clause SEQ is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang seq + + !ERROR: Clause SEQ is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker seq + + !ERROR: Clause SEQ is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector seq + +end subroutine + +subroutine sub7() + !$acc routine device_type(*) gang device_type(host) worker + + !ERROR: Clause SEQ is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine device_type(*) gang seq + + !ERROR: Clause WORKER is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine device_type(*) gang worker + + !ERROR: Clause GANG is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang device_type(*) gang + + !ERROR: Clause WORKER is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang device_type(*) worker + + !ERROR: Clause VECTOR is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang device_type(*) vector + + !ERROR: Clause SEQ is not allowed if clause GANG appears on the ROUTINE directive + !$acc routine gang device_type(*) seq + + !ERROR: Clause WORKER is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker device_type(*) worker + + !ERROR: Clause GANG is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker device_type(*) gang + + !ERROR: Clause VECTOR is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker device_type(*) vector + + !ERROR: Clause SEQ is not allowed if clause WORKER appears on the ROUTINE directive + !$acc routine worker device_type(*) seq + + !ERROR: Clause VECTOR is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector device_type(*) vector + + !ERROR: Clause GANG is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector device_type(*) gang + + !ERROR: Clause VECTOR is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector device_type(*) vector + + !ERROR: Clause SEQ is not allowed if clause VECTOR appears on the ROUTINE directive + !$acc routine vector device_type(*) seq + + !ERROR: Clause SEQ is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq device_type(*) seq + + !ERROR: Clause GANG is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq device_type(*) gang + + !ERROR: Clause VECTOR is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq device_type(*) vector + + !ERROR: Clause WORKER is not allowed if clause SEQ appears on the ROUTINE directive + !$acc routine seq device_type(*) worker + + !$acc routine device_type(host) seq device_type(nvidia) gang device_type(multicore) vector device_type(*) worker +end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-serial-loop.f90 b/flang/test/Semantics/OpenACC/acc-serial-loop.f90 new file mode 100644 index 00000000000000..2832274680eca3 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-serial-loop.f90 @@ -0,0 +1,114 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.11 Serial Loop + +program openacc_serial_loop_validity + + implicit none + + integer :: i, b + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + logical :: ifCondition = .TRUE. + real(8), dimension(N) :: a + + + !$acc serial loop reduction(+: reduction_r) + do i = 1, N + reduction_r = a(i) + i + end do + + !$acc serial loop reduction(*: reduction_r) + do i = 1, N + reduction_r = reduction_r * (a(i) + i) + end do + + !$acc serial loop reduction(min: reduction_r) + do i = 1, N + reduction_r = min(reduction_r, a(i) * i) + end do + + !$acc serial loop reduction(max: reduction_r) + do i = 1, N + reduction_r = max(reduction_r, a(i) * i) + end do + + !$acc serial loop reduction(iand: b) + do i = 1, N + b = iand(b, c(i)) + end do + + !$acc serial loop reduction(ior: b) + do i = 1, N + b = ior(b, c(i)) + end do + + !$acc serial loop reduction(ieor: b) + do i = 1, N + b = ieor(b, c(i)) + end do + + !$acc serial loop reduction(.and.: reduction_l) + do i = 1, N + reduction_l = d(i) .and. e(i) + end do + + !$acc serial loop reduction(.or.: reduction_l) + do i = 1, N + reduction_l = d(i) .or. e(i) + end do + + !$acc serial loop reduction(.eqv.: reduction_l) + do i = 1, N + reduction_l = d(i) .eqv. e(i) + end do + + !$acc serial loop reduction(.neqv.: reduction_l) + do i = 1, N + reduction_l = d(i) .neqv. e(i) + end do + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the SERIAL LOOP directive + !$acc serial loop device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial loop + + !$acc serial loop if(ifCondition) + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial loop + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + end do + !ERROR: Unmatched END PARALLEL LOOP directive + !$acc end parallel loop + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial loop + + !$acc serial loop + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial + + !$acc serial loop + do i = 1, n + if(i == 10) cycle + end do + +end program openacc_serial_loop_validity diff --git a/flang/test/Semantics/OpenACC/acc-serial.f90 b/flang/test/Semantics/OpenACC/acc-serial.f90 new file mode 100644 index 00000000000000..a23daecce8dd35 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-serial.f90 @@ -0,0 +1,182 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc -pedantic + +! Check OpenACC clause validity for the following construct and directive: +! 2.5.2 Serial + +program openacc_serial_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + real(8) :: s + end type atype + + integer :: i, j, b, gang_size, vector_size, worker_size + integer, parameter :: N = 256 + integer, dimension(N) :: c + logical, dimension(N) :: d, e + integer :: async1 + integer :: wait1, wait2 + real :: reduction_r + logical :: reduction_l + real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + + real(8), dimension(N) :: a, f, g, h + + !$acc serial + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + !$acc end serial + + !$acc serial + !$acc loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + !$acc end serial + + !$acc serial + !$acc end serial + + !$acc serial async + !$acc end serial + + !$acc serial async(1) + !$acc end serial + + !ERROR: At most one ASYNC clause can appear on the SERIAL directive + !$acc serial async(1) async(2) + !$acc end serial + + !$acc serial async(async1) + !$acc end serial + + !$acc serial wait + !$acc end serial + + !$acc serial wait(1) + !$acc end serial + + !$acc serial wait(wait1) + !$acc end serial + + !$acc serial wait(1,2) + !$acc end serial + + !$acc serial wait(wait1, wait2) + !$acc end serial + + !$acc serial wait(wait1) wait(wait2) + !$acc end serial + + !PORTABILITY: NUM_GANGS clause is not allowed on the SERIAL directive and will be ignored + !$acc serial num_gangs(8) + !$acc end serial + + !PORTABILITY: NUM_WORKERS clause is not allowed on the SERIAL directive and will be ignored + !$acc serial num_workers(8) + !$acc end serial + + !PORTABILITY: VECTOR_LENGTH clause is not allowed on the SERIAL directive and will be ignored + !$acc serial vector_length(128) + !$acc end serial + + !$acc serial if(.true.) + !$acc end serial + + !ERROR: At most one IF clause can appear on the SERIAL directive + !$acc serial if(.true.) if(ifCondition) + !$acc end serial + + !$acc serial if(ifCondition) + !$acc end serial + + !$acc serial self + !$acc end serial + + !$acc serial self(.true.) + !$acc end serial + + !$acc serial self(ifCondition) + !$acc end serial + + !$acc serial reduction(.neqv.: reduction_l) + !$acc loop reduction(.neqv.: reduction_l) + do i = 1, N + reduction_l = d(i) .neqv. e(i) + end do + !$acc end serial + + !$acc serial copy(aa) copyin(bb) copyout(cc) + !$acc end serial + + !$acc serial copy(aa, bb) copyout(zero: cc) + !$acc end serial + + !$acc serial present(aa, bb) create(cc) + !$acc end serial + + !$acc serial copyin(readonly: aa, bb) create(zero: cc) + !$acc end serial + + !$acc serial deviceptr(aa, bb) no_create(cc) + !$acc end serial + + !ERROR: Argument `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc serial attach(aa, dd, p) + !$acc end serial + + !$acc serial firstprivate(bb, cc) + !$acc end serial + + !$acc serial private(aa) + !$acc end serial + + !$acc serial default(none) + !$acc end serial + + !$acc serial default(present) + !$acc end serial + + !ERROR: At most one DEFAULT clause can appear on the SERIAL directive + !$acc serial default(present) default(none) + !$acc end serial + + !$acc serial device_type(*) async wait + !$acc end serial + + !$acc serial device_type(*) async + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the SERIAL directive + !$acc serial device_type(*) if(.TRUE.) + do i = 1, N + a(i) = 3.14 + end do + !$acc end serial + + do i = 1, 100 + !$acc serial + !ERROR: CYCLE to construct outside of SERIAL construct is not allowed + if (i == 10) cycle + !$acc end serial + end do + + !$acc serial + do i = 1, 100 + if (i == 10) cycle + end do + !$acc end serial + +end program openacc_serial_validity diff --git a/flang/test/Semantics/OpenACC/acc-set-validity.f90 b/flang/test/Semantics/OpenACC/acc-set-validity.f90 new file mode 100644 index 00000000000000..74522b30d11bc4 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-set-validity.f90 @@ -0,0 +1,108 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.14.3 Set + +program openacc_clause_validity + + implicit none + + integer :: i, j + integer, parameter :: N = 256 + real(8), dimension(N) :: a + + !$acc parallel + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + !$acc end parallel + + !$acc serial + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + !$acc end serial + + !$acc kernels + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + !$acc end kernels + + !$acc parallel + !$acc loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + !$acc end parallel + + !$acc serial + !$acc loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + !$acc end serial + + !$acc kernels + !$acc loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + !$acc end kernels + + !$acc parallel loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + + !$acc serial loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + !ERROR: Directive SET may not be called within a compute region + !$acc set default_async(i) + a(i) = 3.14 + end do + + !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive + !$acc set + + !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive + !$acc set if(.TRUE.) + + !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive + !$acc set default_async(2) default_async(1) + + !ERROR: At most one DEFAULT_ASYNC clause can appear on the SET directive + !$acc set default_async(2) default_async(1) + + !ERROR: At most one DEVICE_NUM clause can appear on the SET directive + !$acc set device_num(1) device_num(i) + + !ERROR: At most one DEVICE_TYPE clause can appear on the SET directive + !$acc set device_type(*) device_type(nvidia) + + !$acc set default_async(2) + !$acc set default_async(i) + !$acc set device_num(1) + !$acc set device_num(i) + !$acc set device_type(default) + !$acc set device_num(1) default_async(2) device_type(*) + + !ERROR: The DEVICE_TYPE clause on the SET directive accepts only one value + !$acc set device_type(*, default) + + !ERROR: At least one of DEFAULT_ASYNC, DEVICE_NUM, DEVICE_TYPE clause must appear on the SET directive + !$acc set + +end program openacc_clause_validity diff --git a/flang/test/Semantics/OpenACC/acc-shutdown-validity.f90 b/flang/test/Semantics/OpenACC/acc-shutdown-validity.f90 new file mode 100644 index 00000000000000..43aed4fc98f42e --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-shutdown-validity.f90 @@ -0,0 +1,96 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.14.2 Shutdown + +program openacc_shutdown_validity + + implicit none + + integer :: i, j + integer, parameter :: N = 256 + logical :: ifCondition = .TRUE. + real(8), dimension(N) :: a + + !$acc parallel + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + !$acc end parallel + + !$acc serial + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + !$acc end serial + + !$acc kernels + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + !$acc end kernels + + !$acc parallel + !$acc loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + !$acc end parallel + + !$acc serial + !$acc loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + !$acc end serial + + !$acc kernels + !$acc loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + !$acc end kernels + + !$acc parallel loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + + !$acc serial loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + + !$acc kernels loop + do i = 1, N + !ERROR: Directive SHUTDOWN may not be called within a compute region + !$acc shutdown + a(i) = 3.14 + end do + + !$acc shutdown + !$acc shutdown if(.TRUE.) + !$acc shutdown if(ifCondition) + !$acc shutdown device_num(1) + !$acc shutdown device_num(i) + !$acc shutdown device_type(*) + !$acc shutdown device_type(*, default, host) + !$acc shutdown device_num(i) device_type(default, host) if(ifCondition) + + !ERROR: At most one IF clause can appear on the SHUTDOWN directive + !$acc shutdown if(.TRUE.) if(ifCondition) + + !ERROR: At most one DEVICE_NUM clause can appear on the SHUTDOWN directive + !$acc shutdown device_num(1) device_num(i) + + !ERROR: At most one DEVICE_TYPE clause can appear on the SHUTDOWN directive + !$acc shutdown device_type(*) device_type(host, default) + +end program openacc_shutdown_validity diff --git a/flang/test/Semantics/OpenACC/acc-symbols01.f90 b/flang/test/Semantics/OpenACC/acc-symbols01.f90 new file mode 100644 index 00000000000000..375445bad13a54 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-symbols01.f90 @@ -0,0 +1,26 @@ +! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenacc + +!DEF: /mm MainProgram +program mm + !DEF: /mm/x ObjectEntity REAL(4) + !DEF: /mm/y ObjectEntity REAL(4) + real x, y + !DEF: /mm/a ObjectEntity INTEGER(4) + !DEF: /mm/b ObjectEntity INTEGER(4) + !DEF: /mm/c ObjectEntity INTEGER(4) + !DEF: /mm/i ObjectEntity INTEGER(4) + integer a(10), b(10), c(10), i + !REF: /mm/b + b = 2 + !$acc parallel present(c) firstprivate(b) private(a) + !$acc loop + !REF: /mm/i + do i=1,10 + !REF: /mm/a + !REF: /mm/i + !REF: /mm/b + a(i) = b(i) + end do + !$acc end parallel + end program + diff --git a/flang/test/Semantics/OpenACC/acc-symbols02.f90 b/flang/test/Semantics/OpenACC/acc-symbols02.f90 new file mode 100644 index 00000000000000..0627af80b1563f --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-symbols02.f90 @@ -0,0 +1,21 @@ +! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenacc + +!DEF:/acc_declare_symbolsModule +module acc_declare_symbols + !DEF: /acc_declare_symbols/a PUBLIC (AccCreate, AccDeclare) ObjectEntity REAL(4) + real a(100) + !$acc declare create(a) + + !DEF:/acc_declare_symbols/b PUBLIC (AccCopyIn, AccDeclare) ObjectEntity REAL(4) + real b(20) + !$acc declare copyin(b) + + !DEF:/acc_declare_symbols/c PUBLIC (AccDeviceResident, AccDeclare) ObjectEntity REAL(4) + real c(10) + !$acc declare device_resident(c) + + !DEF:/acc_declare_symbols/d PUBLIC (AccLink, AccDeclare) ObjectEntity REAL(4) + real d(10) + !$acc declare link(d) + +end module diff --git a/flang/test/Semantics/OpenACC/acc-update-validity.f90 b/flang/test/Semantics/OpenACC/acc-update-validity.f90 new file mode 100644 index 00000000000000..1e75742e63e97b --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-update-validity.f90 @@ -0,0 +1,67 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.14.4 Update + +program openacc_update_validity + + implicit none + + type atype + real(8), dimension(10) :: arr + end type atype + + integer :: i + integer, parameter :: N = 256 + integer, dimension(N) :: c + integer :: async1 + integer :: wait1, wait2 + real(8), dimension(N, N) :: aa, bb, cc + logical :: ifCondition = .TRUE. + type(atype) :: t + type(atype), dimension(10) :: ta + real(8), dimension(N) :: a, f, g, h + + !ERROR: At least one of DEVICE, HOST, SELF clause must appear on the UPDATE directive + !$acc update + + !$acc update device(t%arr(:)) + + !$acc update device(ta(i)%arr(:)) + + !$acc update self(a, f) host(g) device(h) + + !$acc update host(aa) async(1) + + !$acc update device(bb) async(async1) + + !ERROR: At most one ASYNC clause can appear on the UPDATE directive + !$acc update host(aa, bb) async(1) async(2) + + !$acc update self(bb, cc(:,:)) wait(1) + + !ERROR: SELF clause on the UPDATE directive must have a var-list + !$acc update self + + !$acc update device(aa, bb, cc) wait(wait1) + + !$acc update host(aa) host(bb) device(cc) wait(1,2) + + !$acc update device(aa, cc) wait(wait1, wait2) + + !$acc update device(aa) device_type(*) async + + !$acc update host(bb) device_type(*) wait + + !$acc update self(cc) device_type(host,multicore) async device_type(*) wait + + !ERROR: At most one IF clause can appear on the UPDATE directive + !$acc update device(aa) if(.true.) if(ifCondition) + + !ERROR: At most one IF_PRESENT clause can appear on the UPDATE directive + !$acc update device(bb) if_present if_present + + !ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the UPDATE directive + !$acc update device(i) device_type(*) if(.TRUE.) + +end program openacc_update_validity diff --git a/flang/test/Semantics/OpenACC/acc-wait-validity.f90 b/flang/test/Semantics/OpenACC/acc-wait-validity.f90 new file mode 100644 index 00000000000000..25d603dad05026 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-wait-validity.f90 @@ -0,0 +1,42 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! Check OpenACC clause validity for the following construct and directive: +! 2.16.13 Wait + +program openacc_wait_validity + + implicit none + + logical :: ifCondition = .TRUE. + + !$acc wait + + !$acc wait async + + !$acc wait(1) + !$acc wait(1, 2) + + !$acc wait(queues: 1) + !$acc wait(queues: 1, 2) + + !$acc wait(devnum: 1: 3) + !$acc wait(devnum: 1: 3, 4) + + !$acc wait(devnum: 1: queues: 3) + !$acc wait(devnum: 1: queues: 3, 4) + + !$acc wait(1) if(.true.) + + !ERROR: At most one IF clause can appear on the WAIT directive + !$acc wait(1) if(.true.) if(.false.) + + !$acc wait(1) if(.true.) async + + !$acc wait(1) if(ifCondition) async + + !$acc wait(1) if(.true.) async(1) + + !ERROR: At most one ASYNC clause can appear on the WAIT directive + !$acc wait(1) if(.true.) async(1) async + +end program openacc_wait_validity diff --git a/flang/test/Semantics/cuf10.cuf b/flang/test/Semantics/cuf10.cuf new file mode 100644 index 00000000000000..047503b3cca4ea --- /dev/null +++ b/flang/test/Semantics/cuf10.cuf @@ -0,0 +1,26 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenacc +module m + real, device :: a(4,8) + real, managed, allocatable :: b(:,:) + contains + attributes(global) subroutine kernel(a,b,c,n,m) + integer, value :: n + integer, intent(in) :: m + real a(n,m), c(n,m) + real, managed :: b(n,m) + end + attributes(device) subroutine devsub(a,n) + integer, value :: n + real, device :: a(n) + end + subroutine test + real c(4) + allocate(b(4,8)) + !ERROR: dummy argument 'm=' has ATTRIBUTES(DEVICE) but its associated actual argument has no CUDA data attribute + call kernel<<<1,32>>>(a,b,b,4,8) + !$acc parallel loop copy(c) + do j = 1, 1 + call devsub(c,4) ! not checked in OpenACC construct + end do + end +end diff --git a/flang/test/Semantics/loop-directives.f90 b/flang/test/Semantics/loop-directives.f90 index cc23c384d272cd..58fb9b8082bc1a 100644 --- a/flang/test/Semantics/loop-directives.f90 +++ b/flang/test/Semantics/loop-directives.f90 @@ -1,4 +1,5 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenacc -Werror subroutine empty ! WARNING: A DO loop must follow the VECTOR ALWAYS directive