diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 0df2e494234da..2b4fa15a950c1 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -35,6 +35,7 @@ #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/LLVMIR/Transforms/AddComdats.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/BuiltinTypes.h" @@ -3815,6 +3816,14 @@ class FIRToLLVMLowering std::move(pattern)))) { signalPassFailure(); } + + // Run pass to add comdats to functions that have weak linkage on relevant platforms + if (fir::getTargetTriple(mod).supportsCOMDAT()) { + mlir::OpPassManager comdatPM("builtin.module"); + comdatPM.addPass(mlir::LLVM::createLLVMAddComdats()); + if (mlir::failed(runPipeline(comdatPM, mod))) + return signalPassFailure(); + } } private: diff --git a/flang/test/Fir/comdat.fir b/flang/test/Fir/comdat.fir new file mode 100644 index 0000000000000..2f5da505e4903 --- /dev/null +++ b/flang/test/Fir/comdat.fir @@ -0,0 +1,41 @@ + +// RUN: fir-opt %s --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %s --check-prefixes="CHECK-COMDAT" +// RUN: fir-opt %s --fir-to-llvm-ir="target=x86_64-pc-windows-msvc" | FileCheck %s --check-prefixes="CHECK-COMDAT" +// RUN: fir-opt %s --fir-to-llvm-ir="target=aarch64-apple-darwin" | FileCheck %s --check-prefixes="CHECK-NOCOMDAT" +// RUN: fir-opt %s --fir-to-llvm-ir="target=powerpc64-ibm-aix" | FileCheck %s --check-prefixes="CHECK-NOCOMDAT" + +// CHECK-COMDAT: llvm.func linkonce @fun_linkonce(%arg0: i32) -> i32 comdat(@__llvm_comdat::@fun_linkonce) +// CHECK-NOCOMDAT: llvm.func linkonce @fun_linkonce(%arg0: i32) -> i32 { +func.func @fun_linkonce(%arg0: i32) -> i32 attributes {llvm.linkage = #llvm.linkage} { + return %arg0 : i32 +} + +// CHECK-COMDAT: llvm.func linkonce_odr @fun_linkonce_odr(%arg0: i32) -> i32 comdat(@__llvm_comdat::@fun_linkonce_odr) +// CHECK-NOCOMDAT: llvm.func linkonce_odr @fun_linkonce_odr(%arg0: i32) -> i32 { +func.func @fun_linkonce_odr(%arg0: i32) -> i32 attributes {llvm.linkage = #llvm.linkage} { + return %arg0 : i32 +} + +// CHECK-COMDAT: llvm.mlir.global linkonce constant @global_linkonce() comdat(@__llvm_comdat::@global_linkonce) {addr_space = 0 : i32} : i32 +// CHECK-NOCOMDAT: llvm.mlir.global linkonce constant @global_linkonce() {addr_space = 0 : i32} : i32 { +fir.global linkonce @global_linkonce constant : i32 { + %0 = arith.constant 0 : i32 + fir.has_value %0 : i32 +} + +// CHECK-COMDAT: llvm.comdat @__llvm_comdat { +// CHECK-COMDAT: llvm.comdat_selector @fun_linkonce_odr any +// CHECK-COMDAT: llvm.comdat_selector @fun_linkonce any +// CHECK-COMDAT: llvm.comdat_selector @global_linkonce any +// CHECK-COMDAT: llvm.comdat_selector @global_linkonce_odr any + +// CHECK-NOCOMDAT-NOT: llvm.comdat +// CHECK-NOCOMDAT-NOT: llvm.comdat_selector + + +// CHECK-COMDAT: llvm.mlir.global linkonce_odr constant @global_linkonce_odr() comdat(@__llvm_comdat::@global_linkonce_odr) {addr_space = 0 : i32} : i32 +// CHECK-NOCOMDAT: llvm.mlir.global linkonce_odr constant @global_linkonce_odr() {addr_space = 0 : i32} : i32 { +fir.global linkonce_odr @global_linkonce_odr constant : i32 { + %0 = arith.constant 0 : i32 + fir.has_value %0 : i32 +} \ No newline at end of file diff --git a/flang/test/Intrinsics/math-codegen.fir b/flang/test/Intrinsics/math-codegen.fir index 0af896adf3226..62d841253075e 100644 --- a/flang/test/Intrinsics/math-codegen.fir +++ b/flang/test/Intrinsics/math-codegen.fir @@ -1467,9 +1467,15 @@ func.func private @llvm.powi.f64.i32(f64, i32) -> f64 func.func private @pow(f64, f64) -> f64 //--- exponentiation_integer.fir -// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_integer.fir +// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_integer.fir --check-prefixes="CHECK,CHECK-COMDAT" +// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=x86_64-pc-windows-msvc" | FileCheck %t/exponentiation_integer.fir --check-prefixes="CHECK,CHECK-COMDAT" +// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=aarch64-apple-darwin" | FileCheck %t/exponentiation_integer.fir --check-prefixes="CHECK,CHECK-NOCOMDAT" +// CHECK-COMDAT: llvm.comdat_selector @__mlir_math_ipowi_i32 any +// CHECK-NOCOMDAT-NOT: llvm.comdat_selector @__mlir_math_ipowi_i32 any // CHECK: @_QPtest_int4 // CHECK: llvm.call @__mlir_math_ipowi_i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (i32, i32) -> i32 +// CHECK-COMDAT: llvm.func linkonce_odr @__mlir_math_ipowi_i32(%arg0: i32, %arg1: i32) -> i32 comdat(@__llvm_comdat::@__mlir_math_ipowi_i32) +// CHECK-NOCOMDAT: llvm.func linkonce_odr @__mlir_math_ipowi_i32(%arg0: i32, %arg1: i32) -> i32 func.func @_QPtest_int4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref {fir.bindc_name = "z"}) { %0 = fir.load %arg0 : !fir.ref