Skip to content

Commit 5cd85d0

Browse files
committed
[ScheduleDAGRRList] Limit number of candidates to explore.
Currently popFromQueueImpl iterates over all candidates to find the best one. While the candidate queue is small, this is not a problem. But it becomes a problem once the queue gets larger. For example, the snippet below takes 330s to compile with llc -O0, but completes in 3s with this patch. define void @test(i4000000* %ptr) { entry: store i4000000 0, i4000000* %ptr, align 4 ret void } This patch limits the number of candidates to check to 1000. This limit ensures that it never triggers for test-suite/SPEC2000/SPEC2006 on X86 and AArch64 with -O3, while still drastically limiting the compile-time in case of very large queues. It would be even better to use a binary heap to manage to queue (D83335), but some heuristics change the score of a node in the queue after another node has been scheduled. I plan to address this for backends that use the MachineScheduler in the future, but that requires a more careful evaluation. In the meantime, the limit should help users impacted by this issue. The patch includes a slightly smaller version of the motivating example as test case, to guard against the issue. Reviewers: efriedma, paquette, niravd Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D84328
1 parent 3bf3c67 commit 5cd85d0

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,13 +1838,15 @@ class RegReductionPQBase : public SchedulingPriorityQueue {
18381838

18391839
template<class SF>
18401840
static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
1841-
std::vector<SUnit *>::iterator Best = Q.begin();
1842-
for (auto I = std::next(Q.begin()), E = Q.end(); I != E; ++I)
1843-
if (Picker(*Best, *I))
1844-
Best = I;
1845-
SUnit *V = *Best;
1846-
if (Best != std::prev(Q.end()))
1847-
std::swap(*Best, Q.back());
1841+
unsigned BestIdx = 0;
1842+
// Only compute the cost for the first 1000 items in the queue, to avoid
1843+
// excessive compile-times for very large queues.
1844+
for (unsigned I = 1, E = std::min(Q.size(), 1000ul); I != E; I++)
1845+
if (Picker(Q[BestIdx], Q[I]))
1846+
BestIdx = I;
1847+
SUnit *V = Q[BestIdx];
1848+
if (BestIdx + 1 != Q.size())
1849+
std::swap(Q[BestIdx], Q.back());
18481850
Q.pop_back();
18491851
return V;
18501852
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: llc -O0 -mtriple=x86_64-apple-macosx %s -o %t.s
2+
3+
; Stress test for the list scheduler. The store will be expanded to a very
4+
; large number of stores during isel, stressing ScheduleDAGRRList. It should
5+
; compiles in a reasonable amount of time. Run with -O0, to disable most other
6+
; optimizations.
7+
8+
define void @test(i1000000* %ptr) {
9+
entry:
10+
store i1000000 0, i1000000* %ptr, align 4
11+
ret void
12+
}

0 commit comments

Comments
 (0)