[flang-commits] [flang] 8cb0c3b - [flang] Add COMDAT to global variables where needed
David Truby via flang-commits
flang-commits at lists.llvm.org
Wed Jun 28 05:49:39 PDT 2023
Author: David Truby
Date: 2023-06-28T13:49:30+01:00
New Revision: 8cb0c3bb2173890e5f6cf2082fe65682b15888ba
URL: https://github.com/llvm/llvm-project/commit/8cb0c3bb2173890e5f6cf2082fe65682b15888ba
DIFF: https://github.com/llvm/llvm-project/commit/8cb0c3bb2173890e5f6cf2082fe65682b15888ba.diff
LOG: [flang] Add COMDAT to global variables where needed
On platforms which support COMDAT sections we should use them when
linkonce or linkonce_odr linkage is requested. This is required on
Windows (PE/COFF) and provides better behaviour than weak symbols on
ELF-based platforms.
This patch also reverts string literals to use linkonce instead of
internal linkage now that comdats are supported.
Differential Revision: https://reviews.llvm.org/D153768
Added:
Modified:
flang/lib/Optimizer/Builder/FIRBuilder.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/test/Fir/convert-to-llvm.fir
flang/test/Fir/tbaa.fir
flang/test/Lower/allocatable-assignment.f90
flang/test/Lower/character-assignment.f90
flang/test/Lower/convert.f90
flang/test/Lower/global-format-strings.f90
flang/test/Lower/io-statement-open-options.f90
flang/test/Lower/namelist.f90
flang/test/Lower/read-write-buffer.f90
flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
Removed:
################################################################################
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 5f98b105eb1f9..fe23e139152ef 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -999,9 +999,7 @@ fir::ExtendedValue fir::factory::createStringLiteral(fir::FirOpBuilder &builder,
auto stringLitOp = builder.createStringLitOp(loc, str);
builder.create<fir::HasValueOp>(loc, stringLitOp);
},
- builder.createInternalLinkage());
- // TODO: This can be changed to linkonce linkage once we have support for
- // generating comdat sections
+ builder.createLinkOnceLinkage());
auto addr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
global.getSymbol());
auto len = builder.createIntegerConstant(
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 2e207a9caab4d..0061d18af65fc 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -2856,6 +2856,14 @@ struct GlobalOpConversion : public FIROpConversion<fir::GlobalOp> {
auto g = rewriter.create<mlir::LLVM::GlobalOp>(
loc, tyAttr, isConst, linkage, global.getSymName(), initAttr);
+ auto module = global->getParentOfType<mlir::ModuleOp>();
+ // Add comdat if necessary
+ if (fir::getTargetTriple(module).supportsCOMDAT() &&
+ (linkage == mlir::LLVM::Linkage::Linkonce ||
+ linkage == mlir::LLVM::Linkage::LinkonceODR)) {
+ addComdat(g, rewriter, module);
+ }
+
// Apply all non-Fir::GlobalOp attributes to the LLVM::GlobalOp, preserving
// them; whilst taking care not to apply attributes that are lowered in
// other ways.
@@ -2931,6 +2939,27 @@ struct GlobalOpConversion : public FIROpConversion<fir::GlobalOp> {
}
return mlir::LLVM::Linkage::External;
}
+
+private:
+ static void addComdat(mlir::LLVM::GlobalOp &global,
+ mlir::ConversionPatternRewriter &rewriter,
+ mlir::ModuleOp &module) {
+ const char *comdatName = "__llvm_comdat";
+ mlir::LLVM::ComdatOp comdatOp =
+ module.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
+ if (!comdatOp) {
+ comdatOp =
+ rewriter.create<mlir::LLVM::ComdatOp>(module.getLoc(), comdatName);
+ }
+ mlir::OpBuilder::InsertionGuard guard(rewriter);
+ rewriter.setInsertionPointToEnd(&comdatOp.getBody().back());
+ auto selectorOp = rewriter.create<mlir::LLVM::ComdatSelectorOp>(
+ comdatOp.getLoc(), global.getSymName(),
+ mlir::LLVM::comdat::Comdat::Any);
+ global.setComdatAttr(mlir::SymbolRefAttr::get(
+ rewriter.getContext(), comdatName,
+ mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr())));
+ }
};
/// `fir.load` --> `llvm.load`
diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index d1d62027515e0..14cd58a6148b1 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -1,7 +1,9 @@
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-pc-win32" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-apple-darwin" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT
//=============================================================================
// SUMMARY: Tests for FIR --> LLVM MLIR conversion independent of the target
@@ -49,7 +51,8 @@ fir.global weak @w_i86 (86:i32) : i32
// -----
fir.global linkonce @w_i86 (86:i32) : i32
-// CHECK: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
+// CHECK-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) comdat(@__llvm_comdat::@w_i86) {addr_space = 0 : i32} : i32
+// CHECK-NO-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
// -----
@@ -1678,7 +1681,8 @@ func.func @embox1(%arg0: !fir.ref<!fir.type<_QMtest_dinitTtseq{i:i32}>>) {
return
}
-// CHECK: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
+// CHECK-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() comdat(@__llvm_comdat::@_QMtest_dinitE.dt.tseq) {addr_space = 0 : i32} : i8
+// CHECK-NO-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
// CHECK-LABEL: llvm.func @embox1
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(42 : i32) : i32
// CHECK: %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
diff --git a/flang/test/Fir/tbaa.fir b/flang/test/Fir/tbaa.fir
index 66261e6ee002a..3528f61b5bfcc 100644
--- a/flang/test/Fir/tbaa.fir
+++ b/flang/test/Fir/tbaa.fir
@@ -195,7 +195,7 @@ module {
// CHECK: llvm.func @_FortranAioOutputDescriptor(!llvm.ptr<i8>, !llvm.ptr<struct<(ptr<struct<()>>, i64, i32, i8, i8, i8, i8, ptr<i8>, array<1 x i64>)>>) -> i1 attributes {fir.io, fir.runtime, sym_visibility = "private"}
// CHECK: llvm.func @_FortranAioEndIoStatement(!llvm.ptr<i8>) -> i32 attributes {fir.io, fir.runtime, sym_visibility = "private"}
-// CHECK-LABEL: llvm.mlir.global linkonce constant @_QQcl.2E2F64756D6D792E66393000() {addr_space = 0 : i32} : !llvm.array<12 x i8> {
+// CHECK-LABEL: llvm.mlir.global linkonce constant @_QQcl.2E2F64756D6D792E66393000() comdat(@__llvm_comdat::@_QQcl.2E2F64756D6D792E66393000) {addr_space = 0 : i32} : !llvm.array<12 x i8> {
// CHECK: %[[VAL_0:.*]] = llvm.mlir.constant("./dummy.f90\00") : !llvm.array<12 x i8>
// CHECK: llvm.return %[[VAL_0]] : !llvm.array<12 x i8>
// CHECK: }
diff --git a/flang/test/Lower/allocatable-assignment.f90 b/flang/test/Lower/allocatable-assignment.f90
index 60f6fac107bf4..5d2f28177bcbf 100644
--- a/flang/test/Lower/allocatable-assignment.f90
+++ b/flang/test/Lower/allocatable-assignment.f90
@@ -1242,7 +1242,7 @@ end function elt
! CHECK: }
end subroutine
-! CHECK: fir.global internal @[[error_message]] constant : !fir.char<1,76> {
+! CHECK: fir.global linkonce @[[error_message]] constant : !fir.char<1,76> {
! CHECK: %[[msg:.*]] = fir.string_lit "array left hand side must be allocated when the right hand side is a scalar\00"(76) : !fir.char<1,76>
! CHECK: fir.has_value %[[msg:.*]] : !fir.char<1,76>
! CHECK: }
diff --git a/flang/test/Lower/character-assignment.f90 b/flang/test/Lower/character-assignment.f90
index fad419ea9fc3b..7f1874d3f083f 100644
--- a/flang/test/Lower/character-assignment.f90
+++ b/flang/test/Lower/character-assignment.f90
@@ -102,7 +102,7 @@ subroutine assign_zero_size_array(n)
! CHECK: return
end subroutine
-! CHECK-LABEL: fir.global internal @_QQcl.48656C6C6F20576F726C64
+! CHECK-LABEL: fir.global linkonce @_QQcl.48656C6C6F20576F726C64
! CHECK: %[[lit:.*]] = fir.string_lit "Hello World"(11) : !fir.char<1,11>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,11>
! CHECK: }
diff --git a/flang/test/Lower/convert.f90 b/flang/test/Lower/convert.f90
index 50050190803e2..1ab93dcc17320 100755
--- a/flang/test/Lower/convert.f90
+++ b/flang/test/Lower/convert.f90
@@ -21,11 +21,11 @@ program test
! ALL: %[[VAL_8:.*]] = fir.insert_value %[[VAL_4]], %[[VAL_7]], [0 : index, 1 : index] : (!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>, !fir.ref<i8>) -> !fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>
! ALL: fir.has_value %[[VAL_8]] : !fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>
-! ALL: fir.global internal @[[FC_STR]] constant : !fir.char<1,13> {
+! ALL: fir.global linkonce @[[FC_STR]] constant : !fir.char<1,13> {
! ALL: %[[VAL_0:.*]] = fir.string_lit "FORT_CONVERT\00"(13) : !fir.char<1,13>
! ALL: fir.has_value %[[VAL_0]] : !fir.char<1,13>
-! ALL: fir.global internal @[[OPT_STR]] constant : !fir.char<1,[[OPT_STR_LEN]]> {
+! ALL: fir.global linkonce @[[OPT_STR]] constant : !fir.char<1,[[OPT_STR_LEN]]> {
! UNKNOWN: %[[VAL_0:.*]] = fir.string_lit "UNKNOWN\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
! NATIVE: %[[VAL_0:.*]] = fir.string_lit "NATIVE\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
! LITTLE_ENDIAN: %[[VAL_0:.*]] = fir.string_lit "LITTLE_ENDIAN\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
diff --git a/flang/test/Lower/global-format-strings.f90 b/flang/test/Lower/global-format-strings.f90
index d9307abd74731..3112da33dc0fe 100644
--- a/flang/test/Lower/global-format-strings.f90
+++ b/flang/test/Lower/global-format-strings.f90
@@ -8,7 +8,7 @@ program other
! CHECK: fir.address_of(@{{.*}}) :
1008 format('ok')
end
-! CHECK-LABEL: fir.global internal @_QQcl.28276F6B2729 constant
+! CHECK-LABEL: fir.global linkonce @_QQcl.28276F6B2729 constant
! CHECK: %[[lit:.*]] = fir.string_lit "('ok')"(6) : !fir.char<1,6>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,6>
! CHECK: }
diff --git a/flang/test/Lower/io-statement-open-options.f90 b/flang/test/Lower/io-statement-open-options.f90
index 4d414e069f599..4348767ec2033 100755
--- a/flang/test/Lower/io-statement-open-options.f90
+++ b/flang/test/Lower/io-statement-open-options.f90
@@ -15,6 +15,6 @@ subroutine test_convert_specifier(unit)
close(unit)
end subroutine
-! CHECK: fir.global internal @[[be_str_name]] constant : !fir.char<1,10> {
+! CHECK: fir.global linkonce @[[be_str_name]] constant : !fir.char<1,10> {
! CHECK: %[[be_str_lit:.*]] = fir.string_lit "BIG_ENDIAN"(10) : !fir.char<1,10>
! CHECK: fir.has_value %[[be_str_lit]] : !fir.char<1,10>
diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90
index 6637283b61381..643e30adf2ec8 100644
--- a/flang/test/Lower/namelist.f90
+++ b/flang/test/Lower/namelist.f90
@@ -83,6 +83,6 @@ subroutine global_pointer
write(10, nml=mygroup)
end
- ! CHECK-DAG: fir.global internal @_QQcl.6A6A6A00 constant : !fir.char<1,4>
- ! CHECK-DAG: fir.global internal @_QQcl.63636300 constant : !fir.char<1,4>
- ! CHECK-DAG: fir.global internal @_QQcl.6E6E6E00 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.6A6A6A00 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.63636300 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.6E6E6E00 constant : !fir.char<1,4>
diff --git a/flang/test/Lower/read-write-buffer.f90 b/flang/test/Lower/read-write-buffer.f90
index 188cdb088973f..889209242cb4a 100644
--- a/flang/test/Lower/read-write-buffer.f90
+++ b/flang/test/Lower/read-write-buffer.f90
@@ -29,7 +29,7 @@ subroutine some()
write (buffer, 10) "compiler"
read (buffer, 10) greeting
end
-! CHECK-LABEL: fir.global internal @_QQcl.636F6D70696C6572
+! CHECK-LABEL: fir.global linkonce @_QQcl.636F6D70696C6572
! CHECK: %[[lit:.*]] = fir.string_lit "compiler"(8) : !fir.char<1,8>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,8>
! CHECK: }
diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index 650a4d13b2b52..c3436ccd1c779 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -311,7 +311,7 @@ TEST_F(FIRBuilderTest, createStringLiteral) {
auto symbol = addrOp.getSymbol().getRootReference().getValue();
auto global = builder.getNamedGlobal(symbol);
EXPECT_EQ(
- builder.createInternalLinkage().getValue(), global.getLinkName().value());
+ builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
EXPECT_EQ(fir::CharacterType::get(builder.getContext(), 1, strValue.size()),
global.getType());
More information about the flang-commits
mailing list