[llvm] [mlir] [Flang][OpenMP][MLIR] Attach source location to target/target-data runtime c… (PR #222389)

Jason Van Beusekom via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 10:50:00 PDT 2026


https://github.com/Jason-Van-Beusekom updated https://github.com/llvm/llvm-project/pull/222389

>From b3cda4c89b93ab5d83eb740a6b54ecae78aa9789 Mon Sep 17 00:00:00 2001
From: Jason Van Beusekom <jason.van-beusekom at hpe.com>
Date: Wed, 9 Sep 2026 10:48:41 -0500
Subject: [PATCH 1/3] [OpenMP][MLIR] Attach source location to
 target/target-data runtime calls

---
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       |  5 +-
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 24 +++++----
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 53 +++++++++++++++----
 mlir/test/Target/LLVMIR/omptarget-llvm.mlir   | 10 ++--
 mlir/test/Target/LLVMIR/omptarget-nowait.mlir |  4 +-
 .../Target/LLVMIR/omptarget-region-llvm.mlir  |  2 +-
 ...target-target-data-source-loc-nodebug.mlir | 28 ++++++++++
 ...rget-target-region-source-loc-nodebug.mlir | 23 ++++++++
 .../omptarget-target-region-source-loc.mlir   | 40 ++++++++++++++
 9 files changed, 161 insertions(+), 28 deletions(-)
 create mode 100644 mlir/test/Target/LLVMIR/omptarget-target-data-source-loc-nodebug.mlir
 create mode 100644 mlir/test/Target/LLVMIR/omptarget-target-region-source-loc-nodebug.mlir
 create mode 100644 mlir/test/Target/LLVMIR/omptarget-target-region-source-loc.mlir

diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index b87f051c6e6a46..d1a84539bde267 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -3837,6 +3837,9 @@ class OpenMPIRBuilder {
   ///        parent function, so it cannot be used for code emitted inside the
   ///        outlined function. If this is empty, such code is emitted without a
   ///        debug location.
+  /// \param RTLocOverride Optional runtime source-location identifier to report
+  ///        to the offload runtime for the kernel launch. When null, the
+  ///        identifier is derived from \p Loc.
   LLVM_ABI InsertPointOrErrorTy createTarget(
       const LocationDescription &Loc, bool IsOffloadEntry,
       OpenMPIRBuilder::InsertPointTy AllocaIP,
@@ -3853,7 +3856,7 @@ class OpenMPIRBuilder {
       Value *DynCGroupMem = nullptr,
       omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback =
           omp::OMPDynGroupprivateFallbackType::Abort,
-      DebugLoc OutlinedFnLoc = {});
+      DebugLoc OutlinedFnLoc = {}, Value *RTLocOverride = nullptr);
 
   /// Returns __kmpc_for_static_init_* runtime function for the specified
   /// size \a IVSize and sign \a IVSigned. Will create a distribute call
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 3173fecc5d5269..a7cbc7b1a556c9 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -10094,6 +10094,7 @@ Error OpenMPIRBuilder::emitOffloadingArraysAndArgs(
 
 static void emitTargetCall(
     OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder,
+    const OpenMPIRBuilder::LocationDescription &Loc, Value *RTLocOverride,
     OpenMPIRBuilder::InsertPointTy AllocaIP,
     ArrayRef<BasicBlock *> DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info,
     const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs,
@@ -10233,10 +10234,13 @@ static void emitTargetCall(
     }
 
     unsigned NumTargetItems = Info.NumberOfPtrs;
-    uint32_t SrcLocStrSize;
-    Constant *SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
-    Value *RTLoc = OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize,
-                                               llvm::omp::IdentFlag(0), 0);
+    Value *RTLoc = RTLocOverride;
+    if (!RTLoc) {
+      uint32_t SrcLocStrSize;
+      Constant *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(Loc, SrcLocStrSize);
+      RTLoc = OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize,
+                                          llvm::omp::IdentFlag(0), 0);
+    }
 
     Value *TripCount = RuntimeAttrs.LoopTripCount
                            ? Builder.CreateIntCast(RuntimeAttrs.LoopTripCount,
@@ -10301,8 +10305,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTarget(
     OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
     CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies,
     bool HasNowait, Value *DynCGroupMem,
-    OMPDynGroupprivateFallbackType DynCGroupMemFallback,
-    DebugLoc OutlinedFnLoc) {
+    OMPDynGroupprivateFallbackType DynCGroupMemFallback, DebugLoc OutlinedFnLoc,
+    Value *RTLocOverride) {
 
   if (!updateToLocation(Loc))
     return InsertPointTy();
@@ -10323,10 +10327,10 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTarget(
   // to make a remote call (offload) to the previously outlined function
   // that represents the target region. Do that now.
   if (!Config.isTargetDevice())
-    emitTargetCall(*this, Builder, AllocaIP, DeallocBlocks, Info, DefaultAttrs,
-                   RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
-                   GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
-                   DynCGroupMem, DynCGroupMemFallback);
+    emitTargetCall(*this, Builder, Loc, RTLocOverride, AllocaIP, DeallocBlocks,
+                   Info, DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn,
+                   OutlinedFnID, Inputs, GenMapInfoCB, CustomMapperCB,
+                   Dependencies, HasNowait, DynCGroupMem, DynCGroupMemFallback);
   return Builder.saveIP();
 }
 
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index d8b596ad9c83e8..ae0f4d1ab02ed8 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -8438,6 +8438,20 @@ emitUserDefinedMapper(Operation *op, llvm::IRBuilderBase &builder,
   return *newFn;
 }
 
+static llvm::Value *
+getFallbackKernelLaunchIdent(llvm::IRBuilderBase &builder,
+                             llvm::OpenMPIRBuilder &ompBuilder, Operation *op) {
+  auto fileLoc = op->getLoc()->findInstanceOf<FileLineColLoc>();
+  if (!fileLoc)
+    return nullptr;
+  uint32_t strSize;
+  llvm::Function *parentFn = builder.GetInsertBlock()->getParent();
+  llvm::StringRef fnName = parentFn ? parentFn->getName() : "";
+  llvm::Constant *srcStr = LLVM::createSourceLocStrFromLocation(
+      fileLoc, ompBuilder, fnName, strSize);
+  return ompBuilder.getOrCreateIdent(srcStr, strSize);
+}
+
 static LogicalResult
 convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder,
                      LLVM::ModuleTranslation &moduleTranslation) {
@@ -8663,16 +8677,26 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder,
   llvm::SmallVector<llvm::BasicBlock *> deallocBlocks;
   llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
       findAllocInsertPoints(builder, moduleTranslation, &deallocBlocks);
+
+  // Without -g there is no debug location to carry the data region's source
+  // position to the runtime.
+  llvm::Value *srcLocOverride =
+      (isOffloadEntry && !ompLoc.DL)
+          ? getFallbackKernelLaunchIdent(builder, *ompBuilder, op)
+          : nullptr;
+
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
     if (isa<omp::TargetDataOp>(op))
-      return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
-                                          deallocBlocks, deviceID, ifCond, info,
-                                          genMapInfoCB, customMapperCB,
-                                          /*MapperFunc=*/nullptr, bodyGenCB,
-                                          /*DeviceAddrCB=*/nullptr);
-    return ompBuilder->createTargetData(ompLoc, allocaIP, builder.saveIP(),
-                                        deallocBlocks, deviceID, ifCond, info,
-                                        genMapInfoCB, customMapperCB, &RTLFn);
+      return ompBuilder->createTargetData(
+          ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
+          info, genMapInfoCB, customMapperCB,
+          /*MapperFunc=*/nullptr, bodyGenCB,
+          /*DeviceAddrCB=*/nullptr, srcLocOverride);
+    return ompBuilder->createTargetData(
+        ompLoc, allocaIP, builder.saveIP(), deallocBlocks, deviceID, ifCond,
+        info, genMapInfoCB, customMapperCB, &RTLFn,
+        /*BodyGenCB=*/nullptr,
+        /*DeviceAddrCB=*/nullptr, srcLocOverride);
   }();
 
   if (failed(handleError(afterIP, *op)))
@@ -9835,12 +9859,23 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
   llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
       getDynGroupprivateFallbackType(targetOp.getDynGroupprivateFallbackAttr());
 
+  // Without -g there is no debug location to carry the target region's source
+  // position to the runtime. Build a kernel-launch identifier from the op's own
+  // MLIR location so the runtime can still report file/line without -g. Only on
+  // the host offload path that actually emits the kernel launch, to avoid
+  // creating an unused identifier on the device.
+  llvm::Value *rtLocOverride =
+      (!isTargetDevice && isOffloadEntry && !ompLoc.DL)
+          ? getFallbackKernelLaunchIdent(builder, *ompBuilder, targetOp)
+          : nullptr;
+
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
       moduleTranslation.getOpenMPBuilder()->createTarget(
           ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), deallocBlocks,
           info, entryInfo, defaultAttrs, runtimeAttrs, ifCond, kernelInput,
           genMapInfoCB, bodyCB, argAccessorCB, customMapperCB, dds,
-          targetOp.getNowait(), dynSizeVal, fallbackType, outlinedFnDbgLoc);
+          targetOp.getNowait(), dynSizeVal, fallbackType, outlinedFnDbgLoc,
+          rtLocOverride);
 
   if (failed(handleError(afterIP, opInst)))
     return failure();
