diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1590,7 +1590,7 @@ Conf.MAttrs = TOpts.Features; Conf.RelocModel = CGOpts.RelocationModel; Conf.CGOptLevel = getCGOptLevel(CGOpts); - Conf.OptLevel = CGOpts.OptimizationLevel; + Conf.OptLevel = mapToLevel(CGOpts); initTargetOptions(Diags, Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts); Conf.SampleProfile = std::move(SampleProfile); Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops; diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/COFF.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CachePruning.h" #include #include @@ -156,7 +157,7 @@ bool noSEH = false; // Used for /opt:lldlto=N - unsigned ltoo = 2; + llvm::OptimizationLevel ltoo = llvm::OptimizationLevel::O2; // Used for /opt:lldltojobs=N std::string thinLTOJobs; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -36,6 +36,7 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -1613,7 +1614,12 @@ ltoDebugPM = false; } else if (s.startswith("lldlto=")) { StringRef optLevel = s.substr(7); - if (optLevel.getAsInteger(10, config->ltoo) || config->ltoo > 3) + Optional OL; + if (optLevel.size() == 1) + OL = OptimizationLevel::forChar(optLevel[0]); + if (OL) + config->ltoo = *OL; + else error("/opt:lldlto: invalid optimization level: " + optLevel); } else if (s.startswith("lldltojobs=")) { StringRef jobs = s.substr(11); diff --git a/lld/Common/Args.cpp b/lld/Common/Args.cpp --- a/lld/Common/Args.cpp +++ b/lld/Common/Args.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/Path.h" using namespace llvm; @@ -19,13 +20,27 @@ // TODO(sbc): Remove this once CGOptLevel can be set completely based on bitcode // function metadata. -CodeGenOpt::Level lld::args::getCGOptLevel(int optLevelLTO) { - if (optLevelLTO == 3) +CodeGenOpt::Level lld::args::getCGOptLevel(OptimizationLevel optLevelLTO) { + if (optLevelLTO.getSpeedupLevel() == 3) return CodeGenOpt::Aggressive; - assert(optLevelLTO < 3); return CodeGenOpt::Default; } +OptimizationLevel args::getOptLevel(llvm::opt::InputArgList &args, + unsigned int key, + llvm::OptimizationLevel Default) { + Optional OL; + if (opt::Arg *arg = args.getLastArg(key)) { + std::string lto = arg->getValue(); + if (lto.size() == 1) + OL = llvm::OptimizationLevel::forChar(lto[0]); + if (!OL) + error("invalid optimization level for LTO: " + lto); + return OL.getValueOr(Default); + } + return Default; +} + static int64_t getInteger(opt::InputArgList &args, unsigned key, int64_t Default, unsigned base) { auto *a = args.getLastArg(key); diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt --- a/lld/Common/CMakeLists.txt +++ b/lld/Common/CMakeLists.txt @@ -49,6 +49,7 @@ Demangle MC Option + Passes Support Target diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Endian.h" @@ -273,7 +274,7 @@ uint64_t mipsGotSize; uint64_t zStackSize; unsigned ltoPartitions; - unsigned ltoo; + llvm::OptimizationLevel ltoo; unsigned optimize; StringRef thinLTOJobs; unsigned timeTraceGranularity; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -49,6 +49,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" #include "llvm/LTO/LTO.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" @@ -1069,7 +1070,8 @@ config->ltoWholeProgramVisibility = args.hasFlag(OPT_lto_whole_program_visibility, OPT_no_lto_whole_program_visibility, false); - config->ltoo = args::getInteger(args, OPT_lto_O, 2); + config->ltoo = + args::getOptLevel(args, OPT_lto_O, llvm::OptimizationLevel::O2); config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile); @@ -1274,8 +1276,6 @@ if (auto *arg = args.getLastArg(OPT_thinlto_jobs)) config->thinLTOJobs = arg->getValue(); - if (config->ltoo > 3) - error("invalid optimization level for LTO: " + Twine(config->ltoo)); if (config->ltoPartitions == 0) error("--lto-partitions: number of threads must be > 0"); if (!get_threadpool_strategy(config->thinLTOJobs)) diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -132,8 +132,8 @@ c.MAttrs = getMAttrs(); c.CGOptLevel = args::getCGOptLevel(config->ltoo); - c.PTO.LoopVectorization = c.OptLevel > 1; - c.PTO.SLPVectorization = c.OptLevel > 1; + c.PTO.LoopVectorization = c.OptLevel.getSpeedupLevel() > 1; + c.PTO.SLPVectorization = c.OptLevel.getSpeedupLevel() > 1; // Set up a custom pipeline if we've been asked to. c.OptPipeline = std::string(config->ltoNewPmPasses); diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -15,6 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/VersionTuple.h" @@ -142,7 +143,7 @@ llvm::StringRef ltoObjPath; llvm::StringRef thinLTOJobs; llvm::StringRef umbrella; - uint32_t ltoo = 2; + llvm::OptimizationLevel ltoo = llvm::OptimizationLevel::O2; llvm::CachePruningPolicy thinLTOCachePolicy; llvm::StringRef thinLTOCacheDir; bool deadStripDylibs = false; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1234,9 +1234,8 @@ config->ltoNewPassManager = args.hasFlag(OPT_no_lto_legacy_pass_manager, OPT_lto_legacy_pass_manager, LLVM_ENABLE_NEW_PASS_MANAGER); - config->ltoo = args::getInteger(args, OPT_lto_O, 2); - if (config->ltoo > 3) - error("--lto-O: invalid optimization level: " + Twine(config->ltoo)); + config->ltoo = + args::getOptLevel(args, OPT_lto_O, llvm::OptimizationLevel::O2); config->thinLTOCacheDir = args.getLastArgValue(OPT_cache_path_lto); config->thinLTOCachePolicy = getLTOCachePolicy(args); config->runtimePaths = args::getStrings(args, OPT_rpath); diff --git a/lld/include/lld/Common/Args.h b/lld/include/lld/Common/Args.h --- a/lld/include/lld/Common/Args.h +++ b/lld/include/lld/Common/Args.h @@ -10,6 +10,7 @@ #define LLD_ARGS_H #include "lld/Common/LLVM.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -23,7 +24,9 @@ namespace lld { namespace args { -llvm::CodeGenOpt::Level getCGOptLevel(int optLevelLTO); +llvm::CodeGenOpt::Level getCGOptLevel(llvm::OptimizationLevel optLevelLTO); +llvm::OptimizationLevel getOptLevel(llvm::opt::InputArgList &args, unsigned key, + llvm::OptimizationLevel Default); int64_t getInteger(llvm::opt::InputArgList &args, unsigned key, int64_t Default); diff --git a/lld/test/COFF/lto-opt-level.ll b/lld/test/COFF/lto-opt-level.ll --- a/lld/test/COFF/lto-opt-level.ll +++ b/lld/test/COFF/lto-opt-level.ll @@ -4,8 +4,17 @@ ; RUN: FileCheck --check-prefix=CHECK-O0 %s < %t0.map ; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /lldmap:%t2.map %t.obj ; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2.map +; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=s /lldmap:%t2.map %t.obj +; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2.map +; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=z /lldmap:%t2.map %t.obj +; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2.map ; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /lldmap:%t2a.map %t.obj ; RUN: FileCheck --check-prefix=CHECK-O2 %s < %t2a.map +; RUN: not lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=a /lldmap:%t2.map %t.obj 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR-A +; RUN: not lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=abc /lldmap:%t2.map %t.obj 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR-ABC + +; CHECK-ERROR-A: invalid optimization level: a +; CHECK-ERROR-ABC: invalid optimization level: abc target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" diff --git a/lld/test/ELF/lto/opt-level.ll b/lld/test/ELF/lto/opt-level.ll --- a/lld/test/ELF/lto/opt-level.ll +++ b/lld/test/ELF/lto/opt-level.ll @@ -10,6 +10,10 @@ ; RUN: llvm-nm %t2a | FileCheck --check-prefix=CHECK-O2 %s ; RUN: ld.lld -o %t2 -e main %t.o --plugin-opt O2 ; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s +; RUN: ld.lld -o %t2 -e main --lto-Os %t.o +; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s +; RUN: ld.lld -o %t2 -e main --lto-Oz %t.o +; RUN: llvm-nm %t2 | FileCheck --check-prefix=CHECK-O2 %s ; Reject invalid optimization levels. ; RUN: not ld.lld -o /dev/null -e main --lto-O6 %t.o 2>&1 | \ @@ -19,14 +23,14 @@ ; RUN: FileCheck --check-prefix=INVALID1 %s ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=Ofoo %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALID2 %s -; INVALID2: --plugin-opt=Ofoo: number expected, but got 'foo' +; INVALID2: invalid optimization level for LTO: foo ; RUN: not ld.lld -o /dev/null -e main --lto-O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE1 %s -; INVALIDNEGATIVE1: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE1: invalid optimization level for LTO: -1 ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE2 %s -; INVALIDNEGATIVE2: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE2: invalid optimization level for LTO: -1 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lld/test/MachO/lto-opt-level.ll b/lld/test/MachO/lto-opt-level.ll --- a/lld/test/MachO/lto-opt-level.ll +++ b/lld/test/MachO/lto-opt-level.ll @@ -9,6 +9,12 @@ ; RUN: %lld %t/test.o --lto-O2 -o %t/test ; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes=CHECK-O2 +; RUN: %lld %t/test.o --lto-Os -o %t/test +; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes=CHECK-O2 + +; RUN: %lld %t/test.o --lto-Oz -o %t/test +; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes=CHECK-O2 + ; RUN: %lld %t/test.o -o %t/test ; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes=CHECK-O2 diff --git a/lld/test/wasm/lto/opt-level.ll b/lld/test/wasm/lto/opt-level.ll --- a/lld/test/wasm/lto/opt-level.ll +++ b/lld/test/wasm/lto/opt-level.ll @@ -3,6 +3,10 @@ ; RUN: obj2yaml %t0 | FileCheck --check-prefix=CHECK-O0 %s ; RUN: wasm-ld -o %t2 -e main --lto-O2 %t.o ; RUN: obj2yaml %t2 | FileCheck --check-prefix=CHECK-O2 %s +; RUN: wasm-ld -o %t2 -e main --lto-Os %t.o +; RUN: obj2yaml %t2 | FileCheck --check-prefix=CHECK-O2 %s +; RUN: wasm-ld -o %t2 -e main --lto-Oz %t.o +; RUN: obj2yaml %t2 | FileCheck --check-prefix=CHECK-O2 %s ; RUN: wasm-ld -o %t2a -e main %t.o ; RUN: obj2yaml %t2a | FileCheck --check-prefix=CHECK-O2 %s @@ -13,7 +17,7 @@ ; RUN: not wasm-ld -o %t3 -e main --lto-O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s -; INVALIDNEGATIVE: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE: invalid optimization level for LTO: -1 target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown-wasm" diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/Wasm.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CachePruning.h" namespace lld { @@ -57,7 +58,7 @@ uint64_t maxMemory; uint64_t zStackSize; unsigned ltoPartitions; - unsigned ltoo; + llvm::OptimizationLevel ltoo = llvm::OptimizationLevel::O2; unsigned optimize; llvm::StringRef thinLTOJobs; bool ltoNewPassManager; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -372,7 +372,8 @@ config->sharedMemory = args.hasArg(OPT_shared_memory); config->importTable = args.hasArg(OPT_import_table); config->importUndefined = args.hasArg(OPT_import_undefined); - config->ltoo = args::getInteger(args, OPT_lto_O, 2); + config->ltoo = + args::getOptLevel(args, OPT_lto_O, llvm::OptimizationLevel::O2); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoNewPassManager = args.hasFlag(OPT_no_lto_legacy_pass_manager, OPT_lto_legacy_pass_manager, @@ -494,8 +495,6 @@ error("--compress-relocations is incompatible with output debug" " information. Please pass --strip-debug or --strip-all"); - if (config->ltoo > 3) - error("invalid optimization level for LTO: " + Twine(config->ltoo)); if (config->ltoPartitions == 0) error("--lto-partitions: number of threads must be > 0"); if (!get_threadpool_strategy(config->thinLTOJobs)) diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h --- a/llvm/include/llvm/LTO/Config.h +++ b/llvm/include/llvm/LTO/Config.h @@ -20,6 +20,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" @@ -54,7 +55,7 @@ Optional CodeModel = None; CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; CodeGenFileType CGFileType = CGFT_ObjectFile; - unsigned OptLevel = 2; + OptimizationLevel OptLevel = OptimizationLevel::O2; bool DisableVerify = false; /// Use the new pass manager diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -43,6 +43,7 @@ #include "llvm/IR/Module.h" #include "llvm/LTO/Config.h" #include "llvm/LTO/LTO.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ToolOutputFile.h" @@ -98,7 +99,7 @@ void setCpu(StringRef MCpu) { Config.CPU = std::string(MCpu); } void setAttrs(std::vector MAttrs) { Config.MAttrs = MAttrs; } - void setOptLevel(unsigned OptLevel); + void setOptLevel(OptimizationLevel OptLevel); void setShouldInternalize(bool Value) { ShouldInternalize = Value; } void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } diff --git a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h --- a/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -20,6 +20,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/LTO/LTO.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/MemoryBuffer.h" @@ -222,9 +223,7 @@ } /// IR optimization level: from 0 to 3. - void setOptLevel(unsigned NewOptLevel) { - OptLevel = (NewOptLevel > 3) ? 3 : NewOptLevel; - } + void setOptLevel(OptimizationLevel NewOptLevel) { OptLevel = NewOptLevel; } /// Enable or disable the new pass manager. void setUseNewPM(unsigned Enabled) { UseNewPM = Enabled; } @@ -346,7 +345,7 @@ bool Freestanding = false; /// IR Optimization Level [0-3]. - unsigned OptLevel = 3; + OptimizationLevel OptLevel = OptimizationLevel::O3; /// Flag to indicate whether the new pass manager should be used for IR /// optimizations. diff --git a/llvm/include/llvm/Passes/OptimizationLevel.h b/llvm/include/llvm/Passes/OptimizationLevel.h --- a/llvm/include/llvm/Passes/OptimizationLevel.h +++ b/llvm/include/llvm/Passes/OptimizationLevel.h @@ -15,6 +15,7 @@ #ifndef LLVM_PASSES_OPTIMIZATIONLEVEL_H #define LLVM_PASSES_OPTIMIZATIONLEVEL_H +#include "llvm/ADT/Optional.h" #include namespace llvm { @@ -35,6 +36,26 @@ public: OptimizationLevel() = default; + + static Optional forChar(char c) { + switch (c) { + case '0': + return O0; + case '1': + return O1; + case '2': + return O2; + case '3': + return O3; + case 's': + return Os; + case 'z': + return Oz; + default: + return Optional(); + } + } + /// Disable as many optimizations as possible. This doesn't completely /// disable the optimizer in all cases, for example always_inline functions /// can be required to be inlined for correctness. diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -132,7 +132,8 @@ AddUnsigned(-1); AddUnsigned(Conf.CGOptLevel); AddUnsigned(Conf.CGFileType); - AddUnsigned(Conf.OptLevel); + AddUnsigned(Conf.OptLevel.getSizeLevel()); + AddUnsigned(Conf.OptLevel.getSpeedupLevel()); AddUnsigned(Conf.UseNewPM); AddUnsigned(Conf.Freestanding); AddString(Conf.OptPipeline); @@ -1027,7 +1028,8 @@ return It->second; }; computeDeadSymbolsWithConstProp(ThinLTO.CombinedIndex, GUIDPreservedSymbols, - isPrevailing, Conf.OptLevel > 0); + isPrevailing, + Conf.OptLevel.getSpeedupLevel() > 0); // Setup output file to emit statistics. auto StatsFileOrErr = setupStatsFile(Conf.StatsFile); @@ -1469,7 +1471,7 @@ runWholeProgramDevirtOnIndex(ThinLTO.CombinedIndex, ExportedGUIDs, LocalWPDTargetsMap); - if (Conf.OptLevel > 0) + if (Conf.OptLevel.getSpeedupLevel() > 0) ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, ImportLists, ExportLists); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -210,8 +210,7 @@ } static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM, - unsigned OptLevel, bool IsThinLTO, - ModuleSummaryIndex *ExportSummary, + bool IsThinLTO, ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary) { Optional PGOOpt; if (!Conf.SampleProfile.empty()) @@ -274,25 +273,6 @@ if (!Conf.DisableVerify) MPM.addPass(VerifierPass()); - OptimizationLevel OL; - - switch (OptLevel) { - default: - llvm_unreachable("Invalid optimization level"); - case 0: - OL = OptimizationLevel::O0; - break; - case 1: - OL = OptimizationLevel::O1; - break; - case 2: - OL = OptimizationLevel::O2; - break; - case 3: - OL = OptimizationLevel::O3; - break; - } - // Parse a custom pipeline if asked to. if (!Conf.OptPipeline.empty()) { if (auto Err = PB.parsePassPipeline(MPM, Conf.OptPipeline)) { @@ -300,9 +280,9 @@ Conf.OptPipeline + "': " + toString(std::move(Err))); } } else if (IsThinLTO) { - MPM.addPass(PB.buildThinLTODefaultPipeline(OL, ImportSummary)); + MPM.addPass(PB.buildThinLTODefaultPipeline(Conf.OptLevel, ImportSummary)); } else { - MPM.addPass(PB.buildLTODefaultPipeline(OL, ExportSummary)); + MPM.addPass(PB.buildLTODefaultPipeline(Conf.OptLevel, ExportSummary)); } if (!Conf.DisableVerify) @@ -330,7 +310,8 @@ PMB.VerifyOutput = !Conf.DisableVerify; PMB.LoopVectorize = true; PMB.SLPVectorize = true; - PMB.OptLevel = Conf.OptLevel; + PMB.OptLevel = Conf.OptLevel.getSpeedupLevel(); + PMB.SizeLevel = Conf.OptLevel.getSizeLevel(); PMB.PGOSampleUse = Conf.SampleProfile; PMB.EnablePGOCSInstrGen = Conf.RunCSIRInstr; if (!Conf.RunCSIRInstr && !Conf.CSIRProfile.empty()) { @@ -367,8 +348,7 @@ } // FIXME: Plumb the combined index into the new pass manager. if (Conf.UseNewPM || !Conf.OptPipeline.empty()) { - runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary, - ImportSummary); + runNewPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary); } else { runOldPMPasses(Conf, Mod, TM, IsThinLTO, ExportSummary, ImportSummary); } diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -45,6 +45,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -184,11 +185,11 @@ llvm_unreachable("Unknown debug format!"); } -void LTOCodeGenerator::setOptLevel(unsigned Level) { +void LTOCodeGenerator::setOptLevel(OptimizationLevel Level) { Config.OptLevel = Level; - Config.PTO.LoopVectorization = Config.OptLevel > 1; - Config.PTO.SLPVectorization = Config.OptLevel > 1; - switch (Config.OptLevel) { + Config.PTO.LoopVectorization = Config.OptLevel.getSpeedupLevel() > 1; + Config.PTO.SLPVectorization = Config.OptLevel.getSpeedupLevel() > 1; + switch (Config.OptLevel.getSpeedupLevel()) { case 0: Config.CGOptLevel = CodeGenOpt::None; return; diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -40,6 +40,7 @@ #include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Remarks/HotnessThresholdParser.h" @@ -238,7 +239,7 @@ } static void optimizeModule(Module &TheModule, TargetMachine &TM, - unsigned OptLevel, bool Freestanding, + OptimizationLevel OptLevel, bool Freestanding, ModuleSummaryIndex *Index) { // Populate the PassManager PassManagerBuilder PMB; @@ -247,7 +248,8 @@ PMB.LibraryInfo->disableAllFunctions(); PMB.Inliner = createFunctionInliningPass(); // FIXME: should get it from the bitcode? - PMB.OptLevel = OptLevel; + PMB.OptLevel = OptLevel.getSpeedupLevel(); + PMB.SizeLevel = OptLevel.getSizeLevel(); PMB.LoopVectorize = true; PMB.SLPVectorize = true; // Already did this in verifyLoadedModule(). @@ -268,7 +270,7 @@ } static void optimizeModuleNewPM(Module &TheModule, TargetMachine &TM, - unsigned OptLevel, bool Freestanding, + OptimizationLevel OptLevel, bool Freestanding, bool DebugPassManager, ModuleSummaryIndex *Index) { Optional PGOOpt; @@ -300,26 +302,7 @@ ModulePassManager MPM; - OptimizationLevel OL; - - switch (OptLevel) { - default: - llvm_unreachable("Invalid optimization level"); - case 0: - OL = OptimizationLevel::O0; - break; - case 1: - OL = OptimizationLevel::O1; - break; - case 2: - OL = OptimizationLevel::O2; - break; - case 3: - OL = OptimizationLevel::O3; - break; - } - - MPM.addPass(PB.buildThinLTODefaultPipeline(OL, Index)); + MPM.addPass(PB.buildThinLTODefaultPipeline(OptLevel, Index)); MPM.run(TheModule, MAM); } @@ -394,7 +377,7 @@ const FunctionImporter::ImportMapTy &ImportList, const FunctionImporter::ExportSetTy &ExportList, const std::map &ResolvedODR, - const GVSummaryMapTy &DefinedGVSummaries, unsigned OptLevel, + const GVSummaryMapTy &DefinedGVSummaries, OptimizationLevel OptLevel, bool Freestanding, const TargetMachineBuilder &TMBuilder) { if (CachePath.empty()) return; @@ -483,8 +466,8 @@ const GVSummaryMapTy &DefinedGlobals, const ThinLTOCodeGenerator::CachingOptions &CacheOptions, bool DisableCodeGen, StringRef SaveTempsDir, - bool Freestanding, unsigned OptLevel, unsigned count, - bool UseNewPM, bool DebugPassManager) { + bool Freestanding, OptimizationLevel OptLevel, + unsigned count, bool UseNewPM, bool DebugPassManager) { // "Benchmark"-like optimization: single-source case bool SingleModule = (ModuleMap.size() == 1); diff --git a/llvm/test/tools/llvm-lto2/X86/opt-levels.ll b/llvm/test/tools/llvm-lto2/X86/opt-levels.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-lto2/X86/opt-levels.ll @@ -0,0 +1,42 @@ +; RUN: opt -module-summary %s -o %t1.bc + +; RUN: llvm-lto2 run %t1.bc -o %t5.o -O3 -r %t1.bc,c,plx -r %t1.bc,d,plx -r %t1.bc,f,plx -r %t1.bc,foo,plx \ +; RUN: -use-new-pm -save-temps +; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefixes=O3,CHECK + +; RUN: llvm-lto2 run %t1.bc -o %t5.o -Os -r %t1.bc,c,plx -r %t1.bc,d,plx -r %t1.bc,f,plx -r %t1.bc,foo,plx \ +; RUN: -use-new-pm -save-temps +; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefixes=OS,CHECK + +; RUN: llvm-lto2 run %t1.bc -o %t5.o -Oz -r %t1.bc,c,plx -r %t1.bc,d,plx -r %t1.bc,f,plx -r %t1.bc,foo,plx \ +; RUN: -use-new-pm -save-temps +; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefixes=OZ,CHECK + +; CHECK-LABEL: define {{.*}}@foo +; O3-NOT: call void @c +; O3-NOT: call void @d +; OS-NOT: call void @c +; OS: call void @d +; OZ: call void @c +; OZ: call void @d + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @f() + +define void @c() "function-inline-cost"="10" { + call void @f() + ret void +} + +define void @d() "function-inline-cost"="100" { + call void @f() + ret void +} + +define void @foo(i32* %a) { + call void @c() + call void @d() + ret void +} \ No newline at end of file diff --git a/llvm/test/tools/llvm-lto2/X86/slp-vectorize-pm.ll b/llvm/test/tools/llvm-lto2/X86/slp-vectorize-pm.ll --- a/llvm/test/tools/llvm-lto2/X86/slp-vectorize-pm.ll +++ b/llvm/test/tools/llvm-lto2/X86/slp-vectorize-pm.ll @@ -17,6 +17,14 @@ ; RUN: -use-new-pm -save-temps 2>&1 | FileCheck %s --check-prefix=CHECK-O3-SLP ; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-O3-LPV +; RUN: llvm-lto2 run %t1.bc -o %t5.o -Os -r %t1.bc,foo,plx -debug-pass-manager \ +; RUN: -use-new-pm -save-temps 2>&1 | FileCheck %s --check-prefix=CHECK-O3-SLP +; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-O3-LPV + +; RUN: llvm-lto2 run %t1.bc -o %t5.o -Oz -r %t1.bc,foo,plx -debug-pass-manager \ +; RUN: -use-new-pm -save-temps 2>&1 | FileCheck %s --check-prefix=CHECK-O3-SLP +; RUN: llvm-dis %t5.o.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-O3-LPV + ; CHECK-O0-SLP-NOT: Running pass: SLPVectorizerPass ; CHECK-O1-SLP-NOT: Running pass: SLPVectorizerPass ; CHECK-O2-SLP: Running pass: SLPVectorizerPass diff --git a/llvm/test/tools/lto/opt-level.ll b/llvm/test/tools/lto/opt-level.ll --- a/llvm/test/tools/lto/opt-level.ll +++ b/llvm/test/tools/lto/opt-level.ll @@ -3,6 +3,10 @@ ; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O0 %s ; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O2 -o %t.dylib %t.o -lSystem ; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O2 %s +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -Os -o %t.dylib %t.o -lSystem +; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O2 %s +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -Oz -o %t.dylib %t.o -lSystem +; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O2 %s target triple = "x86_64-apple-macosx10.8.0" diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -68,7 +68,7 @@ static cl::opt OptLevel("O", - cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + cl::desc("Optimization level. [-O0, -O1, -O2, -O3, -Os, or -Oz] " "(default = '-O2')"), cl::Prefix, cl::ZeroOrMore, cl::init('2'), cl::cat(LTOCategory)); @@ -940,9 +940,6 @@ cl::HideUnrelatedOptions({<OCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); - if (OptLevel < '0' || OptLevel > '3') - error("optimization level must be between 0 and 3"); - // Initialize the configured targets. InitializeAllTargets(); InitializeAllTargetMCs(); @@ -1065,7 +1062,11 @@ // Set cpu and attrs strings for the default target/subtarget. CodeGen.setCpu(codegen::getMCPU()); - CodeGen.setOptLevel(OptLevel - '0'); + Optional OL = OptimizationLevel::forChar(OptLevel); + if (!OL) + error("invalid optimization level: -O" + Twine(OptLevel)); + CodeGen.setOptLevel(*OL); + CodeGen.setAttrs(codegen::getMAttrs()); CodeGen.setUseNewPM(UseNewPM); diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -20,6 +20,7 @@ #include "llvm/Config/llvm-config.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/LTO/LTO.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/Caching.h" @@ -36,8 +37,9 @@ static codegen::RegisterCodeGenFlags CGF; static cl::opt - OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " - "(default = '-O2')"), + OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, -O3, -Os, or -Oz] " + "(default = '-O2')"), cl::Prefix, cl::ZeroOrMore, cl::init('2')); static cl::opt CGOptLevel( @@ -272,7 +274,12 @@ Conf.OptPipeline = OptPipeline; Conf.AAPipeline = AAPipeline; - Conf.OptLevel = OptLevel - '0'; + if (auto OL = OptimizationLevel::forChar(OptLevel)) { + Conf.OptLevel = *OL; + } else { + llvm::errs() << "invalid -O level: -O" << OptLevel << "\n"; + return 1; + } Conf.UseNewPM = UseNewPM; Conf.Freestanding = EnableFreestanding; for (auto &PluginFN : PassPlugins) @@ -301,8 +308,8 @@ Conf.OverrideTriple = OverrideTriple; Conf.DefaultTriple = DefaultTriple; Conf.StatsFile = StatsFile; - Conf.PTO.LoopVectorization = Conf.OptLevel > 1; - Conf.PTO.SLPVectorization = Conf.OptLevel > 1; + Conf.PTO.LoopVectorization = Conf.OptLevel.getSpeedupLevel() > 1; + Conf.PTO.SLPVectorization = Conf.OptLevel.getSpeedupLevel() > 1; ThinBackend Backend; if (ThinLTODistributedIndexes) diff --git a/llvm/tools/lto/lto.cpp b/llvm/tools/lto/lto.cpp --- a/llvm/tools/lto/lto.cpp +++ b/llvm/tools/lto/lto.cpp @@ -23,6 +23,7 @@ #include "llvm/LTO/legacy/LTOCodeGenerator.h" #include "llvm/LTO/legacy/LTOModule.h" #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" @@ -34,12 +35,10 @@ // extra command-line flags needed for LTOCodeGenerator static cl::opt -OptLevel("O", - cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " - "(default = '-O2')"), - cl::Prefix, - cl::ZeroOrMore, - cl::init('2')); + OptLevel("O", + cl::desc("Optimization level. [-O0, -O1, -O2, -O3, -Os, or -Oz] " + "(default = '-O2')"), + cl::Prefix, cl::ZeroOrMore, cl::init('2')); static cl::opt EnableFreestanding( "lto-freestanding", cl::init(false), @@ -152,9 +151,10 @@ LTOCodeGenerator *CG = unwrap(cg); CG->setAttrs(codegen::getMAttrs()); - if (OptLevel < '0' || OptLevel > '3') - report_fatal_error("Optimization level must be between 0 and 3"); - CG->setOptLevel(OptLevel - '0'); + Optional OL = OptimizationLevel::forChar(OptLevel); + if (!OL) + report_fatal_error("invalid optimization level: -O" + Twine(OptLevel)); + CG->setOptLevel(*OL); CG->setFreestanding(EnableFreestanding); CG->setDisableVerify(DisableVerify); } @@ -525,20 +525,21 @@ CodeGen->setFreestanding(EnableFreestanding); if (OptLevel.getNumOccurrences()) { - if (OptLevel < '0' || OptLevel > '3') - report_fatal_error("Optimization level must be between 0 and 3"); - CodeGen->setOptLevel(OptLevel - '0'); - switch (OptLevel) { - case '0': + Optional OL = OptimizationLevel::forChar(OptLevel); + if (!OL) + report_fatal_error("Invalid optimization level: " + Twine(OptLevel)); + CodeGen->setOptLevel(*OL); + switch (OL->getSpeedupLevel()) { + case 0: CodeGen->setCodeGenOptLevel(CodeGenOpt::None); break; - case '1': + case 1: CodeGen->setCodeGenOptLevel(CodeGenOpt::Less); break; - case '2': + case 2: CodeGen->setCodeGenOptLevel(CodeGenOpt::Default); break; - case '3': + case 3: CodeGen->setCodeGenOptLevel(CodeGenOpt::Aggressive); break; } diff --git a/llvm/utils/gn/secondary/lld/Common/BUILD.gn b/llvm/utils/gn/secondary/lld/Common/BUILD.gn --- a/llvm/utils/gn/secondary/lld/Common/BUILD.gn +++ b/llvm/utils/gn/secondary/lld/Common/BUILD.gn @@ -27,6 +27,7 @@ "//llvm/lib/IR", "//llvm/lib/MC", "//llvm/lib/Option", + "//llvm/lib/Passes", "//llvm/lib/Support", "//llvm/lib/Target", ]