llvm.org GIT mirror llvm / 9a61a42
CodeGen: Use a single SlotTracker in MachineFunction::print() Expose enough of the IR-level `SlotTracker` so that `MachineFunction::print()` can use a single one for printing `BasicBlock`s. Next step would be to lift this through a few more APIs so that we can make other print methods faster. Fixes PR23865, changing the runtime of `llc -print-machineinstrs` from many minutes (killed after 3 minutes, but it wasn't very close) to 13 seconds for a 502185 line dump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240842 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 4 years ago
6 changed file(s) with 167 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
659659 // Debugging methods.
660660 void dump() const;
661661 void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
662 void print(raw_ostream &OS, ModuleSlotTracker &MST,
663 SlotIndexes * = nullptr) const;
662664
663665 // Printing method used by LoopInfo.
664666 void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
0 //===-- llvm/IR/ModuleSlotTracker.h -----------------------------*- 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 #ifndef LLVM_IR_MODULESLOTTRACKER_H
10 #define LLVM_IR_MODULESLOTTRACKER_H
11
12 #include
13
14 namespace llvm {
15
16 class Module;
17 class Function;
18 class SlotTracker;
19
20 /// Manage lifetime of a slot tracker for printing IR.
21 ///
22 /// Wrapper around the \a SlotTracker used internally by \a AsmWriter. This
23 /// class allows callers to share the cost of incorporating the metadata in a
24 /// module or a function.
25 ///
26 /// If the IR changes from underneath \a ModuleSlotTracker, strings like
27 /// "" will be printed, or, worse, the wrong slots entirely.
28 class ModuleSlotTracker {
29 /// Storage for a slot tracker.
30 std::unique_ptr MachineStorage;
31
32 const Module *M = nullptr;
33 const Function *F = nullptr;
34 SlotTracker *Machine = nullptr;
35
36 public:
37 /// Wrap a preinitialized SlotTracker.
38 ModuleSlotTracker(SlotTracker &Machine, const Module *M,
39 const Function *F = nullptr);
40
41 /// Construct a slot tracker from a module.
42 ///
43 /// If \a M is \c nullptr, uses a null slot tracker.
44 explicit ModuleSlotTracker(const Module *M);
45
46 /// Destructor to clean up storage.
47 ~ModuleSlotTracker();
48
49 SlotTracker *getMachine() const { return Machine; }
50 const Module *getModule() const { return M; }
51 const Function *getCurrentFunction() const { return F; }
52
53 /// Incorporate the given function.
54 ///
55 /// Purge the currently incorporated function and incorporate \c F. If \c F
56 /// is currently incorporated, this is a no-op.
57 void incorporateFunction(const Function &F);
58 };
59
60 } // end namespace llvm
61
62 #endif
3737 class Instruction;
3838 class LLVMContext;
3939 class Module;
40 class ModuleSlotTracker;
4041 class StringRef;
4142 class Twine;
4243 class Type;
206207 /// instruction that generated it. If you specify a Module for context, then
207208 /// even constanst get pretty-printed; for example, the type of a null
208209 /// pointer is printed symbolically.
210 /// @{
209211 void printAsOperand(raw_ostream &O, bool PrintType = true,
210212 const Module *M = nullptr) const;
213 void printAsOperand(raw_ostream &O, bool PrintType,
214 ModuleSlotTracker &MST) const;
215 /// @}
211216
212217 /// \brief All values are typed, get the type of this value.
213218 Type *getType() const { return VTy; }
2323 #include "llvm/CodeGen/SlotIndexes.h"
2424 #include "llvm/IR/BasicBlock.h"
2525 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/ModuleSlotTracker.h"
2627 #include "llvm/MC/MCAsmInfo.h"
2728 #include "llvm/MC/MCContext.h"
2829 #include "llvm/Support/Debug.h"
243244 << " is null\n";
244245 return;
245246 }
247 const Function *F = MF->getFunction();
248 const Module *M = F ? F->getParent() : nullptr;
249 ModuleSlotTracker MST(M);
250 print(OS, MST, Indexes);
251 }
252
253 void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST,
254 SlotIndexes *Indexes) const {
255 const MachineFunction *MF = getParent();
256 if (!MF) {
257 OS << "Can't print out MachineBasicBlock because parent MachineFunction"
258 << " is null\n";
259 return;
260 }
246261
247262 if (Indexes)
248263 OS << Indexes->getMBBStartIdx(this) << '\t';
252267 const char *Comma = "";
253268 if (const BasicBlock *LBB = getBasicBlock()) {
254269 OS << Comma << "derived from LLVM BB ";
255 LBB->printAsOperand(OS, /*PrintType=*/false);
270 LBB->printAsOperand(OS, /*PrintType=*/false, MST);
256271 Comma = ", ";
257272 }
258273 if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; }
2828 #include "llvm/IR/DataLayout.h"
2929 #include "llvm/IR/DebugInfo.h"
3030 #include "llvm/IR/Function.h"
31 #include "llvm/IR/ModuleSlotTracker.h"
3132 #include "llvm/MC/MCAsmInfo.h"
3233 #include "llvm/MC/MCContext.h"
3334 #include "llvm/Support/Debug.h"
360361 OS << '\n';
361362 }
362363
364 ModuleSlotTracker MST(getFunction()->getParent());
365 MST.incorporateFunction(*getFunction());
363366 for (const auto &BB : *this) {
364367 OS << '\n';
365 BB.print(OS, Indexes);
368 BB.print(OS, MST, Indexes);
366369 }
367370
368371 OS << "\n# End machine code for function " << getName() << ".\n\n";
2929 #include "llvm/IR/IntrinsicInst.h"
3030 #include "llvm/IR/LLVMContext.h"
3131 #include "llvm/IR/Module.h"
32 #include "llvm/IR/ModuleSlotTracker.h"
3233 #include "llvm/IR/Operator.h"
3334 #include "llvm/IR/Statepoint.h"
3435 #include "llvm/IR/TypeFinder.h"
543544 OS << '>';
544545 }
545546
546 namespace {
547 namespace llvm {
547548 //===----------------------------------------------------------------------===//
548549 // SlotTracker Class: Enumerate slot numbers for unnamed values
549550 //===----------------------------------------------------------------------===//
662663 SlotTracker(const SlotTracker &) = delete;
663664 void operator=(const SlotTracker &) = delete;
664665 };
665 } // namespace
666 } // namespace llvm
667
668 ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
669 const Function *F)
670 : M(M), F(F), Machine(&Machine) {}
671
672 ModuleSlotTracker::ModuleSlotTracker(const Module *M)
673 : MachineStorage(
674 M ? new SlotTracker(M, /* ShouldInitializeAllMetadata */ true)
675 : nullptr),
676 M(M), Machine(MachineStorage.get()) {}
677
678 ModuleSlotTracker::~ModuleSlotTracker() {}
679
680 void ModuleSlotTracker::incorporateFunction(const Function &F) {
681 if (!Machine)
682 return;
683
684 // Nothing to do if this is the right function already.
685 if (this->F == &F)
686 return;
687 if (this->F)
688 Machine->purgeFunction();
689 Machine->incorporateFunction(&F);
690 this->F = &F;
691 }
666692
667693 static SlotTracker *createSlotTracker(const Module *M) {
668694 return new SlotTracker(M);
19471973 class AssemblyWriter {
19481974 formatted_raw_ostream &Out;
19491975 const Module *TheModule;
1950 std::unique_ptr ModuleSlotTracker;
1976 std::unique_ptr SlotTrackerStorage;
19511977 SlotTracker &Machine;
19521978 TypePrinting TypePrinter;
19531979 AssemblyAnnotationWriter *AnnotationWriter;
20372063 AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, const Module *M,
20382064 AssemblyAnnotationWriter *AAW,
20392065 bool ShouldPreserveUseListOrder)
2040 : Out(o), TheModule(M), ModuleSlotTracker(createSlotTracker(M)),
2041 Machine(*ModuleSlotTracker), AnnotationWriter(AAW),
2066 : Out(o), TheModule(M), SlotTrackerStorage(createSlotTracker(M)),
2067 Machine(*SlotTrackerStorage), AnnotationWriter(AAW),
20422068 ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
20432069 init();
20442070 }
31993225 }
32003226 }
32013227
3202 void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
3203 // Fast path: Don't construct and populate a TypePrinting object if we
3204 // won't be needing any types printed.
3205 bool IsMetadata = isa(this);
3206 if (!PrintType && ((!isa(this) && !IsMetadata) || hasName() ||
3207 isa(this))) {
3208 WriteAsOperandInternal(O, this, nullptr, nullptr, M);
3209 return;
3210 }
3211
3228 /// Print without a type, skipping the TypePrinting object.
3229 ///
3230 /// \return \c true iff printing was succesful.
3231 static bool printWithoutType(const Value &V, raw_ostream &O,
3232 SlotTracker *Machine, const Module *M) {
3233 if (V.hasName() || isa(V) ||
3234 (!isa(V) && !isa(V))) {
3235 WriteAsOperandInternal(O, &V, nullptr, Machine, M);
3236 return true;
3237 }
3238 return false;
3239 }
3240
3241 static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
3242 ModuleSlotTracker &MST) {
3243 TypePrinting TypePrinter;
3244 if (const Module *M = MST.getModule())
3245 TypePrinter.incorporateTypes(*M);
3246 if (PrintType) {
3247 TypePrinter.print(V.getType(), O);
3248 O << ' ';
3249 }
3250
3251 WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(),
3252 MST.getModule());
3253 }
3254
3255 void Value::printAsOperand(raw_ostream &O, bool PrintType,
3256 const Module *M) const {
32123257 if (!M)
32133258 M = getModuleFromVal(this);
32143259
3215 TypePrinting TypePrinter;
3216 if (M)
3217 TypePrinter.incorporateTypes(*M);
3218 if (PrintType) {
3219 TypePrinter.print(getType(), O);
3220 O << ' ';
3221 }
3222
3223 SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata);
3224 WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M);
3260 if (!PrintType)
3261 if (printWithoutType(*this, O, nullptr, M))
3262 return;
3263
3264 SlotTracker Machine(
3265 M, /* ShouldInitializeAllMetadata */ isa(this));
3266 ModuleSlotTracker MST(Machine, M);
3267 printAsOperandImpl(*this, O, PrintType, MST);
3268 }
3269
3270 void Value::printAsOperand(raw_ostream &O, bool PrintType,
3271 ModuleSlotTracker &MST) const {
3272 if (!PrintType)
3273 if (printWithoutType(*this, O, MST.getMachine(), MST.getModule()))
3274 return;
3275
3276 printAsOperandImpl(*this, O, PrintType, MST);
32253277 }
32263278
32273279 static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,