Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -123,8 +123,9 @@ enum FileType { FT_Object, FT_Static, FT_Shared }; enum LTOPluginType { - LTOPT_LLVMgold, // LTO plugin used by toolchains that use the GNU linker. - LTOPT_LLVMldlld // LTO plugin used by toolchains that use the ld.lld. + LTOPT_LLVMgold, // LTO plugin used by toolchains that use the GNU linker. + LTOPT_LLVMldlld, // LTO plugin used by toolchains that use the ld.lld. + LTOPT_LLVMlto_AIX // LTO plugin used by the AIX toolchain. }; private: Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -658,6 +658,8 @@ case LTOPluginType::LTOPT_LLVMgold: case LTOPluginType::LTOPT_LLVMldlld: return "-plugin-opt="; + case LTOPluginType::LTOPT_LLVMlto_AIX: + return "-bplugin_opt:"; } llvm_unreachable("Unexpected LTO plugin type"); } Index: clang/lib/Driver/ToolChains/AIX.h =================================================================== --- clang/lib/Driver/ToolChains/AIX.h +++ clang/lib/Driver/ToolChains/AIX.h @@ -67,6 +67,7 @@ return false; } bool isPICDefaultForced() const override { return true; } + bool HasNativeLLVMSupport() const override { return true; } void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, @@ -90,6 +91,8 @@ return llvm::DebuggerKind::DBX; } + LTOPluginType getLTOPluginTypeImpl() const override; + protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; Index: clang/lib/Driver/ToolChains/AIX.cpp =================================================================== --- clang/lib/Driver/ToolChains/AIX.cpp +++ clang/lib/Driver/ToolChains/AIX.cpp @@ -164,6 +164,12 @@ // '-bnocdtors' that '-Wl' might forward. CmdArgs.push_back("-bcdtors:all:0:s"); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + // Specify linker input file(s). AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); @@ -289,6 +295,10 @@ return ToolChain::RLT_CompilerRT; } +ToolChain::LTOPluginType AIX::getLTOPluginTypeImpl() const { + return LTOPluginType::LTOPT_LLVMlto_AIX; +} + auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -66,6 +66,10 @@ static void MakePluginOpt(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const llvm::Twine &opt, bool Seperator = false) { + // AIX libLTO opts always require a dash. + if (ToolChain.getLTOPluginType() == + ToolChain::LTOPluginType::LTOPT_LLVMlto_AIX) + Seperator = true; CmdArgs.push_back(Args.MakeArgString(Twine(ToolChain.getLTOPluginPrefix()) + (Seperator ? Twine("-") : Twine("")) + opt)); @@ -103,30 +107,46 @@ F = Output.getFilename(); assert(!F.empty() && "Cannot determine remarks output name."); + const bool IsLTOPluginTypeAIX = ToolChain.getLTOPluginType() == + ToolChain::LTOPluginType::LTOPT_LLVMlto_AIX; + const char *remarksFileOpt = + IsLTOPluginTypeAIX ? "lto-pass-remarks-output=" : "opt-remarks-filename="; // Append "opt.ld." to the end of the file name. MakePluginOpt(ToolChain, Args, CmdArgs, - "opt-remarks-filename=" + F + Twine(".opt.ld.") + Format); + remarksFileOpt + F + Twine(".opt.ld.") + Format); + const char *remarksPassesOpt = + IsLTOPluginTypeAIX ? "lto-pass-remarks-filter=" : "opt-remarks-passes="; if (const Arg *A = Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) MakePluginOpt(ToolChain, Args, CmdArgs, - Twine("opt-remarks-passes=") + A->getValue()); + Twine(remarksPassesOpt) + A->getValue()); + const char *remarksFormatOpt = + IsLTOPluginTypeAIX ? "lto-pass-remarks-format=" : "opt-remarks-format="; MakePluginOpt(ToolChain, Args, CmdArgs, - Twine("opt-remarks-format=") + Format.data()); + Twine(remarksFormatOpt) + Format.data()); } static void renderRemarksHotnessOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs) { + const bool IsLTOPluginTypeAIX = ToolChain.getLTOPluginType() == + ToolChain::LTOPluginType::LTOPT_LLVMlto_AIX; + const char *remarksWithHotnessOpt = IsLTOPluginTypeAIX + ? "lto-pass-remarks-with-hotness" + : "opt-remarks-with-hotness"; if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness, options::OPT_fno_diagnostics_show_hotness, false)) - MakePluginOpt(ToolChain, Args, CmdArgs, "opt-remarks-with-hotness"); + MakePluginOpt(ToolChain, Args, CmdArgs, remarksWithHotnessOpt); + const char *remarksHotnessThresholdOpt = + IsLTOPluginTypeAIX ? "lto-pass-remarks-hotness-threshold=" + : "opt-remarks-hotness-threshold="; if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) MakePluginOpt(ToolChain, Args, CmdArgs, - Twine("opt-remarks-hotness-threshold=") + A->getValue()); + Twine(remarksHotnessThresholdOpt) + A->getValue()); } void tools::addPathIfExists(const Driver &D, const Twine &Path, @@ -495,21 +515,26 @@ const InputInfo &Input, bool IsThinLTO) { const ToolChain::LTOPluginType LTOPluginType = ToolChain.getLTOPluginType(); const Driver &D = ToolChain.getDriver(); - if (LTOPluginType != ToolChain::LTOPluginType::LTOPT_LLVMldlld) { - // Tell the linker to load the plugin. This has to come before - // AddLinkerInputs as gold requires -plugin to come before any -plugin-opt - // that -Wl might forward. - CmdArgs.push_back("-plugin"); - #if defined(_WIN32) - const char *Suffix = ".dll"; + const char *Suffix = ".dll"; #elif defined(__APPLE__) - const char *Suffix = ".dylib"; + const char *Suffix = ".dylib"; #else - const char *Suffix = ".so"; + const char *Suffix = ".so"; #endif + SmallString<1024> Plugin; + if (LTOPluginType == ToolChain::LTOPluginType::LTOPT_LLVMlto_AIX) { + llvm::sys::path::native("-bplugin:" + Twine(D.Dir) + + "/../lib" CLANG_LIBDIR_SUFFIX "/libLTO" + + Suffix, + Plugin); + CmdArgs.push_back(Args.MakeArgString(Plugin)); + } else if (LTOPluginType == ToolChain::LTOPluginType::LTOPT_LLVMgold) { + // Tell the linker to load the plugin. This has to come before + // AddLinkerInputs as gold requires -plugin to come before any -plugin-opt + // that -Wl might forward. + CmdArgs.push_back("-plugin"); - SmallString<1024> Plugin; llvm::sys::path::native( Twine(D.Dir) + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + Suffix, Plugin); Index: clang/test/Driver/lto.c =================================================================== --- clang/test/Driver/lto.c +++ clang/test/Driver/lto.c @@ -48,35 +48,66 @@ // RUN: -fuse-ld=gold -flto -fno-lto -### 2>&1 | FileCheck --check-prefix=NO-LLVMGOLD %s // NO-LLVMGOLD-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +/// With AIX ld, use libLTO. +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto=full -### 2>&1 | FileCheck --check-prefix=AIXLD %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -fno-lto -flto -### 2>&1 | FileCheck --check-prefix=AIXLD %s +// AIXLD: "-bplugin:{{.*}}{{[/\\]}}libLTO.{{dll|dylib|so}}" + // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -O -### 2>&1 | FileCheck --check-prefix=O1 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -O -### 2>&1 | FileCheck --check-prefix=O1AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -O1 -### 2>&1 | FileCheck --check-prefix=O1 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -O1 -### 2>&1 | FileCheck --check-prefix=O1AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -Og -### 2>&1 | FileCheck --check-prefix=O1 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -Og -### 2>&1 | FileCheck --check-prefix=O1AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -O2 -### 2>&1 | FileCheck --check-prefix=O2 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -O2 -### 2>&1 | FileCheck --check-prefix=O2AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -Os -### 2>&1 | FileCheck --check-prefix=O2 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -Os -### 2>&1 | FileCheck --check-prefix=O2AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -Oz -### 2>&1 | FileCheck --check-prefix=O2 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -Oz -### 2>&1 | FileCheck --check-prefix=O2AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -O3 -### 2>&1 | FileCheck --check-prefix=O3 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -O3 -### 2>&1 | FileCheck --check-prefix=O3AIX %s // RUN: %clang -target x86_64-unknown-linux-gnu --sysroot %S/Inputs/basic_cross_linux_tree %s \ // RUN: -fuse-ld=lld -flto -Ofast -### 2>&1 | FileCheck --check-prefix=O3 %s +// RUN: %clang -target powerpc-ibm-aix --sysroot %S/Inputs/aix_ppc_tree %s \ +// RUN: -fuse-ld=ld -flto -Ofast -### 2>&1 | FileCheck --check-prefix=O3AIX %s // O1: -plugin-opt=O1 +// O1AIX: -bplugin_opt:-O1 // O2: -plugin-opt=O2 +// O2AIX: -bplugin_opt:-O2 // O3: -plugin-opt=O3 +// O3AIX: -bplugin_opt:-O3 // -flto passes along an explicit debugger tuning argument. // RUN: %clang -target x86_64-unknown-linux -### %s -flto -glldb 2> %t // RUN: FileCheck -check-prefix=CHECK-TUNING-LLDB < %t %s // RUN: %clang -target x86_64-unknown-linux -### %s -flto -g 2> %t // RUN: FileCheck -check-prefix=CHECK-NO-TUNING < %t %s +// RUN: %clang -target powerpc-ibm-aix -### %s -flto -fuse-ld=ld -gdbx 2> %t +// RUN: FileCheck -check-prefix=CHECK-TUNING-DBX < %t %s +// RUN: %clang -target powerpc-ibm-aix -### %s -flto -fuse-ld=ld -g 2> %t +// RUN: FileCheck -check-prefix=CHECK-NO-TUNING < %t %s // // CHECK-TUNING-LLDB: "-plugin-opt=-debugger-tune=lldb" -// CHECK-NO-TUNING-NOT: "-plugin-opt=-debugger-tune +// CHECK-TUNING-DBX: "-bplugin_opt:-debugger-tune=dbx" +// CHECK-NO-TUNING-NOT: "{{-plugin-opt=|-bplugin_opt:}}-debugger-tune // // -flto=auto and -flto=jobserver pass along -flto=full // RUN: %clang -target x86_64-unknown-linux -### %s -flto=auto 2>&1 | FileCheck --check-prefix=FLTO-AUTO %s @@ -104,4 +135,4 @@ // FLTO-THIN-NOT: "-flto" // FLTO-THIN: -flto=thin // FLTO-THIN-NOT: "-flto" -// FLTO-THIN-NOT: -flto=full \ No newline at end of file +// FLTO-THIN-NOT: -flto=full Index: clang/test/Driver/opt-record.c =================================================================== --- clang/test/Driver/opt-record.c +++ clang/test/Driver/opt-record.c @@ -45,36 +45,67 @@ // Test remarks options pass-through // No pass-through: lto is disabled // RUN: %clang -target x86_64 -### -o FOO -fdiagnostics-hotness-threshold=100 -fsave-optimization-record %s 2>&1 | FileCheck %s -check-prefix=CHECK-NOPASS +// RUN: %clang -target powerpc-ibm-aix -### -o FOO -fdiagnostics-hotness-threshold=100 -fsave-optimization-record %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-NOPASS // Pass-through: // RUN: %clang -target x86_64-linux -### -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-A +// RUN: %clang -target powerpc-ibm-aix -### -fuse-ld=ld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-PASS-A // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=gold -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS +// RUN: %clang -target powerpc-ibm-aix -### -o FOO -fuse-ld=ld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-PASS // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=100 -fsave-optimization-record=some-format -foptimization-record-file=FOO.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-CUSTOM +// RUN: %clang -target powerpc-ibm-aix -### -o FOO -fuse-ld=ld -flto=full -fdiagnostics-hotness-threshold=100 -fsave-optimization-record=some-format -foptimization-record-file=FOO.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-PASS-CUSTOM // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=100 -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-RPASS +// RUN: %clang -target powerpc-ibm-aix -### -o FOO -fuse-ld=ld -flto=full -fdiagnostics-hotness-threshold=100 -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-PASS-RPASS // RUN: %clang -target x86_64-linux -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS-AUTO +// RUN: %clang -target powerpc-ibm-aix -### -o FOO -fuse-ld=ld -flto=full -fdiagnostics-hotness-threshold=auto -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AIX-PASS-AUTO // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-filename=" // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-passes=inline" // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-format=yaml" // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-hotness-threshold=100" +// CHECK-AIX-NOPASS-NOT: "-bplugin_opt:-lto-pass-remarks-output=" +// CHECK-AIX-NOPASS-NOT: "-bplugin_opt:-lto-pass-remarks-filter=inline" +// CHECK-AIX-NOPASS-NOT: "-bplugin_opt:-lto-pass-remarks-format=yaml" +// CHECK-AIX-NOPASS-NOT: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=100" + // CHECK-PASS-A: "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-passes=inline" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-format=yaml" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" +// CHECK-AIX-PASS-A: "-bplugin_opt:-lto-pass-remarks-output=a.out.opt.ld.yaml" +// CHECK-AIX-PASS-A-SAME: "-bplugin_opt:-lto-pass-remarks-filter=inline" +// CHECK-AIX-PASS-A-SAME: "-bplugin_opt:-lto-pass-remarks-format=yaml" +// CHECK-AIX-PASS-A-SAME: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=100" + // CHECK-PASS: "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-passes=inline" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-format=yaml" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" +// CHECK-AIX-PASS: "-bplugin_opt:-lto-pass-remarks-output=FOO.opt.ld.yaml" +// CHECK-AIX-PASS-SAME: "-bplugin_opt:-lto-pass-remarks-filter=inline" +// CHECK-AIX-PASS-SAME: "-bplugin_opt:-lto-pass-remarks-format=yaml" +// CHECK-AIX-PASS-SAME: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=100" + // CHECK-PASS-CUSTOM: "-plugin-opt=opt-remarks-filename=FOO.txt.opt.ld.some-format" // CHECK-PASS-CUSTOM-SAME: "-plugin-opt=opt-remarks-format=some-format" // CHECK-PASS-CUSTOM-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" +// CHECK-AIX-PASS-CUSTOM: "-bplugin_opt:-lto-pass-remarks-output=FOO.txt.opt.ld.some-format" +// CHECK-AIX-PASS-CUSTOM-SAME: "-bplugin_opt:-lto-pass-remarks-format=some-format" +// CHECK-AIX-PASS-CUSTOM-SAME: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=100" + // CHECK-PASS-RPASS: "-plugin-opt=-pass-remarks=inline" // CHECK-PASS-RPASS-SAME: "-plugin-opt=-pass-remarks-missed=inline" // CHECK-PASS-RPASS-SAME: "-plugin-opt=-pass-remarks-analysis=inline" // CHECK-PASS-RPASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" +// CHECK-AIX-PASS-RPASS: "-bplugin_opt:-pass-remarks=inline" +// CHECK-AIX-PASS-RPASS-SAME: "-bplugin_opt:-pass-remarks-missed=inline" +// CHECK-AIX-PASS-RPASS-SAME: "-bplugin_opt:-pass-remarks-analysis=inline" +// CHECK-AIX-PASS-RPASS-SAME: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=100" + // CHECK-PASS-AUTO: "-plugin-opt=opt-remarks-hotness-threshold=auto" +// CHECK-AIX-PASS-AUTO: "-bplugin_opt:-lto-pass-remarks-hotness-threshold=auto"