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
25namespace llvm {
26
27  class LiveInterval;
28  class LiveIntervals;
29  class MachineInstr;
30  class MachineRegisterInfo;
31  class RenderMachineFunction;
32  class TargetRegisterClass;
33  class TargetRegisterInfo;
34  class VirtRegMap;
35  class raw_ostream;
36
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
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
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
205    RenderMachineFunction() : MachineFunctionPass(ID) {
206      initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
207    }
208
209    virtual void getAnalysisUsage(AnalysisUsage &au) const;
210
211    virtual bool runOnMachineFunction(MachineFunction &fn);
212
213    virtual void releaseMemory();
214
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
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".
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.
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,
236                               const VirtRegMap *vrm = 0,
237                               const char *renderSuffix = 0);
238
239  private:
240    class Spacer;
241    friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s);
242
243    std::string fqn;
244
245    MachineFunction *mf;
246    MachineRegisterInfo *mri;
247    const TargetRegisterInfo *tri;
248    LiveIntervals *lis;
249    SlotIndexes *sis;
250    const VirtRegMap *vrm;
251
252    TargetRegisterExtraInfo trei;
253    MFRenderingOptions ro;
254
255
256
257    // Utilities.
258    typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState;
259    LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const;
260
261    typedef enum { Zero, Low, High } PressureState;
262    PressureState getPressureStateAt(const TargetRegisterClass *trc,
263                                     SlotIndex i) const;
264
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
276    // ---------- Rendering methods ----------
277
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); }
283      void print(raw_ostream &os) const;
284    private:
285      unsigned ns;
286    };
287
288    Spacer s(unsigned ns) const;
289
290    template <typename Iterator>
291    std::string escapeChars(Iterator sBegin, Iterator sEnd) const;
292
293    /// \brief Render a machine instruction.
294    void renderMachineInstr(raw_ostream &os,
295                            const MachineInstr *mi) const;
296
297    /// \brief Render vertical text.
298    template <typename T>
299    void renderVertical(const Spacer &indent,
300                        raw_ostream &os,
301                        const T &t) const;
302
303    /// \brief Insert CSS layout info.
304    void insertCSS(const Spacer &indent,
305                   raw_ostream &os) const;
306
307    /// \brief Render a brief summary of the function (including rendering
308    ///        context).
309    void renderFunctionSummary(const Spacer &indent,
310                               raw_ostream &os,
311                               const char * const renderContextStr) const;
312
313    /// \brief Render a legend for the pressure table.
314    void renderPressureTableLegend(const Spacer &indent,
315                                   raw_ostream &os) const;
316
317    /// \brief Render a consecutive set of HTML cells of the same class using
318    /// the colspan attribute for run-length encoding.
319    template <typename CellType>
320    void renderCellsWithRLE(
321                     const Spacer &indent, raw_ostream &os,
322                     const std::pair<CellType, unsigned> &rleAccumulator,
323                     const std::map<CellType, std::string> &cellTypeStrs) const;
324
325    /// \brief Render code listing, potentially with register pressure
326    ///        and live intervals shown alongside.
327    void renderCodeTablePlusPI(const Spacer &indent,
328                               raw_ostream &os) const;
329
330    /// \brief Render the HTML page representing the MachineFunction.
331    void renderFunctionPage(raw_ostream &os,
332                            const char * const renderContextStr) const;
333
334    std::string escapeChars(const std::string &s) const;
335  };
336}
337
338#endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */
339