Skip to content

Commit 6980476

Browse files
committed
[OpenMP] Improve debug info generation for outlined function.
In OMPIRBuilder, a new function is created for the TargetOp. We also create a new DISubprogram for it. All the variables that were in the target region now have to be updated to have the correct scope. This after the fact updating of debug information becomes very difficult in certain cases. This PR is making the change that OMPIRBuilder will not generate a DISubprogram. The responsibility has been shifted to the frontend. This allows us to simplify the updating of debug records. The commit is made a bit more complicated by the the fact that in new scheme, the debug location already points to the new DISubprogram by the time it reaches convertOmpTarget. But we need some code generation in the parent function so we have to carefully manage the debug locations. This fixes issue `#134991`.
1 parent e476d57 commit 6980476

File tree

9 files changed

+94
-55
lines changed

9 files changed

+94
-55
lines changed

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6891,23 +6891,19 @@ static void FixupDebugInfoForOutlinedFunction(
68916891
if (!NewSP)
68926892
return;
68936893

6894-
DenseMap<const MDNode *, MDNode *> Cache;
68956894
SmallDenseMap<DILocalVariable *, DILocalVariable *> RemappedVariables;
68966895

68976896
auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar, unsigned arg) {
6898-
auto NewSP = Func->getSubprogram();
68996897
DILocalVariable *&NewVar = RemappedVariables[OldVar];
69006898
// Only use cached variable if the arg number matches. This is important
69016899
// so that DIVariable created for privatized variables are not discarded.
69026900
if (NewVar && (arg == NewVar->getArg()))
69036901
return NewVar;
69046902

6905-
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
6906-
*OldVar->getScope(), *NewSP, Builder.getContext(), Cache);
69076903
NewVar = llvm::DILocalVariable::get(
6908-
Builder.getContext(), NewScope, OldVar->getName(), OldVar->getFile(),
6909-
OldVar->getLine(), OldVar->getType(), arg, OldVar->getFlags(),
6910-
OldVar->getAlignInBits(), OldVar->getAnnotations());
6904+
Builder.getContext(), OldVar->getScope(), OldVar->getName(),
6905+
OldVar->getFile(), OldVar->getLine(), OldVar->getType(), arg,
6906+
OldVar->getFlags(), OldVar->getAlignInBits(), OldVar->getAnnotations());
69116907
return NewVar;
69126908
};
69136909

@@ -6921,7 +6917,8 @@ static void FixupDebugInfoForOutlinedFunction(
69216917
ArgNo = std::get<1>(Iter->second) + 1;
69226918
}
69236919
}
6924-
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
6920+
if (ArgNo != 0)
6921+
DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
69256922
};
69266923

