Skip to content

Commit 9e08db7

Browse files
authored
[OpenMPIRBuilder] Don't drop debug info for target region. (#80692)
When an outlined function is generated for omp target region, a corresponding DISubprogram was not being generated. This resulted in all the debug information for the target region being dropped. This commit adds DISubprogram for the outlined function if there is one available for the parent function. It also updates the current debug location so that the right scope is used for the entries in the outlined function. There are places in the OpenMPIRBuilder which changes insertion point but don't update the debug location accordingly. They cause issue when debug info is enabled. I have fixed a few that I observed to cause issue. But there may be more and a systematic cleanup may be required. With this change in place, I can set source line breakpoint in target region and run to them in debugger.
1 parent 58f2896 commit 9e08db7

File tree

6 files changed

+134
-7
lines changed

6 files changed

+134
-7
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,11 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
309309
return;
310310

311311
funcOp.walk([&](fir::cg::XDeclareOp declOp) {
312-
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
312+
// FIXME: We currently dont handle variables that are not in the entry
313+
// blocks of the fuctions. These may be variable or arguments used in the
314+
// OpenMP target regions.
315+
if (&funcOp.front() == declOp->getBlock())
316+
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
313317
});
314318
}
315319

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
! RUN: %flang_fc1 -fopenmp -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s
2+
3+
! Test that variables inside OpenMP target region don't cause build failure.
4+
subroutine test1
5+
implicit none
6+
real, allocatable :: xyz(:)
7+
integer :: i
8+
9+
!$omp target simd map(from:xyz)
10+
do i = 1, size(xyz)
11+
xyz(i) = 5.0 * xyz(i)
12+
end do
13+
end subroutine
14+
15+
subroutine test2 (xyz)
16+
integer :: i
17+
integer :: xyz(:)
18+
19+
!$omp target map(from:xyz)
20+
!$omp do private(xyz)
21+
do i = 1, 10
22+
xyz(i) = i
23+
end do
24+
!$omp end target
25+
end subroutine
26+
27+
!CHECK: DISubprogram(name: "test1"{{.*}})
28+
!CHECK: DISubprogram(name: "test2"{{.*}})

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "llvm/IR/CallingConv.h"
3333
#include "llvm/IR/Constant.h"
3434
#include "llvm/IR/Constants.h"
35+
#include "llvm/IR/DIBuilder.h"
3536
#include "llvm/IR/DebugInfoMetadata.h"
3637
#include "llvm/IR/DerivedTypes.h"
3738
#include "llvm/IR/Function.h"
@@ -4328,6 +4329,7 @@ workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder,
43284329
// That's why make an unconditional branch from loop preheader to loop
43294330
// exit block
43304331
Builder.restoreIP({Preheader, Preheader->end()});
4332+
Builder.SetCurrentDebugLocation(Preheader->getTerminator()->getDebugLoc());
43314333
Preheader->getTerminator()->eraseFromParent();
43324334
Builder.CreateBr(CLI->getExit());
43334335

@@ -6584,13 +6586,45 @@ static Function *createOutlinedFunction(
65846586
ParameterTypes.push_back(Arg->getType());
65856587
}
65866588

6589+
auto BB = Builder.GetInsertBlock();
6590+
auto M = BB->getModule();
65876591
auto FuncType = FunctionType::get(Builder.getVoidTy(), ParameterTypes,
65886592
/*isVarArg*/ false);
6589-
auto Func = Function::Create(FuncType, GlobalValue::InternalLinkage, FuncName,
6590-
Builder.GetInsertBlock()->getModule());
6593+
auto Func =
6594+
Function::Create(FuncType, GlobalValue::InternalLinkage, FuncName, M);
65916595

