Program: 133142
Project: 133142
Buggy source:
private static boolean mergeWaits(Logger logger,Function fn,Block block){
  boolean changed=false;
  boolean fin;
  do {
    fin=true;
    MultiMap<String,WaitStatement> waitMap=buildWaitMap(block);
    String winner=mostSharedVar(waitMap);
    if (winner != null) {
      fin=false;
      changed=true;
      List<WaitStatement> waits=waitMap.get(winner);
      assert(waits != null && waits.size() >= 2);
      boolean explicit=false;
      boolean allRecursive=true;
      Set<String> intersection=null;
      for (      WaitStatement wait : waits) {
        Set<String> nameSet=Var.nameSet(wait.getWaitVars());
        if (intersection == null) {
          intersection=nameSet;
        }
 else {
          intersection.retainAll(nameSet);
        }
        explicit=explicit || wait.getMode() != WaitMode.DATA_ONLY;
        allRecursive=allRecursive && wait.isRecursive();
      }
      assert(intersection != null && !intersection.isEmpty());
      List<Var> intersectionVs=ICUtil.getVarsByName(intersection,waits.get(0).getWaitVars());
      WaitStatement newWait=new WaitStatement(fn.getName() + "String_Node_Str",intersectionVs,new ArrayList<Var>(0),new ArrayList<Var>(0),explicit ? WaitMode.EXPLICIT : WaitMode.DATA_ONLY,allRecursive,TaskMode.LOCAL);
      ArrayList<Var> usedVars=new ArrayList<Var>();
      ArrayList<Var> keepOpen=new ArrayList<Var>();
      for (      WaitStatement wait : waits) {
        if (allRecursive) {
          wait.tryInline(Collections.<String>emptySet(),intersection);
        }
 else {
          wait.tryInline(intersection,Collections.<String>emptySet());
        }
        if (wait.getWaitVars().isEmpty() && wait.getMode() != WaitMode.TASK_DISPATCH) {
          newWait.getBlock().insertInline(wait.getBlock());
        }
 else {
          wait.setParent(newWait.getBlock());
          newWait.getBlock().addContinuation(wait);
        }
        keepOpen.addAll(wait.getKeepOpenVars());
        usedVars.addAll(wait.getPassedInVars());
      }
      ICUtil.removeDuplicates(keepOpen);
      for (      Var v : keepOpen) {
        newWait.addKeepOpenVar(v);
      }
      ICUtil.removeDuplicates(usedVars);
      newWait.addPassedInVars(usedVars);
      block.addContinuation(newWait);
      block.removeContinuations(waits);
    }
    changed=changed || !fin;
  }
 while (!fin);
  return changed;
}

Fixed version (ground truth):
private static boolean mergeWaits(Logger logger,Function fn,Block block){
  boolean changed=false;
  boolean fin;
  do {
    fin=true;
    MultiMap<String,WaitStatement> waitMap=buildWaitMap(block);
    String winner=mostSharedVar(waitMap);
    if (winner != null) {
      fin=false;
      changed=true;
      List<WaitStatement> waits=waitMap.get(winner);
      assert(waits != null && waits.size() >= 2);
      boolean explicit=false;
      boolean allRecursive=true;
      Set<String> intersection=null;
      for (      WaitStatement wait : waits) {
        Set<String> nameSet=Var.nameSet(wait.getWaitVars());
        if (intersection == null) {
          intersection=nameSet;
        }
 else {
          intersection.retainAll(nameSet);
        }
        explicit=explicit || wait.getMode() != WaitMode.DATA_ONLY;
        allRecursive=allRecursive && wait.isRecursive();
      }
      assert(intersection != null && !intersection.isEmpty());
      List<Var> intersectionVs=ICUtil.getVarsByName(intersection,waits.get(0).getWaitVars());
      WaitStatement newWait=new WaitStatement(fn.getName() + "String_Node_Str",intersectionVs,new ArrayList<Var>(0),new ArrayList<Var>(0),null,explicit ? WaitMode.EXPLICIT : WaitMode.DATA_ONLY,allRecursive,TaskMode.LOCAL);
      ArrayList<Var> usedVars=new ArrayList<Var>();
      ArrayList<Var> keepOpen=new ArrayList<Var>();
      for (      WaitStatement wait : waits) {
        if (allRecursive) {
          wait.tryInline(Collections.<String>emptySet(),intersection);
        }
 else {
          wait.tryInline(intersection,Collections.<String>emptySet());
        }
        if (wait.getWaitVars().isEmpty() && wait.getMode() != WaitMode.TASK_DISPATCH) {
          newWait.getBlock().insertInline(wait.getBlock());
        }
 else {
          wait.setParent(newWait.getBlock());
          newWait.getBlock().addContinuation(wait);
        }
        keepOpen.addAll(wait.getKeepOpenVars());
        usedVars.addAll(wait.getPassedInVars());
      }
      ICUtil.removeDuplicates(keepOpen);
      for (      Var v : keepOpen) {
        newWait.addKeepOpenVar(v);
      }
      ICUtil.removeDuplicates(usedVars);
      newWait.addPassedInVars(usedVars);
      block.addContinuation(newWait);
      block.removeContinuations(waits);
    }
    changed=changed || !fin;
  }
 while (!fin);
  return changed;
}