2010-07-19 17:22:28 +02:00
|
|
|
//===-- 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;
|
2010-09-02 10:27:00 +02:00
|
|
|
class RenderMachineFunction;
|
2010-07-19 17:22:28 +02:00
|
|
|
class TargetRegisterClass;
|
|
|
|
class TargetRegisterInfo;
|
2010-07-20 09:41:44 +02:00
|
|
|
class VirtRegMap;
|
2010-07-21 11:02:06 +02:00
|
|
|
class raw_ostream;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
/// \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,
|
2010-09-02 10:27:00 +02:00
|
|
|
LiveIntervals *lis, const RenderMachineFunction *rmf);
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
/// 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,
|
2010-09-02 10:27:00 +02:00
|
|
|
AllPhys = 1,
|
|
|
|
VirtNoSpills = 2,
|
|
|
|
VirtSpills = 4,
|
|
|
|
AllVirt = 6,
|
|
|
|
All = 7 }
|
2010-07-19 17:22:28 +02:00
|
|
|
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;
|
2010-09-02 10:27:00 +02:00
|
|
|
const RenderMachineFunction *rmf;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
mutable bool regClassesTranslatedToCurrentFunction;
|
|
|
|
mutable RegClassSet regClassSet;
|
|
|
|
|
|
|
|
mutable bool intervalsTranslatedToCurrentFunction;
|
|
|
|
mutable IntervalSet intervalSet;
|
|
|
|
|
|
|
|
void translateRegClassNamesToCurrentFunction() const;
|
|
|
|
|
|
|
|
void translateIntervalNumbersToCurrentFunction() const;
|
|
|
|
};
|
|
|
|
|
2010-09-02 10:27:00 +02:00
|
|
|
/// \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();
|
|
|
|
};
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
/// \brief Render MachineFunction objects and related information to a HTML
|
|
|
|
/// page.
|
|
|
|
class RenderMachineFunction : public MachineFunctionPass {
|
|
|
|
public:
|
|
|
|
static char ID;
|
|
|
|
|
2010-10-19 19:21:58 +02:00
|
|
|
RenderMachineFunction() : MachineFunctionPass(ID) {
|
|
|
|
initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &au) const;
|
|
|
|
|
|
|
|
virtual bool runOnMachineFunction(MachineFunction &fn);
|
|
|
|
|
|
|
|
virtual void releaseMemory();
|
|
|
|
|
2010-09-02 10:27:00 +02:00
|
|
|
void rememberUseDefs(const LiveInterval *li);
|
|
|
|
|
|
|
|
void rememberSpills(const LiveInterval *li,
|
|
|
|
const std::vector<LiveInterval*> &spills);
|
|
|
|
|
|
|
|
bool isSpill(const LiveInterval *li) const;
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
/// \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".
|
2010-07-20 09:41:44 +02:00
|
|
|
/// @param vrm If non-null the VRM will be queried to determine
|
|
|
|
/// whether a virtual register was allocated to a
|
|
|
|
/// physical register or spilled.
|
2010-07-19 17:22:28 +02:00
|
|
|
/// @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,
|
2010-07-20 09:41:44 +02:00
|
|
|
const VirtRegMap *vrm = 0,
|
2010-07-19 17:22:28 +02:00
|
|
|
const char *renderSuffix = 0);
|
|
|
|
|
|
|
|
private:
|
2010-07-20 12:18:54 +02:00
|
|
|
class Spacer;
|
2010-07-21 11:02:06 +02:00
|
|
|
friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s);
|
2010-07-20 12:18:54 +02:00
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
std::string fqn;
|
|
|
|
|
|
|
|
MachineFunction *mf;
|
|
|
|
MachineRegisterInfo *mri;
|
|
|
|
const TargetRegisterInfo *tri;
|
|
|
|
LiveIntervals *lis;
|
|
|
|
SlotIndexes *sis;
|
2010-07-20 09:41:44 +02:00
|
|
|
const VirtRegMap *vrm;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
TargetRegisterExtraInfo trei;
|
|
|
|
MFRenderingOptions ro;
|
|
|
|
|
2010-09-02 10:27:00 +02:00
|
|
|
|
|
|
|
|
2010-07-20 09:41:44 +02:00
|
|
|
// Utilities.
|
|
|
|
typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState;
|
|
|
|
LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
2010-07-20 12:18:54 +02:00
|
|
|
typedef enum { Zero, Low, High } PressureState;
|
|
|
|
PressureState getPressureStateAt(const TargetRegisterClass *trc,
|
|
|
|
SlotIndex i) const;
|
|
|
|
|
2010-09-02 10:27:00 +02:00
|
|
|
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;
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
// ---------- Rendering methods ----------
|
|
|
|
|
2010-07-20 11:13:29 +02:00
|
|
|
/// 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); }
|
2010-07-21 11:02:06 +02:00
|
|
|
void print(raw_ostream &os) const;
|
2010-07-20 11:13:29 +02:00
|
|
|
private:
|
|
|
|
unsigned ns;
|
|
|
|
};
|
|
|
|
|
|
|
|
Spacer s(unsigned ns) const;
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
template <typename Iterator>
|
|
|
|
std::string escapeChars(Iterator sBegin, Iterator sEnd) const;
|
|
|
|
|
2010-07-20 09:41:44 +02:00
|
|
|
/// \brief Render a machine instruction.
|
2010-07-21 11:02:06 +02:00
|
|
|
void renderMachineInstr(raw_ostream &os,
|
2010-07-20 09:41:44 +02:00
|
|
|
const MachineInstr *mi) const;
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
/// \brief Render vertical text.
|
2010-07-21 11:02:06 +02:00
|
|
|
template <typename T>
|
2010-07-20 11:13:29 +02:00
|
|
|
void renderVertical(const Spacer &indent,
|
2010-07-21 11:02:06 +02:00
|
|
|
raw_ostream &os,
|
2010-07-19 17:22:28 +02:00
|
|
|
const T &t) const;
|
|
|
|
|
|
|
|
/// \brief Insert CSS layout info.
|
2010-07-20 11:13:29 +02:00
|
|
|
void insertCSS(const Spacer &indent,
|
2010-07-21 11:02:06 +02:00
|
|
|
raw_ostream &os) const;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
/// \brief Render a brief summary of the function (including rendering
|
|
|
|
/// context).
|
2010-07-20 11:13:29 +02:00
|
|
|
void renderFunctionSummary(const Spacer &indent,
|
2010-07-21 11:02:06 +02:00
|
|
|
raw_ostream &os,
|
2010-07-19 17:22:28 +02:00
|
|
|
const char * const renderContextStr) const;
|
|
|
|
|
|
|
|
/// \brief Render a legend for the pressure table.
|
2010-07-20 11:13:29 +02:00
|
|
|
void renderPressureTableLegend(const Spacer &indent,
|
2010-07-21 11:02:06 +02:00
|
|
|
raw_ostream &os) const;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
2010-07-20 12:18:54 +02:00
|
|
|
/// \brief Render a consecutive set of HTML cells of the same class using
|
|
|
|
/// the colspan attribute for run-length encoding.
|
2010-07-21 11:02:06 +02:00
|
|
|
template <typename CellType>
|
2010-07-20 12:18:54 +02:00
|
|
|
void renderCellsWithRLE(
|
2010-07-21 11:02:06 +02:00
|
|
|
const Spacer &indent, raw_ostream &os,
|
2010-07-20 12:18:54 +02:00
|
|
|
const std::pair<CellType, unsigned> &rleAccumulator,
|
|
|
|
const std::map<CellType, std::string> &cellTypeStrs) const;
|
|
|
|
|
2010-07-19 17:22:28 +02:00
|
|
|
/// \brief Render code listing, potentially with register pressure
|
|
|
|
/// and live intervals shown alongside.
|
2010-07-20 11:13:29 +02:00
|
|
|
void renderCodeTablePlusPI(const Spacer &indent,
|
2010-07-21 11:02:06 +02:00
|
|
|
raw_ostream &os) const;
|
2010-07-19 17:22:28 +02:00
|
|
|
|
|
|
|
/// \brief Render the HTML page representing the MachineFunction.
|
2010-07-21 11:02:06 +02:00
|
|
|
void renderFunctionPage(raw_ostream &os,
|
2010-07-19 17:22:28 +02:00
|
|
|
const char * const renderContextStr) const;
|
|
|
|
|
|
|
|
std::string escapeChars(const std::string &s) const;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */
|