use of com.dat3m.dartagnan.program.event.lang.svcomp.EndAtomic 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.lang.svcomp.EndAtomic in project Dat3M by hernanponcedeleon.
the class WitnessBuilder method reOrderBasedOnAtomicity.
private List<Event> reOrderBasedOnAtomicity(Program program, List<Event> order) {
List<Event> result = new ArrayList<>();
// Maintained for constant lookup time
Set<Event> processedEvents = new HashSet<>();
// All the atomic blocks in the code that have to stay together in any execution
List<List<Event>> atomicBlocks = program.getCache().getEvents(FilterBasic.get(Tag.SVCOMP.SVCOMPATOMIC)).stream().map(e -> ((EndAtomic) e).getBlock().stream().filter(order::contains).collect(Collectors.toList())).collect(Collectors.toList());
for (Event next : order) {
if (processedEvents.contains(next)) {
// next was added as part of a previous block
continue;
}
List<Event> block = atomicBlocks.stream().filter(b -> Collections.binarySearch(b, next) >= 0).findFirst().orElseGet(() -> Collections.singletonList(next));
result.addAll(block);
processedEvents.addAll(block);
}
return result;
}
use of com.dat3m.dartagnan.program.event.lang.svcomp.EndAtomic in project Dat3M by hernanponcedeleon.
the class RelRf method atomicBlockOptimization.
private void atomicBlockOptimization() {
// TODO: This function can not only reduce rf-edges
// but we could also figure out implied coherences:
// Assume w1 and w2 are aliasing in the same block and w1 is before w2,
// then if w1 is co-before some external w3, then so is w2, i.e.
// co(w1, w3) => co(w2, w3), but we also have co(w2, w3) => co(w1, w3)
// so co(w1, w3) <=> co(w2, w3).
// This information is not expressible in terms of min/must sets, but
// we could still encode it.
int sizeBefore = maxTupleSet.size();
// Atomics blocks: BeginAtomic -> EndAtomic
ExecutionAnalysis exec = analysisContext.get(ExecutionAnalysis.class);
AliasAnalysis alias = analysisContext.get(AliasAnalysis.class);
FilterAbstract filter = FilterIntersection.get(FilterBasic.get(RMW), FilterBasic.get(SVCOMP.SVCOMPATOMIC));
for (Event end : task.getProgram().getCache().getEvents(filter)) {
// Collect memEvents of the atomic block
List<Store> writes = new ArrayList<>();
List<Load> reads = new ArrayList<>();
EndAtomic endAtomic = (EndAtomic) end;
for (Event b : endAtomic.getBlock()) {
if (b instanceof Load) {
reads.add((Load) b);
} else if (b instanceof Store) {
writes.add((Store) b);
}
}
for (Load r : reads) {
// If there is any write w inside the atomic block that is guaranteed to
// execute before the read and that aliases with it,
// then the read won't be able to read any external writes
boolean hasImpliedWrites = writes.stream().anyMatch(w -> w.getCId() < r.getCId() && exec.isImplied(r, w) && alias.mustAlias(r, w));
if (hasImpliedWrites) {
maxTupleSet.removeIf(t -> t.getSecond() == r && t.isCrossThread());
}
}
}
logger.info("Atomic block optimization eliminated " + (sizeBefore - maxTupleSet.size()) + " reads");
}
use of com.dat3m.dartagnan.program.event.lang.svcomp.EndAtomic in project Dat3M by hernanponcedeleon.
the class AtomicAsLock method run.
private void run(MemoryObject address, Thread thread) {
Label end;
if (thread.getExit() instanceof Label) {
end = (Label) thread.getExit();
} else {
end = newLabel("__VERIFIER_atomic_thread_end");
thread.getExit().setSuccessor(end);
thread.updateExit(end);
}
Register register = thread.newRegister(ARCH_PRECISION);
for (Event predecessor = thread.getEntry(); predecessor != null; ) {
Event event = predecessor.getSuccessor();
boolean begin = event instanceof BeginAtomic;
if (begin || event instanceof EndAtomic) {
Event load = EventFactory.newLoad(register, address, null);
Event check = EventFactory.newJump(new Atom(register, NEQ, begin ? IValue.ZERO : IValue.ONE), end);
Event store = EventFactory.newStore(address, begin ? IValue.ONE : IValue.ZERO, null);
load.setOId(event.getOId());
check.setOId(event.getOId());
store.setOId(event.getOId());
load.addFilters(Tag.C11.LOCK, Tag.RMW);
check.addFilters(Tag.C11.LOCK, Tag.RMW);
store.addFilters(Tag.C11.LOCK, Tag.RMW);
predecessor.setSuccessor(load);
load.setSuccessor(check);
check.setSuccessor(store);
store.setSuccessor(event.getSuccessor());
predecessor = store;
} else {
predecessor = event;
}
}
}
use of com.dat3m.dartagnan.program.event.lang.svcomp.EndAtomic in project Dat3M by hernanponcedeleon.
the class ExecutionModel method extractEventsFromModel.
// ========================== Internal methods =========================
private void extractEventsFromModel() {
// TODO(TH): We might also want to extract events such as inline assertions
// and whether they were violated or not.
int id = 0;
eventList.clear();
threadList.clear();
threadEventsMap.clear();
atomicBlocksMap.clear();
// This one can probably be constant and need not be rebuilt!
addressInitMap.clear();
addressWritesMap.clear();
addressReadsMap.clear();
writeReadsMap.clear();
fenceMap.clear();
eventMap.clear();
addrDepMap.clear();
dataDepMap.clear();
ctrlDepMap.clear();
List<Thread> threadList = new ArrayList<>(getProgram().getThreads());
List<Integer> threadEndIndexList = new ArrayList<>(threadList.size());
Map<Thread, List<List<Integer>>> atomicBlockRangesMap = new HashMap<>();
for (Thread thread : threadList) {
initDepTracking();
List<List<Integer>> atomicBlockRanges = atomicBlockRangesMap.computeIfAbsent(thread, key -> new ArrayList<>());
Event e = thread.getEntry();
int atomicBegin = -1;
int localId = 0;
do {
if (!e.wasExecuted(model)) {
e = e.getSuccessor();
continue;
}
if (eventFilter.filter(e)) {
addEvent(e, id++, localId++);
}
trackDependencies(e);
// ===== Atomic blocks =====
if (e instanceof BeginAtomic) {
atomicBegin = id;
} else if (e instanceof EndAtomic) {
Preconditions.checkState(atomicBegin != -1, "EndAtomic without matching BeginAtomic in model");
atomicBlockRanges.add(ImmutableList.of(atomicBegin, id));
atomicBegin = -1;
}
if (e instanceof CondJump) {
CondJump jump = (CondJump) e;
if (jump.didJump(model, context)) {
e = jump.getLabel();
continue;
}
}
e = e.getSuccessor();
} while (e != null);
// We have a BeginAtomic without EndAtomic since the program terminated within the block
if (atomicBegin != -1) {
atomicBlockRanges.add(ImmutableList.of(atomicBegin, id));
}
// -----------
threadEndIndexList.add(id);
}
// Get sublists for all threads
int start = 0;
for (int i = 0; i < threadList.size(); i++) {
Thread thread = threadList.get(i);
int end = threadEndIndexList.get(i);
if (start != end) {
this.threadList.add(thread);
threadEventsMap.put(thread, Collections.unmodifiableList(eventList.subList(start, end)));
atomicBlocksMap.put(thread, new ArrayList<>());
for (List<Integer> aRange : atomicBlockRangesMap.get(thread)) {
atomicBlocksMap.get(thread).add(eventList.subList(aRange.get(0), aRange.get(1)));
}
}
start = end;
}
}
Aggregations