69276924
// The location and scope of variable intrinsics and records still point to
@@ -7000,36 +6997,9 @@ static Expected<Function *> createOutlinedFunction(
70006997

70016998
// Save insert point.
70026999
IRBuilder<>::InsertPointGuard IPG(Builder);
7003-
// If there's a DISubprogram associated with current function, then
7004-
// generate one for the outlined function.
7005-
if (Function *ParentFunc = BB->getParent()) {
7006-
if (DISubprogram *SP = ParentFunc->getSubprogram()) {
7007-
DICompileUnit *CU = SP->getUnit();
7008-
DIBuilder DB(*M, true, CU);
7009-
DebugLoc DL = Builder.getCurrentDebugLocation();
7010-
if (DL) {
7011-
// TODO: We are using nullopt for arguments at the moment. This will
7012-
// need to be updated when debug data is being generated for variables.
7013-
DISubroutineType *Ty =
7014-
DB.createSubroutineType(DB.getOrCreateTypeArray({}));
7015-
DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagDefinition |
7016-
DISubprogram::SPFlagOptimized |
7017-
DISubprogram::SPFlagLocalToUnit;
7018-
7019-
DISubprogram *OutlinedSP = DB.createFunction(
7020-
CU, FuncName, FuncName, SP->getFile(), DL.getLine(), Ty,
7021-
DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags);
7022-
7023-
// Attach subprogram to the function.
7024-
Func->setSubprogram(OutlinedSP);
7025-
// Update the CurrentDebugLocation in the builder so that right scope
7026-
// is used for things inside outlined function.
7027-
Builder.SetCurrentDebugLocation(
7028-
DILocation::get(Func->getContext(), DL.getLine(), DL.getCol(),
7029-
OutlinedSP, DL.getInlinedAt()));
7030-
}
7031-
}
7032-
}
7000+
// We will generate the entries in the outlined function but the debug
7001+
// location may still be pointing to the parent function. Reset it now.
7002+
Builder.SetCurrentDebugLocation(llvm::DebugLoc());
70337003

70347004
// Generate the region into the function.
70357005
BasicBlock *EntryBB = BasicBlock::Create(Builder.getContext(), "entry", Func);

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5324,9 +5324,27 @@ static LogicalResult
53245324
convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
53255325
LLVM::ModuleTranslation &moduleTranslation) {
53265326
auto targetOp = cast<omp::TargetOp>(opInst);
5327+
// The current debug location already has the DISubprogram for the outlined
5328+
// function that will be created for the target op. We save it here so that
5329+
// we can set it on the outlined function.
5330+
llvm::DebugLoc outlinedFnLoc = builder.getCurrentDebugLocation();
53275331
if (failed(checkImplementationStatus(opInst)))
53285332
return failure();
53295333

5334+
// During the handling of target op, we will generate instructions in the
5335+
// parent function like call to the oulined function or branch to a new
5336+
// BasicBlock. We set the debug location here to parent function so that those
5337+
// get the correct debug locations. For outlined functions, the normal MLIR op
5338+
// conversion will automatically pick the correct location.
5339+
llvm::BasicBlock *parentBB = builder.GetInsertBlock();
5340+
assert(parentBB && "No insert block is set for the builder");
5341+
llvm::Function *parentLLVMFn = parentBB->getParent();
5342+
assert(parentLLVMFn && "Parent Function must be valid");
5343+
if (llvm::DISubprogram *SP = parentLLVMFn->getSubprogram())
5344+
builder.SetCurrentDebugLocation(llvm::DILocation::get(
5345+
parentLLVMFn->getContext(), outlinedFnLoc.getLine(),
5346+
outlinedFnLoc.getCol(), SP, outlinedFnLoc.getInlinedAt()));
5347+
53305348
llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
53315349
bool isTargetDevice = ompBuilder->Config.isTargetDevice();
53325350
bool isGPU = ompBuilder->Config.isGPU();
@@ -5420,6 +5438,9 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
54205438
assert(llvmParentFn && llvmOutlinedFn &&
54215439
"Both parent and outlined functions must exist at this point");
54225440

5441+
if (outlinedFnLoc && llvmParentFn->getSubprogram())
5442+
llvmOutlinedFn->setSubprogram(outlinedFnLoc->getScope()->getSubprogram());
5443+
54235444
if (auto attr = llvmParentFn->getFnAttribute("target-cpu");
54245445
attr.isStringAttribute())
54255446
llvmOutlinedFn->addFnAttr(attr);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2+
3+
module attributes {omp.is_target_device = false} {
4+
llvm.func @test() {
5+
omp.target {
6+
omp.terminator
7+
} loc(#loc4)
8+
llvm.return
9+
} loc(#loc3)
10+
}
11+
#file = #llvm.di_file<"target.f90" in "">
12+
#cu = #llvm.di_compile_unit<id = distinct[0]<>,
13+
sourceLanguage = DW_LANG_Fortran95, file = #file, isOptimized = false,
14+
emissionKind = Full>
15+
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
16+
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
17+
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
18+
#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
19+
name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
20+
type = #sp_ty>
21+
#loc1 = loc("target.f90":1:1)
22+
#loc2 = loc("target.f90":46:3)
23+
#loc3 = loc(fused<#sp>[#loc1])
24+
#loc4 = loc(fused<#sp1>[#loc2])
25+
26+
// CHECK: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}})
27+

mlir/test/Target/LLVMIR/omptarget-debug-nowait.mlir

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module attributes {omp.is_target_device = false} {
2020
^bb3: // pred: ^bb1
2121
llvm.store %13, %arg1 : i32, !llvm.ptr
2222
omp.terminator
23-
}
23+
} loc(#loc3)
2424
llvm.return
2525
} loc(#loc2)
2626
}
@@ -34,7 +34,10 @@ module attributes {omp.is_target_device = false} {
3434
types = #di_null_type>
3535
#sp = #llvm.di_subprogram<compileUnit = #cu, name = "main", file=#file,
3636
subprogramFlags = "Definition", type = #sp_ty>
37+
#sp1 = #llvm.di_subprogram<compileUnit = #cu, name = "target", file=#file,
38+
subprogramFlags = "Definition", type = #sp_ty>
3739

3840
#loc1 = loc("test.f90":6:7)
3941
#loc2 = loc(fused<#sp>[#loc1])
42+
#loc3 = loc(fused<#sp1>[#loc1])
4043

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
2020
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
2121
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22-
#var_arr = #llvm.di_local_variable<scope = #sp,
22+
#sp1 = #llvm.di_subprogram<id = distinct[3]<>, compileUnit = #cu, scope = #file,
23+
name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#var_arr = #llvm.di_local_variable<scope = #sp1,
2325
name = "arr", file = #file, line = 4, type = #array_ty>
24-
#var_i = #llvm.di_local_variable<scope = #sp,
26+
#var_i = #llvm.di_local_variable<scope = #sp1,
2527
name = "i", file = #file, line = 13, type = #int_ty>
26-
#var_x = #llvm.di_local_variable<scope = #sp,
28+
#var_x = #llvm.di_local_variable<scope = #sp1,
2729
name = "x", file = #file, line = 12, type = #real_ty>
2830

2931
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui32>>, llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_target_device = true} {
@@ -47,7 +49,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
4749
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
4850
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
4951
omp.terminator
50-
}
52+
} loc(#loc5)
5153
llvm.return
5254
} loc(#loc3)
5355
llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> {
@@ -57,8 +59,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
5759
#loc2 = loc("target.f90":11:7)
5860
#loc3 = loc(fused<#sp>[#loc2])
5961
#loc4 = loc(fused<#g_var>[#loc1])
62+
#loc5 = loc(fused<#sp1>[#loc2])
6063

61-
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
64+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}})
6265
// CHECK: !DILocalVariable(name: "dyn_ptr", arg: 1, scope: ![[SP]]{{.*}}flags: DIFlagArtificial)
6366
// CHECK: !DILocalVariable(name: "x", arg: 2, scope: ![[SP]]{{.*}})
6467
// CHECK: !DILocalVariable(name: "arr", arg: 3, scope: ![[SP]]{{.*}})

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
#g_var_expr = #llvm.di_global_variable_expression<var = #g_var>
2020
#sp = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
2121
name = "test", file = #file, subprogramFlags = "Definition", type = #sp_ty>
22-
#var_arr = #llvm.di_local_variable<scope = #sp,
22+
#sp1 = #llvm.di_subprogram<id = distinct[3]<>, compileUnit = #cu, scope = #file,
23+
name = "target", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#var_arr = #llvm.di_local_variable<scope = #sp1,
2325
name = "arr", file = #file, line = 4, type = #array_ty>
24-
#var_i = #llvm.di_local_variable<scope = #sp,
26+
#var_i = #llvm.di_local_variable<scope = #sp1,
2527
name = "i", file = #file, line = 13, type = #int_ty>
26-
#var_x = #llvm.di_local_variable<scope = #sp,
28+
#var_x = #llvm.di_local_variable<scope = #sp1,
2729
name = "x", file = #file, line = 12, type = #real_ty>
2830

