Skip to content

Commit a9eec8c

Browse files
authored
[flang][OMPIRBuilder] Improve debug info for OpenMP target region. (llvm#576)
This PR builds on PR#118314 and PR#125692 which enable the debugging of variables in the OpenMP target region. This PR adds the following changes so that usable debug info comes out of AMDGPU backend. 1. Add DIOp based expressions. 2. Use alloca as location of the variable in debug record. Regarding 2nd point, OMPIRBuilder creates a function to implement target construct. The variable that are mapped are passed as argument to it. The argument handling code adds alloca+store+load for the arguments which are mapped by reference. It was observed that if the argument* is used as location of variable in debug record (directly or when it is result of LoadInst), the debug information is dropped for that variable. Thing work ok if the location of the alloca is used instead.
2 parents 7cadba3 + edea26a commit a9eec8c

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
! RUN: %flang_fc1 -triple amdgcn-amd-amdhsa -emit-llvm -fopenmp -fopenmp-is-target-device -debug-info-kind=standalone %s -o - | FileCheck %s
2+
3+
subroutine fff(x, y)
4+
implicit none
5+
integer :: y(:)
6+
integer :: x
7+
8+
!$omp target map(tofrom: x) map(tofrom: y)
9+
x = 5
10+
y = 10
11+
!$omp end target
12+
13+
end subroutine fff
14+
15+
! CHECK: define{{.*}}amdgpu_kernel void @[[FN:[0-9a-zA_Z_]+]](ptr %0, ptr %[[ARG1:[0-9]+]], ptr %[[ARG2:[0-9]+]]){{.*}}!dbg ![[SP:[0-9]+]]
16+
! CHECK-DAG: store ptr %[[ARG1]], ptr %[[CAST1:[0-9]+]]{{.*}}
17+
! CHECK-DAG: %[[CAST1]] = addrspacecast ptr addrspace(5) %[[AL1:[0-9]+]]
18+
! CHECK-DAG: %[[AL1]] = alloca{{.*}}
19+
! CHECK-DAG: store ptr %[[ARG2]], ptr %[[CAST2:[0-9]+]]{{.*}}
20+
! CHECK-DAG: %[[CAST2]] = addrspacecast ptr addrspace(5) %[[AL2:[0-9]+]]
21+
! CHECK-DAG: %[[AL2]] = alloca{{.*}}
22+
! CHECK-DAG: #dbg_declare(ptr %[[CAST1]], ![[X:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), {{.*}})
23+
! CHECK-DAG: #dbg_declare(ptr %[[CAST2]], ![[Y:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), {{.*}})
24+
! CHECK: }
25+
26+
! CHECK-DAG: ![[SP]] = {{.*}}!DISubprogram(name: "[[FN]]"{{.*}})
27+
! CHECK-DAG: ![[X]] = !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}}type: ![[INT:[0-9]+]])
28+
! CHECK-DAG: ![[INT]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)
29+
! CHECK-DAG: ![[Y]] = !DILocalVariable(name: "y", arg: 3, scope: ![[SP]]{{.*}}type: ![[ARR:[0-9]+]])
30+
! CHECK-DAG: ![[ARR]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[INT]]{{.*}})

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6996,7 +6996,6 @@ static void FixupDebugInfoForOutlinedFunction(
69966996
SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables;
69976997

69986998
auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) {
6999-
auto NewSP = Func->getSubprogram();
70006999
DILocalVariable *&NewVar = RemappedVariables[OldVar];
70017000
// Only use cached variable if the arg number matches. This is important
70027001
// so that DIVariable created for privatized variables are not discarded.
@@ -7008,8 +7007,8 @@ static void FixupDebugInfoForOutlinedFunction(
70087007
NewVar = llvm::DILocalVariable::get(
70097008
Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(),
70107009
OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(),
7011-
llvm::dwarf::DW_MSPACE_LLVM_none,
7012-
OldVar->getAlignInBits(), OldVar->getAnnotations());
7010+
OldVar->getDWARFMemorySpace(), OldVar->getAlignInBits(),
7011+
OldVar->getAnnotations());
70137012
return NewVar;
70147013
};
70157014

