[flang-commits] [flang] [flang][debug] Only import debug info for specified renamed variables (PR #194926)
via flang-commits
flang-commits at lists.llvm.org
Thu May 7 09:32:48 PDT 2026
https://github.com/timsmith78 updated https://github.com/llvm/llvm-project/pull/194926
>From 07623b498311cac4fc062c0a0da5f190bec26eb1 Mon Sep 17 00:00:00 2001
From: Timothy Smith <timothy.smith at hpe.com>
Date: Thu, 23 Apr 2026 11:58:41 -0500
Subject: [PATCH 1/4] Only import debug info for specified renamed variables
Given the following:
USE mod, ONLY : alias => var
Currently, flang will create a DW_TAG_imported_module tag for mod when
it should only be creating a list of DW_TAG_imported_declaration tags
for each imported variable. This causes erroneous variables from mod to be
visible in the debugger with undefined information.
Fixes #180836
---
flang/lib/Lower/PFTBuilder.cpp | 1 +
flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 8 ++++++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index afabb6b29f4f1..367b516bdcdac 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -253,6 +253,7 @@ class PFTBuilder {
std::string localName{
std::get<0>(names.t).source.ToString()};
stmt.renames.push_back(localName);
+ stmt.onlyNames.push_back(localName);
},
[&](const parser::Rename::Operators &) {
// Operator renames - not commonly needed for debug
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 65c8508de9c9f..167ce0c5f0acd 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -823,8 +823,12 @@ void AddDebugInfoPass::handleOnlyClause(
fir::UseStmtOp useOp, mlir::LLVM::DISubprogramAttr spAttr,
mlir::LLVM::DIFileAttr fileAttr, mlir::SymbolTable *symbolTable,
llvm::DenseSet<mlir::LLVM::DIImportedEntityAttr> &importedModules) {
+
+ auto onlySymbols = useOp.getOnlySymbols();
+ auto renames = useOp.getRenames();
+
// Process ONLY symbols (without renames)
- if (auto onlySymbols = useOp.getOnlySymbols()) {
+ if (onlySymbols && !renames) {
for (mlir::Attribute attr : *onlySymbols) {
auto symbolRef = mlir::cast<mlir::FlatSymbolRefAttr>(attr);
if (auto importedDecl = createImportedDeclForGlobal(
@@ -835,7 +839,7 @@ void AddDebugInfoPass::handleOnlyClause(
}
// Process renames within ONLY clause
- if (auto renames = useOp.getRenames()) {
+ if (renames) {
for (auto attr : *renames) {
auto renameAttr = mlir::cast<fir::UseRenameAttr>(attr);
if (auto importedDecl = createImportedDeclForGlobal(
>From 6943088b3f8b7a4fa1caaa2dc3953216f0786bc7 Mon Sep 17 00:00:00 2001
From: Timothy Smith <timothy.smith at hpe.com>
Date: Fri, 1 May 2026 15:01:26 -0500
Subject: [PATCH 2/4] Fix cases where USE, ONLY clause contains mix of renames
and non-renames
---
.../lib/Optimizer/Transforms/AddDebugInfo.cpp | 20 +++++++++++++++++--
flang/test/Integration/debug-use-stmt.f90 | 2 ++
flang/test/Lower/debug-use-stmt.f90 | 4 ++--
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 167ce0c5f0acd..09efc27f93368 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -828,10 +828,26 @@ void AddDebugInfoPass::handleOnlyClause(
auto renames = useOp.getRenames();
// Process ONLY symbols (without renames)
- if (onlySymbols && !renames) {
+ if (onlySymbols) {
for (mlir::Attribute attr : *onlySymbols) {
auto symbolRef = mlir::cast<mlir::FlatSymbolRefAttr>(attr);
- if (auto importedDecl = createImportedDeclForGlobal(
+
+ // Check if this symbol is also in renames, if so skip it
+ bool isInRenames = false;
+ if (renames) {
+ for (auto renameAttr : *renames) {
+ auto rename = mlir::cast<fir::UseRenameAttr>(renameAttr);
+ if (rename.getSymbol().getValue() == symbolRef.getValue()) {
+ isInRenames = true;
+ break;
+ }
+ }
+ }
+
+ if (isInRenames)
+ continue;
+
+ if (auto importedDecl = createImportedDeclForGlobal(
symbolRef.getValue(), spAttr, fileAttr, mlir::StringAttr(),
symbolTable))
importedModules.insert(*importedDecl);
diff --git a/flang/test/Integration/debug-use-stmt.f90 b/flang/test/Integration/debug-use-stmt.f90
index db20dd94e85d1..50a70da3941f8 100644
--- a/flang/test/Integration/debug-use-stmt.f90
+++ b/flang/test/Integration/debug-use-stmt.f90
@@ -26,6 +26,8 @@ program test_use
! CHECK-DAG: [[SP:![0-9]+]] = distinct !DISubprogram(name: "TEST_USE", linkageName: "_QQmain"{{.*}}retainedNodes:
+! Check that the full testmod module is not imported
+! CHECK-NOT: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[SP]], entity: [[TESTMOD]]
! Check testmod imports: var_b directly (no rename), var_d as rename of var_c
! CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[SP]], entity: [[VAR_B]],{{.*}}file:{{.*}}line:
! CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "var_d", scope: [[SP]], entity: [[VAR_C]],{{.*}}file:{{.*}}line:
diff --git a/flang/test/Lower/debug-use-stmt.f90 b/flang/test/Lower/debug-use-stmt.f90
index 293b38c78e17a..7404f7da932ea 100644
--- a/flang/test/Lower/debug-use-stmt.f90
+++ b/flang/test/Lower/debug-use-stmt.f90
@@ -73,8 +73,8 @@ subroutine test_only_rename()
! NO_DEBUG-NOT: fir.use_stmt
! WITH_DEBUG-LABEL: func.func @_QPtest_only_rename()
-! WITH_DEBUG-DAG: fir.use_stmt "mod1" only_symbols{{\[}}[@_QMmod1Ec]] renames{{\[}}[#fir.use_rename<"local_b", @_QMmod1Eb>, #fir.use_rename<"local_a", @_QMmod1Ea>]]
-! WITH_DEBUG-DAG: fir.use_stmt "mod2" renames{{\[}}[#fir.use_rename<"local_x", @_QMmod2Ex>, #fir.use_rename<"local_y", @_QMmod2Ey>]]
+! WITH_DEBUG-DAG: fir.use_stmt "mod1" only_symbols{{\[}}[@_QMmod1Eb, @_QMmod1Ec, @_QMmod1Ea]] renames{{\[}}[#fir.use_rename<"local_b", @_QMmod1Eb>, #fir.use_rename<"local_a", @_QMmod1Ea>]]
+! WITH_DEBUG-DAG: fir.use_stmt "mod2" only_symbols{{\[}}[@_QMmod2Ex, @_QMmod2Ey]] renames{{\[}}[#fir.use_rename<"local_x", @_QMmod2Ex>, #fir.use_rename<"local_y", @_QMmod2Ey>]]
! NO_DEBUG-LABEL: func.func @_QPtest_only_rename()
! NO_DEBUG-NOT: fir.use_stmt
>From abba9362c3ebca64be6a604d3179ef09e67040c6 Mon Sep 17 00:00:00 2001
From: Timothy Smith <timothy.smith at hpe.com>
Date: Fri, 1 May 2026 16:18:03 -0500
Subject: [PATCH 3/4] Fix formatting
---
flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 09efc27f93368..e0f572560932f 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -844,10 +844,10 @@ void AddDebugInfoPass::handleOnlyClause(
}
}
- if (isInRenames)
- continue;
+ if (isInRenames)
+ continue;
- if (auto importedDecl = createImportedDeclForGlobal(
+ if (auto importedDecl = createImportedDeclForGlobal(
symbolRef.getValue(), spAttr, fileAttr, mlir::StringAttr(),
symbolTable))
importedModules.insert(*importedDecl);
>From ba077b8caa13fd77b83807844eeaf445c56efe8b Mon Sep 17 00:00:00 2001
From: Timothy Smith <timothy.smith at hpe.com>
Date: Thu, 7 May 2026 11:31:01 -0500
Subject: [PATCH 4/4] Replace quadratic algorithm with more efficient
flag-based algorithm
---
flang/include/flang/Optimizer/Dialect/FIROps.td | 7 ++++++-
flang/include/flang/Semantics/scope.h | 1 +
flang/lib/Lower/Bridge.cpp | 4 +++-
flang/lib/Lower/PFTBuilder.cpp | 2 +-
flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 17 +----------------
flang/test/Lower/debug-use-stmt.f90 | 4 ++--
6 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 453379b010075..14dabbd123dd9 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -3314,12 +3314,14 @@ def fir_UseStmtOp
}];
let arguments = (ins StrAttr:$module_name,
- OptionalAttr<ArrayAttr>:$only_symbols, OptionalAttr<ArrayAttr>:$renames);
+ OptionalAttr<ArrayAttr>:$only_symbols, OptionalAttr<ArrayAttr>:$renames,
+ DefaultValuedAttr<BoolAttr, "false">:$hasOnlyWithRenames);
let assemblyFormat = [{
$module_name
(`only_symbols` `[` $only_symbols^ `]`)?
(`renames` `[` $renames^ `]`)?
+ (`hasOnlyWithRenames` $hasOnlyWithRenames^)?
attr-dict
}];
@@ -3332,6 +3334,9 @@ def fir_UseStmtOp
/// Returns true if this imports the entire module (no ONLY clause)
bool importsAll() { return !hasOnlyClause(); }
+
+ /// Returns true if this USE statement has both ONLY clause and renames
+ bool hasOnlyWithRenames() { return getHasOnlyWithRenames(); }
}];
}
diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h
index 16553fe692e79..7cab6e2122319 100644
--- a/flang/include/flang/Semantics/scope.h
+++ b/flang/include/flang/Semantics/scope.h
@@ -60,6 +60,7 @@ struct PreservedUseStmt {
std::string moduleName;
std::vector<std::string> onlyNames; // For USE ONLY
std::vector<std::string> renames; // local_name (resolved via GetUltimate)
+ bool hasOnlyWithRenames{false}; // true if there are renames in an ONLY clause
PreservedUseStmt(std::string modName) : moduleName(std::move(modName)) {}
};
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index cf9da627c19f1..36b9842c831a8 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -283,9 +283,11 @@ static void emitUseStmtOp(Fortran::lower::AbstractConverter &converter,
mlir::ArrayAttr renamesAttr =
renameAttrs.empty() ? mlir::ArrayAttr()
: mlir::ArrayAttr::get(context, renameAttrs);
+ mlir::BoolAttr hasOnlyWithRenamesAttr =
+ mlir::BoolAttr::get(context, stmt.hasOnlyWithRenames);
fir::UseStmtOp::create(builder, loc, moduleNameAttr, onlySymbolsAttr,
- renamesAttr);
+ renamesAttr, hasOnlyWithRenamesAttr);
}
/// Emit fir.module_debug_imports for USE statements in a module.
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 367b516bdcdac..a7cf64ccb583b 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -253,7 +253,7 @@ class PFTBuilder {
std::string localName{
std::get<0>(names.t).source.ToString()};
stmt.renames.push_back(localName);
- stmt.onlyNames.push_back(localName);
+ stmt.hasOnlyWithRenames = true;
},
[&](const parser::Rename::Operators &) {
// Operator renames - not commonly needed for debug
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index e0f572560932f..ceb79dc110d0a 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -832,21 +832,6 @@ void AddDebugInfoPass::handleOnlyClause(
for (mlir::Attribute attr : *onlySymbols) {
auto symbolRef = mlir::cast<mlir::FlatSymbolRefAttr>(attr);
- // Check if this symbol is also in renames, if so skip it
- bool isInRenames = false;
- if (renames) {
- for (auto renameAttr : *renames) {
- auto rename = mlir::cast<fir::UseRenameAttr>(renameAttr);
- if (rename.getSymbol().getValue() == symbolRef.getValue()) {
- isInRenames = true;
- break;
- }
- }
- }
-
- if (isInRenames)
- continue;
-
if (auto importedDecl = createImportedDeclForGlobal(
symbolRef.getValue(), spAttr, fileAttr, mlir::StringAttr(),
symbolTable))
@@ -928,7 +913,7 @@ void AddDebugInfoPass::expandUseStmtForDebug(
/*decl=*/true);
llvm::DenseSet<mlir::LLVM::DIImportedEntityAttr> importedModules;
- if (useOp.hasOnlyClause())
+ if (useOp.hasOnlyClause() || useOp.getHasOnlyWithRenames())
handleOnlyClause(useOp, spAttr, fileAttr, symbolTable, importedModules);
else if (useOp.hasRenames())
handleRenamesWithoutOnly(useOp, spAttr, modAttr, fileAttr, symbolTable,
diff --git a/flang/test/Lower/debug-use-stmt.f90 b/flang/test/Lower/debug-use-stmt.f90
index 7404f7da932ea..9701d938b5f0b 100644
--- a/flang/test/Lower/debug-use-stmt.f90
+++ b/flang/test/Lower/debug-use-stmt.f90
@@ -73,8 +73,8 @@ subroutine test_only_rename()
! NO_DEBUG-NOT: fir.use_stmt
! WITH_DEBUG-LABEL: func.func @_QPtest_only_rename()
-! WITH_DEBUG-DAG: fir.use_stmt "mod1" only_symbols{{\[}}[@_QMmod1Eb, @_QMmod1Ec, @_QMmod1Ea]] renames{{\[}}[#fir.use_rename<"local_b", @_QMmod1Eb>, #fir.use_rename<"local_a", @_QMmod1Ea>]]
-! WITH_DEBUG-DAG: fir.use_stmt "mod2" only_symbols{{\[}}[@_QMmod2Ex, @_QMmod2Ey]] renames{{\[}}[#fir.use_rename<"local_x", @_QMmod2Ex>, #fir.use_rename<"local_y", @_QMmod2Ey>]]
+! WITH_DEBUG-DAG: fir.use_stmt "mod1" only_symbols{{\[}}[@_QMmod1Ec]] renames{{\[}}[#fir.use_rename<"local_b", @_QMmod1Eb>, #fir.use_rename<"local_a", @_QMmod1Ea>]] hasOnlyWithRenames true
+! WITH_DEBUG-DAG: fir.use_stmt "mod2" renames{{\[}}[#fir.use_rename<"local_x", @_QMmod2Ex>, #fir.use_rename<"local_y", @_QMmod2Ey>]] hasOnlyWithRenames true
! NO_DEBUG-LABEL: func.func @_QPtest_only_rename()
! NO_DEBUG-NOT: fir.use_stmt
More information about the flang-commits
mailing list