use of com.dat3m.dartagnan.program.event.core.CondJump in project Dat3M by hernanponcedeleon.
the class FindSpinLoops method detectAndMarkSpinLoops.
private void detectAndMarkSpinLoops(Thread t) {
Event curr = t.getEntry();
while (curr != null) {
// Find start of spinloop that is not already marked.
if (curr instanceof Label && !curr.is(Tag.SPINLOOP)) {
Label label = (Label) curr;
// Importantly, this looks for the LAST backjump to the label
List<CondJump> backjumps = label.getJumpSet().stream().filter(x -> x.getOId() > label.getOId()).sorted().collect(Collectors.toList());
if (!backjumps.isEmpty()) {
Label loopStart = label;
CondJump loopEnd = backjumps.get(backjumps.size() - 1);
if (isSideEffectFree(loopStart, loopEnd)) {
loopStart.addFilters(Tag.SPINLOOP, Tag.NOOPT);
backjumps.forEach(x -> x.addFilters(Tag.SPINLOOP, Tag.NOOPT));
spinloops++;
}
}
}
curr = curr.getSuccessor();
}
t.clearCache();
}
use of com.dat3m.dartagnan.program.event.core.CondJump in project Dat3M by hernanponcedeleon.
the class LoopUnrolling method unrollThread.
private void unrollThread(Thread thread, int defaultBound) {
Event cur = thread.getEntry();
while (cur != null) {
Event next = cur.getSuccessor();
if (cur instanceof CondJump && ((CondJump) cur).getLabel().getOId() < cur.getOId()) {
CondJump jump = (CondJump) cur;
if (jump.getLabel().getJumpSet().stream().allMatch(x -> x.getOId() <= jump.getOId())) {
// TODO: Get different bounds for different loops (e.g. via annotations)
int bound = jump.is(Tag.SPINLOOP) ? 1 : defaultBound;
unrollLoop((CondJump) cur, bound);
}
}
cur = next;
}
}
use of com.dat3m.dartagnan.program.event.core.CondJump in project Dat3M by hernanponcedeleon.
the class LoopUnrolling method unrollLoop.
private void unrollLoop(CondJump loopBackJump, int bound) {
Label loopBegin = loopBackJump.getLabel();
Preconditions.checkArgument(bound >= 1, "Positive unrolling bound expected.");
Preconditions.checkArgument(loopBegin.getOId() < loopBackJump.getOId(), "The jump does not belong to a loop.");
Preconditions.checkArgument(loopBackJump.getUId() < 0, "The loop has already been unrolled");
// (1) Collect continue points of the loop
List<CondJump> continues = new ArrayList<>();
for (Event e = loopBegin; e != null && e != loopBackJump; e = e.getSuccessor()) {
if (e instanceof CondJump && ((CondJump) e).getLabel() == loopBegin) {
continues.add((CondJump) e);
}
}
continues.add(loopBackJump);
// (2) Collect forward jumps from the outside into the loop
List<CondJump> enterJumps = new ArrayList<>();
for (Event e = loopBegin; e != null && e != loopBackJump; e = e.getSuccessor()) {
if (e instanceof Label) {
Label label = (Label) e;
label.getJumpSet().stream().filter(j -> j.getOId() < loopBegin.getOId()).forEach(enterJumps::add);
}
}
int iterCounter = 0;
while (--bound >= 0) {
iterCounter++;
if (bound == 0) {
Label exit = (Label) loopBackJump.getThread().getExit();
loopBegin.setName(loopBegin.getName() + "_" + iterCounter);
for (CondJump cont : continues) {
if (!cont.isGoto()) {
logger.warn("Conditional jump {} was replaced by unconditional bound event", cont);
}
CondJump boundEvent = EventFactory.newGoto(exit);
// Keep tags of original jump.
boundEvent.addFilters(cont.getFilters());
boundEvent.addFilters(Tag.BOUND, Tag.NOOPT);
cont.getPredecessor().setSuccessor(boundEvent);
boundEvent.setSuccessor(cont.getSuccessor());
cont.delete();
}
} else {
Map<Event, Event> copyCtx = new HashMap<>();
List<Event> copies = copyPath(loopBegin, loopBackJump, copyCtx);
((Label) copyCtx.get(loopBegin)).setName(loopBegin.getName() + "_" + iterCounter);
// Insert copies at right place
loopBegin.getPredecessor().setSuccessor(copies.get(0));
copies.get(copies.size() - 1).setSuccessor(loopBegin);
// Update entering jumps to go to the copies.
for (CondJump enterJump : enterJumps) {
enterJump.updateReferences(copyCtx);
}
enterJumps.clear();
// All "continues" that were copied need to get updated to jump forward to the next iteration.
for (CondJump cont : continues) {
if (cont == loopBackJump) {
continue;
}
CondJump copy = (CondJump) copyCtx.get(cont);
copy.updateReferences(Map.of(copy.getLabel(), loopBegin));
enterJumps.add(cont);
}
}
}
}
use of com.dat3m.dartagnan.program.event.core.CondJump in project Dat3M by hernanponcedeleon.
the class RemoveDeadCondJumps method eliminateDeadCondJumps.
private void eliminateDeadCondJumps(Thread thread) {
Map<Event, List<Event>> immediateLabelPredecessors = new HashMap<>();
List<Event> removed = new ArrayList<>();
Event pred = thread.getEntry();
Event current = pred.getSuccessor();
// We fill the map of predecessors
while (current != null) {
if (current instanceof CondJump) {
CondJump jump = (CondJump) current;
// After constant propagation some jumps have False as condition and are dead
if (jump.isDead()) {
removed.add(jump);
} else {
immediateLabelPredecessors.computeIfAbsent(jump.getLabel(), key -> new ArrayList<>()).add(jump);
}
} else if (current instanceof Label && !(pred instanceof CondJump && ((CondJump) pred).isGoto())) {
immediateLabelPredecessors.computeIfAbsent(current, key -> new ArrayList<>()).add(pred);
}
pred = current;
current = current.getSuccessor();
}
// We check which ifs can be removed
for (Event label : immediateLabelPredecessors.keySet()) {
Event next = label.getSuccessor();
List<Event> preds = immediateLabelPredecessors.get(label);
// BOUND events
if (next instanceof CondJump && preds.stream().allMatch(e -> mutuallyExclusiveIfs((CondJump) next, e))) {
removed.add(next);
}
// SPINLOOP events
if (next != null && preds.size() == 1 && preds.get(0).getSuccessor().equals(label)) {
removed.add(label);
}
}
// Here is the actual removal
pred = null;
Event cur = thread.getEntry();
boolean dead = false;
while (cur != null) {
if (dead && cur instanceof Label && !immediateLabelPredecessors.getOrDefault(cur, List.of()).isEmpty()) {
dead = false;
}
if (dead && cur instanceof CondJump && immediateLabelPredecessors.containsKey(((CondJump) cur).getLabel())) {
immediateLabelPredecessors.get(((CondJump) cur).getLabel()).remove(cur);
}
if (dead && immediateLabelPredecessors.containsKey(cur.getSuccessor())) {
immediateLabelPredecessors.get(cur.getSuccessor()).remove(cur);
}
if ((dead || removed.contains(cur)) && !cur.is(Tag.NOOPT)) {
cur.delete();
cur = pred;
}
if (cur instanceof CondJump && ((CondJump) cur).isGoto()) {
dead = true;
}
pred = cur;
cur = cur.getSuccessor();
}
}
Aggregations