@@ -7023,6 +7022,53 @@ static void FixupDebugInfoForOutlinedFunction(
70237022
ArgNo = std::get<1>(Iter->second) + 1;
70247023
}
70257024
}
7025+
7026+
Module *M = Func->getParent();
7027+
if ((Triple(M->getTargetTriple())).isAMDGPU()) {
7028+
// For target side, the ArgAccessorFuncCB/createDeviceArgumentAccessor
7029+
// adds following for the kenel arguments.
7030+
// %3 = alloca ptr, align 8, addrspace(5), !dbg !26
7031+
// %4 = addrspacecast ptr addrspace(5) %3 to ptr, !dbg !26
7032+
// store ptr %1, ptr %4, align 8, !dbg !26
7033+
7034+
// For arguments that are passed by ref, there is an extra load like the
7035+
// following.
7036+
// %8 = load ptr, ptr %4, align 8
7037+
//
7038+
// The debug record at this moment may be pointing to %8 (in above
7039+
// snippet) as location of variable. The AMDGPU backend drops the debug
7040+
// info for variable in such cases. So we change the location to alloca
7041+
// instead.
7042+
bool PassByRef = false;
7043+
llvm::Type *locType = nullptr;
7044+
for (auto Loc : DR->location_ops()) {
7045+
locType = Loc->getType();
7046+
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Loc)) {
7047+
DR->replaceVariableLocationOp(Loc, Load->getPointerOperand());
7048+
PassByRef = true;
7049+
}
7050+
}
7051+
// Add DIOps based expression. Note that we generate an extra indirection
7052+
// if an argument is mapped by reference. The first reads the pointer
7053+
// from alloca and 2nd read the value of the variable from that pointer.
7054+
llvm::DIExprBuilder ExprBuilder(Builder.getContext());
7055+
unsigned int allocaAS = M->getDataLayout().getAllocaAddrSpace();
7056+
unsigned int defaultAS = M->getDataLayout().getProgramAddressSpace();
7057+
ExprBuilder.append<llvm::DIOp::Arg>(0u, Builder.getPtrTy(allocaAS));
7058+
// We have 2 options for the variables that are mapped byRef.
7059+
// 1. Use a single indirection but change the type to the reference to the
7060+
// original type. It will show up in the debugger as
7061+
// "x=@0x7ffeec820000: 5"
7062+
// This is similar to what clang does.
7063+
// 2. Use double indirection and keep the original type. It will show up
7064+
// in debugger as "x=5". This approached is used here as it is
7065+
// consistent with the normal fortran parameters display.
7066+
if (PassByRef)
7067+
ExprBuilder.append<llvm::DIOp::Deref>(Builder.getPtrTy(defaultAS));
7068+
ExprBuilder.append<llvm::DIOp::Deref>(locType);
7069+
DR->setExpression(ExprBuilder.intoExpression());
7070+
}
7071+
70267072
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
70277073
};
70287074

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#var_x = #llvm.di_local_variable<scope = #sp,
2727
name = "x", file = #file, line = 12, type = #real_ty>
2828

29-
module attributes {llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_target_device = true} {
29+
module attributes {llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_target_device = true, dlti.dl_spec = #dlti.dl_spec<"dlti.alloca_memory_space" = 5 : ui64>} {
3030
llvm.func @test() {
3131
%0 = llvm.mlir.constant(1 : i64) : i64
3232
%1 = llvm.alloca %0 x f32 : (i64) -> !llvm.ptr
@@ -56,8 +56,23 @@ module attributes {llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_target_devic
5656
#loc3 = loc(fused<#sp>[#loc2])
5757
#loc4 = loc(fused<#g_var>[#loc1])
5858

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]]{{.*}})
59+
// CHECK: define{{.*}}@__omp_offloading{{.*}}test{{.*}}(ptr %0, ptr %[[ARG1:[0-9]+]], ptr %[[ARG2:[0-9]+]], ptr %[[ARG3:[0-9]+]])
60+
// CHECK-DAG: store ptr %[[ARG1]], ptr %[[CAST1:[0-9]+]]{{.*}}
61+
// CHECK-DAG: %[[CAST1]] = addrspacecast ptr addrspace(5) %[[AL1:[0-9]+]]
62+
// CHECK-DAG: %[[AL1]] = alloca{{.*}}
63+
// CHECK-DAG: store ptr %[[ARG2]], ptr %[[CAST2:[0-9]+]]{{.*}}
64+
// CHECK-DAG: %[[CAST2]] = addrspacecast ptr addrspace(5) %[[AL2:[0-9]+]]
65+
// CHECK-DAG: %[[AL2]] = alloca{{.*}}
66+
// CHECK-DAG: store ptr %[[ARG3]], ptr %[[CAST3:[0-9]+]]{{.*}}
67+
// CHECK-DAG: %[[CAST3]] = addrspacecast ptr addrspace(5) %[[AL3:[0-9]+]]
68+
// CHECK-DAG: %[[AL3]] = alloca{{.*}}
69+
70+
// CHECK-DAG: #dbg_declare(ptr %[[CAST1]], ![[X:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), {{.*}})
71+
// CHECK-DAG: #dbg_declare(ptr %[[CAST2]], ![[ARR:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), {{.*}})
72+
// CHECK-DAG: #dbg_declare(ptr %[[CAST3]], ![[I:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr)), {{.*}})
73+
74+
// CHECK-DAG: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
75+
// CHECK-DAG: !DILocalVariable(name: "dyn_ptr", arg: 1, scope: ![[SP]]{{.*}}flags: DIFlagArtificial)
76+
// CHECK-DAG: ![[X:[0-9]+]] = !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}})
77+
// CHECK-DAG: ![[ARR:[0-9]+]] = !DILocalVariable(name: "arr", arg: 3, scope: ![[SP]]{{.*}})
78+
// CHECK-DAG: ![[I:[0-9]+]] = !DILocalVariable(name: "i", arg: 4, scope: ![[SP]]{{.*}})

0 commit comments

Comments
 (0)