Skip to content

Commit

Permalink
[VPlan] Use consecutive numbers to print VPValues instead of addresses.
Browse files Browse the repository at this point in the history
Currently when printing VPValues we use the object address, which makes
it hard to distinguish VPValues as they usually are large numbers with
varying distance between them.

This patch adds a simple slot tracker, similar to the ModuleSlotTracker
used for IR values. In order to dump a VPValue or anything containing a
VPValue, a slot tracker for the enclosing VPlan needs to be created. The
existing VPlanPrinter can take care of that for the existing code. We
assign consecutive numbers to each VPValue we encounter in a reverse
post order traversal of the VPlan.

Reviewers: rengolin, hsaito, fhahn, Ayal, dorit, gilr

Reviewed By: gilr

Differential Revision: https://reviews.llvm.org/D73078
  • Loading branch information
fhahn committed Mar 5, 2020
1 parent 11ab687 commit 40e7bfc
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 50 deletions.
7 changes: 4 additions & 3 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Expand Up @@ -7347,16 +7347,17 @@ Value *LoopVectorizationPlanner::VPCallbackILV::getOrCreateScalarValue(
return ILV.getOrCreateScalarValue(V, Instance);
}

void VPInterleaveRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPInterleaveRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n"
<< Indent << "\"INTERLEAVE-GROUP with factor " << IG->getFactor() << " at ";
IG->getInsertPos()->printAsOperand(O, false);
O << ", ";
getAddr()->printAsOperand(O);
getAddr()->printAsOperand(O, SlotTracker);
VPValue *Mask = getMask();
if (Mask) {
O << ", ";
Mask->printAsOperand(O);
Mask->printAsOperand(O, SlotTracker);
}
O << "\\l\"";
for (unsigned i = 0; i < IG->getFactor(); ++i)
Expand Down
134 changes: 105 additions & 29 deletions llvm/lib/Transforms/Vectorize/VPlan.cpp
Expand Up @@ -49,13 +49,20 @@ extern cl::opt<bool> EnableVPlanNativePath;
#define DEBUG_TYPE "vplan"

raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) {
if (const VPInstruction *Instr = dyn_cast<VPInstruction>(&V))
Instr->print(OS);
else
V.printAsOperand(OS);
const VPInstruction *Instr = dyn_cast<VPInstruction>(&V);
VPSlotTracker SlotTracker(
(Instr && Instr->getParent()) ? Instr->getParent()->getPlan() : nullptr);
V.print(OS, SlotTracker);
return OS;
}

void VPValue::print(raw_ostream &OS, VPSlotTracker &SlotTracker) const {
if (const VPInstruction *Instr = dyn_cast<VPInstruction>(this))
Instr->print(OS, SlotTracker);
else
printAsOperand(OS, SlotTracker);
}

// Get the top-most entry block of \p Start. This is the entry block of the
// containing VPlan. This function is templated to support both const and non-const blocks
template <typename T> static T *getPlanEntry(T *Start) {
Expand Down Expand Up @@ -384,14 +391,20 @@ void VPInstruction::execute(VPTransformState &State) {
generateInstruction(State, Part);
}

void VPInstruction::print(raw_ostream &O, const Twine &Indent) const {
void VPInstruction::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"EMIT ";
print(O);
print(O, SlotTracker);
O << "\\l\"";
}

void VPInstruction::print(raw_ostream &O) const {
printAsOperand(O);
VPSlotTracker SlotTracker(getParent()->getPlan());
print(O, SlotTracker);
}

void VPInstruction::print(raw_ostream &O, VPSlotTracker &SlotTracker) const {
printAsOperand(O, SlotTracker);
O << " = ";

switch (getOpcode()) {
Expand All @@ -413,7 +426,7 @@ void VPInstruction::print(raw_ostream &O) const {

for (const VPValue *Operand : operands()) {
O << " ";
Operand->printAsOperand(O);
Operand->printAsOperand(O, SlotTracker);
}
}

Expand Down Expand Up @@ -567,10 +580,14 @@ void VPlanPrinter::dump() {
OS << "\\n" << DOT::EscapeString(Plan.getName());
if (!Plan.Value2VPValue.empty() || Plan.BackedgeTakenCount) {
OS << ", where:";
if (Plan.BackedgeTakenCount)
OS << "\\n" << *Plan.BackedgeTakenCount << " := BackedgeTakenCount";
if (Plan.BackedgeTakenCount) {
OS << "\\n";
Plan.BackedgeTakenCount->print(OS, SlotTracker);
OS << " := BackedgeTakenCount";
}
for (auto Entry : Plan.Value2VPValue) {
OS << "\\n" << *Entry.second;
OS << "\\n";
Entry.second->print(OS, SlotTracker);
OS << DOT::EscapeString(" := ");
Entry.first->printAsOperand(OS, false);
}
Expand Down Expand Up @@ -637,25 +654,25 @@ void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) {
if (Pred) {
OS << " +\n" << Indent << " \"BlockPredicate: ";
if (const VPInstruction *PredI = dyn_cast<VPInstruction>(Pred)) {
PredI->printAsOperand(OS);
PredI->printAsOperand(OS, SlotTracker);
OS << " (" << DOT::EscapeString(PredI->getParent()->getName())
<< ")\\l\"";
} else
Pred->printAsOperand(OS);
Pred->printAsOperand(OS, SlotTracker);
}

for (const VPRecipeBase &Recipe : *BasicBlock)
Recipe.print(OS, Indent);
Recipe.print(OS, Indent, SlotTracker);

// Dump the condition bit.
const VPValue *CBV = BasicBlock->getCondBit();
if (CBV) {
OS << " +\n" << Indent << " \"CondBit: ";
if (const VPInstruction *CBI = dyn_cast<VPInstruction>(CBV)) {
CBI->printAsOperand(OS);
CBI->printAsOperand(OS, SlotTracker);
OS << " (" << DOT::EscapeString(CBI->getParent()->getName()) << ")\\l\"";
} else {
CBV->printAsOperand(OS);
CBV->printAsOperand(OS, SlotTracker);
OS << "\"";
}
}
Expand Down Expand Up @@ -702,14 +719,15 @@ void VPlanPrinter::printAsIngredient(raw_ostream &O, Value *V) {
O << DOT::EscapeString(IngredientString);
}

void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"WIDEN\\l\"";
for (auto &Instr : make_range(Begin, End))
O << " +\n" << Indent << "\" " << VPlanIngredient(&Instr) << "\\l\"";
}

void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O,
const Twine &Indent) const {
void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"WIDEN-INDUCTION";
if (Trunc) {
O << "\\l\"";
Expand All @@ -719,7 +737,8 @@ void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O,
O << " " << VPlanIngredient(IV) << "\\l\"";
}

void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"WIDEN-GEP ";
O << (IsPtrLoopInvariant ? "Inv" : "Var");
size_t IndicesNumber = IsIndexLoopInvariant.size();
Expand All @@ -729,11 +748,13 @@ void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent) const {
O << " +\n" << Indent << "\" " << VPlanIngredient(GEP) << "\\l\"";
}

void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"WIDEN-PHI " << VPlanIngredient(Phi) << "\\l\"";
}

void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"BLEND ";
Phi->printAsOperand(O, false);
O << " =";
Expand All @@ -747,13 +768,14 @@ void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const {
O << " ";
Phi->getIncomingValue(I)->printAsOperand(O, false);
O << "/";
User->getOperand(I)->printAsOperand(O);
User->getOperand(I)->printAsOperand(O, SlotTracker);
}
}
O << "\\l\"";
}

