1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-22 21:29:50 +00:00

Implemented loop depth analysis pass.

This commit is contained in:
jespergravgaard 2017-07-28 02:55:19 +02:00
parent d1a13402fe
commit 007a5d34b4
12 changed files with 250 additions and 37 deletions

View File

@ -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.
*/

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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

View File

@ -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 ]

View File

@ -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 ]

View File

@ -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 ]

View File

@ -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 ]

View File

@ -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

View File

@ -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 ]