private static boolean findAndReduceRedundantLoop()

in src/org/jetbrains/java/decompiler/modules/decompiler/EliminateLoopsHelper.java [72:181]


  private static boolean findAndReduceRedundantLoop(DoStatement loop) {

    if (loop.getLoopType() != DoStatement.LoopType.DO) {
      return false;
    }

    // get parent loop if exists
    Statement parentloop = loop.getParent();
    while (parentloop != null && parentloop.type != Statement.StatementType.DO) {
      parentloop = parentloop.getParent();
    }

    if (parentloop == null || parentloop.getBasichead() != loop.getBasichead()) {
      return false;
    }

    // collect relevant break edges
    List<StatEdge> lstBreakEdges = new ArrayList<>();
    for (StatEdge edge : loop.getLabelEdges()) {
      if (edge.getType() == StatEdge.EdgeType.BREAK) { // all break edges are explicit because of LOOP_DO type
        lstBreakEdges.add(edge);
      }
    }


    Statement loopcontent = loop.getFirst();

    boolean firstok = loopcontent.getAllSuccessorEdges().isEmpty();
    if (loopcontent.type == Statement.StatementType.SWITCH &&
        loopcontent instanceof SwitchStatement switchStatement &&
        switchStatement.getHeadExprent() != null &&
        SwitchPatternHelper.isBootstrapSwitch(switchStatement.getHeadExprent())) {
      Set<StatEdge> allEdges = new HashSet<>();
      for (Statement statement : switchStatement.getCaseStatements()) {
        allEdges.addAll(statement.getAllSuccessorEdges());
      }
      //not a good workaround, but there is not another key, because edges are broken at this moment
      if (allEdges.stream()
            .anyMatch(edge -> edge.closure.type == Statement.StatementType.DO)) {
        return false;
      }
    }
    if (!firstok) {
      StatEdge edge = loopcontent.getAllSuccessorEdges().get(0);
      firstok = (edge.closure == loop && edge.getType() == StatEdge.EdgeType.BREAK);
      if (firstok) {
        lstBreakEdges.remove(edge);
      }
    }


    if (!lstBreakEdges.isEmpty()) {
      if (firstok) {

        HashMap<Integer, Boolean> statLabeled = new HashMap<>();
        List<Statement> lstEdgeClosures = new ArrayList<>();

        for (StatEdge edge : lstBreakEdges) {
          Statement minclosure = LowBreakHelper.getMinClosure(loopcontent, edge.getSource());
          lstEdgeClosures.add(minclosure);
        }

        int precount = loop.isLabeled() ? 1 : 0;
        for (Statement st : lstEdgeClosures) {
          if (!statLabeled.containsKey(st.id)) {
            boolean btemp = st.isLabeled();
            precount += btemp ? 1 : 0;
            statLabeled.put(st.id, btemp);
          }
        }

        for (int i = 0; i < lstBreakEdges.size(); i++) {
          Statement st = lstEdgeClosures.get(i);
          statLabeled.put(st.id, LowBreakHelper.isBreakEdgeLabeled(lstBreakEdges.get(i).getSource(), st) | statLabeled.get(st.id));
        }

        for (int i = 0; i < lstBreakEdges.size(); i++) {
          lstEdgeClosures.set(i, getMaxBreakLift(lstEdgeClosures.get(i), lstBreakEdges.get(i), statLabeled, loop));
        }

        statLabeled.clear();
        for (Statement st : lstEdgeClosures) {
          statLabeled.put(st.id, st.isLabeled());
        }

        for (int i = 0; i < lstBreakEdges.size(); i++) {
          Statement st = lstEdgeClosures.get(i);
          statLabeled.put(st.id, LowBreakHelper.isBreakEdgeLabeled(lstBreakEdges.get(i).getSource(), st) | statLabeled.get(st.id));
        }

        long postcount = statLabeled.values().stream().filter(Boolean::booleanValue).count();

        if (precount <= postcount) {
          return false;
        }
        else {
          for (int i = 0; i < lstBreakEdges.size(); i++) {
            lstEdgeClosures.get(i).addLabeledEdge(lstBreakEdges.get(i));
          }
        }
      }
      else {
        return false;
      }
    }

    eliminateLoop(loop, parentloop);

    return true;
  }