[flang-commits] [clang] [flang] [mlir] [Flang][Driver] Added support for -funique-internal-linkage-names option (PR #216680)
Kaviya Rajendiran via flang-commits
flang-commits at lists.llvm.org
Fri Aug 28 03:47:19 PDT 2026
https://github.com/kaviya2510 updated https://github.com/llvm/llvm-project/pull/216680
>From f1cc2d4c9b37d05ef41bd4f49d33ef1b06e1dafe Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Mon, 17 Aug 2026 15:31:44 +0530
Subject: [PATCH 1/3] [Flang][Driver] Added support for
-funique-internal-linkage-names
---
clang/include/clang/Options/Options.td | 4 +--
clang/lib/Driver/ToolChains/Flang.cpp | 3 +++
.../include/flang/Frontend/CodeGenOptions.def | 1 +
flang/include/flang/Lower/Bridge.h | 4 +++
.../flang/Optimizer/Transforms/Passes.td | 4 +++
flang/include/flang/Tools/CrossToolHelpers.h | 3 +++
flang/lib/Frontend/CompilerInvocation.cpp | 5 ++++
flang/lib/Lower/Bridge.cpp | 15 ++++++++++-
flang/lib/Optimizer/Passes/Pipelines.cpp | 1 +
.../lib/Optimizer/Transforms/FunctionAttr.cpp | 7 +++++
.../Driver/funique-internal-linkage-names.f90 | 20 ++++++++++++++
.../unique-internal-linkage-names.f90 | 22 ++++++++++++++++
...on-attrs-unique-internal-linkage-names.fir | 26 +++++++++++++++++++
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 3 ++-
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 7 +++++
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 5 ++++
.../sample-profile-suffix-elision-policy.ll | 15 +++++++++++
.../sample-profile-suffix-elision-policy.mlir | 7 +++++
18 files changed, 148 insertions(+), 4 deletions(-)
create mode 100644 flang/test/Driver/funique-internal-linkage-names.f90
create mode 100644 flang/test/Integration/unique-internal-linkage-names.f90
create mode 100644 flang/test/Transforms/function-attrs-unique-internal-linkage-names.fir
create mode 100644 mlir/test/Target/LLVMIR/Import/sample-profile-suffix-elision-policy.ll
create mode 100644 mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index eb5a009b5628c..b617604e29d9b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5054,10 +5054,10 @@ defm unique_basic_block_section_names : BoolFOption<"unique-basic-block-section-
NegFlag<SetFalse>>;
defm unique_internal_linkage_names : BoolFOption<"unique-internal-linkage-names",
CodeGenOpts<"UniqueInternalLinkageNames">, DefaultFalse,
- PosFlag<SetTrue, [], [ClangOption, CC1Option],
+ PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option],
"Uniqueify Internal Linkage Symbol Names by appending"
" the MD5 hash of the module path">,
- NegFlag<SetFalse>>;
+ NegFlag<SetFalse, [], [ClangOption, CC1Option, FlangOption, FC1Option]>>;
defm unique_section_names : BoolFOption<"unique-section-names",
CodeGenOpts<"UniqueSectionNames">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option],
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index ccd99b5e0892c..13bd618cf3d8d 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -349,6 +349,9 @@ void Flang::addCodegenOptions(const ArgList &Args,
options::OPT_fno_experimental_loop_fusion);
Args.AddLastArg(CmdArgs, options::OPT_ffp_sum_reassociation,
options::OPT_fno_fp_sum_reassociation);
+
+ Args.addOptInFlag(CmdArgs, options::OPT_funique_internal_linkage_names,
+ options::OPT_fno_unique_internal_linkage_names);
handleInterchangeLoopsArgs(Args, CmdArgs);
handleVectorizeLoopsArgs(Args, CmdArgs);
diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def
index d49a7f3647eec..0726b71a71dff 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.def
+++ b/flang/include/flang/Frontend/CodeGenOptions.def
@@ -60,6 +60,7 @@ CODEGENOPT(AliasAnalysis, 1, 0) ///< Enable alias analysis pass
CODEGENOPT(DwarfVersion, 3, 0) ///< Dwarf version
CODEGENOPT(DebugInfoForProfiling, 1, 0) ///< Emit extra debug info to make sample profile more accurate.
CODEGENOPT(PseudoProbeForProfiling, 1, 0) ///< Emit pseudo probes for sample profiling.
+CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Append MD5 hash to internal linkage symbols.
CODEGENOPT(Underscoring, 1, 1)
ENUM_CODEGENOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, Fortran::common::FPMaxminBehavior::Legacy)
diff --git a/flang/include/flang/Lower/Bridge.h b/flang/include/flang/Lower/Bridge.h
index dbddef7b1169d..f8421f27e6ec2 100644
--- a/flang/include/flang/Lower/Bridge.h
+++ b/flang/include/flang/Lower/Bridge.h
@@ -24,6 +24,7 @@
#include "flang/Support/Fortran.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"
+#include "llvm/ProfileData/SampleProf.h"
#include <set>
namespace llvm {
@@ -118,6 +119,8 @@ class LoweringBridge {
return languageFeatures;
}
+ const std::string &getModuleNameHash() const { return moduleNameHash; }
+
/// Create a folding context. Careful: this is very expensive.
Fortran::evaluate::FoldingContext createFoldingContext();
@@ -180,6 +183,7 @@ class LoweringBridge {
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults;
const Fortran::common::LanguageFeatureControl &languageFeatures;
std::set<std::string> tempNames;
+ std::string moduleNameHash;
std::optional<mlir::DiagnosticEngine::HandlerID> diagHandlerID;
};
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index ef18cb33d4b8a..ffc0062c6f63d 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -519,6 +519,10 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> {
/*default=*/"false",
"Set the use-sample-profile attribute on functions in the "
"module.">,
+ Option<"UniqueInternalLinkageNames", "unique-internal-linkage-names",
+ "bool", /*default=*/"false",
+ "Set the sample-profile-suffix-elision-policy attribute on "
+ "internal linkage functions in the module.">,
Option<"tuneCPU", "tune-cpu", "std::string", /*default=*/"",
"Set the tune-cpu attribute on functions in the module.">,
Option<"setNoCapture", "set-nocapture", "bool", /*default=*/"false",
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index 6569d34e0f255..0e1681a078bdf 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -138,6 +138,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
Reciprocals = opts.Reciprocals;
PreferVectorWidth = opts.PreferVectorWidth;
UseSampleProfile = !opts.SampleProfileFile.empty();
+ UniqueInternalLinkageNames = opts.UniqueInternalLinkageNames;
DebugInfoForProfiling = opts.DebugInfoForProfiling;
if (opts.InstrumentFunctions) {
InstrumentFunctionEntry = "__cyg_profile_func_enter";
@@ -176,6 +177,8 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
bool EnableOpenMPIsTargetDevice =
false; ///< Compiling for an OpenMP target device.
bool UseSampleProfile = false; ///< Enable sample based profiling
+ bool UniqueInternalLinkageNames = false; ///< Append MD5 hash suffix to
+ ///< internal linkage symbol names.
bool DebugInfoForProfiling = false; ///< Enable extra debugging info
bool EnableOpenMPSimd = false; ///< Enable OpenMP simd-only mode.
bool SkipConvertComplexPow = false; ///< Do not run complex pow conversion.
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 87a25f3101ddd..b80a306cce625 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -317,6 +317,11 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
clang::options::OPT_fno_safe_trampoline, false))
opts.EnableSafeTrampoline = 1;
+ if (args.hasFlag(clang::options::OPT_funique_internal_linkage_names,
+ clang::options::OPT_fno_unique_internal_linkage_names,
+ false))
+ opts.UniqueInternalLinkageNames = 1;
+
if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
clang::options::OPT_fno_fp_sum_reassociation, false))
opts.SplitSumExpressionTree = 1;
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index c6c230af7cf58..7dfe305637cc7 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -1220,9 +1220,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
}
std::string
mangleName(const Fortran::semantics::Symbol &symbol) override final {
- return Fortran::lower::mangle::mangleName(
+ std::string mangledName = Fortran::lower::mangle::mangleName(
symbol, scopeBlockIdMap, /*keepExternalInScope=*/false,
getLoweringOptions().getUnderscoring());
+ const auto &hash = bridge.getModuleNameHash();
+ if (!hash.empty() &&
+ Fortran::semantics::ClassifyProcedure(symbol) ==
+ Fortran::semantics::ProcedureDefinitionClass::Internal)
+ mangledName += hash;
+ return mangledName;
}
std::string mangleName(
const Fortran::semantics::DerivedTypeSpec &derivedType) override final {
@@ -6937,6 +6943,13 @@ Fortran::lower::LoweringBridge::LoweringBridge(
else if (languageFeatures.IsEnabled(
Fortran::common::LanguageFeature::CudaManaged))
fir::setCudaHeapAllocMode(*module, fir::CudaHeapAllocMode::Managed);
+
+ if (cgOpts.UniqueInternalLinkageNames) {
+ if (auto fileLoc = mlir::dyn_cast<mlir::FileLineColLoc>(module->getLoc())) {
+ moduleNameHash =
+ llvm::getUniqueInternalLinkagePostfix(fileLoc.getFilename());
+ }
+ }
}
Fortran::lower::LoweringBridge::~LoweringBridge() {
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index ad59f824611d2..988dfa6ea7eef 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -453,6 +453,7 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
config.InstrumentFunctionExit, config.NoInfsFPMath, config.NoNaNsFPMath,
config.ApproxFuncFPMath, config.NoSignedZerosFPMath, config.UnsafeFPMath,
config.Reciprocals, config.PreferVectorWidth, config.UseSampleProfile,
+ config.UniqueInternalLinkageNames,
/*tuneCPU=*/"", setNoCapture, setNoAlias, setReadOnly}));
if (config.EnableOpenMP) {
diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
index 45b32d13ad62e..44acf6e3ef7ae 100644
--- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
+++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
@@ -144,6 +144,13 @@ void FunctionAttrPass::runOnOperation() {
context, mlir::LLVM::LLVMFuncOp::getUseSampleProfileAttrName(
llvmFuncOpName)),
mlir::BoolAttr::get(context, true));
+ if (UniqueInternalLinkageNames && fir::isInternalProcedure(func))
+ func->setAttr(
+ getLlvmFuncPropertyAttrName(
+ context,
+ mlir::LLVM::LLVMFuncOp::getSampleProfileSuffixElisionPolicyAttrName(
+ llvmFuncOpName)),
+ mlir::StringAttr::get(context, "selected"));
LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n");
}
diff --git a/flang/test/Driver/funique-internal-linkage-names.f90 b/flang/test/Driver/funique-internal-linkage-names.f90
new file mode 100644
index 0000000000000..88cafb520a019
--- /dev/null
+++ b/flang/test/Driver/funique-internal-linkage-names.f90
@@ -0,0 +1,20 @@
+! Test that -funique-internal-linkage-names / -fno-unique-internal-linkage-names are forwarded to flang -fc1.
+
+! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
+! RUN: %flang -### -funique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=ENABLED
+! RUN: %flang -### -fno-unique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=DISABLED
+! RUN: %flang -### -funique-internal-linkage-names -fno-unique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=DISABLED
+! RUN: %flang -### -fno-unique-internal-linkage-names -funique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=ENABLED
+
+! DEFAULT-NOT: "-funique-internal-linkage-names"
+! DEFAULT-NOT: "-fno-unique-internal-linkage-names"
+
+! ENABLED: "-fc1"{{.*}}"-funique-internal-linkage-names"
+! DISABLED-NOT: "-funique-internal-linkage-names"
+
+subroutine host()
+ call inner()
+contains
+ subroutine inner()
+ end subroutine
+end subroutine
diff --git a/flang/test/Integration/unique-internal-linkage-names.f90 b/flang/test/Integration/unique-internal-linkage-names.f90
new file mode 100644
index 0000000000000..c96e854b8eae4
--- /dev/null
+++ b/flang/test/Integration/unique-internal-linkage-names.f90
@@ -0,0 +1,22 @@
+! Test that -funique-internal-linkage-names appends a hash suffix to internal
+! procedures and sets the "sample-profile-suffix-elision-policy" attribute.
+
+! RUN: %flang_fc1 -emit-llvm -funique-internal-linkage-names -o - %s | FileCheck %s
+
+! CHECK-LABEL: define void @test_(
+! CHECK : call void @_QFtestPfooX__uniqX{{[0-9]+}}(ptr {{.*}})
+
+! CHECK-LABEL: define internal void @_QFtestPfooX__uniqX{{[0-9]+}}(ptr {{.*}}) #0
+! CHECK-NOT : define internal void @_QFtestPfoo(
+
+! CHECK: attributes #0 = { "sample-profile-suffix-elision-policy"="selected" }
+
+subroutine test(x)
+ integer, intent(inout) :: x
+ call foo(x)
+contains
+ subroutine foo(y)
+ integer, intent(inout) :: y
+ y = y + 1
+ end subroutine
+end subroutine
diff --git a/flang/test/Transforms/function-attrs-unique-internal-linkage-names.fir b/flang/test/Transforms/function-attrs-unique-internal-linkage-names.fir
new file mode 100644
index 0000000000000..9d5cf40ea6e35
--- /dev/null
+++ b/flang/test/Transforms/function-attrs-unique-internal-linkage-names.fir
@@ -0,0 +1,26 @@
+// RUN: fir-opt --function-attr="unique-internal-linkage-names=true" %s | FileCheck %s --check-prefix=ENABLED
+// RUN: fir-opt --function-attr="unique-internal-linkage-names=false" %s | FileCheck %s --check-prefix=DISABLED
+
+// Internal procedure: has fir.host_symbol, should get the attribute.
+// ENABLED-LABEL: func.func @_QFhost_subPinner(
+// ENABLED-SAME: llvm.sample_profile_suffix_elision_policy = "selected"
+
+// DISABLED-LABEL: func.func @_QFhost_subPinner(
+// DISABLED-NOT: sample_profile_suffix_elision_policy
+func.func @_QFhost_subPinner(%arg0: !fir.ref<i32>) attributes {fir.host_symbol = @_QFhost_sub} {
+ return
+}
+
+// Host procedure: no fir.host_symbol, should NOT get the attribute.
+// ENABLED-LABEL: func.func @_QFhost_sub(
+// ENABLED-NOT: sample_profile_suffix_elision_policy
+func.func @_QFhost_sub(%arg0: !fir.ref<i32>) {
+ return
+}
+
+// External procedure: should NOT get the attribute.
+// ENABLED-LABEL: func.func @_QPexternal_sub(
+// ENABLED-NOT: sample_profile_suffix_elision_policy
+func.func @_QPexternal_sub(%arg0: !fir.ref<i32>) {
+ return
+}
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index d5373d4bc6186..c8b39b596e95e 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2120,7 +2120,8 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
OptionalAttr<I32Attr>:$intel_reqd_sub_group_size,
OptionalAttr<LLVM_FunctionMetadataArrayAttr>:$function_metadata,
OptionalAttr<UWTableKindAttr>:$uwtable_kind,
- OptionalAttr<BoolAttr>:$use_sample_profile
+ OptionalAttr<BoolAttr>:$use_sample_profile,
+ OptionalAttr<StrAttr>:$sample_profile_suffix_elision_policy
);
let regions = (region AnyRegion:$body);
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 02cdb6088b6ac..8a74012d25597 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2858,6 +2858,7 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
StringLiteral("save-reg-params"),
StringLiteral("target-features"),
StringLiteral("trap-func-name"),
+ StringLiteral("sample-profile-suffix-elision-policy"),
StringLiteral("tune-cpu"),
StringLiteral("uwtable"),
StringLiteral("vscale_range"),
@@ -3022,6 +3023,12 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func,
if (func->hasFnAttribute("use-sample-profile"))
funcOp.setUseSampleProfile(true);
+ if (llvm::Attribute attr =
+ func->getFnAttribute("sample-profile-suffix-elision-policy");
+ attr.isStringAttribute())
+ funcOp.setSampleProfileSuffixElisionPolicy(
+ StringAttr::get(context, attr.getValueAsString()));
+
if (llvm::Attribute attr = func->getFnAttribute("target-cpu");
attr.isStringAttribute())
funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 5bb42575a0955..c74a54d017a3f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1736,6 +1736,11 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
if (func.getUseSampleProfile())
llvmFunc->addFnAttr("use-sample-profile");
+ if (auto sampleProfileSuffixElisionPolicy =
+ func.getSampleProfileSuffixElisionPolicy())
+ llvmFunc->addFnAttr("sample-profile-suffix-elision-policy",
+ *sampleProfileSuffixElisionPolicy);
+
if (auto attr = func.getVscaleRange())
llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
getLLVMContext(), attr->getMinRange().getInt(),
diff --git a/mlir/test/Target/LLVMIR/Import/sample-profile-suffix-elision-policy.ll b/mlir/test/Target/LLVMIR/Import/sample-profile-suffix-elision-policy.ll
new file mode 100644
index 0000000000000..8f9a59fea827c
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/sample-profile-suffix-elision-policy.ll
@@ -0,0 +1,15 @@
+; RUN: mlir-translate -import-llvm %s | FileCheck %s
+
+; CHECK-LABEL: llvm.func @with_elision_policy()
+; CHECK-SAME: sample_profile_suffix_elision_policy = "selected"
+define void @with_elision_policy() #0 {
+ ret void
+}
+
+; CHECK-LABEL: llvm.func @without_elision_policy()
+; CHECK-NOT: sample_profile_suffix_elision_policy
+define void @without_elision_policy() {
+ ret void
+}
+
+attributes #0 = { "sample-profile-suffix-elision-policy"="selected" }
diff --git a/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir b/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
new file mode 100644
index 0000000000000..4882a886d4558
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
@@ -0,0 +1,7 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK: define void @with_elision_policy() #[[ATTRS:.*]] {
+// CHECK: attributes #[[ATTRS]] = { "sample-profile-suffix-elision-policy"="selected" }
+llvm.func @with_elision_policy() attributes {sample_profile_suffix_elision_policy = "selected"} {
+ llvm.return
+}
>From 6e913e95cea625a89d00707f1deae17abf672548 Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Thu, 20 Aug 2026 00:56:31 +0530
Subject: [PATCH 2/3] [Flang] Preserve .__uniq. suffix in
CompilerGeneratedNamesConversion pass and added new testcases
---
clang/include/clang/Options/Options.td | 2 +-
clang/lib/Driver/ToolChains/Flang.cpp | 4 +--
flang/lib/Frontend/CompilerInvocation.cpp | 8 +++---
.../Transforms/CompilerGeneratedNames.cpp | 2 ++
.../Driver/funique-internal-linkage-names.f90 | 17 +++++-------
.../unique-internal-linkage-names.f90 | 22 ----------------
.../Lower/unique-internal-linkage-names.f90 | 20 ++++++++++++++
...ion-attr-unique-internal-linkage-names.fir | 26 +++++++++++++++++++
.../LLVMIR/unique-internal-linkage-names.mlir | 20 ++++++++++++++
9 files changed, 80 insertions(+), 41 deletions(-)
delete mode 100644 flang/test/Integration/unique-internal-linkage-names.f90
create mode 100644 flang/test/Lower/unique-internal-linkage-names.f90
create mode 100644 flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
create mode 100644 mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index b617604e29d9b..0f26bda02af7c 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -5057,7 +5057,7 @@ defm unique_internal_linkage_names : BoolFOption<"unique-internal-linkage-names"
PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option],
"Uniqueify Internal Linkage Symbol Names by appending"
" the MD5 hash of the module path">,
- NegFlag<SetFalse, [], [ClangOption, CC1Option, FlangOption, FC1Option]>>;
+ NegFlag<SetFalse, [], [ClangOption, CC1Option, FlangOption]>>;
defm unique_section_names : BoolFOption<"unique-section-names",
CodeGenOpts<"UniqueSectionNames">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option],
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 13bd618cf3d8d..e1cb98a443c81 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -349,9 +349,9 @@ void Flang::addCodegenOptions(const ArgList &Args,
options::OPT_fno_experimental_loop_fusion);
Args.AddLastArg(CmdArgs, options::OPT_ffp_sum_reassociation,
options::OPT_fno_fp_sum_reassociation);
-
+
Args.addOptInFlag(CmdArgs, options::OPT_funique_internal_linkage_names,
- options::OPT_fno_unique_internal_linkage_names);
+ options::OPT_fno_unique_internal_linkage_names);
handleInterchangeLoopsArgs(Args, CmdArgs);
handleVectorizeLoopsArgs(Args, CmdArgs);
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index b80a306cce625..e71a53b3b488c 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -317,15 +317,13 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
clang::options::OPT_fno_safe_trampoline, false))
opts.EnableSafeTrampoline = 1;
- if (args.hasFlag(clang::options::OPT_funique_internal_linkage_names,
- clang::options::OPT_fno_unique_internal_linkage_names,
- false))
- opts.UniqueInternalLinkageNames = 1;
-
if (args.hasFlag(clang::options::OPT_ffp_sum_reassociation,
clang::options::OPT_fno_fp_sum_reassociation, false))
opts.SplitSumExpressionTree = 1;
+ if (args.hasArg(clang::options::OPT_funique_internal_linkage_names))
+ opts.UniqueInternalLinkageNames = 1;
+
if (args.getLastArg(clang::options::OPT_floop_interchange))
opts.InterchangeLoops = 1;
diff --git a/flang/lib/Optimizer/Transforms/CompilerGeneratedNames.cpp b/flang/lib/Optimizer/Transforms/CompilerGeneratedNames.cpp
index 7a173da514b16..ca33639bbb888 100644
--- a/flang/lib/Optimizer/Transforms/CompilerGeneratedNames.cpp
+++ b/flang/lib/Optimizer/Transforms/CompilerGeneratedNames.cpp
@@ -45,6 +45,8 @@ void CompilerGeneratedNamesConversionPass::runOnOperation() {
auto processOp = [&](mlir::Operation &op) {
auto symName = mlir::cast<mlir::SymbolOpInterface>(&op).getNameAttr();
+ if (symName.getValue().contains(".__uniq."))
+ return;
auto deconstructedName = fir::NameUniquer::deconstruct(symName);
if (deconstructedName.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&
!fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) {
diff --git a/flang/test/Driver/funique-internal-linkage-names.f90 b/flang/test/Driver/funique-internal-linkage-names.f90
index 88cafb520a019..6192e3617cec0 100644
--- a/flang/test/Driver/funique-internal-linkage-names.f90
+++ b/flang/test/Driver/funique-internal-linkage-names.f90
@@ -1,20 +1,15 @@
! Test that -funique-internal-linkage-names / -fno-unique-internal-linkage-names are forwarded to flang -fc1.
-! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
+! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefix=DISABLED
! RUN: %flang -### -funique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=ENABLED
! RUN: %flang -### -fno-unique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=DISABLED
! RUN: %flang -### -funique-internal-linkage-names -fno-unique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=DISABLED
! RUN: %flang -### -fno-unique-internal-linkage-names -funique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=ENABLED
-! DEFAULT-NOT: "-funique-internal-linkage-names"
-! DEFAULT-NOT: "-fno-unique-internal-linkage-names"
-
-! ENABLED: "-fc1"{{.*}}"-funique-internal-linkage-names"
+! DISABLED: "-fc1"
! DISABLED-NOT: "-funique-internal-linkage-names"
+! DISABLED-NOT: "-fno-unique-internal-linkage-names"
+
+! ENABLED: "-fc1"
+! ENABLED-SAME: "-funique-internal-linkage-names"
-subroutine host()
- call inner()
-contains
- subroutine inner()
- end subroutine
-end subroutine
diff --git a/flang/test/Integration/unique-internal-linkage-names.f90 b/flang/test/Integration/unique-internal-linkage-names.f90
deleted file mode 100644
index c96e854b8eae4..0000000000000
--- a/flang/test/Integration/unique-internal-linkage-names.f90
+++ /dev/null
@@ -1,22 +0,0 @@
-! Test that -funique-internal-linkage-names appends a hash suffix to internal
-! procedures and sets the "sample-profile-suffix-elision-policy" attribute.
-
-! RUN: %flang_fc1 -emit-llvm -funique-internal-linkage-names -o - %s | FileCheck %s
-
-! CHECK-LABEL: define void @test_(
-! CHECK : call void @_QFtestPfooX__uniqX{{[0-9]+}}(ptr {{.*}})
-
-! CHECK-LABEL: define internal void @_QFtestPfooX__uniqX{{[0-9]+}}(ptr {{.*}}) #0
-! CHECK-NOT : define internal void @_QFtestPfoo(
-
-! CHECK: attributes #0 = { "sample-profile-suffix-elision-policy"="selected" }
-
-subroutine test(x)
- integer, intent(inout) :: x
- call foo(x)
-contains
- subroutine foo(y)
- integer, intent(inout) :: y
- y = y + 1
- end subroutine
-end subroutine
diff --git a/flang/test/Lower/unique-internal-linkage-names.f90 b/flang/test/Lower/unique-internal-linkage-names.f90
new file mode 100644
index 0000000000000..811519f3db5ab
--- /dev/null
+++ b/flang/test/Lower/unique-internal-linkage-names.f90
@@ -0,0 +1,20 @@
+! Test that -funique-internal-linkage-names appends a .__uniq. hash suffix
+! to internal procedures at the FIR level.
+
+! RUN: %flang_fc1 -emit-fir -funique-internal-linkage-names -o - %s | FileCheck %s
+
+! CHECK-LABEL: func.func @_QPtest
+! CHECK: fir.call @_QFtestPfoo.__uniq.{{[0-9]+}}
+
+! CHECK: func.func private @_QFtestPfoo.__uniq.{{[0-9]+}}
+! CHECK-SAME: attributes {fir.host_symbol = @_QPtest, llvm.linkage = #llvm.linkage<internal>}
+
+subroutine test(x)
+ integer, intent(inout) :: x
+ call foo(x)
+contains
+ subroutine foo(y)
+ integer, intent(inout) :: y
+ y = y + 1
+ end subroutine
+end subroutine
diff --git a/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir b/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
new file mode 100644
index 0000000000000..0284f75004b62
--- /dev/null
+++ b/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
@@ -0,0 +1,26 @@
+// RUN: fir-opt --function-attr="unique-internal-linkage-names=true" %s | FileCheck %s --check-prefix=ENABLED
+// RUN: fir-opt --function-attr="unique-internal-linkage-names=false" %s | FileCheck %s --check-prefix=DISABLED
+
+// ENABLED: func.func @_QPtest() {
+// ENABLED-NEXT: return
+// ENABLED-NEXT: }
+
+// DISABLED: func.func @_QPtest() {
+// DISABLED-NEXT: return
+// DISABLED-NEXT: }
+func.func @_QPtest() {
+ return
+}
+
+// ENABLED: func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest, llvm.sample_profile_suffix_elision_policy = "selected"} {
+// ENABLED-NEXT: return
+// ENABLED-NEXT: }
+
+// DISABLED: func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest} {
+// DISABLED-NEXT: return
+// DISABLED-NEXT: }
+
+func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest} {
+ return
+}
+
diff --git a/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir b/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
new file mode 100644
index 0000000000000..a1113caed3ed1
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
@@ -0,0 +1,20 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define void @test_(ptr noalias %0)
+// CHECK: call void @_QFtestPfoo.__uniq.12345(ptr %0)
+
+llvm.func @test_(%arg0: !llvm.ptr {llvm.noalias}) {
+ llvm.call @_QFtestPfoo.__uniq.12345(%arg0) : (!llvm.ptr) -> ()
+ llvm.return
+}
+
+// CHECK-LABEL: define internal void @_QFtestPfoo.__uniq.12345(ptr noalias %0)
+llvm.func internal @_QFtestPfoo.__uniq.12345(%arg0: !llvm.ptr {llvm.noalias}) attributes {sample_profile_suffix_elision_policy = "selected"} {
+ %0 = llvm.load %arg0 : !llvm.ptr -> i32
+ %1 = llvm.mlir.constant(1 : i32) : i32
+ %2 = llvm.add %0, %1 : i32
+ llvm.store %2, %arg0 : i32, !llvm.ptr
+ llvm.return
+}
+
+// CHECK: attributes #[[ATTRS:.*]] = { "sample-profile-suffix-elision-policy"="selected" }
>From 2e745b21ae7d1774bad800ee69b31587ddfaba95 Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Fri, 28 Aug 2026 15:58:33 +0530
Subject: [PATCH 3/3] [Flang] Addressed review comment and modified testcases
---
flang/lib/Lower/Bridge.cpp | 2 +-
.../Driver/funique-internal-linkage-names.f90 | 1 -
.../Lower/unique-internal-linkage-names.f90 | 9 +++----
...ion-attr-unique-internal-linkage-names.fir | 26 -------------------
.../sample-profile-suffix-elision-policy.mlir | 11 ++++++--
.../LLVMIR/unique-internal-linkage-names.mlir | 20 --------------
6 files changed, 13 insertions(+), 56 deletions(-)
delete mode 100644 flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
delete mode 100644 mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 7dfe305637cc7..5cb33f88fbd1b 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -1223,7 +1223,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
std::string mangledName = Fortran::lower::mangle::mangleName(
symbol, scopeBlockIdMap, /*keepExternalInScope=*/false,
getLoweringOptions().getUnderscoring());
- const auto &hash = bridge.getModuleNameHash();
+ const std::string &hash = bridge.getModuleNameHash();
if (!hash.empty() &&
Fortran::semantics::ClassifyProcedure(symbol) ==
Fortran::semantics::ProcedureDefinitionClass::Internal)
diff --git a/flang/test/Driver/funique-internal-linkage-names.f90 b/flang/test/Driver/funique-internal-linkage-names.f90
index 6192e3617cec0..d81e405cff541 100644
--- a/flang/test/Driver/funique-internal-linkage-names.f90
+++ b/flang/test/Driver/funique-internal-linkage-names.f90
@@ -12,4 +12,3 @@
! ENABLED: "-fc1"
! ENABLED-SAME: "-funique-internal-linkage-names"
-
diff --git a/flang/test/Lower/unique-internal-linkage-names.f90 b/flang/test/Lower/unique-internal-linkage-names.f90
index 811519f3db5ab..7699212ddff3a 100644
--- a/flang/test/Lower/unique-internal-linkage-names.f90
+++ b/flang/test/Lower/unique-internal-linkage-names.f90
@@ -9,12 +9,9 @@
! CHECK: func.func private @_QFtestPfoo.__uniq.{{[0-9]+}}
! CHECK-SAME: attributes {fir.host_symbol = @_QPtest, llvm.linkage = #llvm.linkage<internal>}
-subroutine test(x)
- integer, intent(inout) :: x
- call foo(x)
+subroutine test()
+ call foo()
contains
- subroutine foo(y)
- integer, intent(inout) :: y
- y = y + 1
+ subroutine foo()
end subroutine
end subroutine
diff --git a/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir b/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
deleted file mode 100644
index 0284f75004b62..0000000000000
--- a/flang/test/Transforms/function-attr-unique-internal-linkage-names.fir
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: fir-opt --function-attr="unique-internal-linkage-names=true" %s | FileCheck %s --check-prefix=ENABLED
-// RUN: fir-opt --function-attr="unique-internal-linkage-names=false" %s | FileCheck %s --check-prefix=DISABLED
-
-// ENABLED: func.func @_QPtest() {
-// ENABLED-NEXT: return
-// ENABLED-NEXT: }
-
-// DISABLED: func.func @_QPtest() {
-// DISABLED-NEXT: return
-// DISABLED-NEXT: }
-func.func @_QPtest() {
- return
-}
-
-// ENABLED: func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest, llvm.sample_profile_suffix_elision_policy = "selected"} {
-// ENABLED-NEXT: return
-// ENABLED-NEXT: }
-
-// DISABLED: func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest} {
-// DISABLED-NEXT: return
-// DISABLED-NEXT: }
-
-func.func @_QFtestPfoo() attributes {fir.host_symbol = @_QPtest} {
- return
-}
-
diff --git a/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir b/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
index 4882a886d4558..4953620571318 100644
--- a/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
+++ b/mlir/test/Target/LLVMIR/sample-profile-suffix-elision-policy.mlir
@@ -1,7 +1,14 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
-// CHECK: define void @with_elision_policy() #[[ATTRS:.*]] {
-// CHECK: attributes #[[ATTRS]] = { "sample-profile-suffix-elision-policy"="selected" }
+// CHECK: define void @with_elision_policy() #[[ATTRS_WITH:.*]] {
llvm.func @with_elision_policy() attributes {sample_profile_suffix_elision_policy = "selected"} {
llvm.return
}
+
+// CHECK: define void @without_elision_policy() {
+// CHECK-NOT: "sample-profile-suffix-elision-policy"
+llvm.func @without_elision_policy() {
+ llvm.return
+}
+
+// CHECK: attributes #[[ATTRS_WITH]] = { "sample-profile-suffix-elision-policy"="selected" }
diff --git a/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir b/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
deleted file mode 100644
index a1113caed3ed1..0000000000000
--- a/mlir/test/Target/LLVMIR/unique-internal-linkage-names.mlir
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
-
-// CHECK-LABEL: define void @test_(ptr noalias %0)
-// CHECK: call void @_QFtestPfoo.__uniq.12345(ptr %0)
-
-llvm.func @test_(%arg0: !llvm.ptr {llvm.noalias}) {
- llvm.call @_QFtestPfoo.__uniq.12345(%arg0) : (!llvm.ptr) -> ()
- llvm.return
-}
-
-// CHECK-LABEL: define internal void @_QFtestPfoo.__uniq.12345(ptr noalias %0)
-llvm.func internal @_QFtestPfoo.__uniq.12345(%arg0: !llvm.ptr {llvm.noalias}) attributes {sample_profile_suffix_elision_policy = "selected"} {
- %0 = llvm.load %arg0 : !llvm.ptr -> i32
- %1 = llvm.mlir.constant(1 : i32) : i32
- %2 = llvm.add %0, %1 : i32
- llvm.store %2, %arg0 : i32, !llvm.ptr
- llvm.return
-}
-
-// CHECK: attributes #[[ATTRS:.*]] = { "sample-profile-suffix-elision-policy"="selected" }
More information about the flang-commits
mailing list