Skip to content

Commit aeec2c6

Browse files
authored
[VPlan] Speed up VPSlotTracker by using ModuleSlotTracker (#139881)
Currently, when VPSlotTracker is initialized with a VPlan, its assignName method calls printAsOperand on each underlying instruction. Each such call recomputes slot numbers for the entire function, leading to O(N × M) complexity, where M is the number of instructions in the loop and N is the number of instructions in the function. This results in slow debug output for large loops. For example, printing costs of all instructions becomes O(M² × N), which is especially painful when enabling verbose dumps. This patch improves debugging performance by caching slot numbers using ModuleSlotTracker. It avoids redundant recomputation and makes debug output significantly faster.
1 parent e811383 commit aeec2c6

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,10 +1508,9 @@ void VPSlotTracker::assignName(const VPValue *V) {
15081508
// Use the name of the underlying Value, wrapped in "ir<>", and versioned by
15091509
// appending ".Number" to the name if there are multiple uses.
15101510
std::string Name;
1511-
if (UV) {
1512-
raw_string_ostream S(Name);
1513-
UV->printAsOperand(S, false);
1514-
} else
1511+
if (UV)
1512+
Name = getName(UV);
1513+
else
15151514
Name = VPI->getName();
15161515

15171516
assert(!Name.empty() && "Name cannot be empty.");
@@ -1558,6 +1557,30 @@ void VPSlotTracker::assignNames(const VPBasicBlock *VPBB) {
15581557
assignName(Def);
15591558
}
15601559

1560+
std::string VPSlotTracker::getName(const Value *V) {
1561+
std::string Name;
1562+
raw_string_ostream S(Name);
1563+
if (V->hasName() || !isa<Instruction>(V)) {
1564+
V->printAsOperand(S, false);
1565+
return Name;
1566+
}
1567+
1568+
if (!MST) {
1569+
// Lazily create the ModuleSlotTracker when we first hit an unnamed
1570+
// instruction.
1571+
auto *I = cast<Instruction>(V);
1572+
// This check is required to support unit tests with incomplete IR.
1573+
if (I->getParent()) {
1574+
MST = std::make_unique<ModuleSlotTracker>(I->getModule());
1575+
MST->incorporateFunction(*I->getFunction());
1576+
} else {
1577+
MST = std::make_unique<ModuleSlotTracker>(nullptr);
1578+
}
1579+
}
1580+
V->printAsOperand(S, false, *MST);
1581+
return Name;
1582+
}
1583+
15611584
std::string VPSlotTracker::getOrCreateName(const VPValue *V) const {
15621585
std::string Name = VPValue2Name.lookup(V);
15631586
if (!Name.empty())

llvm/lib/Transforms/Vectorize/VPlanHelpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Analysis/DomTreeUpdater.h"
2424
#include "llvm/Analysis/TargetTransformInfo.h"
2525
#include "llvm/IR/DebugLoc.h"
26+
#include "llvm/IR/ModuleSlotTracker.h"
2627
#include "llvm/Support/InstructionCost.h"
2728

2829
namespace llvm {
@@ -388,9 +389,14 @@ class VPSlotTracker {
388389
/// Number to assign to the next VPValue without underlying value.
389390
unsigned NextSlot = 0;
390391

392+
/// Lazily created ModuleSlotTracker, used only when unnamed IR instructions
393+
/// require slot tracking.
394+
std::unique_ptr<ModuleSlotTracker> MST;
395+
391396
void assignName(const VPValue *V);
392397
void assignNames(const VPlan &Plan);
393398
void assignNames(const VPBasicBlock *VPBB);
399+
std::string getName(const Value *V);
394400

395401
public:
396402
VPSlotTracker(const VPlan *Plan = nullptr) {

0 commit comments

Comments
 (0)