@@ -1300,18 +1300,7 @@ void VPValue::replaceUsesWithIf(
13001300
13011301#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
13021302void 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
13171306void 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
14041449bool vputils::onlyFirstLaneUsed (const VPValue *Def) {
0 commit comments