65926596
// Save insert point.
6593-
auto OldInsertPoint = Builder.saveIP();
6597+
IRBuilder<>::InsertPointGuard IPG(Builder);
6598+
// If there's a DISubprogram associated with current function, then
6599+
// generate one for the outlined function.
6600+
if (Function *ParentFunc = BB->getParent()) {
6601+
if (DISubprogram *SP = ParentFunc->getSubprogram()) {
6602+
DICompileUnit *CU = SP->getUnit();
6603+
DIBuilder DB(*M, true, CU);
6604+
DebugLoc DL = Builder.getCurrentDebugLocation();
6605+
if (DL) {
6606+
// TODO: We are using nullopt for arguments at the moment. This will
6607+
// need to be updated when debug data is being generated for variables.
6608+
DISubroutineType *Ty =
6609+
DB.createSubroutineType(DB.getOrCreateTypeArray(std::nullopt));
6610+
DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
6611+
DISubprogram::SPFlagOptimized |
6612+
DISubprogram::SPFlagLocalToUnit;
6613+
6614+
DISubprogram *OutlinedSP = DB.createFunction(
6615+
CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty,
6616+
DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags);
6617+
6618+
// Attach subprogram to the function.
6619+
Func->setSubprogram(OutlinedSP);
6620+
// Update the CurrentDebugLocation in the builder so that right scope
6621+
// is used for things inside outlined function.
6622+
Builder.SetCurrentDebugLocation(
6623+
DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(),
6624+
OutlinedSP, DL.getInlinedAt()));
6625+
}
6626+
}
6627+
}
65946628

65956629
// Generate the region into the function.
65966630
BasicBlock *EntryBB = BasicBlock::Create(Builder.getContext(), "entry", Func);
@@ -6697,9 +6731,6 @@ static Function *createOutlinedFunction(
66976731
for (auto Deferred : DeferredReplacement)
66986732
ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
66996733

6700-
// Restore insert point.
6701-
Builder.restoreIP(OldInsertPoint);
6702-
67036734
return Func;
67046735
}
67056736

llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6006,6 +6006,10 @@ TEST_F(OpenMPIRBuilderTest, TargetRegion) {
60066006
BasicBlock *FallbackBlock = Branch->getSuccessor(0);
60076007
Iter = FallbackBlock->rbegin();
60086008
CallInst *FCall = dyn_cast<CallInst>(&*(++Iter));
6009+
// 'F' has a dummy DISubprogram which causes OutlinedFunc to also
6010+
// have a DISubprogram. In this case, the call to OutlinedFunc needs
6011+
// to have a debug loc, otherwise verifier will complain.
6012+
FCall->setDebugLoc(DL);
60096013
EXPECT_NE(FCall, nullptr);
60106014

60116015
// Check that the correct aguments are passed in
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
module attributes {omp.is_target_device = true} {
4+
llvm.func @_QQmain() {
5+
%0 = llvm.mlir.constant(1 : i32) : i32
6+
%1 = llvm.alloca %0 x i32 : (i32) -> !llvm.ptr
7+
%9 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
8+
omp.target map_entries(%9 -> %arg0 : !llvm.ptr) {
9+
^bb0(%arg0: !llvm.ptr):
10+
%13 = llvm.mlir.constant(1 : i32) : i32
11+
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
12+
omp.terminator
13+
}
14+
llvm.return
15+
} loc(#loc3)
16+
}
17+
#file = #llvm.di_file<"target.f90" in "">
18+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
19+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
20+
emissionKind = LineTablesOnly>
21+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
22+
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
23+
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#loc1 = loc("target.f90":1:1)
25+
#loc2 = loc("target.f90":46:3)
26+
#loc3 = loc(fused<#sp>[#loc1])
27+
28+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
29+
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
// Same test as omptarget-debug.mlir but with is_target_device = false.
4+
// Somehow test with omp.target don't work with -split-input-file.
5+
module attributes {omp.is_target_device = false} {
6+
llvm.func @_QQmain() {
7+
%0 = llvm.mlir.constant(1 : i32) : i32
8+
%1 = llvm.alloca %0 x i32 : (i32) -> !llvm.ptr
9+
%9 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
10+
omp.target map_entries(%9 -> %arg0 : !llvm.ptr) {
11+
^bb0(%arg0: !llvm.ptr):
12+
%13 = llvm.mlir.constant(1 : i32) : i32
13+
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
14+
omp.terminator
15+
}
16+
llvm.return
17+
} loc(#loc3)
18+
}
19+
#file = #llvm.di_file<"target.f90" in "">
20+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
21+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
22+
emissionKind = LineTablesOnly>
23+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
24+
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
25+
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
26+
#loc1 = loc("target.f90":1:1)
27+
#loc2 = loc("target.f90":46:3)
28+
#loc3 = loc(fused<#sp>[#loc1])
29+
30+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
31+
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])

0 commit comments

Comments
 (0)