Index: lib/CodeGen/GlobalMerge.cpp =================================================================== --- lib/CodeGen/GlobalMerge.cpp +++ lib/CodeGen/GlobalMerge.cpp @@ -615,7 +615,7 @@ // It's not safe to merge globals that may be preempted if (TM && !TM->shouldAssumeDSOLocal(M, &GV)) continue; - + if (!(MergeExternalGlobals && GV.hasExternalLinkage()) && !GV.hasInternalLinkage()) continue; Index: lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetMachine.cpp +++ lib/Target/AArch64/AArch64TargetMachine.cpp @@ -461,7 +461,14 @@ EnableGlobalMerge == cl::BOU_TRUE) { bool OnlyOptimizeForSize = (TM->getOptLevel() < CodeGenOpt::Aggressive) && (EnableGlobalMerge == cl::BOU_UNSET); - addPass(createGlobalMergePass(TM, 4095, OnlyOptimizeForSize)); + + // Merging of extern globals is enabled by default on non-Mach-O as we + // expect it to be generally either beneficial or harmless. On Mach-O it + // is disabled as we emit the .subsections_via_symbols directive which + // means that merging extern globals is not safe. + bool MergeExternalByDefault = !TM->getTargetTriple().isOSBinFormatMachO(); + addPass(createGlobalMergePass(TM, 4095, OnlyOptimizeForSize, + MergeExternalByDefault)); } return false; Index: test/CodeGen/AArch64/global_merge_aarc64_ac6.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/global_merge_aarc64_ac6.ll @@ -0,0 +1,35 @@ +;RUN: llc -O3 %s -o - -verify-machineinstrs | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-arm-none-eabi" + +@global0 = dso_local local_unnamed_addr global i32 0, align 4 +@global1 = dso_local local_unnamed_addr global i32 0, align 4 + +; Function Attrs: minsize norecurse nounwind optsize readonly + +;CHECK-LABEL: @func +;CHECK: adrp x8, .L_MergedGlobals +;CHECK: add x8, x8, :lo12:.L_MergedGlobals +;CHECK-NEXT: ldp +;CHECK-NEXT: add +;CHECK-NEXT: ret +define dso_local i32 @func() local_unnamed_addr #0 { +entry: + %0 = load i32, i32* @global0, align 4, !tbaa !2 + %1 = load i32, i32* @global1, align 4, !tbaa !2 + %add = add nsw i32 %1, %0 + ret i32 %add +} + +attributes #0 = { minsize norecurse nounwind optsize readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a53" "target-features"="+aes,+crc,+crypto,+fp-armv8,+neon,+sha2" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 9.0.0 (https://git.llvm.org/git/clang.git/ 7a6d690bb52df60e979a7c7f9d03a774009bb443) (https://git.llvm.org/git/llvm.git/ 71abe189dddb95b0d5782e0866058b9a92ff2402)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C/C++ TBAA"}