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

Working loop unrolling! There are probably still a lot of non-working cases - and the lack of loop unroll limit will definitely cause infinite loops.

This commit is contained in:
jespergravgaard 2018-08-22 01:42:00 +02:00
parent bbeb37ea61
commit be18a84d98
35 changed files with 6887 additions and 195 deletions

View File

@ -30,12 +30,17 @@ public class CompileLog {
/**
* Should SSA optimization be verbose.
*/
private boolean verboseSSAOptimize = true;
private boolean verboseSSAOptimize = false;
/**
* Should SSA optimization be verbose.
*/
private boolean verboseLoopUnroll = false;
/**
* Should the log be output to System.out while being built
*/
private boolean sysOut = true;
private boolean sysOut = false;
public CompileLog() {
this.log = new StringBuilder();
@ -93,6 +98,10 @@ public class CompileLog {
this.verboseSSAOptimize = verboseSSAOptimize;
}
public boolean isVerboseLoopUnroll() {
return verboseLoopUnroll;
}
public boolean isSysOut() {
return sysOut;
}

View File

@ -1,6 +1,8 @@
package dk.camelot64.kickc;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.StatementSequence;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Variable;
@ -37,7 +39,7 @@ public class Compiler {
}
final CharStream fileStream = CharStreams.fromPath(file.toPath());
imported.add(file.getAbsolutePath());
program.getLog().append("PARSING " + file.getPath().replace("\\","/"));
program.getLog().append("PARSING " + file.getPath().replace("\\", "/"));
program.getLog().append(fileStream.toString());
KickCLexer lexer = new KickCLexer(fileStream);
KickCParser parser = new KickCParser(new CommonTokenStream(lexer));
@ -93,7 +95,7 @@ public class Compiler {
program.setStatementSequence(sequence);
pass1GenerateSSA();
pass2OptimizeSSA();
pass2Optimize();
pass2UnrollLoops();
pass2InlineConstants();
pass3Analysis();
@ -184,7 +186,7 @@ public class Compiler {
}
}
private void pass2OptimizeSSA() {
private void pass2Optimize() {
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(program));
optimizations.add(new Pass2UnaryNotSimplification(program));
@ -203,19 +205,10 @@ public class Compiler {
optimizations.add(new Pass2NopCastElimination(program));
optimizations.add(new Pass2EliminateUnusedBlocks(program));
optimizations.add(new Pass2RangeResolving(program));
pass2OptimizeSSA(optimizations);
pass2Execute(optimizations);
}
private void pass2UnrollLoops() {
getLog().append("CONTROL FLOW GRAPH BEFORE UNROLLING");
getLog().append(program.getGraph().toString(program));
new Pass2DominatorsAnalysis(program).step();
getLog().append("NATURAL LOOPS");
new Pass2LoopAnalysis(program).step();
getLog().append(program.getLoopSet().toString());
List<Pass2SsaOptimization> loopUnrolling = new ArrayList<>();
loopUnrolling.add(new PassNStatementIndices(program));
loopUnrolling.add(new PassNVariableReferenceInfos(program));
@ -224,7 +217,21 @@ public class Compiler {
loopUnrolling.add(new Pass2LoopAnalysis(program));
loopUnrolling.add(new Pass2LoopUnrollPhiPrepare(program));
loopUnrolling.add(new Pass2LoopUnroll(program));
pass2OptimizeSSA(loopUnrolling);
boolean unrolled;
do {
unrolled = pass2ExecuteOnce(loopUnrolling);
if(unrolled) {
if(getLog().isVerboseLoopUnroll()) {
getLog().append("UNROLLED CONTROL FLOW GRAPH");
getLog().append(program.getGraph().toString(program));
}
pass2Optimize();
new Pass3BlockSequencePlanner(program).plan();
}
} while(unrolled);
}
private void pass2InlineConstants() {
@ -235,10 +242,15 @@ public class Compiler {
constantOptimizations.add(new Pass2ConstantIdentification(program));
constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
constantOptimizations.add(new Pass2ConstantIfs(program));
pass2OptimizeSSA(constantOptimizations);
pass2Execute(constantOptimizations);
}
private void pass2OptimizeSSA(List<Pass2SsaOptimization> optimizations) {
/**
* Execute optimization steps repeatedly until none of them performs an optimization anymore
*
* @param optimizations The optimizations to repeat
*/
private void pass2Execute(List<Pass2SsaOptimization> optimizations) {
getLog().append("OPTIMIZING CONTROL FLOW GRAPH");
boolean ssaOptimized = true;
while(ssaOptimized) {
@ -261,6 +273,29 @@ public class Compiler {
}
}
/**
* Repeat a set of optimizations steps once each.
*
* @param optimizations The optimizations
* @return true if any step performed an optimization
*/
private boolean pass2ExecuteOnce(List<Pass2SsaOptimization> optimizations) {
boolean ssaOptimized = false;
for(Pass2SsaOptimization optimization : optimizations) {
pass2AssertSSA();
boolean stepOptimized = optimization.step();
if(stepOptimized) {
getLog().append("Successful SSA optimization " + optimization.getClass().getSimpleName() + "");
ssaOptimized = true;
if(getLog().isVerboseSSAOptimize()) {
getLog().append("CONTROL FLOW GRAPH");
getLog().append(program.getGraph().toString(program));
}
}
}
return ssaOptimized;
}
private void pass3Analysis() {
new Pass3AssertRValues(program).check();
@ -321,7 +356,10 @@ public class Compiler {
getLog().append(program.getDominators().toString());
getLog().append("NATURAL LOOPS");
boolean wasVerbose = getLog().isVerboseSSAOptimize();
getLog().setVerboseSSAOptimize(true);
new Pass2LoopAnalysis(program).step();
getLog().setVerboseSSAOptimize(wasVerbose);
getLog().append(program.getLoopSet().toString());
getLog().append("NATURAL LOOPS WITH DEPTH");

View File

@ -18,8 +18,12 @@ public interface Statement {
void setIndex(Integer idx);
/**
* Get the source for the statement*
* Get the source for the statement
*/
StatementSource getSource();
/**
* Set the source for the statement
*/
void setSource(StatementSource source);
}

View File

@ -26,6 +26,11 @@ public abstract class StatementBase implements Statement {
return source;
}
@Override
public void setSource(StatementSource source) {
this.source = source;
}
@Override
public Integer getIndex() {
return index;

View File

@ -263,7 +263,7 @@ public abstract class Scope implements Symbol {
}
public Label getLabel(String name) {
return (Label) symbols.get(name);
return (Label) getSymbol(name);
}
public Label getLabel(LabelRef labelRef) {

View File

@ -41,6 +41,14 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
Variable variable = getScope().getVariable((VariableRef) lValue);
variable.getScope().remove(variable);
}
} else if(stmt instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) stmt).getPhiVariables()) {
VariableRef phiVar = phiVariable.getVariable();
getLog().append("Eliminating variable " + phiVar.toString(getProgram()) + " from unused block " + block.getLabel());
Variable variable = getScope().getVariable(phiVar);
variable.getScope().remove(variable);
}
}
}
}

View File

@ -99,7 +99,9 @@ public class Pass2LoopAnalysis extends Pass2SsaOptimization {
loop.addTails(other.getTails());
loop.addBlocks(other.getBlocks());
loopSet.remove(other);
getLog().append("Coalesced: " + loop.toString());
if(getLog().isVerboseSSAOptimize()) {
getLog().append("Coalesced: " + loop.toString());
}
return true;
}
}

View File

@ -1,15 +1,14 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.VariableVersion;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.values.*;
import java.util.*;
@ -23,80 +22,295 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
@Override
public boolean step() {
// Look for loops to unroll
NaturalLoopSet loops = getProgram().getLoopSet();
List<NaturalLoop> unrollLoopCandidates = findUnrollLoopCandidates(getProgram(), loops);
List<NaturalLoop> unrollLoops = findUnrollLoops(getProgram());
// Is there any unrolling to do?
if(unrollLoopCandidates.isEmpty()) {
if(unrollLoops.isEmpty()) {
return false;
}
// Choose the candidate loop with the fewest blocks (and if several have the same number of blocks the first one encountered)
NaturalLoop unrollLoop = chooseUnrollLoop(unrollLoopCandidates);
NaturalLoop unrollLoop = chooseUnrollLoop(unrollLoops);
getLog().append("Unrolling loop " + unrollLoop);
// Unroll the first iteration of the loop
// 0. Unroll Symbols
// - Create new versions of all symbols assigned inside the loop
Map<VariableRef, VariableRef> definedToNewVar = new LinkedHashMap<>();
for(VariableRef definedVarRef : getVarsDefinedInLoop(getProgram(), unrollLoop)) {
Variable definedVar = getScope().getVariable(definedVarRef);
Variable newVar;
if(definedVarRef.isIntermediate()) {
newVar = definedVar.getScope().addVariableIntermediate();
} else if(definedVarRef.isVersion()) {
newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
} else {
throw new RuntimeException("Error! Variable is not versioned or intermediate " + definedVar.toString(getProgram()));
}
definedToNewVar.put(definedVarRef, newVar.getRef());
getLog().append("Defined in loop: " + definedVarRef.getFullName() + " -> " + newVar.getRef().getFullName());
}
Map<VariableRef, VariableRef> definedToNewVar = copyVarsDefinedInLoop(unrollLoop);
// - Create new labels for all blocks in the loop
Map<LabelRef, LabelRef> blockToNewBlock = copyBlocksInLoop(unrollLoop);
// 1. Copy all loop blocks to create the "rest of the loop" and modifying the existing loop to only be the first iteration)
// - Unroll Statements (copy all statements, replace symbols properly (with the new versions / the versions assigned in the existing loop)
// - Includes unrolling PHI-statements properly
// - Unroll Successors (loop-exit successors should point to the same exit, loop-internal successors should point to the new loop-internal block)
for(ControlFlowBlock block : unrollLoop.getBlocks(getGraph())) {
// Find the serial number
int unrollSerial = 1;
String unrollLabelName = block.getLabel() + "_" + unrollSerial;
while(getScope().getLabel(unrollLabelName) != null) {
unrollSerial++;
}
// Create a label
Label unrollLabel = getScope().getScope(block.getScope()).addLabel(unrollLabelName);
// Create the new block
ControlFlowBlock unrollBlock = new ControlFlowBlock(unrollLabel.getRef(), block.getScope());
getProgram().getGraph().addBlock(unrollBlock);
LabelRef newBlockLabel = unrollLabel(block.getLabel(), blockToNewBlock);
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel, block.getScope());
getProgram().getGraph().addBlock(newBlock);
for(Statement statement : block.getStatements()) {
Statement newStatement = unrollStatement(statement, unrollLoop, blockToNewBlock, definedToNewVar);
newBlock.addStatement(newStatement);
if(newStatement instanceof StatementConditionalJump) {
newBlock.setConditionalSuccessor(((StatementConditionalJump) newStatement).getDestination());
}
}
newBlock.setDefaultSuccessor(unrollLabel(block.getDefaultSuccessor(), blockToNewBlock));
}
// Patch the "old loop" to only contain the first iteration
for(ControlFlowBlock block : unrollLoop.getBlocks(getGraph())) {
// - All successors in the old loop to the loop head should point to the new loop head instead.
// If the successor is the loop head then update to the new copied loop head instead
block.setDefaultSuccessor(fixSuccessor(block.getDefaultSuccessor(), blockToNewBlock, unrollLoop));
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementPhiBlock) {
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
StatementPhiBlock unrollPhiBlock = new StatementPhiBlock();
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
VariableRef phiVar = phiVariable.getVariable();
VariableRef newVar = definedToNewVar.get(phiVar);
StatementPhiBlock.PhiVariable unrollPhiVariable = unrollPhiBlock.addPhiVariable(newVar);
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
/* FIX */
LabelRef predecessor = phiRValue.getPredecessor();
/* FIX */
RValue rValue = phiRValue.getrValue();
unrollPhiVariable.setrValue(predecessor, rValue);
// - Remove phi-variables in the old head from looping. (as this predecessor now no longer exists)
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
List<StatementPhiBlock.PhiRValue> phiVariableValues = phiVariable.getValues();
ListIterator<StatementPhiBlock.PhiRValue> phiRValueListIterator = phiVariableValues.listIterator();
while(phiRValueListIterator.hasNext()) {
StatementPhiBlock.PhiRValue phiRValue = phiRValueListIterator.next();
if(unrollLoop.getBlocks().contains(phiRValue.getPredecessor())) {
// Found predecessor inside the same loop - remove it!
phiRValueListIterator.remove();
}
}
}
} else {
throw new RuntimeException("Statement not handled by unroll " + statement);
} else if(statement instanceof StatementConditionalJump) {
// - Remove the "unroll" directive on the condition in the old loop (as it is already unrolled).
// TODO: Only remove "unroll" from the conditional that represents the loop we are unrolling
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
conditionalJump.setDeclaredUnroll(false);
// Fix the destination (if needed)!
LabelRef fixedDestination = fixSuccessor(conditionalJump.getDestination(), blockToNewBlock, unrollLoop);
conditionalJump.setDestination(fixedDestination);
block.setConditionalSuccessor(fixedDestination);
}
}
}
// Patch the "old loop" to only contain the first iteration
// - All successors in the old loop to the loop head should point to the new loop head instead.
// - Remove phi-variables in the old head from looping. (as this predecessor now no longer exists)
// - Remove the "unroll" directive on the condition in the old loop (as it is already unrolled).
// Update phi-blocks in loop successors to also include the new unrolled "rest" loop
List<LoopSuccessorBlock> loopSuccessorBlocks = getLoopSuccessorBlocks(unrollLoop, getGraph());
for(LoopSuccessorBlock loopSuccessorBlock : loopSuccessorBlocks) {
ControlFlowBlock successorBlock = getGraph().getBlock(loopSuccessorBlock.successor);
StatementPhiBlock phiBlock = successorBlock.getPhiBlock();
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(unrollLoop.getBlocks().contains(phiRValue.getPredecessor())) {
// Found a phi variable with values from the poriginal loop in a loop successor block
// Add another value when entering from the unrolled loop
phiVariable.setrValue(unrollLabel(phiRValue.getPredecessor(), blockToNewBlock), unrollValue(phiRValue.getrValue(), definedToNewVar));
break;
}
}
}
}
return false;
return true;
}
/**
* Fix a successor block in the original loop (that is now only the first iteration).
*
* @param successor The successor
* @param blockToNewBlock The map from loop blocks to the corresponding unrolled "rest" loop blocks.
* @param unrollLoop The loop being unrolled
* @return The fixed successor label
*/
private LabelRef fixSuccessor(LabelRef successor, Map<LabelRef, LabelRef> blockToNewBlock, NaturalLoop unrollLoop) {
LabelRef fixed;
if(unrollLoop.getHead().equals(successor)) {
fixed = blockToNewBlock.get(successor);
} else {
fixed = successor;
}
return fixed;
}
/**
* Unroll a single statement inside a loop.
* Copy the statement, replace symbols properly (with the new versions if needed). This includes unrolling loop PHI-statements properly
* Unroll Successors (loop-exit successors should point to the same exit, loop-internal successors should point to the new loop-internal block)
*
* @param statement The statement to unroll
* @param unrollLoop The loop being unrolled
* @param blockToNewBlock Map from loop block label to the label of the copied block in the new (rest) loop
* @param definedToNewVar Map from variables defined in the loop to the copied variable in the new (rest) loop
* @return The copied & unrolled statement
*/
private Statement unrollStatement(Statement statement, NaturalLoop unrollLoop, Map<LabelRef, LabelRef> blockToNewBlock, Map<VariableRef, VariableRef> definedToNewVar) {
if(statement instanceof StatementPhiBlock) {
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
StatementPhiBlock newPhiBlock = new StatementPhiBlock();
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
VariableRef phiVar = phiVariable.getVariable();
VariableRef newVar = definedToNewVar.get(phiVar);
StatementPhiBlock.PhiVariable newPhiVariable = newPhiBlock.addPhiVariable(newVar);
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
LabelRef predecessor = phiRValue.getPredecessor();
if(unrollLoop.getBlocks().contains(predecessor)) {
// Predecessor inside the loop - create two copies (one from the original loop block and onw from the new copy)
// Entering from iteration 1 use the original value from iteration 1
RValue rValue = copyValue(phiRValue.getrValue());
newPhiVariable.setrValue(predecessor, rValue);
// Entering from the new rest-of-loop block perform a mapping replacing all references to variables inside the loop to the new versions.
RValue rValueNew = unrollValue(phiRValue.getrValue(), definedToNewVar);
newPhiVariable.setrValue(unrollLabel(predecessor, blockToNewBlock), rValueNew);
} else {
// Predecessor outside loop - do not copy since all entry to the copy of the loop will be through the first iteration
}
}
}
return newPhiBlock;
} else if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
return new StatementAssignment(
(LValue) unrollValue(assignment.getlValue(), definedToNewVar),
unrollValue(assignment.getrValue1(), definedToNewVar),
assignment.getOperator(),
unrollValue(assignment.getrValue2(), definedToNewVar),
assignment.getSource()
);
} else if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditional = (StatementConditionalJump) statement;
LabelRef labelRef = conditional.getDestination();
StatementConditionalJump newConditional = new StatementConditionalJump(
unrollValue(conditional.getrValue1(), definedToNewVar),
conditional.getOperator(),
unrollValue(conditional.getrValue2(), definedToNewVar),
unrollLabel(labelRef, blockToNewBlock),
conditional.getSource()
);
newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll());
return newConditional;
} else {
throw new RuntimeException("Statement not handled by unroll " + statement);
}
}
/**
* If the passed label is from the original loop return the corresponding label from the unrolled "rest" loop
* Otherwise the passed label is returned.
*
* @param labelRef The label
* @param blockToNewBlock Maps labels from the original loop to the new labels in the unrolled "rest" loop.
* @return The label to use in the unrolled loop
*/
private LabelRef unrollLabel(LabelRef labelRef, Map<LabelRef, LabelRef> blockToNewBlock) {
LabelRef unrolledLabel = blockToNewBlock.get(labelRef);
if(unrolledLabel == null) {
return labelRef;
} else {
return unrolledLabel;
}
}
/**
* Update all variable references in an RValue that point to variables inside the loop to the new unrolled "rest" loop.
*
* @param rValue The rValue to update
* @param definedToNewVar Map from variables defined in the original loop to the variables in the new unrolled "rest" loop
* @return A copy of the RValue with all relevant variable sreferences updated
*/
private RValue unrollValue(RValue rValue, Map<VariableRef, VariableRef> definedToNewVar) {
if(rValue == null) return null;
RValue rValueCopy = copyValue(rValue);
ProgramValue.GenericValue genericValue = new ProgramValue.GenericValue(rValueCopy);
ProgramValueIterator.execute(genericValue, (programValue, currentStmt, stmtIt, currentBlock) -> {
RValue rVal = programValue.get();
if(rVal instanceof VariableRef) {
if(definedToNewVar.get(rVal) != null) {
programValue.set(definedToNewVar.get(rVal));
}
}
}, null, null, null);
return genericValue.get();
}
/**
* Create a copy of the passed value object (to avoid that two parts of the model points to the same object).
*
* @param rValue The value to copy
* @return An exact copy of the value
*/
private RValue copyValue(RValue rValue) {
if(rValue == null) return null;
ProgramValue.GenericValue genericValue = new ProgramValue.GenericValue(rValue);
ProgramValueIterator.execute(genericValue, (programValue, currentStmt, stmtIt, currentBlock) -> {
RValue rVal = programValue.get();
if(rVal instanceof PointerDereferenceSimple) {
programValue.set(new PointerDereferenceSimple(((PointerDereferenceSimple) rVal).getPointer()));
} else if(rVal instanceof PointerDereferenceIndexed) {
programValue.set(new PointerDereferenceIndexed(((PointerDereferenceIndexed) rVal).getPointer(), ((PointerDereferenceIndexed) rVal).getIndex()));
} else if(rVal instanceof CastValue) {
programValue.set(new CastValue(((CastValue) rVal).getToType(), ((CastValue) rVal).getValue()));
} else if(rVal instanceof ValueList) {
programValue.set(new ValueList(new ArrayList<>(((ValueList) rVal).getList())));
}
}, null, null, null);
return genericValue.get();
}
/**
* Copy all blocks in a loop. The new copies are named from the original name plus an integer suffix.
*
* @param unrollLoop The loop being copied
* @return A map from each block label (from the loop) to the new copied labels
*/
private Map<LabelRef, LabelRef> copyBlocksInLoop(NaturalLoop unrollLoop) {
LinkedHashMap<LabelRef, LabelRef> blockToNewBlock = new LinkedHashMap<>();
for(ControlFlowBlock block : unrollLoop.getBlocks(getGraph())) {
Scope blockScope = getScope().getScope(block.getScope());
// Find the serial number
int unrollSerial = 1;
String localName = block.getLabel().getLocalName();
int serialPos = localName.lastIndexOf("_");
if(serialPos>=0) {
localName = localName.substring(0, serialPos);
}
String unrollLabelName;
do {
unrollLabelName = localName + "_" + unrollSerial++;
} while(blockScope.getLabel(unrollLabelName) != null);
// Create a label
Label unrollLabel = blockScope.addLabel(unrollLabelName);
blockToNewBlock.put(block.getLabel(), unrollLabel.getRef());
}
return blockToNewBlock;
}
/**
* Create new versions of all symbols assigned inside the loop
*
* @param unrollLoop The loop being unrolled
* @return A map from variables assigned inside the loop to the new copy of the variable
*/
private Map<VariableRef, VariableRef> copyVarsDefinedInLoop(NaturalLoop unrollLoop) {
Map<VariableRef, VariableRef> definedToNewVar = new LinkedHashMap<>();
for(VariableRef definedVarRef : getVarsDefinedInLoop(unrollLoop, getProgram())) {
Variable definedVar = getScope().getVariable(definedVarRef);
Variable newVar;
if(definedVarRef.isIntermediate()) {
newVar = definedVar.getScope().addVariableIntermediate();
newVar.setType(definedVar.getType());
newVar.setDeclaredRegister(definedVar.getDeclaredRegister());
newVar.setDeclaredVolatile(definedVar.isDeclaredVolatile());
newVar.setDeclaredAlignment(definedVar.getDeclaredAlignment());
newVar.setInferredType(definedVar.isInferredType());
} else if(definedVarRef.isVersion()) {
newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
} else {
throw new RuntimeException("Error! Variable is not versioned or intermediate " + definedVar.toString(getProgram()));
}
definedToNewVar.put(definedVarRef, newVar.getRef());
//getLog().append("Defined in loop: " + definedVarRef.getFullName() + " -> " + newVar.getRef().getFullName());
}
return definedToNewVar;
}
/**
@ -104,10 +318,10 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
* The smallest loop (fewest control flow blocks) is chosen.
* If multiple loops have the same size the first one is chosen.
*
* @param unrollLoopCandidates All loops that are decalred to be unrolled
* @param unrollLoopCandidates All loops that are declared to be unrolled
* @return The loop to unroll first.
*/
private NaturalLoop chooseUnrollLoop(List<NaturalLoop> unrollLoopCandidates) {
private static NaturalLoop chooseUnrollLoop(List<NaturalLoop> unrollLoopCandidates) {
NaturalLoop unrollLoop = null;
for(NaturalLoop unrollLoopCandidate : unrollLoopCandidates) {
if(unrollLoop == null) {
@ -121,14 +335,14 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
return unrollLoop;
}
/**
* Find all loops declared for unrolling. This is done by examining all conditional jumps, which hold the loop unroll declaration.
*
* @param loops All loops identified in the program
* @param program The program
* @return All loops declared to be unrolled
*/
static List<NaturalLoop> findUnrollLoopCandidates(Program program, NaturalLoopSet loops) {
static List<NaturalLoop> findUnrollLoops(Program program) {
NaturalLoopSet loops = program.getLoopSet();
List<NaturalLoop> unrollLoopCandidates = new ArrayList<>();
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
@ -155,11 +369,12 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
/**
* Get all variables defined inside a loop
* @param program The program
*
* @param loop The loop
* @param program The program
* @return All variables defined inside the blocks of the loop
*/
static List<VariableRef> getVarsDefinedInLoop(Program program, NaturalLoop loop) {
static List<VariableRef> getVarsDefinedInLoop(NaturalLoop loop, Program program) {
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
List<VariableRef> definedInLoop = new ArrayList<>();
for(ControlFlowBlock block : loop.getBlocks(program.getGraph())) {
@ -173,23 +388,24 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
return definedInLoop;
}
/** Information about a block successing a loop - ie. a place where the flow of control leaves a loop. */
/** Information about a block succeeding a loop - ie. a place where the flow of control leaves a loop. */
public static class LoopSuccessorBlock {
/** A block that is the sucessor to a block inside the loop. */
LabelRef sucessor;
/** The block inside the loop that is the predecessor of the loop sucessor block. */
/** A block that is the successor to a block inside the loop. */
LabelRef successor;
/** The block inside the loop that is the predecessor of the loop successor block. */
LabelRef predecessor;
public LoopSuccessorBlock(LabelRef sucessor, LabelRef predecessor) {
this.sucessor = sucessor;
public LoopSuccessorBlock(LabelRef successor, LabelRef predecessor) {
this.successor = successor;
this.predecessor = predecessor;
}
}
/**
* Find all transitions where the flow of control leaves a loop
*
* @param loop The loop to examine
* @param graph The control flow graph
* @param graph The control flow graph
* @return
*/
static List<LoopSuccessorBlock> getLoopSuccessorBlocks(NaturalLoop loop, ControlFlowGraph graph) {
@ -207,5 +423,19 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
return loopSuccessors;
}
static boolean isReferencedOutsideLoop(VariableRef definedVarRef, NaturalLoop unrollLoop, Program program) {
boolean referencedOutsideLoop = false;
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
Collection<Integer> varRefStatements = variableReferenceInfos.getVarRefStatements(definedVarRef);
for(Integer varRefStatement : varRefStatements) {
StatementInfos statementInfos = program.getStatementInfos();
ControlFlowBlock refBlock = statementInfos.getBlock(varRefStatement);
if(!unrollLoop.getBlocks().contains(refBlock.getLabel())) {
referencedOutsideLoop = true;
break;
}
}
return referencedOutsideLoop;
}
}

View File

@ -1,8 +1,9 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.NaturalLoop;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.VariableVersion;
@ -11,13 +12,11 @@ import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
/**
* Prepare for unrolling loops declared as inline.
* This is done byensuring that all variables defined inside the loops and used outside the loop is passed through a PHI-functions
* This is done by ensuring that all variables defined inside the loops and used outside the loop is passed through a PHI-functions
* upon loop exit thus ensuring that these variables are only used inside the loop and in the PHI-function.
* This makes it much easier to perform the unrolling as only a few parts of the program must be modified.
*/
@ -30,82 +29,45 @@ public class Pass2LoopUnrollPhiPrepare extends Pass2SsaOptimization {
@Override
public boolean step() {
// Look for loops to unroll
NaturalLoopSet loops = getProgram().getLoopSet();
List<NaturalLoop> unrollLoopCandidates = Pass2LoopUnroll.findUnrollLoopCandidates(getProgram(), loops);
// Is there any unrolling to do?
if(unrollLoopCandidates.isEmpty()) {
return false;
}
for(NaturalLoop unrollLoop : unrollLoopCandidates) {
List<VariableRef> definedInLoop = Pass2LoopUnroll.getVarsDefinedInLoop(getProgram(), unrollLoop);
for(NaturalLoop unrollLoop : Pass2LoopUnroll.findUnrollLoops(getProgram())) {
// - Ensure that all variables assigned inside the loop has a PHI in successor blocks to the loop
// - Find loop successor blocks
List<Pass2LoopUnroll.LoopSuccessorBlock> loopSuccessors = Pass2LoopUnroll.getLoopSuccessorBlocks(unrollLoop, getGraph());
// - Add any needed PHI-statements to the successors
for(VariableRef definedVarRef : definedInLoop) {
for(VariableRef definedVarRef : Pass2LoopUnroll.getVarsDefinedInLoop(unrollLoop, getProgram())) {
// Find out if the variable is ever referenced outside the loop
if(isReferencedOutsideLoop(definedVarRef, unrollLoop, getProgram())) {
for(Pass2LoopUnroll.LoopSuccessorBlock loopSuccessor : loopSuccessors) {
LabelRef successorBlockRef = loopSuccessor.sucessor;
if(Pass2LoopUnroll.isReferencedOutsideLoop(definedVarRef, unrollLoop, getProgram())) {
// - Add any needed PHI-statements to the successors
for(Pass2LoopUnroll.LoopSuccessorBlock loopSuccessor : Pass2LoopUnroll.getLoopSuccessorBlocks(unrollLoop, getGraph())) {
LabelRef successorBlockRef = loopSuccessor.successor;
LabelRef successorPredecessorRef = loopSuccessor.predecessor;
ControlFlowBlock successorBlock = getGraph().getBlock(successorBlockRef);
StatementPhiBlock phiBlock = successorBlock.getPhiBlock();
// Look for a phi-variable
boolean phiFound = false;
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
if(phiVariable.getVariable().isVersion() && definedVarRef.isVersion()) {
if(phiVariable.getVariable().getFullNameUnversioned().equals(definedVarRef.getFullNameUnversioned())) {
phiFound = true;
// Create a new version of the variable
Variable definedVar = getScope().getVariable(definedVarRef);
Variable newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
// Replace all references outside the loop to the new version!
LinkedHashMap<SymbolRef, RValue> aliases = new LinkedHashMap<>();
aliases.put(definedVarRef, newVar.getRef());
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(currentBlock != null) {
if(!unrollLoop.getBlocks().contains(currentBlock.getLabel())) {
new AliasReplacer(aliases).execute(programValue, currentStmt, stmtIt, currentBlock);
}
}
}
if(!phiFound) {
Variable definedVar = getScope().getVariable(definedVarRef);
Variable newVar = ((VariableVersion) definedVar).getVersionOf().createVersion();
});
// Replace all references to definedVarRef outside loop to newVar!
LinkedHashMap<SymbolRef, RValue> aliases = new LinkedHashMap<>();
aliases.put(definedVarRef, newVar.getRef());
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(currentBlock != null) {
if(!unrollLoop.getBlocks().contains(currentBlock.getLabel())) {
new AliasReplacer(aliases).execute(programValue, currentStmt, stmtIt, currentBlock);
}
}
});
// Create the new phi-variable in the successor phi block
StatementPhiBlock.PhiVariable newPhiVar = phiBlock.addPhiVariable(newVar.getRef());
newPhiVar.setrValue(successorPredecessorRef, definedVarRef);
getLog().append("Creating PHI for " + definedVarRef.getFullName() + " in block " + successorBlock.getLabel() + " - " + phiBlock.toString(getProgram(), false));
// Create the new phi-variable
StatementPhiBlock.PhiVariable newPhiVar = phiBlock.addPhiVariable(newVar.getRef());
newPhiVar.setrValue(successorPredecessorRef, definedVarRef);
getLog().append("Creating PHI for " + definedVarRef.getFullName() + " in block " + successorBlock.getLabel() + " - " + phiBlock.toString(getProgram(), false));
}
}
}
}
}
getLog().append(getGraph().toString(getProgram()));
return false;
}
private static boolean isReferencedOutsideLoop(VariableRef definedVarRef, NaturalLoop unrollLoop, Program program) {
boolean referencedOutsideLoop = false;
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
Collection<Integer> varRefStatements = variableReferenceInfos.getVarRefStatements(definedVarRef);
for(Integer varRefStatement : varRefStatements) {
StatementInfos statementInfos = program.getStatementInfos();
ControlFlowBlock refBlock = statementInfos.getBlock(varRefStatement);
if(!unrollLoop.getBlocks().contains(refBlock.getLabel())) {
referencedOutsideLoop = true;
break;
}
}
return referencedOutsideLoop;
}
}

View File

@ -1,18 +1,15 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.values.LabelRef;
import java.util.*;
/** Plan the optimal sequence for the blocks of the control flow graph */
public class Pass3BlockSequencePlanner extends Pass2Base {
Deque<ScopeTodo> todoScopes = new ArrayDeque<>();
public Pass3BlockSequencePlanner(Program program) {

View File

@ -52,8 +52,18 @@ public class TestPrograms {
}
@Test
public void testUnrollScreenFill() throws IOException, URISyntaxException {
compileAndCompare("unroll-screenfill");
public void testUnrollScreenFillFor() throws IOException, URISyntaxException {
compileAndCompare("unroll-screenfill-for");
}
@Test
public void testUnrollScreenFillWhile() throws IOException, URISyntaxException {
compileAndCompare("unroll-screenfill-while");
}
@Test
public void testUnrollModifyVar() throws IOException, URISyntaxException {
compileAndCompare("unroll-loop-modifyvar");
}
@Test

View File

@ -0,0 +1,13 @@
// An unrolled loop modifying a var used later
void main() {
byte* SCREEN = $400;
byte a=3;
inline do {
SCREEN[a]=a;
a++;
} while(a<14);
SCREEN[a]=a;
}

View File

@ -0,0 +1,13 @@
// Fills the screen using an unrolled inner ranged for()-loop
void main() {
byte* SCREEN = $400;
for(byte x: 0..39) {
inline for(byte line: 0..24) {
(SCREEN+line*40)[x] = x;
}
}
}

View File

@ -0,0 +1,13 @@
// Fills the screen using an unrolled inner while()-loop
void main() {
byte* SCREEN = $400;
for(byte x: 0..39) {
byte line = 0;
inline while(line!=25) {
(SCREEN+line*40)[x] = x;
line++;
}
}
}

View File

@ -1,35 +0,0 @@
// Fills the screen using an unrolled inner loop
void main() {
byte* SCREEN = $400;
byte a=3;
inline do {
SCREEN[a]=a;
a++;
} while(a<14);
SCREEN[a]=a;
/*
for(byte x: 0..39) {
inline for(byte line: 0..24) {
(SCREEN+line*40)[x] = x;
}
}
*/
/*
for(byte x: 0..39) {
byte line = 0;
inline while(line!=25 || x<10) {
(SCREEN+line*40)[x] = x;
line++;
}
}
*/
}

View File

@ -0,0 +1,12 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
ldx #0
b1:
inx
cpx #$64
bcc b1
rts
}

View File

@ -0,0 +1,20 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@1
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 ) [ main::i#2 ] ( main:2 [ main::i#2 ] )
[6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:2 [ main::i#1 ] )
[7] if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] )
to:main::@return
main::@return: scope:[main] from main::@1
[8] return [ ] ( main:2 [ ] )
to:@return

View File

@ -0,0 +1,346 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/loop100.kc
void main() {
for(byte i=0; i<100; i++) { }
}
Adding pre/post-modifier (byte) main::i ← ++ (byte) main::i
SYMBOLS
(label) @1
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from
(byte) main::i ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(byte) main::i ← ++ (byte) main::i
(bool~) main::$0 ← (byte) main::i < (byte/signed byte/word/signed word/dword/signed dword) 100
if((bool~) main::$0) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
@1: scope:[] from @begin
call main
to:@end
@end: scope:[] from @1
Removing empty block main::@2
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
(byte) main::i#1 ← ++ (byte) main::i#2
(bool~) main::$0 ← (byte) main::i#1 < (byte/signed byte/word/signed word/dword/signed dword) 100
if((bool~) main::$0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @2
Succesful SSA optimization Pass2CullEmptyBlocks
Simple Condition (bool~) main::$0 if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1
Succesful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) main::i#0 = 0
Succesful SSA optimization Pass2ConstantIdentification
OPTIMIZING CONTROL FLOW GRAPH
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Succesful SSA optimization Pass2ConstantInlining
Block Sequence Planned @begin @1 @end main main::@1 main::@return
Added new block during phi lifting main::@3(between main::@1 and main::@1)
Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Propagating live ranges...
Propagating live ranges...
Created 1 initial phi equivalence classes
Coalesced [9] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) main::@3
Block Sequence Planned @begin @1 @end main main::@1 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Propagating live ranges...
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@1
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 ) [ main::i#2 ] ( main:2 [ main::i#2 ] )
[6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:2 [ main::i#1 ] )
[7] if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] )
to:main::@return
main::@return: scope:[main] from main::@1
[8] return [ ] ( main:2 [ ] )
to:@return
DOMINATORS
@begin dominated by @begin
@1 dominated by @1 @begin
@end dominated by @1 @begin @end
main dominated by @1 @begin main
main::@1 dominated by @1 @begin main::@1 main
main::@return dominated by main::@return @1 @begin main::@1 main
NATURAL LOOPS
Found back edge: Loop head: main::@1 tails: main::@1 blocks: null
Populated: Loop head: main::@1 tails: main::@1 blocks: main::@1
Loop head: main::@1 tails: main::@1 blocks: main::@1
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 1 loops in scope [main]
Loop head: main::@1 tails: main::@1 blocks: main::@1
Loop head: main::@1 tails: main::@1 blocks: main::@1 depth: 1
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 22.0
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label i = 2
//SEG10 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG11 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta i
jmp b1
//SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG14 main::@1
b1:
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuz1=_inc_vbuz1
inc i
//SEG16 [7] if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuz1_lt_vbuc1_then_la1
lda i
cmp #$64
bcc b1_from_b1
jmp breturn
//SEG17 main::@return
breturn:
//SEG18 [8] return [ ] ( main:2 [ ] )
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 38.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplift Scope []
Uplifting [main] best 193 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 193 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
//SEG10 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG11 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG14 main::@1
b1:
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx=_inc_vbuxx
inx
//SEG16 [7] if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx_lt_vbuc1_then_la1
cpx #$64
bcc b1_from_b1
jmp breturn
//SEG17 main::@return
breturn:
//SEG18 [8] return [ ] ( main:2 [ ] )
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b1 with b1
Removing instruction bbegin:
Removing instruction b1_from_bbegin:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b1:
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 22.0
reg byte x [ main::i#2 main::i#1 ]
FINAL ASSEMBLER
Score: 97
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG4 @1
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
//SEG10 [5] phi from main to main::@1 [phi:main->main::@1]
//SEG11 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
//SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
//SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG14 main::@1
b1:
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx=_inc_vbuxx
inx
//SEG16 [7] if((byte) main::i#1<(byte/signed byte/word/signed word/dword/signed dword) 100) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx_lt_vbuc1_then_la1
cpx #$64
bcc b1
//SEG17 main::@return
//SEG18 [8] return [ ] ( main:2 [ ] )
rts
}

View File

@ -0,0 +1,11 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 22.0
reg byte x [ main::i#2 main::i#1 ]

View File

@ -0,0 +1,32 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
.label SCREEN = $400
lda #3
sta SCREEN+3
lda #3+1
sta SCREEN+3+1
lda #3+1+1
sta SCREEN+3+1+1
lda #3+1+1+1
sta SCREEN+3+1+1+1
lda #3+1+1+1+1
sta SCREEN+3+1+1+1+1
lda #3+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1
lda #3+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1
lda #3+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1
lda #3+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1
lda #3+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1
lda #3+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1
lda #3+1+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1+1
rts
}

View File

@ -0,0 +1,51 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main
[5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_1
main::@1_1: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_2
main::@1_2: scope:[main] from main::@1_1
[7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_3
main::@1_3: scope:[main] from main::@1_2
[8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_4
main::@1_4: scope:[main] from main::@1_3
[9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_5
main::@1_5: scope:[main] from main::@1_4
[10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_6
main::@1_6: scope:[main] from main::@1_5
[11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_7
main::@1_7: scope:[main] from main::@1_6
[12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_8
main::@1_8: scope:[main] from main::@1_7
[13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_9
main::@1_9: scope:[main] from main::@1_8
[14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_10
main::@1_10: scope:[main] from main::@1_9
[15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::@1_10
[16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@2
[17] return [ ] ( main:2 [ ] )
to:@return

View File

@ -0,0 +1,920 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/unroll-loop-modifyvar.kc
// An unrolled loop modifying a var used later
void main() {
byte* SCREEN = $400;
byte a=3;
inline do {
SCREEN[a]=a;
a++;
} while(a<14);
SCREEN[a]=a;
}
Adding pre/post-modifier (byte) main::a ← ++ (byte) main::a
SYMBOLS
(label) @1
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(byte) main::a
Promoting word/signed word/dword/signed dword to byte* in main::SCREEN ← ((byte*)) 1024
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from
(byte*) main::SCREEN ← ((byte*)) (word/signed word/dword/signed dword) 1024
(byte) main::a ← (byte/signed byte/word/signed word/dword/signed dword) 3
to:main::@1
main::@1: scope:[main] from main main::@1
*((byte*) main::SCREEN + (byte) main::a) ← (byte) main::a
(byte) main::a ← ++ (byte) main::a
(bool~) main::$0 ← (byte) main::a < (byte/signed byte/word/signed word/dword/signed dword) 14
unroll if((bool~) main::$0) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
*((byte*) main::SCREEN + (byte) main::a) ← (byte) main::a
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
@1: scope:[] from @begin
call main
to:@end
@end: scope:[] from @1
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
(byte) main::a#0 ← (byte/signed byte/word/signed word/dword/signed dword) 3
to:main::@1
main::@1: scope:[main] from main main::@1
(byte*) main::SCREEN#1 ← phi( main/(byte*) main::SCREEN#0 main::@1/(byte*) main::SCREEN#1 )
(byte) main::a#2 ← phi( main/(byte) main::a#0 main::@1/(byte) main::a#1 )
*((byte*) main::SCREEN#1 + (byte) main::a#2) ← (byte) main::a#2
(byte) main::a#1 ← ++ (byte) main::a#2
(bool~) main::$0 ← (byte) main::a#1 < (byte/signed byte/word/signed word/dword/signed dword) 14
unroll if((bool~) main::$0) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
(byte*) main::SCREEN#2 ← phi( main::@1/(byte*) main::SCREEN#1 )
(byte) main::a#3 ← phi( main::@1/(byte) main::a#1 )
*((byte*) main::SCREEN#2 + (byte) main::a#3) ← (byte) main::a#3
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(byte*) main::SCREEN#1
(byte*) main::SCREEN#2
(byte) main::a
(byte) main::a#0
(byte) main::a#1
(byte) main::a#2
(byte) main::a#3
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @2
Succesful SSA optimization Pass2CullEmptyBlocks
Alias (byte) main::a#1 = (byte) main::a#3
Alias (byte*) main::SCREEN#1 = (byte*) main::SCREEN#2
Succesful SSA optimization Pass2AliasElimination
Self Phi Eliminated (byte*) main::SCREEN#1
Succesful SSA optimization Pass2SelfPhiElimination
Redundant Phi (byte*) main::SCREEN#1 (byte*) main::SCREEN#0
Succesful SSA optimization Pass2RedundantPhiElimination
Simple Condition (bool~) main::$0 unroll if((byte) main::a#1<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1
Succesful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::SCREEN#0 = ((byte*))1024
Constant (const byte) main::a#0 = 3
Succesful SSA optimization Pass2ConstantIdentification
Creating PHI for main::a#1 in block main::@2 - (byte) main::a#4 ← phi( main::@1/(byte) main::a#1 )
Unrolling loop Loop head: main::@1 tails: main::@1 blocks: main::@1
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#2 (const byte) main::a#0
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#1 = ++main::a#0
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#0)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1) in block main::@2
if() condition always true - replacing block destination [3] if((const byte) main::a#1<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_1
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#4 = (byte) main::a#6
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@2 main::@return
Creating PHI for main::a#4 in block main::@2 - (byte) main::a#7 ← phi( main::@1_1/(byte) main::a#4 )
Unrolling loop Loop head: main::@1_1 tails: main::@1_1 blocks: main::@1_1
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#5 (const byte) main::a#1
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#4 = ++main::a#1
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#1)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_1) in block main::@2
if() condition always true - replacing block destination [5] if((const byte) main::a#4<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_2
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#7 = (byte) main::a#9
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@2 main::@return
Creating PHI for main::a#7 in block main::@2 - (byte) main::a#10 ← phi( main::@1_2/(byte) main::a#7 )
Unrolling loop Loop head: main::@1_2 tails: main::@1_2 blocks: main::@1_2
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#8 (const byte) main::a#4
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#7 = ++main::a#4
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#4)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_2) in block main::@2
if() condition always true - replacing block destination [6] if((const byte) main::a#7<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_3
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#10 = (byte) main::a#12
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@2 main::@return
Creating PHI for main::a#10 in block main::@2 - (byte) main::a#13 ← phi( main::@1_3/(byte) main::a#10 )
Unrolling loop Loop head: main::@1_3 tails: main::@1_3 blocks: main::@1_3
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#11 (const byte) main::a#7
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#10 = ++main::a#7
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#7)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_3) in block main::@2
if() condition always true - replacing block destination [7] if((const byte) main::a#10<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_4
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#13 = (byte) main::a#15
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@2 main::@return
Creating PHI for main::a#13 in block main::@2 - (byte) main::a#16 ← phi( main::@1_4/(byte) main::a#13 )
Unrolling loop Loop head: main::@1_4 tails: main::@1_4 blocks: main::@1_4
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#14 (const byte) main::a#10
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#13 = ++main::a#10
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#10)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_4) in block main::@2
if() condition always true - replacing block destination [8] if((const byte) main::a#13<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_5
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#16 = (byte) main::a#18
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@2 main::@return
Creating PHI for main::a#16 in block main::@2 - (byte) main::a#19 ← phi( main::@1_5/(byte) main::a#16 )
Unrolling loop Loop head: main::@1_5 tails: main::@1_5 blocks: main::@1_5
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#17 (const byte) main::a#13
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#16 = ++main::a#13
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#13)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_5) in block main::@2
if() condition always true - replacing block destination [9] if((const byte) main::a#16<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_6
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#19 = (byte) main::a#21
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@2 main::@return
Creating PHI for main::a#19 in block main::@2 - (byte) main::a#22 ← phi( main::@1_6/(byte) main::a#19 )
Unrolling loop Loop head: main::@1_6 tails: main::@1_6 blocks: main::@1_6
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#20 (const byte) main::a#16
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#19 = ++main::a#16
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#16)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_6) in block main::@2
if() condition always true - replacing block destination [10] if((const byte) main::a#19<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_7
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#22 = (byte) main::a#24
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@2 main::@return
Creating PHI for main::a#22 in block main::@2 - (byte) main::a#25 ← phi( main::@1_7/(byte) main::a#22 )
Unrolling loop Loop head: main::@1_7 tails: main::@1_7 blocks: main::@1_7
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#23 (const byte) main::a#19
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#22 = ++main::a#19
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#19)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_7) in block main::@2
if() condition always true - replacing block destination [11] if((const byte) main::a#22<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_8
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#25 = (byte) main::a#27
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@2 main::@return
Creating PHI for main::a#25 in block main::@2 - (byte) main::a#28 ← phi( main::@1_8/(byte) main::a#25 )
Unrolling loop Loop head: main::@1_8 tails: main::@1_8 blocks: main::@1_8
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#26 (const byte) main::a#22
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#25 = ++main::a#22
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#22)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_8) in block main::@2
if() condition always true - replacing block destination [12] if((const byte) main::a#25<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_9
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#28 = (byte) main::a#30
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@2 main::@return
Creating PHI for main::a#28 in block main::@2 - (byte) main::a#31 ← phi( main::@1_9/(byte) main::a#28 )
Unrolling loop Loop head: main::@1_9 tails: main::@1_9 blocks: main::@1_9
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#29 (const byte) main::a#25
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#28 = ++main::a#25
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#25)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_9) in block main::@2
if() condition always true - replacing block destination [13] if((const byte) main::a#28<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_10
Succesful SSA optimization Pass2ConstantIfs
Alias (byte) main::a#31 = (byte) main::a#33
Succesful SSA optimization Pass2AliasElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@1_10 main::@2 main::@return
Creating PHI for main::a#31 in block main::@2 - (byte) main::a#34 ← phi( main::@1_10/(byte) main::a#31 )
Unrolling loop Loop head: main::@1_10 tails: main::@1_10 blocks: main::@1_10
Successful SSA optimization Pass2LoopUnroll
OPTIMIZING CONTROL FLOW GRAPH
Redundant Phi (byte) main::a#32 (const byte) main::a#28
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte) main::a#31 = ++main::a#28
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+main::a#28)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::@1_10) in block main::@1_11
if() condition always false - eliminating [14] if((const byte) main::a#31<(byte/signed byte/word/signed word/dword/signed dword) 14) goto main::@1_11
Succesful SSA optimization Pass2ConstantIfs
Eliminating variable (byte) main::a#35 from unused block main::@1_11
Eliminating variable (byte) main::a#36 and from unused block main::@1_11
Removing PHI-reference to removed block (main::@1_11) in block main::@2
Removing unused block main::@1_11
Succesful SSA optimization Pass2EliminateUnusedBlocks
Redundant Phi (byte) main::a#34 (const byte) main::a#31
Succesful SSA optimization Pass2RedundantPhiElimination
Consolidated array index constant in *(main::SCREEN#0+main::a#31)
Succesful SSA optimization Pass2ConstantAdditionElimination
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@1_10 main::@2 main::@return
OPTIMIZING CONTROL FLOW GRAPH
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#0
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#1
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#4
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#7
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#10
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#13
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#16
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#19
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#22
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#25
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#28
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Inlining constant with different constant siblings (const byte) main::a#31
Constant inlined main::a#22 = ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#10 = ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#31 = ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#25 = ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#13 = ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#0 = (byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#19 = ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#28 = ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#1 = ++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#16 = ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#7 = ++++++(byte/signed byte/word/signed word/dword/signed dword) 3
Constant inlined main::a#4 = ++++(byte/signed byte/word/signed word/dword/signed dword) 3
Succesful SSA optimization Pass2ConstantInlining
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@1_10 main::@2 main::@return
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@1_10 main::@2 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Propagating live ranges...
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Block Sequence Planned @begin @1 @end main main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4 main::@1_5 main::@1_6 main::@1_7 main::@1_8 main::@1_9 main::@1_10 main::@2 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main
[5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_1
main::@1_1: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_2
main::@1_2: scope:[main] from main::@1_1
[7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_3
main::@1_3: scope:[main] from main::@1_2
[8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_4
main::@1_4: scope:[main] from main::@1_3
[9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_5
main::@1_5: scope:[main] from main::@1_4
[10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_6
main::@1_6: scope:[main] from main::@1_5
[11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_7
main::@1_7: scope:[main] from main::@1_6
[12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_8
main::@1_8: scope:[main] from main::@1_7
[13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_9
main::@1_9: scope:[main] from main::@1_8
[14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@1_10
main::@1_10: scope:[main] from main::@1_9
[15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::@1_10
[16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@2
[17] return [ ] ( main:2 [ ] )
to:@return
DOMINATORS
@begin dominated by @begin
@1 dominated by @begin @1
@end dominated by @begin @end @1
main dominated by @begin main @1
main::@1 dominated by @begin main @1 main::@1
main::@1_1 dominated by @begin main @1 main::@1 main::@1_1
main::@1_2 dominated by @begin main @1 main::@1 main::@1_1 main::@1_2
main::@1_3 dominated by @begin main @1 main::@1 main::@1_1 main::@1_2 main::@1_3
main::@1_4 dominated by @begin main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_5 dominated by @begin main::@1_5 main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_6 dominated by @begin main::@1_5 main::@1_6 main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_7 dominated by @begin main::@1_5 main::@1_6 main::@1_7 main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_8 dominated by @begin main::@1_5 main::@1_6 main::@1_7 main::@1_8 main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_9 dominated by main::@1_9 @begin main::@1_5 main::@1_6 main::@1_7 main::@1_8 main @1 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@1_10 dominated by main::@1_9 @begin main::@1_5 main::@1_6 main::@1_7 main::@1_8 main @1 main::@1_10 main::@1 main::@1_1 main::@1_2 main::@1_3 main::@1_4
main::@2 dominated by main::@1_9 @begin main::@1_5 main::@1_6 main::@1_7 main::@1_8 main @1 main::@1_10 main::@1 main::@1_1 main::@1_2 main::@2 main::@1_3 main::@1_4
main::@return dominated by main::@1_9 main::@return @begin main::@1_5 main::@1_6 main::@1_7 main::@1_8 main @1 main::@1_10 main::@1 main::@1_1 main::@1_2 main::@2 main::@1_3 main::@1_4
NATURAL LOOPS
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 0 loops in scope [main]
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(byte) main::a
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
jmp b1
//SEG10 main::@1
b1:
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+3
jmp b1_1
//SEG12 main::@1_1
b1_1:
//SEG13 [6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1
sta SCREEN+3+1
jmp b1_2
//SEG14 main::@1_2
b1_2:
//SEG15 [7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1
sta SCREEN+3+1+1
jmp b1_3
//SEG16 main::@1_3
b1_3:
//SEG17 [8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1
sta SCREEN+3+1+1+1
jmp b1_4
//SEG18 main::@1_4
b1_4:
//SEG19 [9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1
sta SCREEN+3+1+1+1+1
jmp b1_5
//SEG20 main::@1_5
b1_5:
//SEG21 [10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1
jmp b1_6
//SEG22 main::@1_6
b1_6:
//SEG23 [11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1
jmp b1_7
//SEG24 main::@1_7
b1_7:
//SEG25 [12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1
jmp b1_8
//SEG26 main::@1_8
b1_8:
//SEG27 [13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1
jmp b1_9
//SEG28 main::@1_9
b1_9:
//SEG29 [14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1
jmp b1_10
//SEG30 main::@1_10
b1_10:
//SEG31 [15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1
jmp b2
//SEG32 main::@2
b2:
//SEG33 [16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1+1
jmp breturn
//SEG34 main::@return
breturn:
//SEG35 [17] return [ ] ( main:2 [ ] )
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 156 combination
Uplifting [] best 156 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
jmp b1
//SEG10 main::@1
b1:
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+3
jmp b1_1
//SEG12 main::@1_1
b1_1:
//SEG13 [6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1
sta SCREEN+3+1
jmp b1_2
//SEG14 main::@1_2
b1_2:
//SEG15 [7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1
sta SCREEN+3+1+1
jmp b1_3
//SEG16 main::@1_3
b1_3:
//SEG17 [8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1
sta SCREEN+3+1+1+1
jmp b1_4
//SEG18 main::@1_4
b1_4:
//SEG19 [9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1
sta SCREEN+3+1+1+1+1
jmp b1_5
//SEG20 main::@1_5
b1_5:
//SEG21 [10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1
jmp b1_6
//SEG22 main::@1_6
b1_6:
//SEG23 [11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1
jmp b1_7
//SEG24 main::@1_7
b1_7:
//SEG25 [12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1
jmp b1_8
//SEG26 main::@1_8
b1_8:
//SEG27 [13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1
jmp b1_9
//SEG28 main::@1_9
b1_9:
//SEG29 [14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1
jmp b1_10
//SEG30 main::@1_10
b1_10:
//SEG31 [15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1
jmp b2
//SEG32 main::@2
b2:
//SEG33 [16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1+1
jmp breturn
//SEG34 main::@return
breturn:
//SEG35 [17] return [ ] ( main:2 [ ] )
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b1_1
Removing instruction jmp b1_2
Removing instruction jmp b1_3
Removing instruction jmp b1_4
Removing instruction jmp b1_5
Removing instruction jmp b1_6
Removing instruction jmp b1_7
Removing instruction jmp b1_8
Removing instruction jmp b1_9
Removing instruction jmp b1_10
Removing instruction jmp b2
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b1_from_bbegin:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b1:
Removing instruction bend:
Removing instruction b1:
Removing instruction b1_1:
Removing instruction b1_2:
Removing instruction b1_3:
Removing instruction b1_4:
Removing instruction b1_5:
Removing instruction b1_6:
Removing instruction b1_7:
Removing instruction b1_8:
Removing instruction b1_9:
Removing instruction b1_10:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@1_1
(label) main::@1_10
(label) main::@1_2
(label) main::@1_3
(label) main::@1_4
(label) main::@1_5
(label) main::@1_6
(label) main::@1_7
(label) main::@1_8
(label) main::@1_9
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::a
FINAL ASSEMBLER
Score: 84
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG4 @1
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG10 main::@1
//SEG11 [5] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3
sta SCREEN+3
//SEG12 main::@1_1
//SEG13 [6] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1
sta SCREEN+3+1
//SEG14 main::@1_2
//SEG15 [7] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1
sta SCREEN+3+1+1
//SEG16 main::@1_3
//SEG17 [8] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1
sta SCREEN+3+1+1+1
//SEG18 main::@1_4
//SEG19 [9] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1
sta SCREEN+3+1+1+1+1
//SEG20 main::@1_5
//SEG21 [10] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1
//SEG22 main::@1_6
//SEG23 [11] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1
//SEG24 main::@1_7
//SEG25 [12] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1
//SEG26 main::@1_8
//SEG27 [13] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1
//SEG28 main::@1_9
//SEG29 [14] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1
//SEG30 main::@1_10
//SEG31 [15] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1
//SEG32 main::@2
//SEG33 [16] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3) ← ++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 3 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #3+1+1+1+1+1+1+1+1+1+1+1
sta SCREEN+3+1+1+1+1+1+1+1+1+1+1+1
//SEG34 main::@return
//SEG35 [17] return [ ] ( main:2 [ ] )
rts
}

View File

@ -0,0 +1,21 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@1_1
(label) main::@1_10
(label) main::@1_2
(label) main::@1_3
(label) main::@1_4
(label) main::@1_5
(label) main::@1_6
(label) main::@1_7
(label) main::@1_8
(label) main::@1_9
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::a

View File

@ -0,0 +1,63 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
.label SCREEN = $400
ldx #0
b2:
txa
sta SCREEN+0*$28,x
txa
sta SCREEN+(0+1)*$28,x
txa
sta SCREEN+(0+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
inx
cpx #$28
bne b2
rts
}

View File

@ -0,0 +1,97 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (byte) main::x#4 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::x#1 ) [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2
main::@2: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_1
main::@2_1: scope:[main] from main::@2
[7] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_2
main::@2_2: scope:[main] from main::@2_1
[8] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_3
main::@2_3: scope:[main] from main::@2_2
[9] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_4
main::@2_4: scope:[main] from main::@2_3
[10] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_5
main::@2_5: scope:[main] from main::@2_4
[11] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_6
main::@2_6: scope:[main] from main::@2_5
[12] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_7
main::@2_7: scope:[main] from main::@2_6
[13] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_8
main::@2_8: scope:[main] from main::@2_7
[14] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_9
main::@2_9: scope:[main] from main::@2_8
[15] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_10
main::@2_10: scope:[main] from main::@2_9
[16] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_11
main::@2_11: scope:[main] from main::@2_10
[17] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_12
main::@2_12: scope:[main] from main::@2_11
[18] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_13
main::@2_13: scope:[main] from main::@2_12
[19] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_14
main::@2_14: scope:[main] from main::@2_13
[20] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_15
main::@2_15: scope:[main] from main::@2_14
[21] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_16
main::@2_16: scope:[main] from main::@2_15
[22] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_17
main::@2_17: scope:[main] from main::@2_16
[23] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_18
main::@2_18: scope:[main] from main::@2_17
[24] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_19
main::@2_19: scope:[main] from main::@2_18
[25] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_20
main::@2_20: scope:[main] from main::@2_19
[26] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_21
main::@2_21: scope:[main] from main::@2_20
[27] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_22
main::@2_22: scope:[main] from main::@2_21
[28] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_23
main::@2_23: scope:[main] from main::@2_22
[29] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@2_24
main::@2_24: scope:[main] from main::@2_23
[30] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#4) ← (byte) main::x#4 [ main::x#4 ] ( main:2 [ main::x#4 ] )
to:main::@3
main::@3: scope:[main] from main::@2_24
[31] (byte) main::x#1 ← ++ (byte) main::x#4 [ main::x#1 ] ( main:2 [ main::x#1 ] )
[32] if((byte) main::x#1!=(byte/signed byte/word/signed word/dword/signed dword) 40) goto main::@1 [ main::x#1 ] ( main:2 [ main::x#1 ] )
to:main::@return
main::@return: scope:[main] from main::@3
[33] return [ ] ( main:2 [ ] )
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@2_1
(label) main::@2_10
(label) main::@2_11
(label) main::@2_12
(label) main::@2_13
(label) main::@2_14
(label) main::@2_15
(label) main::@2_16
(label) main::@2_17
(label) main::@2_18
(label) main::@2_19
(label) main::@2_2
(label) main::@2_20
(label) main::@2_21
(label) main::@2_22
(label) main::@2_23
(label) main::@2_24
(label) main::@2_3
(label) main::@2_4
(label) main::@2_5
(label) main::@2_6
(label) main::@2_7
(label) main::@2_8
(label) main::@2_9
(label) main::@3
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::line
(byte) main::x
(byte) main::x#1 reg byte x 16.5
(byte) main::x#4 reg byte x 22.00000000000001
reg byte x [ main::x#4 main::x#1 ]

View File

@ -0,0 +1,63 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
.label SCREEN = $400
ldx #0
b3:
txa
sta SCREEN+0*$28,x
txa
sta SCREEN+(0+1)*$28,x
txa
sta SCREEN+(0+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
txa
sta SCREEN+(0+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1)*$28,x
inx
cpx #$28
bne b3
rts
}

View File

@ -0,0 +1,97 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main main::@4
[5] (byte) main::x#5 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@4/(byte) main::x#1 ) [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3
main::@3: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_1
main::@3_1: scope:[main] from main::@3
[7] *((const byte*) main::SCREEN#0+++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_2
main::@3_2: scope:[main] from main::@3_1
[8] *((const byte*) main::SCREEN#0+++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_3
main::@3_3: scope:[main] from main::@3_2
[9] *((const byte*) main::SCREEN#0+++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_4
main::@3_4: scope:[main] from main::@3_3
[10] *((const byte*) main::SCREEN#0+++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_5
main::@3_5: scope:[main] from main::@3_4
[11] *((const byte*) main::SCREEN#0+++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_6
main::@3_6: scope:[main] from main::@3_5
[12] *((const byte*) main::SCREEN#0+++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_7
main::@3_7: scope:[main] from main::@3_6
[13] *((const byte*) main::SCREEN#0+++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_8
main::@3_8: scope:[main] from main::@3_7
[14] *((const byte*) main::SCREEN#0+++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_9
main::@3_9: scope:[main] from main::@3_8
[15] *((const byte*) main::SCREEN#0+++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_10
main::@3_10: scope:[main] from main::@3_9
[16] *((const byte*) main::SCREEN#0+++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_11
main::@3_11: scope:[main] from main::@3_10
[17] *((const byte*) main::SCREEN#0+++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_12
main::@3_12: scope:[main] from main::@3_11
[18] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_13
main::@3_13: scope:[main] from main::@3_12
[19] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_14
main::@3_14: scope:[main] from main::@3_13
[20] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_15
main::@3_15: scope:[main] from main::@3_14
[21] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_16
main::@3_16: scope:[main] from main::@3_15
[22] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_17
main::@3_17: scope:[main] from main::@3_16
[23] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_18
main::@3_18: scope:[main] from main::@3_17
[24] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_19
main::@3_19: scope:[main] from main::@3_18
[25] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_20
main::@3_20: scope:[main] from main::@3_19
[26] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_21
main::@3_21: scope:[main] from main::@3_20
[27] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_22
main::@3_22: scope:[main] from main::@3_21
[28] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_23
main::@3_23: scope:[main] from main::@3_22
[29] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@3_24
main::@3_24: scope:[main] from main::@3_23
[30] *((const byte*) main::SCREEN#0+++++++++++++++++++++++++++++++++++++++++++++++++(byte/signed byte/word/signed word/dword/signed dword) 0*(byte/signed byte/word/signed word/dword/signed dword) 40 + (byte) main::x#5) ← (byte) main::x#5 [ main::x#5 ] ( main:2 [ main::x#5 ] )
to:main::@4
main::@4: scope:[main] from main::@3_24
[31] (byte) main::x#1 ← ++ (byte) main::x#5 [ main::x#1 ] ( main:2 [ main::x#1 ] )
[32] if((byte) main::x#1!=(byte/signed byte/word/signed word/dword/signed dword) 40) goto main::@1 [ main::x#1 ] ( main:2 [ main::x#1 ] )
to:main::@return
main::@return: scope:[main] from main::@4
[33] return [ ] ( main:2 [ ] )
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@3
(label) main::@3_1
(label) main::@3_10
(label) main::@3_11
(label) main::@3_12
(label) main::@3_13
(label) main::@3_14
(label) main::@3_15
(label) main::@3_16
(label) main::@3_17
(label) main::@3_18
(label) main::@3_19
(label) main::@3_2
(label) main::@3_20
(label) main::@3_21
(label) main::@3_22
(label) main::@3_23
(label) main::@3_24
(label) main::@3_3
(label) main::@3_4
(label) main::@3_5
(label) main::@3_6
(label) main::@3_7
(label) main::@3_8
(label) main::@3_9
(label) main::@4
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::line
(byte) main::x
(byte) main::x#1 reg byte x 16.5
(byte) main::x#5 reg byte x 22.00000000000001
reg byte x [ main::x#5 main::x#1 ]

View File

@ -0,0 +1,10 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
jsr main
main: {
.label SCREEN = $400
b2:
inc SCREEN
jmp b2
}

View File

@ -0,0 +1,15 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main main::@2
[5] *((const byte*) main::SCREEN#0) ← ++ *((const byte*) main::SCREEN#0) [ ] ( main:2 [ ] )
to:main::@2

View File

@ -0,0 +1,357 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/unusedblockproblem.kc
// Problem with eliminating unused blocks/vars after the infinite loop (symbol line#2 not removed from symbol table)
void main() {
byte* SCREEN = $400;
while(true) {
(*SCREEN)++;
}
for(byte line: 0..24) {
SCREEN[line] = line;
}
}
Adding pre/post-modifier *((byte*) main::SCREEN) ← ++ *((byte*) main::SCREEN)
SYMBOLS
(label) @1
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@8
(label) main::@return
(byte*) main::SCREEN
(byte) main::line
Promoting word/signed word/dword/signed dword to byte* in main::SCREEN ← ((byte*)) 1024
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from
(byte*) main::SCREEN ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:main::@1
main::@1: scope:[main] from main main::@2
if(true) goto main::@2
to:main::@5
main::@2: scope:[main] from main::@1 main::@6
*((byte*) main::SCREEN) ← ++ *((byte*) main::SCREEN)
to:main::@1
main::@5: scope:[main] from main::@1
to:main::@3
main::@3: scope:[main] from main::@5 main::@7
(byte) main::line ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@4
main::@6: scope:[main] from
to:main::@2
main::@7: scope:[main] from
to:main::@3
main::@4: scope:[main] from main::@3 main::@4
*((byte*) main::SCREEN + (byte) main::line) ← (byte) main::line
(byte) main::line ← (byte) main::line + rangenext(0,24)
(bool~) main::$0 ← (byte) main::line != rangelast(0,24)
if((bool~) main::$0) goto main::@4
to:main::@8
main::@8: scope:[main] from main::@4
to:main::@return
main::@return: scope:[main] from main::@8
return
to:@return
@1: scope:[] from @begin
call main
to:@end
@end: scope:[] from @1
Removing empty block main::@5
Removing empty block main::@6
Removing empty block main::@7
Removing empty block main::@8
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:main::@1
main::@1: scope:[main] from main main::@2
(byte*) main::SCREEN#3 ← phi( main/(byte*) main::SCREEN#0 main::@2/(byte*) main::SCREEN#1 )
if(true) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte*) main::SCREEN#1 ← phi( main::@1/(byte*) main::SCREEN#3 )
*((byte*) main::SCREEN#1) ← ++ *((byte*) main::SCREEN#1)
to:main::@1
main::@3: scope:[main] from main::@1
(byte*) main::SCREEN#4 ← phi( main::@1/(byte*) main::SCREEN#3 )
(byte) main::line#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@4
main::@4: scope:[main] from main::@3 main::@4
(byte*) main::SCREEN#2 ← phi( main::@3/(byte*) main::SCREEN#4 main::@4/(byte*) main::SCREEN#2 )
(byte) main::line#2 ← phi( main::@3/(byte) main::line#0 main::@4/(byte) main::line#1 )
*((byte*) main::SCREEN#2 + (byte) main::line#2) ← (byte) main::line#2
(byte) main::line#1 ← (byte) main::line#2 + rangenext(0,24)
(bool~) main::$0 ← (byte) main::line#1 != rangelast(0,24)
if((bool~) main::$0) goto main::@4
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(byte*) main::SCREEN#1
(byte*) main::SCREEN#2
(byte*) main::SCREEN#3
(byte*) main::SCREEN#4
(byte) main::line
(byte) main::line#0
(byte) main::line#1
(byte) main::line#2
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @2
Succesful SSA optimization Pass2CullEmptyBlocks
Alias (byte*) main::SCREEN#1 = (byte*) main::SCREEN#3 (byte*) main::SCREEN#4
Succesful SSA optimization Pass2AliasElimination
Self Phi Eliminated (byte*) main::SCREEN#1
Self Phi Eliminated (byte*) main::SCREEN#2
Succesful SSA optimization Pass2SelfPhiElimination
Redundant Phi (byte*) main::SCREEN#1 (byte*) main::SCREEN#0
Redundant Phi (byte*) main::SCREEN#2 (byte*) main::SCREEN#1
Succesful SSA optimization Pass2RedundantPhiElimination
Simple Condition (bool~) main::$0 if((byte) main::line#1!=rangelast(0,24)) goto main::@4
Succesful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::SCREEN#0 = ((byte*))1024
Constant (const byte) main::line#0 = 0
Succesful SSA optimization Pass2ConstantIdentification
if() condition always true - replacing block destination if(true) goto main::@2
Succesful SSA optimization Pass2ConstantIfs
Eliminating variable (byte) main::line#2 from unused block main::@4
Eliminating variable (byte) main::line#1 and from unused block main::@4
Removing PHI-reference to removed block (main::@3) in block main::@4
Removing unused block main::@3
Removing unused block main::@4
Removing unused block main::@return
Succesful SSA optimization Pass2EliminateUnusedBlocks
Culled Empty Block (label) main::@1
Succesful SSA optimization Pass2CullEmptyBlocks
Eliminating unused constant (const byte) main::line#0
Succesful SSA optimization PassNEliminateUnusedVars
OPTIMIZING CONTROL FLOW GRAPH
Block Sequence Planned @begin @1 @end main main::@2
Block Sequence Planned @begin @1 @end main main::@2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Propagating live ranges...
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Block Sequence Planned @begin @1 @end main main::@2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@1
@1: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main [ ] ( )
to:@end
@end: scope:[] from @1
[3] phi() [ ] ( )
main: scope:[main] from @1
[4] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main main::@2
[5] *((const byte*) main::SCREEN#0) ← ++ *((const byte*) main::SCREEN#0) [ ] ( main:2 [ ] )
to:main::@2
DOMINATORS
@begin dominated by @begin
@1 dominated by @1 @begin
@end dominated by @1 @begin @end
main dominated by @1 @begin main
main::@2 dominated by @1 @begin main::@2 main
NATURAL LOOPS
Found back edge: Loop head: main::@2 tails: main::@2 blocks: null
Populated: Loop head: main::@2 tails: main::@2 blocks: main::@2
Loop head: main::@2 tails: main::@2 blocks: main::@2
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 1 loops in scope [main]
Loop head: main::@2 tails: main::@2 blocks: main::@2
Loop head: main::@2 tails: main::@2 blocks: main::@2 depth: 1
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(byte) main::line
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
jmp b2
//SEG10 main::@2
b2:
//SEG11 [5] *((const byte*) main::SCREEN#0) ← ++ *((const byte*) main::SCREEN#0) [ ] ( main:2 [ ] ) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp b2
}
REGISTER UPLIFT POTENTIAL REGISTERS
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 132 combination
Uplifting [] best 132 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG4 @1
b1:
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
jmp b2
//SEG10 main::@2
b2:
//SEG11 [5] *((const byte*) main::SCREEN#0) ← ++ *((const byte*) main::SCREEN#0) [ ] ( main:2 [ ] ) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp b2
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b2
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b1_from_bbegin:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b1:
Removing instruction bend:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@2
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::line
FINAL ASSEMBLER
Score: 96
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
//SEG2 @begin
//SEG3 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG4 @1
//SEG5 [2] call main [ ] ( )
//SEG6 [4] phi from @1 to main [phi:@1->main]
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG10 main::@2
b2:
//SEG11 [5] *((const byte*) main::SCREEN#0) ← ++ *((const byte*) main::SCREEN#0) [ ] ( main:2 [ ] ) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp b2
}

View File

@ -0,0 +1,9 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@2
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024
(byte) main::line