2931
module attributes {omp.is_target_device = false} {
@@ -45,7 +47,7 @@ module attributes {omp.is_target_device = false} {
4547
llvm.intr.dbg.declare #var_arr = %arg1 : !llvm.ptr
4648
llvm.intr.dbg.declare #var_i = %arg2 : !llvm.ptr
4749
omp.terminator
48-
}
50+
} loc(#loc5)
4951
llvm.return
5052
} loc(#loc3)
5153
llvm.mlir.global internal @_QFEarr() {addr_space = 0 : i32, dbg_exprs = [#g_var_expr]} : !llvm.array<10 x i32> {
@@ -55,8 +57,9 @@ module attributes {omp.is_target_device = false} {
5557
#loc2 = loc("target.f90":11:7)
5658
#loc3 = loc(fused<#sp>[#loc2])
5759
#loc4 = loc(fused<#g_var>[#loc1])
60+
#loc5 = loc(fused<#sp1>[#loc2])
5861

59-
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "__omp_offloading{{.*}}test{{.*}})
62+
// CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "target"{{.*}})
6063
// CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[SP]]{{.*}})
6164
// CHECK: !DILocalVariable(name: "arr", arg: 2, scope: ![[SP]]{{.*}})
6265
// CHECK: !DILocalVariable(name: "i", arg: 3, scope: ![[SP]]{{.*}})

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
1010
%13 = llvm.mlir.constant(1 : i32) : i32
1111
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
1212
omp.terminator
13-
}
13+
} loc(#loc4)
1414
llvm.return
1515
} loc(#loc3)
1616
}
@@ -21,9 +21,13 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
2121
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
2222
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
2323
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
24+
#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
25+
name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
26+
type = #sp_ty>
2427
#loc1 = loc("target.f90":1:1)
2528
#loc2 = loc("target.f90":46:3)
2629
#loc3 = loc(fused<#sp>[#loc1])
30+
#loc4 = loc(fused<#sp1>[#loc1])
2731

28-
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
32+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}})
2933
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])

