From f8b347bff813495c19310a70dd8d4a991ed03ccc Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 29 Apr 2025 12:31:00 +0100 Subject: [PATCH 1/3] [OpenMP] Improve debug info generation for outlined function. In OMPIRBuilder, a new function is created for the TargetOp. We also create a new DISubprogram for it. All the variables that were in the target region now have to be updated to have the correct scope. This after the fact updating of debug information becomes very difficult in certain cases. This PR is making the change that OMPIRBuilder will not generate a DISubprogram. The responsibility has been shifted to the frontend. This allows us to simplify the updating of debug records. The PR is made a bit more complicated by the the fact that in new scheme, the debug location already points to the new DISubprogram by the time it reaches convertOmpTarget. But we need some code generation in the parent function so we have to carefully manage the debug locations. This builds on `#138039` and fixes issue `#134991`. --- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 46 ++++--------------- .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 17 +++++++ .../Target/LLVMIR/omptarget-debug-nowait.mlir | 5 +- .../Target/LLVMIR/omptarget-debug-var-1.mlir | 13 ++++-- .../Target/LLVMIR/omptarget-debug-var-2.mlir | 13 ++++-- mlir/test/Target/LLVMIR/omptarget-debug.mlir | 8 +++- mlir/test/Target/LLVMIR/omptarget-debug2.mlir | 8 +++- .../LLVMIR/omptarget-parallel-llvm-debug.mlir | 8 +++- 8 files changed, 63 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index ddc9c5392f922..2fce5bc2428ca 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -6887,23 +6887,19 @@ static void FixupDebugInfoForOutlinedFunction( if (!NewSP) return; - DenseMap Cache; SmallDenseMap RemappedVariables; auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) { - auto NewSP = Func->getSubprogram(); DILocalVariable *&NewVar = RemappedVariables[OldVar]; // Only use cached variable if the arg number matches. This is important // so that DIVariable created for privatized variables are not discarded. if (NewVar && (arg == NewVar->getArg())) return NewVar; - DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram( - *OldVar->getScope(), *NewSP, Builder.getContext(), Cache); NewVar = llvm::DILocalVariable::get( - Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(), - OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(), - OldVar->getAlignInBits(), OldVar->getAnnotations()); + Builder.getContext(), OldVar->getScope(), OldVar->getName(), + OldVar->getFile(), OldVar->getLine(), OldVar->getType(), arg, + OldVar->getFlags(), OldVar->getAlignInBits(), OldVar->getAnnotations()); return NewVar; }; @@ -6917,7 +6913,8 @@ static void FixupDebugInfoForOutlinedFunction( ArgNo = std::get<1>(Iter->second) + 1; } } - DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); + if (ArgNo != 0) + DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo)); }; // The location and scope of variable intrinsics and records still point to @@ -6996,36 +6993,9 @@ static Expected createOutlinedFunction( // Save insert point. IRBuilder<>::InsertPointGuard IPG(Builder); - // If there's a DISubprogram associated with current function, then - // generate one for the outlined function. - if (Function *ParentFunc = BB->getParent()) { - if (DISubprogram *SP = ParentFunc->getSubprogram()) { - DICompileUnit *CU = SP->getUnit(); - DIBuilder DB(*M, true, CU); - DebugLoc DL = Builder.getCurrentDebugLocation(); - if (DL) { - // TODO: We are using nullopt for arguments at the moment. This will - // need to be updated when debug data is being generated for variables. - DISubroutineType *Ty = - DB.createSubroutineType(DB.getOrCreateTypeArray({})); - DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition | - DISubprogram::SPFlagOptimized | - DISubprogram::SPFlagLocalToUnit; - - DISubprogram *OutlinedSP = DB.createFunction( - CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty, - DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags); - - // Attach subprogram to the function. - Func->setSubprogram(OutlinedSP); - // Update the CurrentDebugLocation in the builder so that right scope - // is used for things inside outlined function. - Builder.SetCurrentDebugLocation( - DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(), - OutlinedSP, DL.getInlinedAt())); - } - } - } + // We will generate the entries in the outlined function but the debug + // location may still be pointing to the parent function. Reset it now. + Builder.SetCurrentDebugLocation(llvm::DebugLoc()); // Generate the region into the function. BasicBlock *EntryBB = BasicBlock::Create(Builder.getContext(), "entry", Func); diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 90ce06a0345c0..6a744a4aa6096 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -5299,6 +5299,20 @@ static LogicalResult convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { auto targetOp = cast(opInst); + // The current debug location already has the DISubprogram for the outlined + // function that will be created for the target op. We save it here so that + // we can set it on the outlined function. + llvm::DebugLoc OutlinedFnLoc = builder.getCurrentDebugLocation(); + // During the handling of target op, we will generate instructions in the + // parent function like call to oulined function or branch to new BasicBlock. + // We set the debug location here to parent function so that those get the + // correct debug locations. For outlined functions, the normal MLIR op + // conversion will automatically pick the correct location. + llvm::BasicBlock *parentBB = builder.GetInsertBlock(); + if (parentBB && !parentBB->empty()) + builder.SetCurrentDebugLocation(parentBB->back().getDebugLoc()); + else + builder.SetCurrentDebugLocation(llvm::DebugLoc()); if (failed(checkImplementationStatus(opInst))) return failure(); @@ -5395,6 +5409,9 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, assert(llvmParentFn && llvmOutlinedFn && "Both parent and outlined functions must exist at this point"); + if (OutlinedFnLoc && llvmParentFn->getSubprogram()) + llvmOutlinedFn->setSubprogram(OutlinedFnLoc->getScope()->getSubprogram()); + if (auto attr = llvmParentFn->getFnAttribute("target-cpu"); attr.isStringAttribute()) llvmOutlinedFn->addFnAttr(attr); diff --git a/mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir b/mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir index eaa88d9dd6053..3bd724f42e8ce 100644 --- a/mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir @@ -20,7 +20,7 @@ module attributes {omp.is_target_device = false} { ^bb3: // pred: ^bb1 llvm.store %13, %arg1 : i32, !llvm.ptr omp.terminator - } + } loc(#loc3) llvm.return } loc(#loc2) } @@ -34,7 +34,10 @@ module attributes {omp.is_target_device = false} { types = #di_null_type> #sp = #llvm.di_subprogram +#sp1 = #llvm.di_subprogram #loc1 = loc("test.f90":6:7) #loc2 = loc(fused<#sp>[#loc1]) +#loc3 = loc(fused<#sp1>[#loc1]) diff --git a/mlir/test/Target/LLVMIR/omptarget-debug-var-1.mlir b/mlir/test/Target/LLVMIR/omptarget-debug-var-1.mlir index ea92589bbd031..8f42995af23a8 100644 --- a/mlir/test/Target/LLVMIR/omptarget-debug-var-1.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-debug-var-1.mlir @@ -19,11 +19,13 @@ #g_var_expr = #llvm.di_global_variable_expression #sp = #llvm.di_subprogram, compileUnit = #cu, scope = #file, name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty> -#var_arr = #llvm.di_local_variable, compileUnit = #cu, scope = #file, + name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty> +#var_arr = #llvm.di_local_variable -#var_i = #llvm.di_local_variable -#var_x = #llvm.di_local_variable module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui32>>, llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_target_device = true} { @@ -47,7 +49,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr omp.terminator - } + } loc(#loc5) llvm.return } loc(#loc3) llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> { @@ -57,8 +59,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo #loc2 = loc("target.f90":11:7) #loc3 = loc(fused<#sp>[#loc2]) #loc4 = loc(fused<#g_var>[#loc1]) +#loc5 = loc(fused<#sp1>[#loc2]) -// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}}) +// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}}) // CHECK: !DILocalVariable(name: "dyn_ptr", arg: 1, scope: ![[SP]]{{.*}}flags: DIFlagArtificial) // CHECK: !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}}) // CHECK: !DILocalVariable(name: "arr", arg: 3, scope: ![[SP]]{{.*}}) diff --git a/mlir/test/Target/LLVMIR/omptarget-debug-var-2.mlir b/mlir/test/Target/LLVMIR/omptarget-debug-var-2.mlir index 22db86fd85e2c..11a07dfd9a180 100644 --- a/mlir/test/Target/LLVMIR/omptarget-debug-var-2.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-debug-var-2.mlir @@ -19,11 +19,13 @@ #g_var_expr = #llvm.di_global_variable_expression #sp = #llvm.di_subprogram, compileUnit = #cu, scope = #file, name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty> -#var_arr = #llvm.di_local_variable, compileUnit = #cu, scope = #file, + name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty> +#var_arr = #llvm.di_local_variable -#var_i = #llvm.di_local_variable -#var_x = #llvm.di_local_variable module attributes {omp.is_target_device = false} { @@ -45,7 +47,7 @@ module attributes {omp.is_target_device = false} { llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr omp.terminator - } + } loc(#loc5) llvm.return } loc(#loc3) llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> { @@ -55,8 +57,9 @@ module attributes {omp.is_target_device = false} { #loc2 = loc("target.f90":11:7) #loc3 = loc(fused<#sp>[#loc2]) #loc4 = loc(fused<#g_var>[#loc1]) +#loc5 = loc(fused<#sp1>[#loc2]) -// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}}) +// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}}) // CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[SP]]{{.*}}) // CHECK: !DILocalVariable(name: "arr", arg: 2, scope: ![[SP]]{{.*}}) // CHECK: !DILocalVariable(name: "i", arg: 3, scope: ![[SP]]{{.*}}) diff --git a/mlir/test/Target/LLVMIR/omptarget-debug.mlir b/mlir/test/Target/LLVMIR/omptarget-debug.mlir index 9c8344d69dc74..ab687f198b9b4 100644 --- a/mlir/test/Target/LLVMIR/omptarget-debug.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-debug.mlir @@ -10,7 +10,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo %13 = llvm.mlir.constant(1 : i32) : i32 llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2) omp.terminator - } + } loc(#loc4) llvm.return } loc(#loc3) } @@ -21,9 +21,13 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo #sp_ty = #llvm.di_subroutine_type #sp = #llvm.di_subprogram, compileUnit = #cu, scope = #file, name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty> +#sp1 = #llvm.di_subprogram, compileUnit = #cu, scope = #file, + name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition", + type = #sp_ty> #loc1 = loc("target.f90":1:1) #loc2 = loc("target.f90":46:3) #loc3 = loc(fused<#sp>[#loc1]) +#loc4 = loc(fused<#sp1>[#loc1]) -// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}}) +// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}}) // CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]]) diff --git a/mlir/test/Target/LLVMIR/omptarget-debug2.mlir b/mlir/test/Target/LLVMIR/omptarget-debug2.mlir index 78dc6e18a40a7..6cf75af38f916 100644 --- a/mlir/test/Target/LLVMIR/omptarget-debug2.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-debug2.mlir @@ -11,7 +11,7 @@ module attributes {omp.is_target_device = false} { %13 = llvm.mlir.constant(1 : i32) : i32 llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2) omp.terminator - } + } loc(#loc4) llvm.return } loc(#loc3) } @@ -22,9 +22,13 @@ module attributes {omp.is_target_device = false} { #sp_ty = #llvm.di_subroutine_type #sp = #llvm.di_subprogram, compileUnit = #cu, scope = #file, name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty> +#sp1 = #llvm.di_subprogram, compileUnit = #cu, scope = #file, + name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition", + type = #sp_ty> #loc1 = loc("target.f90":1:1) #loc2 = loc("target.f90":46:3) #loc3 = loc(fused<#sp>[#loc1]) +#loc4 = loc(fused<#sp1>[#loc1]) -// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}}) +// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}}) // CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]]) diff --git a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir index 3c45f1f1c76fb..b18338ea35cc3 100644 --- a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir @@ -6,8 +6,10 @@ #cu = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang", isOptimized = false, emissionKind = Full> #sp_ty = #llvm.di_subroutine_type #sp = #llvm.di_subprogram +#sp1 = #llvm.di_subprogram #int_ty = #llvm.di_basic_type #var_x = #llvm.di_local_variable +#var_x1 = #llvm.di_local_variable module attributes {dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr = dense<64> : vector<4xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.endianness" = "little", "dlti.stack_alignment" = 128 : i64, "dlti.mangling_mode" = "e">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", fir.target_cpu = "x86-64", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 21.0.0 (/home/haqadeer/work/src/aomp-llvm-project/flang 793f9220ab32f92fc3b253efec2e332c18090e53)", llvm.target_triple = "x86_64-unknown-linux-gnu", omp.is_gpu = false, omp.is_target_device = false, omp.requires = #omp, omp.target_triples = ["amdgcn-amd-amdhsa"], omp.version = #omp.version} { llvm.func @_QQmain() attributes {fir.bindc_name = "test", frame_pointer = #llvm.framePointerKind, target_cpu = "x86-64"} { %0 = llvm.mlir.constant(1 : i64) : i64 @@ -16,7 +18,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, %5 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "x"} omp.target map_entries(%5 -> %arg0 : !llvm.ptr) { %6 = llvm.mlir.constant(1 : i32) : i32 - llvm.intr.dbg.declare #var_x = %arg0 : !llvm.ptr loc(#loc2) + llvm.intr.dbg.declare #var_x1 = %arg0 : !llvm.ptr loc(#loc3) omp.parallel { %7 = llvm.load %arg0 : !llvm.ptr -> i32 %8 = llvm.add %7, %6 : i32 @@ -24,12 +26,14 @@ module attributes {dlti.dl_spec = #dlti.dl_spec : vector<2xi64>, omp.terminator } omp.terminator - } + } loc(#loc4) llvm.return } loc(#loc10) } #loc1 = loc("target.f90":1:7) #loc2 = loc("target.f90":3:18) +#loc3 = loc("target.f90":6:18) +#loc4 = loc(fused<#sp1>[#loc3]) #loc10 = loc(fused<#sp>[#loc1]) From b0d08b3c59fd2b2ef748d6a6b050dc3bd049ec2e Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 20 May 2025 18:11:41 +0100 Subject: [PATCH 2/3] Handle review comments. The new way to set debug location can better handle empty basic block or function. A testcase is added as well. --- .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 28 +++++++++++-------- .../Target/LLVMIR/omptarget-debug-empty.mlir | 27 ++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 mlir/test/Target/LLVMIR/omptarget-debug-empty.mlir diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 6a744a4aa6096..adf1727da86ca 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -5302,19 +5302,23 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, // The current debug location already has the DISubprogram for the outlined // function that will be created for the target op. We save it here so that // we can set it on the outlined function. - llvm::DebugLoc OutlinedFnLoc = builder.getCurrentDebugLocation(); + llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation(); + if (failed(checkImplementationStatus(opInst))) + return failure(); + // During the handling of target op, we will generate instructions in the - // parent function like call to oulined function or branch to new BasicBlock. - // We set the debug location here to parent function so that those get the - // correct debug locations. For outlined functions, the normal MLIR op + // parent function like call to the oulined function or branch to a new + // BasicBlock. We set the debug location here to parent function so that those + // get the correct debug locations. For outlined functions, the normal MLIR op // conversion will automatically pick the correct location. llvm::BasicBlock *parentBB = builder.GetInsertBlock(); - if (parentBB && !parentBB->empty()) - builder.SetCurrentDebugLocation(parentBB->back().getDebugLoc()); - else - builder.SetCurrentDebugLocation(llvm::DebugLoc()); - if (failed(checkImplementationStatus(opInst))) - return failure(); + assert(parentBB); + llvm::Function *parentLLVMFn = parentBB->getParent(); + assert(parentLLVMFn); + if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram()) + builder.SetCurrentDebugLocation(llvm::DILocation::get( + parentLLVMFn->getContext(), outlinedFnLoc.getLine(), + outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt())); llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); bool isTargetDevice = ompBuilder->Config.isTargetDevice(); @@ -5409,8 +5413,8 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, assert(llvmParentFn && llvmOutlinedFn && "Both parent and outlined functions must exist at this point"); - if (OutlinedFnLoc && llvmParentFn->getSubprogram()) - llvmOutlinedFn->setSubprogram(OutlinedFnLoc->getScope()->getSubprogram()); + if (outlinedFnLoc && llvmParentFn->getSubprogram()) + llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram()); if (auto attr = llvmParentFn->getFnAttribute("target-cpu"); attr.isStringAttribute()) diff --git a/mlir/test/Target/LLVMIR/omptarget-debug-empty.mlir b/mlir/test/Target/LLVMIR/omptarget-debug-empty.mlir new file mode 100644 index 0000000000000..45e5d2612e2c2 --- /dev/null +++ b/mlir/test/Target/LLVMIR/omptarget-debug-empty.mlir @@ -0,0 +1,27 @@ +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s + +module attributes {omp.is_target_device = false} { + llvm.func @test() { + omp.target { + omp.terminator + } loc(#loc4) + llvm.return + } loc(#loc3) +} +#file = #llvm.di_file<"target.f90" in ""> +#cu = #llvm.di_compile_unit, + sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false, + emissionKind = Full> +#sp_ty = #llvm.di_subroutine_type +#sp = #llvm.di_subprogram, compileUnit = #cu, scope = #file, + name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty> +#sp1 = #llvm.di_subprogram, compileUnit = #cu, scope = #file, + name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition", + type = #sp_ty> +#loc1 = loc("target.f90":1:1) +#loc2 = loc("target.f90":46:3) +#loc3 = loc(fused<#sp>[#loc1]) +#loc4 = loc(fused<#sp1>[#loc2]) + +// CHECK: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}}) + From d9c78aad3ee1cecfe1b354436a2e4305b83d13fa Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Wed, 18 Jun 2025 16:10:18 +0100 Subject: [PATCH 3/3] Add message in asserts. --- .../LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index adf1727da86ca..1d04df989145d 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -5312,9 +5312,9 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, // get the correct debug locations. For outlined functions, the normal MLIR op // conversion will automatically pick the correct location. llvm::BasicBlock *parentBB = builder.GetInsertBlock(); - assert(parentBB); + assert(parentBB && "No insert block is set for the builder"); llvm::Function *parentLLVMFn = parentBB->getParent(); - assert(parentLLVMFn); + assert(parentLLVMFn && "Parent Function must be valid"); if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram()) builder.SetCurrentDebugLocation(llvm::DILocation::get( parentLLVMFn->getContext(), outlinedFnLoc.getLine(),