Skip to content

Commit 47b748a

Browse files
committed
[flang][OpenMP][debug] Adjust debu info for declare target function.
The debug info for the function arguments and locals for the declare target functions needs following changes for AMDGPU target. 1. Add DIOp based expressions 2. If a debug reocrd points to function Argument as location then change it to use an alloca instead.
1 parent aabd6ca commit 47b748a

File tree

3 files changed

+125
-3
lines changed

3 files changed

+125
-3
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
function add(a, b) result(ret)
4+
real ret
5+
real a
6+
real b
7+
!$omp declare target
8+
if (a > b) then
9+
ret = a;
10+
else
11+
ret = b;
12+
end if
13+
end
14+
15+
!CHECK: define float @add_({{.*}}){{.*}}!dbg ![[SP:[0-9]+]] {
16+
!CHECK: #dbg_declare({{.*}}, ![[A:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), !{{.*}})
17+
!CHECK: #dbg_declare({{.*}}, ![[B:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), !{{.*}})
18+
!CHECK: #dbg_declare({{.*}}, ![[RET:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr)), !{{.*}})
19+
!CHECK: }
20+
!CHECK: ![[SP]] = {{.*}}!DISubprogram(name: "add"{{.*}})
21+
!CHECK: ![[A]] = !DILocalVariable(name: "a", arg: 1, scope: ![[SP]]{{.*}})
22+
!CHECK: ![[B]] = !DILocalVariable(name: "b", arg: 2, scope: ![[SP]]{{.*}})
23+
!CHECK: ![[RET]] = !DILocalVariable(name: "ret", scope: ![[SP]]{{.*}})

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

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "llvm/TargetParser/Triple.h"
4040
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
4141
#include "llvm/Transforms/Utils/ModuleUtils.h"
42+
#include "llvm/IR/InstIterator.h"
43+
#include "llvm/IR/IntrinsicInst.h"
4244

4345
#include <any>
4446
#include <cstdint>
@@ -5462,6 +5464,67 @@ static void updateDebugInfoForDeclareTargetVariables(
54625464
}
54635465
}
54645466

