Skip to content

Commit 778b85a

Browse files
authored
[flang][debug] handle inlined dummy_scope after #167489 (#168039)
#167489 did not work properly when MLIR inlining is enabled (experimental in flang, enabled with `-mllvm -inline-all`). The reason is that inlining will cause several `fir.dummy_scope` to coexist inside a same `func.func` (`fir.dummy_scope` of inlined `func.func` are preserved in order to preserve the relationship between arguments of the inlined call for better aliasing deductions). After #167489, the debug info pass creates argument debug info for all fir.declare with a fir.dummy_scope. This causes arguments from inlined calls to appear as argument of the procedure where the call was inlined. To avoid this, only consider that fir.declare are arguments of the current function if their fir.dummy_scope is the first one created in the function (fir.dummy_scope cannot be reorder because they have write effects to the debug memory ressource, and the fir.dummy_scope of the current functions is always emitted before any calls are lowered, so before any fir.dummy_scope are inlined).
1 parent 5829bb9 commit 778b85a

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
5353
mlir::LLVM::DIFileAttr fileAttr,
5454
mlir::LLVM::DIScopeAttr scopeAttr,
5555
fir::DebugTypeGenerator &typeGen,
56-
mlir::SymbolTable *symbolTable);
56+
mlir::SymbolTable *symbolTable, mlir::Value dummyScope);
5757

5858
public:
5959
AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {}
@@ -206,7 +206,8 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
206206
mlir::LLVM::DIFileAttr fileAttr,
207207
mlir::LLVM::DIScopeAttr scopeAttr,
208208
fir::DebugTypeGenerator &typeGen,
209-
mlir::SymbolTable *symbolTable) {
209+
mlir::SymbolTable *symbolTable,
210+
mlir::Value dummyScope) {
210211
mlir::MLIRContext *context = &getContext();
211212
mlir::OpBuilder builder(context);
212213
auto result = fir::NameUniquer::deconstruct(declOp.getUniqName());
@@ -230,7 +231,7 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
230231

231232
// Get the dummy argument position from the explicit attribute.
232233
unsigned argNo = 0;
233-
if (declOp.getDummyScope()) {
234+
if (dummyScope && declOp.getDummyScope() == dummyScope) {
234235
if (auto argNoOpt = declOp.getDummyArgNo())
235236
argNo = *argNoOpt;
236237
}
@@ -610,6 +611,21 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
610611
funcOp->setLoc(builder.getFusedLoc({l}, spAttr));
611612
addTargetOpDISP(/*lineTableOnly=*/false, entities);
612613

614+
// Find the first dummy_scope definition. This is the one of the current
615+
// function. The other ones may come from inlined calls. The variables inside
616+
// those inlined calls should not be identified as arguments of the current
617+
// function.
618+
mlir::Value dummyScope;
619+
funcOp.walk([&](fir::UndefOp undef) -> mlir::WalkResult {
620+
// TODO: delay fir.dummy_scope translation to undefined until
621+
// codegeneration. This is nicer and safer to match.
622+
if (llvm::isa<fir::DummyScopeType>(undef.getType())) {
623+
dummyScope = undef;
624+
return mlir::WalkResult::interrupt();
625+
}
626+
return mlir::WalkResult::advance();
627+
});
628+
613629
funcOp.walk([&](fir::cg::XDeclareOp declOp) {
614630
mlir::LLVM::DISubprogramAttr spTy = spAttr;
615631
if (auto tOp = declOp->getParentOfType<mlir::omp::TargetOp>()) {
@@ -619,7 +635,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
619635
spTy = sp;
620636
}
621637
}
622-
handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable);
638+
handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable, dummyScope);
623639
});
624640
// commonBlockMap ensures that we don't create multiple DICommonBlockAttr of
625641
// the same name in one function. But it is ok (rather required) to create
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Tests that inlined calls arguments are not mistaken for the arguments of the
2+
// procedure where the calls were inlined.
3+
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s
4+
5+
// CHECK: #di_local_variable = #llvm.di_local_variable<scope = #di_subprogram, name = "i", file = #di_file, line = 6, arg = 1, type = #di_basic_type>
6+
// CHECK: #di_local_variable1 = #llvm.di_local_variable<scope = #di_subprogram, name = "i", file = #di_file, line = 1, type = #di_basic_type>
7+
8+
func.func @foo_(%arg0: !fir.ref<i32> {fir.bindc_name = "i"} loc("debug-dummy-argument-inline.f90":5:1)) attributes {fir.internal_name = "_QPfoo"} {
9+
%0 = fir.undefined !fir.dscope loc(#loc5)
10+
%1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFfooEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc6)
11+
%2 = fir.undefined !fir.dscope loc(#loc11)
12+
%3 = fircg.ext_declare %1 dummy_scope %2 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc12)
13+
fir.call @buzz_(%3) fastmath<contract> : (!fir.ref<i32>) -> () loc(#loc13)
14+
%4 = fir.undefined !fir.dscope loc(#loc14)
15+
%5 = fircg.ext_declare %1 dummy_scope %4 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc15)
16+
fir.call @buzz_(%5) fastmath<contract> : (!fir.ref<i32>) -> () loc(#loc16)
17+
return loc(#loc9)
18+
} loc(#loc5)
19+
func.func private @buzz_(!fir.ref<i32>) attributes {fir.internal_name = "_QPbuzz"} loc(#loc10)
20+
#loc = loc("debug-dummy-argument-inline.f90":0:0)
21+
#loc1 = loc("debug-dummy-argument-inline.f90":1:1)
22+
#loc2 = loc("debug-dummy-argument-inline.f90":2:14)
23+
#loc3 = loc("debug-dummy-argument-inline.f90":3:3)
24+
#loc4 = loc("debug-dummy-argument-inline.f90":4:1)
25+
#loc5 = loc("debug-dummy-argument-inline.f90":5:1)
26+
#loc6 = loc("debug-dummy-argument-inline.f90":6:14)
27+
#loc7 = loc("debug-dummy-argument-inline.f90":7:3)
28+
#loc8 = loc("debug-dummy-argument-inline.f90":8:3)
29+
#loc9 = loc("debug-dummy-argument-inline.f90":9:1)
30+
#loc10 = loc("debug-dummy-argument-inline.f90":3:8)
31+
#loc11 = loc(callsite(#loc1 at #loc7))
32+
#loc12 = loc(callsite(#loc2 at #loc7))
33+
#loc13 = loc(callsite(#loc3 at #loc7))
34+
#loc14 = loc(callsite(#loc1 at #loc8))
35+
#loc15 = loc(callsite(#loc2 at #loc8))
36+
#loc16 = loc(callsite(#loc3 at #loc8))

0 commit comments

Comments
 (0)