Skip to content

Commit f8b347b

Browse files
committed
[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`.
1 parent d8e8ab7 commit f8b347b

File tree

8 files changed

+63
-55
lines changed

8 files changed

+63
-55
lines changed

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6887,23 +6887,19 @@ static void FixupDebugInfoForOutlinedFunction(
68876887
if (!NewSP)
68886888
return;
68896889

6890-
DenseMap<const MDNode *, MDNode *> Cache;
68916890
SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables;
68926891

68936892
auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) {
6894-
auto NewSP = Func->getSubprogram();
68956893
DILocalVariable *&NewVar = RemappedVariables[OldVar];
68966894
// Only use cached variable if the arg number matches. This is important
68976895
// so that DIVariable created for privatized variables are not discarded.
68986896
if (NewVar && (arg == NewVar->getArg()))
68996897
return NewVar;
69006898

6901-
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
6902-
*OldVar->getScope(), *NewSP, Builder.getContext(), Cache);
69036899
NewVar = llvm::DILocalVariable::get(
6904-
Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(),
6905-
OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(),
6906-
OldVar->getAlignInBits(), OldVar->getAnnotations());
6900+
Builder.getContext(), OldVar->getScope(), OldVar->getName(),
6901+
OldVar->getFile(), OldVar->getLine(), OldVar->getType(), arg,
6902+
OldVar->getFlags(), OldVar->getAlignInBits(), OldVar->getAnnotations());
69076903
return NewVar;
69086904
};
69096905

@@ -6917,7 +6913,8 @@ static void FixupDebugInfoForOutlinedFunction(
69176913
ArgNo = std::get<1>(Iter->second) + 1;
69186914
}
69196915
}
6920-
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
6916+
if (ArgNo != 0)
6917+
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
69216918
};
69226919

69236920
// The location and scope of variable intrinsics and records still point to
@@ -6996,36 +6993,9 @@ static Expected<Function *> createOutlinedFunction(
69966993

69976994
// Save insert point.
69986995
IRBuilder<>::InsertPointGuard IPG(Builder);
6999-
// If there's a DISubprogram associated with current function, then
7000-
// generate one for the outlined function.
7001-
if (Function *ParentFunc = BB->getParent()) {
7002-
if (DISubprogram *SP = ParentFunc->getSubprogram()) {
7003-
DICompileUnit *CU = SP->getUnit();
7004-
DIBuilder DB(*M, true, CU);
7005-
DebugLoc DL = Builder.getCurrentDebugLocation();
7006-
if (DL) {
7007-
// TODO: We are using nullopt for arguments at the moment. This will
7008-
// need to be updated when debug data is being generated for variables.
7009-
DISubroutineType *Ty =
7010-
DB.createSubroutineType(DB.getOrCreateTypeArray({}));
7011-
DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
7012-
DISubprogram::SPFlagOptimized |
7013-
DISubprogram::SPFlagLocalToUnit;
7014-
7015-
DISubprogram *OutlinedSP = DB.createFunction(
7016-
CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty,
7017-
DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags);
7018-
7019-
// Attach subprogram to the function.
7020-
Func->setSubprogram(OutlinedSP);
7021-
// Update the CurrentDebugLocation in the builder so that right scope
7022-
// is used for things inside outlined function.
7023-
Builder.SetCurrentDebugLocation(
7024-
DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(),
7025-
OutlinedSP, DL.getInlinedAt()));
7026-
}
7027-
}
7028-
}
6996+
// We will generate the entries in the outlined function but the debug
6997+
// location may still be pointing to the parent function. Reset it now.
6998+
Builder.SetCurrentDebugLocation(llvm::DebugLoc());
70296999

70307000
// Generate the region into the function.
70317001
BasicBlock *EntryBB = BasicBlock::Create(Builder.getContext(), "entry", Func);

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5299,6 +5299,20 @@ static LogicalResult
52995299
convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
53005300
LLVM::ModuleTranslation &moduleTranslation) {
53015301
auto targetOp = cast<omp::TargetOp>(opInst);
5302+
// The current debug location already has the DISubprogram for the outlined
5303+
// function that will be created for the target op. We save it here so that
5304+
// we can set it on the outlined function.
5305+
llvm::DebugLoc OutlinedFnLoc = builder.getCurrentDebugLocation();
5306+
// During the handling of target op, we will generate instructions in the
5307+
// parent function like call to oulined function or branch to new BasicBlock.
5308+
// We set the debug location here to parent function so that those get the
5309+
// correct debug locations. For outlined functions, the normal MLIR op
5310+
// conversion will automatically pick the correct location.
5311+
llvm::BasicBlock *parentBB = builder.GetInsertBlock();
5312+
if (parentBB && !parentBB->empty())
5313+
builder.SetCurrentDebugLocation(parentBB->back().getDebugLoc());
5314+
else
5315+
builder.SetCurrentDebugLocation(llvm::DebugLoc());
53025316
if (failed(checkImplementationStatus(opInst)))
53035317
return failure();
53045318

@@ -5395,6 +5409,9 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
53955409
assert(llvmParentFn && llvmOutlinedFn &&
53965410
"Both parent and outlined functions must exist at this point");
53975411

5412+
if (OutlinedFnLoc && llvmParentFn->getSubprogram())
5413+
llvmOutlinedFn->setSubprogram(OutlinedFnLoc->getScope()->getSubprogram());
5414+
53985415
if (auto attr = llvmParentFn->getFnAttribute("target-cpu");
53995416
attr.isStringAttribute())
54005417
llvmOutlinedFn->addFnAttr(attr);

mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module attributes {omp.is_target_device = false} {
2020
^bb3: // pred: ^bb1
2121
llvm.store %13, %arg1 : i32, !llvm.ptr
2222
omp.terminator
23-
}
23+
} loc(#loc3)
2424
llvm.return
2525
} loc(#loc2)
2626
}
@@ -34,7 +34,10 @@ module attributes {omp.is_target_device = false} {
3434
types = #di_null_type>
3535
#sp = #llvm.di_subprogram<compileUnit = #cu, name = "main", file=#file,
3636
subprogramFlags = "Definition", type = #sp_ty>
37+
#sp1 = #llvm.di_subprogram<compileUnit = #cu, name = "target", file=#file,
38+
subprogramFlags = "Definition", type = #sp_ty>
3739

3840
#loc1 = loc("test.f90":6:7)
3941
#loc2 = loc(fused<#sp>[#loc1])
42+
#loc3 = loc(fused<#sp1>[#loc1])
4043

mlir/test/Target/LLVMIR/omptarget-debug-var-1.mlir

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
2020
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
2121
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22-
#var_arr = #llvm.di_local_variable<scope = #sp,
22+
#sp1 = #llvm.di_subprogram<id = distinct[3]<>, compileUnit = #cu, scope = #file,
23+
name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#var_arr = #llvm.di_local_variable<scope = #sp1,
2325
name = "arr", file = #file, line = 4, type = #array_ty>
24-
#var_i = #llvm.di_local_variable<scope = #sp,
26+
#var_i = #llvm.di_local_variable<scope = #sp1,
2527
name = "i", file = #file, line = 13, type = #int_ty>
26-
#var_x = #llvm.di_local_variable<scope = #sp,
28+
#var_x = #llvm.di_local_variable<scope = #sp1,
2729
name = "x", file = #file, line = 12, type = #real_ty>
2830

2931
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
4749
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
4850
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
4951
omp.terminator
50-
}
52+
} loc(#loc5)
5153
llvm.return
5254
} loc(#loc3)
5355
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
5759
#loc2 = loc("target.f90":11:7)
5860
#loc3 = loc(fused<#sp>[#loc2])
5961
#loc4 = loc(fused<#g_var>[#loc1])
62+
#loc5 = loc(fused<#sp1>[#loc2])
6063

61-
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
64+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}})
6265
// CHECK: !DILocalVariable(name: "dyn_ptr", arg: 1, scope: ![[SP]]{{.*}}flags: DIFlagArtificial)
6366
// CHECK: !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}})
6467
// CHECK: !DILocalVariable(name: "arr", arg: 3, scope: ![[SP]]{{.*}})

mlir/test/Target/LLVMIR/omptarget-debug-var-2.mlir

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
2020
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
2121
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22-
#var_arr = #llvm.di_local_variable<scope = #sp,
22+
#sp1 = #llvm.di_subprogram<id = distinct[3]<>, compileUnit = #cu, scope = #file,
23+
name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#var_arr = #llvm.di_local_variable<scope = #sp1,
2325
name = "arr", file = #file, line = 4, type = #array_ty>
24-
#var_i = #llvm.di_local_variable<scope = #sp,
26+
#var_i = #llvm.di_local_variable<scope = #sp1,
2527
name = "i", file = #file, line = 13, type = #int_ty>
26-
#var_x = #llvm.di_local_variable<scope = #sp,
28+
#var_x = #llvm.di_local_variable<scope = #sp1,
2729
name = "x", file = #file, line = 12, type = #real_ty>
2830

2931
module attributes {omp.is_target_device = false} {
@@ -45,7 +47,7 @@ module attributes {omp.is_target_device = false} {
4547
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
4648
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
4749
omp.terminator
48-
}
50+
} loc(#loc5)
4951
llvm.return
5052
} loc(#loc3)
5153
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} {
5557
#loc2 = loc("target.f90":11:7)
5658
#loc3 = loc(fused<#sp>[#loc2])
5759
#loc4 = loc(fused<#g_var>[#loc1])
60+
#loc5 = loc(fused<#sp1>[#loc2])
5861

59-
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
62+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}})
6063
// CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[SP]]{{.*}})
6164
// CHECK: !DILocalVariable(name: "arr", arg: 2, scope: ![[SP]]{{.*}})
6265
// CHECK: !DILocalVariable(name: "i", arg: 3, scope: ![[SP]]{{.*}})

mlir/test/Target/LLVMIR/omptarget-debug.mlir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
1010
%13 = llvm.mlir.constant(1 : i32) : i32
1111
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
1212
omp.terminator
13-
}
13+
} loc(#loc4)
1414
llvm.return
1515
} loc(#loc3)
1616
}
@@ -21,9 +21,13 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
2121
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
2222
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
2323
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
25+
name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
26+
type = #sp_ty>
2427
#loc1 = loc("target.f90":1:1)
2528
#loc2 = loc("target.f90":46:3)
2629
#loc3 = loc(fused<#sp>[#loc1])
30+
#loc4 = loc(fused<#sp1>[#loc1])
2731

28-
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
32+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}})
2933
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])

mlir/test/Target/LLVMIR/omptarget-debug2.mlir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module attributes {omp.is_target_device = false} {
1111
%13 = llvm.mlir.constant(1 : i32) : i32
1212
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
1313
omp.terminator
14-
}
14+
} loc(#loc4)
1515
llvm.return
1616
} loc(#loc3)
1717
}
@@ -22,9 +22,13 @@ module attributes {omp.is_target_device = false} {
2222
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
2323
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
2424
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
25+
#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
26+
name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
27+
type = #sp_ty>
2528
#loc1 = loc("target.f90":1:1)
2629
#loc2 = loc("target.f90":46:3)
2730
#loc3 = loc(fused<#sp>[#loc1])
31+
#loc4 = loc(fused<#sp1>[#loc1])
2832

29-
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
33+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}})
3034
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])

mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang", isOptimized = false, emissionKind = Full>
77
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_program, types = #di_null_type>
88
#sp = #llvm.di_subprogram<compileUnit = #cu, scope = #di_file, name = "test", file = #di_file, subprogramFlags = "Definition", type = #sp_ty>
9+
#sp1 = #llvm.di_subprogram<compileUnit = #cu, scope = #di_file, name = "kernel", file = #di_file, subprogramFlags = "Definition", type = #sp_ty>
910
#int_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed>
1011
#var_x = #llvm.di_local_variable<scope = #sp, name = "x", file = #di_file, type = #int_ty>
12+
#var_x1 = #llvm.di_local_variable<scope = #sp1, name = "x", file = #di_file, type = #int_ty>
1113
module attributes {dlti.dl_spec = #dlti.dl_spec<i32 = dense<32> : 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<clause_requires none>, omp.target_triples = ["amdgcn-amd-amdhsa"], omp.version = #omp.version<version = 52>} {
1214
llvm.func @_QQmain() attributes {fir.bindc_name = "test", frame_pointer = #llvm.framePointerKind<all>, target_cpu = "x86-64"} {
1315
%0 = llvm.mlir.constant(1 : i64) : i64
@@ -16,20 +18,22 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<i32 = dense<32> : vector<2xi64>,
1618
%5 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "x"}
1719
omp.target map_entries(%5 -> %arg0 : !llvm.ptr) {
1820
%6 = llvm.mlir.constant(1 : i32) : i32
19-
llvm.intr.dbg.declare #var_x = %arg0 : !llvm.ptr loc(#loc2)
21+
llvm.intr.dbg.declare #var_x1 = %arg0 : !llvm.ptr loc(#loc3)
2022
omp.parallel {
2123
%7 = llvm.load %arg0 : !llvm.ptr -> i32
2224
%8 = llvm.add %7, %6 : i32
2325
llvm.store %8, %arg0 : i32, !llvm.ptr
2426
omp.terminator
2527
}
2628
omp.terminator
27-
}
29+
} loc(#loc4)
2830
llvm.return
2931
} loc(#loc10)
3032
}
3133
#loc1 = loc("target.f90":1:7)
3234
#loc2 = loc("target.f90":3:18)
35+
#loc3 = loc("target.f90":6:18)
36+
#loc4 = loc(fused<#sp1>[#loc3])
3337
#loc10 = loc(fused<#sp>[#loc1])
3438

3539

0 commit comments

Comments
 (0)