5467+
// This function handle any adjustments needed in declare target function to
5468+
// generate valid debug info for AMDGPU. It does 2 main things:
5469+
// 1. Add DIOp based expressions
5470+
// 2. If a debug reocrd points to function Argument as location then change it
5471+
// to use an alloca instead.
5472+
static void updateDebugInfoForDeclareTargetFunctions(
5473+
llvm::Function *Fn, LLVM::ModuleTranslation &moduleTranslation) {
5474+
llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
5475+
llvm::Module &M = ompBuilder->M;
5476+
5477+
if (!((llvm::Triple(M.getTargetTriple())).isAMDGPU()))
5478+
return;
5479+
5480+
llvm::IRBuilderBase &builder = ompBuilder->Builder;
5481+
llvm::OpenMPIRBuilder::InsertPointTy curInsert = builder.saveIP();
5482+
unsigned int allocaAS = M.getDataLayout().getAllocaAddrSpace();
5483+
unsigned int defaultAS = M.getDataLayout().getProgramAddressSpace();
5484+
5485+
// In most cases, function argument are passed by reference in Fortran. In
5486+
// such cases, flang does not generate an alloca for such arguments. The
5487+
// debug record also point to the Argument* as the location. The AMDGPU
5488+
// backend drops the debug record in such cases. To side step this issue,
5489+
// we generate an alloca and store the Argument pointer in it. Then we can
5490+
// use that alloca as variable location and it works fine. Note that the
5491+
// expression used in the debug record has doubel indirection now. One for
5492+
// reading Argument* from the alloca and then reading the variable value from
5493+
// the Argument*.
5494+
auto genAlloca = [&](llvm::Value *Arg) {
5495+
builder.SetInsertPoint(Fn->getEntryBlock().getFirstInsertionPt());
5496+
llvm::Value *V = builder.CreateAlloca(Arg->getType(), allocaAS, nullptr);
5497+
if (allocaAS != defaultAS && Arg->getType()->isPointerTy())
5498+
V = ompBuilder->Builder.CreateAddrSpaceCast(V,
5499+
builder.getPtrTy(defaultAS));
5500+
builder.CreateStore(Arg, V);
5501+
builder.restoreIP(curInsert);
5502+
return V;
5503+
};
5504+
auto UpdateDebugRecord = [&](auto *DR) {
5505+
for (auto Loc : DR->location_ops()) {
5506+
llvm::DIExprBuilder ExprBuilder(Fn->getContext());
5507+
ExprBuilder.append<llvm::DIOp::Arg>(
5508+
0u, ompBuilder->Builder.getPtrTy(allocaAS));
5509+
if (auto *Arg = dyn_cast<llvm::Argument>(Loc)) {
5510+
ExprBuilder.append<llvm::DIOp::Deref>(
5511+
ompBuilder->Builder.getPtrTy(defaultAS));
5512+
llvm::Value *newLoc = genAlloca(Arg);
5513+
DR->replaceVariableLocationOp(Arg, newLoc);
5514+
}
5515+
ExprBuilder.append<llvm::DIOp::Deref>(Loc->getType());
5516+
DR->setExpression(ExprBuilder.intoExpression());
5517+
}
5518+
};
5519+
for (llvm::Instruction &I : instructions(Fn)) {
5520+
if (auto *DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&I))
5521+
UpdateDebugRecord(DDI);
5522+
5523+
for (llvm::DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange()))
5524+
UpdateDebugRecord(&DVR);
5525+
}
5526+
}
5527+
54655528
static LogicalResult
54665529
convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
54675530
LLVM::ModuleTranslation &moduleTranslation) {
@@ -5481,12 +5544,13 @@ convertDeclareTargetAttr(Operation *op, mlir::omp::DeclareTargetAttr attribute,
54815544
omp::DeclareTargetDeviceType declareType =
54825545
attribute.getDeviceType().getValue();
54835546

5547+
llvm::Function *llvmFunc =
5548+
moduleTranslation.lookupFunction(funcOp.getName());
54845549
if (declareType == omp::DeclareTargetDeviceType::host) {
5485-
llvm::Function *llvmFunc =
5486-
moduleTranslation.lookupFunction(funcOp.getName());
54875550
llvmFunc->dropAllReferences();
54885551
llvmFunc->eraseFromParent();
5489-
}
5552+
} else
5553+
updateDebugInfoForDeclareTargetFunctions(llvmFunc, moduleTranslation);
54905554
}
54915555
return success();
54925556
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
#file = #llvm.di_file<"target.f90" in "">
4+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
5+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
6+
emissionKind = LineTablesOnly>
7+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
8+
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
9+
name = "add", file = #file, subprogramFlags = "Definition", type = #sp_ty>
10+
#ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float>
11+
#var_a = #llvm.di_local_variable<scope = #sp, name = "a", file = #file, line = 22, arg = 1, type = #ty>
12+
13+
14+
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>} {
15+
llvm.func @add(%arg0: !llvm.ptr) attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to)>} {
16+
llvm.intr.dbg.declare #var_a = %arg0 : !llvm.ptr loc(#loc2)
17+
llvm.return
18+
} loc(#loc3)
19+
}
20+
21+
#loc1 = loc("target.f90":1:1)
22+
#loc2 = loc("target.f90":46:3)
23+
#loc3 = loc(fused<#sp>[#loc1])
24+
25+
// CHECK: define{{.*}}@add(ptr %[[ARG:[0-9]+]]){{.*}}!dbg ![[SP:[0-9]+]] {
26+
// CHECK: %[[AL:[0-9]+]] = alloca{{.*}}
27+
// CHECK: %[[CAST:[0-9]+]] = addrspacecast ptr addrspace(5) %[[AL]]
28+
// CHECK: store ptr %[[ARG]], ptr %[[CAST]]{{.*}}
29+
// CHECK: #dbg_declare(ptr %[[CAST]], ![[A:[0-9]+]], !DIExpression(DIOpArg(0, ptr addrspace(5)), DIOpDeref(ptr), DIOpDeref(ptr)), !{{.*}})
30+
// CHECK: }
31+
// CHECK: ![[SP]] = {{.*}}!DISubprogram(name: "add"{{.*}})
32+
// CHECK: ![[A]] = !DILocalVariable(name: "a", arg: 1, scope: ![[SP]]{{.*}})
33+
34+
35+

0 commit comments

Comments
 (0)