diff --git a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
index 2aaf916fa2978c..908e8f0a02fc14 100644
--- a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir
@@ -204,7 +204,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // CHECK:         store ptr null, ptr %[[VAL_36]], align 8
 // CHECK:         %[[VAL_37:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
 // CHECK:         %[[VAL_38:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
-// CHECK:         call void @__tgt_target_data_end_mapper(ptr @3, i64 %[[DEV_I64_END]], i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr @.offload_mapnames.3, ptr null)
+// CHECK:         call void @__tgt_target_data_end_mapper(ptr @7, i64 %[[DEV_I64_END]], i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr @.offload_mapnames.3, ptr null)
 // CHECK:         br label %[[VAL_39:.*]]
 // CHECK:       omp_if.else8:                                     ; preds = %[[VAL_25]]
 // CHECK:         br label %[[VAL_39]]
@@ -502,7 +502,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // CHECK:         store ptr null, ptr %[[MAPPERS_VAL]], align 8
 // CHECK:         %[[BASEPTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:         %[[PTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:         call void @__tgt_target_data_update_mapper(ptr @2, i64 -1, i32 1, ptr %[[BASEPTRS_VAL_2]], ptr %[[PTRS_VAL_2]], ptr @{{.*}}, ptr @{{.*}}, ptr @{{.*}}, ptr null)
