[flang-commits] [flang] [Flang] mark safe external globals as dso_local (PR #189709)
Jason Van Beusekom via flang-commits
flang-commits at lists.llvm.org
Tue Mar 31 13:48:50 PDT 2026
https://github.com/Jason-Van-Beusekom updated https://github.com/llvm/llvm-project/pull/189709
>From 1507a035a3306ad2d0bbb3d961b1c7ee3c0ac1e8 Mon Sep 17 00:00:00 2001
From: Jason Van Beusekom <jason.van-beusekom at hpe.com>
Date: Tue, 31 Mar 2026 11:16:16 -0500
Subject: [PATCH 1/3] [Flang] mark safe external globals as dso_local
---
.../Optimizer/Dialect/Support/FIRContext.h | 13 +++
flang/lib/Lower/Bridge.cpp | 2 +
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 13 +++
.../Optimizer/Dialect/Support/FIRContext.cpp | 29 +++++++
flang/test/Fir/dso-local-macho.fir | 17 ++++
flang/test/Fir/dso-local.fir | 84 +++++++++++++++++++
6 files changed, 158 insertions(+)
create mode 100644 flang/test/Fir/dso-local-macho.fir
create mode 100644 flang/test/Fir/dso-local.fir
diff --git a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
index c0c0b744206cd..3fea111941551 100644
--- a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
+++ b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
@@ -19,6 +19,7 @@
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/TargetParser/Triple.h"
namespace mlir {
@@ -102,6 +103,18 @@ void setCommandline(mlir::ModuleOp mod, llvm::StringRef cmdLine);
/// Get the command line used in this invocation.
llvm::StringRef getCommandline(mlir::ModuleOp mod);
+/// Set the relocation model for the module.
+void setRelocationModel(mlir::ModuleOp mod, llvm::Reloc::Model rm);
+
+/// Get the relocation model from the Module (defaults to PIC).
+llvm::Reloc::Model getRelocationModel(mlir::ModuleOp mod);
+
+/// Set whether the module is compiled as a position-independent executable.
+void setIsPIE(mlir::ModuleOp mod, bool value);
+
+/// Get whether the module is compiled as a position-independent executable.
+bool getIsPIE(mlir::ModuleOp mod);
+
/// Helper for determining the target from the host, etc. Tools may use this
/// function to provide a consistent interpretation of the `--target=<string>`
/// command-line option.
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 7459f814a0d4d..0f2049d41efee 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -7411,6 +7411,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
fir::setIdent(*module, Fortran::common::getFlangFullVersion());
+ fir::setRelocationModel(*module, cgOpts.getRelocationModel());
+ fir::setIsPIE(*module, cgOpts.IsPIE);
if (cgOpts.RecordCommandLine)
fir::setCommandline(*module, *cgOpts.RecordCommandLine);
}
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 25eb6194efa99..849662f9ae35a 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3391,6 +3391,19 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
g.setAlignment(*global.getAlignment());
auto module = global->getParentOfType<mlir::ModuleOp>();
+
+ // Mimic shouldAssumeDSOLocal in clang, marking external definitions as dso_local if
+ // it is defined and is ELF, and either static or PIE.
+ bool isDefinition =
+ !global.getRegion().empty() || global.getInitVal().has_value();
+ if (isDefinition && linkage == mlir::LLVM::Linkage::External &&
+ fir::getTargetTriple(module).isOSBinFormatELF()) {
+ llvm::Reloc::Model rm = fir::getRelocationModel(module);
+ bool isPIE = fir::getIsPIE(module);
+ if (rm == llvm::Reloc::Static || isPIE)
+ g.setDsoLocal(true);
+ }
+
auto gpuMod = global->getParentOfType<mlir::gpu::GPUModuleOp>();
// Add comdat if necessary
if (fir::getTargetTriple(module).supportsCOMDAT() &&
diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
index c2e0afe122b4e..63170dd03f3db 100644
--- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
@@ -197,6 +197,35 @@ llvm::StringRef fir::getCommandline(mlir::ModuleOp mod) {
return {};
}
+static constexpr const char *relocationModelName = "fir.relocation_model";
+
+void fir::setRelocationModel(mlir::ModuleOp mod, llvm::Reloc::Model rm) {
+ auto *ctx = mod.getContext();
+ mod->setAttr(relocationModelName,
+ mlir::IntegerAttr::get(mlir::IntegerType::get(ctx, 32),
+ static_cast<unsigned>(rm)));
+}
+
+llvm::Reloc::Model fir::getRelocationModel(mlir::ModuleOp mod) {
+ if (auto attr = mod->getAttrOfType<mlir::IntegerAttr>(relocationModelName))
+ return static_cast<llvm::Reloc::Model>(attr.getInt());
+ return llvm::Reloc::PIC_;
+}
+
+static constexpr const char *isPIEName = "fir.is_pie";
+
+void fir::setIsPIE(mlir::ModuleOp mod, bool value) {
+ if (value) {
+ auto *ctx = mod.getContext();
+ mod->setAttr(isPIEName, mlir::UnitAttr::get(ctx));
+ } else {
+ if (mod->hasAttr(isPIEName))
+ mod->removeAttr(isPIEName);
+ }
+}
+
+bool fir::getIsPIE(mlir::ModuleOp mod) { return mod->hasAttr(isPIEName); }
+
std::string fir::determineTargetTriple(llvm::StringRef triple) {
// Treat "" or "default" as stand-ins for the default machine.
if (triple.empty() || triple == "default")
diff --git a/flang/test/Fir/dso-local-macho.fir b/flang/test/Fir/dso-local-macho.fir
new file mode 100644
index 0000000000000..d34f9fb6f5f67
--- /dev/null
+++ b/flang/test/Fir/dso-local-macho.fir
@@ -0,0 +1,17 @@
+// Test that dso_local is not set on non-ELF targets, even with static
+// relocation model. Uses a separate file because fir-to-llvm-ir target=
+// overrides the module triple for all splits.
+
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-apple-darwin" %s | FileCheck %s
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 0 : i32,
+ llvm.target_triple = "x86_64-apple-darwin"} {
+ fir.global @macho_def : i32 {
+ %0 = fir.zero_bits i32
+ fir.has_value %0 : i32
+ }
+}
+// CHECK: llvm.mlir.global external @macho_def()
+// CHECK-NOT: dso_local
+// CHECK-SAME: : i32
diff --git a/flang/test/Fir/dso-local.fir b/flang/test/Fir/dso-local.fir
new file mode 100644
index 0000000000000..ab3566184403f
--- /dev/null
+++ b/flang/test/Fir/dso-local.fir
@@ -0,0 +1,84 @@
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
+
+// Static relocation model, ELF, external definition: dso_local
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 0 : i32,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global @static_def : i32 {
+ %0 = fir.zero_bits i32
+ fir.has_value %0 : i32
+ }
+}
+// CHECK: llvm.mlir.global external @static_def()
+// CHECK-SAME: dso_local
+
+// -----
+
+// PIC + PIE, ELF, external definition: dso_local
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 1 : i32, fir.is_pie,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global @pie_def : i32 {
+ %0 = fir.zero_bits i32
+ fir.has_value %0 : i32
+ }
+}
+// CHECK: llvm.mlir.global external @pie_def()
+// CHECK-SAME: dso_local
+
+// -----
+
+// PIC without PIE, ELF, external definition: no dso_local
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 1 : i32,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global @pic_def : i32 {
+ %0 = fir.zero_bits i32
+ fir.has_value %0 : i32
+ }
+}
+// CHECK: llvm.mlir.global external @pic_def()
+// CHECK-NOT: dso_local
+// CHECK-SAME: : i32
+
+// -----
+
+// Static relocation model, ELF, declaration only: no dso_local
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 0 : i32,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global @decl_only : i32
+}
+// CHECK: llvm.mlir.global external @decl_only()
+// CHECK-NOT: dso_local
+// CHECK-SAME: : i32
+
+// -----
+
+// Static relocation model, ELF, internal linkage: no dso_local from this path
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 0 : i32,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global internal @internal_var : i32 {
+ %0 = fir.zero_bits i32
+ fir.has_value %0 : i32
+ }
+}
+// CHECK: llvm.mlir.global internal @internal_var()
+// CHECK-NOT: dso_local
+// CHECK-SAME: : i32
+
+// -----
+
+// Static relocation model, ELF, linkonce: no dso_local from this path
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "",
+ fir.relocation_model = 0 : i32,
+ llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+ fir.global linkonce @linkonce_str constant : !fir.char<1,5> {
+ %0 = fir.string_lit "hello"(5) : !fir.char<1,5>
+ fir.has_value %0 : !fir.char<1,5>
+ }
+}
+// CHECK: llvm.mlir.global linkonce constant @linkonce_str()
+// CHECK-NOT: dso_local
+// CHECK-SAME: : !llvm.array<5 x i8>
>From 3fdde968c368107fdd5eb0138e97863125e377f5 Mon Sep 17 00:00:00 2001
From: Jason Van Beusekom <jason.van-beusekom at hpe.com>
Date: Tue, 31 Mar 2026 12:14:00 -0500
Subject: [PATCH 2/3] format
---
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 849662f9ae35a..d76fac8fbbb5b 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3392,8 +3392,8 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
auto module = global->getParentOfType<mlir::ModuleOp>();
- // Mimic shouldAssumeDSOLocal in clang, marking external definitions as dso_local if
- // it is defined and is ELF, and either static or PIE.
+ // Mimic shouldAssumeDSOLocal in clang, marking external definitions as
+ // dso_local if it is defined and is ELF, and either static or PIE.
bool isDefinition =
!global.getRegion().empty() || global.getInitVal().has_value();
if (isDefinition && linkage == mlir::LLVM::Linkage::External &&
>From 59648fec3b3f131ded1f064faccbfd8ae8fd3085 Mon Sep 17 00:00:00 2001
From: Jason-Van-Beusekom <jason.van-beusekom at hpe.com>
Date: Tue, 31 Mar 2026 15:46:33 -0500
Subject: [PATCH 3/3] update on feedback
---
flang/lib/Optimizer/Dialect/Support/FIRContext.cpp | 7 +++++--
flang/test/Lower/common-block.f90 | 4 ++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
index 63170dd03f3db..6b47d7c1a0d66 100644
--- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
@@ -207,8 +207,11 @@ void fir::setRelocationModel(mlir::ModuleOp mod, llvm::Reloc::Model rm) {
}
llvm::Reloc::Model fir::getRelocationModel(mlir::ModuleOp mod) {
- if (auto attr = mod->getAttrOfType<mlir::IntegerAttr>(relocationModelName))
- return static_cast<llvm::Reloc::Model>(attr.getInt());
+ if (auto attr = mod->getAttrOfType<mlir::IntegerAttr>(relocationModelName)) {
+ auto val = attr.getInt();
+ if (val >= llvm::Reloc::Static && val <= llvm::Reloc::ROPI_RWPI)
+ return static_cast<llvm::Reloc::Model>(val);
+ }
return llvm::Reloc::PIC_;
}
diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90
index 5e32c119bcf21..45810d3d00e29 100644
--- a/flang/test/Lower/common-block.f90
+++ b/flang/test/Lower/common-block.f90
@@ -6,9 +6,9 @@
! CHECK: @co1_ = common global [16 x i8] zeroinitializer, align 16
! CHECK: @rien_ = common global [1 x i8] zeroinitializer
! CHECK: @with_empty_equiv_ = common global [8 x i8] zeroinitializer
-! CHECK: @x_ = global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} }
+! CHECK: @x_ = {{(dso_local )?}}global { float, float } { float 1.0{{.*}}, float 2.0{{.*}} }
! CHECK: @y_ = common global [12 x i8] zeroinitializer
-! CHECK: @z_ = global { i32, [4 x i8], float } { i32 42, [4 x i8] zeroinitializer, float 3.000000e+00 }
+! CHECK: @z_ = {{(dso_local )?}}global { i32, [4 x i8], float } { i32 42, [4 x i8] zeroinitializer, float 3.000000e+00 }
! CHECK-LABEL: _QPs0
subroutine s0
More information about the flang-commits
mailing list