[Mlir-commits] [mlir] 877c39a - [OpenMPIRBuilder] Handle empty blocks in restoreIPandDebugLoc (#212535)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Aug 3 08:05:11 PDT 2026
Author: Abid Qadeer
Date: 2026-08-03T16:05:07+01:00
New Revision: 877c39aa8e15abe05c4c9562743d49b29689f2ce
URL: https://github.com/llvm/llvm-project/commit/877c39aa8e15abe05c4c9562743d49b29689f2ce
DIFF: https://github.com/llvm/llvm-project/commit/877c39aa8e15abe05c4c9562743d49b29689f2ce.diff
LOG: [OpenMPIRBuilder] Handle empty blocks in restoreIPandDebugLoc (#212535)
`restoreIPandDebugLoc` previously only recovered a debug location when
the insertion block was non-empty, using its last instruction. For an
empty block it left the current debug location unchanged so instructions
emitted afterwards could have wrong debug location.
This PR enhance `restoreIPandDebugLoc` to also handle the empty-block
case: when the insertion point is at the end of an empty block,
synthesize a location scoped to the parent function's subprogram
provided the function has debug metadata.
This helps us get a valid debug location when we switch to `CodeGenIP`
in `emitOffloadingArrays` even when `CodeGenIP` is pointing to an empty
`BB`.
Fixes https://github.com/llvm/llvm-project/issues/212488
Co-authored-by: Cursor <cursoragent at cursor.com>
Added:
mlir/test/Target/LLVMIR/openmp-target-in-reduction-debug.mlir
Modified:
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 9a49f4124da5e..ca191165c61c1 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -162,16 +162,31 @@ static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType) {
}
#endif
-/// This is wrapper over IRBuilderBase::restoreIP that also restores the current
-/// debug location to the last instruction in the specified basic block if the
-/// insert point points to the end of the block.
+/// This is a wrapper over IRBuilderBase::restoreIP that also restores a current
+/// debug location when the insert point is at the end of a block. It picks a
+/// location scoped to the current function: the block's last instruction
+/// location if the block is non-empty, otherwise a location synthesized from
+/// the function's subprogram (when the function has debug info).
static void restoreIPandDebugLoc(llvm::IRBuilderBase &Builder,
llvm::IRBuilderBase::InsertPoint IP) {
Builder.restoreIP(IP);
+ // When IP points at a real instruction, restoreIP (SetInsertPoint) already
+ // set the debug location from that instruction, so leave it alone.
llvm::BasicBlock *BB = Builder.GetInsertBlock();
- llvm::BasicBlock::iterator I = Builder.GetInsertPoint();
- if (!BB->empty() && I == BB->end())
+ if (Builder.GetInsertPoint() != BB->end())
+ return;
+
+ // At the end of a block, pick a location guaranteed to belong to the current
+ // insertion function's subprogram. Prefer the block's own last instruction;
+ // otherwise synthesize a location from the function's subprogram.
+ if (!BB->empty())
Builder.SetCurrentDebugLocation(BB->back().getStableDebugLoc());
+ else if (llvm::DISubprogram *FSP =
+ BB->getParent() ? BB->getParent()->getSubprogram() : nullptr) {
+ unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
+ Builder.SetCurrentDebugLocation(
+ llvm::DILocation::get(FSP->getContext(), Line, /*Column=*/0, FSP));
+ }
}
static bool hasGridValue(const Triple &T) {
@@ -10843,7 +10858,7 @@ Error OpenMPIRBuilder::emitOffloadingArrays(
CodeGenIP = Builder.saveIP();
Builder.restoreIP(AllocaIP);
Info.DevicePtrInfoMap[BPVal] = {BP, Builder.CreateAlloca(PtrTy)};
- Builder.restoreIP(CodeGenIP);
+ restoreIPandDebugLoc(Builder, CodeGenIP);
if (DeviceAddrCB)
DeviceAddrCB(I, Info.DevicePtrInfoMap[BPVal].second);
} else if (CombinedInfo.DevicePointers[I] == DeviceInfoTy::Address) {
diff --git a/mlir/test/Target/LLVMIR/openmp-target-in-reduction-debug.mlir b/mlir/test/Target/LLVMIR/openmp-target-in-reduction-debug.mlir
new file mode 100644
index 0000000000000..55ca27f39d5ea
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-target-in-reduction-debug.mlir
@@ -0,0 +1,61 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Regression test for debug-location preservation across offload-array codegen.
+//
+// When an omp.target is lowered for the host, OpenMPIRBuilder emits the host
+// fallback path that calls the outlined kernel stub directly. Building the
+// offload arrays (emitOffloadingArrays) temporarily moves the IRBuilder to the
+// alloca block, which clears the builder's current debug location. Before the
+// fix that location was never restored, so the inlinable fallback call to the
+// kernel stub was emitted with no !dbg attachment. In a function that has debug
+// info that call fails the verifier:
+//
+// inlinable function call in a function with debug info must have a !dbg
+// location
+//
+// The nesting below (parallel > taskgroup task_reduction > target in_reduction)
+// reproduces the exact state in which the location was dropped. This test pins
+// down that the host fallback call carries a debug location (and build does not
+// fail).
+
+#di_file = #llvm.di_file<"repro.f90" in "">
+#di_null_type = #llvm.di_null_type
+#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang", isOptimized = false, emissionKind = Full>
+#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_program, types = #di_null_type>
+#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #di_file, name = "foo", file = #di_file, subprogramFlags = "Definition", type = #sp_ty>
+#sp_tgt = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #di_file, name = "target_region", file = #di_file, subprogramFlags = "LocalToUnit|Definition", type = #sp_ty>
+#loc = loc("repro.f90":1:1)
+#loc_foo = loc(fused<#sp>[#loc])
+#loc_tgt = loc(fused<#sp_tgt>[#loc])
+
+module attributes {llvm.target_triple = "x86_64-unknown-linux-gnu", omp.is_gpu = false, omp.is_target_device = false, omp.target_triples = ["amdgcn-amd-amdhsa"], omp.version = #omp.version<version = 50>} {
+ omp.declare_reduction @add_reduction_i32 : i32 init {
+ ^bb0(%arg0: i32):
+ %0 = llvm.mlir.constant(0 : i32) : i32
+ omp.yield(%0 : i32)
+ } combiner {
+ ^bb0(%arg0: i32, %arg1: i32):
+ %0 = llvm.add %arg0, %arg1 : i32
+ omp.yield(%0 : i32)
+ }
+ llvm.func @foo_() {
+ %0 = llvm.mlir.constant(1 : i64) : i64
+ %1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
+ omp.parallel {
+ omp.taskgroup task_reduction(@add_reduction_i32 %1 -> %arg0 : !llvm.ptr) {
+ %2 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !llvm.ptr {name = "sum"}
+ omp.target kernel_type(generic) in_reduction(@add_reduction_i32 %arg0 : !llvm.ptr) map_entries(%2 -> %arg1 : !llvm.ptr) {
+ %c1 = llvm.mlir.constant(1 : i32) : i32
+ llvm.store %c1, %arg1 : i32, !llvm.ptr
+ omp.terminator
+ } loc(#loc_tgt)
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+ } loc(#loc_foo)
+}
+
+// CHECK-LABEL: define void @foo_(
+// CHECK: call void @__omp_offloading_{{.*}}_foo__{{.*}}(ptr %{{.+}}, ptr null), !dbg
More information about the Mlir-commits
mailing list