Skip to content

Commit 6254b6d

Browse files
authored
[VPlan] Version VPValue names in VPSlotTracker. (#81411)
This patch restructures the way names for printing VPValues are handled. It moves the logic to generate names for printing to VPSlotTracker. VPSlotTracker will now version names of the same underlying value if it is used by multiple VPValues, by adding a .V suffix to the name. This fixes cases where at the moment the same name is printed for different VPValues. PR: #81411
1 parent d48ebac commit 6254b6d

File tree

3 files changed

+94
-41
lines changed

3 files changed

+94
-41
lines changed

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,18 +1300,7 @@ void VPValue::replaceUsesWithIf(
13001300

13011301
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
13021302
void VPValue::printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const {
1303-
if (const Value *UV = getUnderlyingValue()) {
1304-
OS << "ir<";
1305-
UV->printAsOperand(OS, false);
1306-
OS << ">";
1307-
return;
1308-
}
1309-
1310-
unsigned Slot = Tracker.getSlot(this);
1311-
if (Slot == unsigned(-1))
1312-
OS << "<badref>";
1313-
else
1314-
OS << "vp<%" << Tracker.getSlot(this) << ">";
1303+
OS << Tracker.getOrCreateName(this);
13151304
}
13161305

13171306
void VPUser::printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const {
@@ -1373,32 +1362,88 @@ VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan,
13731362
visitRegion(Plan.getVectorLoopRegion(), Old2New, IAI);
13741363
}
13751364

1376-
void VPSlotTracker::assignSlot(const VPValue *V) {
1377-
if (V->getUnderlyingValue())
1365+
void VPSlotTracker::assignName(const VPValue *V) {
1366+
assert(!VPValue2Name.contains(V) && "VPValue already has a name!");
1367+
auto *UV = V->getUnderlyingValue();
1368+
if (!UV) {
1369+
VPValue2Name[V] = (Twine("vp<%") + Twine(NextSlot) + ">").str();
1370+
NextSlot++;
13781371
return;
1379-
assert(!Slots.contains(V) && "VPValue already has a slot!");
1380-
Slots[V] = NextSlot++;
1372+
}
1373+
1374+
// Use the name of the underlying Value, wrapped in "ir<>", and versioned by
1375+
// appending ".Number" to the name if there are multiple uses.
1376+
std::string Name;
1377+
raw_string_ostream S(Name);
1378+
UV->printAsOperand(S, false);
1379+
assert(!Name.empty() && "Name cannot be empty.");
1380+
std::string BaseName = (Twine("ir<") + Name + Twine(">")).str();
1381+
1382+
// First assign the base name for V.
1383+
const auto &[A, _] = VPValue2Name.insert({V, BaseName});
1384+
// Integer or FP constants with different types will result in he same string
1385+
// due to stripping types.
1386+
if (V->isLiveIn() && isa<ConstantInt, ConstantFP>(UV))
1387+
return;
1388+
1389+
// If it is already used by C > 0 other VPValues, increase the version counter
1390+
// C and use it for V.
1391+
const auto &[C, UseInserted] = BaseName2Version.insert({BaseName, 0});
1392+
if (!UseInserted) {
1393+
C->second++;
1394+
A->second = (BaseName + Twine(".") + Twine(C->second)).str();
1395+
}
13811396
}
13821397

1383-
void VPSlotTracker::assignSlots(const VPlan &Plan) {
1398+
void VPSlotTracker::assignNames(const VPlan &Plan) {
13841399
if (Plan.VFxUF.getNumUsers() > 0)
1385-
assignSlot(&Plan.VFxUF);
1386-
assignSlot(&Plan.VectorTripCount);
1400+
assignName(&Plan.VFxUF);
1401+
assignName(&Plan.VectorTripCount);
13871402
if (Plan.BackedgeTakenCount)
1388-
assignSlot(Plan.BackedgeTakenCount);
1389-
assignSlots(Plan.getPreheader());
1403+
assignName(Plan.BackedgeTakenCount);
1404+
for (VPValue *LI : Plan.VPLiveInsToFree)
1405+
assignName(LI);
1406+
assignNames(Plan.getPreheader());
13901407

13911408
ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<const VPBlockBase *>>
13921409
RPOT(VPBlockDeepTraversalWrapper<const VPBlockBase *>(Plan.getEntry()));
13931410
for (const VPBasicBlock *VPBB :
13941411
VPBlockUtils::blocksOnly<const VPBasicBlock>(RPOT))
1395-
assignSlots(VPBB);
1412+
assignNames(VPBB);
13961413
}
13971414

1398-
void VPSlotTracker::assignSlots(const VPBasicBlock *VPBB) {
1415+
void VPSlotTracker::assignNames(const VPBasicBlock *VPBB) {
13991416
for (const VPRecipeBase &Recipe : *VPBB)
14001417
for (VPValue *Def : Recipe.definedValues())
1401-
assignSlot(Def);
1418+
assignName(Def);
1419+
}
1420+
1421+
std::string VPSlotTracker::getOrCreateName(const VPValue *V) const {
1422+
std::string Name = VPValue2Name.lookup(V);
1423+
if (!Name.empty())
1424+
return Name;
1425+
1426+
// If no name was assigned, no VPlan was provided when creating the slot
1427+
// tracker or it is not reachable from the provided VPlan. This can happen,
1428+
// e.g. when trying to print a recipe that has not been inserted into a VPlan
1429+
// in a debugger.
1430+
// TODO: Update VPSlotTracker constructor to assign names to recipes &
1431+
// VPValues not associated with a VPlan, instead of constructing names ad-hoc
1432+
// here.
1433+
const VPRecipeBase *DefR = V->getDefiningRecipe();
1434+
(void)DefR;
1435+
assert((!DefR || !DefR->getParent() || !DefR->getParent()->getPlan()) &&
1436+
"VPValue defined by a recipe in a VPlan?");
1437+
1438+
// Use the underlying value's name, if there is one.
1439+
if (auto *UV = V->getUnderlyingValue()) {
1440+
std::string Name;
1441+
raw_string_ostream S(Name);
1442+
UV->printAsOperand(S, false);
1443+
return (Twine("ir<") + Name + ">").str();
1444+
}
1445+
1446+
return "<badref>";
14021447
}
14031448

14041449
bool vputils::onlyFirstLaneUsed(const VPValue *Def) {

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/ADT/DenseMap.h"
2424
#include "llvm/ADT/STLExtras.h"
2525
#include "llvm/ADT/SmallVector.h"
26+
#include "llvm/ADT/StringMap.h"
2627
#include "llvm/ADT/TinyPtrVector.h"
2728
#include "llvm/ADT/iterator_range.h"
2829

@@ -443,29 +444,36 @@ class VPDef {
443444
class VPlan;
444445
class VPBasicBlock;
445446

446-
/// This class can be used to assign consecutive numbers to all VPValues in a
447-
/// VPlan and allows querying the numbering for printing, similar to the
447+
/// This class can be used to assign names to VPValues. For VPValues without
448+
/// underlying value, assign consecutive numbers and use those as names (wrapped
449+
/// in vp<>). Otherwise, use the name from the underlying value (wrapped in
450+
/// ir<>), appending a .V version number if there are multiple uses of the same
451+
/// name. Allows querying names for VPValues for printing, similar to the
448452
/// ModuleSlotTracker for IR values.
449453
class VPSlotTracker {
450-
DenseMap<const VPValue *, unsigned> Slots;
454+
/// Keep track of versioned names assigned to VPValues with underlying IR
455+
/// values.
456+
DenseMap<const VPValue *, std::string> VPValue2Name;
457+
/// Keep track of the next number to use to version the base name.
458+
StringMap<unsigned> BaseName2Version;
459+
460+
/// Number to assign to the next VPValue without underlying value.
451461
unsigned NextSlot = 0;
452462

453-
void assignSlot(const VPValue *V);
454-
void assignSlots(const VPlan &Plan);
455-
void assignSlots(const VPBasicBlock *VPBB);
463+
void assignName(const VPValue *V);
464+
void assignNames(const VPlan &Plan);
465+
void assignNames(const VPBasicBlock *VPBB);
456466

457467
public:
458468
VPSlotTracker(const VPlan *Plan = nullptr) {
459469
if (Plan)
460-
assignSlots(*Plan);
470+
assignNames(*Plan);
461471
}
462472

463-
unsigned getSlot(const VPValue *V) const {
464-
auto I = Slots.find(V);
465-
if (I == Slots.end())
466-
return -1;
467-
return I->second;
468-
}
473+
/// Returns the name assigned to \p V, if there is one, otherwise try to
474+
/// construct one from the underlying value, if there's one; else return
475+
/// <badref>.
476+
std::string getOrCreateName(const VPValue *V) const;
469477
};
470478

471479
} // namespace llvm

llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -986,8 +986,8 @@ define void @sinking_requires_duplication(ptr %addr) {
986986
; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue
987987
; CHECK-EMPTY:
988988
; CHECK-NEXT: pred.store.if:
989-
; CHECK-NEXT: REPLICATE ir<%gep> = getelementptr ir<%addr>, vp<[[STEPS]]>
990-
; CHECK-NEXT: REPLICATE store ir<1.000000e+01>, ir<%gep>
989+
; CHECK-NEXT: REPLICATE ir<%gep>.1 = getelementptr ir<%addr>, vp<[[STEPS]]>
990+
; CHECK-NEXT: REPLICATE store ir<1.000000e+01>, ir<%gep>.1
991991
; CHECK-NEXT: Successor(s): pred.store.continue
992992
; CHECK-EMPTY:
993993
; CHECK-NEXT: pred.store.continue:
@@ -1129,8 +1129,8 @@ define void @ptr_induction_remove_dead_recipe(ptr %start, ptr %end) {
11291129
; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue
11301130
; CHECK-EMPTY:
11311131
; CHECK-NEXT: pred.store.if:
1132-
; CHECK-NEXT: REPLICATE ir<%ptr.iv.next> = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1>
1133-
; CHECK-NEXT: REPLICATE store ir<95>, ir<%ptr.iv.next>
1132+
; CHECK-NEXT: REPLICATE ir<%ptr.iv.next>.1 = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1>
1133+
; CHECK-NEXT: REPLICATE store ir<95>, ir<%ptr.iv.next>.1
11341134
; CHECK-NEXT: Successor(s): pred.store.continue
11351135
; CHECK-EMPTY:
11361136
; CHECK-NEXT: pred.store.continue:

0 commit comments

Comments
 (0)