1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Implemented control flow graph loop analysis.

This commit is contained in:
jespergravgaard 2017-07-27 22:20:50 +02:00
parent 709cc57a1a
commit e7ea5fb4ea
24 changed files with 1311 additions and 190 deletions

View File

@ -110,8 +110,8 @@ public class Compiler {
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
Pass3IdentifyLiveRanges pass3IdentifyLiveRanges = new Pass3IdentifyLiveRanges(program, log);
pass3IdentifyLiveRanges.findLiveRanges();
Pass3LiveRangesAnalysis pass3LiveRangesAnalysis = new Pass3LiveRangesAnalysis(program, log);
pass3LiveRangesAnalysis.findLiveRanges();
log.append("CONTROL FLOW GRAPH - LIVE RANGES");
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
@ -121,13 +121,20 @@ public class Compiler {
Pass2CullEmptyBlocks cullEmptyBlocks = new Pass2CullEmptyBlocks(program, log);
cullEmptyBlocks.optimize();
pass3BlockSequencePlanner.plan();
pass3IdentifyLiveRanges.findLiveRanges();
pass3LiveRangesAnalysis.findLiveRanges();
log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
log.append(program.getGraph().toString(program.getScope()));
pass2AssertSSA(program, log);
Pass3DominatorsAnalysis pass3DominatorsAnalysis = new Pass3DominatorsAnalysis(program, log);
pass3DominatorsAnalysis.findDominators();
log.append("DOMINATORS");
log.append(program.getGraph().getDominators().toString());
Pass3LoopAnalysis pass3LoopAnalysis = new Pass3LoopAnalysis(program, log);
pass3LoopAnalysis.detectLoops();
pass3LoopAnalysis.findLoops();
log.append("NATURAL LOOPS");
log.append(program.getGraph().getLoopSet().toString());
}

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** A named/labelled sequence of SSA statements connected to other basic blocks.
@ -158,4 +159,22 @@ public class ControlFlowBlock {
}
/** Get all successors of the block
*
* @return All successors
*/
@JsonIgnore
public Collection<LabelRef> getSuccessors() {
List<LabelRef> successors = new ArrayList<>();
if(defaultSuccessor!=null) {
successors.add(defaultSuccessor);
}
if(conditionalSuccessor!=null) {
successors.add(conditionalSuccessor);
}
if(callSuccessor!=null) {
successors.add(callSuccessor);
}
return successors;
}
}

View File

@ -13,6 +13,8 @@ public class ControlFlowGraph {
private Map<LabelRef, ControlFlowBlock> blocks;
private LabelRef firstBlockRef;
private List<LabelRef> sequence;
private DominatorsGraph dominators;
private NaturalLoopSet loopSet;
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
this.blocks = blocks;
@ -175,4 +177,20 @@ 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;
}
}

View File

@ -0,0 +1,100 @@
package dk.camelot64.kickc.icl;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/** The Dominators for a specific block.
* <p>
* Definition: Block d dominates block i if all paths from entry to block i includes block d
* <p>
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
* */
public class DominatorsBlock {
/**
* Set containing the labels of all blocks that are dominators of the block.
*/
Set<LabelRef> dominators;
public DominatorsBlock() {
this.dominators = new HashSet<>();
}
/**
* Add a single dominator
*
* @param dominator The dominator to add
*/
public void add(LabelRef dominator) {
dominators.add(dominator);
}
/**
* Adds a bunch of dominators
*
* @param dominators The dominators to add
*/
public void addAll(Collection<LabelRef> dominators) {
for (LabelRef dominator : dominators) {
add(dominator);
}
}
/**
* Modifies this set of dominators to be the intersection between this set and the passed set.
* Effectively removes all labels from this set that is not also present in the passed set.
*
* @param other The dominator set to intersect with
*/
public void intersect(DominatorsBlock other) {
Iterator<LabelRef> iterator = dominators.iterator();
while (iterator.hasNext()) {
LabelRef dominator = iterator.next();
if (!other.contains(dominator)) {
iterator.remove();
}
}
}
/**
* Determines if the dominator set contains a specific block
*
* @param block The block to look for
* @return true if the dominator set contains the block
*/
public boolean contains(LabelRef block) {
return dominators.contains(block);
}
public Set<LabelRef> getDominators() {
return dominators;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DominatorsBlock that = (DominatorsBlock) o;
return dominators != null ? dominators.equals(that.dominators) : that.dominators == null;
}
@Override
public int hashCode() {
return dominators != null ? dominators.hashCode() : 0;
}
@Override
public String toString() {
StringBuilder out = new StringBuilder();
for (LabelRef dominator : dominators) {
out.append(dominator);
out.append(" ");
}
return out.toString();
}
}

View File

@ -0,0 +1,69 @@
package dk.camelot64.kickc.icl;
import java.util.LinkedHashMap;
import java.util.Map;
/** Dominators for a control flow graph.
* <p>
* Definition: Block d dominates block i if all paths from entry to block i includes block d
* <p>
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
*
* */
public class DominatorsGraph {
/**
* Maps block label to the dominators of the block.
*/
Map<LabelRef, DominatorsBlock> blockDominators;
public DominatorsGraph() {
this.blockDominators = new LinkedHashMap<>();
}
/**
* Get the dominators for a specific block.
*
* @param block Label of the block
* @return The block dominators
*/
public DominatorsBlock getDominators(LabelRef block) {
return blockDominators.get(block);
}
/**
* Creates dominators for a specific block
*
* @param block Label of the block
* @return The newly created block dominators
*/
public DominatorsBlock addDominators(LabelRef block) {
DominatorsBlock dominatorsBlock = new DominatorsBlock();
this.blockDominators.put(block, dominatorsBlock);
return dominatorsBlock;
}
/**
* Set the dominators for a specific block
*
* @param block The block
* @param dominators The new dominators
*/
public void setDominators(LabelRef block, DominatorsBlock dominators) {
blockDominators.put(block, dominators);
}
@Override
public String toString() {
StringBuilder out = new StringBuilder();
for (LabelRef block : blockDominators.keySet()) {
DominatorsBlock dominators = getDominators(block);
out.append(block);
out.append(" dominated by ");
out.append(dominators.toString());
out.append("\n");
}
return out.toString();
}
}

