[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