[llvm-branch-commits] [flang] [mlir] [Flang][OpenMP] Improve implicit declare_target propagation (PR #214184)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Aug 5 03:19:59 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-openmp

Author: Sergio Afonso (skatrak)

<details>
<summary>Changes</summary>

After starting to run the `MarkDeclareTarget` pass later in the pipeline, some limitations of its original implementation started to be hit; specifically, some calls being missed could result in an overly restrictive marking that would cause the `HostOpFiltering` pass to remove reachable device code.

This patch aims to address these problems by making the following changes:
- It makes sure to mark functions in every `RecipeInterface` op pointed to by OpenMP operations.
- It recursively propagates and combines declare_target information from target regions and explicitly set declare_target functions to unmarked functions, but it never modifies explicitly marked functions.
- External and public functions can now only be marked with `device_type(any)`. Before, marking them as `nohost` or `host` was possible, but without the ability to see all users we can't give such guarantees.
- There was a bug in the handling of declare_target on interface subprograms that improvements to the pass made visible. Instead of adding the attribute to the MLIR function associated to the interface subprogram, it wasn't added at all, making it susceptible to being modified by the pass according to uses. This is fixed.

Fixes #<!-- -->213367.

---

Patch is 83.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/214184.diff


11 Files Affected:

- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+29-7) 
- (modified) flang/test/Integration/OpenMP/function-filtering-2.f90 (+46-44) 
- (modified) flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90 (+3-3) 
- (modified) flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 (+1-1) 
- (modified) flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 (+132-119) 
- (modified) flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90 (+153-140) 
- (modified) flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90 (+92-79) 
- (modified) flang/test/Lower/OpenMP/declare-target-named-main-interface.f90 (+2-2) 
- (modified) mlir/include/mlir/Dialect/OpenMP/Transforms/Passes.td (+3) 
- (modified) mlir/lib/Dialect/OpenMP/Transforms/MarkDeclareTarget.cpp (+243-100) 
- (added) mlir/test/Dialect/OpenMP/mark-declare-target.mlir (+363) 


