<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, Aug 16, 2016 at 10:12 PM Daniel Berlin via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">FWIW: the traditional solution to this problem is the "double stack" approach (really a double queue), which is maintaining a current and next worklist.<div>After evaluating worklist algorithms and datastructures on  tons and tons and tons and tons testcases (and looking at the behaviors of all the existing worklists), this is what ended up being the final solution in gcc.<br></div><div><br></div><div>The practical performance and memory differences between the various  data structures are ... essentially nil on most cases.</div><div><br></div><div>Now, the algorithms and what tricks you use to avoid revisiting stuff and ordering, that matters.</div><div>(probably not so much here though :P)<br></div></div></blockquote><div><br></div><div>Yea, I only did minimal work to avoid redundant calls to relatively heavyweight predicates like isSafeToSpeculativelyExecute. Probably the most that could be warranted here.</div><div><br></div><div>I'm much more interested in the avoidance of a quadratic failure mode.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Whether it's worth making a new ADT for worklists, i'd only do it if we thought it had API and maintenance benefits, because IMHO it's unlikely to have any significant performance benefits.</div></div></blockquote><div><br></div><div>FWIW, and as a side note, I used to really be interested in figuring out the "right" API for an LLVM worklist.</div><div><br></div><div>I've mostly convinced myself this is hopeless. Most worklists that *really* matter have highly specialized properties that they can and should exploit to maximize efficiency. As a classic example, here and in many other places I have had to avoid using SetVector just so that I can differently handle the visited set from the worklist vector. This stuff keeps coming up, and I no longer think there is a really beautiful generalization here.</div><div><br></div><div>What I *do* think we need lots of are the building blocks. Really good sets, vectors, setvectors, mapvectors, and other primitives. We should probably get a vector for which objects with an obvious null state can be "GC"ed off the front whenever a grow would trigger walking the vector anyways. We should also probably get a double stack at some point.</div><div><br></div><div>Then we should just make sure that the patterns for combining these in common was are clean and well understood.</div><div><br></div><div>That's my best feeling for how to handle this.</div></div></div>