Faster loop+break detection.

This commit is contained in:
Jindra Petřík
2015-07-12 13:11:19 +02:00
parent 6d52d3fbb2
commit 5b3a3d854b
3 changed files with 211 additions and 291 deletions

View File

@@ -71,6 +71,149 @@ public class Graph {
public static final int SOP_REMOVE_STATIC = 2;
/**
* Identify loop exits
*
* @param localData
* @param N All nodes
* @return
*/
public Map<GraphPart, List<GraphPart>> identifyLoopBreaks(BaseLocalData localData, List<GraphPart> N) {
Map<GraphPart, List<GraphPart>> lb = new HashMap<>();
for (GraphPart b0 : N) {
List<GraphPart> np = new ArrayList<>(b0.nextParts);
np.addAll(b0.throwParts);
for (GraphPart b : np) {
GraphPart hdr = (b0.type == GraphPart.TYPE_LOOP_HEADER || b0.type == GraphPart.TYPE_REENTRY) ? b0 : b0.iloop_header;
if (hdr != null && b.iloop_header != hdr && b.iloop_header == hdr.iloop_header && b != hdr) {
if (!lb.containsKey(hdr)) {
lb.put(hdr, new ArrayList<>());
}
if (!lb.get(hdr).contains(b)) {
lb.get(hdr).add(b);
}
}
}
}
return lb;
}
/**
* Identifying loops. Based on http://lenx.100871.net/papers/loop-SAS.pdf
*
* @param localData
* @param loopContinues Result - list of loop headers
* @param heads Entries
* @param N All Nodes
*/
public void identifyLoops(BaseLocalData localData, List<GraphPart> loopContinues, List<GraphPart> heads, List<GraphPart> N) {
for (GraphPart b : N) {
b.traversed = false;
b.DFSP_pos = 0;
b.irreducible = false;
b.type = GraphPart.TYPE_NONE;
//initialize b
}
for (GraphPart h0 : heads) {
trav_loops_DFS(localData, loopContinues, h0, 1);
}
}
/**
* Tag h as loop headr of b.
*
* @param b Block
* @param h Loop header
*/
protected void tag_lhead(GraphPart b, GraphPart h) {
if (b == h || h == null) {
return;
}
GraphPart cur1 = b;
GraphPart cur2 = h;
while (cur1.iloop_header != null) {
GraphPart ih = cur1.iloop_header;
if (ih == cur2) {
return;
}
if (ih.DFSP_pos < cur2.DFSP_pos) {
cur1.iloop_header = cur2;
cur1 = cur2;
cur2 = ih;
} else {
cur1 = h;
}
}
if (cur1 == cur2) {
return;
}
cur1.iloop_header = cur2;
}
/**
* Traverse loops deep first search
*
* @param localData
* @param loopHeaders Resulting loop headers
* @param b0 Current node
* @param DFSP_pos Position in DFSP
* @return innermost loop header of b0
*/
protected GraphPart trav_loops_DFS(BaseLocalData localData, List<GraphPart> loopHeaders, GraphPart b0, int DFSP_pos) {
List<GraphPart> folParts = new ArrayList<>(b0.nextParts);
folParts.addAll(b0.throwParts);
b0.traversed = true;
b0.DFSP_pos = DFSP_pos; //Mark b0s position in DFSP
for (GraphPart b : folParts) {
b = checkPart(null, localData, b, null);
if (b == null) {
continue;
}
if (!b.traversed) {
//case (A), new
GraphPart nh = trav_loops_DFS(localData, loopHeaders, b, DFSP_pos + 1);
tag_lhead(b0, nh);
} else {
if (b.DFSP_pos > 0) { // b in DFSP(b0)
//case (B)
if (b.type != GraphPart.TYPE_LOOP_HEADER) {
b.type = GraphPart.TYPE_LOOP_HEADER;
loopHeaders.add(b);
}
tag_lhead(b0, b);
} else if (b.iloop_header == null) {
//case (C), do nothing
} else {
GraphPart h = b.iloop_header;
if (h.DFSP_pos > 0) { // h in DFSP(b0)
//case (D)
tag_lhead(b0, h);
} else { // h not in DFSP(b0)
//case (E), reentry
b.type = GraphPart.TYPE_REENTRY; //TODO:and b0,b ?
h.irreducible = true;
while (h.iloop_header != null) {
h = h.iloop_header;
if (h.DFSP_pos > 0) { //h in DFSP(b0)
tag_lhead(b0, h);
break;
}
h.irreducible = true;
}
}
}
}
}
b0.DFSP_pos = 0; // clear b0s DFSP position
return b0.iloop_header;
}
public Graph(GraphSource code, List<Integer> alternateEntries) {
this.code = code;
this.alternateEntries = alternateEntries;
@@ -217,6 +360,7 @@ public class Graph {
return getCommonPart(localData, part.nextParts, loops);
}
//TODO: Make this faster!
public GraphPart getCommonPart(BaseLocalData localData, List<GraphPart> parts, List<Loop> loops) throws InterruptedException {
if (parts.isEmpty()) {
return null;
@@ -429,20 +573,46 @@ public class Graph {
}
TranslateStack stack = new TranslateStack(path);
List<Loop> loops = new ArrayList<>();
getLoops(localData, heads.get(0), loops, null);
//getLoops(localData, heads.get(0), loops, null);
List<GraphPart> loopHeads = new ArrayList<>();
identifyLoops(localData, loopHeads, heads, allParts);
Map<GraphPart, List<GraphPart>> loopBreaks = identifyLoopBreaks(localData, allParts);
List<Loop> loops2 = new ArrayList<>();
for (int i = 0; i < loopHeads.size(); i++) {
loops2.add(new Loop(loops2.size(), loopHeads.get(i), null));
}
for (int i = 0; i < loopHeads.size(); i++) {
if (loopBreaks.containsKey(loopHeads.get(i))) {
/*System.err.print("" + loopHeads.get(i) + ", breaks:");
for (GraphPart p : loopBreaks.get(loopHeads.get(i))) {
System.err.print("" + p + " ");
}
System.err.println("");*/
loops2.get(i).loopBreak = loopBreaks.get(loopHeads.get(i)).get(0);//getMostCommonPart(localData, loopBreaks.get(loopHeads.get(i)), loops2);
} else {
loops2.get(i).loopBreak = null;
}
}
loops = loops2;
/*1
System.err.println("<loops>");
for (Loop el : loops) {
System.err.println(el);
}
System.err.println("</loops>");*/
//TODO: Make getPrecontinues faster
getPrecontinues(path, localData, null, heads.get(0), allParts, loops, null);
/*System.err.println("<loopspre>");
for (Loop el : loops) {
System.err.println(el);
}
System.err.println("</loopspre>");//*/
List<GraphTargetItem> ret = printGraph(new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path);
processIfs(ret);
finalProcessStack(stack, ret);
@@ -831,6 +1001,7 @@ public class Graph {
return loopItem;
}
//TODO: Make this faster!!!
private void getPrecontinues(String path, BaseLocalData localData, GraphPart parent, GraphPart part, List<GraphPart> allParts, List<Loop> loops, List<GraphPart> stopPart) throws InterruptedException {
try {
markLevels(path, localData, part, allParts, loops);
@@ -1039,292 +1210,6 @@ public class Graph {
}
}
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<GraphPart> stopPart) throws InterruptedException {
clearLoops(loops);
getLoops(localData, part, loops, stopPart, true, 1, new ArrayList<>());
clearLoops(loops);
}
private void getLoops(BaseLocalData localData, GraphPart part, List<Loop> loops, List<GraphPart> stopPart, boolean first, int level, List<GraphPart> visited) throws InterruptedException {
boolean debugMode = false;
if (stopPart == null) {
stopPart = new ArrayList<>();
}
if (part == null) {
return;
}
part = checkPart(null, localData, part, null);
if (part == null) {
return;
}
if (!visited.contains(part)) {
visited.add(part);
}
if (debugMode) {
System.err.println("getloops: " + part);
}
List<GraphPart> loopContinues = getLoopsContinues(loops);
Loop lastP1 = null;
for (Loop el : loops) {
if ((el.phase == 1) && el.loopBreak == null) { //break not found yet
if (el.loopContinue != part) {
lastP1 = el;
} else {
lastP1 = null;
}
}
}
if (lastP1 != null) {
if (lastP1.breakCandidates.contains(part)) {
lastP1.breakCandidates.add(part);
lastP1.breakCandidatesLevels.add(level);
return;
} else {
List<GraphPart> loopContinues2 = new ArrayList<>(loopContinues);
loopContinues2.remove(lastP1.loopContinue);
List<Loop> loops2 = new ArrayList<>(loops);
loops2.remove(lastP1);
if (!part.leadsTo(localData, this, code, lastP1.loopContinue, loops2)) {
if (lastP1.breakCandidatesLocked == 0) {
if (debugMode) {
System.err.println("added breakCandidate " + part + " to " + lastP1);
}
lastP1.breakCandidates.add(part);
lastP1.breakCandidatesLevels.add(level);
return;
}
}
}
}
for (Loop el : loops) {
if (el.loopContinue == part) {
return;
}
}
if (stopPart.contains(part)) {
return;
}
part.level = level;
boolean isLoop = part.leadsTo(localData, this, code, part, loops);
Loop currentLoop = null;
if (isLoop) {
currentLoop = new Loop(loops.size(), part, null);
currentLoop.phase = 1;
loops.add(currentLoop);
loopContinues.add(part);
}
if (part.nextParts.size() == 2) {
List<GraphPart> nps = new ArrayList<>(part.nextParts);
/*for(int i=0;i<nps.size();i++){
nps.set(i,getNextNoJump(nps.get(i),localData));
}
if(nps.get(0) == nps.get(1)){
nps = part.nextParts;
}*/
nps = part.nextParts;
GraphPart next = getCommonPart(localData, nps, loops);//part.getNextPartPath(loopContinues);
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
if (next != null) {
stopPart2.add(next);
}
if (next != nps.get(0)) {
getLoops(localData, nps.get(0), loops, stopPart2, false, level + 1, visited);
}
if (next != nps.get(1)) {
getLoops(localData, nps.get(1), loops, stopPart2, false, level + 1, visited);
}
if (next != null) {
getLoops(localData, next, loops, stopPart, false, level, visited);
}
}
if (part.nextParts.size() > 2) {
GraphPart next = getNextCommonPart(localData, part, loops);
for (GraphPart p : part.nextParts) {
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
if (next != null) {
stopPart2.add(next);
}
for (GraphPart p2 : part.nextParts) {
if (p2 == p) {
continue;
}
if (!stopPart2.contains(p2)) {
stopPart2.add(p2);
}
}
if (next != p) {
getLoops(localData, p, loops, stopPart2, false, level + 1, visited);
}
}
if (next != null) {
getLoops(localData, next, loops, stopPart, false, level, visited);
}
}
if (part.nextParts.size() == 1) {
getLoops(localData, part.nextParts.get(0), loops, stopPart, false, level, visited);
}
List<Loop> loops2 = new ArrayList<>(loops);
for (Loop l : loops2) {
l.breakCandidatesLocked++;
}
for (GraphPart t : part.throwParts) {
if (!visited.contains(t)) {
getLoops(localData, t, loops, stopPart, false, level, visited);
}
}
for (Loop l : loops2) {
l.breakCandidatesLocked--;
}
if (isLoop) {
GraphPart found;
Map<GraphPart, Integer> removed = new HashMap<>();
do {
found = null;
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
GraphPart ch = checkPart(null, localData, currentLoop.breakCandidates.get(i), null);
if (ch == null) {
currentLoop.breakCandidates.remove(i);
i--;
}
}
loopcand:
for (GraphPart cand : currentLoop.breakCandidates) {
for (GraphPart cand2 : currentLoop.breakCandidates) {
if (cand == cand2) {
continue;
}
if (cand.leadsTo(localData, this, code, cand2, loops)) {
int lev1 = Integer.MAX_VALUE;
int lev2 = Integer.MAX_VALUE;
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
if (currentLoop.breakCandidates.get(i) == cand) {
if (currentLoop.breakCandidatesLevels.get(i) < lev1) {
lev1 = currentLoop.breakCandidatesLevels.get(i);
}
}
if (currentLoop.breakCandidates.get(i) == cand2) {
if (currentLoop.breakCandidatesLevels.get(i) < lev2) {
lev2 = currentLoop.breakCandidatesLevels.get(i);
}
}
}
if (lev1 <= lev2) {
found = cand2;
} else {
found = cand;
}
break loopcand;
}
}
}
if (found != null) {
int maxlevel = 0;
while (currentLoop.breakCandidates.contains(found)) {
int ind = currentLoop.breakCandidates.indexOf(found);
currentLoop.breakCandidates.remove(ind);
int lev = currentLoop.breakCandidatesLevels.remove(ind);
if (lev > maxlevel) {
maxlevel = lev;
}
}
if (removed.containsKey(found)) {
if (removed.get(found) > maxlevel) {
maxlevel = removed.get(found);
}
}
removed.put(found, maxlevel);
}
} while ((found != null) && (currentLoop.breakCandidates.size() > 1));
Map<GraphPart, Integer> count = new HashMap<>();
GraphPart winner = null;
int winnerCount = 0;
for (GraphPart cand : currentLoop.breakCandidates) {
if (!count.containsKey(cand)) {
count.put(cand, 0);
}
count.put(cand, count.get(cand) + 1);
boolean otherBreakCandidate = false;
for (Loop el : loops) {
if (el == currentLoop) {
continue;
}
if (el.breakCandidates.contains(cand)) {
otherBreakCandidate = true;
break;
}
}
if (otherBreakCandidate) {
} else if (count.get(cand) > winnerCount) {
winnerCount = count.get(cand);
winner = cand;
} else if (count.get(cand) == winnerCount) {
if (cand.path.length() < winner.path.length()) {
winner = cand;
}
}
}
for (int i = 0; i < currentLoop.breakCandidates.size(); i++) {
GraphPart cand = currentLoop.breakCandidates.get(i);
if (cand != winner) {
int lev = currentLoop.breakCandidatesLevels.get(i);
if (removed.containsKey(cand)) {
if (removed.get(cand) > lev) {
lev = removed.get(cand);
}
}
removed.put(cand, lev);
}
}
currentLoop.loopBreak = winner;
currentLoop.phase = 2;
boolean start = false;
for (int l = 0; l < loops.size(); l++) {
Loop el = loops.get(l);
if (start) {
el.phase = 1;
}
if (el == currentLoop) {
start = true;
}
}
List<GraphPart> removedVisited = new ArrayList<>();
for (GraphPart r : removed.keySet()) {
if (removedVisited.contains(r)) {
continue;
}
getLoops(localData, r, loops, stopPart, false, removed.get(r), visited);
removedVisited.add(r);
}
start = false;
for (int l = 0; l < loops.size(); l++) {
Loop el = loops.get(l);
if (el == currentLoop) {
start = true;
}
if (start) {
el.phase = 2;
}
}
getLoops(localData, currentLoop.loopBreak, loops, stopPart, false, level, visited);
}
}
protected List<GraphTargetItem> printGraph(Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, List<GraphPart> visited, BaseLocalData localData, TranslateStack stack, List<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();