+// CHECK:         call void @__tgt_target_data_update_mapper(ptr @4, i64 -1, i32 1, ptr %[[BASEPTRS_VAL_2]], ptr %[[PTRS_VAL_2]], ptr @{{.*}}, ptr @{{.*}}, ptr @{{.*}}, ptr null)
 
 // CHECK:         ret void
 
@@ -549,12 +549,12 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // CHECK:         store ptr @.omp_mapper._QQFmy_testmy_mapper, ptr %[[VAL_9]], align 8
 // CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
 // CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
-// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @4, i64 -1, i32 1, ptr %[[VAL_10]], ptr %[[VAL_11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %[[VAL_2]])
+// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_10]], ptr %[[VAL_11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %[[VAL_2]])
 // CHECK:         %[[VAL_12:.*]] = getelementptr %[[VAL_4]], ptr %[[VAL_3]], i32 0, i32 0
 // CHECK:         store i32 10, ptr %[[VAL_12]], align 4
 // CHECK:         %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
 // CHECK:         %[[VAL_14:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
-// CHECK:         call void @__tgt_target_data_end_mapper(ptr @4, i64 -1, i32 1, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %[[VAL_2]])
+// CHECK:         call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %[[VAL_2]])
 // CHECK:         ret void
 
 // CHECK-LABEL: define internal void @.omp_mapper._QQFmy_testmy_mapper