View File

@ -66,7 +66,7 @@ public class LiveRange {
private Integer getIndex(Statement statement) {
Integer index = statement.getIndex();
if (index == null) {
throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3IdentifyLiveRanges.generateStatementIndexes).");
throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3LiveRangesAnalysis.generateStatementIndexes).");
}
return index;
}

View File

@ -0,0 +1,129 @@
package dk.camelot64.kickc.icl;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* A single natural loop in a control flow graph.
*/
public class NaturalLoop {
/**
* The head of the natural loop. The block where control enters the loop and the block where the back edge returns to. Dominates all nodes in the loop.
*/
private LabelRef head;
/**
* The tail(s) of the natural loop. The source(s) of the back edge.
* Normally there is only one tail in a loop - but loops with multiple tails occur when the loop body is split. An example
* <code>while(i!=0) { if(i<5) { tail1; } else { tail2; }}</code>
*/
private Set<LabelRef> tails;
/**
* The blocks of the natural loop (including head and tail)
*/
private Set<LabelRef> blocks;
/**
* Create a new natural loop.
* The loop is not filled with all blocks from the start, but only holds the head & tail.
*
* @param head The head block, start of the loop.
* @param tail The tail block, source of the back edge
*/
public NaturalLoop(LabelRef head, LabelRef tail) {
this.head = head;
this.tails = new LinkedHashSet<>();
tails.add(tail);
this.blocks = null;
}
public LabelRef getHead() {
return head;
}
public Set<LabelRef> getTails() {
return tails;
}
public Set<LabelRef> getBlocks() {
return blocks;
}
public void setBlocks(Set<LabelRef> blocks) {
this.blocks = blocks;
}
@Override
public String toString() {
StringBuilder out = new StringBuilder();
out.append("Loop head: ")
.append(head)
.append(" tails: ");
for (LabelRef tail : tails) {
out.append(tail).append(" ");
}
out.append("blocks: ");
if (blocks != null) {
for (LabelRef block : blocks) {
out.append(block.toString()).append(" ");
}
} else {
out.append("null");
}
return out.toString();
}
/**
* Determines if this loop contains another loop - ie. if the other loops blocks are all contained in this loops blocks.
*
* @param other The other loop
* @return true if this loop contains the other loop
*/
public boolean nests(NaturalLoop other) {
for (LabelRef otherBlock : other.getBlocks()) {
if (!blocks.contains(otherBlock)) {
return false;
}
}
return true;
}
/**
* Add more tails to the loop
* @param tails The tails to add
*/
public void addTails(Set<LabelRef> tails) {
this.tails.addAll(tails);
}
/**
* Add more blocks to the loop
* @param blocks The blocks to add
*/
public void addBlocks(Set<LabelRef> blocks) {
this.blocks.addAll(blocks);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NaturalLoop that = (NaturalLoop) o;
if (head != null ? !head.equals(that.head) : that.head != null) return false;
if (tails != null ? !tails.equals(that.tails) : that.tails != null) return false;
return blocks != null ? blocks.equals(that.blocks) : that.blocks == null;
}
@Override
public int hashCode() {
int result = head != null ? head.hashCode() : 0;
result = 31 * result + (tails != null ? tails.hashCode() : 0);
result = 31 * result + (blocks != null ? blocks.hashCode() : 0);
return result;
}
}

View File

