Index: llvm/include/llvm/CodeGen/CommandFlags.inc =================================================================== --- llvm/include/llvm/CodeGen/CommandFlags.inc +++ llvm/include/llvm/CodeGen/CommandFlags.inc @@ -18,11 +18,13 @@ #include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.inc" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/ProfileData/PropellerProf.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include #include using namespace llvm; @@ -238,6 +240,12 @@ cl::desc("Emit functions into separate sections"), cl::init(false)); +static cl::opt + BBSections("basicblock-sections", + cl::desc("Emit basic blocks into separate sections"), + cl::value_desc("all | | none"), + cl::init("none")); + static cl::opt TLSSize("tls-size", cl::desc("Bit size of immediate TLS offsets"), cl::init(0)); @@ -251,6 +259,11 @@ cl::desc("Give unique names to every section"), cl::init(true)); +static cl::opt UniqueBBSectionNames( + "unique-bb-section-names", + cl::desc("Give unique names to every basic block section"), + cl::init(false)); + static cl::opt EABIVersion("meabi", cl::desc("Set EABI type (default depends on triple):"), cl::init(EABI::Default), @@ -285,6 +298,18 @@ cl::desc("Always emit a debug frame section."), cl::init(false)); +static llvm::BasicBlockSection::SectionMode +getBBSectionsMode(llvm::TargetOptions &Options) { + if (BBSections == "all") + return BasicBlockSection::All; + else if (BBSections == "labels") + return BasicBlockSection::Labels; + else if (BBSections == "none") + return BasicBlockSection::None; + llvm::propeller::getBBSectionsList(BBSections, Options.BBSectionsList); + return BasicBlockSection::List; +} + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -308,7 +333,9 @@ Options.RelaxELFRelocations = RelaxELFRelocations; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.BBSections = getBBSectionsMode(Options); Options.UniqueSectionNames = UniqueSectionNames; + Options.UniqueBBSectionNames = UniqueBBSectionNames; Options.TLSSize = TLSSize; Options.EmulatedTLS = EmulatedTLS; Options.ExplicitEmulatedTLS = EmulatedTLS.getNumOccurrences() > 0; Index: llvm/include/llvm/IR/BasicBlock.h =================================================================== --- llvm/include/llvm/IR/BasicBlock.h +++ llvm/include/llvm/IR/BasicBlock.h @@ -428,6 +428,12 @@ Optional getIrrLoopHeaderWeight() const; + /// Set the section prefix for this block. + void setSectionPrefix(StringRef Prefix); + + /// Get the section prefix for this block. + Optional getSectionPrefix() const; + private: /// Increment the internal refcount of the number of BlockAddresses /// referencing this BasicBlock by \p Amt. Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -96,6 +96,11 @@ friend class SymbolTableListTraits; + /// Whether Basic Block Sections is enabled for this function. + bool BBSections = false; + /// Whether Basic Block Labels is enabled for this function. + bool BasicBlockLabels = false; + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is /// built on demand, so that the list isn't allocated until the first client /// needs it. The hasLazyArguments predicate returns true if the arg list @@ -159,6 +164,18 @@ /// within this function. unsigned getInstructionCount() const; + /// Returns true if this function has basic block sections enabled. + bool getBBSections() const { return BBSections; } + + /// Indicates that basic block sections is enabled for this function. + void setBBSections(bool value) { BBSections = value; } + + /// Returns true if this function has basic block labels enabled. + bool getBasicBlockLabels() const { return BasicBlockLabels; } + + /// Indicates that basic block labels is enabled for this function. + void setBasicBlockLabels(bool value) { BasicBlockLabels = value; } + /// Returns the FunctionType for me. FunctionType *getFunctionType() const { return cast(getValueType()); Index: llvm/include/llvm/ProfileData/PropellerProf.h =================================================================== --- /dev/null +++ llvm/include/llvm/ProfileData/PropellerProf.h @@ -0,0 +1,20 @@ +#ifndef LLVM_PROFILEDATA_PROPELLERPROF_H +#define LLVM_PROFILEDATA_PROPELLERPROF_H + +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +using llvm::SmallSet; +using llvm::StringMap; +using llvm::StringRef; + +namespace llvm { +namespace propeller { +bool getBBSectionsList(StringRef profFileName, + StringMap> &bbMap); + +} +} // namespace llvm + +#endif Index: llvm/include/llvm/Target/TargetMachine.h =================================================================== --- llvm/include/llvm/Target/TargetMachine.h +++ llvm/include/llvm/Target/TargetMachine.h @@ -242,6 +242,9 @@ bool getUniqueSectionNames() const { return Options.UniqueSectionNames; } + /// Return true if unique basic block section names must be generated. + bool getUniqueBBSectionNames() const { return Options.UniqueBBSectionNames; } + /// Return true if data objects should be emitted into their own section, /// corresponds to -fdata-sections. bool getDataSections() const { @@ -254,6 +257,24 @@ return Options.FunctionSections; } + /// If basic blocks should be emitted into their own section, + /// corresponding to -fbasicblock-sections. + llvm::BasicBlockSection::SectionMode getBBSections() const { + return Options.BBSections; + } + + /// Return true if a given function's name in the list of functions for which + /// basic block sections must be generated. + bool isFunctionInBBSectionsList(const StringRef &name) const { + return Options.BBSectionsList.find(name) != Options.BBSectionsList.end(); + } + + /// For a given function, return the set of basic block id's that must be + /// emitted in a unique section. + SmallSet getBBSectionsSet(const StringRef &name) const { + return Options.BBSectionsList.lookup(name); + } + /// Get a \c TargetIRAnalysis appropriate for the target. /// /// This is used to construct the new pass manager's target IR analysis pass, Index: llvm/include/llvm/Target/TargetOptions.h =================================================================== --- llvm/include/llvm/Target/TargetOptions.h +++ llvm/include/llvm/Target/TargetOptions.h @@ -14,6 +14,8 @@ #ifndef LLVM_TARGET_TARGETOPTIONS_H #define LLVM_TARGET_TARGETOPTIONS_H +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" #include "llvm/MC/MCTargetOptions.h" namespace llvm { @@ -63,6 +65,15 @@ }; } + namespace BasicBlockSection { + enum SectionMode { + None, // Do not use Basic Block Sections. + All, // Use Basic Block Sections for all functions. + Labels, // Do not use Basic Block Sections but label basic blocks. + List // Get list of functions & BBs from a file + }; + } + enum class EABI { Unknown, Default, // Default means not specified @@ -114,9 +125,9 @@ EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), DisableIntegratedAS(false), RelaxELFRelocations(false), FunctionSections(false), DataSections(false), - UniqueSectionNames(true), TrapUnreachable(false), - NoTrapAfterNoreturn(false), TLSSize(0), EmulatedTLS(false), - ExplicitEmulatedTLS(false), EnableIPRA(false), + UniqueSectionNames(true), UniqueBBSectionNames(false), + TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0), + EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), SupportsDefaultOutlining(false), EmitAddrsig(false), EnableDebugEntryValues(false), ForceDwarfFrameSection(false) {} @@ -224,6 +235,9 @@ unsigned UniqueSectionNames : 1; + /// Use unique names for basic block sections. + unsigned UniqueBBSectionNames : 1; + /// Emit target-specific trap instruction for 'unreachable' IR instructions. unsigned TrapUnreachable : 1; @@ -256,6 +270,13 @@ /// Emit address-significance table. unsigned EmitAddrsig : 1; + /// Emit basic blocks into separate sections. + BasicBlockSection::SectionMode BBSections = BasicBlockSection::None; + + /// A map from function name to a set of basic block id's that require + /// unique basic block sections. + StringMap> BBSectionsList; + /// Emit debug info about parameter's entry values. unsigned EnableDebugEntryValues : 1; Index: llvm/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -441,6 +441,24 @@ BFI.reset(new BlockFrequencyInfo(F, *BPI, *LI)); PSI = &getAnalysis().getPSI(); OptSize = F.hasOptSize(); + + /// Check if basic block sections must be enabled for this function. + /// Two basic block section modes are supported: + /// 1. "All" mode where where every block is placed in a separate section. + /// 2. "List" mode where the list of functions that needs sections is + /// specified in a file. + if (TM && TM->getBBSections() == llvm::BasicBlockSection::All) + F.setBBSections(true); + + if (TM && TM->getBBSections() == llvm::BasicBlockSection::List && + TM->isFunctionInBBSectionsList(F.getName())) + F.setBBSections(true); + + /// Check if basic block labels must be enabled for this function. Each + /// basic block in this function gets a unique symbol (label). + if (TM && TM->getBBSections() == llvm::BasicBlockSection::Labels) + F.setBasicBlockLabels(true); + if (ProfileGuidedSectionPrefix) { if (PSI->isFunctionHotInCallGraph(&F, *BFI)) F.setSectionPrefix(".hot"); Index: llvm/lib/ProfileData/CMakeLists.txt =================================================================== --- llvm/lib/ProfileData/CMakeLists.txt +++ llvm/lib/ProfileData/CMakeLists.txt @@ -4,6 +4,7 @@ InstrProfReader.cpp InstrProfWriter.cpp ProfileSummaryBuilder.cpp + PropellerProf.cpp SampleProf.cpp SampleProfReader.cpp SampleProfWriter.cpp Index: llvm/lib/ProfileData/PropellerProf.cpp =================================================================== --- /dev/null +++ llvm/lib/ProfileData/PropellerProf.cpp @@ -0,0 +1,63 @@ +#include "llvm/ProfileData/PropellerProf.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +#include +#include + +using llvm::SmallSet; +using llvm::StringMap; +using llvm::StringRef; + +namespace llvm { +namespace propeller { + +// Basic Block Sections can be enabled for a subset of machine basic blocks. +// This is done by passing a file containing names of functions for which basic +// block sections are desired. Additionally, machine basic block ids of the +// functions can also be specified for a finer granularity. +// A file with basic block sections for all of function main and two blocks for +// function foo looks like this: +// ---------------------------- +// list.txt: +// !main +// !foo +// !!2 +// !!4 +bool getBBSectionsList(StringRef profFileName, + StringMap> &bbMap) { + if (profFileName.empty()) + return false; + + std::ifstream fin(profFileName); + if (!fin.good()) + return false; + + StringMap>::iterator fi = bbMap.end(); + std::string line; + while ((std::getline(fin, line)).good()) { + StringRef S(line); + // Lines beginning with @, # are not useful here. + if (S.empty() || S[0] == '@' || S[0] == '#') + continue; + if (!S.consume_front("!") || S.empty()) + break; + if (S.consume_front("!")) { + if (fi != bbMap.end()) + fi->second.insert(std::stoi(S)); + else + return false; + } else { + // Start a new function. + auto R = bbMap.try_emplace(S.split('/').first); + fi = R.first; + assert(R.second); + } + } + return true; +} + +} // namespace propeller +} // namespace llvm