mlir/test/Target/LLVMIR/omptarget-debug2.mlir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module attributes {omp.is_target_device = false} {
1111
%13 = llvm.mlir.constant(1 : i32) : i32
1212
llvm.store %13, %arg0 : i32, !llvm.ptr loc(#loc2)
1313
omp.terminator
14-
}
14+
} loc(#loc4)
1515
llvm.return
1616
} loc(#loc3)
1717
}
@@ -22,9 +22,13 @@ module attributes {omp.is_target_device = false} {
2222
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_normal>
2323
#sp = #llvm.di_subprogram<id = distinct[1]<>, compileUnit = #cu, scope = #file,
2424
name = "_QQmain", file = #file, subprogramFlags = "Definition", type = #sp_ty>
25+
#sp1 = #llvm.di_subprogram<id = distinct[2]<>, compileUnit = #cu, scope = #file,
26+
name = "__omp_offloading_target", file = #file, subprogramFlags = "Definition",
27+
type = #sp_ty>
2528
#loc1 = loc("target.f90":1:1)
2629
#loc2 = loc("target.f90":46:3)
2730
#loc3 = loc(fused<#sp>[#loc1])
31+
#loc4 = loc(fused<#sp1>[#loc1])
2832

29-
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_{{.*}}"{{.*}})
33+
// CHECK-DAG: ![[SP:.*]] = {{.*}}!DISubprogram(name: "__omp_offloading_target"{{.*}})
3034
// CHECK-DAG: !DILocation(line: 46, column: 3, scope: ![[SP]])

mlir/test/Target/LLVMIR/omptarget-parallel-llvm-debug.mlir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang", isOptimized = false, emissionKind = Full>
77
#sp_ty = #llvm.di_subroutine_type<callingConvention = DW_CC_program, types = #di_null_type>
88
#sp = #llvm.di_subprogram<compileUnit = #cu, scope = #di_file, name = "test", file = #di_file, subprogramFlags = "Definition", type = #sp_ty>
9+
#sp1 = #llvm.di_subprogram<compileUnit = #cu, scope = #di_file, name = "kernel", file = #di_file, subprogramFlags = "Definition", type = #sp_ty>
910
#int_ty = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed>
1011
#var_x = #llvm.di_local_variable<scope = #sp, name = "x", file = #di_file, type = #int_ty>
12+
#var_x1 = #llvm.di_local_variable<scope = #sp1, name = "x", file = #di_file, type = #int_ty>
1113
module attributes {dlti.dl_spec = #dlti.dl_spec<i32 = dense<32> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr = dense<64> : vector<4xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, "dlti.endianness" = "little", "dlti.stack_alignment" = 128 : i64, "dlti.mangling_mode" = "e">, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", fir.target_cpu = "x86-64", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.ident = "flang version 21.0.0 (/home/haqadeer/work/src/aomp-llvm-project/flang 793f9220ab32f92fc3b253efec2e332c18090e53)", llvm.target_triple = "x86_64-unknown-linux-gnu", omp.is_gpu = false, omp.is_target_device = false, omp.requires = #omp<clause_requires none>, omp.target_triples = ["amdgcn-amd-amdhsa"], omp.version = #omp.version<version = 52>} {
1214
llvm.func @_QQmain() attributes {fir.bindc_name = "test", frame_pointer = #llvm.framePointerKind<all>, target_cpu = "x86-64"} {
1315
%0 = llvm.mlir.constant(1 : i64) : i64
@@ -16,20 +18,22 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<i32 = dense<32> : vector<2xi64>,
1618
%5 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "x"}
1719
omp.target map_entries(%5 -> %arg0 : !llvm.ptr) {
1820
%6 = llvm.mlir.constant(1 : i32) : i32
19-
llvm.intr.dbg.declare #var_x = %arg0 : !llvm.ptr loc(#loc2)
21+
llvm.intr.dbg.declare #var_x1 = %arg0 : !llvm.ptr loc(#loc3)
2022
omp.parallel {
2123
%7 = llvm.load %arg0 : !llvm.ptr -> i32
2224
%8 = llvm.add %7, %6 : i32
2325
llvm.store %8, %arg0 : i32, !llvm.ptr
2426
omp.terminator
2527
}
2628
omp.terminator
27-
}
29+
} loc(#loc4)
2830
llvm.return
2931
} loc(#loc10)
3032
}
3133
#loc1 = loc("target.f90":1:7)
3234
#loc2 = loc("target.f90":3:18)
35+
#loc3 = loc("target.f90":6:18)
36+
#loc4 = loc(fused<#sp1>[#loc3])
3337
#loc10 = loc(fused<#sp>[#loc1])
3438

3539

0 commit comments

Comments
 (0)