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