diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 185e0316870e9..5cff95c7d125b 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1120,7 +1120,21 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, if (auto refType = baseOp.getType().dyn_cast()) eleType = refType.getElementType(); - if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { + // If a variable is specified in declare target link and if device + // type is not specified as `nohost`, it needs to be mapped tofrom + mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); + mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym)); + auto declareTargetOp = + llvm::dyn_cast_if_present(op); + if (declareTargetOp && declareTargetOp.isDeclareTarget()) { + if (declareTargetOp.getDeclareTargetCaptureClause() == + mlir::omp::DeclareTargetCaptureClause::link && + declareTargetOp.getDeclareTargetDeviceType() != + mlir::omp::DeclareTargetDeviceType::nohost) { + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; + } + } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { captureKind = mlir::omp::VariableCaptureKind::ByCopy; } else if (!fir::isa_builtin_cptr_type(eleType)) { mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; diff --git a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 new file mode 100644 index 0000000000000..7cd0597161578 --- /dev/null +++ b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 @@ -0,0 +1,55 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s + +program test_link + + integer :: test_int = 1 + !$omp declare target link(test_int) + + integer :: test_array_1d(3) = (/1,2,3/) + !$omp declare target link(test_array_1d) + + integer, pointer :: test_ptr1 + !$omp declare target link(test_ptr1) + + integer, target :: test_target = 1 + !$omp declare target link(test_target) + + integer, pointer :: test_ptr2 + !$omp declare target link(test_ptr2) + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref {name = "test_int"} + !$omp target + test_int = test_int + 1 + !$omp end target + + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>, !fir.array<3xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{%.*}}) -> !fir.ref> {name = "test_array_1d"} + !$omp target + do i = 1,3 + test_array_1d(i) = i * 2 + end do + !$omp end target + + allocate(test_ptr1) + test_ptr1 = 1 + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr1"} + !$omp target + test_ptr1 = test_ptr1 + 1 + !$omp end target + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref {name = "test_target"} + !$omp target + test_target = test_target + 1 + !$omp end target + + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr2"} + test_ptr2 => test_target + !$omp target + test_ptr2 = test_ptr2 + 1 + !$omp end target + +end diff --git a/openmp/libomptarget/test/offloading/fortran/declare-target-array-in-target-region.f90 b/openmp/libomptarget/test/offloading/fortran/declare-target-array-in-target-region.f90 deleted file mode 100644 index c09146198768b..0000000000000 --- a/openmp/libomptarget/test/offloading/fortran/declare-target-array-in-target-region.f90 +++ /dev/null @@ -1,33 +0,0 @@ -! Offloading test with a target region mapping a declare target -! Fortran array writing some values to it and checking the host -! correctly receives the updates made on the device. -! REQUIRES: flang -! UNSUPPORTED: nvptx64-nvidia-cuda-LTO -! UNSUPPORTED: aarch64-unknown-linux-gnu -! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO -! UNSUPPORTED: x86_64-pc-linux-gnu -! UNSUPPORTED: x86_64-pc-linux-gnu-LTO - -! RUN: %libomptarget-compile-fortran-run-and-check-generic -module test_0 - implicit none - INTEGER :: sp(10) = (/0,0,0,0,0,0,0,0,0,0/) - !$omp declare target link(sp) -end module test_0 - -program main - use test_0 - integer :: i = 1 - integer :: j = 11 -!$omp target map(tofrom:sp, i, j) - do while (i <= j) - sp(i) = i; - i = i + 1 - end do -!$omp end target - -PRINT *, sp(:) - -end program - -! CHECK: 1 2 3 4 5 6 7 8 9 10 diff --git a/openmp/libomptarget/test/offloading/fortran/declare-target-vars-in-target-region.f90 b/openmp/libomptarget/test/offloading/fortran/declare-target-vars-in-target-region.f90 new file mode 100644 index 0000000000000..f524deac3bcce --- /dev/null +++ b/openmp/libomptarget/test/offloading/fortran/declare-target-vars-in-target-region.f90 @@ -0,0 +1,81 @@ +! Offloading test with a target region mapping a declare target +! Fortran array writing some values to it and checking the host +! correctly receives the updates made on the device. +! REQUIRES: flang +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +module test_0 + implicit none + INTEGER :: arr1(10) = (/0,0,0,0,0,0,0,0,0,0/) + INTEGER :: arr2(10) = (/0,0,0,0,0,0,0,0,0,0/) + !$omp declare target link(arr1) enter(arr2) + INTEGER :: scalar = 1 + !$omp declare target link(scalar) +end module test_0 + +subroutine test_with_array_link_and_tofrom() + use test_0 + integer :: i = 1 + integer :: j = 11 + !$omp target map(tofrom:arr1, i, j) + do while (i <= j) + arr1(i) = i; + i = i + 1 + end do + !$omp end target + + ! CHECK: 1 2 3 4 5 6 7 8 9 10 + PRINT *, arr1(:) +end subroutine test_with_array_link_and_tofrom + +subroutine test_with_array_link_only() + use test_0 + integer :: i = 1 + integer :: j = 11 + !$omp target map(i, j) + do while (i <= j) + arr1(i) = i + 1; + i = i + 1 + end do + !$omp end target + + ! CHECK: 2 3 4 5 6 7 8 9 10 11 + PRINT *, arr1(:) +end subroutine test_with_array_link_only + +subroutine test_with_array_enter_only() + use test_0 + integer :: i = 1 + integer :: j = 11 + !$omp target map(i, j) + do while (i <= j) + arr2(i) = i + 1; + i = i + 1 + end do + !$omp end target + + ! CHECK: 0 0 0 0 0 0 0 0 0 0 + PRINT *, arr2(:) +end subroutine test_with_array_enter_only + +subroutine test_with_scalar_link_only() + use test_0 + !$omp target + scalar = 10 + !$omp end target + + ! CHECK: 10 + PRINT *, scalar +end subroutine test_with_scalar_link_only + +program main + call test_with_array_link_and_tofrom() + call test_with_array_link_only() + call test_with_array_enter_only() + call test_with_scalar_link_only() +end program