@@ -603,7 +603,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // propagated to each entry the mapper pushes.
 // CHECK:         %[[VAL_MODMASK:.*]] = and i64 %{{.*}}, 1036
 // CHECK:         %[[VAL_MTYPEMOD:.*]] = or i64 %[[VAL_61]], %[[VAL_MODMASK]]
-// CHECK:         call void @__tgt_push_mapper_component(ptr %[[VAL_37]], ptr %[[VAL_45]], ptr %[[VAL_45]], i64 4, i64 %[[VAL_MTYPEMOD]], ptr @2)
+// CHECK:         call void @__tgt_push_mapper_component(ptr %[[VAL_37]], ptr %[[VAL_45]], ptr %[[VAL_45]], i64 4, i64 %[[VAL_MTYPEMOD]], ptr @4)
 // CHECK:         %[[VAL_44]] = getelementptr %[[VAL_18]], ptr %[[VAL_43]], i32 1
 // CHECK:         %[[VAL_62:.*]] = icmp eq ptr %[[VAL_44]], %[[VAL_17]]
 // CHECK:         br i1 %[[VAL_62]], label %[[VAL_63:.*]], label %[[VAL_41]]
diff --git a/mlir/test/Target/LLVMIR/omptarget-nowait.mlir b/mlir/test/Target/LLVMIR/omptarget-nowait.mlir
index 39d5300552678c..4e75f0bb871919 100644
--- a/mlir/test/Target/LLVMIR/omptarget-nowait.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-nowait.mlir
@@ -40,7 +40,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // CHECK: %[[SIZES_GEP:.*]] = getelementptr inbounds [5 x i64], ptr %[[SIZES]], i32 0, i32 0
 
 // CHECK: %[[GL_THRD_NUM:.*]] = call i32 @__kmpc_global_thread_num
-// CHECK: %[[TASK_DESC:.*]] = call ptr @__kmpc_omp_target_task_alloc(ptr @4, i32 {{.*}}, i32 0, i64 160, i64 16, ptr [[TGT_TSK_PRXY_FNC:.*]], i64 -1)
+// CHECK: %[[TASK_DESC:.*]] = call ptr @__kmpc_omp_target_task_alloc(ptr @6, i32 {{.*}}, i32 0, i64 160, i64 16, ptr [[TGT_TSK_PRXY_FNC:.*]], i64 -1)
 // CHECK: %[[TSK_PTR:.*]] = getelementptr inbounds nuw %struct.[[TSK_WTH_PRVTS]], ptr %[[TASK_DESC]], i32 0, i32 0
 // CHECK: %[[SHAREDS:.*]] = getelementptr inbounds nuw %struct.kmp_task_ompbuilder_t, ptr %[[TSK_PTR]], i32 0, i32 0
 // CHECK: %[[SHAREDS_PTR:.*]] = load ptr, ptr %[[SHAREDS]], align 8
@@ -52,7 +52,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[VAL_53]], ptr align 1 %[[PTRS_GEP]], i64 40, i1 false)
 // CHECK: %[[VAL_54:.*]] = getelementptr inbounds nuw %struct.[[PRVTS]], ptr %[[VAL_50]], i32 0, i32 2
 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[VAL_54]], ptr align 1 %[[SIZES_GEP]], i64 40, i1 false)