``````````diff
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index ae1eb897c9348..f6711bff65a2e 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1433,16 +1433,38 @@ static void getDeclareTargetInfo(
   } else {
     List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
     if (clauses.empty()) {
+      // Case: implicit capture of the enclosing function/subroutine.
       Fortran::lower::pft::FunctionLikeUnit *owningProc =
           eval.getOwningProcedure();
-      // Main programs are never device routines. Skip them so that a bare
-      // '!$omp declare target' inside an interface body that lives in a named
-      // main program does not incorrectly mark _QQmain as a device function.
-      if (owningProc && !owningProc->isMainProgram()) {
-        // Case: declare target, implicit capture of enclosing
-        // function/subroutine.
+      bool owningProcNotMainProgram =
+          owningProc && !owningProc->isMainProgram();
+
+      const semantics::Symbol *owningSym =
+          owningProcNotMainProgram
+              ? &owningProc->getSubprogramSymbol()
+              : (owningProc ? owningProc->getMainProgramSymbol() : nullptr);
+
+      // A bare '!$omp declare target' may appear in the specification part of
+      // an interface body. In that case the PFT records the directive as an
+      // evaluation of the enclosing program unit rather than of the interface
+      // body's subprogram, so eval.getOwningProcedure() points at the main
+      // program. Detect this by comparing the program unit lexically containing
+      // the directive with the procedure currently being lowered; when they
+      // differ, the directive belongs to the interface-body subprogram, which
+      // is the symbol we must capture.
+      const semantics::Scope &progUnitScope =
+          semantics::GetProgramUnitContaining(
+              semaCtx.FindScope(construct.v.source));
+      const semantics::Symbol *lexicalSym = progUnitScope.symbol();
+
+      if (lexicalSym && lexicalSym != owningSym) {
+        // Interface subprogram capture.
         symbolAndClause.emplace_back(mlir::omp::DeclareTargetCaptureClause::to,
-                                     owningProc->getSubprogramSymbol());
+                                     *lexicalSym);
+      } else if (owningProcNotMainProgram) {
+        // Main programs are never device routines, so skip those here.
+        symbolAndClause.emplace_back(mlir::omp::DeclareTargetCaptureClause::to,
+                                     *owningSym);
       }
     }
 
diff --git a/flang/test/Integration/OpenMP/function-filtering-2.f90 b/flang/test/Integration/OpenMP/function-filtering-2.f90
index eda3015811e73..ee0c68adc78b3 100644
--- a/flang/test/Integration/OpenMP/function-filtering-2.f90
+++ b/flang/test/Integration/OpenMP/function-filtering-2.f90
@@ -13,49 +13,51 @@
 ! RUN: bbc -fopenmp -fopenmp-version=52 -emit-hlfir %s -o - | tco -test-gen | FileCheck --check-prefixes=MLIR-ALL,MLIR-HOST %s
 ! RUN: %if amdgpu-registered-target %{ bbc -target amdgcn-amd-amdhsa -fopenmp -fopenmp-version=52 -fopenmp-is-target-device -emit-hlfir %s -o - | tco -test-gen | FileCheck --check-prefixes=MLIR-ALL,MLIR-DEVICE %s %}
 
-! MLIR-ALL: llvm.func @{{.*}}implicit_invocation() attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
-! MLIR-ALL: llvm.return
-! LLVM-ALL: define {{.*}} @{{.*}}implicit_invocation{{.*}}(
-subroutine implicit_invocation()
-end subroutine implicit_invocation
-
-! MLIR-ALL: llvm.func @{{.*}}declaretarget() attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
-! MLIR-ALL: llvm.return
-! LLVM-ALL: define {{.*}} @{{.*}}declaretarget{{.*}}(
-subroutine declaretarget()
-!$omp declare target to(declaretarget) device_type(nohost)
-    call implicit_invocation()
-end subroutine declaretarget
-
-! MLIR-ALL: llvm.func @{{.*}}declaretarget_enter() attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-! MLIR-ALL: llvm.return
-! LLVM-ALL: define {{.*}} @{{.*}}declaretarget_enter{{.*}}(
-subroutine declaretarget_enter()
-!$omp declare target enter(declaretarget_enter) device_type(nohost)
-    call implicit_invocation()
-end subroutine declaretarget_enter
-
-! MLIR-ALL: llvm.func @{{.*}}no_declaretarget() attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
-! MLIR-ALL: llvm.return
-! LLVM-ALL: define {{.*}} @{{.*}}no_declaretarget{{.*}}(
-subroutine no_declaretarget()
-end subroutine no_declaretarget
-
-! MLIR-ALL: llvm.func @{{.+}}main(
-! MLIR-ALL: omp.target
-! MLIR-ALL: llvm.return
-
-! MLIR-HOST: llvm.func @main(
-! MLIR-HOST: llvm.return
-! MLIR-DEVICE-NOT: llvm.func @main(
-
-! LLVM-HOST: define {{.*}} @{{.*}}main{{.*}}(
-! LLVM-HOST: {{.*}} @{{.*}}__omp_offloading{{.*}}main_{{.*}}(
-! LLVM-DEVICE-NOT: {{.*}} @{{.*}}main{{.*}}(
-! LLVM-DEVICE: define {{.*}} @{{.*}}__omp_offloading{{.*}}main_{{.*}}(
 program main
-!$omp target
-    call declaretarget()
-    call no_declaretarget()
-!$omp end target
+    ! MLIR-ALL: llvm.func @{{.+}}main(
+    ! MLIR-ALL: omp.target
+    ! MLIR-ALL: llvm.return
+    !$omp target
+        call declaretarget()
+        call declaretarget_enter()
+        call no_declaretarget()
+    !$omp end target
+
+    contains
+    ! MLIR-ALL: llvm.func{{.*}} @{{.*}}implicit_invocation() attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+    ! MLIR-ALL: llvm.return
+    ! LLVM-ALL: define {{.*}} @{{.*}}implicit_invocation{{.*}}(
+    subroutine implicit_invocation()
+    end subroutine implicit_invocation
+
+    ! MLIR-ALL: llvm.func{{.*}} @{{.*}}declaretarget() attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+    ! MLIR-ALL: llvm.return
+    ! LLVM-ALL: define {{.*}} @{{.*}}declaretarget{{.*}}(
+    subroutine declaretarget()
+    !$omp declare target to(declaretarget) device_type(nohost)
+        call implicit_invocation()
+    end subroutine declaretarget
+
+    ! MLIR-ALL: llvm.func{{.*}} @{{.*}}declaretarget_enter() attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
+    ! MLIR-ALL: llvm.return
+    ! LLVM-ALL: define {{.*}} @{{.*}}declaretarget_enter{{.*}}(
+    subroutine declaretarget_enter()
+    !$omp declare target enter(declaretarget_enter) device_type(nohost)
+        call implicit_invocation()
+    end subroutine declaretarget_enter
+
+    ! MLIR-ALL: llvm.func{{.*}} @{{.*}}no_declaretarget() attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+    ! MLIR-ALL: llvm.return
+    ! LLVM-ALL: define {{.*}} @{{.*}}no_declaretarget{{.*}}(
+    subroutine no_declaretarget()
+    end subroutine no_declaretarget
+
+    ! MLIR-HOST: llvm.func{{.*}} @main(
+    ! MLIR-DEVICE-NOT: llvm.func{{.*}} @main(
+    ! MLIR-HOST: llvm.return
+
+    ! LLVM-HOST: define {{.*}} @{{.*}}main{{.*}}(
+    ! LLVM-HOST: {{.*}} @{{.*}}__omp_offloading{{.*}}main_{{.*}}(
+    ! LLVM-DEVICE-NOT: {{.*}} @{{.*}}main{{.*}}(
+    ! LLVM-DEVICE: define {{.*}} @{{.*}}__omp_offloading{{.*}}main_{{.*}}(
 end program main
diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90
index b245f5fdc560b..a95561389364c 100644
--- a/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90
+++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking-reductions.f90
@@ -31,6 +31,6 @@ end function mycombine
  end program main
 
 !CHECK: llvm.func @myinit(!llvm.ptr, !llvm.ptr)
-!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}
-!CHECK: llvm.func @mycombine(!llvm.ptr, !llvm.ptr)
-!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}
+!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}
+!CHECK-LABEL: llvm.func @mycombine(!llvm.ptr, !llvm.ptr)
+!CHECK-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}
diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
index ee2a6c70c0057..a82e2f31afa93 100644
--- a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
+++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
@@ -53,7 +53,7 @@ end program main
 !HOST-LABEL: llvm.func @host_interface()
 !HOST-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter), automap = false>{{.*}}
 !ALL-LABEL: llvm.func @called_from_target_interface(!llvm.ptr, !llvm.ptr)
-!ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}
+!ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}
 !ALL-LABEL: llvm.func @any_interface()
 !ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}
 !ALL-LABEL: llvm.func @device_interface()
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
index 3e20e7a8b0170..26a458e34c950 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
@@ -3,109 +3,134 @@
 !RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | tco -test-gen | FileCheck %s
 !RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | tco -test-gen | FileCheck %s --check-prefix=DEVICE
 
-! CHECK-LABEL: llvm.func @_QPimplicitly_captured_twice
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_twice() result(k)
-   integer :: i
-   i = 10
-   k = i
-end function implicitly_captured_twice
-
-! CHECK-LABEL: llvm.func @_QPtarget_function_twice_host
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter), automap = false>{{.*}}}
-function target_function_twice_host() result(i)
-!$omp declare target enter(target_function_twice_host) device_type(host)
-   integer :: i
-   i = implicitly_captured_twice()
-end function target_function_twice_host
+program mb
+   interface
+      subroutine caller_recursive
+         !$omp declare target enter(caller_recursive) device_type(nohost)
+      end subroutine
 
-! DEVICE-LABEL: llvm.func @_QPtarget_function_twice_device
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-function target_function_twice_device() result(i)
-!$omp declare target enter(target_function_twice_device) device_type(nohost)
-   integer :: i
-   i = implicitly_captured_twice()
-end function target_function_twice_device
+      recursive subroutine implicitly_captured_recursive(increment)
+         integer :: increment
+      end subroutine
+   end interface
 
-!! -----
+   integer :: tmp
+
+   ! Make sure to make all internal functions reachable. Otherwise, they could
+   ! be optimized out.
+   tmp = target_function_twice_host()
+   tmp = target_function_test_host()
+   !$omp target
+      tmp = target_function_twice_device()
+      tmp = target_function_test()
+      tmp = target_function_test_device()
+   !$omp end target
+
+   contains
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_twice
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_twice() result(k)
+      integer :: i
+      i = 10
+      k = i
+   end function implicitly_captured_twice
 
-! DEVICE-LABEL: llvm.func @_QPimplicitly_captured_nest
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_nest() result(k)
-   integer :: i
-   i = 10
-   k = i
-end function implicitly_captured_nest
-
-! DEVICE-LABEL: llvm.func @_QPimplicitly_captured_one
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter){{.*}}}
-function implicitly_captured_one() result(k)
-   k = implicitly_captured_nest()
-end function implicitly_captured_one
-
-! DEVICE-LABEL: llvm.func @_QPimplicitly_captured_two
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_two() result(k)
-   integer :: i
-   i = 10
-   k = i
-end function implicitly_captured_two
-
-! DEVICE-LABEL: llvm.func @_QPtarget_function_test
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-function target_function_test() result(j)
-!$omp declare target enter(target_function_test) device_type(nohost)
-   integer :: i, j
-   i = implicitly_captured_one()
-   j = implicitly_captured_two() + i
-end function target_function_test
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPtarget_function_twice_host()
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter), automap = false>{{.*}}}
+   function target_function_twice_host() result(i)
+   !$omp declare target enter(target_function_twice_host) device_type(host)
+      integer :: i
+      i = implicitly_captured_twice()
+   end function target_function_twice_host
 
-!! -----
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPtarget_function_twice_device()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
+   function target_function_twice_device() result(i)
+   !$omp declare target enter(target_function_twice_device) device_type(nohost)
+      integer :: i
+      i = implicitly_captured_twice()
+   end function target_function_twice_device
 
-! CHECK-LABEL: llvm.func @_QPimplicitly_captured_nest_twice
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_nest_twice() result(k)
-   integer :: i
-   i = 10
-   k = i
-end function implicitly_captured_nest_twice
-
-! CHECK-LABEL: llvm.func @_QPimplicitly_captured_one_twice
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_one_twice() result(k)
-   k = implicitly_captured_nest_twice()
-end function implicitly_captured_one_twice
-
-! CHECK-LABEL: llvm.func @_QPimplicitly_captured_two_twice
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
-function implicitly_captured_two_twice() result(k)
-   integer :: i
-   i = 10
-   k = i
-end function implicitly_captured_two_twice
-
-! DEVICE-LABEL: llvm.func @_QPtarget_function_test_device
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
-function target_function_test_device() result(j)
-   !$omp declare target enter(target_function_test_device) device_type(nohost)
-   integer :: i, j
-   i = implicitly_captured_one_twice()
-   j = implicitly_captured_two_twice() + i
-end function target_function_test_device
-
-! CHECK-LABEL: llvm.func @_QPtarget_function_test_host
-! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter), automap = false>{{.*}}}
-function target_function_test_host() result(j)
-   !$omp declare target enter(target_function_test_host) device_type(host)
-   integer :: i, j
-   i = implicitly_captured_one_twice()
-   j = implicitly_captured_two_twice() + i
-end function target_function_test_host
+   !! -----
+
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_nest()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_nest() result(k)
+      integer :: i
+      i = 10
+      k = i
+   end function implicitly_captured_nest
+
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_one()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to){{.*}}}
+   function implicitly_captured_one() result(k)
+      k = implicitly_captured_nest()
+   end function implicitly_captured_one
+
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_two()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_two() result(k)
+      integer :: i
+      i = 10
+      k = i
+   end function implicitly_captured_two
+
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPtarget_function_test()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
+   function target_function_test() result(j)
+   !$omp declare target enter(target_function_test) device_type(nohost)
+      integer :: i, j
+      i = implicitly_captured_one()
+      j = implicitly_captured_two() + i
+   end function target_function_test
+
+   !! -----
+
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_nest_twice()
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_nest_twice() result(k)
+      integer :: i
+      i = 10
+      k = i
+   end function implicitly_captured_nest_twice
+
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_one_twice()
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_one_twice() result(k)
+      k = implicitly_captured_nest_twice()
+   end function implicitly_captured_one_twice
+
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPimplicitly_captured_two_twice()
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
+   function implicitly_captured_two_twice() result(k)
+      integer :: i
+      i = 10
+      k = i
+   end function implicitly_captured_two_twice
+
+   ! DEVICE-LABEL: llvm.func{{.*}} @_QFPtarget_function_test_device()
+   ! DEVICE-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
+   function target_function_test_device() result(j)
+      !$omp declare target enter(target_function_test_device) device_type(nohost)
+      integer :: i, j
+      i = implicitly_captured_one_twice()
+      j = implicitly_captured_two_twice() + i
+   end function target_function_test_device
+
+   ! CHECK-LABEL: llvm.func{{.*}} @_QFPtarget_function_test_host()
+   ! CHECK-SAME: {{.*}}attributes {{{.*}}omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (enter), automap = false>{{.*}}}
+   function target_function_test_host() result(j)
+      !$omp declare target enter(target_function_test_host) device_type(host)
+      integer :: i, j
+  ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/214184


More information about the llvm-branch-commits mailing list