|  | //===-- llvm/CodeGen/RenderMachineFunction.h - MF->HTML -*- C++ -*---------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_CODEGEN_RENDERMACHINEFUNCTION_H | 
|  | #define LLVM_CODEGEN_RENDERMACHINEFUNCTION_H | 
|  |  | 
|  | #include "llvm/CodeGen/LiveInterval.h" | 
|  | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | #include "llvm/CodeGen/SlotIndexes.h" | 
|  | #include "llvm/Target/TargetRegisterInfo.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <map> | 
|  | #include <set> | 
|  | #include <string> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class LiveInterval; | 
|  | class LiveIntervals; | 
|  | class MachineInstr; | 
|  | class MachineRegisterInfo; | 
|  | class RenderMachineFunction; | 
|  | class TargetRegisterClass; | 
|  | class TargetRegisterInfo; | 
|  | class VirtRegMap; | 
|  | class raw_ostream; | 
|  |  | 
|  | /// \brief Helper class to process rendering options. Tries to be as lazy as | 
|  | ///        possible. | 
|  | class MFRenderingOptions { | 
|  | public: | 
|  |  | 
|  | struct RegClassComp { | 
|  | bool operator()(const TargetRegisterClass *trc1, | 
|  | const TargetRegisterClass *trc2) const { | 
|  | std::string trc1Name(trc1->getName()), trc2Name(trc2->getName()); | 
|  | return std::lexicographical_compare(trc1Name.begin(), trc1Name.end(), | 
|  | trc2Name.begin(), trc2Name.end()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | typedef std::set<const TargetRegisterClass*, RegClassComp> RegClassSet; | 
|  |  | 
|  | struct IntervalComp { | 
|  | bool operator()(const LiveInterval *li1, const LiveInterval *li2) const { | 
|  | return li1->reg < li2->reg; | 
|  | } | 
|  | }; | 
|  |  | 
|  | typedef std::set<const LiveInterval*, IntervalComp> IntervalSet; | 
|  |  | 
|  | /// Initialise the rendering options. | 
|  | void setup(MachineFunction *mf, const TargetRegisterInfo *tri, | 
|  | LiveIntervals *lis, const RenderMachineFunction *rmf); | 
|  |  | 
|  | /// Clear translations of options to the current function. | 
|  | void clear(); | 
|  |  | 
|  | /// Reset any options computed for this specific rendering. | 
|  | void resetRenderSpecificOptions(); | 
|  |  | 
|  | /// Should we render the current function. | 
|  | bool shouldRenderCurrentMachineFunction() const; | 
|  |  | 
|  | /// Return the set of register classes to render pressure for. | 
|  | const RegClassSet& regClasses() const; | 
|  |  | 
|  | /// Return the set of live intervals to render liveness for. | 
|  | const IntervalSet& intervals() const; | 
|  |  | 
|  | /// Render indexes which are not associated with instructions / MBB starts. | 
|  | bool renderEmptyIndexes() const; | 
|  |  | 
|  | /// Return whether or not to render using SVG for fancy vertical text. | 
|  | bool fancyVerticals() const; | 
|  |  | 
|  | private: | 
|  |  | 
|  | static bool renderingOptionsProcessed; | 
|  | static std::set<std::string> mfNamesToRender; | 
|  | static bool renderAllMFs; | 
|  |  | 
|  | static std::set<std::string> classNamesToRender; | 
|  | static bool renderAllClasses; | 
|  |  | 
|  |  | 
|  | static std::set<std::pair<unsigned, unsigned> > intervalNumsToRender; | 
|  | typedef enum { ExplicitOnly     = 0, | 
|  | AllPhys          = 1, | 
|  | VirtNoSpills     = 2, | 
|  | VirtSpills       = 4, | 
|  | AllVirt          = 6, | 
|  | All              = 7 } | 
|  | IntervalTypesToRender; | 
|  | static unsigned intervalTypesToRender; | 
|  |  | 
|  | template <typename OutputItr> | 
|  | static void splitComaSeperatedList(const std::string &s, OutputItr outItr); | 
|  |  | 
|  | static void processOptions(); | 
|  |  | 
|  | static void processFuncNames(); | 
|  | static void processRegClassNames(); | 
|  | static void processIntervalNumbers(); | 
|  |  | 
|  | static void processIntervalRange(const std::string &intervalRangeStr); | 
|  |  | 
|  | MachineFunction *mf; | 
|  | const TargetRegisterInfo *tri; | 
|  | LiveIntervals *lis; | 
|  | const RenderMachineFunction *rmf; | 
|  |  | 
|  | mutable bool regClassesTranslatedToCurrentFunction; | 
|  | mutable RegClassSet regClassSet; | 
|  |  | 
|  | mutable bool intervalsTranslatedToCurrentFunction; | 
|  | mutable IntervalSet intervalSet; | 
|  |  | 
|  | void translateRegClassNamesToCurrentFunction() const; | 
|  |  | 
|  | void translateIntervalNumbersToCurrentFunction() const; | 
|  | }; | 
|  |  | 
|  | /// \brief Provide extra information about the physical and virtual registers | 
|  | ///        in the function being compiled. | 
|  | class TargetRegisterExtraInfo { | 
|  | public: | 
|  | TargetRegisterExtraInfo(); | 
|  |  | 
|  | /// \brief Set up TargetRegisterExtraInfo with pointers to necessary | 
|  | ///        sources of information. | 
|  | void setup(MachineFunction *mf, MachineRegisterInfo *mri, | 
|  | const TargetRegisterInfo *tri, LiveIntervals *lis); | 
|  |  | 
|  | /// \brief Recompute tables for changed function. | 
|  | void reset(); | 
|  |  | 
|  | /// \brief Free all tables in TargetRegisterExtraInfo. | 
|  | void clear(); | 
|  |  | 
|  | /// \brief Maximum number of registers from trc which alias reg. | 
|  | unsigned getWorst(unsigned reg, const TargetRegisterClass *trc) const; | 
|  |  | 
|  | /// \brief Returns the number of allocable registers in trc. | 
|  | unsigned getCapacity(const TargetRegisterClass *trc) const; | 
|  |  | 
|  | /// \brief Return the number of registers of class trc that may be | 
|  | ///        needed at slot i. | 
|  | unsigned getPressureAtSlot(const TargetRegisterClass *trc, | 
|  | SlotIndex i) const; | 
|  |  | 
|  | /// \brief Return true if the number of registers of type trc that may be | 
|  | ///        needed at slot i is greater than the capacity of trc. | 
|  | bool classOverCapacityAtSlot(const TargetRegisterClass *trc, | 
|  | SlotIndex i) const; | 
|  |  | 
|  | private: | 
|  |  | 
|  | MachineFunction *mf; | 
|  | MachineRegisterInfo *mri; | 
|  | const TargetRegisterInfo *tri; | 
|  | LiveIntervals *lis; | 
|  |  | 
|  | typedef std::map<const TargetRegisterClass*, unsigned> WorstMapLine; | 
|  | typedef std::map<const TargetRegisterClass*, WorstMapLine> VRWorstMap; | 
|  | VRWorstMap vrWorst; | 
|  |  | 
|  | typedef std::map<unsigned, WorstMapLine> PRWorstMap; | 
|  | PRWorstMap prWorst; | 
|  |  | 
|  | typedef std::map<const TargetRegisterClass*, unsigned> CapacityMap; | 
|  | CapacityMap capacityMap; | 
|  |  | 
|  | typedef std::map<const TargetRegisterClass*, unsigned> PressureMapLine; | 
|  | typedef std::map<SlotIndex, PressureMapLine> PressureMap; | 
|  | PressureMap pressureMap; | 
|  |  | 
|  | bool mapsPopulated; | 
|  |  | 
|  | /// \brief Initialise the 'worst' table. | 
|  | void initWorst(); | 
|  |  | 
|  | /// \brief Initialise the 'capacity' table. | 
|  | void initCapacity(); | 
|  |  | 
|  | /// \brief Initialise/Reset the 'pressure' and live states tables. | 
|  | void resetPressureAndLiveStates(); | 
|  | }; | 
|  |  | 
|  | /// \brief Render MachineFunction objects and related information to a HTML | 
|  | ///        page. | 
|  | class RenderMachineFunction : public MachineFunctionPass { | 
|  | public: | 
|  | static char ID; | 
|  |  | 
|  | RenderMachineFunction() : MachineFunctionPass(ID) { | 
|  | initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | virtual void getAnalysisUsage(AnalysisUsage &au) const; | 
|  |  | 
|  | virtual bool runOnMachineFunction(MachineFunction &fn); | 
|  |  | 
|  | virtual void releaseMemory(); | 
|  |  | 
|  | void rememberUseDefs(const LiveInterval *li); | 
|  |  | 
|  | void rememberSpills(const LiveInterval *li, | 
|  | const std::vector<LiveInterval*> &spills); | 
|  |  | 
|  | bool isSpill(const LiveInterval *li) const; | 
|  |  | 
|  | /// \brief Render this machine function to HTML. | 
|  | /// | 
|  | /// @param renderContextStr This parameter will be included in the top of | 
|  | ///                         the html file to explain where (in the | 
|  | ///                         codegen pipeline) this function was rendered | 
|  | ///                         from. Set it to something like | 
|  | ///                         "Pre-register-allocation". | 
|  | /// @param vrm              If non-null the VRM will be queried to determine | 
|  | ///                         whether a virtual register was allocated to a | 
|  | ///                         physical register or spilled. | 
|  | /// @param renderFilePrefix This string will be appended to the function | 
|  | ///                         name (before the output file suffix) to enable | 
|  | ///                         multiple renderings from the same function. | 
|  | void renderMachineFunction(const char *renderContextStr, | 
|  | const VirtRegMap *vrm = 0, | 
|  | const char *renderSuffix = 0); | 
|  |  | 
|  | private: | 
|  | class Spacer; | 
|  | friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s); | 
|  |  | 
|  | std::string fqn; | 
|  |  | 
|  | MachineFunction *mf; | 
|  | MachineRegisterInfo *mri; | 
|  | const TargetRegisterInfo *tri; | 
|  | LiveIntervals *lis; | 
|  | SlotIndexes *sis; | 
|  | const VirtRegMap *vrm; | 
|  |  | 
|  | TargetRegisterExtraInfo trei; | 
|  | MFRenderingOptions ro; | 
|  |  | 
|  |  | 
|  |  | 
|  | // Utilities. | 
|  | typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState; | 
|  | LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const; | 
|  |  | 
|  | typedef enum { Zero, Low, High } PressureState; | 
|  | PressureState getPressureStateAt(const TargetRegisterClass *trc, | 
|  | SlotIndex i) const; | 
|  |  | 
|  | typedef std::map<const LiveInterval*, std::set<const LiveInterval*> > | 
|  | SpillIntervals; | 
|  | SpillIntervals spillIntervals; | 
|  |  | 
|  | typedef std::map<const LiveInterval*, const LiveInterval*> SpillForMap; | 
|  | SpillForMap spillFor; | 
|  |  | 
|  | typedef std::set<SlotIndex> SlotSet; | 
|  | typedef std::map<const LiveInterval*, SlotSet> UseDefs; | 
|  | UseDefs useDefs; | 
|  |  | 
|  | // ---------- Rendering methods ---------- | 
|  |  | 
|  | /// For inserting spaces when pretty printing. | 
|  | class Spacer { | 
|  | public: | 
|  | explicit Spacer(unsigned numSpaces) : ns(numSpaces) {} | 
|  | Spacer operator+(const Spacer &o) const { return Spacer(ns + o.ns); } | 
|  | void print(raw_ostream &os) const; | 
|  | private: | 
|  | unsigned ns; | 
|  | }; | 
|  |  | 
|  | Spacer s(unsigned ns) const; | 
|  |  | 
|  | template <typename Iterator> | 
|  | std::string escapeChars(Iterator sBegin, Iterator sEnd) const; | 
|  |  | 
|  | /// \brief Render a machine instruction. | 
|  | void renderMachineInstr(raw_ostream &os, | 
|  | const MachineInstr *mi) const; | 
|  |  | 
|  | /// \brief Render vertical text. | 
|  | template <typename T> | 
|  | void renderVertical(const Spacer &indent, | 
|  | raw_ostream &os, | 
|  | const T &t) const; | 
|  |  | 
|  | /// \brief Insert CSS layout info. | 
|  | void insertCSS(const Spacer &indent, | 
|  | raw_ostream &os) const; | 
|  |  | 
|  | /// \brief Render a brief summary of the function (including rendering | 
|  | ///        context). | 
|  | void renderFunctionSummary(const Spacer &indent, | 
|  | raw_ostream &os, | 
|  | const char * const renderContextStr) const; | 
|  |  | 
|  | /// \brief Render a legend for the pressure table. | 
|  | void renderPressureTableLegend(const Spacer &indent, | 
|  | raw_ostream &os) const; | 
|  |  | 
|  | /// \brief Render a consecutive set of HTML cells of the same class using | 
|  | /// the colspan attribute for run-length encoding. | 
|  | template <typename CellType> | 
|  | void renderCellsWithRLE( | 
|  | const Spacer &indent, raw_ostream &os, | 
|  | const std::pair<CellType, unsigned> &rleAccumulator, | 
|  | const std::map<CellType, std::string> &cellTypeStrs) const; | 
|  |  | 
|  | /// \brief Render code listing, potentially with register pressure | 
|  | ///        and live intervals shown alongside. | 
|  | void renderCodeTablePlusPI(const Spacer &indent, | 
|  | raw_ostream &os) const; | 
|  |  | 
|  | /// \brief Render the HTML page representing the MachineFunction. | 
|  | void renderFunctionPage(raw_ostream &os, | 
|  | const char * const renderContextStr) const; | 
|  |  | 
|  | std::string escapeChars(const std::string &s) const; | 
|  | }; | 
|  | } | 
|  |  | 
|  | #endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */ |