use of com.dat3m.dartagnan.program.event.core.Event in project Dat3M by hernanponcedeleon.
the class Acyclic method consistent.
@Override
public BooleanFormula consistent(SolverContext ctx) {
FormulaManager fmgr = ctx.getFormulaManager();
BooleanFormulaManager bmgr = fmgr.getBooleanFormulaManager();
IntegerFormulaManager imgr = fmgr.getIntegerFormulaManager();
BooleanFormula enc = bmgr.makeTrue();
for (Tuple tuple : rel.getEncodeTupleSet()) {
Event e1 = tuple.getFirst();
Event e2 = tuple.getSecond();
enc = bmgr.and(enc, bmgr.implication(rel.getSMTVar(tuple, ctx), imgr.lessThan(Utils.intVar(rel.getName(), e1, ctx), Utils.intVar(rel.getName(), e2, ctx))));
}
return enc;
}
use of com.dat3m.dartagnan.program.event.core.Event in project Dat3M by hernanponcedeleon.
the class Acyclic method reduceWithMinSets.
private void reduceWithMinSets(TupleSet encodeSet) {
/*
ASSUMPTION: MinSet is acyclic!
IDEA:
Edges that are (must-)transitively implied do not need to get encoded.
For this, we compute a (must-)transitive closure and a (must-)transitive reduction of must(rel).
The difference "must(rel)+ \ red(must(rel))" does not net to be encoded.
Note that it this is sound if the closure gets underapproximated and/or the reduction
gets over approximated.
COMPUTATION:
(1) We compute an approximate (must-)transitive closure of must(rel)
- must(rel) is likely to be already transitive per thread (due to mostly coming from po)
Hence, we get a reasonable approximation by closing transitively over thread-crossing edges only.
(2) We compute a (must) transitive reduction of the transitively closed must(rel)+.
- Since must(rel)+ is transitive, it suffice to check for each edge (a, c) if there
is an intermediate event b such that (a, b) and (b, c) are in must(rel)+
and b is implied by either a or c.
- It is possible to reduce must(rel) but that may give a less precise result.
*/
ExecutionAnalysis exec = analysisContext.get(ExecutionAnalysis.class);
TupleSet minSet = rel.getMinTupleSet();
// (1) Approximate transitive closure of minSet (only gets computed when crossEdges are available)
List<Tuple> crossEdges = minSet.stream().filter(t -> t.isCrossThread() && !t.getFirst().is(Tag.INIT)).collect(Collectors.toList());
TupleSet transMinSet = crossEdges.isEmpty() ? minSet : new TupleSet(minSet);
for (Tuple crossEdge : crossEdges) {
Event e1 = crossEdge.getFirst();
Event e2 = crossEdge.getSecond();
List<Event> ingoing = new ArrayList<>();
// ingoing events + self
ingoing.add(e1);
minSet.getBySecond(e1).stream().map(Tuple::getFirst).filter(e -> exec.isImplied(e, e1)).forEach(ingoing::add);
List<Event> outgoing = new ArrayList<>();
// outgoing edges + self
outgoing.add(e2);
minSet.getByFirst(e2).stream().map(Tuple::getSecond).filter(e -> exec.isImplied(e, e2)).forEach(outgoing::add);
for (Event in : ingoing) {
for (Event out : outgoing) {
transMinSet.add(new Tuple(in, out));
}
}
}
// (2) Approximate reduction of transitive must-set: red(must(r)+).
// Note: We reduce the transitive closure which may have more edges
// that can be used to perform reduction
TupleSet reduct = TupleSet.approximateTransitiveMustReduction(exec, transMinSet);
// Remove (must(r)+ \ red(must(r)+)
encodeSet.removeIf(t -> transMinSet.contains(t) && !reduct.contains(t));
}
use of com.dat3m.dartagnan.program.event.core.Event in project Dat3M by hernanponcedeleon.
the class RelCrit method encodeApprox.
// TODO: Not the most efficient implementation
// Let's see if we need to keep a reference to a thread in events for anything else, and then optimize this method
@Override
protected BooleanFormula encodeApprox(SolverContext ctx) {
BooleanFormulaManager bmgr = ctx.getFormulaManager().getBooleanFormulaManager();
BooleanFormula enc = bmgr.makeTrue();
for (Thread thread : task.getProgram().getThreads()) {
for (Event lock : thread.getCache().getEvents(FilterBasic.get(Tag.Linux.RCU_LOCK))) {
for (Event unlock : thread.getCache().getEvents(FilterBasic.get(Tag.Linux.RCU_UNLOCK))) {
if (lock.getCId() < unlock.getCId()) {
Tuple tuple = new Tuple(lock, unlock);
if (encodeTupleSet.contains(tuple)) {
BooleanFormula relation = bmgr.and(getExecPair(lock, unlock, ctx));
for (Event otherLock : thread.getCache().getEvents(FilterBasic.get(Tag.Linux.RCU_LOCK))) {
if (lock.getCId() < otherLock.getCId() && otherLock.getCId() < unlock.getCId()) {
relation = bmgr.and(relation, bmgr.not(this.getSMTVar(otherLock, unlock, ctx)));
}
}
for (Event otherUnlock : thread.getCache().getEvents(FilterBasic.get(Tag.Linux.RCU_UNLOCK))) {
if (lock.getCId() < otherUnlock.getCId() && otherUnlock.getCId() < unlock.getCId()) {
relation = bmgr.and(relation, bmgr.not(this.getSMTVar(lock, otherUnlock, ctx)));
}
}
enc = bmgr.and(enc, bmgr.equivalence(this.getSMTVar(tuple, ctx), relation));
}
}
}
}
}
return enc;
}
use of com.dat3m.dartagnan.program.event.core.Event in project Dat3M by hernanponcedeleon.
the class RelRMW method getMaxTupleSet.
@Override
public TupleSet getMaxTupleSet() {
if (maxTupleSet == null) {
logger.info("Computing maxTupleSet for " + getName());
baseMaxTupleSet = new TupleSet();
// RMWLoad -> RMWStore
FilterAbstract filter = FilterIntersection.get(FilterBasic.get(Tag.RMW), FilterBasic.get(Tag.WRITE));
for (Event store : task.getProgram().getCache().getEvents(filter)) {
if (store instanceof RMWStore) {
baseMaxTupleSet.add(new Tuple(((RMWStore) store).getLoadEvent(), store));
}
}
// Locks: Load -> Assume/CondJump -> Store
FilterAbstract locks = FilterUnion.get(FilterBasic.get(Tag.C11.LOCK), FilterBasic.get(Tag.Linux.LOCK_READ));
filter = FilterIntersection.get(FilterBasic.get(Tag.RMW), locks);
for (Event e : task.getProgram().getCache().getEvents(filter)) {
// Connect Load to Store
baseMaxTupleSet.add(new Tuple(e, e.getSuccessor().getSuccessor()));
}
// Atomics blocks: BeginAtomic -> EndAtomic
filter = FilterIntersection.get(FilterBasic.get(Tag.RMW), FilterBasic.get(SVCOMPATOMIC));
for (Event end : task.getProgram().getCache().getEvents(filter)) {
List<Event> block = ((EndAtomic) end).getBlock().stream().filter(x -> x.is(Tag.VISIBLE)).collect(Collectors.toList());
for (int i = 0; i < block.size(); i++) {
for (int j = i + 1; j < block.size(); j++) {
baseMaxTupleSet.add(new Tuple(block.get(i), block.get(j)));
}
}
}
removeMutuallyExclusiveTuples(baseMaxTupleSet);
maxTupleSet = new TupleSet();
maxTupleSet.addAll(baseMaxTupleSet);
// to find guaranteed pairs (the encoding can then also be improved)
for (Thread thread : task.getProgram().getThreads()) {
for (Event load : thread.getCache().getEvents(loadExclFilter)) {
for (Event store : thread.getCache().getEvents(storeExclFilter)) {
if (load.getCId() < store.getCId()) {
maxTupleSet.add(new Tuple(load, store));
}
}
}
}
removeMutuallyExclusiveTuples(maxTupleSet);
logger.info("maxTupleSet size for " + getName() + ": " + maxTupleSet.size());
}
return maxTupleSet;
}
use of com.dat3m.dartagnan.program.event.core.Event in project Dat3M by hernanponcedeleon.
the class BasicRegRelation method mkTupleSets.
private void mkTupleSets() {
maxTupleSet = new TupleSet();
minTupleSet = new TupleSet();
Dependency dep = analysisContext.requires(Dependency.class);
for (Event regReader : getEvents()) {
for (Register register : getRegisters(regReader)) {
Dependency.State r = dep.of(regReader, register);
for (Event regWriter : r.may) {
maxTupleSet.add(new Tuple(regWriter, regReader));
}
for (Event regWriter : r.must) {
minTupleSet.add(new Tuple(regWriter, regReader));
}
}
}
}
Aggregations