Skip to content

Commit 6150e84

Browse files
authored
[CodeGen][SDAG] Remove Combiner WorklistMap (#92900)
DenseMap for pointer lookup is expensive, and this is only used for deduplication and index lookup. Instead, store the worklist index in the node itself. This brings a substantial performance improvement.
1 parent 2bfa26d commit 6150e84

File tree

2 files changed

+30
-24
lines changed

2 files changed

+30
-24
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,17 +479,12 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
479479
/// The operation that this node performs.
480480
int32_t NodeType;
481481

482-
public:
483-
/// Unique and persistent id per SDNode in the DAG. Used for debug printing.
484-
/// We do not place that under `#if LLVM_ENABLE_ABI_BREAKING_CHECKS`
485-
/// intentionally because it adds unneeded complexity without noticeable
486-
/// benefits (see discussion with @thakis in D120714).
487-
uint16_t PersistentId = 0xffff;
482+
SDNodeFlags Flags;
488483

489484
protected:
490485
// We define a set of mini-helper classes to help us interpret the bits in our
491486
// SubclassData. These are designed to fit within a uint16_t so they pack
492-
// with PersistentId.
487+
// with SDNodeFlags.
493488

494489
#if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__))
495490
// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words
@@ -611,6 +606,14 @@ END_TWO_BYTE_PACK()
611606
static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide");
612607
static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide");
613608

609+
public:
610+
/// Unique and persistent id per SDNode in the DAG. Used for debug printing.
611+
/// We do not place that under `#if LLVM_ENABLE_ABI_BREAKING_CHECKS`
612+
/// intentionally because it adds unneeded complexity without noticeable
613+
/// benefits (see discussion with @thakis in D120714). Currently, there are
614+
/// two padding bytes after this field.
615+
uint16_t PersistentId = 0xffff;
616+
614617
private:
615618
friend class SelectionDAG;
616619
// TODO: unfriend HandleSDNode once we fix its operand handling.
@@ -646,7 +649,8 @@ END_TWO_BYTE_PACK()
646649
/// Return a pointer to the specified value type.
647650
static const EVT *getValueTypeList(EVT VT);
648651

649-
SDNodeFlags Flags;
652+
/// Index in worklist of DAGCombiner, or -1.
653+
int CombinerWorklistIndex = -1;
650654

651655
uint32_t CFIType = 0;
652656

@@ -747,6 +751,12 @@ END_TWO_BYTE_PACK()
747751
/// Set unique node id.
748752
void setNodeId(int Id) { NodeId = Id; }
749753

754+
/// Get worklist index for DAGCombiner
755+
int getCombinerWorklistIndex() const { return CombinerWorklistIndex; }
756+
757+
/// Set worklist index for DAGCombiner
758+
void setCombinerWorklistIndex(int Index) { CombinerWorklistIndex = Index; }
759+
750760
/// Return the node ordering.
751761
unsigned getIROrder() const { return IROrder; }
752762

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,11 @@ namespace {
170170
/// back and when processing we pop off of the back.
171171
///
172172
/// The worklist will not contain duplicates but may contain null entries
173-
/// due to nodes being deleted from the underlying DAG.
173+
/// due to nodes being deleted from the underlying DAG. For fast lookup and
174+
/// deduplication, the index of the node in this vector is stored in the
175+
/// node in SDNode::CombinerWorklistIndex.
174176
SmallVector<SDNode *, 64> Worklist;
175177

176-
/// Mapping from an SDNode to its position on the worklist.
177-
///
178-
/// This is used to find and remove nodes from the worklist (by nulling
179-
/// them) when they are deleted from the underlying DAG. It relies on
180-
/// stable indices of nodes within the worklist.
181-
DenseMap<SDNode *, unsigned> WorklistMap;
182-
183178
/// This records all nodes attempted to be added to the worklist since we
184179
/// considered a new worklist entry. As we keep do not add duplicate nodes
185180
/// in the worklist, this is different from the tail of the worklist.
@@ -238,10 +233,9 @@ namespace {
238233
}
239234

240235
if (N) {
241-
bool GoodWorklistEntry = WorklistMap.erase(N);
242-
(void)GoodWorklistEntry;
243-
assert(GoodWorklistEntry &&
236+
assert(N->getCombinerWorklistIndex() >= 0 &&
244237
"Found a worklist entry without a corresponding map entry!");
238+
N->setCombinerWorklistIndex(-1);
245239
}
246240
return N;
247241
}
@@ -285,8 +279,10 @@ namespace {
285279
if (IsCandidateForPruning)
286280
ConsiderForPruning(N);
287281

288-
if (WorklistMap.insert(std::make_pair(N, Worklist.size())).second)
282+
if (N->getCombinerWorklistIndex() == -1) {
283+
N->setCombinerWorklistIndex(Worklist.size());
289284
Worklist.push_back(N);
285+
}
290286
}
291287

292288
/// Remove all instances of N from the worklist.
@@ -295,13 +291,13 @@ namespace {
295291
PruningList.remove(N);
296292
StoreRootCountMap.erase(N);
297293

298-
auto It = WorklistMap.find(N);
299-
if (It == WorklistMap.end())
294+
int WorklistIndex = N->getCombinerWorklistIndex();
295+
if (WorklistIndex == -1)
300296
return; // Not in the worklist.
301297

302298
// Null out the entry rather than erasing it to avoid a linear operation.
303-
Worklist[It->second] = nullptr;
304-
WorklistMap.erase(It);
299+
Worklist[WorklistIndex] = nullptr;
300+
N->setCombinerWorklistIndex(-1);
305301
}
306302

307303
void deleteAndRecombine(SDNode *N);

0 commit comments

Comments
 (0)