| //===-- 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 */ |