Skip to content

Commit

Permalink
CodeGen: Use a single SlotTracker in MachineFunction::print()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dexonsmith committed Jun 26, 2015
1 parent 0be7d0c commit 9a61a42
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 22 deletions.
2 changes: 2 additions & 0 deletions include/llvm/CodeGen/MachineBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,8 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
// Debugging methods.
void dump() const;
void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST,
SlotIndexes * = nullptr) const;

// Printing method used by LoopInfo.
void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
Expand Down
63 changes: 63 additions & 0 deletions include/llvm/IR/ModuleSlotTracker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- llvm/IR/ModuleSlotTracker.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IR_MODULESLOTTRACKER_H
#define LLVM_IR_MODULESLOTTRACKER_H

#include <memory>

namespace llvm {

class Module;
class Function;
class SlotTracker;

/// Manage lifetime of a slot tracker for printing IR.
///
/// Wrapper around the \a SlotTracker used internally by \a AsmWriter. This
/// class allows callers to share the cost of incorporating the metadata in a
/// module or a function.
///
/// If the IR changes from underneath \a ModuleSlotTracker, strings like
/// "<badref>" will be printed, or, worse, the wrong slots entirely.
class ModuleSlotTracker {
/// Storage for a slot tracker.
std::unique_ptr<SlotTracker> MachineStorage;

const Module *M = nullptr;
const Function *F = nullptr;
SlotTracker *Machine = nullptr;

public:
/// Wrap a preinitialized SlotTracker.
ModuleSlotTracker(SlotTracker &Machine, const Module *M,
const Function *F = nullptr);

/// Construct a slot tracker from a module.
///
/// If \a M is \c nullptr, uses a null slot tracker.
explicit ModuleSlotTracker(const Module *M);

/// Destructor to clean up storage.
~ModuleSlotTracker();

SlotTracker *getMachine() const { return Machine; }
const Module *getModule() const { return M; }
const Function *getCurrentFunction() const { return F; }

/// Incorporate the given function.
///
/// Purge the currently incorporated function and incorporate \c F. If \c F
/// is currently incorporated, this is a no-op.
void incorporateFunction(const Function &F);
};

} // end namespace llvm

#endif
5 changes: 5 additions & 0 deletions include/llvm/IR/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class InlineAsm;
class Instruction;
class LLVMContext;
class Module;
class ModuleSlotTracker;
class StringRef;
class Twine;
class Type;
Expand Down Expand Up @@ -207,8 +208,12 @@ class Value {
/// instruction that generated it. If you specify a Module for context, then
/// even constanst get pretty-printed; for example, the type of a null
/// pointer is printed symbolically.
/// @{
void printAsOperand(raw_ostream &O, bool PrintType = true,
const Module *M = nullptr) const;
void printAsOperand(raw_ostream &O, bool PrintType,
ModuleSlotTracker &MST) const;
/// @}

/// \brief All values are typed, get the type of this value.
Type *getType() const { return VTy; }
Expand Down
17 changes: 16 additions & 1 deletion lib/CodeGen/MachineBasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/Debug.h"
Expand Down Expand Up @@ -244,6 +245,20 @@ void MachineBasicBlock::print(raw_ostream &OS, SlotIndexes *Indexes) const {
<< " is null\n";
return;
}
const Function *F = MF->getFunction();
const Module *M = F ? F->getParent() : nullptr;
ModuleSlotTracker MST(M);
print(OS, MST, Indexes);
}

void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST,
SlotIndexes *Indexes) const {
const MachineFunction *MF = getParent();
if (!MF) {
OS << "Can't print out MachineBasicBlock because parent MachineFunction"
<< " is null\n";
return;
}

if (Indexes)
OS << Indexes->getMBBStartIdx(this) << '\t';
Expand All @@ -253,7 +268,7 @@ void MachineBasicBlock::print(raw_ostream &OS, SlotIndexes *Indexes) const {
const char *Comma = "";
if (const BasicBlock *LBB = getBasicBlock()) {
OS << Comma << "derived from LLVM BB ";
LBB->printAsOperand(OS, /*PrintType=*/false);
LBB->printAsOperand(OS, /*PrintType=*/false, MST);
Comma = ", ";
}
if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; }
Expand Down
5 changes: 4 additions & 1 deletion lib/CodeGen/MachineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/Debug.h"
Expand Down Expand Up @@ -361,9 +362,11 @@ void MachineFunction::print(raw_ostream &OS, SlotIndexes *Indexes) const {
OS << '\n';
}

ModuleSlotTracker MST(getFunction()->getParent());
MST.incorporateFunction(*getFunction());
for (const auto &BB : *this) {
OS << '\n';
BB.print(OS, Indexes);
BB.print(OS, MST, Indexes);
}

OS << "\n# End machine code for function " << getName() << ".\n\n";
Expand Down
92 changes: 72 additions & 20 deletions lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -544,7 +545,7 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
OS << '>';
}

namespace {
namespace llvm {
//===----------------------------------------------------------------------===//
// SlotTracker Class: Enumerate slot numbers for unnamed values
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -663,7 +664,32 @@ class SlotTracker {
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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 9a61a42

Please sign in to comment.