llvm.org GIT mirror llvm / 3122447
Remove the RenderMachineFunction HTML output pass. I don't think anyone has been using this functionality for a while, and it is getting in the way of refactoring now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158876 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 8 years ago
7 changed file(s) with 0 addition(s) and 1375 deletion(s). Raw diff Collapse all Expand all
215215 void initializeRegionOnlyViewerPass(PassRegistry&);
216216 void initializeRegionPrinterPass(PassRegistry&);
217217 void initializeRegionViewerPass(PassRegistry&);
218 void initializeRenderMachineFunctionPass(PassRegistry&);
219218 void initializeSCCPPass(PassRegistry&);
220219 void initializeSROA_DTPass(PassRegistry&);
221220 void initializeSROA_SSAUpPass(PassRegistry&);
7979 RegisterCoalescer.cpp
8080 RegisterPressure.cpp
8181 RegisterScavenging.cpp
82 RenderMachineFunction.cpp
8382 ScheduleDAG.cpp
8483 ScheduleDAGInstrs.cpp
8584 ScheduleDAGPrinter.cpp
5252 initializeProcessImplicitDefsPass(Registry);
5353 initializePEIPass(Registry);
5454 initializeRegisterCoalescerPass(Registry);
55 initializeRenderMachineFunctionPass(Registry);
5655 initializeSlotIndexesPass(Registry);
5756 initializeStackProtectorPass(Registry);
5857 initializeStackSlotColoringPass(Registry);
1515 #include "AllocationOrder.h"
1616 #include "RegAllocBase.h"
1717 #include "LiveDebugVariables.h"
18 #include "RenderMachineFunction.h"
1918 #include "Spiller.h"
2019 #include "VirtRegMap.h"
2120 #include "LiveRegMatrix.h"
6564 // context
6665 MachineFunction *MF;
6766
68 #ifndef NDEBUG
69 // analyses
70 RenderMachineFunction *RMF;
71 #endif
72
7367 // state
7468 std::auto_ptr SpillerInstance;
7569 std::priority_queue,
139133 initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
140134 initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
141135 initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry());
142 initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
143136 }
144137
145138 void RABasic::getAnalysisUsage(AnalysisUsage &AU) const {
162155 AU.addPreserved();
163156 AU.addRequired();
164157 AU.addPreserved();
165 DEBUG(AU.addRequired());
166158 MachineFunctionPass::getAnalysisUsage(AU);
167159 }
168160
283275 << ((Value*)mf.getFunction())->getName() << '\n');
284276
285277 MF = &mf;
286 DEBUG(RMF = &getAnalysis());
287
288278 RegAllocBase::init(getAnalysis(),
289279 getAnalysis(),
290280 getAnalysis());
295285 // Diagnostic output before rewriting
296286 DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n");
297287
298 // optional HTML output
299 DEBUG(RMF->renderMachineFunction("After basic register allocation.", VRM));
300
301288 releaseMemory();
302289 return true;
303290 }
3030
3131 #define DEBUG_TYPE "regalloc"
3232
33 #include "RenderMachineFunction.h"
3433 #include "Spiller.h"
3534 #include "VirtRegMap.h"
3635 #include "RegisterCoalescer.h"
9796 initializeLiveStacksPass(*PassRegistry::getPassRegistry());
9897 initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry());
9998 initializeVirtRegMapPass(*PassRegistry::getPassRegistry());
100 initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
10199 }
102100
103101 /// Return the pass name.
133131 const TargetInstrInfo *tii;
134132 const MachineLoopInfo *loopInfo;
135133 MachineRegisterInfo *mri;
136 RenderMachineFunction *rmf;
137134
138135 std::auto_ptr spiller;
139136 LiveIntervals *lis;
490487 au.addRequired();
491488 au.addPreserved();
492489 au.addRequired();
493 au.addRequired();
494490 MachineFunctionPass::getAnalysisUsage(au);
495491 }
496492
600596 lis = &getAnalysis();
601597 lss = &getAnalysis();
602598 loopInfo = &getAnalysis();
603 rmf = &getAnalysis();
604599
605600 vrm = &getAnalysis();
606601 spiller.reset(createInlineSpiller(*this, MF, *vrm));
664659
665660 // Finalise allocation, allocate empty ranges.
666661 finalizeAlloc();
667
668 rmf->renderMachineFunction("After PBQP register allocation.", vrm);
669
670662 vregsToAlloc.clear();
671663 emptyIntervalVRegs.clear();
672664
+0
-1013
lib/CodeGen/RenderMachineFunction.cpp less more
\n";
None //===-- llvm/CodeGen/RenderMachineFunction.cpp - MF->HTML -----------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #define DEBUG_TYPE "rendermf"
10
11 #include "RenderMachineFunction.h"
12
13 #include "VirtRegMap.h"
14
15 #include "llvm/Function.h"
16 #include "llvm/Module.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Target/TargetMachine.h"
26
27 #include
28
29 using namespace llvm;
30
31 char RenderMachineFunction::ID = 0;
32 INITIALIZE_PASS_BEGIN(RenderMachineFunction, "rendermf",
33 "Render machine functions (and related info) to HTML pages",
34 false, false)
35 INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
36 INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
37 INITIALIZE_PASS_END(RenderMachineFunction, "rendermf",
38 "Render machine functions (and related info) to HTML pages",
39 false, false)
40
41 static cl::opt
42 outputFileSuffix("rmf-file-suffix",
43 cl::desc("Appended to function name to get output file name "
44 "(default: \".html\")"),
45 cl::init(".html"), cl::Hidden);
46
47 static cl::opt
48 machineFuncsToRender("rmf-funcs",
49 cl::desc("Comma separated list of functions to render"
50 ", or \"*\"."),
51 cl::init(""), cl::Hidden);
52
53 static cl::opt
54 pressureClasses("rmf-classes",
55 cl::desc("Register classes to render pressure for."),
56 cl::init(""), cl::Hidden);
57
58 static cl::opt
59 showIntervals("rmf-intervals",
60 cl::desc("Live intervals to show alongside code."),
61 cl::init(""), cl::Hidden);
62
63 static cl::opt
64 filterEmpty("rmf-filter-empty-intervals",
65 cl::desc("Don't display empty intervals."),
66 cl::init(true), cl::Hidden);
67
68 static cl::opt
69 showEmptyIndexes("rmf-empty-indexes",
70 cl::desc("Render indexes not associated with instructions or "
71 "MBB starts."),
72 cl::init(false), cl::Hidden);
73
74 static cl::opt
75 useFancyVerticals("rmf-fancy-verts",
76 cl::desc("Use SVG for vertical text."),
77 cl::init(true), cl::Hidden);
78
79 static cl::opt
80 prettyHTML("rmf-pretty-html",
81 cl::desc("Pretty print HTML. For debugging the renderer only.."),
82 cl::init(false), cl::Hidden);
83
84
85 namespace llvm {
86
87 bool MFRenderingOptions::renderingOptionsProcessed;
88 std::set MFRenderingOptions::mfNamesToRender;
89 bool MFRenderingOptions::renderAllMFs = false;
90
91 std::set MFRenderingOptions::classNamesToRender;
92 bool MFRenderingOptions::renderAllClasses = false;
93
94 std::set >
95 MFRenderingOptions::intervalNumsToRender;
96 unsigned MFRenderingOptions::intervalTypesToRender = ExplicitOnly;
97
98 template
99 void MFRenderingOptions::splitComaSeperatedList(const std::string &s,
100 OutputItr outItr) {
101 std::string::const_iterator curPos = s.begin();
102 std::string::const_iterator nextComa = std::find(curPos, s.end(), ',');
103 while (nextComa != s.end()) {
104 std::string elem;
105 std::copy(curPos, nextComa, std::back_inserter(elem));
106 *outItr = elem;
107 ++outItr;
108 curPos = llvm::next(nextComa);
109 nextComa = std::find(curPos, s.end(), ',');
110 }
111
112 if (curPos != s.end()) {
113 std::string elem;
114 std::copy(curPos, s.end(), std::back_inserter(elem));
115 *outItr = elem;
116 ++outItr;
117 }
118 }
119
120 void MFRenderingOptions::processOptions() {
121 if (!renderingOptionsProcessed) {
122 processFuncNames();
123 processRegClassNames();
124 processIntervalNumbers();
125 renderingOptionsProcessed = true;
126 }
127 }
128
129 void MFRenderingOptions::processFuncNames() {
130 if (machineFuncsToRender == "*") {
131 renderAllMFs = true;
132 } else {
133 splitComaSeperatedList(machineFuncsToRender,
134 std::inserter(mfNamesToRender,
135 mfNamesToRender.begin()));
136 }
137 }
138
139 void MFRenderingOptions::processRegClassNames() {
140 if (pressureClasses == "*") {
141 renderAllClasses = true;
142 } else {
143 splitComaSeperatedList(pressureClasses,
144 std::inserter(classNamesToRender,
145 classNamesToRender.begin()));
146 }
147 }
148
149 void MFRenderingOptions::processIntervalNumbers() {
150 std::set intervalRanges;
151 splitComaSeperatedList(showIntervals,
152 std::inserter(intervalRanges,
153 intervalRanges.begin()));
154 std::for_each(intervalRanges.begin(), intervalRanges.end(),
155 processIntervalRange);
156 }
157
158 void MFRenderingOptions::processIntervalRange(
159 const std::string &intervalRangeStr) {
160 if (intervalRangeStr == "*") {
161 intervalTypesToRender |= All;
162 } else if (intervalRangeStr == "virt-nospills*") {
163 intervalTypesToRender |= VirtNoSpills;
164 } else if (intervalRangeStr == "spills*") {
165 intervalTypesToRender |= VirtSpills;
166 } else if (intervalRangeStr == "virt*") {
167 intervalTypesToRender |= AllVirt;
168 } else if (intervalRangeStr == "phys*") {
169 intervalTypesToRender |= AllPhys;
170 } else {
171 std::istringstream iss(intervalRangeStr);
172 unsigned reg1, reg2;
173 if ((iss >> reg1 >> std::ws)) {
174 if (iss.eof()) {
175 intervalNumsToRender.insert(std::make_pair(reg1, reg1 + 1));
176 } else {
177 char c;
178 iss >> c;
179 if (c == '-' && (iss >> reg2)) {
180 intervalNumsToRender.insert(std::make_pair(reg1, reg2 + 1));
181 } else {
182 dbgs() << "Warning: Invalid interval range \""
183 << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
184 }
185 }
186 } else {
187 dbgs() << "Warning: Invalid interval number \""
188 << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n";
189 }
190 }
191 }
192
193 void MFRenderingOptions::setup(MachineFunction *mf,
194 const TargetRegisterInfo *tri,
195 LiveIntervals *lis,
196 const RenderMachineFunction *rmf) {
197 this->mf = mf;
198 this->tri = tri;
199 this->lis = lis;
200 this->rmf = rmf;
201
202 clear();
203 }
204
205 void MFRenderingOptions::clear() {
206 regClassesTranslatedToCurrentFunction = false;
207 regClassSet.clear();
208
209 intervalsTranslatedToCurrentFunction = false;
210 intervalSet.clear();
211 }
212
213 void MFRenderingOptions::resetRenderSpecificOptions() {
214 intervalSet.clear();
215 intervalsTranslatedToCurrentFunction = false;
216 }
217
218 bool MFRenderingOptions::shouldRenderCurrentMachineFunction() const {
219 processOptions();
220
221 return (renderAllMFs ||
222 mfNamesToRender.find(mf->getFunction()->getName()) !=
223 mfNamesToRender.end());
224 }
225
226 const MFRenderingOptions::RegClassSet& MFRenderingOptions::regClasses() const{
227 translateRegClassNamesToCurrentFunction();
228 return regClassSet;
229 }
230
231 const MFRenderingOptions::IntervalSet& MFRenderingOptions::intervals() const {
232 translateIntervalNumbersToCurrentFunction();
233 return intervalSet;
234 }
235
236 bool MFRenderingOptions::renderEmptyIndexes() const {
237 return showEmptyIndexes;
238 }
239
240 bool MFRenderingOptions::fancyVerticals() const {
241 return useFancyVerticals;
242 }
243
244 void MFRenderingOptions::translateRegClassNamesToCurrentFunction() const {
245 if (!regClassesTranslatedToCurrentFunction) {
246 processOptions();
247 for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
248 rcEnd = tri->regclass_end();
249 rcItr != rcEnd; ++rcItr) {
250 const TargetRegisterClass *trc = *rcItr;
251 if (renderAllClasses ||
252 classNamesToRender.find(trc->getName()) !=
253 classNamesToRender.end()) {
254 regClassSet.insert(trc);
255 }
256 }
257 regClassesTranslatedToCurrentFunction = true;
258 }
259 }
260
261 void MFRenderingOptions::translateIntervalNumbersToCurrentFunction() const {
262 if (!intervalsTranslatedToCurrentFunction) {
263 processOptions();
264
265 // If we're not just doing explicit then do a copy over all matching
266 // types.
267 if (intervalTypesToRender != ExplicitOnly) {
268 for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end();
269 liItr != liEnd; ++liItr) {
270 LiveInterval *li = liItr->second;
271
272 if (filterEmpty && li->empty())
273 continue;
274
275 if ((TargetRegisterInfo::isPhysicalRegister(li->reg) &&
276 (intervalTypesToRender & AllPhys))) {
277 intervalSet.insert(li);
278 } else if (TargetRegisterInfo::isVirtualRegister(li->reg)) {
279 if (((intervalTypesToRender & VirtNoSpills) && !rmf->isSpill(li)) ||
280 ((intervalTypesToRender & VirtSpills) && rmf->isSpill(li))) {
281 intervalSet.insert(li);
282 }
283 }
284 }
285 }
286
287 // If we need to process the explicit list...
288 if (intervalTypesToRender != All) {
289 for (std::set >::const_iterator
290 regRangeItr = intervalNumsToRender.begin(),
291 regRangeEnd = intervalNumsToRender.end();
292 regRangeItr != regRangeEnd; ++regRangeItr) {
293 const std::pair &range = *regRangeItr;
294 for (unsigned reg = range.first; reg != range.second; ++reg) {
295 if (lis->hasInterval(reg)) {
296 intervalSet.insert(&lis->getInterval(reg));
297 }
298 }
299 }
300 }
301
302 intervalsTranslatedToCurrentFunction = true;
303 }
304 }
305
306 // ---------- TargetRegisterExtraInformation implementation ----------
307
308 TargetRegisterExtraInfo::TargetRegisterExtraInfo()
309 : mapsPopulated(false) {
310 }
311
312 void TargetRegisterExtraInfo::setup(MachineFunction *mf,
313 MachineRegisterInfo *mri,
314 const TargetRegisterInfo *tri,
315 LiveIntervals *lis) {
316 this->mf = mf;
317 this->mri = mri;
318 this->tri = tri;
319 this->lis = lis;
320 }
321
322 void TargetRegisterExtraInfo::reset() {
323 if (!mapsPopulated) {
324 initWorst();
325 //initBounds();
326 initCapacity();
327 mapsPopulated = true;
328 }
329
330 resetPressureAndLiveStates();
331 }
332
333 void TargetRegisterExtraInfo::clear() {
334 prWorst.clear();
335 vrWorst.clear();
336 capacityMap.clear();
337 pressureMap.clear();
338 //liveStatesMap.clear();
339 mapsPopulated = false;
340 }
341
342 void TargetRegisterExtraInfo::initWorst() {
343 assert(!mapsPopulated && prWorst.empty() && vrWorst.empty() &&
344 "Worst map already initialised?");
345
346 // Start with the physical registers.
347 for (unsigned preg = 1; preg < tri->getNumRegs(); ++preg) {
348 WorstMapLine &pregLine = prWorst[preg];
349
350 for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
351 rcEnd = tri->regclass_end();
352 rcItr != rcEnd; ++rcItr) {
353 const TargetRegisterClass *trc = *rcItr;
354
355 unsigned numOverlaps = 0;
356 for (TargetRegisterClass::iterator rItr = trc->begin(),
357 rEnd = trc->end();
358 rItr != rEnd; ++rItr) {
359 unsigned trcPReg = *rItr;
360 if (tri->regsOverlap(preg, trcPReg))
361 ++numOverlaps;
362 }
363
364 pregLine[trc] = numOverlaps;
365 }
366 }
367
368 // Now the register classes.
369 for (TargetRegisterInfo::regclass_iterator rc1Itr = tri->regclass_begin(),
370 rcEnd = tri->regclass_end();
371 rc1Itr != rcEnd; ++rc1Itr) {
372 const TargetRegisterClass *trc1 = *rc1Itr;
373 WorstMapLine &classLine = vrWorst[trc1];
374
375 for (TargetRegisterInfo::regclass_iterator rc2Itr = tri->regclass_begin();
376 rc2Itr != rcEnd; ++rc2Itr) {
377 const TargetRegisterClass *trc2 = *rc2Itr;
378
379 unsigned worst = 0;
380
381 for (TargetRegisterClass::iterator trc1Itr = trc1->begin(),
382 trc1End = trc1->end();
383 trc1Itr != trc1End; ++trc1Itr) {
384 unsigned trc1Reg = *trc1Itr;
385 unsigned trc1RegWorst = 0;
386
387 for (TargetRegisterClass::iterator trc2Itr = trc2->begin(),
388 trc2End = trc2->end();
389 trc2Itr != trc2End; ++trc2Itr) {
390 unsigned trc2Reg = *trc2Itr;
391 if (tri->regsOverlap(trc1Reg, trc2Reg))
392 ++trc1RegWorst;
393 }
394 if (trc1RegWorst > worst) {
395 worst = trc1RegWorst;
396 }
397 }
398
399 if (worst != 0) {
400 classLine[trc2] = worst;
401 }
402 }
403 }
404 }
405
406 unsigned TargetRegisterExtraInfo::getWorst(
407 unsigned reg,
408 const TargetRegisterClass *trc) const {
409 const WorstMapLine *wml = 0;
410 if (TargetRegisterInfo::isPhysicalRegister(reg)) {
411 PRWorstMap::const_iterator prwItr = prWorst.find(reg);
412 assert(prwItr != prWorst.end() && "Missing prWorst entry.");
413 wml = &prwItr->second;
414 } else {
415 const TargetRegisterClass *regTRC = mri->getRegClass(reg);
416 VRWorstMap::const_iterator vrwItr = vrWorst.find(regTRC);
417 assert(vrwItr != vrWorst.end() && "Missing vrWorst entry.");
418 wml = &vrwItr->second;
419 }
420
421 WorstMapLine::const_iterator wmlItr = wml->find(trc);
422 if (wmlItr == wml->end())
423 return 0;
424
425 return wmlItr->second;
426 }
427
428 void TargetRegisterExtraInfo::initCapacity() {
429 assert(!mapsPopulated && capacityMap.empty() &&
430 "Capacity map already initialised?");
431
432 for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(),
433 rcEnd = tri->regclass_end();
434 rcItr != rcEnd; ++rcItr) {
435 const TargetRegisterClass *trc = *rcItr;
436 unsigned capacity = trc->getRawAllocationOrder(*mf).size();
437
438 if (capacity != 0)
439 capacityMap[trc] = capacity;
440 }
441 }
442
443 unsigned TargetRegisterExtraInfo::getCapacity(
444 const TargetRegisterClass *trc) const {
445 CapacityMap::const_iterator cmItr = capacityMap.find(trc);
446 assert(cmItr != capacityMap.end() &&
447 "vreg with unallocable register class");
448 return cmItr->second;
449 }
450
451 void TargetRegisterExtraInfo::resetPressureAndLiveStates() {
452 pressureMap.clear();
453 //liveStatesMap.clear();
454
455 // Iterate over all slots.
456
457
458 // Iterate over all live intervals.
459 for (LiveIntervals::iterator liItr = lis->begin(),
460 liEnd = lis->end();
461 liItr != liEnd; ++liItr) {
462 LiveInterval *li = liItr->second;
463
464 if (TargetRegisterInfo::isPhysicalRegister(li->reg))
465 continue;
466
467 // For all ranges in the current interal.
468 for (LiveInterval::iterator lrItr = li->begin(),
469 lrEnd = li->end();
470 lrItr != lrEnd; ++lrItr) {
471 LiveRange *lr = &*lrItr;
472
473 // For all slots in the current range.
474 for (SlotIndex i = lr->start; i != lr->end; i = i.getNextSlot()) {
475
476 // Record increased pressure at index for all overlapping classes.
477 for (TargetRegisterInfo::regclass_iterator
478 rcItr = tri->regclass_begin(),
479 rcEnd = tri->regclass_end();
480 rcItr != rcEnd; ++rcItr) {
481 const TargetRegisterClass *trc = *rcItr;
482
483 if (trc->getRawAllocationOrder(*mf).empty())
484 continue;
485
486 unsigned worstAtI = getWorst(li->reg, trc);
487
488 if (worstAtI != 0) {
489 pressureMap[i][trc] += worstAtI;
490 }
491 }
492 }
493 }
494 }
495 }
496
497 unsigned TargetRegisterExtraInfo::getPressureAtSlot(
498 const TargetRegisterClass *trc,
499 SlotIndex i) const {
500 PressureMap::const_iterator pmItr = pressureMap.find(i);
501 if (pmItr == pressureMap.end())
502 return 0;
503 const PressureMapLine &pmLine = pmItr->second;
504 PressureMapLine::const_iterator pmlItr = pmLine.find(trc);
505 if (pmlItr == pmLine.end())
506 return 0;
507 return pmlItr->second;
508 }
509
510 bool TargetRegisterExtraInfo::classOverCapacityAtSlot(
511 const TargetRegisterClass *trc,
512 SlotIndex i) const {
513 return (getPressureAtSlot(trc, i) > getCapacity(trc));
514 }
515
516 // ---------- MachineFunctionRenderer implementation ----------
517
518 void RenderMachineFunction::Spacer::print(raw_ostream &os) const {
519 if (!prettyHTML)
520 return;
521 for (unsigned i = 0; i < ns; ++i) {
522 os << " ";
523 }
524 }
525
526 RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const {
527 return Spacer(ns);
528 }
529
530 raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) {
531 s.print(os);
532 return os;
533 }
534
535 template
536 std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const {
537 std::string r;
538
539 for (Iterator sItr = sBegin; sItr != sEnd; ++sItr) {
540 char c = *sItr;
541
542 switch (c) {
543 case '<': r.append("<"); break;
544 case '>': r.append(">"); break;
545 case '&': r.append("&"); break;
546 case ' ': r.append(" "); break;
547 case '\"': r.append("""); break;
548 default: r.push_back(c); break;
549 }
550 }
551
552 return r;
553 }
554
555 RenderMachineFunction::LiveState
556 RenderMachineFunction::getLiveStateAt(const LiveInterval *li,
557 SlotIndex i) const {
558 const MachineInstr *mi = sis->getInstructionFromIndex(i);
559
560 // For uses/defs recorded use/def indexes override current liveness and
561 // instruction operands (Only for the interval which records the indexes).
562 // FIXME: This is all wrong, uses and defs share the same slots.
563 if (i.isEarlyClobber() || i.isRegister()) {
564 UseDefs::const_iterator udItr = useDefs.find(li);
565 if (udItr != useDefs.end()) {
566 const SlotSet &slotSet = udItr->second;
567 if (slotSet.count(i)) {
568 if (i.isEarlyClobber()) {
569 return Used;
570 }
571 // else
572 return Defined;
573 }
574 }
575 }
576
577 // If the slot is a load/store, or there's no info in the use/def set then
578 // use liveness and instruction operand info.
579 if (li->liveAt(i)) {
580
581 if (mi == 0) {
582 if (vrm == 0 ||
583 (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
584 return AliveReg;
585 } else {
586 return AliveStack;
587 }
588 } else {
589 if (i.isRegister() && mi->definesRegister(li->reg, tri)) {
590 return Defined;
591 } else if (i.isEarlyClobber() && mi->readsRegister(li->reg)) {
592 return Used;
593 } else {
594 if (vrm == 0 ||
595 (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) {
596 return AliveReg;
597 } else {
598 return AliveStack;
599 }
600 }
601 }
602 }
603 return Dead;
604 }
605
606 RenderMachineFunction::PressureState
607 RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc,
608 SlotIndex i) const {
609 if (trei.getPressureAtSlot(trc, i) == 0) {
610 return Zero;
611 } else if (trei.classOverCapacityAtSlot(trc, i)){
612 return High;
613 }
614 return Low;
615 }
616
617 /// \brief Render a machine instruction.
618 void RenderMachineFunction::renderMachineInstr(raw_ostream &os,
619 const MachineInstr *mi) const {
620 std::string s;
621 raw_string_ostream oss(s);
622 oss << *mi;
623
624 os << escapeChars(oss.str());
625 }
626
627 template
628 void RenderMachineFunction::renderVertical(const Spacer &indent,
629 raw_ostream &os,
630 const T &t) const {
631 if (ro.fancyVerticals()) {
632 os << indent << "
633 << indent + s(2) << "class=\"obj\"\n"
634 << indent + s(2) << "type=\"image/svg+xml\"\n"
635 << indent + s(2) << "width=\"14px\"\n"
636 << indent + s(2) << "height=\"55px\"\n"
637 << indent + s(2) << "data=\"data:image/svg+xml,\n"
638 << indent + s(4) << "\n"
639 << indent + s(6) << "
640 "font-family='Courier' font-size='12' "
641 "transform='rotate(-90)' "
642 "text-rendering='optimizeSpeed' "
643 "fill='#000'>" << t << "\n"
644 << indent + s(4) << "\">\n"
645 << indent << "\n";
646 } else {
647 std::ostringstream oss;
648 oss << t;
649 std::string tStr(oss.str());
650
651 os << indent;
652 for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end();
653 tStrItr != tStrEnd; ++tStrItr) {
654 os << *tStrItr << "
";
655 }
656 os << "\n";
657 }
658 }
659
660 void RenderMachineFunction::insertCSS(const Spacer &indent,
661 raw_ostream &os) const {
662 os << indent << "\n";
678 }
679
680 void RenderMachineFunction::renderFunctionSummary(
681 const Spacer &indent, raw_ostream &os,
682 const char * const renderContextStr) const {
683 os << indent << "

Function: " << mf->getFunction()->getName()

684 << "\n"
685 << indent << "

Rendering context: " << renderContextStr << "

\n";
686 }
687
688
689 void RenderMachineFunction::renderPressureTableLegend(
690 const Spacer &indent,
691 raw_ostream &os) const {
692 os << indent << "

Rendering Pressure Legend:

\n"
693 << indent << "\n" \n" " \n" \n" \n" " " \n" \n" \n" " " \n" \n" \n" " " \n" \n"
694 << indent + s(2) << "
695 << indent + s(4) << "PressureDescription
696 "Appearance
697 << indent + s(2) << "
698 << indent + s(2) << "
699 << indent + s(4) << "No Pressure
700 "No physical registers of this class requested.
701 "  
702 << indent + s(2) << "
703 << indent + s(2) << "
704 << indent + s(4) << "Low Pressure
705 "Sufficient physical registers to meet demand.
706 "  
707 << indent + s(2) << "
708 << indent + s(2) << "
709 << indent + s(4) << "High Pressure
710 "Potentially insufficient physical registers to meet demand.
711 "  
712 << indent + s(2) << "
713 << indent << "
\n";
714 }
715
716 template
717 void RenderMachineFunction::renderCellsWithRLE(
718 const Spacer &indent, raw_ostream &os,
719 const std::pair &rleAccumulator,
720 const std::map &cellTypeStrs) const {
721
722 if (rleAccumulator.second == 0)
723 return;
724
725 typename std::map::const_iterator ctsItr =
726 cellTypeStrs.find(rleAccumulator.first);
727
728 assert(ctsItr != cellTypeStrs.end() && "No string for given cell type.");
729
730 os << indent + s(4) << "second << "\"";
731 if (rleAccumulator.second > 1)
732 os << " colspan=" << rleAccumulator.second;
733 os << ">
734 }
735
736
737 void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent,
738 raw_ostream &os) const {
739
740 std::map lsStrs;
741 lsStrs[Dead] = "l-n";
742 lsStrs[Defined] = "l-d";
743 lsStrs[Used] = "l-u";
744 lsStrs[AliveReg] = "l-r";
745 lsStrs[AliveStack] = "l-s";
746
747 std::map psStrs;
748 psStrs[Zero] = "p-z";
749 psStrs[Low] = "p-l";
750 psStrs[High] = "p-h";
751
752 // Open the table...
753
754 os << indent << "\n" \n"; \n" \n"; \n"; \n"; \n"; \n" \n"; \n"; \n";
755 << indent + s(2) << "
756
757 // Render the header row...
758
759 os << indent + s(4) << "index
760 << indent + s(4) << "instr
761
762 // Render class names if necessary...
763 if (!ro.regClasses().empty()) {
764 for (MFRenderingOptions::RegClassSet::const_iterator
765 rcItr = ro.regClasses().begin(),
766 rcEnd = ro.regClasses().end();
767 rcItr != rcEnd; ++rcItr) {
768 const TargetRegisterClass *trc = *rcItr;
769 os << indent + s(4) << "\n";
770 renderVertical(indent + s(6), os, trc->getName());
771 os << indent + s(4) << "\n";
772 }
773 }
774
775 // FIXME: Is there a nicer way to insert space between columns in HTML?
776 if (!ro.regClasses().empty() && !ro.intervals().empty())
777 os << indent + s(4) << "  
778
779 // Render interval numbers if necessary...
780 if (!ro.intervals().empty()) {
781 for (MFRenderingOptions::IntervalSet::const_iterator
782 liItr = ro.intervals().begin(),
783 liEnd = ro.intervals().end();
784 liItr != liEnd; ++liItr) {
785
786 const LiveInterval *li = *liItr;
787 os << indent + s(4) << "\n";
788 renderVertical(indent + s(6), os, li->reg);
789 os << indent + s(4) << "\n";
790 }
791 }
792
793 os << indent + s(2) << "
794
795 // End header row, start with the data rows...
796
797 MachineInstr *mi = 0;
798
799 // Data rows:
800 for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex();
801 i = i.getNextSlot()) {
802
803 // Render the slot column.
804 os << indent + s(2) << "
805
806 // Render the code column.
807 if (i.isBlock()) {
808 MachineBasicBlock *mbb = sis->getMBBFromIndex(i);
809 mi = sis->getInstructionFromIndex(i);
810
811 if (i == sis->getMBBStartIdx(mbb) || mi != 0 ||
812 ro.renderEmptyIndexes()) {
813 os << indent + s(4) << "" << i << " 
814 << indent + s(4) << "\n";
815
816 if (i == sis->getMBBStartIdx(mbb)) {
817 os << indent + s(6) << "BB#" << mbb->getNumber() << ": \n";
818 } else if (mi != 0) {
819 os << indent + s(6) << "  ";
820 renderMachineInstr(os, mi);
821 } else {
822 // Empty interval - leave blank.
823 }
824 os << indent + s(4) << "
825 } else {
826 i = i.getDeadSlot(); // <- Will be incremented to the next index.
827 continue;
828 }
829 }
830
831 // Render the class columns.
832 if (!ro.regClasses().empty()) {
833 std::pair psRLEAccumulator(Zero, 0);
834 for (MFRenderingOptions::RegClassSet::const_iterator
835 rcItr = ro.regClasses().begin(),
836 rcEnd = ro.regClasses().end();
837 rcItr != rcEnd; ++rcItr) {
838 const TargetRegisterClass *trc = *rcItr;
839 PressureState newPressure = getPressureStateAt(trc, i);
840
841 if (newPressure == psRLEAccumulator.first) {
842 ++psRLEAccumulator.second;
843 } else {
844 renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
845 psRLEAccumulator.first = newPressure;
846 psRLEAccumulator.second = 1;
847 }
848 }
849 renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs);
850 }
851
852 // FIXME: Is there a nicer way to insert space between columns in HTML?
853 if (!ro.regClasses().empty() && !ro.intervals().empty())
854 os << indent + s(4) << "
855
856 if (!ro.intervals().empty()) {
857 std::pair lsRLEAccumulator(Dead, 0);
858 for (MFRenderingOptions::IntervalSet::const_iterator
859 liItr = ro.intervals().begin(),
860 liEnd = ro.intervals().end();
861 liItr != liEnd; ++liItr) {
862 const LiveInterval *li = *liItr;
863 LiveState newLiveness = getLiveStateAt(li, i);
864
865 if (newLiveness == lsRLEAccumulator.first) {
866 ++lsRLEAccumulator.second;
867 } else {
868 renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
869 lsRLEAccumulator.first = newLiveness;
870 lsRLEAccumulator.second = 1;
871 }
872 }
873 renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs);
874 }
875 os << indent + s(2) << "
876 }
877
878 os << indent << "
\n";
879
880 if (!ro.regClasses().empty())
881 renderPressureTableLegend(indent, os);
882 }
883
884 void RenderMachineFunction::renderFunctionPage(
885 raw_ostream &os,
886 const char * const renderContextStr) const {
887 os << "\n"
888 << s(2) << "\n"
889 << s(4) << "" << fqn << "\n";
890
891 insertCSS(s(4), os);
892
893 os << s(2) << "\n"
894 << s(2) << "\n";
895
896 renderFunctionSummary(s(4), os, renderContextStr);
897
898 os << s(4) << "


\n";
899
900 //renderLiveIntervalInfoTable(" ", os);
901
902 os << s(4) << "


\n";
903
904 renderCodeTablePlusPI(s(4), os);
905
906 os << s(2) << "\n"
907 << "\n";
908 }
909
910 void RenderMachineFunction::getAnalysisUsage(AnalysisUsage &au) const {
911 au.addRequired();
912 au.addRequired();
913 au.setPreservesAll();
914 MachineFunctionPass::getAnalysisUsage(au);
915 }
916
917 bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) {
918
919 mf = &fn;
920 mri = &mf->getRegInfo();
921 tri = mf->getTarget().getRegisterInfo();
922 lis = &getAnalysis();
923 sis = &getAnalysis();
924
925 trei.setup(mf, mri, tri, lis);
926 ro.setup(mf, tri, lis, this);
927 spillIntervals.clear();
928 spillFor.clear();
929 useDefs.clear();
930
931 fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." +
932 mf->getFunction()->getName().str();
933
934 return false;
935 }
936
937 void RenderMachineFunction::releaseMemory() {
938 trei.clear();
939 ro.clear();
940 spillIntervals.clear();
941 spillFor.clear();
942 useDefs.clear();
943 }
944
945 void RenderMachineFunction::rememberUseDefs(const LiveInterval *li) {
946
947 if (!ro.shouldRenderCurrentMachineFunction())
948 return;
949
950 for (MachineRegisterInfo::reg_iterator rItr = mri->reg_begin(li->reg),
951 rEnd = mri->reg_end();
952 rItr != rEnd; ++rItr) {
953 const MachineInstr *mi = &*rItr;
954 if (mi->readsRegister(li->reg)) {
955 useDefs[li].insert(lis->getInstructionIndex(mi).getRegSlot(true));
956 }
957 if (mi->definesRegister(li->reg)) {
958 useDefs[li].insert(lis->getInstructionIndex(mi).getRegSlot());
959 }
960 }
961 }
962
963 void RenderMachineFunction::rememberSpills(
964 const LiveInterval *li,
965 const std::vector &spills) {
966
967 if (!ro.shouldRenderCurrentMachineFunction())
968 return;
969
970 for (std::vector::const_iterator siItr = spills.begin(),
971 siEnd = spills.end();
972 siItr != siEnd; ++siItr) {
973 const LiveInterval *spill = *siItr;
974 spillIntervals[li].insert(spill);
975 spillFor[spill] = li;
976 }
977 }
978
979 bool RenderMachineFunction::isSpill(const LiveInterval *li) const {
980 SpillForMap::const_iterator sfItr = spillFor.find(li);
981 if (sfItr == spillFor.end())
982 return false;
983 return true;
984 }
985
986 void RenderMachineFunction::renderMachineFunction(
987 const char *renderContextStr,
988 const VirtRegMap *vrm,
989 const char *renderSuffix) {
990 if (!ro.shouldRenderCurrentMachineFunction())
991 return;
992
993 this->vrm = vrm;
994 trei.reset();
995
996 std::string rpFileName(mf->getFunction()->getName().str() +
997 (renderSuffix ? renderSuffix : "") +
998 outputFileSuffix);
999
1000 std::string errMsg;
1001 raw_fd_ostream outFile(rpFileName.c_str(), errMsg, raw_fd_ostream::F_Binary);
1002
1003 renderFunctionPage(outFile, renderContextStr);
1004
1005 ro.resetRenderSpecificOptions();
1006 }
1007
1008 std::string RenderMachineFunction::escapeChars(const std::string &s) const {
1009 return escapeChars(s.begin(), s.end());
1010 }
1011
1012 }
+0
-338
lib/CodeGen/RenderMachineFunction.h less more
None //===-- llvm/CodeGen/RenderMachineFunction.h - MF->HTML -*- C++ -*---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //===----------------------------------------------------------------------===//
10
11 #ifndef LLVM_CODEGEN_RENDERMACHINEFUNCTION_H
12 #define LLVM_CODEGEN_RENDERMACHINEFUNCTION_H
13
14 #include "llvm/CodeGen/LiveInterval.h"
15 #include "llvm/CodeGen/MachineFunctionPass.h"
16 #include "llvm/CodeGen/SlotIndexes.h"
17 #include "llvm/Target/TargetRegisterInfo.h"
18
19 #include
20 #include
21 #include
22 #include
23
24 namespace llvm {
25
26 class LiveInterval;
27 class LiveIntervals;
28 class MachineInstr;
29 class MachineRegisterInfo;
30 class RenderMachineFunction;
31 class TargetRegisterClass;
32 class TargetRegisterInfo;
33 class VirtRegMap;
34 class raw_ostream;
35
36 /// \brief Helper class to process rendering options. Tries to be as lazy as
37 /// possible.
38 class MFRenderingOptions {
39 public:
40
41 struct RegClassComp {
42 bool operator()(const TargetRegisterClass *trc1,
43 const TargetRegisterClass *trc2) const {
44 std::string trc1Name(trc1->getName()), trc2Name(trc2->getName());
45 return std::lexicographical_compare(trc1Name.begin(), trc1Name.end(),
46 trc2Name.begin(), trc2Name.end());
47 }
48 };
49
50 typedef std::set RegClassSet;
51
52 struct IntervalComp {
53 bool operator()(const LiveInterval *li1, const LiveInterval *li2) const {
54 return li1->reg < li2->reg;
55 }
56 };
57
58 typedef std::set IntervalSet;
59
60 /// Initialise the rendering options.
61 void setup(MachineFunction *mf, const TargetRegisterInfo *tri,
62 LiveIntervals *lis, const RenderMachineFunction *rmf);
63
64 /// Clear translations of options to the current function.
65 void clear();
66
67 /// Reset any options computed for this specific rendering.
68 void resetRenderSpecificOptions();
69
70 /// Should we render the current function.
71 bool shouldRenderCurrentMachineFunction() const;
72
73 /// Return the set of register classes to render pressure for.
74 const RegClassSet& regClasses() const;
75
76 /// Return the set of live intervals to render liveness for.
77 const IntervalSet& intervals() const;
78
79 /// Render indexes which are not associated with instructions / MBB starts.
80 bool renderEmptyIndexes() const;
81
82 /// Return whether or not to render using SVG for fancy vertical text.
83 bool fancyVerticals() const;
84
85 private:
86
87 static bool renderingOptionsProcessed;
88 static std::set mfNamesToRender;
89 static bool renderAllMFs;
90
91 static std::set classNamesToRender;
92 static bool renderAllClasses;
93
94
95 static std::set > intervalNumsToRender;
96 typedef enum { ExplicitOnly = 0,
97 AllPhys = 1,
98 VirtNoSpills = 2,
99 VirtSpills = 4,
100 AllVirt = 6,
101 All = 7 }
102 IntervalTypesToRender;
103 static unsigned intervalTypesToRender;
104
105 template
106 static void splitComaSeperatedList(const std::string &s, OutputItr outItr);
107
108 static void processOptions();
109
110 static void processFuncNames();
111 static void processRegClassNames();
112 static void processIntervalNumbers();
113
114 static void processIntervalRange(const std::string &intervalRangeStr);
115
116 MachineFunction *mf;
117 const TargetRegisterInfo *tri;
118 LiveIntervals *lis;
119 const RenderMachineFunction *rmf;
120
121 mutable bool regClassesTranslatedToCurrentFunction;
122 mutable RegClassSet regClassSet;
123
124 mutable bool intervalsTranslatedToCurrentFunction;
125 mutable IntervalSet intervalSet;
126
127 void translateRegClassNamesToCurrentFunction() const;
128
129 void translateIntervalNumbersToCurrentFunction() const;
130 };
131
132 /// \brief Provide extra information about the physical and virtual registers
133 /// in the function being compiled.
134 class TargetRegisterExtraInfo {
135 public:
136 TargetRegisterExtraInfo();
137
138 /// \brief Set up TargetRegisterExtraInfo with pointers to necessary
139 /// sources of information.
140 void setup(MachineFunction *mf, MachineRegisterInfo *mri,
141 const TargetRegisterInfo *tri, LiveIntervals *lis);
142
143 /// \brief Recompute tables for changed function.
144 void reset();
145
146 /// \brief Free all tables in TargetRegisterExtraInfo.
147 void clear();
148
149 /// \brief Maximum number of registers from trc which alias reg.
150 unsigned getWorst(unsigned reg, const TargetRegisterClass *trc) const;
151
152 /// \brief Returns the number of allocable registers in trc.
153 unsigned getCapacity(const TargetRegisterClass *trc) const;
154
155 /// \brief Return the number of registers of class trc that may be
156 /// needed at slot i.
157 unsigned getPressureAtSlot(const TargetRegisterClass *trc,
158 SlotIndex i) const;
159
160 /// \brief Return true if the number of registers of type trc that may be
161 /// needed at slot i is greater than the capacity of trc.
162 bool classOverCapacityAtSlot(const TargetRegisterClass *trc,
163 SlotIndex i) const;
164
165 private:
166
167 MachineFunction *mf;
168 MachineRegisterInfo *mri;
169 const TargetRegisterInfo *tri;
170 LiveIntervals *lis;
171
172 typedef std::map WorstMapLine;
173 typedef std::map VRWorstMap;
174 VRWorstMap vrWorst;
175
176 typedef std::map PRWorstMap;
177 PRWorstMap prWorst;
178
179 typedef std::map CapacityMap;
180 CapacityMap capacityMap;
181
182 typedef std::map PressureMapLine;
183 typedef std::map PressureMap;
184 PressureMap pressureMap;
185
186 bool mapsPopulated;
187
188 /// \brief Initialise the 'worst' table.
189 void initWorst();
190
191 /// \brief Initialise the 'capacity' table.
192 void initCapacity();
193
194 /// \brief Initialise/Reset the 'pressure' and live states tables.
195 void resetPressureAndLiveStates();
196 };
197
198 /// \brief Render MachineFunction objects and related information to a HTML
199 /// page.
200 class RenderMachineFunction : public MachineFunctionPass {
201 public:
202 static char ID;
203
204 RenderMachineFunction() : MachineFunctionPass(ID) {
205 initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry());
206 }
207
208 virtual void getAnalysisUsage(AnalysisUsage &au) const;
209
210 virtual bool runOnMachineFunction(MachineFunction &fn);
211
212 virtual void releaseMemory();
213
214 void rememberUseDefs(const LiveInterval *li);
215
216 void rememberSpills(const LiveInterval *li,
217 const std::vector &spills);
218
219 bool isSpill(const LiveInterval *li) const;
220
221 /// \brief Render this machine function to HTML.
222 ///
223 /// @param renderContextStr This parameter will be included in the top of
224 /// the html file to explain where (in the
225 /// codegen pipeline) this function was rendered
226 /// from. Set it to something like
227 /// "Pre-register-allocation".
228 /// @param vrm If non-null the VRM will be queried to determine
229 /// whether a virtual register was allocated to a
230 /// physical register or spilled.
231 /// @param renderFilePrefix This string will be appended to the function
232 /// name (before the output file suffix) to enable
233 /// multiple renderings from the same function.
234 void renderMachineFunction(const char *renderContextStr,
235 const VirtRegMap *vrm = 0,
236 const char *renderSuffix = 0);
237
238 private:
239 class Spacer;
240 friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s);
241
242 std::string fqn;
243
244 MachineFunction *mf;
245 MachineRegisterInfo *mri;
246 const TargetRegisterInfo *tri;
247 LiveIntervals *lis;
248 SlotIndexes *sis;
249 const VirtRegMap *vrm;
250
251 TargetRegisterExtraInfo trei;
252 MFRenderingOptions ro;
253
254
255
256 // Utilities.
257 typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState;
258 LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const;
259
260 typedef enum { Zero, Low, High } PressureState;
261 PressureState getPressureStateAt(const TargetRegisterClass *trc,
262 SlotIndex i) const;
263
264 typedef std::map >
265 SpillIntervals;
266 SpillIntervals spillIntervals;
267
268 typedef std::map SpillForMap;
269 SpillForMap spillFor;
270
271 typedef std::set SlotSet;
272 typedef std::map UseDefs;
273 UseDefs useDefs;
274
275 // ---------- Rendering methods ----------
276
277 /// For inserting spaces when pretty printing.
278 class Spacer {
279 public:
280 explicit Spacer(unsigned numSpaces) : ns(numSpaces) {}
281 Spacer operator+(const Spacer &o) const { return Spacer(ns + o.ns); }
282 void print(raw_ostream &os) const;
283 private:
284 unsigned ns;
285 };
286
287 Spacer s(unsigned ns) const;
288
289 template
290 std::string escapeChars(Iterator sBegin, Iterator sEnd) const;
291
292 /// \brief Render a machine instruction.
293 void renderMachineInstr(raw_ostream &os,
294 const MachineInstr *mi) const;
295
296 /// \brief Render vertical text.
297 template
298 void renderVertical(const Spacer &indent,
299 raw_ostream &os,
300 const T &t) const;
301
302 /// \brief Insert CSS layout info.
303 void insertCSS(const Spacer &indent,
304 raw_ostream &os) const;
305
306 /// \brief Render a brief summary of the function (including rendering
307 /// context).
308 void renderFunctionSummary(const Spacer &indent,
309 raw_ostream &os,
310 const char * const renderContextStr) const;
311
312 /// \brief Render a legend for the pressure table.
313 void renderPressureTableLegend(const Spacer &indent,
314 raw_ostream &os) const;
315
316 /// \brief Render a consecutive set of HTML cells of the same class using
317 /// the colspan attribute for run-length encoding.
318 template
319 void renderCellsWithRLE(
320 const Spacer &indent, raw_ostream &os,
321 const std::pair &rleAccumulator,
322 const std::map &cellTypeStrs) const;
323
324 /// \brief Render code listing, potentially with register pressure
325 /// and live intervals shown alongside.
326 void renderCodeTablePlusPI(const Spacer &indent,
327 raw_ostream &os) const;
328
329 /// \brief Render the HTML page representing the MachineFunction.
330 void renderFunctionPage(raw_ostream &os,
331 const char * const renderContextStr) const;
332
333 std::string escapeChars(const std::string &s) const;
334 };
335 }
336
337 #endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */