Skip to content

Commit 0db9e5c

Browse files
committed
[OMPIRBuilder][debug] Fix debug info for variables in target region.
PR llvm#118314.
1 parent aa2e579 commit 0db9e5c

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include "llvm/IR/Function.h"
3939
#include "llvm/IR/GlobalVariable.h"
4040
#include "llvm/IR/IRBuilder.h"
41+
#include "llvm/IR/InstIterator.h"
42+
#include "llvm/IR/IntrinsicInst.h"
4143
#include "llvm/IR/LLVMContext.h"
4244
#include "llvm/IR/MDBuilder.h"
4345
#include "llvm/IR/Metadata.h"
@@ -7027,6 +7029,8 @@ static Expected<Function *> createOutlinedFunction(
70277029
? make_range(Func->arg_begin() + 1, Func->arg_end())
70287030
: Func->args();
70297031

7032+
DenseMap<Value *, std::tuple<Value *, unsigned>> ValueReplacementMap;
7033+
70307034
auto ReplaceValue = [](Value *Input, Value *InputCopy, Function *Func) {
70317035
// Things like GEP's can come in the form of Constants. Constants and
70327036
// ConstantExpr's do not have access to the knowledge of what they're
@@ -7068,6 +7072,7 @@ static Expected<Function *> createOutlinedFunction(
70687072
if (!AfterIP)
70697073
return AfterIP.takeError();
70707074
Builder.restoreIP(*AfterIP);
7075+
ValueReplacementMap[Input] = std::make_tuple(InputCopy, Arg.getArgNo());
70717076

70727077
// In certain cases a Global may be set up for replacement, however, this
70737078
// Global may be used in multiple arguments to the kernel, just segmented
@@ -7099,6 +7104,67 @@ static Expected<Function *> createOutlinedFunction(
70997104
for (auto Deferred : DeferredReplacement)
71007105
ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
71017106

7107+
DenseMap<const MDNode *, MDNode *> Cache;
7108+
SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables;
7109+
7110+
auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) {
7111+
auto NewSP = Func->getSubprogram();
7112+
DILocalVariable *&NewVar = RemappedVariables[OldVar];
7113+
if (!NewVar) {
7114+
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
7115+
*OldVar->getScope(), *NewSP, Builder.getContext(), Cache);
7116+
NewVar = llvm::DILocalVariable::get(
7117+
Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(),
7118+
OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(),
7119+
OldVar->getAlignInBits(), OldVar->getAnnotations());
7120+
}
7121+
return NewVar;
7122+
};
7123+
7124+
DISubprogram *NewSP = Func->getSubprogram();
7125+
if (NewSP) {
7126+
// The location and scope of variable intrinsics and records still point to
7127+
// the parent function of the target region. Update them.
7128+
for (Instruction &I : instructions(Func)) {
7129+
if (auto *DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) {
7130+
DILocalVariable *OldVar = DDI->getVariable();
7131+
unsigned ArgNo = OldVar->getArg();
7132+
for (auto Loc : DDI->location_ops()) {
7133+
auto Iter = ValueReplacementMap.find(Loc);
7134+
if (Iter != ValueReplacementMap.end()) {
7135+
DDI->replaceVariableLocationOp(Loc, std::get<0>(Iter->second));
7136+
ArgNo = std::get<1>(Iter->second) + 1;
7137+
}
7138+
}
7139+
DDI->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
7140+
}
7141+
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
7142+
DILocalVariable *OldVar = DVR.getVariable();
7143+
unsigned ArgNo = OldVar->getArg();
7144+
for (auto Loc : DVR.location_ops()) {
7145+
auto Iter = ValueReplacementMap.find(Loc);
7146+
if (Iter != ValueReplacementMap.end()) {
7147+
DVR.replaceVariableLocationOp(Loc, std::get<0>(Iter->second));
7148+
ArgNo = std::get<1>(Iter->second) + 1;
7149+
}
7150+
}
7151+
DVR.setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
7152+
}
7153+
}
7154+
// An extra argument is passed to the device. Create the debug data for it.
7155+
if (OMPBuilder.Config.isTargetDevice()) {
7156+
DICompileUnit *CU = NewSP->getUnit();
7157+
DIBuilder DB(*M, true, CU);
7158+
DIType *VoidPtrTy =
7159+
DB.createQualifiedType(dwarf::DW_TAG_pointer_type, nullptr);
7160+
DILocalVariable *Var = DB.createParameterVariable(
7161+
NewSP, "dyn_ptr", /*ArgNo*/ 1, NewSP->getFile(), /*LineNo=*/0,
7162+
VoidPtrTy, /*AlwaysPreserve=*/false, DINode::DIFlags::FlagArtificial);
7163+
auto Loc = DILocation::get(Func->getContext(), 0, 0, NewSP, 0);
7164+
DB.insertDeclare(&(*Func->arg_begin()), Var, DB.createExpression(), Loc,
7165+
&(*Func->begin()));
7166+
}
7167+
}
71027168
return Func;
71037169
}
71047170

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
#int_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer",
4+
sizeInBits = 32, encoding = DW_ATE_signed>
5+
#real_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real",
6+
sizeInBits = 32, encoding = DW_ATE_float>
7+
#file = #llvm.di_file<"target.f90" in "">
8+
#di_null_type = #llvm.di_null_type
9+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
10+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
11+
emissionKind = Full>
12+
#array_ty = #llvm.di_composite_type<tag = DW_TAG_array_type,
13+
baseType = #int_ty, elements = #llvm.di_subrange<count = 10 : i64>>
14+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_program,
15+
types = #di_null_type>
16+
#g_var = #llvm.di_global_variable<scope = #cu, name = "arr",
17+
linkageName = "_QFEarr", file = #file, line = 4,
18+
type = #array_ty, isDefined = true>
19+
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
20+
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
21+
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22+
#var_arr = #llvm.di_local_variable<scope = #sp,
23+
name = "arr", file = #file, line = 4, type = #array_ty>
24+
#var_i = #llvm.di_local_variable<scope = #sp,
25+
name = "i", file = #file, line = 13, type = #int_ty>
26+
#var_x = #llvm.di_local_variable<scope = #sp,
27+
name = "x", file = #file, line = 12, type = #real_ty>
28+
29+
module attributes {omp.is_target_device = true} {
30+
llvm.func @test() {
31+
%0 = llvm.mlir.constant(1 : i64) : i64
32+
%1 = llvm.alloca %0 x f32 : (i64) -> !llvm.ptr
33+
%4 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
34+
%6 = llvm.mlir.constant(9 : index) : i64
35+
%7 = llvm.mlir.constant(0 : index) : i64
36+
%8 = llvm.mlir.constant(1 : index) : i64
37+
%10 = llvm.mlir.constant(10 : index) : i64
38+
%11 = llvm.mlir.addressof @_QFEarr : !llvm.ptr
39+
%14 = omp.map.info var_ptr(%1 : !llvm.ptr, f32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr
40+
%15 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) extent(%10 : i64) stride(%8 : i64) start_idx(%8 : i64)
41+
%16 = omp.map.info var_ptr(%11 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr
42+
%17 = omp.map.info var_ptr(%4 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr
43+
omp.target map_entries(%14 -> %arg0, %16 -> %arg1, %17 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
44+
llvm.intr.dbg.declare #var_x = %arg0 : !llvm.ptr
45+
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
46+
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
47+
omp.terminator
48+
}
49+
llvm.return
50+
} loc(#loc3)
51+
llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> {
52+
} loc(#loc4)
53+
}
54+
#loc1 = loc("target.f90":4:7)
55+
#loc2 = loc("target.f90":11:7)
56+
#loc3 = loc(fused<#sp>[#loc2])
57+
#loc4 = loc(fused<#g_var>[#loc1])
58+
59+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
60+
// CHECK: !DILocalVariable(name: "dyn_ptr", arg: 1, scope: ![[SP]]{{.*}}flags: DIFlagArtificial)
61+
// CHECK: !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}})
62+
// CHECK: !DILocalVariable(name: "arr", arg: 3, scope: ![[SP]]{{.*}})
63+
// CHECK: !DILocalVariable(name: "i", arg: 4, scope: ![[SP]]{{.*}})
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
#int_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer",
4+
sizeInBits = 32, encoding = DW_ATE_signed>
5+
#real_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real",
6+
sizeInBits = 32, encoding = DW_ATE_float>
7+
#file = #llvm.di_file<"target.f90" in "">
8+
#di_null_type = #llvm.di_null_type
9+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
10+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
11+
emissionKind = Full>
12+
#array_ty = #llvm.di_composite_type<tag = DW_TAG_array_type,
13+
baseType = #int_ty, elements = #llvm.di_subrange<count = 10 : i64>>
14+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_program,
15+
types = #di_null_type>
16+
#g_var = #llvm.di_global_variable<scope = #cu, name = "arr",
17+
linkageName = "_QFEarr", file = #file, line = 4,
18+
type = #array_ty, isDefined = true>
19+
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
20+
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
21+
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22+
#var_arr = #llvm.di_local_variable<scope = #sp,
23+
name = "arr", file = #file, line = 4, type = #array_ty>
24+
#var_i = #llvm.di_local_variable<scope = #sp,
25+
name = "i", file = #file, line = 13, type = #int_ty>
26+
#var_x = #llvm.di_local_variable<scope = #sp,
27+
name = "x", file = #file, line = 12, type = #real_ty>
28+
29+
module attributes {omp.is_target_device = false} {
30+
llvm.func @test() {
31+
%0 = llvm.mlir.constant(1 : i64) : i64
32+
%1 = llvm.alloca %0 x f32 : (i64) -> !llvm.ptr
33+
%4 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
34+
%6 = llvm.mlir.constant(9 : index) : i64
35+
%7 = llvm.mlir.constant(0 : index) : i64
36+
%8 = llvm.mlir.constant(1 : index) : i64
37+
%10 = llvm.mlir.constant(10 : index) : i64
38+
%11 = llvm.mlir.addressof @_QFEarr : !llvm.ptr
39+
%14 = omp.map.info var_ptr(%1 : !llvm.ptr, f32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr
40+
%15 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) extent(%10 : i64) stride(%8 : i64) start_idx(%8 : i64)
41+
%16 = omp.map.info var_ptr(%11 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr
42+
%17 = omp.map.info var_ptr(%4 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr
43+
omp.target map_entries(%14 -> %arg0, %16 -> %arg1, %17 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {
44+
llvm.intr.dbg.declare #var_x = %arg0 : !llvm.ptr
45+
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
46+
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
47+
omp.terminator
48+
}
49+
llvm.return
50+
} loc(#loc3)
51+
llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> {
52+
} loc(#loc4)
53+
}
54+
#loc1 = loc("target.f90":4:7)
55+
#loc2 = loc("target.f90":11:7)
56+
#loc3 = loc(fused<#sp>[#loc2])
57+
#loc4 = loc(fused<#g_var>[#loc1])
58+
59+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
60+
// CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[SP]]{{.*}})
61+
// CHECK: !DILocalVariable(name: "arr", arg: 2, scope: ![[SP]]{{.*}})
62+
// CHECK: !DILocalVariable(name: "i", arg: 3, scope: ![[SP]]{{.*}})

0 commit comments

Comments
 (0)