void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n"
<< Indent << "\"" << (IsUniform ? "CLONE " : "REPLICATE ")
<< VPlanIngredient(Ingredient);
Expand All @@ -762,21 +784,22 @@ void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const {
O << "\\l\"";
}

void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n"
<< Indent << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst)
<< "\\l\"";
}

void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
const Twine &Indent) const {
void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << " +\n" << Indent << "\"WIDEN " << VPlanIngredient(&Instr);
O << ", ";
getAddr()->printAsOperand(O);
getAddr()->printAsOperand(O, SlotTracker);
VPValue *Mask = getMask();
if (Mask) {
O << ", ";
Mask->printAsOperand(O);
Mask->printAsOperand(O, SlotTracker);
}
O << "\\l\"";
}
Expand All @@ -790,6 +813,14 @@ void VPValue::replaceAllUsesWith(VPValue *New) {
User->setOperand(I, New);
}

void VPValue::printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const {
unsigned Slot = Tracker.getSlot(this);
if (Slot == unsigned(-1))
OS << "<badref>";
else
OS << "%vp" << Tracker.getSlot(this);
}

void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region,
Old2NewTy &Old2New,
InterleavedAccessInfo &IAI) {
Expand Down Expand Up @@ -835,3 +866,48 @@ VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan,
Old2NewTy Old2New;
visitRegion(cast<VPRegionBlock>(Plan.getEntry()), Old2New, IAI);
}

void VPSlotTracker::assignSlot(const VPValue *V) {
assert(Slots.find(V) == Slots.end() && "VPValue already has a slot!");
Slots[V] = NextSlot++;
}

void VPSlotTracker::assignSlots(const VPBlockBase *VPBB) {
if (auto *Region = dyn_cast<VPRegionBlock>(VPBB))
assignSlots(Region);
else
assignSlots(cast<VPBasicBlock>(VPBB));
}

void VPSlotTracker::assignSlots(const VPRegionBlock *Region) {
ReversePostOrderTraversal<const VPBlockBase *> RPOT(Region->getEntry());
for (const VPBlockBase *Block : RPOT)
assignSlots(Block);
}

void VPSlotTracker::assignSlots(const VPBasicBlock *VPBB) {
for (const VPRecipeBase &Recipe : *VPBB) {
if (const auto *VPI = dyn_cast<VPInstruction>(&Recipe))
assignSlot(VPI);
}
}

void VPSlotTracker::assignSlots(const VPlan &Plan) {

for (const VPValue *V : Plan.VPExternalDefs)
assignSlot(V);

for (auto &E : Plan.Value2VPValue)
if (!isa<VPInstruction>(E.second))
assignSlot(E.second);

for (const VPValue *V : Plan.VPCBVs)
assignSlot(V);

if (Plan.BackedgeTakenCount)
assignSlot(Plan.BackedgeTakenCount);

ReversePostOrderTraversal<const VPBlockBase *> RPOT(Plan.getEntry());
for (const VPBlockBase *Block : RPOT)
assignSlots(Block);
}

0 comments on commit 40e7bfc

Please sign in to comment.