public boolean reducible() {
    if (dfsTree.isBackEmpty()) {
      return true;
    }
    int size = controlFlow.transitions.length;
    boolean[] loopEnters = dfsTree.loopEnters;
    IntOpenHashSet[] cycleIncoming = new IntOpenHashSet[size];
    // really this may be array, since dfs already ensures no duplicates
    IntArrayList[] nonCycleIncoming = new IntArrayList[size];
    int[] collapsedTo = new int[size];
    int[] queue = new int[size];
    int top;
    for (int i = 0; i < size; i++) {
      if (loopEnters[i]) {
        cycleIncoming[i] = new IntOpenHashSet();
      }
      nonCycleIncoming[i] = new IntArrayList();
      collapsedTo[i] = i;
    }

    // from whom back connections
    dfsTree.iterateBack((from, to) -> cycleIncoming[to].add(from));
    // from whom ordinary connections
    dfsTree.iterateNonBack((from, to) -> nonCycleIncoming[to].add(from));

    for (int w = size - 1; w >= 0 ; w--) {
      top = 0;
      // NB - it is modified later!
      IntOpenHashSet p = cycleIncoming[w];
      if (p == null) {
        continue;
      }
      IntIterator it = p.iterator();
      while (it.hasNext()) {
        queue[top++] = it.nextInt();
      }

      while (top > 0) {
        int x = queue[--top];
        IntList incoming = nonCycleIncoming[x];
        for (int i = 0; i < incoming.size(); i++) {
          int y1 = collapsedTo[incoming.getInt(i)];
          if (!dfsTree.isDescendant(y1, w)) {
            return false;
          }
          if (y1 != w && p.add(y1)) {
            queue[top++] = y1;
          }
        }
      }

      it = p.iterator();
      while (it.hasNext()) {
        collapsedTo[it.next()] = w;
      }
    }

    return true;
  }
public boolean reducible()