-// CHECK: %[[VAL_55:.*]] = call i32 @__kmpc_omp_task(ptr @4, i32 %[[GL_THRD_NUM]], ptr %[[TASK_DESC]])
+// CHECK: %[[VAL_55:.*]] = call i32 @__kmpc_omp_task(ptr @6, i32 %[[GL_THRD_NUM]], ptr %[[TASK_DESC]])
 
 // CHECK: define internal void @[[WORKER:.*]](i32 {{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}}) {
 
diff --git a/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir
index e40d7320279fa1..21969ce9751d8c 100644
--- a/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir
@@ -42,7 +42,7 @@ module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-a
 // CHECK: omp_offload.cont:
 
 // CHECK: define void @omp_target_no_map()
-// CHECK: call i32 @__tgt_target_kernel(ptr @4, i64 -1, i32 -1, i32 0, ptr @.__omp_offloading_[[DEV:.*]]_[[FIL:.*]]_omp_target_no_map_l[[LINE2:.*]].region_id, ptr %kernel_args)
+// CHECK: call i32 @__tgt_target_kernel(ptr @6, i64 -1, i32 -1, i32 0, ptr @.__omp_offloading_[[DEV:.*]]_[[FIL:.*]]_omp_target_no_map_l[[LINE2:.*]].region_id, ptr %kernel_args)
 
 // CHECK: br i1 %{{.*}}, label %omp_offload.failed, label %omp_offload.cont
 // CHECK: omp_offload.failed:
diff --git a/mlir/test/Target/LLVMIR/omptarget-target-data-source-loc-nodebug.mlir b/mlir/test/Target/LLVMIR/omptarget-target-data-source-loc-nodebug.mlir
new file mode 100644
index 00000000000000..7775b68e08baae
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/omptarget-target-data-source-loc-nodebug.mlir
@@ -0,0 +1,28 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Without debug info, the target data begin/end mappers must still carry the
+// region's source location (built from the omp.target_data op's own MLIR
+// location) instead of the default ";unknown;unknown;0;0;;". Requires
+// target_triples so an offloading entry is generated.
+
+module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+  llvm.func @_QPtdata() {
+    %0 = llvm.mlir.constant(1 : i64) : i64
+    %1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
+    %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) name("") -> !llvm.ptr
+    omp.target_data map_entries(%2 : !llvm.ptr) {
+      %3 = llvm.mlir.constant(99 : i32) : i32
+      llvm.store %3, %1 : i32, !llvm.ptr
+      omp.terminator
+    } loc(#loc1)
+    llvm.return
+  }
+}
+#loc1 = loc("target_data.f90":7:9)
+
+// The begin and end mappers of the same region share one identifier that
+// references the real file/line source-location string.
+// CHECK: @[[SRC:[0-9]+]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";target_data.f90;{{[^;]*}};7;9;;\00"
+// CHECK: @[[IDENT:[0-9]+]] = private unnamed_addr constant %struct.ident_t {{.*}}ptr @[[SRC]] }
+// CHECK: call void @__tgt_target_data_begin_mapper(ptr @[[IDENT]],
+// CHECK: call void @__tgt_target_data_end_mapper(ptr @[[IDENT]],
diff --git a/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc-nodebug.mlir b/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc-nodebug.mlir
new file mode 100644
index 00000000000000..de8e800f393d69
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc-nodebug.mlir
@@ -0,0 +1,23 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Even without debug info (no -g), the host-side __tgt_target_kernel launch
+// should carry the target region's source location, taken from the op's own
+// MLIR location, rather than the default ";unknown;unknown;0;0;;" identifier.
+
+module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+  llvm.func @_QQmain() {
+    %0 = llvm.mlir.constant(1 : i32) : i32
+    %1 = llvm.alloca %0 x i32 : (i32) -> !llvm.ptr
+    %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) name("") -> !llvm.ptr
+    omp.target kernel_type(generic) map_entries(%2 -> %arg0 : !llvm.ptr) {
+      %3 = llvm.mlir.constant(1 : i32) : i32
+      llvm.store %3, %arg0 : i32, !llvm.ptr
+      omp.terminator
+    } loc("kernel.f90":7:3)
+    llvm.return
+  }
+}
+
+// CHECK: @[[SRCLOC:[0-9]+]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";kernel.f90;{{[^;]*}};7;3;;\00"
+// CHECK: @[[IDENT:[0-9]+]] = private unnamed_addr constant %struct.ident_t {{.*}}ptr @[[SRCLOC]] }
+// CHECK: call i32 @__tgt_target_kernel(ptr @[[IDENT]],
diff --git a/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc.mlir b/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc.mlir
new file mode 100644
index 00000000000000..6abd70c14997d2
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/omptarget-target-region-source-loc.mlir
@@ -0,0 +1,40 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Verify that the host-side __tgt_target_kernel launch is emitted with the
+// target region's real source location (file/line/column) rather than the
+// default ";unknown;unknown;0;0;;" identifier. Requires target_triples so that
+// an offloading entry (and therefore the kernel launch) is generated.
+
+module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+  llvm.func @_QQmain() {
+    %0 = llvm.mlir.constant(1 : i32) : i32
+    %1 = llvm.alloca %0 x i32 : (i32) -> !llvm.ptr
+    %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) name("") -> !llvm.ptr
+    omp.target kernel_type(generic) map_entries(%2 -> %arg0 : !llvm.ptr) {
+      %3 = llvm.mlir.constant(1 : i32) : i32
+      llvm.store %3, %arg0 : i32, !llvm.ptr loc(#loc2)
+      omp.terminator
+    } loc(#loc4)
+    llvm.return
+  } loc(#loc3)
+}
+#file = #llvm.di_file<"target.f90" in "">
+#cu = #llvm.di_compile_unit<id = distinct[0]<>,
+ sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
+ emissionKind = LineTablesOnly>
+#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
+#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
+ name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
+#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
+ name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
+ type = #sp_ty>
+#loc1 = loc("target.f90":10:5)
+#loc2 = loc("target.f90":11:7)
+#loc3 = loc(fused<#sp>[#loc1])
+#loc4 = loc(fused<#sp1>[#loc1])
+
+// The kernel launch identifier must reference a source-location string that
+// carries the real file name and position, not ";unknown;unknown;0;0;;".
+// CHECK: @[[SRCLOC:[0-9]+]] = private unnamed_addr constant [{{[0-9]+}} x i8] c";target.f90;{{[^;]*}};10;5;;\00"
+// CHECK: @[[IDENT:[0-9]+]] = private unnamed_addr constant %struct.ident_t {{.*}}ptr @[[SRCLOC]] }
+// CHECK: call i32 @__tgt_target_kernel(ptr @[[IDENT]],

>From 300127da40622343ed95e512856a11a32e58ec14 Mon Sep 17 00:00:00 2001
From: Jason Van Beusekom <jason.van-beusekom at hpe.com>
Date: Thu, 10 Sep 2026 16:47:09 -0500
Subject: [PATCH 2/3] feedback

---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 27 +++++++++----------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index ae0f4d1ab02ed8..dc8134eb8853d1 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -8438,9 +8438,9 @@ emitUserDefinedMapper(Operation *op, llvm::IRBuilderBase &builder,
   return *newFn;
 }
 
-static llvm::Value *
-getFallbackKernelLaunchIdent(llvm::IRBuilderBase &builder,
-                             llvm::OpenMPIRBuilder &ompBuilder, Operation *op) {
+static llvm::Value *getSourceLocIdentFromOp(llvm::IRBuilderBase &builder,
+                                            llvm::OpenMPIRBuilder &ompBuilder,
+                                            Operation *op) {
   auto fileLoc = op->getLoc()->findInstanceOf<FileLineColLoc>();
   if (!fileLoc)
     return nullptr;
@@ -8678,12 +8678,11 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder,
   llvm::OpenMPIRBuilder::InsertPointTy allocaIP =
       findAllocInsertPoints(builder, moduleTranslation, &deallocBlocks);
 
-  // Without -g there is no debug location to carry the data region's source
-  // position to the runtime.
+  // Pass the region's source location to the runtime, taken from the op's own
+  // location; only offloading entries emit the mapper calls that consume it.
   llvm::Value *srcLocOverride =
-      (isOffloadEntry && !ompLoc.DL)
-          ? getFallbackKernelLaunchIdent(builder, *ompBuilder, op)
-          : nullptr;
+      isOffloadEntry ? getSourceLocIdentFromOp(builder, *ompBuilder, op)
+                     : nullptr;
 
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP = [&]() {
     if (isa<omp::TargetDataOp>(op))
@@ -9859,14 +9858,12 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
   llvm::omp::OMPDynGroupprivateFallbackType fallbackType =
       getDynGroupprivateFallbackType(targetOp.getDynGroupprivateFallbackAttr());
 
-  // Without -g there is no debug location to carry the target region's source
-  // position to the runtime. Build a kernel-launch identifier from the op's own
-  // MLIR location so the runtime can still report file/line without -g. Only on
-  // the host offload path that actually emits the kernel launch, to avoid
-  // creating an unused identifier on the device.
+  // Pass the target region's source location to the runtime, taken from the
+  // op's own location. Restricted to the host offload path that actually emits
+  // the kernel launch, to avoid creating an unused identifier on the device.
   llvm::Value *rtLocOverride =
-      (!isTargetDevice && isOffloadEntry && !ompLoc.DL)
-          ? getFallbackKernelLaunchIdent(builder, *ompBuilder, targetOp)
+      (!isTargetDevice && isOffloadEntry)
+          ? getSourceLocIdentFromOp(builder, *ompBuilder, targetOp)
           : nullptr;
 
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =

>From 4e26833542823567ebc95a530ed1aff74ef37f6e Mon Sep 17 00:00:00 2001
From: Jason Van Beusekom <jason.van-beusekom at hpe.com>
Date: Fri, 11 Sep 2026 14:40:07 -0500
Subject: [PATCH 3/3] feedback

---
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index a7cbc7b1a556c9..a2d186f9008c37 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -10093,8 +10093,7 @@ Error OpenMPIRBuilder::emitOffloadingArraysAndArgs(
 }
 
 static void emitTargetCall(
-    OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder,
-    const OpenMPIRBuilder::LocationDescription &Loc, Value *RTLocOverride,
+    OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Value *RTLocOverride,
     OpenMPIRBuilder::InsertPointTy AllocaIP,
     ArrayRef<BasicBlock *> DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info,
     const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs,
@@ -10237,7 +10236,8 @@ static void emitTargetCall(
     Value *RTLoc = RTLocOverride;
     if (!RTLoc) {
       uint32_t SrcLocStrSize;
-      Constant *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(Loc, SrcLocStrSize);
+      Constant *SrcLocStr =
+          OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
       RTLoc = OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize,
                                           llvm::omp::IdentFlag(0), 0);
     }
@@ -10327,10 +10327,10 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createTarget(
   // to make a remote call (offload) to the previously outlined function
   // that represents the target region. Do that now.
   if (!Config.isTargetDevice())
-    emitTargetCall(*this, Builder, Loc, RTLocOverride, AllocaIP, DeallocBlocks,
-                   Info, DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn,
-                   OutlinedFnID, Inputs, GenMapInfoCB, CustomMapperCB,
-                   Dependencies, HasNowait, DynCGroupMem, DynCGroupMemFallback);
+    emitTargetCall(*this, Builder, RTLocOverride, AllocaIP, DeallocBlocks, Info,
+                   DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
+                   Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
+                   HasNowait, DynCGroupMem, DynCGroupMemFallback);
   return Builder.saveIP();
 }
 



More information about the llvm-commits mailing list