@ -0,0 +1,80 @@
package dk.camelot64.kickc.icl;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/** 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
* */
public class NaturalLoopSet {
private List<NaturalLoop> loops;
public NaturalLoopSet() {
this.loops = new ArrayList<>();
}
/**
* Add a loop to the set
*
* @param loop The loop to add
*/
public void addLoop(NaturalLoop loop) {
loops.add(loop);
}
/**
* Get all the loops
* @return The loops
*/
public List<NaturalLoop> getLoops() {
return loops;
}
@Override
public String toString() {
StringBuilder out = new StringBuilder();
for (NaturalLoop loop : loops) {
out.append(loop.toString());
out.append("\n");
}
return out.toString();
}
/**
* Get all blocks that are heads of a loop
* @return The labels for all blocks that are head of a loop.
*/
public Set<LabelRef> getLoopHeads() {
LinkedHashSet<LabelRef> heads = new LinkedHashSet<>();
for (NaturalLoop loop : loops) {
heads.add(loop.getHead());
}
return heads;
}
/**
* Get all loops with a given loop head
* @param loopHead The loop head
* @return Set with all loops that have the given head
*/
public Set<NaturalLoop> getLoopsFromHead(LabelRef loopHead) {
LinkedHashSet<NaturalLoop> result = new LinkedHashSet<>();
for (NaturalLoop loop : loops) {
if(loopHead.equals(loop.getHead())) {
result.add(loop);
}
}
return result;
}
/**
* Remove a loop from the set
* @param loop The loop to remove
*/
public void remove(NaturalLoop loop) {
this.loops.remove(loop);
}
}

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/** A KickC Intermediate Compiler Language (ICL) Program */
public class Program {
/** The main scope. */
private ProgramScope scope;
/** The control flow graph. */

View File

@ -0,0 +1,84 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.icl.*;
import java.util.ArrayList;
import java.util.List;
/** Finds the dominators for the control flow graph. */
public class Pass3DominatorsAnalysis {
private Program program;
private CompileLog log;
public Pass3DominatorsAnalysis(Program program, CompileLog log) {
this.program = program;
this.log = log;
}
public Program getProgram() {
return program;
}
public CompileLog getLog() {
return log;
}
/**
* Analyse the control flow graph to find dominators for all blocks.
* <p>
* Definition: d dom i if all paths from entry to node i include d
* <p>
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
*
* @return The graph dominators
*/
public void findDominators() {
DominatorsGraph dominatorsGraph = new DominatorsGraph();
// Initialize dominators: Dom[first]={first}, Dom[block]={all}
LabelRef firstBlock = program.getGraph().getFirstBlock().getLabel();
DominatorsBlock firstDominators = dominatorsGraph.addDominators(firstBlock);
firstDominators.add(firstBlock);
List<LabelRef> allBlocks = new ArrayList<>();
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
allBlocks.add(block.getLabel());
}
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
if (!block.getLabel().equals(firstBlock)) {
DominatorsBlock dominatorsBlock = dominatorsGraph.addDominators(block.getLabel());
dominatorsBlock.addAll(allBlocks);
}
}
// Iteratively refine dominators until they do not change
// For all nodes:
// Dom[n] = {n} UNION ( INTERSECT Dom[p] for all p that are predecessors of n)
boolean change = false;
do {
change = false;
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
if (!block.getLabel().equals(firstBlock)) {
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
DominatorsBlock newDominators = new DominatorsBlock();
newDominators.addAll(allBlocks);
for (ControlFlowBlock predecessor : predecessors) {
DominatorsBlock predecessorDominators = dominatorsGraph.getDominators(predecessor.getLabel());
newDominators.intersect(predecessorDominators);
}
newDominators.add(block.getLabel());
DominatorsBlock currentDominators = dominatorsGraph.getDominators(block.getLabel());
if (!currentDominators.equals(newDominators)) {
change = true;
dominatorsGraph.setDominators(block.getLabel(), newDominators);
}
}
}
} while (change);
program.getGraph().setDominators(dominatorsGraph);
}
}

View File

