[flang-commits] [flang] [flang][OpenMP] Avoid marking named main programs as declare target (PR #190250)

Sairudra More via flang-commits flang-commits at lists.llvm.org
Wed Apr 8 04:07:11 PDT 2026


https://github.com/Saieiei updated https://github.com/llvm/llvm-project/pull/190250

>From 051e7f980deedc7cbf22ec1e67cc708e7227b5e1 Mon Sep 17 00:00:00 2001
From: Saieiei <sairudra60 at gmail.com>
Date: Thu, 2 Apr 2026 14:40:15 -0500
Subject: [PATCH] [flang][OpenMP] Avoid marking named main programs as declare
 target

A bare !$omp declare target could incorrectly mark _QQmain as
omp.declare_target when it appeared in an interface body inside a named
main program. That pulled host-only callees into device compilation and
caused offload link failures.

Fix this by skipping main programs in the implicit-capture path.
Also add a regression test for the named-main interface case and update
real10.f90 to use a valid bare declare target container.
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  9 +++--
 .../declare-target-named-main-interface.f90   | 34 +++++++++++++++++++
 flang/test/Lower/OpenMP/real10.f90            |  6 ++--
 3 files changed, 43 insertions(+), 6 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/declare-target-named-main-interface.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 43c6128d46647..d6599dcb24177 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -778,9 +778,12 @@ static void getDeclareTargetInfo(
     if (clauses.empty()) {
       Fortran::lower::pft::FunctionLikeUnit *owningProc =
           eval.getOwningProcedure();
-      if (owningProc && (!owningProc->isMainProgram() ||
-                         owningProc->getMainProgramSymbol())) {
-        // Case: declare target, implicit capture of function
+      // 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.
         symbolAndClause.emplace_back(mlir::omp::DeclareTargetCaptureClause::to,
                                      owningProc->getSubprogramSymbol());
       }
diff --git a/flang/test/Lower/OpenMP/declare-target-named-main-interface.f90 b/flang/test/Lower/OpenMP/declare-target-named-main-interface.f90
new file mode 100644
index 0000000000000..32ba6e7723b15
--- /dev/null
+++ b/flang/test/Lower/OpenMP/declare-target-named-main-interface.f90
@@ -0,0 +1,34 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefix=HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+
+! Test that a bare '!$omp declare target' inside an interface body that
+! appears in a *named* main program does not incorrectly mark the main
+! program (_QQmain) as a declare-target function.  The subroutines
+! declared in the interface blocks are defined externally and carry their
+! own '!$omp declare target' in their definitions; that path is tested
+! separately.
+!
+! In host compilation _QQmain must not be tagged with declare_target at all.
+! In device compilation the MarkDeclareTargetPass may annotate _QQmain with
+! device_type(host) (harmless); the bug was device_type(any) which caused
+! _QQmain to be emitted into the device image.
+
+! HOST-NOT: func.func @_QQmain{{.*}}omp.declare_target
+! DEVICE-NOT: func.func @_QQmain{{.*}}device_type = (any)
+! DEVICE-NOT: func.func @_QQmain{{.*}}device_type = (nohost)
+! HOST: func.func private @_QPsub_a{{.*}}device_type = (nohost)
+! DEVICE: func.func private @_QPsub_a{{.*}}device_type = (nohost)
+
+program named_main
+  interface
+    subroutine sub_a(x)
+      implicit none
+      !$omp declare target
+      integer, intent(inout) :: x
+    end subroutine sub_a
+  end interface
+  integer :: v = 0
+  !$omp target
+    call sub_a(v)
+  !$omp end target
+end program named_main
diff --git a/flang/test/Lower/OpenMP/real10.f90 b/flang/test/Lower/OpenMP/real10.f90
index c76c2bde0f6f6..7323f421ad2c0 100644
--- a/flang/test/Lower/OpenMP/real10.f90
+++ b/flang/test/Lower/OpenMP/real10.f90
@@ -2,9 +2,9 @@
 
 !RUN: %flang_fc1 -emit-hlfir -fopenmp -triple amdgcn -fopenmp -fopenmp-is-target-device -o - %s | FileCheck %s
 
-!CHECK: hlfir.declare %{{.*}} {uniq_name = "_QFEx"} : (!fir.ref<f80>) -> (!fir.ref<f80>, !fir.ref<f80>)
+!CHECK: hlfir.declare %{{.*}} {uniq_name = "_QFtest_real10Ex"} : (!fir.ref<f80>) -> (!fir.ref<f80>, !fir.ref<f80>)
 
-program p
+subroutine test_real10()
   !$omp declare target
   real(10) :: x
-end
+end subroutine test_real10



More information about the flang-commits mailing list