mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Implemented loop depth analysis pass.
This commit is contained in:
parent
d1a13402fe
commit
007a5d34b4
@ -47,8 +47,8 @@ public class CallGraph {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CallBlock getFirstCallBlock() {
|
||||
return getOrCreateCallBlock(new LabelRef(""));
|
||||
public LabelRef getFirstCallBlock() {
|
||||
return new LabelRef("");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,6 +65,21 @@ public class CallGraph {
|
||||
return called;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all call blocks that call a specific call block
|
||||
* @param scopeLabel The label of scope (the call block)
|
||||
* @return The scope labels of call blocks that call the passed block
|
||||
*/
|
||||
public Collection<LabelRef> getCallingBlocks(LabelRef scopeLabel) {
|
||||
ArrayList<LabelRef> callingBlocks = new ArrayList<>();
|
||||
for (CallBlock callBlock : callBlocks) {
|
||||
if(callBlock.getCalledBlocks().contains(scopeLabel)) {
|
||||
callingBlocks.add(callBlock.getScopeLabel());
|
||||
}
|
||||
}
|
||||
return callingBlocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
@ -110,7 +125,6 @@ public class CallGraph {
|
||||
called.add(call.getProcedure());
|
||||
}
|
||||
return called;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,6 +137,29 @@ public class CallGraph {
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all calls
|
||||
* @return The calls
|
||||
*/
|
||||
public List<Call> getCalls() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all calls to a specific call block
|
||||
* @param scope The scope label of the block
|
||||
* @return All calls to the passed scope
|
||||
*/
|
||||
public Collection<Call> getCalls(LabelRef scope) {
|
||||
ArrayList<Call> callsToScope = new ArrayList<>();
|
||||
for (Call call : calls) {
|
||||
if(call.getProcedure().equals(scope)) {
|
||||
callsToScope.add(call);
|
||||
}
|
||||
}
|
||||
return callsToScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single call found in the call block.
|
||||
*/
|
||||
|
@ -155,6 +155,41 @@ public class ControlFlowGraph {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDominators(DominatorsGraph dominators) {
|
||||
this.dominators = dominators;
|
||||
}
|
||||
|
||||
public DominatorsGraph getDominators() {
|
||||
return dominators;
|
||||
}
|
||||
|
||||
public void setLoops(NaturalLoopSet loopSet) {
|
||||
this.loopSet = loopSet;
|
||||
}
|
||||
|
||||
public NaturalLoopSet getLoopSet() {
|
||||
return loopSet;
|
||||
}
|
||||
|
||||
public CallGraph getCallGraph() {
|
||||
return callGraph;
|
||||
}
|
||||
|
||||
public void setCallGraph(CallGraph callGraph) {
|
||||
this.callGraph = callGraph;
|
||||
}
|
||||
|
||||
public ControlFlowBlock getBlockFromStatementIdx(int statementIdx) {
|
||||
for (ControlFlowBlock block : getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if(statementIdx==statement.getIndex()) {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString(ProgramScope scope) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (ControlFlowBlock block : getAllBlocks()) {
|
||||
@ -183,28 +218,4 @@ public class ControlFlowGraph {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setDominators(DominatorsGraph dominators) {
|
||||
this.dominators = dominators;
|
||||
}
|
||||
|
||||
public DominatorsGraph getDominators() {
|
||||
return dominators;
|
||||
}
|
||||
|
||||
public void setLoops(NaturalLoopSet loopSet) {
|
||||
this.loopSet = loopSet;
|
||||
}
|
||||
|
||||
public NaturalLoopSet getLoopSet() {
|
||||
return loopSet;
|
||||
}
|
||||
|
||||
public CallGraph getCallGraph() {
|
||||
return callGraph;
|
||||
}
|
||||
|
||||
public void setCallGraph(CallGraph callGraph) {
|
||||
this.callGraph = callGraph;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ public class NaturalLoop {
|
||||
*/
|
||||
private Set<LabelRef> blocks;
|
||||
|
||||
/** The loop nesting depth of the loop. Calculated by {@link dk.camelot64.kickc.passes.Pass3LoopDepthAnalysis}. */
|
||||
private Integer depth;
|
||||
|
||||
/**
|
||||
* Create a new natural loop.
|
||||
* The loop is not filled with all blocks from the start, but only holds the head & tail.
|
||||
@ -72,6 +75,9 @@ public class NaturalLoop {
|
||||
} else {
|
||||
out.append("null");
|
||||
}
|
||||
if(depth!=null) {
|
||||
out.append(" depth: "+depth);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@ -106,6 +112,14 @@ public class NaturalLoop {
|
||||
this.blocks.addAll(blocks);
|
||||
}
|
||||
|
||||
public Integer getDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public void setDepth(Integer depth) {
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -1,9 +1,6 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/** A set of natural loops in a control flow graph.
|
||||
* <p>For definitions and more see http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
|
||||
@ -71,6 +68,26 @@ public class NaturalLoopSet {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all loops containing a specific control flow graph block
|
||||
*
|
||||
* @param block The block to look for
|
||||
* @return All loops containing the block
|
||||
*/
|
||||
public Collection<NaturalLoop> getLoopsContainingBlock(LabelRef block) {
|
||||
ArrayList<NaturalLoop> containing = new ArrayList<>();
|
||||
for (NaturalLoop loop : loops) {
|
||||
for (LabelRef loopBlock : loop.getBlocks()) {
|
||||
if(block.equals(loopBlock)) {
|
||||
containing.add(loop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return containing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a loop from the set
|
||||
* @param loop The loop to remove
|
||||
@ -78,4 +95,5 @@ public class NaturalLoopSet {
|
||||
public void remove(NaturalLoop loop) {
|
||||
this.loops.remove(loop);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,12 +35,94 @@ public class Pass3LoopDepthAnalysis {
|
||||
CallGraph callGraph = program.getGraph().getCallGraph();
|
||||
NaturalLoopSet loopSet = program.getGraph().getLoopSet();
|
||||
|
||||
Deque<LabelRef> todo = new ArrayDeque<>();
|
||||
Set<LabelRef> done = new LinkedHashSet<>();
|
||||
todo.push(callGraph.getFirstCallBlock());
|
||||
while(!todo.isEmpty()) {
|
||||
LabelRef currentScope = todo.pop();
|
||||
done.add(currentScope);
|
||||
CallGraph.CallBlock currentCallBlock = callGraph.getOrCreateCallBlock(currentScope);
|
||||
// Add called sub blocks for later processing
|
||||
Collection<LabelRef> subBlocks = currentCallBlock.getCalledBlocks();
|
||||
for (LabelRef subBlock : subBlocks) {
|
||||
if (!done.contains(subBlock) && !todo.contains(subBlock)) {
|
||||
todo.add(subBlock);
|
||||
}
|
||||
}
|
||||
// Find the scope blocks calling the current scope block - and the loop depth of the blocks where the call statement is
|
||||
int callingDepth = 1;
|
||||
Collection<LabelRef> callingScopes = callGraph.getCallingBlocks(currentScope);
|
||||
for (LabelRef callingScope : callingScopes) {
|
||||
CallGraph.CallBlock callingBlock = callGraph.getOrCreateCallBlock(callingScope);
|
||||
Collection<CallGraph.CallBlock.Call> calls = callingBlock.getCalls(currentScope);
|
||||
for (CallGraph.CallBlock.Call call : calls) {
|
||||
int callStatementIdx = call.getCallStatementIdx();
|
||||
ControlFlowBlock callingControlBlock = program.getGraph().getBlockFromStatementIdx(callStatementIdx);
|
||||
Collection<NaturalLoop> callingLoops = loopSet.getLoopsContainingBlock(callingControlBlock.getLabel());
|
||||
for (NaturalLoop callingLoop : callingLoops) {
|
||||
int potentialDepth = callingLoop.getDepth()+1;
|
||||
if(potentialDepth >callingDepth) {
|
||||
callingDepth = potentialDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
findLoopDepth(currentScope, callingDepth);
|
||||
}
|
||||
}
|
||||
|
||||
private void findLoopDepth(LabelRef currentScope, int initialDepth) {
|
||||
NaturalLoopSet loopSet = program.getGraph().getLoopSet();
|
||||
// Find loops in the current scope block
|
||||
List<NaturalLoop> currentScopeLoops = new ArrayList<>();
|
||||
for (NaturalLoop loop : loopSet.getLoops()) {
|
||||
LabelRef loopHead = loop.getHead();
|
||||
ControlFlowBlock loopHeadBlock = program.getGraph().getBlock(loopHead);
|
||||
LabelRef scopeRef = Pass3CallGraphAnalysis.getScopeRef(loopHeadBlock, program);
|
||||
if(scopeRef.equals(currentScope)) {
|
||||
// Loop is inside current scope block!
|
||||
currentScopeLoops.add(loop);
|
||||
}
|
||||
}
|
||||
|
||||
log.append("Found "+currentScopeLoops.size()+" loops in scope ["+currentScope.toString()+"]");
|
||||
for (NaturalLoop loop : currentScopeLoops) {
|
||||
log.append(" "+loop.toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Find loop nesting depths in current scope loops
|
||||
Deque<NaturalLoop> todo = new ArrayDeque<>();
|
||||
Set<NaturalLoop> done = new LinkedHashSet<>();
|
||||
todo.addAll(currentScopeLoops);
|
||||
while(!todo.isEmpty()) {
|
||||
NaturalLoop loop = todo.getFirst();
|
||||
todo.removeFirst();
|
||||
// Does any unprocessed loop nest this one?
|
||||
boolean postpone = false;
|
||||
for (NaturalLoop otherLoop : todo) {
|
||||
if(otherLoop.nests(loop)) {
|
||||
// postpone this loop and move on
|
||||
postpone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(postpone) {
|
||||
todo.addLast(loop);
|
||||
continue;
|
||||
}
|
||||
int depth = initialDepth;
|
||||
// Does any already processed loop nest this one?
|
||||
for (NaturalLoop otherLoop : done) {
|
||||
if(otherLoop.nests(loop)) {
|
||||
int potentialDepth = otherLoop.getDepth()+1;
|
||||
if(potentialDepth>depth) {
|
||||
depth = potentialDepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
loop.setDepth(depth);
|
||||
done.add(loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -999,6 +999,11 @@ Populated: Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
NATURAL LOOPS
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
|
||||
Found 1 loops in scope []
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2 depth: 1
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ cursor#3 cursor#5 cursor#1 cursor#2 ]
|
||||
[ x#2 x#1 ]
|
||||
|
@ -3795,6 +3795,33 @@ Loop head: flip::@1 tails: flip::@4 blocks: flip::@4 flip::@2 flip::@1
|
||||
Loop head: flip::@3 tails: flip::@3 blocks: flip::@3
|
||||
Loop head: prepare::@1 tails: prepare::@1 blocks: prepare::@1
|
||||
|
||||
Found 0 loops in scope []
|
||||
Found 4 loops in scope [main]
|
||||
Loop head: main::@3 tails: main::@3 blocks: main::@3
|
||||
Loop head: main::@4 tails: main::@4 blocks: main::@4
|
||||
Loop head: main::@3 tails: main::@6 blocks: main::@6 main::@4 main::@3
|
||||
Loop head: main::@3 tails: main::@11 blocks: main::@11 main::@10 main::@7 main::@6 main::@4 main::@3
|
||||
Found 1 loops in scope [prepare]
|
||||
Loop head: prepare::@1 tails: prepare::@1 blocks: prepare::@1
|
||||
Found 3 loops in scope [flip]
|
||||
Loop head: flip::@2 tails: flip::@2 blocks: flip::@2
|
||||
Loop head: flip::@1 tails: flip::@4 blocks: flip::@4 flip::@2 flip::@1
|
||||
Loop head: flip::@3 tails: flip::@3 blocks: flip::@3
|
||||
Found 2 loops in scope [plot]
|
||||
Loop head: plot::@2 tails: plot::@2 blocks: plot::@2
|
||||
Loop head: plot::@1 tails: plot::@3 blocks: plot::@3 plot::@2 plot::@1
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: main::@3 tails: main::@3 blocks: main::@3 depth: 3
|
||||
Loop head: main::@4 tails: main::@4 blocks: main::@4 depth: 3
|
||||
Loop head: main::@3 tails: main::@6 blocks: main::@6 main::@4 main::@3 depth: 2
|
||||
Loop head: main::@3 tails: main::@11 blocks: main::@11 main::@10 main::@7 main::@6 main::@4 main::@3 depth: 1
|
||||
Loop head: plot::@2 tails: plot::@2 blocks: plot::@2 depth: 3
|
||||
Loop head: plot::@1 tails: plot::@3 blocks: plot::@3 plot::@2 plot::@1 depth: 2
|
||||
Loop head: flip::@2 tails: flip::@2 blocks: flip::@2 depth: 3
|
||||
Loop head: flip::@1 tails: flip::@4 blocks: flip::@4 flip::@2 flip::@1 depth: 2
|
||||
Loop head: flip::@3 tails: flip::@3 blocks: flip::@3 depth: 2
|
||||
Loop head: prepare::@1 tails: prepare::@1 blocks: prepare::@1 depth: 1
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::c#2 main::c#1 ]
|
||||
[ plot::line#2 plot::line#1 ]
|
||||
|
@ -355,6 +355,11 @@ Populated: Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
NATURAL LOOPS
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
|
||||
Found 1 loops in scope []
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: @1 tails: @3 blocks: @3 @1 @2 depth: 1
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ s#2 s#4 s#1 ]
|
||||
|
@ -379,6 +379,11 @@ Coalesced: Loop head: @1 tails: @5 @4 blocks: @5 @2 @1 @4
|
||||
NATURAL LOOPS
|
||||
Loop head: @1 tails: @5 @4 blocks: @5 @2 @1 @4
|
||||
|
||||
Found 1 loops in scope []
|
||||
Loop head: @1 tails: @5 @4 blocks: @5 @2 @1 @4
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: @1 tails: @5 @4 blocks: @5 @2 @1 @4 depth: 1
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
[ s#3 s#1 s#2 ]
|
||||
|
@ -275,6 +275,11 @@ Populated: Loop head: @1 tails: @1 blocks: @1
|
||||
NATURAL LOOPS
|
||||
Loop head: @1 tails: @1 blocks: @1
|
||||
|
||||
Found 1 loops in scope []
|
||||
Loop head: @1 tails: @1 blocks: @1
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
Loop head: @1 tails: @1 blocks: @1 depth: 1
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ i#2 i#1 ]
|
||||
Copy Coalesced equivalence classes
|
||||
|
@ -310,6 +310,10 @@ sum::@return dominated by @BEGIN sum::@return sum
|
||||
|
||||
NATURAL LOOPS
|
||||
|
||||
Found 0 loops in scope []
|
||||
Found 0 loops in scope [sum]
|
||||
NATURAL LOOPS WITH DEPTH
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ sum::a#2 ]
|
||||
[ sum::b#2 ]
|
||||
|
Loading…
Reference in New Issue
Block a user