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