StateMerger: merge ranges if two states differ only by single variable range (speeds up testLongDisjunctionsNotComplex)

This commit is contained in:
Tagir Valeev
2017-03-14 17:36:29 +07:00
parent c41d4cb2d0
commit c0409b583d
3 changed files with 65 additions and 1 deletions
@@ -253,6 +253,52 @@ class StateMerger {
return new ArrayList<>(new LinkedHashSet<>(states));
}
}
// For every variable with more than one range, try to union range info and see if some states could be merged after that
for (Map.Entry<DfaVariableValue, Map<LongRangeSet, LongRangeSet>> entry : ranges.entrySet()) {
if (entry.getValue().size() > 1) {
class Record {
final DfaMemoryStateImpl myState;
final LongRangeSet myRange;
Record(DfaMemoryStateImpl state, LongRangeSet range) {
myState = state;
myRange = range;
}
Record union(Record other) {
return new Record(myState, myRange.union(other.myRange));
}
}
Map<DfaMemoryStateImpl, Record> merged = new LinkedHashMap<>();
DfaVariableValue var = entry.getKey();
for (DfaMemoryStateImpl state : states) {
DfaVariableState variableState = state.getVariableState(var);
LongRangeSet range = variableState.getRange();
if (range == null) {
range = Objects.requireNonNull(LongRangeSet.fromType(var.getVariableType()));
}
merged.merge(copyWithoutVar(state, var), new Record(state, range), Record::union);
}
if(merged.size() < states.size()) {
List<DfaMemoryStateImpl> updated = new ArrayList<>(merged.size());
for (Record record : merged.values()) {
DfaMemoryStateImpl state = record.myState;
DfaVariableState variableState = state.getVariableState(var);
if(!record.myRange.equals(variableState.getRange())) {
state.flushVariable(var);
state.setRange(var, record.myRange);
}
updated.add(state);
}
states = updated;
changed = true;
}
}
}
if (changed) {
return states;
}
if (states.size() <= MAX_RANGE_STATES || ranges.isEmpty()) return null;
// If there are too many states, try to drop range information from some variable
DfaVariableValue lastVar = Collections.max(ranges.keySet(), Comparator.comparingInt(DfaVariableValue::getID));
@@ -79,6 +79,19 @@ public abstract class LongRangeSet {
*/
public abstract LongRangeSet intersect(LongRangeSet other);
/**
* Merge current set with other
*
* @param other other set to merge with
* @return a new set
*/
public LongRangeSet union(LongRangeSet other) {
if(other.isEmpty() || other == this) return this;
if(other.contains(this)) return other;
// TODO: optimize
return Range.LONG_RANGE.subtract(Range.LONG_RANGE.subtract(this).intersect(Range.LONG_RANGE.subtract(other)));
}
/**
* @return a minimal value contained in the set
* @throws NoSuchElementException if set is empty
@@ -266,6 +279,11 @@ public abstract class LongRangeSet {
return this;
}
@Override
public LongRangeSet union(LongRangeSet other) {
return other;
}
@Override
public long min() {
throw new NoSuchElementException();
@@ -11,7 +11,7 @@ package test.deadcode;
import java.io.IOException;
public class aaa {
int a;
Object a;
int b;
void x(int i, Object o) {