Skip to content

Commit eddfebd

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 6951d5d commit eddfebd

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
@@ -6858,23 +6858,19 @@ static void FixupDebugInfoForOutlinedFunction(
68586858
if (!NewSP)
68596859
return;
68606860

6861-
DenseMap<const MDNode *, MDNode *> Cache;
68626861
SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables;
68636862

68646863
auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) {
6865-
auto NewSP = Func->getSubprogram();
68666864
DILocalVariable *&NewVar = RemappedVariables[OldVar];
68676865
// Only use cached variable if the arg number matches. This is important
68686866
// so that DIVariable created for privatized variables are not discarded.
68696867
if (NewVar && (arg == NewVar->getArg()))
68706868
return NewVar;
68716869

6872-
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
6873-
*OldVar->getScope(), *NewSP, Builder.getContext(), Cache);
68746870
NewVar = llvm::DILocalVariable::get(
6875-
Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(),
6876-
OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(),
6877-
OldVar->getAlignInBits(), OldVar->getAnnotations());
6871+
Builder.getContext(), OldVar->getScope(), OldVar->getName(),
6872+
OldVar->getFile(), OldVar->getLine(), OldVar->getType(), arg,
6873+
OldVar->getFlags(), OldVar->getAlignInBits(), OldVar->getAnnotations());
68786874
return NewVar;
68796875
};
68806876

@@ -6888,7 +6884,8 @@ static void FixupDebugInfoForOutlinedFunction(
68886884
ArgNo = std::get<1>(Iter->second) + 1;
68896885
}
68906886
}
6891-
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
6887+
if (ArgNo != 0)
6888+
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
68926889
};
68936890

68946891
// The location and scope of variable intrinsics and records still point to
@@ -6967,36 +6964,9 @@ static Expected<Function *> createOutlinedFunction(
69676964

69686965
// Save insert point.
69696966
IRBuilder<>::InsertPointGuard IPG(Builder);
6970-
// If there's a DISubprogram associated with current function, then
6971-
// generate one for the outlined function.
6972-
if (Function *ParentFunc = BB->getParent()) {
6973-
if (DISubprogram *SP = ParentFunc->getSubprogram()) {
6974-
DICompileUnit *CU = SP->getUnit();
6975-
DIBuilder DB(*M, true, CU);
6976-
DebugLoc DL = Builder.getCurrentDebugLocation();
6977-
if (DL) {
6978-
// TODO: We are using nullopt for arguments at the moment. This will
6979-
// need to be updated when debug data is being generated for variables.
6980-
DISubroutineType *Ty =
6981-
DB.createSubroutineType(DB.getOrCreateTypeArray({}));
6982-
DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
6983-
DISubprogram::SPFlagOptimized |
6984-
DISubprogram::SPFlagLocalToUnit;
6985-
6986-
DISubprogram *OutlinedSP = DB.createFunction(
6987-
CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty,
6988-
DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags);
6989-
6990-
// Attach subprogram to the function.
6991-
Func->setSubprogram(OutlinedSP);
6992-
// Update the CurrentDebugLocation in the builder so that right scope
6993-
// is used for things inside outlined function.
6994-
Builder.SetCurrentDebugLocation(
6995-
DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(),
6996-
OutlinedSP, DL.getInlinedAt()));
6997-
}
6998-
}
6999-
}
6967+
// We will generate the entries in the outlined function but the debug
6968+
// location may still be pointing to the parent function. Reset it now.
6969+
Builder.SetCurrentDebugLocation(llvm::DebugLoc());
70006970

70016971
// Generate the region into the function.
70026972
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
@@ -4982,6 +4982,20 @@ static LogicalResult
49824982
convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
49834983
LLVM::ModuleTranslation &moduleTranslation) {
49844984
auto targetOp = cast<omp::TargetOp>(opInst);
4985+
// The current debug location already has the DISubprogram for the outlined
4986+
// function that will be created for the target op. We save it here so that
4987+
// we can set it on the outlined function.
4988+
llvm::DebugLoc OutlinedFnLoc = builder.getCurrentDebugLocation();
4989+
// During the handling of target op, we will generate instructions in the
4990+
// parent function like call to oulined function or branch to new BasicBlock.
4991+
// We set the debug location here to parent function so that those get the
4992+
// correct debug locations. For outlined functions, the normal MLIR op
4993+
// conversion will automatically pick the correct location.
4994+
llvm::BasicBlock *parentBB = builder.GetInsertBlock();
4995+
if (parentBB && !parentBB->empty())
4996+
builder.SetCurrentDebugLocation(parentBB->back().getDebugLoc());
4997+
else
4998+
builder.SetCurrentDebugLocation(llvm::DebugLoc());
49854999
if (failed(checkImplementationStatus(opInst)))
49865000
return failure();
49875001

@@ -5078,6 +5092,9 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
50785092
assert(llvmParentFn && llvmOutlinedFn &&
50795093
"Both parent and outlined functions must exist at this point");
50805094

5095+
if (OutlinedFnLoc && llvmParentFn->getSubprogram())
5096+
llvmOutlinedFn->setSubprogram(OutlinedFnLoc->getScope()->getSubprogram());
5097+
50815098
if (auto attr = llvmParentFn->getFnAttribute("target-cpu");
50825099
attr.isStringAttribute())
50835100
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)