use of com.dat3m.dartagnan.program.event.core.utils.RegReaderData in project Dat3M by hernanponcedeleon.
the class ExecutionModel method trackDependencies.
private void trackDependencies(Event e) {
while (!endIfs.isEmpty() && e.getCId() >= endIfs.peek().getCId()) {
// We exited an If and remove the dependencies associated with it
// We do this inside a loop just in case multiple Ifs are left simultaneously
endIfs.pop();
curCtrlDeps.removeAll(ifCtrlDeps.pop());
}
if (e instanceof MemEvent) {
// ---- Track address dependency ----
MemEvent memEvent = (MemEvent) e;
HashSet<EventData> deps = new HashSet<>();
for (Register reg : memEvent.getAddress().getRegs()) {
deps.addAll(lastRegWrites.get(reg));
}
addrDepMap.put(eventMap.get(e), deps);
}
if (e.is(Tag.VISIBLE)) {
// ---- Track ctrl dependency ----
// TODO: This may be done more efficiently, as many events share the same set of ctrldeps.
ctrlDepMap.put(eventMap.get(e), new HashSet<>(curCtrlDeps));
}
if (e instanceof RegReaderData) {
// ---- Track data dependency ----
RegReaderData reader = (RegReaderData) e;
HashSet<EventData> deps = new HashSet<>();
for (Register r : reader.getDataRegs()) {
deps.addAll(lastRegWrites.getOrDefault(r, Collections.emptySet()));
}
if (e instanceof Store) {
// ---- visible data dependency ----
dataDepMap.put(eventMap.get(e), deps);
}
if (e instanceof RegWriter) {
// ---- internal data dependency ----
RegWriter writer = (RegWriter) e;
lastRegWrites.put(writer.getResultRegister(), deps);
}
if (e instanceof CondJump) {
if (e instanceof IfAsJump) {
// Remember what dependencies were added when entering the If so we can remove them when exiting
HashSet<EventData> addedDeps = new HashSet<>(Sets.difference(deps, curCtrlDeps));
ifCtrlDeps.push(addedDeps);
endIfs.push(((IfAsJump) e).getEndIf());
}
// Jumps add all dependencies
curCtrlDeps.addAll(deps);
}
}
if (e instanceof Load) {
// ---- Update lastRegWrites ----
Load load = (Load) e;
lastRegWrites.compute(load.getResultRegister(), (k, v) -> new HashSet<>()).add(eventMap.get(e));
}
}
use of com.dat3m.dartagnan.program.event.core.utils.RegReaderData 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.utils.RegReaderData 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.utils.RegReaderData 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