mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-07 02:56:52 +00:00
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:
parent
0be7d0cf17
commit
9a61a42713
@ -660,6 +660,8 @@ public:
|
||||
// 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;
|
||||
|
63
include/llvm/IR/ModuleSlotTracker.h
Normal file
63
include/llvm/IR/ModuleSlotTracker.h
Normal file
@ -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
|
@ -38,6 +38,7 @@ class InlineAsm;
|
||||
class Instruction;
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class ModuleSlotTracker;
|
||||
class StringRef;
|
||||
class Twine;
|
||||
class Type;
|
||||
@ -207,8 +208,12 @@ public:
|
||||
/// 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; }
|
||||
|
@ -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"
|
||||
@ -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';
|
||||
@ -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 = ", "; }
|
||||
|
@ -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"
|
||||
@ -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";
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user