@ -11,12 +11,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Pass3IdentifyLiveRanges {
public class Pass3LiveRangesAnalysis {
private final Program program;
private final CompileLog log;
public Pass3IdentifyLiveRanges(Program program, CompileLog log) {
public Pass3LiveRangesAnalysis(Program program, CompileLog log) {
this.program = program;
this.log = log;
}

View File

@ -1,14 +1,15 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.icl.ControlFlowBlock;
import dk.camelot64.kickc.icl.LabelRef;
import dk.camelot64.kickc.icl.Program;
import dk.camelot64.kickc.icl.*;
import java.util.*;
/**
* Finds loops and nested loops in the control flow graph
* Finds loops and nested loops in the control flow graph.
* Uses the dominators of the graph to find loops.
* <p>
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
*/
public class Pass3LoopAnalysis {
@ -28,194 +29,73 @@ public class Pass3LoopAnalysis {
return log;
}
public void detectLoops() {
GraphDominators graphDominators = analyseDominators();
}
/**
* Analyse the control flow graph to find dominators for all blocks.
* <p>
* Definition: d dom i if all paths from entry to node i include d
* Finds loops and nested loops in the control flow graph.
* Uses the dominators of the graph to find loops.
* <p>
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
*
* @return The graph dominators
*/
private GraphDominators analyseDominators() {
GraphDominators graphDominators = new GraphDominators();
public void findLoops() {
DominatorsGraph dominators = program.getGraph().getDominators();
Collection<ControlFlowBlock> blocks = program.getGraph().getAllBlocks();
// Initialize dominators: Dom[first]={first}, Dom[block]={all}
LabelRef firstBlock = program.getGraph().getFirstBlock().getLabel();
BlockDominators firstDominators = graphDominators.addDominators(firstBlock);
firstDominators.add(firstBlock);
List<LabelRef> allBlocks = new ArrayList<>();
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
allBlocks.add(block.getLabel());
}
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
if (!block.getLabel().equals(firstBlock)) {
BlockDominators blockDominators = graphDominators.addDominators(block.getLabel());
blockDominators.addAll(allBlocks);
}
}
// Iteratively refine dominators until they do not change
// For all nodes:
// Dom[n] = {n} UNION ( INTERSECT Dom[p] for all p that are predecessors of n)
boolean change = false;
do {
change = false;
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
if (!block.getLabel().equals(firstBlock)) {
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
BlockDominators newDominators = new BlockDominators();
newDominators.addAll(allBlocks);
for (ControlFlowBlock predecessor : predecessors) {
BlockDominators predecessorDominators = graphDominators.getDominators(predecessor.getLabel());
newDominators.intersect(predecessorDominators);
}
newDominators.add(block.getLabel());
BlockDominators currentDominators = graphDominators.getDominators(block.getLabel());
if (!currentDominators.equals(newDominators)) {
change = true;
graphDominators.setDominators(block.getLabel(), newDominators);
}
}
}
} while (change);
return graphDominators;
}
public static class GraphDominators {
/**
* Maps block label to the dominators of the block.
*/
Map<LabelRef, BlockDominators> blockDominators;
public GraphDominators() {
this.blockDominators = new LinkedHashMap<>();
}
/**
* Get the dominators for a specific block.
*
* @param block Label of the block
* @return The block dominators
*/
public BlockDominators getDominators(LabelRef block) {
return blockDominators.get(block);
}
/**
* Creates dominators for a specific block
*
* @param block Label of the block
* @return The newly created block dominators
*/
public BlockDominators addDominators(LabelRef block) {
BlockDominators blockDominators = new BlockDominators();
this.blockDominators.put(block, blockDominators);
return blockDominators;
}
/**
* Set the dominators for a specific block
*
* @param block The block
* @param dominators The new dominators
*/
public void setDominators(LabelRef block, BlockDominators dominators) {
blockDominators.put(block, dominators);
}
}
/**
* The Dominators for a specific block.
*/
public static class BlockDominators {
/**
* Set containing the labels of all blocks that are dominators of the block.
*/
Set<LabelRef> dominators;
public BlockDominators() {
this.dominators = new HashSet<>();
}
/**
* Add a single dominator
*
* @param dominator The dominator to add
*/
public void add(LabelRef dominator) {
dominators.add(dominator);
}
/**
* Adds a bunch of dominators
*
* @param dominators The dominators to add
*/
public void addAll(Collection<LabelRef> dominators) {
for (LabelRef dominator : dominators) {
add(dominator);
}
}
/**
* Modifies this set of dominators to be the intersection between this set and the passed set.
* Effectively removes all labels from this set that is not also present in the passed set.
*
* @param other The dominator set to intersect with
*/
public void intersect(BlockDominators other) {
Iterator<LabelRef> iterator = dominators.iterator();
while (iterator.hasNext()) {
LabelRef dominator = iterator.next();
if (!other.contains(dominator)) {
iterator.remove();
// Look through graph for natural loop back edges
NaturalLoopSet loopSet = new NaturalLoopSet();
for (ControlFlowBlock block : blocks) {
DominatorsBlock blockDominators = dominators.getDominators(block.getLabel());
for (LabelRef successor : block.getSuccessors()) {
if (blockDominators.contains(successor)) {
// Found a loop back edge!
NaturalLoop loop = new NaturalLoop(successor, block.getLabel());
log.append("Found back edge: "+loop.toString());
loopSet.addLoop(loop);
}
}
}
/**
* Determines if the dominator set contains a specific block
*
* @param block The block to look for
* @return true if the dominator set contains the block
*/
private boolean contains(LabelRef block) {
return dominators.contains(block);
// Find all blocks for each loop
for (NaturalLoop loop : loopSet.getLoops()) {
Deque<LabelRef> todo = new ArrayDeque<>();
Set<LabelRef> loopBlocks = new LinkedHashSet<>();
todo.addAll(loop.getTails());
while(!todo.isEmpty()) {
LabelRef block = todo.pop();
loopBlocks.add(block);
if(block.equals(loop.getHead())) {
continue;
}
ControlFlowBlock controlFlowBlock = program.getGraph().getBlock(block);
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(controlFlowBlock);
for (ControlFlowBlock predecessor : predecessors) {
if(!loopBlocks.contains(predecessor.getLabel()) && !todo.contains(predecessor.getLabel())) {
todo.add(predecessor.getLabel());
}
}
}
loop.setBlocks(loopBlocks);
log.append("Populated: "+loop.toString());
}
public Set<LabelRef> getDominators() {
return dominators;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BlockDominators that = (BlockDominators) o;
return dominators != null ? dominators.equals(that.dominators) : that.dominators == null;
}
@Override
public int hashCode() {
return dominators != null ? dominators.hashCode() : 0;
// Coalesce loops that are neither nested, nor disjoint
for (NaturalLoop loop : loopSet.getLoops()) {
Set<NaturalLoop> headLoops = loopSet.getLoopsFromHead(loop.getHead());
for (NaturalLoop other : headLoops) {
if(other.equals(loop)) {
// Same loop - do not process
continue;
} else if(loop.nests(other) || other.nests(loop)) {
// One of the loops nest the other loop
continue;
} else {
// Two non-nested loops with a shared head - collect them to one loop
loop.addTails(other.getTails());
loop.addBlocks(other.getBlocks());
loopSet.remove(other);
log.append("Coalesced: "+loop.toString()) ;
}
}
}
program.getGraph().setLoops(loopSet);
}

View File

@ -48,6 +48,11 @@ public class TestCompilationOutput extends TestCase {
tester.testFile("summin");
}
public void testLoopSplit() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopsplit");
}
private void testFile(String fileName) throws IOException, URISyntaxException {
String inputPath = testPath + fileName + ".kc";
System.out.println("Testing output for " + inputPath);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
byte i=100;
byte s=0;
while(--i>0) {
if(i>50) {
s++;
} else {
s--;
}
}

View File

@ -985,6 +985,18 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
[10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ]
to:@3
DOMINATORS
@BEGIN dominated by @BEGIN
@1 dominated by @1 @BEGIN
@3 dominated by @1 @BEGIN @3
@END dominated by @1 @BEGIN @3 @END
@2 dominated by @1 @BEGIN @2
Found back edge: Loop head: @1 tails: @3 blocks: null
Populated: Loop head: @1 tails: @3 blocks: @3 @1 @2
NATURAL LOOPS
Loop head: @1 tails: @3 blocks: @3 @1 @2
Initial phi equivalence classes
[ cursor#3 cursor#5 cursor#1 cursor#2 ]
[ x#2 x#1 ]

View File

@ -3733,6 +3733,64 @@ prepare::@return: from prepare::@1
[45] return [ ]
to:@RETURN
DOMINATORS
@BEGIN dominated by @BEGIN
@END dominated by @BEGIN @END
main dominated by @BEGIN main
main::@3 dominated by @BEGIN main::@3 main
main::@4 dominated by @BEGIN main::@4 main::@3 main
main::@6 dominated by @BEGIN main::@4 main::@3 main::@6 main
main::@7 dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7
main::@10 dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 main::@10
main::@11 dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 main::@10 main::@11
main::@return dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 main::@return main::@10 main::@11
plot dominated by @BEGIN main::@4 main::@3 main::@6 plot main main::@7 main::@10
plot::@1 dominated by @BEGIN main::@4 main::@3 main::@6 main plot main::@7 plot::@1 main::@10
plot::@2 dominated by @BEGIN main::@4 main::@3 main::@6 main plot main::@7 plot::@2 plot::@1 main::@10
plot::@3 dominated by @BEGIN main::@4 main::@3 main::@6 main plot main::@7 plot::@2 plot::@1 main::@10 plot::@3
plot::@return dominated by @BEGIN main::@4 main::@3 plot::@return main::@6 main plot main::@7 plot::@2 plot::@1 main::@10 plot::@3
flip dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 flip
flip::@1 dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 flip::@1 flip
flip::@2 dominated by @BEGIN main::@4 main::@3 main::@6 main main::@7 flip::@1 flip::@2 flip
flip::@4 dominated by flip::@4 @BEGIN main::@4 main::@3 main::@6 main main::@7 flip::@1 flip::@2 flip
flip::@3 dominated by flip::@4 flip::@3 @BEGIN main::@4 main::@3 main::@6 main main::@7 flip::@1 flip::@2 flip
flip::@return dominated by flip::@4 flip::@3 @BEGIN main::@4 main::@3 main::@6 main main::@7 flip::@return flip::@1 flip::@2 flip
prepare dominated by @BEGIN prepare main
prepare::@1 dominated by @BEGIN prepare main prepare::@1
prepare::@return dominated by @BEGIN prepare::@return prepare main prepare::@1
Found back edge: Loop head: main::@3 tails: main::@3 blocks: null
Found back edge: Loop head: main::@4 tails: main::@4 blocks: null
Found back edge: Loop head: main::@3 tails: main::@6 blocks: null
Found back edge: Loop head: main::@3 tails: main::@11 blocks: null
Found back edge: Loop head: plot::@2 tails: plot::@2 blocks: null
Found back edge: Loop head: plot::@1 tails: plot::@3 blocks: null
Found back edge: Loop head: flip::@2 tails: flip::@2 blocks: null
Found back edge: Loop head: flip::@1 tails: flip::@4 blocks: null
Found back edge: Loop head: flip::@3 tails: flip::@3 blocks: null
Found back edge: Loop head: prepare::@1 tails: prepare::@1 blocks: null
Populated: Loop head: main::@3 tails: main::@3 blocks: main::@3
Populated: Loop head: main::@4 tails: main::@4 blocks: main::@4
Populated: Loop head: main::@3 tails: main::@6 blocks: main::@6 main::@4 main::@3
Populated: Loop head: main::@3 tails: main::@11 blocks: main::@11 main::@10 main::@7 main::@6 main::@4 main::@3
Populated: Loop head: plot::@2 tails: plot::@2 blocks: plot::@2
Populated: Loop head: plot::@1 tails: plot::@3 blocks: plot::@3 plot::@2 plot::@1
Populated: Loop head: flip::@2 tails: flip::@2 blocks: flip::@2
Populated: Loop head: flip::@1 tails: flip::@4 blocks: flip::@4 flip::@2 flip::@1
Populated: Loop head: flip::@3 tails: flip::@3 blocks: flip::@3
Populated: Loop head: prepare::@1 tails: prepare::@1 blocks: prepare::@1
NATURAL LOOPS
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
Loop head: plot::@2 tails: plot::@2 blocks: plot::@2
Loop head: plot::@1 tails: plot::@3 blocks: plot::@3 plot::@2 plot::@1
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
Loop head: prepare::@1 tails: prepare::@1 blocks: prepare::@1
Initial phi equivalence classes
[ main::c#2 main::c#1 ]
[ plot::line#2 plot::line#1 ]

View File

@ -341,6 +341,18 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
[5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ]
to:@3
DOMINATORS
@BEGIN dominated by @BEGIN
@1 dominated by @1 @BEGIN
@3 dominated by @1 @BEGIN @3
@END dominated by @1 @BEGIN @3 @END
@2 dominated by @1 @BEGIN @2
Found back edge: Loop head: @1 tails: @3 blocks: null
Populated: Loop head: @1 tails: @3 blocks: @3 @1 @2
NATURAL LOOPS
Loop head: @1 tails: @3 blocks: @3 @1 @2
Initial phi equivalence classes
[ i#2 i#1 ]
[ s#2 s#4 s#1 ]

View File

@ -0,0 +1,24 @@
BBEGIN:
B1_from_BBEGIN:
lda #0
sta 3
lda #100
sta 2
B1:
dec 2
lda 2
BEND:
B2:
lda 2
cmp #50
beq !+
bcs B4
!:
B5:
dec 3
B1_from_B5:
jmp B1
B4:
inc 3
B1_from_B4:
jmp B1

View File

@ -0,0 +1,18 @@
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
[0] (byte) s#3 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) 0 ) [ i#2 s#3 ]
[0] (byte) i#2 ← phi( @4/(byte) i#1 @5/(byte) i#1 @BEGIN/(byte) 100 ) [ i#2 s#3 ]
[1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ]
[2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ]
to:@END
@END: from @1
@2: from @1
[3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ]
to:@5
@5: from @2
[4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ]
to:@1
@4: from @2
[5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ]
to:@1

View File

@ -0,0 +1,564 @@
byte i=100;
byte s=0;
while(--i>0) {
if(i>50) {
s++;
} else {
s--;
}
}
Adding pre/post-modifier (byte) i ← -- (byte) i
Adding pre/post-modifier (byte) s ← ++ (byte) s
Adding pre/post-modifier (byte) s ← -- (byte) s
PROGRAM
(byte) i ← (byte) 100
(byte) s ← (byte) 0
@1:
(byte) i ← -- (byte) i
(boolean~) $0 ← (byte) i > (byte) 0
if((boolean~) $0) goto @2
goto @3
@2:
(boolean~) $1 ← (byte) i > (byte) 50
if((boolean~) $1) goto @4
goto @5
@4:
(byte) s ← ++ (byte) s
goto @6
@5:
(byte) s ← -- (byte) s
@6:
goto @1
@3:
SYMBOLS
(boolean~) $0
(boolean~) $1
(label) @1
(label) @2
(label) @3
(label) @4
(label) @5
(label) @6
(byte) i
(byte) s
INITIAL CONTROL FLOW GRAPH
@BEGIN: from
(byte) i ← (byte) 100
(byte) s ← (byte) 0
to:@1
@1: from @6 @BEGIN
(byte) i ← -- (byte) i
(boolean~) $0 ← (byte) i > (byte) 0
if((boolean~) $0) goto @2
to:@7
@2: from @1 @8
(boolean~) $1 ← (byte) i > (byte) 50
if((boolean~) $1) goto @4
to:@9
@7: from @1
to:@3
@3: from @12 @7
to:@END
@8: from
to:@2
@4: from @10 @2
(byte) s ← ++ (byte) s
to:@6
@9: from @2
to:@5
@5: from @11 @9
(byte) s ← -- (byte) s
to:@6
@10: from
to:@4
@6: from @4 @5
to:@1
@11: from
to:@5
@12: from
to:@3
@END: from @3
Removing empty block @7
Removing empty block @3
Removing empty block @8
Removing empty block @9
Removing empty block @10
Removing empty block @6
Removing empty block @11
Removing empty block @12
CONTROL FLOW GRAPH
@BEGIN: from
(byte) i ← (byte) 100
(byte) s ← (byte) 0
to:@1
@1: from @4 @5 @BEGIN
(byte) i ← -- (byte) i
(boolean~) $0 ← (byte) i > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(boolean~) $1 ← (byte) i > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) s ← ++ (byte) s
to:@1
@5: from @2
(byte) s ← -- (byte) s
to:@1
@END: from @1
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
@BEGIN: from
(byte) i ← (byte) 100
(byte) s ← (byte) 0
to:@1
@1: from @4 @5 @BEGIN
(byte) i ← -- (byte) i
(boolean~) $0 ← (byte) i > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(boolean~) $1 ← (byte) i > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) s ← ++ (byte) s
to:@1
@5: from @2
(byte) s ← -- (byte) s
to:@1
@END: from @1
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@BEGIN: from
(byte) i#0 ← (byte) 100
(byte) s#0 ← (byte) 0
to:@1
@1: from @4 @5 @BEGIN
(byte) s#6 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) s#0 )
(byte) i#2 ← phi( @4/(byte) i#4 @5/(byte) i#5 @BEGIN/(byte) i#0 )
(byte) i#1 ← -- (byte) i#2
(boolean~) $0 ← (byte) i#1 > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(byte) s#5 ← phi( @1/(byte) s#6 )
(byte) i#3 ← phi( @1/(byte) i#1 )
(boolean~) $1 ← (byte) i#3 > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) i#4 ← phi( @2/(byte) i#3 )
(byte) s#3 ← phi( @2/(byte) s#5 )
(byte) s#1 ← ++ (byte) s#3
to:@1
@5: from @2
(byte) i#5 ← phi( @2/(byte) i#3 )
(byte) s#4 ← phi( @2/(byte) s#5 )
(byte) s#2 ← -- (byte) s#4
to:@1
@END: from @1
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
@BEGIN: from
(byte) i#0 ← (byte) 100
(byte) s#0 ← (byte) 0
to:@1
@1: from @4 @5 @BEGIN
(byte) s#6 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) s#0 )
(byte) i#2 ← phi( @4/(byte) i#4 @5/(byte) i#5 @BEGIN/(byte) i#0 )
(byte) i#1 ← -- (byte) i#2
(boolean~) $0 ← (byte) i#1 > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(byte) s#5 ← phi( @1/(byte) s#6 )
(byte) i#3 ← phi( @1/(byte) i#1 )
(boolean~) $1 ← (byte) i#3 > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) i#4 ← phi( @2/(byte) i#3 )
(byte) s#3 ← phi( @2/(byte) s#5 )
(byte) s#1 ← ++ (byte) s#3
to:@1
@5: from @2
(byte) i#5 ← phi( @2/(byte) i#3 )
(byte) s#4 ← phi( @2/(byte) s#5 )
(byte) s#2 ← -- (byte) s#4
to:@1
@END: from @1
Constant (byte) i#0 (byte) 100
Constant (byte) s#0 (byte) 0
Succesful SSA optimization Pass2ConstantPropagation
CONTROL FLOW GRAPH
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
(byte) s#6 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) 0 )
(byte) i#2 ← phi( @4/(byte) i#4 @5/(byte) i#5 @BEGIN/(byte) 100 )
(byte) i#1 ← -- (byte) i#2
(boolean~) $0 ← (byte) i#1 > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(byte) s#5 ← phi( @1/(byte) s#6 )
(byte) i#3 ← phi( @1/(byte) i#1 )
(boolean~) $1 ← (byte) i#3 > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) i#4 ← phi( @2/(byte) i#3 )
(byte) s#3 ← phi( @2/(byte) s#5 )
(byte) s#1 ← ++ (byte) s#3
to:@1
@5: from @2
(byte) i#5 ← phi( @2/(byte) i#3 )
(byte) s#4 ← phi( @2/(byte) s#5 )
(byte) s#2 ← -- (byte) s#4
to:@1
@END: from @1
Alias (byte) i#1 = (byte) i#3 (byte) i#4 (byte) i#5
Alias (byte) s#3 = (byte) s#5 (byte) s#6 (byte) s#4
Succesful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
(byte) s#3 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) 0 )
(byte) i#2 ← phi( @4/(byte) i#1 @5/(byte) i#1 @BEGIN/(byte) 100 )
(byte) i#1 ← -- (byte) i#2
(boolean~) $0 ← (byte) i#1 > (byte) 0
if((boolean~) $0) goto @2
to:@END
@2: from @1
(boolean~) $1 ← (byte) i#1 > (byte) 50
if((boolean~) $1) goto @4
to:@5
@4: from @2
(byte) s#1 ← ++ (byte) s#3
to:@1
@5: from @2
(byte) s#2 ← -- (byte) s#3
to:@1
@END: from @1
Simple Condition (boolean~) $0 if((byte) i#1>(byte) 0) goto @2
Simple Condition (boolean~) $1 if((byte) i#1>(byte) 50) goto @4
Succesful SSA optimization Pass2ConditionalJumpSimplification
CONTROL FLOW GRAPH
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
(byte) s#3 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) 0 )
(byte) i#2 ← phi( @4/(byte) i#1 @5/(byte) i#1 @BEGIN/(byte) 100 )
(byte) i#1 ← -- (byte) i#2
if((byte) i#1>(byte) 0) goto @2
to:@END
@2: from @1
if((byte) i#1>(byte) 50) goto @4
to:@5
@4: from @2
(byte) s#1 ← ++ (byte) s#3
to:@1
@5: from @2
(byte) s#2 ← -- (byte) s#3
to:@1
@END: from @1
Block Sequence Planned @BEGIN @1 @END @2 @5 @4
Block Sequence Planned @BEGIN @1 @END @2 @5 @4
CONTROL FLOW GRAPH - PHI LIFTED
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
(byte) s#3 ← phi( @4/(byte~) s#7 @5/(byte~) s#8 @BEGIN/(byte) 0 )
(byte) i#2 ← phi( @4/(byte~) i#6 @5/(byte~) i#7 @BEGIN/(byte) 100 )
(byte) i#1 ← -- (byte) i#2
if((byte) i#1>(byte) 0) goto @2
to:@END
@END: from @1
@2: from @1
if((byte) i#1>(byte) 50) goto @4
to:@5
@5: from @2
(byte) s#2 ← -- (byte) s#3
(byte~) i#7 ← (byte) i#1
(byte~) s#8 ← (byte) s#2
to:@1
@4: from @2
(byte) s#1 ← ++ (byte) s#3
(byte~) i#6 ← (byte) i#1
(byte~) s#7 ← (byte) s#1
to:@1
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - LIVE RANGES
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
[0] (byte) s#3 ← phi( @4/(byte~) s#7 @5/(byte~) s#8 @BEGIN/(byte) 0 ) [ i#2 s#3 ]
[0] (byte) i#2 ← phi( @4/(byte~) i#6 @5/(byte~) i#7 @BEGIN/(byte) 100 ) [ i#2 s#3 ]
[1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ]
[2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ]
to:@END
@END: from @1
@2: from @1
[3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ]
to:@5
@5: from @2
[4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ]
[5] (byte~) i#7 ← (byte) i#1 [ i#7 s#2 ]
[6] (byte~) s#8 ← (byte) s#2 [ i#7 s#8 ]
to:@1
@4: from @2
[7] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ]
[8] (byte~) i#6 ← (byte) i#1 [ i#6 s#1 ]
[9] (byte~) s#7 ← (byte) s#1 [ i#6 s#7 ]
to:@1
Created 2 initial phi equivalence classes
Coalesced [5] i#7 ← i#1
Coalesced [6] s#8 ← s#2
Coalesced (already) [8] i#6 ← i#1
Coalesced [9] s#7 ← s#1
Coalesced down to 2 phi equivalence classes
Block Sequence Planned @BEGIN @1 @END @2 @5 @4
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
CONTROL FLOW GRAPH - PHI MEM COALESCED
@BEGIN: from
to:@1
@1: from @4 @5 @BEGIN
[0] (byte) s#3 ← phi( @4/(byte) s#1 @5/(byte) s#2 @BEGIN/(byte) 0 ) [ i#2 s#3 ]
[0] (byte) i#2 ← phi( @4/(byte) i#1 @5/(byte) i#1 @BEGIN/(byte) 100 ) [ i#2 s#3 ]
[1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ]
[2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ]
to:@END
@END: from @1
@2: from @1
[3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ]
to:@5
@5: from @2
[4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ]
to:@1
@4: from @2
[5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ]
to:@1
DOMINATORS
@BEGIN dominated by @BEGIN
@1 dominated by @1 @BEGIN
@END dominated by @1 @BEGIN @END
@2 dominated by @1 @BEGIN @2
@5 dominated by @1 @BEGIN @2 @5
@4 dominated by @1 @BEGIN @2 @4
Found back edge: Loop head: @1 tails: @5 blocks: null
Found back edge: Loop head: @1 tails: @4 blocks: null
Populated: Loop head: @1 tails: @5 blocks: @5 @2 @1
Populated: Loop head: @1 tails: @4 blocks: @4 @2 @1
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
Initial phi equivalence classes
[ i#2 i#1 ]
[ s#3 s#1 s#2 ]
Copy Coalesced equivalence classes
[ i#2 i#1 ]
[ s#3 s#1 s#2 ]
Complete equivalence classes
[ i#2 i#1 ]
[ s#3 s#1 s#2 ]
Allocated zp byte:2 to [ i#2 i#1 ]
Allocated zp byte:3 to [ s#3 s#1 s#2 ]
INITIAL ASM
BBEGIN:
B1_from_BBEGIN:
// (byte) s#3 = (byte) 0 // zpby1=coby1
lda #0
sta 3
// (byte) i#2 = (byte) 100 // zpby1=coby1
lda #100
sta 2
jmp B1
B1:
// [1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ] // zpby1=_dec_zpby1
dec 2
// [2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ] // zpby1_gt_0_then_la1
lda 2
bne B2
jmp BEND
BEND:
B2:
// [3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ] // zpby1_gt_coby1_then_la1
lda 2
cmp #50
beq !+
bcs B4
!:
jmp B5
B5:
// [4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ] // zpby1=_dec_zpby1
dec 3
B1_from_B5:
// (byte) s#3 = (byte) s#2 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
B4:
// [5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ] // zpby1=_inc_zpby1
inc 3
B1_from_B4:
// (byte) s#3 = (byte) s#1 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
Removing instruction jmp B1
Removing instruction jmp BEND
Removing instruction jmp B5
Succesful ASM optimization Pass5NextJumpElimination
ASSEMBLER
BBEGIN:
B1_from_BBEGIN:
// (byte) s#3 = (byte) 0 // zpby1=coby1
lda #0
sta 3
// (byte) i#2 = (byte) 100 // zpby1=coby1
lda #100
sta 2
B1:
// [1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ] // zpby1=_dec_zpby1
dec 2
// [2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ] // zpby1_gt_0_then_la1
lda 2
bne B2
BEND:
B2:
// [3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ] // zpby1_gt_coby1_then_la1
lda 2
cmp #50
beq !+
bcs B4
!:
B5:
// [4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ] // zpby1=_dec_zpby1
dec 3
B1_from_B5:
// (byte) s#3 = (byte) s#2 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
B4:
// [5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ] // zpby1=_inc_zpby1
inc 3
B1_from_B4:
// (byte) s#3 = (byte) s#1 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
Removing instruction bne B2
Succesful ASM optimization Pass5NextJumpElimination
ASSEMBLER
BBEGIN:
B1_from_BBEGIN:
// (byte) s#3 = (byte) 0 // zpby1=coby1
lda #0
sta 3
// (byte) i#2 = (byte) 100 // zpby1=coby1
lda #100
sta 2
B1:
// [1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ] // zpby1=_dec_zpby1
dec 2
// [2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ] // zpby1_gt_0_then_la1
lda 2
BEND:
B2:
// [3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ] // zpby1_gt_coby1_then_la1
lda 2
cmp #50
beq !+
bcs B4
!:
B5:
// [4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ] // zpby1=_dec_zpby1
dec 3
B1_from_B5:
// (byte) s#3 = (byte) s#2 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
B4:
// [5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ] // zpby1=_inc_zpby1
inc 3
B1_from_B4:
// (byte) s#3 = (byte) s#1 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @4
(label) @5
(label) @BEGIN
(label) @END
(byte) i
(byte) i#1 zp byte:2
(byte) i#2 zp byte:2
(byte) s
(byte) s#1 zp byte:3
(byte) s#2 zp byte:3
(byte) s#3 zp byte:3
FINAL CODE
BBEGIN:
B1_from_BBEGIN:
// (byte) s#3 = (byte) 0 // zpby1=coby1
lda #0
sta 3
// (byte) i#2 = (byte) 100 // zpby1=coby1
lda #100
sta 2
B1:
// [1] (byte) i#1 ← -- (byte) i#2 [ i#1 s#3 ] // zpby1=_dec_zpby1
dec 2
// [2] if((byte) i#1>(byte) 0) goto @2 [ i#1 s#3 ] // zpby1_gt_0_then_la1
lda 2
BEND:
B2:
// [3] if((byte) i#1>(byte) 50) goto @4 [ i#1 s#3 ] // zpby1_gt_coby1_then_la1
lda 2
cmp #50
beq !+
bcs B4
!:
B5:
// [4] (byte) s#2 ← -- (byte) s#3 [ i#1 s#2 ] // zpby1=_dec_zpby1
dec 3
B1_from_B5:
// (byte) s#3 = (byte) s#2 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1
B4:
// [5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ] // zpby1=_inc_zpby1
inc 3
B1_from_B4:
// (byte) s#3 = (byte) s#1 // register copy
// (byte) i#2 = (byte) i#1 // register copy
jmp B1

View File

@ -0,0 +1,13 @@
(label) @1
(label) @2
(label) @4
(label) @5
(label) @BEGIN
(label) @END
(byte) i
(byte) i#1 zp byte:2
(byte) i#2 zp byte:2
(byte) s
(byte) s#1 zp byte:3
(byte) s#2 zp byte:3
(byte) s#3 zp byte:3

View File

@ -263,6 +263,16 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
to:@END
@END: from @1
DOMINATORS
@BEGIN dominated by @BEGIN
@1 dominated by @1 @BEGIN
@END dominated by @1 @BEGIN @END
Found back edge: Loop head: @1 tails: @1 blocks: null
Populated: Loop head: @1 tails: @1 blocks: @1
NATURAL LOOPS
Loop head: @1 tails: @1 blocks: @1
Initial phi equivalence classes
[ i#2 i#1 ]
Copy Coalesced equivalence classes

View File

@ -298,6 +298,15 @@ sum::@return: from sum
[4] return (byte) s1#0 [ ]
to:@RETURN
DOMINATORS
@BEGIN dominated by @BEGIN
@2 dominated by @BEGIN @2
@END dominated by @BEGIN @2 @END
sum dominated by @BEGIN sum
sum::@return dominated by @BEGIN sum::@return sum
NATURAL LOOPS
Initial phi equivalence classes
[ sum::a#2 ]
[ sum::b#2 ]