--- /dev/null
+// { dg-do run }
+// { dg-require-effective-target c++11 }
+// { dg-options "-O2" }
+
+typedef __UINT64_TYPE__ u64;
+
+struct SmallDenseMap {
+ static constexpr u64 EmptyKey = 0xC0FFEUL;
+ struct V { u64 v; };
+
+ bool contains(u64 Val) {
+ V *TheSlot = nullptr;
+ return (LookupSlotFor(Val, TheSlot) ? 1 : 0);
+ }
+
+ void try_emplace(u64 Key) {
+ V *TheSlot = nullptr;
+ if (LookupSlotFor(Key, TheSlot))
+ return;
+
+ // Otherwise, insert the new element.
+ InsertIntoSlot(TheSlot, Key);
+ }
+
+ void moveFromOldSlots(V *OldSlotsBegin, V *OldSlotsEnd) {
+ Size = 0;
+
+ V *B_ = u.o.Slots;
+ V *E_ = B_ + u.o.Capacity;
+ for (; B_ != E_; ++B_)
+ B_->v = EmptyKey;
+
+ // Insert all the old elements.
+ V *O = OldSlotsBegin;
+ V *E = OldSlotsEnd;
+ for (; O != E; ++O) {
+ if (O->v != EmptyKey) {
+ // Insert the key/value into the new table.
+ V * N = nullptr;
+ LookupSlotFor(O->v, N);
+ N->v = O->v;
+ Size++;
+ }
+ }
+ }
+
+ void InsertIntoSlot(V *TheSlot, u64 Key) {
+ unsigned NewSize = Size + 1;
+ unsigned Capacity = getCapacity();
+ // Make sure we always keep at least one Empty value
+ if (NewSize >= Capacity) {
+ //fprintf(stderr, "GROW: size=%u capacity=%u -> ...\n", Size, Capacity);
+ grow();
+ LookupSlotFor(Key, TheSlot);
+ Capacity = getCapacity();
+ //fprintf(stderr, "GROW: ... -> size=%u capacity=%u\n", NewSize, Capacity);
+ }
+
+ Size++;
+
+ TheSlot->v = Key;
+ }
+
+ bool LookupSlotFor(u64 Val,
+ V *&FoundSlot) {
+ V *SlotsPtr = getSlots();
+ const unsigned Capacity = getCapacity();
+
+ for (unsigned i = 0; i < Capacity; ++i) {
+ V *ThisSlot = SlotsPtr + i;
+ if (Val == ThisSlot->v) {
+ FoundSlot = ThisSlot;
+ return true;
+ }
+
+ if (ThisSlot->v == EmptyKey) {
+ FoundSlot = ThisSlot;
+ return false;
+ }
+ }
+ // Guarantee that within an array there is a match
+ // or Empty value where to insert a new vaue.
+ __builtin_trap();
+ }
+
+ // Needs to bea at least 1 to hld one empty value
+ static constexpr unsigned InlineSlots = 2;
+
+ bool Small;
+ unsigned Size;
+
+ struct LargeRep {
+ V *Slots;
+ unsigned Capacity;
+ };
+
+ union {
+ V i[InlineSlots]; // Small = true
+ LargeRep o; // Small = false
+ } u;
+
+ explicit SmallDenseMap() : Small(true), Size(0) {
+ Size = 0;
+
+ V *B = u.i;
+ V *E = B + InlineSlots;
+ for (; B != E; ++B)
+ B->v = EmptyKey;
+ }
+
+ void grow() {
+ // assert:
+ if (!Small) __builtin_trap();
+
+ // First move the inline Slots into a temporary storage.
+ V TmpStorage[InlineSlots];
+ V *TmpBegin = TmpStorage;
+ V *TmpEnd = TmpBegin;
+
+ // Loop over the Slots, moving non-empty, non-tombstones into the
+ // temporary storage. Have the loop move the TmpEnd forward as it goes.
+ V *P = u.i;
+ V *E = P + InlineSlots;
+ for (; P != E; ++P) {
+ if (P->v != EmptyKey) {
+ TmpEnd->v = P->v;
+ ++TmpEnd;
+ }
+ }
+
+ Small = false;
+ u.o = LargeRep{new V[128], 128};
+ moveFromOldSlots(TmpBegin, TmpEnd);
+ }
+
+ V *getSlots() {
+ if (Small) {
+ V * inl = u.i;
+ return inl;
+ }
+ else {
+ LargeRep * rep = &u.o;
+ return rep->Slots;
+ }
+ }
+
+ unsigned getCapacity() {
+ if (Small) {
+ return InlineSlots;
+ }
+ else {
+ LargeRep * rep = &u.o;
+ return rep->Capacity;
+ }
+ }
+};
+
+#pragma GCC optimize(0)
+
+struct P {
+ u64 f;
+ bool s;
+};
+
+static u64 ws = 0;
+static P WorkList[128];
+
+__attribute__((noipa))
+static void popupateIni() {
+ for (u64 Var : (u64[]){8,7,6,5,4,3,0}) {
+ WorkList[ws++] = P{Var, false};
+ }
+}
+
+__attribute__((noipa))
+static void checkCycle(u64 Var) {
+ // Detect cycles.
+ static bool seen[256];
+ if (Var >= 256 || seen[Var]) __builtin_trap();
+ seen[Var] = true;
+}
+
+
+__attribute__((noipa))
+static void populateDeps(u64 Var) {
+
+ WorkList[ws++] = P{Var, true};
+ if (Var == 8)
+ WorkList[ws++] = P{0, false};
+}
+
+
+__attribute__((noipa)) __attribute__((optimize(3)))
+static void bug() {
+
+ // triggers growth on insert
+ SmallDenseMap Visited;
+
+ popupateIni();
+
+ while (ws > 0) {
+ P Item = WorkList[--ws];
+ u64 Var = Item.f;
+ bool visitedAllDependencies = Item.s;
+
+ if (Visited.contains(Var)) {
+ continue;
+ }
+
+ if (visitedAllDependencies) {
+ Visited.try_emplace(Var);
+ continue;
+ }
+
+ checkCycle(Var);
+ populateDeps(Var);
+ }
+}
+
+__attribute__((noipa))
+int main() {
+ bug();
+}