private static int doVisitForPostorder(
     Instruction curr, int currN, int[] postorder, boolean[] visited) {
   visited[curr.num()] = true;
   for (Instruction succ : curr.allSuccessors()) {
     if (!visited[succ.num()]) {
       currN = doVisitForPostorder(succ, currN, postorder, visited);
     }
   }
   postorder[curr.num()] = --currN;
   return currN;
 }
  private static void findReadsBeforeWrites(
      Instruction[] flow,
      TIntHashSet[] definitelyAssigned,
      List<ReadWriteVariableInstruction> result,
      TObjectIntHashMap<String> namesIndex,
      int[] postorder,
      int[] invpostorder,
      boolean onlyFirstRead) {
    // skip instructions that are not reachable from the start
    int start = ArrayUtil.find(invpostorder, 0);

    for (int i = start; i < flow.length; i++) {
      int j = invpostorder[i];
      Instruction curr = flow[j];
      if (curr instanceof ReadWriteVariableInstruction) {
        ReadWriteVariableInstruction rw = (ReadWriteVariableInstruction) curr;
        int name = namesIndex.get(rw.getVariableName());
        TIntHashSet vars = definitelyAssigned[j];
        if (rw.isWrite()) {
          if (vars == null) {
            vars = new TIntHashSet();
            definitelyAssigned[j] = vars;
          }
          vars.add(name);
        } else {
          if (vars == null || !vars.contains(name)) {
            result.add(rw);
            if (onlyFirstRead) {
              if (vars == null) {
                vars = new TIntHashSet();
                definitelyAssigned[j] = vars;
              }
              vars.add(name);
            }
          }
        }
      }

      for (Instruction succ : curr.allSuccessors()) {
        if (postorder[succ.num()] > postorder[curr.num()]) {
          TIntHashSet currDefinitelyAssigned = definitelyAssigned[curr.num()];
          TIntHashSet succDefinitelyAssigned = definitelyAssigned[succ.num()];
          if (currDefinitelyAssigned != null) {
            int[] currArray = currDefinitelyAssigned.toArray();
            if (succDefinitelyAssigned == null) {
              succDefinitelyAssigned = new TIntHashSet();
              succDefinitelyAssigned.addAll(currArray);
              definitelyAssigned[succ.num()] = succDefinitelyAssigned;
            } else {
              succDefinitelyAssigned.retainAll(currArray);
            }
          } else {
            if (succDefinitelyAssigned != null) {
              succDefinitelyAssigned.clear();
            } else {
              succDefinitelyAssigned = new TIntHashSet();
              definitelyAssigned[succ.num()] = succDefinitelyAssigned;
            }
          }
        }
      }
    }
  }