[flang-commits] [flang] 06dcba6 - [flang][debug] Add fake use ops for dynamic array dimension variables (#200061)
via flang-commits
flang-commits at lists.llvm.org
Mon Jun 22 05:33:45 PDT 2026
Author: Tim
Date: 2026-06-22T13:33:41+01:00
New Revision: 06dcba660904e041cca1d245e674f040bb04f454
URL: https://github.com/llvm/llvm-project/commit/06dcba660904e041cca1d245e674f040bb04f454
DIFF: https://github.com/llvm/llvm-project/commit/06dcba660904e041cca1d245e674f040bb04f454.diff
LOG: [flang][debug] Add fake use ops for dynamic array dimension variables (#200061)
In cases where the upper or lower bounds of a dynamic array are not
explicitly referenced in code, flang can optimize away the internal
variables that represent these values. This causes missing values to
appear in the debugger when examining the dynamic array's type. Adding
an llvm.fake.use op for each bound preserves it for use by a debugger,
similar to the fix for #185432.
Resolves #119474
Added:
flang/test/Transforms/debug-fake-use-multiple-dimensions.fir
flang/test/Transforms/debug-fake-use-multiple-returns.fir
Modified:
flang/include/flang/Optimizer/Transforms/Passes.td
flang/lib/Optimizer/Passes/Pipelines.cpp
flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
flang/test/Transforms/debug-fake-use.fir
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index d9072e7aab4f7..8c082fb073451 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -267,9 +267,9 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
Option<"dwarfDebugFlags", "dwarf-debug-flags",
"std::string", /*default=*/"std::string{}",
"Command-line flags to append to DWARF producer">,
- Option<"emitFakeUseForArguments", "emit-fake-use-for-arguments",
+ Option<"emitFakeUseForDebugVars", "emit-fake-use-for-debug-vars",
"bool", /*default=*/"false",
- "Emit fake use for function arguments to extend their lifetime">
+ "Emit fake use for debug variables to extend their lifetime">
];
}
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index c6d531ce50762..c677962f30199 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -113,7 +113,7 @@ void addDebugInfoPass(mlir::PassManager &pm,
options.dwarfVersion = config.DwarfVersion;
options.splitDwarfFile = config.SplitDwarfFile;
options.dwarfDebugFlags = config.DwarfDebugFlags;
- options.emitFakeUseForArguments =
+ options.emitFakeUseForDebugVars =
(config.OptLevel == llvm::OptimizationLevel::O0) &&
!disableArgumentFakeUse;
addPassConditionally(pm, disableDebugInfo,
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index e0b570a908521..e5c1fc8279630 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -291,6 +291,27 @@ bool AddDebugInfoPass::createCommonBlockGlobal(
return true;
}
+// Create fake uses for compiler-generated internal variables that represent
+// values needed by a debugger. This prevents values from being optimized out
+// such as the count and lower bound of dynamic arrays.
+template <typename Op>
+static void InsertFakeUseForDebugVar(mlir::OpBuilder &builder, Op declOp,
+ mlir::Value var) {
+ if (auto funcOp = declOp->template getParentOfType<mlir::func::FuncOp>()) {
+ if (declOp->getBlock() == &funcOp.getBody().front()) {
+ for (mlir::Block &block : funcOp.getBody()) {
+ if (auto returnOp =
+ mlir::dyn_cast<mlir::func::ReturnOp>(block.getTerminator())) {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPoint(returnOp);
+ if (!fir::getIntIfConstant(var))
+ fir::FakeUseOp::create(builder, declOp.getLoc(), var);
+ }
+ }
+ }
+ }
+}
+
template <typename Op>
void AddDebugInfoPass::handleLocalVariable(Op declOp, llvm::StringRef name,
mlir::LLVM::DIFileAttr fileAttr,
@@ -307,22 +328,9 @@ void AddDebugInfoPass::handleLocalVariable(Op declOp, llvm::StringRef name,
if (dummyScope && declOp.getDummyScope() == dummyScope) {
if (auto argNoOpt = declOp.getDummyArgNo()) {
argNo = *argNoOpt;
- if (emitFakeUseForArguments) {
+ if (emitFakeUseForDebugVars) {
if constexpr (std::is_same_v<Op, fir::cg::XDeclareOp>) {
- if (auto funcOp =
- declOp->template getParentOfType<mlir::func::FuncOp>()) {
- if (declOp->getBlock() == &funcOp.getBody().front()) {
- for (mlir::Block &block : funcOp.getBody()) {
- if (auto returnOp = mlir::dyn_cast<mlir::func::ReturnOp>(
- block.getTerminator())) {
- mlir::OpBuilder::InsertionGuard guard(builder);
- builder.setInsertionPoint(returnOp);
- fir::FakeUseOp::create(builder, declOp.getLoc(),
- declOp.getMemref());
- }
- }
- }
- }
+ InsertFakeUseForDebugVar(builder, declOp, declOp.getMemref());
}
}
}
@@ -331,6 +339,31 @@ void AddDebugInfoPass::handleLocalVariable(Op declOp, llvm::StringRef name,
auto tyAttr =
typeGen.convertType(typeToConvert, fileAttr, scopeAttr, typeGenDeclOp);
+ if (emitFakeUseForDebugVars) {
+ // Create fake uses for internal variables that represent count and lower
+ // bound of dynamic arrays to ensure they are not optimized out.
+ if (auto arrayTy =
+ mlir::dyn_cast<mlir::LLVM::DICompositeTypeAttr>(tyAttr)) {
+ if (arrayTy.getTag() == llvm::dwarf::DW_TAG_array_type) {
+ if constexpr (std::is_same_v<Op, fir::cg::XDeclareOp>) {
+ // Count is represented as a value in the shape attribute
+ for (auto val : declOp.getShape())
+ InsertFakeUseForDebugVar(builder, declOp, val);
+ // Lower bound is represented as a value in the shift attribute
+ for (auto val : declOp.getShift())
+ InsertFakeUseForDebugVar(builder, declOp, val);
+ }
+ }
+ }
+
+ // Create fake uses for the length of character arrays to ensure they
+ // are not optimized out.
+ if constexpr (std::is_same_v<Op, fir::cg::XDeclareOp>) {
+ for (auto val : declOp.getTypeparams())
+ InsertFakeUseForDebugVar(builder, declOp, val);
+ }
+ }
+
auto localVarAttr = mlir::LLVM::DILocalVariableAttr::get(
context, scopeAttr, mlir::StringAttr::get(context, name), fileAttr,
getLineFromLoc(declOp.getLoc()), argNo, /* alignInBits*/ 0, tyAttr,
diff --git a/flang/test/Transforms/debug-fake-use-multiple-dimensions.fir b/flang/test/Transforms/debug-fake-use-multiple-dimensions.fir
new file mode 100644
index 0000000000000..a1479aa14cb00
--- /dev/null
+++ b/flang/test/Transforms/debug-fake-use-multiple-dimensions.fir
@@ -0,0 +1,135 @@
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=true" %s | FileCheck %s --check-prefix=FAKE-USE
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=false" %s | FileCheck %s --check-prefix=NO-FAKE-USE
+
+// Test that fir.fake_use ops are inserted for count and lower bound variables
+// in each dimension of a multi-dimensional dynamic array.
+
+// FAKE-USE-LABEL: func.func @test_2d_dynamic_array
+// FAKE-USE: fircg.ext_declare %arg0(%[[COUNT1:.*]], %[[COUNT2:.*]]) origin %[[LB1:.*]], %[[LB2:.*]] dummy_scope
+// FAKE-USE: fir.call @foo() : () -> ()
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: fir.fake_use %[[COUNT1]]
+// FAKE-USE: fir.fake_use %[[COUNT2]]
+// FAKE-USE: fir.fake_use %[[LB1]]
+// FAKE-USE: fir.fake_use %[[LB2]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_2d_dynamic_array
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}, %{{.*}}) origin %{{.*}}, %{{.*}} dummy_scope
+// NO-FAKE-USE: fir.call @foo() : () -> ()
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_3d_dynamic_array
+// FAKE-USE: fircg.ext_declare %arg0(%[[C1:.*]], %[[C2:.*]], %[[C3:.*]]) origin %[[L1:.*]], %[[L2:.*]], %[[L3:.*]] dummy_scope
+// FAKE-USE: fir.call @foo() : () -> ()
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: fir.fake_use %[[C1]]
+// FAKE-USE: fir.fake_use %[[C2]]
+// FAKE-USE: fir.fake_use %[[C3]]
+// FAKE-USE: fir.fake_use %[[L1]]
+// FAKE-USE: fir.fake_use %[[L2]]
+// FAKE-USE: fir.fake_use %[[L3]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_3d_dynamic_array
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}, %{{.*}}, %{{.*}}) origin %{{.*}}, %{{.*}}, %{{.*}} dummy_scope
+// NO-FAKE-USE: fir.call @foo() : () -> ()
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_2d_dynamic_array_multi_ret
+// FAKE-USE: fircg.ext_declare %arg0(%[[MR_COUNT1:.*]], %[[MR_COUNT2:.*]]) origin %[[MR_LB1:.*]], %[[MR_LB2:.*]] dummy_scope
+// FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// FAKE-USE: ^bb1:
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: fir.fake_use %[[MR_COUNT1]]
+// FAKE-USE: fir.fake_use %[[MR_COUNT2]]
+// FAKE-USE: fir.fake_use %[[MR_LB1]]
+// FAKE-USE: fir.fake_use %[[MR_LB2]]
+// FAKE-USE: return
+// FAKE-USE: ^bb2:
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: fir.fake_use %[[MR_COUNT1]]
+// FAKE-USE: fir.fake_use %[[MR_COUNT2]]
+// FAKE-USE: fir.fake_use %[[MR_LB1]]
+// FAKE-USE: fir.fake_use %[[MR_LB2]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_2d_dynamic_array_multi_ret
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}, %{{.*}}) origin %{{.*}}, %{{.*}} dummy_scope
+// NO-FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// NO-FAKE-USE: ^bb1:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+// NO-FAKE-USE: ^bb2:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_3d_mixed_array
+// FAKE-USE: %[[CST_COUNT:.*]] = arith.constant 10 : index
+// FAKE-USE: %[[CST_LB:.*]] = arith.constant 1 : index
+// FAKE-USE: fircg.ext_declare %arg0(%[[CST_COUNT]], %[[DYN_COUNT1:.*]], %[[DYN_COUNT2:.*]]) origin %[[CST_LB]], %[[DYN_LB1:.*]], %[[DYN_LB2:.*]] dummy_scope
+// FAKE-USE: fir.call @foo() : () -> ()
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: fir.fake_use %[[DYN_COUNT1]]
+// FAKE-USE: fir.fake_use %[[DYN_COUNT2]]
+// FAKE-USE: fir.fake_use %[[DYN_LB1]]
+// FAKE-USE: fir.fake_use %[[DYN_LB2]]
+// FAKE-USE-NOT: fir.fake_use
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_3d_mixed_array
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}, %{{.*}}, %{{.*}}) origin %{{.*}}, %{{.*}}, %{{.*}} dummy_scope
+// NO-FAKE-USE: fir.call @foo() : () -> ()
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+#loc1 = loc("debug-fake-use-multiple-dimensions.f90":1:1)
+#loc3 = loc("debug-fake-use-multiple-dimensions.f90":3:14)
+#loc4 = loc("debug-fake-use-multiple-dimensions.f90":4:14)
+#loc5 = loc("debug-fake-use-multiple-dimensions.f90":5:1)
+#loc6 = loc("debug-fake-use-multiple-dimensions.f90":6:1)
+#loc = loc("debug-fake-use-multiple-dimensions.f90":0:0)
+
+module {
+ func.func private @foo()
+
+ // 2D dynamically-sized array with a single return.
+ func.func @test_2d_dynamic_array(%arg0: !fir.ref<!fir.array<?x?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg1: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg2: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg3: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg4: index loc("debug-fake-use-multiple-dimensions.f90":1:1)) attributes {fir.internal_name = "_QPtest_2d_dynamic_array"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%arg1, %arg3) origin %arg2, %arg4 dummy_scope %0 arg 1 {uniq_name = "_QFtest_2d_dynamic_arrayEarr"} : (!fir.ref<!fir.array<?x?xi32>>, index, index, index, index, !fir.dscope) -> !fir.ref<!fir.array<?x?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ return loc(#loc5)
+ } loc(#loc1)
+
+ // 3D dynamically-sized array with a single return.
+ func.func @test_3d_dynamic_array(%arg0: !fir.ref<!fir.array<?x?x?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg1: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg2: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg3: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg4: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg5: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg6: index loc("debug-fake-use-multiple-dimensions.f90":1:1)) attributes {fir.internal_name = "_QPtest_3d_dynamic_array"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%arg1, %arg3, %arg5) origin %arg2, %arg4, %arg6 dummy_scope %0 arg 1 {uniq_name = "_QFtest_3d_dynamic_arrayEarr"} : (!fir.ref<!fir.array<?x?x?xi32>>, index, index, index, index, index, index, !fir.dscope) -> !fir.ref<!fir.array<?x?x?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ return loc(#loc5)
+ } loc(#loc1)
+
+ // 2D dynamically-sized array with multiple returns.
+ func.func @test_2d_dynamic_array_multi_ret(%arg0: !fir.ref<!fir.array<?x?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg1: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg2: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg3: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg4: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg5: i1 loc("debug-fake-use-multiple-dimensions.f90":1:1)) attributes {fir.internal_name = "_QPtest_2d_dynamic_array_multi_ret"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%arg1, %arg3) origin %arg2, %arg4 dummy_scope %0 arg 1 {uniq_name = "_QFtest_2d_dynamic_array_multi_retEarr"} : (!fir.ref<!fir.array<?x?xi32>>, index, index, index, index, !fir.dscope) -> !fir.ref<!fir.array<?x?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ cf.cond_br %arg5, ^bb1, ^bb2
+ ^bb1:
+ return loc(#loc5)
+ ^bb2:
+ return loc(#loc6)
+ } loc(#loc1)
+
+ // 3D array with mixed constant and dynamic dimensions.
+ func.func @test_3d_mixed_array(%arg0: !fir.ref<!fir.array<10x?x?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg1: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg2: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg3: index loc("debug-fake-use-multiple-dimensions.f90":1:1), %arg4: index loc("debug-fake-use-multiple-dimensions.f90":1:1)) attributes {fir.internal_name = "_QPtest_3d_mixed_array"} {
+ %c10 = arith.constant 10 : index
+ %c1 = arith.constant 1 : index
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%c10, %arg1, %arg3) origin %c1, %arg2, %arg4 dummy_scope %0 arg 1 {uniq_name = "_QFtest_3d_mixed_arrayEarr"} : (!fir.ref<!fir.array<10x?x?xi32>>, index, index, index, index, index, index, !fir.dscope) -> !fir.ref<!fir.array<10x?x?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ return loc(#loc5)
+ } loc(#loc1)
+} loc(#loc)
diff --git a/flang/test/Transforms/debug-fake-use-multiple-returns.fir b/flang/test/Transforms/debug-fake-use-multiple-returns.fir
new file mode 100644
index 0000000000000..ac379d0f587f7
--- /dev/null
+++ b/flang/test/Transforms/debug-fake-use-multiple-returns.fir
@@ -0,0 +1,116 @@
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=true" %s | FileCheck %s --check-prefix=FAKE-USE
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=false" %s | FileCheck %s --check-prefix=NO-FAKE-USE
+
+// Test that fir.fake_use ops are inserted before every return in functions with
+// multiple return locations.
+
+// FAKE-USE-LABEL: func.func @test_dummy_arg_multi_ret
+// FAKE-USE: %[[UNDEF:.*]] = fir.undefined !fir.dscope
+// FAKE-USE: %[[DECL:.*]] = fircg.ext_declare %arg0 dummy_scope %[[UNDEF]] arg 1
+// FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// FAKE-USE: ^bb1:
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: return
+// FAKE-USE: ^bb2:
+// FAKE-USE: fir.fake_use %arg0
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_dummy_arg_multi_ret
+// NO-FAKE-USE: %[[UNDEF:.*]] = fir.undefined !fir.dscope
+// NO-FAKE-USE: %[[DECL:.*]] = fircg.ext_declare %arg0 dummy_scope %[[UNDEF]] arg 1
+// NO-FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// NO-FAKE-USE: ^bb1:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+// NO-FAKE-USE: ^bb2:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_dynamic_array_multi_ret
+// FAKE-USE: fircg.ext_declare %arg0(%[[COUNT:.*]]) origin %[[LB:.*]] dummy_scope
+// FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// FAKE-USE: ^bb1:
+// FAKE-USE: fir.fake_use %[[COUNT]]
+// FAKE-USE: fir.fake_use %[[LB]]
+// FAKE-USE: return
+// FAKE-USE: ^bb2:
+// FAKE-USE: fir.fake_use %[[COUNT]]
+// FAKE-USE: fir.fake_use %[[LB]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_dynamic_array_multi_ret
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}) origin %{{.*}} dummy_scope
+// NO-FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// NO-FAKE-USE: ^bb1:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+// NO-FAKE-USE: ^bb2:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_char_array_multi_ret
+// FAKE-USE: fircg.ext_declare %arg0 typeparams %[[LEN:.*]] dummy_scope
+// FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// FAKE-USE: ^bb1:
+// FAKE-USE: fir.fake_use %[[LEN]]
+// FAKE-USE: return
+// FAKE-USE: ^bb2:
+// FAKE-USE: fir.fake_use %[[LEN]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_char_array_multi_ret
+// NO-FAKE-USE: fircg.ext_declare %arg0 typeparams %{{.*}} dummy_scope
+// NO-FAKE-USE: cf.cond_br %{{.*}}, ^bb1, ^bb2
+// NO-FAKE-USE: ^bb1:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+// NO-FAKE-USE: ^bb2:
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+#loc1 = loc("debug-fake-use-multiple-returns.f90":1:1)
+#loc3 = loc("debug-fake-use-multiple-returns.f90":3:14)
+#loc4 = loc("debug-fake-use-multiple-returns.f90":4:14)
+#loc5 = loc("debug-fake-use-multiple-returns.f90":5:1)
+#loc6 = loc("debug-fake-use-multiple-returns.f90":6:1)
+#loc = loc("debug-fake-use-multiple-returns.f90":0:0)
+
+module {
+ func.func private @foo()
+
+ // Function with a dummy argument and multiple returns.
+ func.func @test_dummy_arg_multi_ret(%arg0: !fir.ref<i32> {fir.bindc_name = "expected"} loc("debug-fake-use-multiple-returns.f90":1:1), %arg1: i1 loc("debug-fake-use-multiple-returns.f90":1:1)) attributes {fir.internal_name = "_QPtest_dummy_arg_multi_ret"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFtest_dummy_arg_multi_retEexpected"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> loc(#loc3)
+ fir.call @foo() : () -> ()
+ cf.cond_br %arg1, ^bb1, ^bb2
+ ^bb1:
+ return loc(#loc5)
+ ^bb2:
+ return loc(#loc6)
+ } loc(#loc1)
+
+ // Function with a dynamically-sized array and multiple returns.
+ func.func @test_dynamic_array_multi_ret(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use-multiple-returns.f90":1:1), %arg1: index loc("debug-fake-use-multiple-returns.f90":1:1), %arg2: index loc("debug-fake-use-multiple-returns.f90":1:1), %arg3: i1 loc("debug-fake-use-multiple-returns.f90":1:1)) attributes {fir.internal_name = "_QPtest_dynamic_array_multi_ret"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%arg1) origin %arg2 dummy_scope %0 arg 1 {uniq_name = "_QFtest_dynamic_array_multi_retEarr"} : (!fir.ref<!fir.array<?xi32>>, index, index, !fir.dscope) -> !fir.ref<!fir.array<?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ cf.cond_br %arg3, ^bb1, ^bb2
+ ^bb1:
+ return loc(#loc5)
+ ^bb2:
+ return loc(#loc6)
+ } loc(#loc1)
+
+ // Function with a dynamically-sized character array and multiple returns.
+ func.func @test_char_array_multi_ret(%arg0: !fir.ref<!fir.char<1,?>> {fir.bindc_name = "str"} loc("debug-fake-use-multiple-returns.f90":1:1), %arg1: index {fir.bindc_name = "n"} loc("debug-fake-use-multiple-returns.f90":1:1), %arg2: i1 loc("debug-fake-use-multiple-returns.f90":1:1)) attributes {fir.internal_name = "_QPtest_char_array_multi_ret"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0 typeparams %arg1 dummy_scope %0 arg 1 {uniq_name = "_QFtest_char_array_multi_retEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ cf.cond_br %arg2, ^bb1, ^bb2
+ ^bb1:
+ return loc(#loc5)
+ ^bb2:
+ return loc(#loc6)
+ } loc(#loc1)
+} loc(#loc)
diff --git a/flang/test/Transforms/debug-fake-use.fir b/flang/test/Transforms/debug-fake-use.fir
index d86cc9b3afee4..d16fa2f6ff028 100644
--- a/flang/test/Transforms/debug-fake-use.fir
+++ b/flang/test/Transforms/debug-fake-use.fir
@@ -1,5 +1,5 @@
-// RUN: fir-opt --add-debug-info="emit-fake-use-for-arguments=true" %s | FileCheck %s --check-prefix=FAKE-USE
-// RUN: fir-opt --add-debug-info="emit-fake-use-for-arguments=false" %s | FileCheck %s --check-prefix=NO-FAKE-USE
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=true" %s | FileCheck %s --check-prefix=FAKE-USE
+// RUN: fir-opt --add-debug-info="emit-fake-use-for-debug-vars=false" %s | FileCheck %s --check-prefix=NO-FAKE-USE
// FAKE-USE-LABEL: func.func @test_
// FAKE-USE: %[[UNDEF:.*]] = fir.undefined !fir.dscope
@@ -31,13 +31,38 @@
// NO-FAKE-USE-NOT: fir.fake_use
// NO-FAKE-USE: return
+// FAKE-USE-LABEL: func.func @test_dynamic_array
+// FAKE-USE: fircg.ext_declare %arg0(%[[COUNT:.*]]) origin %[[LB:.*]] dummy_scope
+// FAKE-USE: fir.call @foo() : () -> ()
+// FAKE-USE: fir.fake_use %[[COUNT]]
+// FAKE-USE: fir.fake_use %[[LB]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_dynamic_array
+// NO-FAKE-USE: fircg.ext_declare %arg0(%{{.*}}) origin %{{.*}} dummy_scope
+// NO-FAKE-USE: fir.call @foo() : () -> ()
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
+// FAKE-USE-LABEL: func.func @test_char_array
+// FAKE-USE: fircg.ext_declare %arg0 typeparams %[[LEN:.*]] dummy_scope
+// FAKE-USE: fir.call @foo() : () -> ()
+// FAKE-USE: fir.fake_use %[[LEN]]
+// FAKE-USE: return
+
+// NO-FAKE-USE-LABEL: func.func @test_char_array
+// NO-FAKE-USE: fircg.ext_declare %arg0 typeparams %{{.*}} dummy_scope
+// NO-FAKE-USE: fir.call @foo() : () -> ()
+// NO-FAKE-USE-NOT: fir.fake_use
+// NO-FAKE-USE: return
+
#loc1 = loc("debug-fake-use.f90":1:1)
#loc3 = loc("debug-fake-use.f90":3:14)
#loc4 = loc("debug-fake-use.f90":4:14)
#loc5 = loc("debug-fake-use.f90":5:1)
#loc = loc("debug-fake-use.f90":0:0)
-module attributes {dlti.dl_spec = #dlti.dl_spec<i128 = dense<128> : vector<2xi64>, f80 = dense<128> : vector<2xi64>, i1 = dense<8> : vector<2xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i64 = dense<64> : vector<2xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i32 = dense<32> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, !llvm.ptr<270> = dense<32> : vector<4xi64>, i8 = dense<8> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, "dlti.stack_alignment" = 128 : i64, "dlti.mangling_mode" = "e", "dlti.endianness" = "little">, 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", llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+module {
func.func private @foo()
func.func @test_(%arg0: !fir.ref<i32> {fir.bindc_name = "expected"} loc("debug-fake-use.f90":1:1)) attributes {fir.internal_name = "_QPtest"} {
%0 = fir.undefined !fir.dscope loc(#loc1)
@@ -53,4 +78,18 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<i128 = dense<128> : vector<2xi64
fir.call @foo() : () -> ()
return loc(#loc5)
} loc(#loc1)
+
+ func.func @test_dynamic_array(%arg0: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"} loc("debug-fake-use.f90":1:1), %arg1: index loc("debug-fake-use.f90":1:1), %arg2: index loc("debug-fake-use.f90":1:1)) attributes {fir.internal_name = "_QPtest_dynamic_array"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0(%arg1) origin %arg2 dummy_scope %0 arg 1 {uniq_name = "_QFtest_dynamic_arrayEarr"} : (!fir.ref<!fir.array<?xi32>>, index, index, !fir.dscope) -> !fir.ref<!fir.array<?xi32>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ return loc(#loc5)
+ } loc(#loc1)
+
+ func.func @test_char_array(%arg0: !fir.ref<!fir.char<1,?>> {fir.bindc_name = "str"} loc("debug-fake-use.f90":1:1), %arg1: index {fir.bindc_name = "n"} loc("debug-fake-use.f90":1:1)) attributes {fir.internal_name = "_QPtest_char_array"} {
+ %0 = fir.undefined !fir.dscope loc(#loc1)
+ %1 = fircg.ext_declare %arg0 typeparams %arg1 dummy_scope %0 arg 1 {uniq_name = "_QFtest_char_arrayEstr"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> !fir.ref<!fir.char<1,?>> loc(#loc3)
+ fir.call @foo() : () -> ()
+ return loc(#loc5)
+ } loc(#loc1)
} loc(#loc)
More information about the flang-commits
mailing list