[flang-commits] [flang] 350d672 - [Flang] mark safe external globals as dso_local (#189709)
via flang-commits
flang-commits at lists.llvm.org
Wed Apr 8 09:13:26 PDT 2026
Author: Jason Van Beusekom
Date: 2026-04-08T11:13:21-05:00
New Revision: 350d672827deaff38e81a859522e5a3bfb584ed3
URL: https://github.com/llvm/llvm-project/commit/350d672827deaff38e81a859522e5a3bfb584ed3
DIFF: https://github.com/llvm/llvm-project/commit/350d672827deaff38e81a859522e5a3bfb584ed3.diff
LOG: [Flang] mark safe external globals as dso_local (#189709)
Globals inside a Fortran module are not marked as dso_local,
which results in their alignment not being promoted.
This fix mimics some of the functionality found in
shouldAssumeDSOLocal in /clang/lib/CIR/CodeGen/CIRGenModule.cpp
Fixes #189069
Added:
flang/test/Fir/dso-local-macho.fir
flang/test/Fir/dso-local.fir
Modified:
flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
flang/lib/Lower/Bridge.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
flang/test/Lower/common-block.f90
Removed:
################################################################################
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 63867fab57678..2642b08b7514c 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -7447,6 +7447,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 2d01463cf604d..5524d2ea08005 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3391,6 +3391,18 @@ 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.isInitialized();
+ 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..2dfc1e845b573 100644
--- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
@@ -197,6 +197,40 @@ 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)) {
+ auto val = attr.getInt();
+ if (val >= llvm::Reloc::Static && val <= llvm::Reloc::ROPI_RWPI)
+ return static_cast<llvm::Reloc::Model>(val);
+ }
+ // Default to PIC_ as the conservative choice, ie don't set globals as
+ // dso_local This also matches the default in CodeGenOptions.def.
+ 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>
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