Index: lld/ELF/CMakeLists.txt =================================================================== --- lld/ELF/CMakeLists.txt +++ lld/ELF/CMakeLists.txt @@ -32,6 +32,7 @@ InputFiles.cpp InputSection.cpp LTO.cpp + LinkerPropeller.cpp LinkerScript.cpp MapFile.cpp MarkLive.cpp Index: lld/ELF/Config.h =================================================================== --- lld/ELF/Config.h +++ lld/ELF/Config.h @@ -108,6 +108,18 @@ llvm::StringRef optRemarksPasses; llvm::StringRef optRemarksFormat; llvm::StringRef progName; + llvm::StringRef propeller; + llvm::StringRef propellerDumpSymbolOrder; + uint64_t propellerFallthroughWeight; + uint64_t propellerForwardJumpWeight; + uint64_t propellerBackwardJumpWeight; + uint64_t propellerClusterMergeSizeThreshold; + uint64_t propellerForwardJumpDistance; + uint64_t propellerBackwardJumpDistance; + uint64_t propellerChainSplitThreshold; + std::vector propellerDumpCfgs; + std::vector propellerDebugSymbols; + std::vector propellerOpts; llvm::StringRef printSymbolOrder; llvm::StringRef soName; llvm::StringRef sysroot; @@ -181,6 +193,12 @@ bool pie; bool printGcSections; bool printIcfSections; + bool propellerKeepNamedSymbols; + bool propellerPrintStats; + bool propellerReorderIP = false; + bool propellerReorderBlocks; + bool propellerReorderFuncs; + bool propellerSplitFuncs; bool relocatable; bool relrPackDynRelocs; bool saveTemps; Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -27,6 +27,7 @@ #include "ICF.h" #include "InputFiles.h" #include "InputSection.h" +#include "LinkerPropeller.h" #include "LinkerScript.h" #include "MarkLive.h" #include "OutputSections.h" @@ -955,6 +956,77 @@ args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order); + + config->propeller = args.getLastArgValue(OPT_propeller); + + config->propellerKeepNamedSymbols = + args.hasFlag(OPT_propeller_keep_named_symbols, + OPT_no_propeller_keep_named_symbols, false); + + config->propellerClusterMergeSizeThreshold = args::getInteger( + args, OPT_propeller_cluster_merge_size_threshold, 1 << 21); + + config->propellerDumpSymbolOrder = + args.getLastArgValue(OPT_propeller_dump_symbol_order); + + config->propellerPrintStats = args.hasFlag( + OPT_propeller_print_stats, OPT_no_propeller_print_stats, false); + + config->propellerDumpCfgs = args::getStrings(args, OPT_propeller_dump_cfg); + + config->propellerDebugSymbols = + args::getStrings(args, OPT_propeller_debug_symbol); + + config->propellerReorderBlocks = config->propellerReorderFuncs = + config->propellerSplitFuncs = !config->propeller.empty(); + + config->propellerFallthroughWeight = + args::getInteger(args, OPT_propeller_fallthrough_weight, 10); + config->propellerForwardJumpWeight = + args::getInteger(args, OPT_propeller_forward_jump_weight, 1); + config->propellerBackwardJumpWeight = + args::getInteger(args, OPT_propeller_backward_jump_weight, 1); + + config->propellerForwardJumpDistance = + args::getInteger(args, OPT_propeller_forward_jump_distance, 1024); + config->propellerBackwardJumpDistance = + args::getInteger(args, OPT_propeller_backward_jump_distance, 640); + config->propellerChainSplitThreshold = + args::getInteger(args, OPT_propeller_chain_split_threshold, 1024); + + // Parse Propeller flags. + auto propellerOpts = args::getStrings(args, OPT_propeller_opt); + bool splitFuncsExplicit = false; + for (auto &propellerOpt : propellerOpts) { + if (propellerOpt == "reorder-ip") { + config->propellerReorderIP = true; + } else if (propellerOpt == "reorder-funcs") { + config->propellerReorderFuncs = true; + } else if (propellerOpt == "no-reorder-funcs") { + config->propellerReorderFuncs = false; + } else if (propellerOpt == "reorder-blocks") { + config->propellerReorderBlocks = true; + } else if (propellerOpt == "no-reorder-blocks") { + config->propellerReorderBlocks = false; + } else if (propellerOpt == "split-funcs") { + config->propellerSplitFuncs = true; + splitFuncsExplicit = true; + } else if (propellerOpt == "no-split-funcs") { + config->propellerSplitFuncs = false; + } else + error("unknown propeller option: " + propellerOpt); + } + + if (!config->propeller.empty() && !config->propellerReorderBlocks) { + if (splitFuncsExplicit) { + error("propeller: Inconsistent combination of propeller optimizations" + " 'split-funcs' and 'no-reorder-blocks'."); + } else { + warn("propeller: no-reorder-blocks implicitly sets no-split-funcs."); + config->propellerSplitFuncs = false; + } + } + config->rpath = getRpath(args); config->relocatable = args.hasArg(OPT_relocatable); config->saveTemps = args.hasArg(OPT_save_temps); @@ -1934,6 +2006,8 @@ for (InputSectionBase *s : f->getSections()) inputSections.push_back(cast(s)); + lld::propeller::doPropeller(); + llvm::erase_if(inputSections, [](InputSectionBase *s) { if (s->type == SHT_LLVM_SYMPART) { readSymbolPartitionSection(s); Index: lld/ELF/LinkerPropeller.h =================================================================== --- /dev/null +++ lld/ELF/LinkerPropeller.h @@ -0,0 +1,33 @@ +//===- LinkerPropeller.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the interface between LLD/ELF and Propeller. All interactions +// between LLD/ELF and propeller must be defined here. +// +// All dependencies on lld/ELF/*.h must happen in this file and +// LinkerPropeller.cpp. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ELF_LINKER_PROPELLER_H +#define LLD_ELF_LINKER_PROPELLER_H + +#include "llvm/ADT/StringRef.h" + +namespace lld { +namespace propeller { +// Propeller interface to lld. +void doPropeller(); + +// Returns true if this is a BB symbol and shall be kept in the final binary's +// strtab. +bool isBBSymbolAndKeepIt(llvm::StringRef N); +} // namespace propeller +} // namespace lld + +#endif Index: lld/ELF/LinkerPropeller.cpp =================================================================== --- /dev/null +++ lld/ELF/LinkerPropeller.cpp @@ -0,0 +1,54 @@ +//===- LinkerPropeller.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is the implementation of interface between LLD/ELF and Propeller. +// +// Current implementation first copies propeller parameters from +// lld::elf::Config instances into PropellerConfig. Then it transforms the +// vector into vector. +// +// "doPropeller" then passes PropellerConfig and vector to Propeller +// instance, and finally, after Propeller is done with its work, doPropeller +// passes the resulting symboll ordering back to lld. +// +// In summary, the dependencies of Propeller are: +// - a set of "lld::elf::InputFile"s. +// - command line arguments in lld::elf::Config +// - lld's being able to arrange section orders according to a vector of +// symbol names. +// +// All lld/ELF/Propeller/* only uses headers from lld/include, and llvm/include. +// +//===----------------------------------------------------------------------===// + +#include "LinkerPropeller.h" + +#include "Config.h" + +namespace lld { +namespace propeller { + +// Propeller framework entrance. +void doPropeller() { + if (lld::elf::config->propeller.empty()) + return; + + // Propeller work starts here. In next CL. + + // prop = make(); + // ... + // ... + // ... +} + +bool isBBSymbolAndKeepIt(llvm::StringRef name) { + // Real work done in next CL. + return false; +} +} // namespace propeller +} // namespace lld Index: lld/ELF/Options.td =================================================================== --- lld/ELF/Options.td +++ lld/ELF/Options.td @@ -296,6 +296,51 @@ defm print_symbol_order: Eq<"print-symbol-order", "Print a symbol order specified by --call-graph-ordering-file into the specified file">; +defm propeller: Eq<"propeller", "Propeller profile">; + +defm propeller_opt: Eq<"propeller-opt", + "Propeller optimization flags: reorder-blocks, reorder-funcs, and split-funcs is on by the default when -propeller is specified.">, + MetaVarName<"[reorder-ip, no-reorder-ip, reorder-blocks, no-reorder-blocks, reorder-funcs, no-reorder-funcs, split-funcs, no-split-funcs]">; + +defm propeller_keep_named_symbols: B<"propeller-keep-named-symbols", + "Do not delete basic block section symbols", + "Delete unused basic block section symbols (default)">; + +defm propeller_print_stats: B<"propeller-print-stats", + "Print propeller statistics.", + "Do not print propeller statistics (default)">; + +defm propeller_cluster_merge_size_threshold: Eq<"propeller-cluster-merge-size-threshold", + "Maximum size of a cluster which could be merged with other clusters (default: 2M).">; + +defm propeller_dump_symbol_order: Eq<"propeller-dump-symbol-order", + "Dump the propeller-generated symbol ordering into the file.">, + MetaVarName<"">; + +defm propeller_dump_cfg: Eq<"propeller-dump-cfg", + "Dump the cfg of the function in DOT format (in a file named the same as the function).">; + +defm propeller_debug_symbol: Eq<"propeller-debug-symbol", + "Print information about propeller actions related to the given symbol.">; + +defm propeller_fallthrough_weight: Eq<"propeller-fallthrough-weight", + "Fallthrough weight parameter to use in ExtTSP algorithm (default: 10).">; + +defm propeller_forward_jump_weight: Eq<"propeller-forward-jump-weight", + "(Near) forward jump weight parameter to use in ExtTSP algorithm (default: 1).">; + +defm propeller_backward_jump_weight: Eq<"propeller-backward-jump-weight", + "(Near) backward jump weight parameter to use in ExtTSP algorithm (default: 1).">; + +defm propeller_forward_jump_distance: Eq<"propeller-forward-jump-distance", + "Maximum distance for a forward jump in ExtTSP algorithm (default: 1024).">; + +defm propeller_backward_jump_distance: Eq<"propeller-backward-jump-distance", + "Maximum distance for a backward jump in ExtTSP algorithm (default: 640).">; + +defm propeller_chain_split_threshold: Eq<"propeller-chain-split-threshold", + "Maximum binary size of a chain which could be split in ExtTSP algorithm (default: 1024).">; + def pop_state: F<"pop-state">, HelpText<"Undo the effect of -push-state">;