Program: 132961
Project: 132961
Buggy source:
private static boolean mergeWaits(Logger logger,Function fn,Block block){
  boolean changed=false;
  boolean fin;
  do {
    fin=true;
    MultiMap<Var,WaitStatement> waitMap=buildWaitMap(block);
    Var winner=mostSharedVar(waitMap);
    if (winner != null) {
      fin=false;
      changed=true;
      List<WaitStatement> waits=waitMap.get(winner);
      assert(waits != null && waits.size() >= 2);
      logger.trace("String_Node_Str" + waits.size() + "String_Node_Str");
      boolean explicit=false;
      boolean allRecursive=true;
      Set<Var> intersection=null;
      for (      WaitStatement wait : waits) {
        Set<Var> waitVars=new HashSet<Var>();
        for (        WaitVar wv : wait.getWaitVars()) {
          waitVars.add(wv.var);
        }
        if (intersection == null) {
          intersection=waitVars;
        }
 else {
          intersection.retainAll(waitVars);
        }
        explicit=explicit || wait.getMode() != WaitMode.WAIT_ONLY;
        allRecursive=allRecursive && wait.isRecursive();
      }
      assert(intersection != null && !intersection.isEmpty());
      WaitStatement newWait=new WaitStatement(fn.getName() + "String_Node_Str",WaitVar.makeList(intersection,false),PassedVar.NONE,Var.NONE,null,WaitMode.WAIT_ONLY,allRecursive,TaskMode.LOCAL);
      for (      WaitStatement wait : waits) {
        if (allRecursive) {
          wait.tryInline(Collections.<Var>emptySet(),intersection,false);
        }
 else {
          wait.tryInline(intersection,Collections.<Var>emptySet(),false);
        }
        if (wait.getWaitVars().isEmpty() && wait.getMode() != WaitMode.TASK_DISPATCH) {
          newWait.getBlock().insertInline(wait.getBlock());
        }
 else {
          wait.setParent(newWait.getBlock());
          newWait.getBlock().addContinuation(wait);
        }
      }
      block.addContinuation(newWait);
      block.removeContinuations(waits);
    }
    changed=changed || !fin;
  }
 while (!fin);
  return changed;
}

Fixed version (ground truth):
private boolean mergeWaits(Logger logger,Function fn,Block block){
  boolean changed=false;
  boolean fin;
  do {
    fin=true;
    MultiMap<Var,WaitStatement> waitMap=buildWaitMap(block);
    Var winner=mostSharedVar(waitMap);
    if (winner != null) {
      fin=false;
      changed=true;
      List<WaitStatement> waits=waitMap.get(winner);
      assert(waits != null && waits.size() >= 2);
      logger.trace("String_Node_Str" + waits.size() + "String_Node_Str");
      boolean explicit=false;
      boolean allRecursive=true;
      Set<Var> explicitVars=new HashSet<Var>();
      Set<Var> notExplicitVars=new HashSet<Var>();
      Set<Var> intersection=null;
      for (      WaitStatement wait : waits) {
        Set<Var> waitVars=new HashSet<Var>();
        for (        WaitVar wv : wait.getWaitVars()) {
          waitVars.add(wv.var);
          if (wv.explicit) {
            explicitVars.add(wv.var);
          }
 else {
            notExplicitVars.add(wv.var);
          }
        }
        if (intersection == null) {
          intersection=waitVars;
        }
 else {
          intersection.retainAll(waitVars);
        }
        explicit=explicit || wait.getMode() != WaitMode.WAIT_ONLY;
        allRecursive=allRecursive && wait.isRecursive();
      }
      assert(intersection != null && !intersection.isEmpty());
      List<WaitVar> mergedWaitVars=new ArrayList<WaitVar>();
      for (      Var v : intersection) {
        boolean mergedExplicit=explicitVars.contains(v) && !notExplicitVars.contains(v);
        mergedWaitVars.add(new WaitVar(v,mergedExplicit));
      }
      WaitStatement newWait=new WaitStatement(fn.getName() + "String_Node_Str",mergedWaitVars,PassedVar.NONE,Var.NONE,null,WaitMode.WAIT_ONLY,allRecursive,TaskMode.LOCAL);
      for (      WaitStatement wait : waits) {
        wait.removeWaitVars(mergedWaitVars,allRecursive,retainExplicit);
        if (wait.getWaitVars().isEmpty() && wait.getMode() != WaitMode.TASK_DISPATCH) {
          newWait.getBlock().insertInline(wait.getBlock());
        }
 else {
          wait.setParent(newWait.getBlock());
          newWait.getBlock().addContinuation(wait);
        }
      }
      block.addContinuation(newWait);
      block.removeContinuations(waits);
    }
    changed=changed || !fin;
  }
 while (!fin);
  return changed;
}