[flang-commits] [flang] [Flang][OpenMP][MLIR] Add attach and ref map type lowering to MLIR (PR #177301)

via flang-commits flang-commits at lists.llvm.org
Wed Mar 4 19:51:07 PST 2026


https://github.com/agozillon updated https://github.com/llvm/llvm-project/pull/177301

>From 0c61f96d23f8679fb8ed5d3515882356b4830658 Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Tue, 20 Jan 2026 21:13:27 -0600
Subject: [PATCH] [Flang][OpenMP][MLIR] Add attach and ref map type lowering to
 MLIR

This doesn't implement the functionality, just the relevant map type
lowering to MLIR's omp.map.info. The more complicated changes to
MapInfoFinalizationPass.cpp and OpenMPTOLLVMIRTranslation.cpp to support
attach map and the various ref/attach semantics will come in a subsequent
set of PRs. This just helps compartmentalize the changeset.
---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |  31 ++++-
 .../Lower/OpenMP/Todo/attach-modifier.f90     |   9 --
 .../Lower/OpenMP/attach-and-ref-modifier.f90  | 107 ++++++++++++++++++
 3 files changed, 136 insertions(+), 11 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/Todo/attach-modifier.f90
 create mode 100644 flang/test/Lower/OpenMP/attach-and-ref-modifier.f90

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index e437ba103a258..fb5c54d2c38ae 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1577,8 +1577,6 @@ bool ClauseProcessor::processMap(
     mlir::Location clauseLocation = converter.genLocation(source);
     const auto &[mapType, typeMods, attachMod, refMod, mappers, iterator,
                  objects] = clause.t;
-    if (attachMod)
-      TODO(currentLocation, "ATTACH modifier is not implemented yet");
     mlir::omp::ClauseMapFlags mapTypeBits = mlir::omp::ClauseMapFlags::none;
     // For data-motion directives we avoid auto-attaching implicit default
     // mappers. Deep recursive mapping there can conflict with explicit
@@ -1630,6 +1628,35 @@ bool ClauseProcessor::processMap(
         mapTypeBits |= mlir::omp::ClauseMapFlags::ompx_hold;
     }
 
+    if (refMod) {
+      switch (*refMod) {
+      case Map::RefModifier::RefPtee:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::ref_ptee;
+        break;
+      case Map::RefModifier::RefPtr:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::ref_ptr;
+        break;
+      case Map::RefModifier::RefPtrPtee:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::ref_ptr |
+                       mlir::omp::ClauseMapFlags::ref_ptee;
+        break;
+      }
+    }
+
+    if (attachMod) {
+      switch (*attachMod) {
+      case Map::AttachModifier::Always:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::attach_always;
+        break;
+      case Map::AttachModifier::Never:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::attach_never;
+        break;
+      case Map::AttachModifier::Auto:
+        mapTypeBits |= mlir::omp::ClauseMapFlags::attach_auto;
+        break;
+      }
+    }
+
     if (iterator) {
       TODO(currentLocation,
            "Support for iterator modifiers is not implemented yet");
diff --git a/flang/test/Lower/OpenMP/Todo/attach-modifier.f90 b/flang/test/Lower/OpenMP/Todo/attach-modifier.f90
deleted file mode 100644
index 099f4a4d8255c..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/attach-modifier.f90
+++ /dev/null
@@ -1,9 +0,0 @@
-!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=61 -o - %s 2>&1 | FileCheck %s
-!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=61 -o - %s 2>&1 | FileCheck %s
-
-!CHECK: not yet implemented: ATTACH modifier is not implemented yet
-subroutine f00(x)
-  integer, pointer :: x
-  !$omp target map(attach(always), tofrom: x)
-  !$omp end target
-end
diff --git a/flang/test/Lower/OpenMP/attach-and-ref-modifier.f90 b/flang/test/Lower/OpenMP/attach-and-ref-modifier.f90
new file mode 100644
index 0000000000000..bcc63a6ca3bf4
--- /dev/null
+++ b/flang/test/Lower/OpenMP/attach-and-ref-modifier.f90
@@ -0,0 +1,107 @@
+! RUN: %flang_fc1 -fopenmp -fopenmp-version=61 -emit-hlfir %s -o - 2>&1 | FileCheck %s
+
+subroutine attach_always()
+    integer, pointer :: x
+
+!CHECK: func.func @{{.*}}attach_always{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_ATTACH]] -> %{{.*}}, %[[MAP_BASE_ADDR]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) {
+    !$omp target map(attach(always): x)
+        x = 1
+    !$omp end target
+end
+
+subroutine attach_never()
+    integer, pointer :: x
+
+!CHECK: func.func @{{.*}}attach_never{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK-NOT: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_BASE_ADDR]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) {
+    !$omp target map(attach(never): x)
+        x = 1
+    !$omp end target
+end
+
+subroutine attach_auto()
+    integer, pointer :: x
+!CHECK: func.func @{{.*}}attach_auto{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(always, to) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_ATTACH]] -> %{{.*}}, %[[MAP_BASE_ADDR]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) {
+    !$omp target map(attach(auto): x)
+        x = 1
+    !$omp end target
+end
+
+subroutine ref_ptr_ptee()
+    integer, pointer :: x
+
+!CHECK: func.func @{{.*}}ref_ptr_ptee{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptr, ref_ptee) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_ATTACH]] -> %{{.*}}, %[[MAP_BASE_ADDR]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) {
+    !$omp target map(ref_ptr_ptee, to: x)
+        x = 1
+    !$omp end target
+end
+
+subroutine ref_ptr()
+  integer, pointer :: x
+
+!CHECK: func.func @{{.*}}ref_ptr{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK-NOT: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK-NOT: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses({{.*}}) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptr) capture(ByRef) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: %[[BASE_ADDR_2:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptr) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_2]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_ATTACH]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) {
+    !$omp target map(ref_ptr, to: x)
+        x = 1
+    !$omp end target
+end
+
+subroutine ref_ptee()
+  integer, pointer :: x
+
+!CHECK: func.func @{{.*}}ref_ptee{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK-NOT: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses({{.*}}) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(attach, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_BASE_ADDR]] -> %{{.*}}, %[[MAP_ATTACH]] -> %{{.*}} : !fir.llvm_ptr<!fir.ref<i32>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) {
+    !$omp target map(ref_ptee, to: x)
+        x = 1
+    !$omp end target
+end
+
+subroutine ref_ptr_ptee_attach_never()
+    integer, pointer :: x
+
+!CHECK: func.func @{{.*}}ref_ptr_ptee_attach_never{{.*}}
+!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %{{.*}} {{{.*}}} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>)
+!CHECK: %[[BASE_ADDR_1:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK: %[[MAP_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptr, ref_ptee) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_1]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""}
+!CHECK: %[[MAP_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(to, ref_ptr, ref_ptee) capture(ByRef) members(%[[MAP_BASE_ADDR]] : [0] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK-NOT: %[[BASE_ADDR_2:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>>
+!CHECK-NOT: %[[MAP_ATTACH:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses({{.*}}) capture(ByRef) var_ptr_ptr(%[[BASE_ADDR_2]] : !fir.llvm_ptr<!fir.ref<i32>>, i32) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "x"}
+!CHECK: omp.target map_entries(%[[MAP_DESCRIPTOR]] -> %{{.*}}, %[[MAP_BASE_ADDR]] -> %{{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.llvm_ptr<!fir.ref<i32>>) {
+    !$omp target map(attach(never), ref_ptr_ptee, to: x)
+        x = 1
+    !$omp end target
+end



More information about the flang-commits mailing list