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
This commit is contained in:
Duncan P. N. Exon Smith
2015-06-26 22:04:20 +00:00
parent 0be7d0cf17
commit 9a61a42713
6 changed files with 162 additions and 22 deletions

View File

@@ -30,6 +30,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/TypeFinder.h"
@@ -544,7 +545,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
OS << '>';
}
namespace {
namespace llvm {
//===----------------------------------------------------------------------===//
// SlotTracker Class: Enumerate slot numbers for unnamed values
//===----------------------------------------------------------------------===//
@@ -663,7 +664,32 @@ private:
SlotTracker(const SlotTracker &) = delete;
void operator=(const SlotTracker &) = delete;
};
} // namespace
} // namespace llvm
ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
const Function *F)
: M(M), F(F), Machine(&Machine) {}
ModuleSlotTracker::ModuleSlotTracker(const Module *M)
: MachineStorage(
M ? new SlotTracker(M, /* ShouldInitializeAllMetadata */ true)
: nullptr),
M(M), Machine(MachineStorage.get()) {}
ModuleSlotTracker::~ModuleSlotTracker() {}
void ModuleSlotTracker::incorporateFunction(const Function &F) {
if (!Machine)
return;
// Nothing to do if this is the right function already.
if (this->F == &F)
return;
if (this->F)
Machine->purgeFunction();
Machine->incorporateFunction(&F);
this->F = &F;
}
static SlotTracker *createSlotTracker(const Module *M) {
return new SlotTracker(M);
@@ -1948,7 +1974,7 @@ namespace {
class AssemblyWriter {
formatted_raw_ostream &Out;
const Module *TheModule;
std::unique_ptr<SlotTracker> ModuleSlotTracker;
std::unique_ptr<SlotTracker> SlotTrackerStorage;
SlotTracker &Machine;
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
@@ -2038,8 +2064,8 @@ AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, const Module *M,
AssemblyAnnotationWriter *AAW,
bool ShouldPreserveUseListOrder)
: Out(o), TheModule(M), ModuleSlotTracker(createSlotTracker(M)),
Machine(*ModuleSlotTracker), AnnotationWriter(AAW),
: Out(o), TheModule(M), SlotTrackerStorage(createSlotTracker(M)),
Machine(*SlotTrackerStorage), AnnotationWriter(AAW),
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
init();
}
@@ -3200,29 +3226,55 @@ void Value::print(raw_ostream &ROS) const {
}
}
void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
// Fast path: Don't construct and populate a TypePrinting object if we
// won't be needing any types printed.
bool IsMetadata = isa<MetadataAsValue>(this);
if (!PrintType && ((!isa<Constant>(this) && !IsMetadata) || hasName() ||
isa<GlobalValue>(this))) {
WriteAsOperandInternal(O, this, nullptr, nullptr, M);
return;
/// Print without a type, skipping the TypePrinting object.
///
/// \return \c true iff printing was succesful.
static bool printWithoutType(const Value &V, raw_ostream &O,
SlotTracker *Machine, const Module *M) {
if (V.hasName() || isa<GlobalValue>(V) ||
(!isa<Constant>(V) && !isa<MetadataAsValue>(V))) {
WriteAsOperandInternal(O, &V, nullptr, Machine, M);
return true;
}
return false;
}
if (!M)
M = getModuleFromVal(this);
static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
ModuleSlotTracker &MST) {
TypePrinting TypePrinter;
if (M)
if (const Module *M = MST.getModule())
TypePrinter.incorporateTypes(*M);
if (PrintType) {
TypePrinter.print(getType(), O);
TypePrinter.print(V.getType(), O);
O << ' ';
}
SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata);
WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M);
WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(),
MST.getModule());
}
void Value::printAsOperand(raw_ostream &O, bool PrintType,
const Module *M) const {
if (!M)
M = getModuleFromVal(this);
if (!PrintType)
if (printWithoutType(*this, O, nullptr, M))
return;
SlotTracker Machine(
M, /* ShouldInitializeAllMetadata */ isa<MetadataAsValue>(this));
ModuleSlotTracker MST(Machine, M);
printAsOperandImpl(*this, O, PrintType, MST);
}
void Value::printAsOperand(raw_ostream &O, bool PrintType,
ModuleSlotTracker &MST) const {
if (!PrintType)
if (printWithoutType(*this, O, MST.getMachine(), MST.getModule()))
return;
printAsOperandImpl(*this, O, PrintType, MST);
}
static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,