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