use of com.dat3m.dartagnan.program.event.core.MemEvent in project Dat3M by hernanponcedeleon.
the class RelRf method applyLocalConsistency.
private void applyLocalConsistency() {
// Remove future reads
maxTupleSet.removeIf(Tuple::isBackward);
// Remove past reads
ExecutionAnalysis exec = analysisContext.get(ExecutionAnalysis.class);
AliasAnalysis alias = analysisContext.get(AliasAnalysis.class);
Set<Tuple> deletedTuples = new HashSet<>();
for (Event r : task.getProgram().getCache().getEvents(FilterBasic.get(READ))) {
MemEvent read = (MemEvent) r;
// The set of same-thread writes as well as init writes that could be read from (all before the read)
// sorted by order (init events first)
List<MemEvent> possibleWrites = maxTupleSet.getBySecond(read).stream().map(Tuple::getFirst).filter(e -> (e.getThread() == read.getThread() || e.is(INIT))).map(x -> (MemEvent) x).sorted((o1, o2) -> o1.is(INIT) == o2.is(INIT) ? (o1.getCId() - o2.getCId()) : o1.is(INIT) ? -1 : 1).collect(Collectors.toList());
// The set of writes that won't be readable due getting overwritten.
Set<MemEvent> deletedWrites = new HashSet<>();
// - w2 must alias with either w1 or r.
for (int i = 0; i < possibleWrites.size(); i++) {
MemEvent w1 = possibleWrites.get(i);
for (MemEvent w2 : possibleWrites.subList(i + 1, possibleWrites.size())) {
// executed
if ((exec.isImplied(w1, w2) || exec.isImplied(read, w2)) && (alias.mustAlias(w1, w2) || alias.mustAlias(w2, read))) {
deletedWrites.add(w1);
break;
}
}
}
for (Event w : deletedWrites) {
deletedTuples.add(new Tuple(w, read));
}
}
maxTupleSet.removeAll(deletedTuples);
}
use of com.dat3m.dartagnan.program.event.core.MemEvent in project Dat3M by hernanponcedeleon.
the class FindSpinLoops method isSideEffectFree.
private boolean isSideEffectFree(Label loopBegin, CondJump loopEnd) {
Event cur = loopBegin.getSuccessor();
// Unsafe means the loop read from the registers before writing to them.
Set<Register> unsafeRegisters = new HashSet<>();
// Safe means the loop wrote to these register before using them
Set<Register> safeRegisters = new HashSet<>();
while (cur != loopEnd) {
if (cur instanceof MemEvent) {
if (cur.is(Tag.WRITE)) {
// Writes always cause side effects
return false;
}
MemEvent memEvent = (MemEvent) cur;
Set<Register> addrRegs = memEvent.getAddress().getRegs();
unsafeRegisters.addAll(Sets.difference(addrRegs, safeRegisters));
}
if (cur instanceof RegReaderData) {
RegReaderData reader = (RegReaderData) cur;
Set<Register> dataRegs = reader.getDataRegs();
unsafeRegisters.addAll(Sets.difference(dataRegs, safeRegisters));
}
if (cur instanceof RegWriter) {
RegWriter writer = (RegWriter) cur;
if (unsafeRegisters.contains(writer.getResultRegister())) {
return false;
} else {
safeRegisters.add(writer.getResultRegister());
}
}
cur = cur.getSuccessor();
}
return true;
}
use of com.dat3m.dartagnan.program.event.core.MemEvent in project Dat3M by hernanponcedeleon.
the class PropertyEncoder method encodeDataRaces.
public BooleanFormula encodeDataRaces(SolverContext ctx) {
final String hb = "hb";
checkState(memoryModel.getAxioms().stream().anyMatch(ax -> ax.isAcyclicity() && ax.getRelation().getName().equals(hb)), "The provided WMM needs an 'acyclic(hb)' axiom to encode data races.");
logger.info("Encoding data-races");
BooleanFormulaManager bmgr = ctx.getFormulaManager().getBooleanFormulaManager();
IntegerFormulaManager imgr = ctx.getFormulaManager().getIntegerFormulaManager();
BooleanFormula enc = bmgr.makeFalse();
for (Thread t1 : program.getThreads()) {
for (Thread t2 : program.getThreads()) {
if (t1.getId() == t2.getId()) {
continue;
}
for (Event e1 : t1.getCache().getEvents(FilterMinus.get(FilterBasic.get(Tag.WRITE), FilterBasic.get(Tag.INIT)))) {
MemEvent w = (MemEvent) e1;
for (Event e2 : t2.getCache().getEvents(FilterMinus.get(FilterBasic.get(Tag.MEMORY), FilterBasic.get(Tag.INIT)))) {
MemEvent m = (MemEvent) e2;
if (w.hasFilter(Tag.RMW) && m.hasFilter(Tag.RMW)) {
continue;
}
if (w.canRace() && m.canRace() && alias.mayAlias(w, m)) {
BooleanFormula conflict = bmgr.and(m.exec(), w.exec(), edge(hb, m, w, ctx), generalEqual(w.getMemAddressExpr(), m.getMemAddressExpr(), ctx), imgr.equal(intVar(hb, w, ctx), imgr.add(intVar(hb, m, ctx), imgr.makeNumber(BigInteger.ONE))));
enc = bmgr.or(enc, conflict);
}
}
}
}
}
// We use the SMT variable to extract from the model if the property was violated
enc = bmgr.equivalence(RACES.getSMTVariable(ctx), enc);
return bmgr.and(RACES.getSMTVariable(ctx), enc);
}
use of com.dat3m.dartagnan.program.event.core.MemEvent in project Dat3M by hernanponcedeleon.
the class Dependency method process.
private void process(Thread thread, ExecutionAnalysis exec) {
Map<Event, Set<Writer>> jumps = new HashMap<>();
Set<Writer> state = new HashSet<>();
for (Register register : thread.getRegisters()) {
state.add(new Writer(register, null));
}
for (Event event : thread.getEvents()) {
// merge with incoming jumps
Set<Writer> j = jumps.remove(event);
if (j != null) {
state.addAll(j);
}
// collecting dependencies, mixing 'data' and 'addr'
Set<Register> registers = new HashSet<>();
if (event instanceof RegReaderData) {
registers.addAll(((RegReaderData) event).getDataRegs());
}
if (event instanceof MemEvent) {
registers.addAll(((MemEvent) event).getAddress().getRegs());
}
if (!registers.isEmpty()) {
Map<Register, State> result = new HashMap<>();
for (Register register : registers) {
if (register.getThreadId() == Register.NO_THREAD) {
continue;
}
State writers;
if (register.getThreadId() != event.getThread().getId()) {
writers = finalWriters.get(register);
checkArgument(writers != null, "Helper thread %s should be listed after their creator thread %s.", thread.getId(), register.getThreadId());
if (writers.may.size() != 1) {
logger.warn("Writers {} for inter-thread register {} read by event {} of thread {}", writers.may, register, event, thread.getId());
}
} else {
writers = process(state, register, exec);
if (!writers.initialized) {
logger.warn("Uninitialized register {} read by event {} of thread {}", register, event, thread.getId());
}
}
result.put(register, writers);
}
map.put(event, result);
}
// update state, if changed by event
if (event instanceof RegWriter) {
Register register = ((RegWriter) event).getResultRegister();
if (event.cfImpliesExec()) {
state.removeIf(e -> e.register.equals(register));
}
state.add(new Writer(register, event));
}
// copy state, if branching
if (event instanceof CondJump) {
jumps.computeIfAbsent(((CondJump) event).getLabel(), k -> new HashSet<>()).addAll(state);
if (((CondJump) event).isGoto()) {
state.clear();
}
}
}
if (!jumps.isEmpty()) {
logger.warn("Thread {} contains jumps to removed labels {}", thread.getId(), jumps.keySet());
for (Set<Writer> j : jumps.values()) {
state.addAll(j);
}
}
for (Register register : thread.getRegisters()) {
finalWriters.put(register, process(state, register, exec));
}
}
use of com.dat3m.dartagnan.program.event.core.MemEvent in project Dat3M by hernanponcedeleon.
the class DeadAssignmentElimination method eliminateDeadStores.
private void eliminateDeadStores(Thread thread) {
Set<Event> removed = new HashSet<>();
// Registers that are used by other threads or assertions cannot be removed
Set<Register> usedRegs = new HashSet<>();
if (program.getAss() != null) {
usedRegs.addAll(program.getAss().getRegs());
}
program.getCache().getEvents(FilterBasic.get(ASSERTION)).stream().filter(RegWriter.class::isInstance).map(RegWriter.class::cast).map(RegWriter::getResultRegister).forEach(usedRegs::add);
program.getEvents().stream().filter(o -> !o.getThread().equals(thread)).filter(o -> o instanceof RegReaderData).forEach(o -> usedRegs.addAll(((RegReaderData) o).getDataRegs()));
for (Event e : Lists.reverse(thread.getEvents())) {
if (e instanceof RegWriter && !e.is(VISIBLE) && !usedRegs.contains(((RegWriter) e).getResultRegister())) {
// Invisible RegWriters that write to an unused reg can get removed
removed.add(e);
}
// An event that was not removed adds its dependencies to the used registers
if (!removed.contains(e)) {
if (e instanceof RegReaderData) {
// Data & Ctrl dependencies
usedRegs.addAll(((RegReaderData) e).getDataRegs());
}
if (e instanceof MemEvent) {
// Address dependencies
usedRegs.addAll(((MemEvent) e).getAddress().getRegs());
}
}
}
// Here is the actual removal
Event pred = null;
Event cur = thread.getEntry();
while (cur != null) {
if (removed.contains(cur) && !cur.is(Tag.NOOPT)) {
cur.delete();
cur = pred;
}
pred = cur;
cur = cur.getSuccessor();
}
}
Aggregations