Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 1 | //===-- llvm/CodeGen/RenderMachineFunction.h - MF->HTML -*- C++ -*---------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | //===----------------------------------------------------------------------===// |
| 11 | |
| 12 | #ifndef LLVM_CODEGEN_RENDERMACHINEFUNCTION_H |
| 13 | #define LLVM_CODEGEN_RENDERMACHINEFUNCTION_H |
| 14 | |
| 15 | #include "llvm/CodeGen/LiveInterval.h" |
| 16 | #include "llvm/CodeGen/MachineFunctionPass.h" |
| 17 | #include "llvm/CodeGen/SlotIndexes.h" |
| 18 | #include "llvm/Target/TargetRegisterInfo.h" |
| 19 | |
| 20 | #include <algorithm> |
| 21 | #include <map> |
| 22 | #include <set> |
| 23 | #include <string> |
| 24 | |
| 25 | namespace llvm { |
| 26 | |
| 27 | class LiveInterval; |
| 28 | class LiveIntervals; |
| 29 | class MachineInstr; |
| 30 | class MachineRegisterInfo; |
| 31 | class TargetRegisterClass; |
| 32 | class TargetRegisterInfo; |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 33 | class VirtRegMap; |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 34 | |
| 35 | /// \brief Provide extra information about the physical and virtual registers |
| 36 | /// in the function being compiled. |
| 37 | class TargetRegisterExtraInfo { |
| 38 | public: |
| 39 | TargetRegisterExtraInfo(); |
| 40 | |
| 41 | /// \brief Set up TargetRegisterExtraInfo with pointers to necessary |
| 42 | /// sources of information. |
| 43 | void setup(MachineFunction *mf, MachineRegisterInfo *mri, |
| 44 | const TargetRegisterInfo *tri, LiveIntervals *lis); |
| 45 | |
| 46 | /// \brief Recompute tables for changed function. |
| 47 | void reset(); |
| 48 | |
| 49 | /// \brief Free all tables in TargetRegisterExtraInfo. |
| 50 | void clear(); |
| 51 | |
| 52 | /// \brief Maximum number of registers from trc which alias reg. |
| 53 | unsigned getWorst(unsigned reg, const TargetRegisterClass *trc) const; |
| 54 | |
| 55 | /// \brief Returns the number of allocable registers in trc. |
| 56 | unsigned getCapacity(const TargetRegisterClass *trc) const; |
| 57 | |
| 58 | /// \brief Return the number of registers of class trc that may be |
| 59 | /// needed at slot i. |
| 60 | unsigned getPressureAtSlot(const TargetRegisterClass *trc, |
| 61 | SlotIndex i) const; |
| 62 | |
| 63 | /// \brief Return true if the number of registers of type trc that may be |
| 64 | /// needed at slot i is greater than the capacity of trc. |
| 65 | bool classOverCapacityAtSlot(const TargetRegisterClass *trc, |
| 66 | SlotIndex i) const; |
| 67 | |
| 68 | private: |
| 69 | |
| 70 | MachineFunction *mf; |
| 71 | MachineRegisterInfo *mri; |
| 72 | const TargetRegisterInfo *tri; |
| 73 | LiveIntervals *lis; |
| 74 | |
| 75 | typedef std::map<const TargetRegisterClass*, unsigned> WorstMapLine; |
| 76 | typedef std::map<const TargetRegisterClass*, WorstMapLine> VRWorstMap; |
| 77 | VRWorstMap vrWorst; |
| 78 | |
| 79 | typedef std::map<unsigned, WorstMapLine> PRWorstMap; |
| 80 | PRWorstMap prWorst; |
| 81 | |
| 82 | typedef std::map<const TargetRegisterClass*, unsigned> CapacityMap; |
| 83 | CapacityMap capacityMap; |
| 84 | |
| 85 | typedef std::map<const TargetRegisterClass*, unsigned> PressureMapLine; |
| 86 | typedef std::map<SlotIndex, PressureMapLine> PressureMap; |
| 87 | PressureMap pressureMap; |
| 88 | |
| 89 | bool mapsPopulated; |
| 90 | |
| 91 | /// \brief Initialise the 'worst' table. |
| 92 | void initWorst(); |
| 93 | |
| 94 | /// \brief Initialise the 'capacity' table. |
| 95 | void initCapacity(); |
| 96 | |
| 97 | /// \brief Initialise/Reset the 'pressure' and live states tables. |
| 98 | void resetPressureAndLiveStates(); |
| 99 | }; |
| 100 | |
| 101 | /// \brief Helper class to process rendering options. Tries to be as lazy as |
| 102 | /// possible. |
| 103 | class MFRenderingOptions { |
| 104 | public: |
| 105 | |
| 106 | struct RegClassComp { |
| 107 | bool operator()(const TargetRegisterClass *trc1, |
| 108 | const TargetRegisterClass *trc2) const { |
| 109 | std::string trc1Name(trc1->getName()), trc2Name(trc2->getName()); |
| 110 | return std::lexicographical_compare(trc1Name.begin(), trc1Name.end(), |
| 111 | trc2Name.begin(), trc2Name.end()); |
| 112 | } |
| 113 | }; |
| 114 | |
| 115 | typedef std::set<const TargetRegisterClass*, RegClassComp> RegClassSet; |
| 116 | |
| 117 | struct IntervalComp { |
| 118 | bool operator()(const LiveInterval *li1, const LiveInterval *li2) const { |
| 119 | return li1->reg < li2->reg; |
| 120 | } |
| 121 | }; |
| 122 | |
| 123 | typedef std::set<const LiveInterval*, IntervalComp> IntervalSet; |
| 124 | |
| 125 | /// Initialise the rendering options. |
| 126 | void setup(MachineFunction *mf, const TargetRegisterInfo *tri, |
| 127 | LiveIntervals *lis); |
| 128 | |
| 129 | /// Clear translations of options to the current function. |
| 130 | void clear(); |
| 131 | |
| 132 | /// Reset any options computed for this specific rendering. |
| 133 | void resetRenderSpecificOptions(); |
| 134 | |
| 135 | /// Should we render the current function. |
| 136 | bool shouldRenderCurrentMachineFunction() const; |
| 137 | |
| 138 | /// Return the set of register classes to render pressure for. |
| 139 | const RegClassSet& regClasses() const; |
| 140 | |
| 141 | /// Return the set of live intervals to render liveness for. |
| 142 | const IntervalSet& intervals() const; |
| 143 | |
| 144 | /// Render indexes which are not associated with instructions / MBB starts. |
| 145 | bool renderEmptyIndexes() const; |
| 146 | |
| 147 | /// Return whether or not to render using SVG for fancy vertical text. |
| 148 | bool fancyVerticals() const; |
| 149 | |
| 150 | private: |
| 151 | |
| 152 | static bool renderingOptionsProcessed; |
| 153 | static std::set<std::string> mfNamesToRender; |
| 154 | static bool renderAllMFs; |
| 155 | |
| 156 | static std::set<std::string> classNamesToRender; |
| 157 | static bool renderAllClasses; |
| 158 | |
| 159 | |
| 160 | static std::set<std::pair<unsigned, unsigned> > intervalNumsToRender; |
| 161 | typedef enum { ExplicitOnly = 0, |
| 162 | VirtPlusExplicit = 1, |
| 163 | PhysPlusExplicit = 2, |
| 164 | All = 3 } |
| 165 | IntervalTypesToRender; |
| 166 | static unsigned intervalTypesToRender; |
| 167 | |
| 168 | template <typename OutputItr> |
| 169 | static void splitComaSeperatedList(const std::string &s, OutputItr outItr); |
| 170 | |
| 171 | static void processOptions(); |
| 172 | |
| 173 | static void processFuncNames(); |
| 174 | static void processRegClassNames(); |
| 175 | static void processIntervalNumbers(); |
| 176 | |
| 177 | static void processIntervalRange(const std::string &intervalRangeStr); |
| 178 | |
| 179 | MachineFunction *mf; |
| 180 | const TargetRegisterInfo *tri; |
| 181 | LiveIntervals *lis; |
| 182 | |
| 183 | mutable bool regClassesTranslatedToCurrentFunction; |
| 184 | mutable RegClassSet regClassSet; |
| 185 | |
| 186 | mutable bool intervalsTranslatedToCurrentFunction; |
| 187 | mutable IntervalSet intervalSet; |
| 188 | |
| 189 | void translateRegClassNamesToCurrentFunction() const; |
| 190 | |
| 191 | void translateIntervalNumbersToCurrentFunction() const; |
| 192 | }; |
| 193 | |
| 194 | /// \brief Render MachineFunction objects and related information to a HTML |
| 195 | /// page. |
| 196 | class RenderMachineFunction : public MachineFunctionPass { |
| 197 | public: |
| 198 | static char ID; |
| 199 | |
| 200 | RenderMachineFunction() : MachineFunctionPass(&ID) {} |
| 201 | |
| 202 | virtual void getAnalysisUsage(AnalysisUsage &au) const; |
| 203 | |
| 204 | virtual bool runOnMachineFunction(MachineFunction &fn); |
| 205 | |
| 206 | virtual void releaseMemory(); |
| 207 | |
| 208 | /// \brief Render this machine function to HTML. |
| 209 | /// |
| 210 | /// @param renderContextStr This parameter will be included in the top of |
| 211 | /// the html file to explain where (in the |
| 212 | /// codegen pipeline) this function was rendered |
| 213 | /// from. Set it to something like |
| 214 | /// "Pre-register-allocation". |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 215 | /// @param vrm If non-null the VRM will be queried to determine |
| 216 | /// whether a virtual register was allocated to a |
| 217 | /// physical register or spilled. |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 218 | /// @param renderFilePrefix This string will be appended to the function |
| 219 | /// name (before the output file suffix) to enable |
| 220 | /// multiple renderings from the same function. |
| 221 | void renderMachineFunction(const char *renderContextStr, |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 222 | const VirtRegMap *vrm = 0, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 223 | const char *renderSuffix = 0); |
| 224 | |
| 225 | private: |
| 226 | |
| 227 | std::string fqn; |
| 228 | |
| 229 | MachineFunction *mf; |
| 230 | MachineRegisterInfo *mri; |
| 231 | const TargetRegisterInfo *tri; |
| 232 | LiveIntervals *lis; |
| 233 | SlotIndexes *sis; |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 234 | const VirtRegMap *vrm; |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 235 | |
| 236 | TargetRegisterExtraInfo trei; |
| 237 | MFRenderingOptions ro; |
| 238 | |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 239 | // Utilities. |
| 240 | typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState; |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 241 | |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 242 | LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const; |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 243 | |
| 244 | // ---------- Rendering methods ---------- |
| 245 | |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 246 | /// For inserting spaces when pretty printing. |
| 247 | class Spacer { |
| 248 | public: |
| 249 | explicit Spacer(unsigned numSpaces) : ns(numSpaces) {} |
| 250 | Spacer operator+(const Spacer &o) const { return Spacer(ns + o.ns); } |
| 251 | template <typename OStream> void print(OStream &os) const; |
| 252 | private: |
| 253 | unsigned ns; |
| 254 | }; |
| 255 | |
| 256 | Spacer s(unsigned ns) const; |
| 257 | |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 258 | template <typename Iterator> |
| 259 | std::string escapeChars(Iterator sBegin, Iterator sEnd) const; |
| 260 | |
Lang Hames | c4bcc77 | 2010-07-20 07:41:44 +0000 | [diff] [blame] | 261 | /// \brief Render a machine instruction. |
| 262 | template <typename OStream> |
| 263 | void renderMachineInstr(OStream &os, |
| 264 | const MachineInstr *mi) const; |
| 265 | |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 266 | /// \brief Render vertical text. |
| 267 | template <typename OStream, typename T> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 268 | void renderVertical(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 269 | OStream &os, |
| 270 | const T &t) const; |
| 271 | |
| 272 | /// \brief Insert CSS layout info. |
| 273 | template <typename OStream> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 274 | void insertCSS(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 275 | OStream &os) const; |
| 276 | |
| 277 | /// \brief Render a brief summary of the function (including rendering |
| 278 | /// context). |
| 279 | template <typename OStream> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 280 | void renderFunctionSummary(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 281 | OStream &os, |
| 282 | const char * const renderContextStr) const; |
| 283 | |
| 284 | /// \brief Render a legend for the pressure table. |
| 285 | template <typename OStream> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 286 | void renderPressureTableLegend(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 287 | OStream &os) const; |
| 288 | |
| 289 | /// \brief Render code listing, potentially with register pressure |
| 290 | /// and live intervals shown alongside. |
| 291 | template <typename OStream> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 292 | void renderCodeTablePlusPI(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 293 | OStream &os) const; |
| 294 | |
| 295 | /// \brief Render warnings about the machine function, or weird rendering |
| 296 | /// parameter combinations (e.g. rendering specified live intervals |
| 297 | /// over more than one machine function). |
| 298 | template <typename OStream> |
Lang Hames | 245581b | 2010-07-20 09:13:29 +0000 | [diff] [blame^] | 299 | void renderWarnings(const Spacer &indent, |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 300 | OStream &os) const; |
| 301 | |
| 302 | /// \brief Render the HTML page representing the MachineFunction. |
| 303 | template <typename OStream> |
| 304 | void renderFunctionPage(OStream &os, |
| 305 | const char * const renderContextStr) const; |
| 306 | |
| 307 | std::string escapeChars(const std::string &s) const; |
Lang Hames | 54cc2ef | 2010-07-19 15:22:28 +0000 | [diff] [blame] | 308 | }; |
| 309 | } |
| 310 | |
| 311 | #endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */ |