private @NotNull Map<PsiVariable, Set<PsiElement>> getReachableAfterWrite(@NotNull Map<PsiVariable, IntList> writeOffsets,
                                                                                @NotNull Map<PsiVariable, IntList> visibleReadOffsets) {
        final Map<PsiVariable, Set<PsiElement>> afterWrite = new HashMap<>();
        final IntFunction<BitSet> calculator = getReachableInstructionsCalculator();
        for (PsiVariable variable : visibleReadOffsets.keySet()) {
          final BitSet collectedOffsets = new BitSet(flowEnd);
          for (int writeOffset : writeOffsets.get(variable).toIntArray()) {
            LOG.assertTrue(writeOffset >= flowStart, "writeOffset");
            final BitSet reachableOffsets = calculator.apply(writeOffset);
            //skip current assignment
            reachableOffsets.set(writeOffset, false);
            if (writeOffset + 1 < flow.getSize()) {
              final PsiElement nextOffsetElement = flow.getElement(writeOffset + 1);
              if (nextOffsetElement instanceof PsiExpressionStatement) {
                if (flow.getElement(writeOffset) == ((PsiExpressionStatement)nextOffsetElement).getExpression()) {
                  reachableOffsets.set(writeOffset + 1, false);
                }
              }
            }
            collectedOffsets.or(reachableOffsets);
          }
          Set<PsiElement> throwSources = afterWrite.getOrDefault(variable, new HashSet<>());
          for (int i = flowStart; i < flowEnd; i++) {
            if (collectedOffsets.get(i)) {
              throwSources.add(flow.getElement(i));
            }
          }
          final List<PsiElement> subordinates = new ArrayList<>();
          for (PsiElement element : throwSources) {
            if (throwSources.contains(element.getParent())) {
              subordinates.add(element);
            }
          }
          subordinates.forEach(throwSources::remove);
          if (throwSources.isEmpty()) {
            afterWrite.remove(variable);
          } else {
            afterWrite.put(variable, throwSources);
          }
        }
        LOG.debug("afterWrite:", afterWrite);
        return afterWrite;
      }
private @NotNull Map<PsiVariable, Set<PsiElement>> getReachableAfterWrite(@NotNull Map<PsiVariable, IntList> writeOffsets,
                                                                                @NotNull Map<PsiVariable, IntList> visibleReadOffsets)