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

Now supporting more complex functions inlining.

This commit is contained in:
jespergravgaard 2018-05-01 22:08:23 +02:00
parent 6bd3a2dedf
commit 4e973cebc7
20 changed files with 2514 additions and 77 deletions

View File

@ -129,6 +129,8 @@ public class Compiler {
new Pass1AssertUsedVars(program).execute();
new Pass1ProcedureInline(program).execute();
//getLog().append("INLINED CONTROL FLOW GRAPH");
//getLog().append(program.getGraph().toString(program));
new Pass1EliminateUncalledProcedures(program).execute();
new PassNEliminateUnusedVars(program).execute();

View File

@ -3,11 +3,9 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementReturn;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.*;
import java.util.List;
@ -69,29 +67,31 @@ public class Pass1ProcedureInline extends Pass1Base {
// Set successors
if(procedureBlock.getDefaultSuccessor() != null) {
LabelRef procBlockSuccessorRef = procedureBlock.getDefaultSuccessor();
if(procBlockSuccessorRef.getFullName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) {
// Set successor of the @return block to the rest block
inlineBlock.setDefaultSuccessor(restBlockLabel.getRef());
} else {
Label procBlockSuccessor = getScope().getLabel(procBlockSuccessorRef);
String inlinedSuccessorName = getInlineSymbolName(procedure, procBlockSuccessor, serial);
Label inlinedSuccessorLabel = callScope.getLabel(inlinedSuccessorName);
inlineBlock.setDefaultSuccessor(inlinedSuccessorLabel.getRef());
}
LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel);
inlineBlock.setDefaultSuccessor(inlinedSuccessor);
}
if(procedureBlock.getConditionalSuccessor() != null) {
throw new CompileError("Not implemented Inline function conditional successors");
LabelRef procBlockSuccessorRef = procedureBlock.getConditionalSuccessor();
LabelRef inlinedSuccessor = inlineSuccessor(procBlockSuccessorRef, procedure, callScope, serial, restBlockLabel);
inlineBlock.setConditionalSuccessor(inlinedSuccessor);
}
}
// Create a new block for the rest of the calling block
ControlFlowBlock restBlock = new ControlFlowBlock(restBlockLabel.getRef(), callScope.getRef());
blocksIt.add(restBlock);
// Generate return assignment
if(call.getlValue() != null) {
if(!procedure.getReturnType().equals(SymbolType.VOID)) {
Variable procReturnVar = procedure.getVariable("return");
String inlinedReturnVarName = getInlineSymbolName(procedure, procReturnVar, serial);
Variable inlinedReturnVar = callScope.getVariable(inlinedReturnVarName);
restBlock.addStatement(new StatementAssignment(call.getlValue(), inlinedReturnVar.getRef()));
} else {
// Remove the tmp var receiving the result
LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) {
callScope.remove(getScope().getVariable((VariableRef) lValue));
call.setlValue(null);
}
}
// Copy the rest of the calling block to the new block
while(statementsIt.hasNext()) {
@ -116,6 +116,20 @@ public class Pass1ProcedureInline extends Pass1Base {
return false;
}
private LabelRef inlineSuccessor(LabelRef procBlockSuccessorRef, Procedure procedure, Scope callScope, int serial, Label restBlockLabel) {
LabelRef inlinedSuccessor;
if(procBlockSuccessorRef.getFullName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) {
// Set successor of the @return block to the rest block
inlinedSuccessor = restBlockLabel.getRef();
} else {
Label procBlockSuccessor = getScope().getLabel(procBlockSuccessorRef);
String inlinedSuccessorName = getInlineSymbolName(procedure, procBlockSuccessor, serial);
Label inlinedSuccessorLabel = callScope.getLabel(inlinedSuccessorName);
inlinedSuccessor = inlinedSuccessorLabel.getRef();
}
return inlinedSuccessor;
}
/**
* Find the next inline serial number for the procedure being inlined in the calling scope.
@ -150,54 +164,66 @@ public class Pass1ProcedureInline extends Pass1Base {
Statement inlinedStatement;
if(procStatement instanceof StatementAssignment) {
StatementAssignment procAssignment = (StatementAssignment) procStatement;
LValue inlineLValue = inlineLValue(procAssignment.getlValue(), procedure, callScope, serial);
RValue inlineRValue1 = inlineRValue(procAssignment.getrValue1(), procedure, callScope, serial);
RValue inlineRValue2 = inlineRValue(procAssignment.getrValue2(), procedure, callScope, serial);
inlinedStatement = new StatementAssignment(inlineLValue, inlineRValue1, procAssignment.getOperator(), inlineRValue2);
inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2());
} else if(procStatement instanceof StatementConditionalJump) {
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
LabelRef procDestinationRef = procConditional.getDestination();
Label procDestination = getScope().getLabel(procDestinationRef);
Label inlinedDest = procDestination;
if(procDestination.getScope().equals(procedure)) {
String inlineSymbolName = getInlineSymbolName(procedure, procDestination, serial);
inlinedDest = callScope.getLabel(inlineSymbolName);
}
inlinedStatement = new StatementConditionalJump(procConditional.getrValue1(), procConditional.getOperator(), procConditional.getrValue2(), inlinedDest.getRef());
} else if(procStatement instanceof StatementReturn) {
// No statement needed
return null;
} else {
throw new CompileError("Statement type of Inline function not handled " + procStatement);
}
if(inlinedStatement!=null) {
ValueReplacer.executeAll(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
}
return inlinedStatement;
}
/**
* Find/create a new LValue to use when inlining an LValue from a procedure
*
* @param lValue The LValue bein used inside the procedure being inlined
* @param serial The serial number (counted up for each inlined call to the same function within the called calling scope).
* @return The LValue to use where the procedure is inlined.
* Ensures that all VariableRefs pointing to variables in the procedure being inlined are converted to refs to the new inlined variables
* Also copies all intermediate RValue objects to ensure they are not references to objects from the original statements in the procedure being inlined
*/
private LValue inlineLValue(LValue lValue, Procedure procedure, Scope callScope, int serial) {
return (LValue) inlineRValue(lValue, procedure, callScope, serial);
}
private class RValueInliner implements ValueReplacer.Replacer {
/**
* Find/create a new RValue to use when inlining an RValue from a procedure
*
* @param rValue The RValue bein used inside the procedure being inlined
* @param serial The serial number (counted up for each inlined call to the same function within the called calling scope).
* @return The RValue to use where the procedure is inlined.
*/
private RValue inlineRValue(RValue rValue, Procedure procedure, Scope callScope, int serial) {
if(rValue == null) {
return null;
} else if(rValue instanceof VariableRef) {
VariableRef procVarRef = (VariableRef) rValue;
Variable procVar = getScope().getVariable(procVarRef);
if(procVar.getScope().equals(procedure)) {
String inlineSymbolName = getInlineSymbolName(procedure, procVar, serial);
Variable inlineVar = callScope.getVariable(inlineSymbolName);
return inlineVar.getRef();
} else {
return procVarRef;
/** The scope where the precedure is being inlined into. */
private final Scope callScope;
/** The procedure being inlined. */
private final Procedure procedure;
/** The serial number (counted up for each inlined call to the same function within the called calling scope) */
private final int serial;
public RValueInliner(Procedure procedure, int serial, Scope callScope) {
this.procedure = procedure;
this.serial = serial;
this.callScope = callScope;
}
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
RValue rValue = replaceable.get();
if(rValue instanceof VariableRef) {
VariableRef procVarRef = (VariableRef) rValue;
Variable procVar = Pass1ProcedureInline.this.getScope().getVariable(procVarRef);
if(procVar.getScope().equals(procedure)) {
String inlineSymbolName = Pass1ProcedureInline.this.getInlineSymbolName(procedure, procVar, serial);
Variable inlineVar = callScope.getVariable(inlineSymbolName);
replaceable.set(inlineVar.getRef());
}
} else if(rValue instanceof PointerDereferenceSimple) {
replaceable.set(new PointerDereferenceSimple(((PointerDereferenceSimple) rValue).getPointer()));
} else if(rValue instanceof PointerDereferenceIndexed) {
replaceable.set(new PointerDereferenceIndexed(((PointerDereferenceIndexed) rValue).getPointer(), ((PointerDereferenceIndexed) rValue).getIndex()));
} else if(rValue instanceof CastValue) {
replaceable.set(new CastValue(((CastValue) rValue).getToType(), ((CastValue) rValue).getValue()));
}
} else if(rValue instanceof ConstantValue) {
return rValue;
} else {
throw new CompileError("Symbol Type of Inline function not handled " + rValue);
}
}

View File

@ -50,7 +50,7 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
) {
VariableRef tempVar = (VariableRef) assignment.getrValue2();
StatementAssignment tempAssignment = assignments.get(tempVar);
if(usages.get(tempVar) == 1 && tempAssignment.getOperator() != null) {
if(usages.get(tempVar) == 1 && tempAssignment!=null && tempAssignment.getOperator() != null) {
switch(tempAssignment.getOperator().getOperator()) {
case "<":
createInverse(">=", assignment, tempAssignment);

View File

@ -24,32 +24,42 @@ public class ValueReplacer {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
if(statement instanceof StatementAssignment) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementCall) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
StatementCall call = (StatementCall) statement;
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, statementsIt, block);
}
}
} else if(statement instanceof StatementConditionalJump) {
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementReturn) {
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, statementsIt, block);
int size = phiVariable.getValues().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, statementsIt, block);
}
}
executeAll(statement, replacer, statementsIt, block);
}
}
}
/**
* Execute a replacer on all replaceable values in a statement
*
* @param statement The statement
* @param replacer The replacer to execute
*/
public static void executeAll(Statement statement, Replacer replacer, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
if(statement instanceof StatementAssignment) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue1((StatementAssignment) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableRValue2((StatementAssignment) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementCall) {
executeAll(new ReplaceableLValue((StatementLValue) statement), replacer, statement, statementsIt, block);
StatementCall call = (StatementCall) statement;
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceableCallParameter(call, i), replacer, statement, statementsIt, block);
}
}
} else if(statement instanceof StatementConditionalJump) {
executeAll(new ReplaceableCondRValue1((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
executeAll(new ReplaceableCondRValue2((StatementConditionalJump) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementReturn) {
executeAll(new ReplaceableReturn((StatementReturn) statement), replacer, statement, statementsIt, block);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
executeAll(new ReplaceablePhiVariable(phiVariable), replacer, statement, statementsIt, block);
int size = phiVariable.getValues().size();
for(int i = 0; i < size; i++) {
executeAll(new ReplaceablePhiValue(phiVariable, i), replacer, statement, statementsIt, block);
}
}
}

View File

@ -44,11 +44,26 @@ public class TestPrograms {
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
}
@Test
public void testInlineFunctionPrint() throws IOException, URISyntaxException {
compileAndCompare("inline-function-print");
}
@Test
public void testInlineFunctionIf() throws IOException, URISyntaxException {
compileAndCompare("inline-function-if");
}
@Test
public void testInlineFunction() throws IOException, URISyntaxException {
compileAndCompare("inline-function");
}
@Test
public void testInlineFunctionMin() throws IOException, URISyntaxException {
compileAndCompare("inline-function-min");
}
@Test
public void testCompoundAssignment() throws IOException, URISyntaxException {
compileAndCompare("compound-assignment");

View File

@ -0,0 +1,17 @@
// Test inlining a slightly complex print function (containing an if)
byte* screen = $400;
void main() {
screen[0] = toUpper('c',true);
screen[1] = toUpper('m',false);
}
inline byte toUpper(byte ch, bool bo) {
byte res = ch;
if(bo) {
res += $40;
}
return res;
}

View File

@ -0,0 +1,13 @@
// Test minimal inline function
byte* screen = $0400;
void main() {
screen[0] = sum(2, 1);
screen[1] = sum(10, 3);
screen[2] = sum(4, 8);
}
inline byte sum( byte a, byte b) {
return a+b;
}

View File

@ -0,0 +1,18 @@
// TEst inlining a slightly complex print function (containing a loop)
byte* screen = $400;
void main() {
byte* hello = "hello world!@";
print(screen, hello);
print(screen+2*40, hello);
}
inline void print(byte* at, byte* msg) {
byte j=0;
for(byte i=0; msg[i]!='@'; i++) {
at[j] = msg[i];
j += 2;
}
}

View File

@ -0,0 +1,15 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label screen = $400
jsr main
main: {
.const toUpper1_ch = 'c'
.const toUpper2_ch = 'm'
.const toUpper1_res = toUpper1_ch+$40
lda #toUpper1_res
sta screen+0
lda #toUpper2_ch
sta screen+1
rts
}

View File

@ -0,0 +1,27 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::toUpper1
main::toUpper1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main::toUpper1
[6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] )
to:main::toUpper2
main::toUpper2: scope:[main] from main::@1
[7] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::toUpper2
[8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@2
[9] return [ ] ( main:2 [ ] )
to:@return

View File

@ -0,0 +1,607 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/inline-function-if.kc
// Test inlining a slightly complex print function (containing an if)
byte* screen = $400;
void main() {
screen[0] = toUpper('c',true);
screen[1] = toUpper('m',false);
}
inline byte toUpper(byte ch, bool bo) {
byte res = ch;
if(bo) {
res += $40;
}
return res;
}
SYMBOLS
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(byte~) main::$0
(byte~) main::$1
(label) main::@return
(byte*) screen
inline (byte()) toUpper((byte) toUpper::ch , (bool) toUpper::bo)
(bool~) toUpper::$0
(label) toUpper::@1
(label) toUpper::@2
(label) toUpper::@3
(label) toUpper::@return
(bool) toUpper::bo
(byte) toUpper::ch
(byte) toUpper::res
(byte) toUpper::return
Promoting word/signed word/dword/signed dword to byte* in screen ← ((byte*)) 1024
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) screen ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@1
main: scope:[main] from
(byte~) main::$0 ← call toUpper (byte) 'c' true
*((byte*) screen + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$0
(byte~) main::$1 ← call toUpper (byte) 'm' false
*((byte*) screen + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$1
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
to:@2
toUpper: scope:[toUpper] from
(byte) toUpper::res ← (byte) toUpper::ch
(bool~) toUpper::$0 ← ! (bool) toUpper::bo
if((bool~) toUpper::$0) goto toUpper::@1
to:toUpper::@2
toUpper::@1: scope:[toUpper] from toUpper toUpper::@2
(byte) toUpper::return ← (byte) toUpper::res
to:toUpper::@return
toUpper::@2: scope:[toUpper] from toUpper
(byte) toUpper::res ← (byte) toUpper::res + (byte/signed byte/word/signed word/dword/signed dword) 64
to:toUpper::@1
toUpper::@return: scope:[toUpper] from toUpper::@1 toUpper::@3
(byte) toUpper::return ← (byte) toUpper::return
return (byte) toUpper::return
to:@return
toUpper::@3: scope:[toUpper] from
to:toUpper::@return
@2: scope:[] from @1
call main
to:@end
@end: scope:[] from @2
Inlined call (byte~) main::$0 ← call toUpper (byte) 'c' true
Inlined call (byte~) main::$1 ← call toUpper (byte) 'm' false
Removing unused procedure toUpper
Removing empty block main::toUpper1_@3
Removing empty block main::toUpper2_@3
Removing empty block @1
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
(byte*) screen#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@2
main: scope:[main] from @2
(byte*) screen#11 ← phi( @2/(byte*) screen#12 )
(byte) main::toUpper1_ch#0 ← (byte) 'c'
(bool) main::toUpper1_bo#0 ← true
to:main::toUpper1
main::toUpper1: scope:[main] from main
(byte*) screen#7 ← phi( main/(byte*) screen#11 )
(bool) main::toUpper1_bo#1 ← phi( main/(bool) main::toUpper1_bo#0 )
(byte) main::toUpper1_ch#1 ← phi( main/(byte) main::toUpper1_ch#0 )
(byte) main::toUpper1_res#0 ← (byte) main::toUpper1_ch#1
(bool) main::toUpper1_$0#0 ← ! (bool) main::toUpper1_bo#1
if((bool) main::toUpper1_$0#0) goto main::toUpper1_@1
to:main::toUpper1_@2
main::toUpper1_@1: scope:[main] from main::toUpper1 main::toUpper1_@2
(byte*) screen#5 ← phi( main::toUpper1/(byte*) screen#7 main::toUpper1_@2/(byte*) screen#8 )
(byte) main::toUpper1_res#2 ← phi( main::toUpper1/(byte) main::toUpper1_res#0 main::toUpper1_@2/(byte) main::toUpper1_res#1 )
(byte) main::toUpper1_return#0 ← (byte) main::toUpper1_res#2
to:main::toUpper1_@return
main::toUpper1_@2: scope:[main] from main::toUpper1
(byte*) screen#8 ← phi( main::toUpper1/(byte*) screen#7 )
(byte) main::toUpper1_res#3 ← phi( main::toUpper1/(byte) main::toUpper1_res#0 )
(byte) main::toUpper1_res#1 ← (byte) main::toUpper1_res#3 + (byte/signed byte/word/signed word/dword/signed dword) 64
to:main::toUpper1_@1
main::toUpper1_@return: scope:[main] from main::toUpper1_@1
(byte*) screen#3 ← phi( main::toUpper1_@1/(byte*) screen#5 )
(byte) main::toUpper1_return#2 ← phi( main::toUpper1_@1/(byte) main::toUpper1_return#0 )
(byte) main::toUpper1_return#1 ← (byte) main::toUpper1_return#2
to:main::@1
main::@1: scope:[main] from main::toUpper1_@return
(byte*) screen#1 ← phi( main::toUpper1_@return/(byte*) screen#3 )
(byte) main::toUpper1_return#3 ← phi( main::toUpper1_@return/(byte) main::toUpper1_return#1 )
(byte~) main::$0 ← (byte) main::toUpper1_return#3
*((byte*) screen#1 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$0
(byte) main::toUpper2_ch#0 ← (byte) 'm'
(bool) main::toUpper2_bo#0 ← false
to:main::toUpper2
main::toUpper2: scope:[main] from main::@1
(byte*) screen#9 ← phi( main::@1/(byte*) screen#1 )
(bool) main::toUpper2_bo#1 ← phi( main::@1/(bool) main::toUpper2_bo#0 )
(byte) main::toUpper2_ch#1 ← phi( main::@1/(byte) main::toUpper2_ch#0 )
(byte) main::toUpper2_res#0 ← (byte) main::toUpper2_ch#1
(bool) main::toUpper2_$0#0 ← ! (bool) main::toUpper2_bo#1
if((bool) main::toUpper2_$0#0) goto main::toUpper2_@1
to:main::toUpper2_@2
main::toUpper2_@1: scope:[main] from main::toUpper2 main::toUpper2_@2
(byte*) screen#6 ← phi( main::toUpper2/(byte*) screen#9 main::toUpper2_@2/(byte*) screen#10 )
(byte) main::toUpper2_res#2 ← phi( main::toUpper2/(byte) main::toUpper2_res#0 main::toUpper2_@2/(byte) main::toUpper2_res#1 )
(byte) main::toUpper2_return#0 ← (byte) main::toUpper2_res#2
to:main::toUpper2_@return
main::toUpper2_@2: scope:[main] from main::toUpper2
(byte*) screen#10 ← phi( main::toUpper2/(byte*) screen#9 )
(byte) main::toUpper2_res#3 ← phi( main::toUpper2/(byte) main::toUpper2_res#0 )
(byte) main::toUpper2_res#1 ← (byte) main::toUpper2_res#3 + (byte/signed byte/word/signed word/dword/signed dword) 64
to:main::toUpper2_@1
main::toUpper2_@return: scope:[main] from main::toUpper2_@1
(byte*) screen#4 ← phi( main::toUpper2_@1/(byte*) screen#6 )
(byte) main::toUpper2_return#2 ← phi( main::toUpper2_@1/(byte) main::toUpper2_return#0 )
(byte) main::toUpper2_return#1 ← (byte) main::toUpper2_return#2
to:main::@2
main::@2: scope:[main] from main::toUpper2_@return
(byte*) screen#2 ← phi( main::toUpper2_@return/(byte*) screen#4 )
(byte) main::toUpper2_return#3 ← phi( main::toUpper2_@return/(byte) main::toUpper2_return#1 )
(byte~) main::$1 ← (byte) main::toUpper2_return#3
*((byte*) screen#2 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$1
to:main::@return
main::@return: scope:[main] from main::@2
return
to:@return
@2: scope:[] from @begin
(byte*) screen#12 ← phi( @begin/(byte*) screen#0 )
call main param-assignment
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(void()) main()
(byte~) main::$0
(byte~) main::$1
(label) main::@1
(label) main::@2
(label) main::@return
(label) main::toUpper1
(bool~) main::toUpper1_$0
(bool) main::toUpper1_$0#0
(label) main::toUpper1_@1
(label) main::toUpper1_@2
(label) main::toUpper1_@return
(bool) main::toUpper1_bo
(bool) main::toUpper1_bo#0
(bool) main::toUpper1_bo#1
(byte) main::toUpper1_ch
(byte) main::toUpper1_ch#0
(byte) main::toUpper1_ch#1
(byte) main::toUpper1_res
(byte) main::toUpper1_res#0
(byte) main::toUpper1_res#1
(byte) main::toUpper1_res#2
(byte) main::toUpper1_res#3
(byte) main::toUpper1_return
(byte) main::toUpper1_return#0
(byte) main::toUpper1_return#1
(byte) main::toUpper1_return#2
(byte) main::toUpper1_return#3
(label) main::toUpper2
(bool~) main::toUpper2_$0
(bool) main::toUpper2_$0#0
(label) main::toUpper2_@1
(label) main::toUpper2_@2
(label) main::toUpper2_@return
(bool) main::toUpper2_bo
(bool) main::toUpper2_bo#0
(bool) main::toUpper2_bo#1
(byte) main::toUpper2_ch
(byte) main::toUpper2_ch#0
(byte) main::toUpper2_ch#1
(byte) main::toUpper2_res
(byte) main::toUpper2_res#0
(byte) main::toUpper2_res#1
(byte) main::toUpper2_res#2
(byte) main::toUpper2_res#3
(byte) main::toUpper2_return
(byte) main::toUpper2_return#0
(byte) main::toUpper2_return#1
(byte) main::toUpper2_return#2
(byte) main::toUpper2_return#3
(byte*) screen
(byte*) screen#0
(byte*) screen#1
(byte*) screen#10
(byte*) screen#11
(byte*) screen#12
(byte*) screen#2
(byte*) screen#3
(byte*) screen#4
(byte*) screen#5
(byte*) screen#6
(byte*) screen#7
(byte*) screen#8
(byte*) screen#9
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @3
Succesful SSA optimization Pass2CullEmptyBlocks
Not aliassing across scopes: screen#11 screen#12
Alias (byte) main::toUpper1_ch#0 = (byte) main::toUpper1_ch#1 (byte) main::toUpper1_res#0 (byte) main::toUpper1_res#3
Alias (bool) main::toUpper1_bo#0 = (bool) main::toUpper1_bo#1
Alias (byte*) screen#11 = (byte*) screen#7 (byte*) screen#8
Alias (byte) main::toUpper1_return#0 = (byte) main::toUpper1_res#2 (byte) main::toUpper1_return#2 (byte) main::toUpper1_return#1 (byte) main::toUpper1_return#3 (byte~) main::$0
Alias (byte*) screen#1 = (byte*) screen#3 (byte*) screen#5 (byte*) screen#9 (byte*) screen#10
Alias (byte) main::toUpper2_ch#0 = (byte) main::toUpper2_ch#1 (byte) main::toUpper2_res#0 (byte) main::toUpper2_res#3
Alias (bool) main::toUpper2_bo#0 = (bool) main::toUpper2_bo#1
Alias (byte) main::toUpper2_return#0 = (byte) main::toUpper2_res#2 (byte) main::toUpper2_return#2 (byte) main::toUpper2_return#1 (byte) main::toUpper2_return#3 (byte~) main::$1
Alias (byte*) screen#2 = (byte*) screen#4 (byte*) screen#6
Alias (byte*) screen#0 = (byte*) screen#12
Succesful SSA optimization Pass2AliasElimination
Not aliassing across scopes: screen#11 screen#0
Alias (byte*) screen#1 = (byte*) screen#11 (byte*) screen#2
Succesful SSA optimization Pass2AliasElimination
Not aliassing across scopes: screen#1 screen#0
Redundant Phi (byte*) screen#1 (byte*) screen#0
Succesful SSA optimization Pass2RedundantPhiElimination
Rewriting ! if()-condition to reversed if() (bool) main::toUpper1_$0#0 ← ! (bool) main::toUpper1_bo#0
Succesful SSA optimization Pass2ConditionalAndOrRewriting
Rewriting ! if()-condition to reversed if() (bool) main::toUpper2_$0#0 ← ! (bool) main::toUpper2_bo#0
Succesful SSA optimization Pass2ConditionalAndOrRewriting
Constant (const byte*) screen#0 = ((byte*))1024
Constant (const byte) main::toUpper1_ch#0 = 'c'
Constant (const bool) main::toUpper1_bo#0 = true
Constant (const byte) main::toUpper2_ch#0 = 'm'
Constant (const bool) main::toUpper2_bo#0 = false
Succesful SSA optimization Pass2ConstantIdentification
Constant (const byte) main::toUpper1_res#1 = main::toUpper1_ch#0+64
Constant (const byte) main::toUpper2_res#1 = main::toUpper2_ch#0+64
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(screen#0+0)
Consolidated array index constant in *(screen#0+1)
Succesful SSA optimization Pass2ConstantAdditionElimination
Removing PHI-reference to removed block (main::toUpper1) in block main::toUpper1_@1
if() condition always true - replacing block destination if((const bool) main::toUpper1_bo#0) goto main::toUpper1_@2
if() condition always false - eliminating if((const bool) main::toUpper2_bo#0) goto main::toUpper2_@2
Succesful SSA optimization Pass2ConstantIfs
Eliminating unused constant (const bool) main::toUpper1_bo#0
Eliminating unused constant (const bool) main::toUpper2_bo#0
Succesful SSA optimization PassNEliminateUnusedVars
Removing PHI-reference to removed block (main::toUpper2_@2) in block main::toUpper2_@1
Removing unused block main::toUpper2_@2
Succesful SSA optimization Pass2EliminateUnusedBlocks
Culled Empty Block (label) main::toUpper1_@2
Culled Empty Block (label) main::toUpper1_@return
Culled Empty Block (label) main::toUpper2_@return
Succesful SSA optimization Pass2CullEmptyBlocks
Redundant Phi (byte) main::toUpper1_return#0 (const byte) main::toUpper1_res#1
Redundant Phi (byte) main::toUpper2_return#0 (const byte) main::toUpper2_ch#0
Succesful SSA optimization Pass2RedundantPhiElimination
Eliminating unused constant (const byte) main::toUpper2_res#1
Succesful SSA optimization PassNEliminateUnusedVars
Culled Empty Block (label) main::toUpper1_@1
Culled Empty Block (label) main::toUpper2_@1
Succesful SSA optimization Pass2CullEmptyBlocks
OPTIMIZING CONTROL FLOW GRAPH
Block Sequence Planned @begin @2 @end main main::toUpper1 main::@1 main::toUpper2 main::@2 main::@return
Block Sequence Planned @begin @2 @end main main::toUpper1 main::@1 main::toUpper2 main::@2 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::toUpper1
Adding NOP phi() at start of main::toUpper2
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 @2 @end main main::toUpper1 main::@1 main::toUpper2 main::@2 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::toUpper1
Adding NOP phi() at start of main::toUpper2
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::toUpper1
main::toUpper1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main::toUpper1
[6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] )
to:main::toUpper2
main::toUpper2: scope:[main] from main::@1
[7] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::toUpper2
[8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@2
[9] return [ ] ( main:2 [ ] )
to:@return
DOMINATORS
@begin dominated by @begin
@2 dominated by @2 @begin
@end dominated by @2 @begin @end
main dominated by @2 @begin main
main::toUpper1 dominated by @2 main::toUpper1 @begin main
main::@1 dominated by @2 main::toUpper1 @begin main::@1 main
main::toUpper2 dominated by @2 main::toUpper1 @begin main::toUpper2 main::@1 main
main::@2 dominated by @2 main::toUpper1 @begin main::toUpper2 main::@1 main::@2 main
main::@return dominated by main::@return @2 main::toUpper1 @begin main::toUpper2 main::@1 main::@2 main
NATURAL LOOPS
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 0 loops in scope [main]
VARIABLE REGISTER WEIGHTS
(void()) main()
(bool~) main::toUpper1_$0
(bool) main::toUpper1_bo
(byte) main::toUpper1_ch
(byte) main::toUpper1_res
(byte) main::toUpper1_return
(bool~) main::toUpper2_$0
(bool) main::toUpper2_bo
(byte) main::toUpper2_ch
(byte) main::toUpper2_res
(byte) main::toUpper2_return
(byte*) screen
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.const toUpper1_ch = 'c'
.const toUpper2_ch = 'm'
.const toUpper1_res = toUpper1_ch+$40
//SEG10 [5] phi from main to main::toUpper1 [phi:main->main::toUpper1]
toUpper1_from_main:
jmp toUpper1
//SEG11 main::toUpper1
toUpper1:
jmp b1
//SEG12 main::@1
b1:
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper1_res
sta screen+0
//SEG14 [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2]
toUpper2_from_b1:
jmp toUpper2
//SEG15 main::toUpper2
toUpper2:
jmp b2
//SEG16 main::@2
b2:
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper2_ch
sta screen+1
jmp breturn
//SEG18 main::@return
breturn:
//SEG19 [9] return [ ] ( main:2 [ ] )
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 99 combination
Uplifting [] best 99 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.const toUpper1_ch = 'c'
.const toUpper2_ch = 'm'
.const toUpper1_res = toUpper1_ch+$40
//SEG10 [5] phi from main to main::toUpper1 [phi:main->main::toUpper1]
toUpper1_from_main:
jmp toUpper1
//SEG11 main::toUpper1
toUpper1:
jmp b1
//SEG12 main::@1
b1:
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper1_res
sta screen+0
//SEG14 [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2]
toUpper2_from_b1:
jmp toUpper2
//SEG15 main::toUpper2
toUpper2:
jmp b2
//SEG16 main::@2
b2:
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper2_ch
sta screen+1
jmp breturn
//SEG18 main::@return
breturn:
//SEG19 [9] return [ ] ( main:2 [ ] )
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp toUpper1
Removing instruction jmp b1
Removing instruction jmp toUpper2
Removing instruction jmp b2
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b2_from_bbegin:
Removing instruction main_from_b2:
Removing instruction bend_from_b2:
Removing instruction toUpper1_from_main:
Removing instruction toUpper1:
Removing instruction toUpper2_from_b1:
Removing instruction toUpper2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction b1:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(label) main::toUpper1
(bool~) main::toUpper1_$0
(bool) main::toUpper1_bo
(byte) main::toUpper1_ch
(const byte) main::toUpper1_ch#0 toUpper1_ch = (byte) 'c'
(byte) main::toUpper1_res
(const byte) main::toUpper1_res#1 toUpper1_res = (const byte) main::toUpper1_ch#0+(byte/signed byte/word/signed word/dword/signed dword) 64
(byte) main::toUpper1_return
(label) main::toUpper2
(bool~) main::toUpper2_$0
(bool) main::toUpper2_bo
(byte) main::toUpper2_ch
(const byte) main::toUpper2_ch#0 toUpper2_ch = (byte) 'm'
(byte) main::toUpper2_res
(byte) main::toUpper2_return
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
FINAL ASSEMBLER
Score: 24
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
//SEG4 @2
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
//SEG8 @end
//SEG9 main
main: {
.const toUpper1_ch = 'c'
.const toUpper2_ch = 'm'
.const toUpper1_res = toUpper1_ch+$40
//SEG10 [5] phi from main to main::toUpper1 [phi:main->main::toUpper1]
//SEG11 main::toUpper1
//SEG12 main::@1
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::toUpper1_res#1 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper1_res
sta screen+0
//SEG14 [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2]
//SEG15 main::toUpper2
//SEG16 main::@2
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #toUpper2_ch
sta screen+1
//SEG18 main::@return
//SEG19 [9] return [ ] ( main:2 [ ] )
rts
}

View File

@ -0,0 +1,25 @@
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(label) main::toUpper1
(bool~) main::toUpper1_$0
(bool) main::toUpper1_bo
(byte) main::toUpper1_ch
(const byte) main::toUpper1_ch#0 toUpper1_ch = (byte) 'c'
(byte) main::toUpper1_res
(const byte) main::toUpper1_res#1 toUpper1_res = (const byte) main::toUpper1_ch#0+(byte/signed byte/word/signed word/dword/signed dword) 64
(byte) main::toUpper1_return
(label) main::toUpper2
(bool~) main::toUpper2_$0
(bool) main::toUpper2_bo
(byte) main::toUpper2_ch
(const byte) main::toUpper2_ch#0 toUpper2_ch = (byte) 'm'
(byte) main::toUpper2_res
(byte) main::toUpper2_return
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024

View File

@ -0,0 +1,23 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label screen = $400
jsr main
main: {
.const sum1_a = 2
.const sum1_b = 1
.const sum2_a = $a
.const sum2_b = 3
.const sum3_a = 4
.const sum3_b = 8
.const sum1_return = sum1_a+sum1_b
.const sum2_return = sum2_a+sum2_b
.const sum3_return = sum3_a+sum3_b
lda #sum1_return
sta screen+0
lda #sum2_return
sta screen+1
lda #sum3_return
sta screen+2
rts
}

View File

@ -0,0 +1,33 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::sum1
main::sum1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main::sum1
[6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] )
to:main::sum2
main::sum2: scope:[main] from main::@1
[7] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::sum2
[8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] )
to:main::sum3
main::sum3: scope:[main] from main::@2
[9] phi() [ ] ( main:2 [ ] )
to:main::@3
main::@3: scope:[main] from main::sum3
[10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@3
[11] return [ ] ( main:2 [ ] )
to:@return

View File

@ -0,0 +1,650 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/inline-function-min.kc
// Test minimal inline function
byte* screen = $0400;
void main() {
screen[0] = sum(2, 1);
screen[1] = sum(10, 3);
screen[2] = sum(4, 8);
}
inline byte sum( byte a, byte b) {
return a+b;
}
SYMBOLS
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(byte~) main::$0
(byte~) main::$1
(byte~) main::$2
(label) main::@return
(byte*) screen
inline (byte()) sum((byte) sum::a , (byte) sum::b)
(byte~) sum::$0
(label) sum::@1
(label) sum::@return
(byte) sum::a
(byte) sum::b
(byte) sum::return
Promoting word/signed word/dword/signed dword to byte* in screen ← ((byte*)) 1024
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) screen ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@1
main: scope:[main] from
(byte~) main::$0 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 2 (byte/signed byte/word/signed word/dword/signed dword) 1
*((byte*) screen + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$0
(byte~) main::$1 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 10 (byte/signed byte/word/signed word/dword/signed dword) 3
*((byte*) screen + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$1
(byte~) main::$2 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 4 (byte/signed byte/word/signed word/dword/signed dword) 8
*((byte*) screen + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$2
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
to:@2
sum: scope:[sum] from
(byte~) sum::$0 ← (byte) sum::a + (byte) sum::b
(byte) sum::return ← (byte~) sum::$0
to:sum::@return
sum::@return: scope:[sum] from sum sum::@1
(byte) sum::return ← (byte) sum::return
return (byte) sum::return
to:@return
sum::@1: scope:[sum] from
to:sum::@return
@2: scope:[] from @1
call main
to:@end
@end: scope:[] from @2
Inlined call (byte~) main::$0 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 2 (byte/signed byte/word/signed word/dword/signed dword) 1
Inlined call (byte~) main::$1 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 10 (byte/signed byte/word/signed word/dword/signed dword) 3
Inlined call (byte~) main::$2 ← call sum (byte/signed byte/word/signed word/dword/signed dword) 4 (byte/signed byte/word/signed word/dword/signed dword) 8
Removing unused procedure sum
Removing empty block main::sum1_@1
Removing empty block main::sum2_@1
Removing empty block main::sum3_@1
Removing empty block @1
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
(byte*) screen#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@2
main: scope:[main] from @2
(byte*) screen#10 ← phi( @2/(byte*) screen#11 )
(byte) main::sum1_a#0 ← (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::sum1_b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 1
to:main::sum1
main::sum1: scope:[main] from main
(byte*) screen#7 ← phi( main/(byte*) screen#10 )
(byte) main::sum1_b#1 ← phi( main/(byte) main::sum1_b#0 )
(byte) main::sum1_a#1 ← phi( main/(byte) main::sum1_a#0 )
(byte) main::sum1_$0#0 ← (byte) main::sum1_a#1 + (byte) main::sum1_b#1
(byte) main::sum1_return#0 ← (byte) main::sum1_$0#0
to:main::sum1_@return
main::sum1_@return: scope:[main] from main::sum1
(byte*) screen#4 ← phi( main::sum1/(byte*) screen#7 )
(byte) main::sum1_return#2 ← phi( main::sum1/(byte) main::sum1_return#0 )
(byte) main::sum1_return#1 ← (byte) main::sum1_return#2
to:main::@1
main::@1: scope:[main] from main::sum1_@return
(byte*) screen#1 ← phi( main::sum1_@return/(byte*) screen#4 )
(byte) main::sum1_return#3 ← phi( main::sum1_@return/(byte) main::sum1_return#1 )
(byte~) main::$0 ← (byte) main::sum1_return#3
*((byte*) screen#1 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$0
(byte) main::sum2_a#0 ← (byte/signed byte/word/signed word/dword/signed dword) 10
(byte) main::sum2_b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 3
to:main::sum2
main::sum2: scope:[main] from main::@1
(byte*) screen#8 ← phi( main::@1/(byte*) screen#1 )
(byte) main::sum2_b#1 ← phi( main::@1/(byte) main::sum2_b#0 )
(byte) main::sum2_a#1 ← phi( main::@1/(byte) main::sum2_a#0 )
(byte) main::sum2_$0#0 ← (byte) main::sum2_a#1 + (byte) main::sum2_b#1
(byte) main::sum2_return#0 ← (byte) main::sum2_$0#0
to:main::sum2_@return
main::sum2_@return: scope:[main] from main::sum2
(byte*) screen#5 ← phi( main::sum2/(byte*) screen#8 )
(byte) main::sum2_return#2 ← phi( main::sum2/(byte) main::sum2_return#0 )
(byte) main::sum2_return#1 ← (byte) main::sum2_return#2
to:main::@2
main::@2: scope:[main] from main::sum2_@return
(byte*) screen#2 ← phi( main::sum2_@return/(byte*) screen#5 )
(byte) main::sum2_return#3 ← phi( main::sum2_@return/(byte) main::sum2_return#1 )
(byte~) main::$1 ← (byte) main::sum2_return#3
*((byte*) screen#2 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$1
(byte) main::sum3_a#0 ← (byte/signed byte/word/signed word/dword/signed dword) 4
(byte) main::sum3_b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 8
to:main::sum3
main::sum3: scope:[main] from main::@2
(byte*) screen#9 ← phi( main::@2/(byte*) screen#2 )
(byte) main::sum3_b#1 ← phi( main::@2/(byte) main::sum3_b#0 )
(byte) main::sum3_a#1 ← phi( main::@2/(byte) main::sum3_a#0 )
(byte) main::sum3_$0#0 ← (byte) main::sum3_a#1 + (byte) main::sum3_b#1
(byte) main::sum3_return#0 ← (byte) main::sum3_$0#0
to:main::sum3_@return
main::sum3_@return: scope:[main] from main::sum3
(byte*) screen#6 ← phi( main::sum3/(byte*) screen#9 )
(byte) main::sum3_return#2 ← phi( main::sum3/(byte) main::sum3_return#0 )
(byte) main::sum3_return#1 ← (byte) main::sum3_return#2
to:main::@3
main::@3: scope:[main] from main::sum3_@return
(byte*) screen#3 ← phi( main::sum3_@return/(byte*) screen#6 )
(byte) main::sum3_return#3 ← phi( main::sum3_@return/(byte) main::sum3_return#1 )
(byte~) main::$2 ← (byte) main::sum3_return#3
*((byte*) screen#3 + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$2
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@2: scope:[] from @begin
(byte*) screen#11 ← phi( @begin/(byte*) screen#0 )
call main param-assignment
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(void()) main()
(byte~) main::$0
(byte~) main::$1
(byte~) main::$2
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(label) main::sum1
(byte~) main::sum1_$0
(byte) main::sum1_$0#0
(label) main::sum1_@return
(byte) main::sum1_a
(byte) main::sum1_a#0
(byte) main::sum1_a#1
(byte) main::sum1_b
(byte) main::sum1_b#0
(byte) main::sum1_b#1
(byte) main::sum1_return
(byte) main::sum1_return#0
(byte) main::sum1_return#1
(byte) main::sum1_return#2
(byte) main::sum1_return#3
(label) main::sum2
(byte~) main::sum2_$0
(byte) main::sum2_$0#0
(label) main::sum2_@return
(byte) main::sum2_a
(byte) main::sum2_a#0
(byte) main::sum2_a#1
(byte) main::sum2_b
(byte) main::sum2_b#0
(byte) main::sum2_b#1
(byte) main::sum2_return
(byte) main::sum2_return#0
(byte) main::sum2_return#1
(byte) main::sum2_return#2
(byte) main::sum2_return#3
(label) main::sum3
(byte~) main::sum3_$0
(byte) main::sum3_$0#0
(label) main::sum3_@return
(byte) main::sum3_a
(byte) main::sum3_a#0
(byte) main::sum3_a#1
(byte) main::sum3_b
(byte) main::sum3_b#0
(byte) main::sum3_b#1
(byte) main::sum3_return
(byte) main::sum3_return#0
(byte) main::sum3_return#1
(byte) main::sum3_return#2
(byte) main::sum3_return#3
(byte*) screen
(byte*) screen#0
(byte*) screen#1
(byte*) screen#10
(byte*) screen#11
(byte*) screen#2
(byte*) screen#3
(byte*) screen#4
(byte*) screen#5
(byte*) screen#6
(byte*) screen#7
(byte*) screen#8
(byte*) screen#9
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @3
Succesful SSA optimization Pass2CullEmptyBlocks
Not aliassing across scopes: screen#10 screen#11
Alias (byte) main::sum1_a#0 = (byte) main::sum1_a#1
Alias (byte) main::sum1_b#0 = (byte) main::sum1_b#1
Alias (byte*) screen#1 = (byte*) screen#7 (byte*) screen#10 (byte*) screen#4 (byte*) screen#8 (byte*) screen#5 (byte*) screen#2 (byte*) screen#9 (byte*) screen#6 (byte*) screen#3
Alias (byte) main::sum1_return#0 = (byte) main::sum1_$0#0 (byte) main::sum1_return#2 (byte) main::sum1_return#1 (byte) main::sum1_return#3 (byte~) main::$0
Alias (byte) main::sum2_a#0 = (byte) main::sum2_a#1
Alias (byte) main::sum2_b#0 = (byte) main::sum2_b#1
Alias (byte) main::sum2_return#0 = (byte) main::sum2_$0#0 (byte) main::sum2_return#2 (byte) main::sum2_return#1 (byte) main::sum2_return#3 (byte~) main::$1
Alias (byte) main::sum3_a#0 = (byte) main::sum3_a#1
Alias (byte) main::sum3_b#0 = (byte) main::sum3_b#1
Alias (byte) main::sum3_return#0 = (byte) main::sum3_$0#0 (byte) main::sum3_return#2 (byte) main::sum3_return#1 (byte) main::sum3_return#3 (byte~) main::$2
Alias (byte*) screen#0 = (byte*) screen#11
Succesful SSA optimization Pass2AliasElimination
Not aliassing across scopes: screen#1 screen#0
Redundant Phi (byte*) screen#1 (byte*) screen#0
Succesful SSA optimization Pass2RedundantPhiElimination
Constant (const byte*) screen#0 = ((byte*))1024
Constant (const byte) main::sum1_a#0 = 2
Constant (const byte) main::sum1_b#0 = 1
Constant (const byte) main::sum2_a#0 = 10
Constant (const byte) main::sum2_b#0 = 3
Constant (const byte) main::sum3_a#0 = 4
Constant (const byte) main::sum3_b#0 = 8
Succesful SSA optimization Pass2ConstantIdentification
Constant (const byte) main::sum1_return#0 = main::sum1_a#0+main::sum1_b#0
Constant (const byte) main::sum2_return#0 = main::sum2_a#0+main::sum2_b#0
Constant (const byte) main::sum3_return#0 = main::sum3_a#0+main::sum3_b#0
Succesful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(screen#0+0)
Consolidated array index constant in *(screen#0+1)
Consolidated array index constant in *(screen#0+2)
Succesful SSA optimization Pass2ConstantAdditionElimination
Culled Empty Block (label) main::sum1_@return
Culled Empty Block (label) main::sum2_@return
Culled Empty Block (label) main::sum3_@return
Succesful SSA optimization Pass2CullEmptyBlocks
OPTIMIZING CONTROL FLOW GRAPH
Block Sequence Planned @begin @2 @end main main::sum1 main::@1 main::sum2 main::@2 main::sum3 main::@3 main::@return
Block Sequence Planned @begin @2 @end main main::sum1 main::@1 main::sum2 main::@2 main::sum3 main::@3 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::sum1
Adding NOP phi() at start of main::sum2
Adding NOP phi() at start of main::sum3
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 @2 @end main main::sum1 main::@1 main::sum2 main::@2 main::sum3 main::@3 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::sum1
Adding NOP phi() at start of main::sum2
Adding NOP phi() at start of main::sum3
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::sum1
main::sum1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::@1
main::@1: scope:[main] from main::sum1
[6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] )
to:main::sum2
main::sum2: scope:[main] from main::@1
[7] phi() [ ] ( main:2 [ ] )
to:main::@2
main::@2: scope:[main] from main::sum2
[8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] )
to:main::sum3
main::sum3: scope:[main] from main::@2
[9] phi() [ ] ( main:2 [ ] )
to:main::@3
main::@3: scope:[main] from main::sum3
[10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] )
to:main::@return
main::@return: scope:[main] from main::@3
[11] return [ ] ( main:2 [ ] )
to:@return
DOMINATORS
@begin dominated by @begin
@2 dominated by @2 @begin
@end dominated by @2 @begin @end
main dominated by @2 @begin main
main::sum1 dominated by @2 @begin main::sum1 main
main::@1 dominated by @2 @begin main::sum1 main::@1 main
main::sum2 dominated by @2 @begin main::sum1 main::@1 main main::sum2
main::@2 dominated by @2 @begin main::sum1 main::@1 main::@2 main main::sum2
main::sum3 dominated by @2 @begin main::sum1 main::@1 main::@2 main main::sum2 main::sum3
main::@3 dominated by @2 @begin main::sum1 main::@1 main::@2 main main::sum2 main::sum3 main::@3
main::@return dominated by main::@return @2 @begin main::sum1 main::@1 main::@2 main main::sum2 main::sum3 main::@3
NATURAL LOOPS
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 0 loops in scope [main]
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::sum1_$0
(byte) main::sum1_a
(byte) main::sum1_b
(byte) main::sum1_return
(byte~) main::sum2_$0
(byte) main::sum2_a
(byte) main::sum2_b
(byte) main::sum2_return
(byte~) main::sum3_$0
(byte) main::sum3_a
(byte) main::sum3_b
(byte) main::sum3_return
(byte*) screen
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.const sum1_a = 2
.const sum1_b = 1
.const sum2_a = $a
.const sum2_b = 3
.const sum3_a = 4
.const sum3_b = 8
.const sum1_return = sum1_a+sum1_b
.const sum2_return = sum2_a+sum2_b
.const sum3_return = sum3_a+sum3_b
//SEG10 [5] phi from main to main::sum1 [phi:main->main::sum1]
sum1_from_main:
jmp sum1
//SEG11 main::sum1
sum1:
jmp b1
//SEG12 main::@1
b1:
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum1_return
sta screen+0
//SEG14 [7] phi from main::@1 to main::sum2 [phi:main::@1->main::sum2]
sum2_from_b1:
jmp sum2
//SEG15 main::sum2
sum2:
jmp b2
//SEG16 main::@2
b2:
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum2_return
sta screen+1
//SEG18 [9] phi from main::@2 to main::sum3 [phi:main::@2->main::sum3]
sum3_from_b2:
jmp sum3
//SEG19 main::sum3
sum3:
jmp b3
//SEG20 main::@3
b3:
//SEG21 [10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum3_return
sta screen+2
jmp breturn
//SEG22 main::@return
breturn:
//SEG23 [11] return [ ] ( main:2 [ ] )
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 138 combination
Uplifting [] best 138 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.const sum1_a = 2
.const sum1_b = 1
.const sum2_a = $a
.const sum2_b = 3
.const sum3_a = 4
.const sum3_b = 8
.const sum1_return = sum1_a+sum1_b
.const sum2_return = sum2_a+sum2_b
.const sum3_return = sum3_a+sum3_b
//SEG10 [5] phi from main to main::sum1 [phi:main->main::sum1]
sum1_from_main:
jmp sum1
//SEG11 main::sum1
sum1:
jmp b1
//SEG12 main::@1
b1:
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum1_return
sta screen+0
//SEG14 [7] phi from main::@1 to main::sum2 [phi:main::@1->main::sum2]
sum2_from_b1:
jmp sum2
//SEG15 main::sum2
sum2:
jmp b2
//SEG16 main::@2
b2:
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum2_return
sta screen+1
//SEG18 [9] phi from main::@2 to main::sum3 [phi:main::@2->main::sum3]
sum3_from_b2:
jmp sum3
//SEG19 main::sum3
sum3:
jmp b3
//SEG20 main::@3
b3:
//SEG21 [10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum3_return
sta screen+2
jmp breturn
//SEG22 main::@return
breturn:
//SEG23 [11] return [ ] ( main:2 [ ] )
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp sum1
Removing instruction jmp b1
Removing instruction jmp sum2
Removing instruction jmp b2
Removing instruction jmp sum3
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b2_from_bbegin:
Removing instruction main_from_b2:
Removing instruction bend_from_b2:
Removing instruction sum1_from_main:
Removing instruction sum1:
Removing instruction sum2_from_b1:
Removing instruction sum2:
Removing instruction sum3_from_b2:
Removing instruction sum3:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction b1:
Removing instruction b2:
Removing instruction b3:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(label) main::sum1
(byte~) main::sum1_$0
(byte) main::sum1_a
(const byte) main::sum1_a#0 sum1_a = (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::sum1_b
(const byte) main::sum1_b#0 sum1_b = (byte/signed byte/word/signed word/dword/signed dword) 1
(byte) main::sum1_return
(const byte) main::sum1_return#0 sum1_return = (const byte) main::sum1_a#0+(const byte) main::sum1_b#0
(label) main::sum2
(byte~) main::sum2_$0
(byte) main::sum2_a
(const byte) main::sum2_a#0 sum2_a = (byte/signed byte/word/signed word/dword/signed dword) 10
(byte) main::sum2_b
(const byte) main::sum2_b#0 sum2_b = (byte/signed byte/word/signed word/dword/signed dword) 3
(byte) main::sum2_return
(const byte) main::sum2_return#0 sum2_return = (const byte) main::sum2_a#0+(const byte) main::sum2_b#0
(label) main::sum3
(byte~) main::sum3_$0
(byte) main::sum3_a
(const byte) main::sum3_a#0 sum3_a = (byte/signed byte/word/signed word/dword/signed dword) 4
(byte) main::sum3_b
(const byte) main::sum3_b#0 sum3_b = (byte/signed byte/word/signed word/dword/signed dword) 8
(byte) main::sum3_return
(const byte) main::sum3_return#0 sum3_return = (const byte) main::sum3_a#0+(const byte) main::sum3_b#0
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
FINAL ASSEMBLER
Score: 30
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
//SEG4 @2
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
//SEG8 @end
//SEG9 main
main: {
.const sum1_a = 2
.const sum1_b = 1
.const sum2_a = $a
.const sum2_b = 3
.const sum3_a = 4
.const sum3_b = 8
.const sum1_return = sum1_a+sum1_b
.const sum2_return = sum2_a+sum2_b
.const sum3_return = sum3_a+sum3_b
//SEG10 [5] phi from main to main::sum1 [phi:main->main::sum1]
//SEG11 main::sum1
//SEG12 main::@1
//SEG13 [6] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (const byte) main::sum1_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum1_return
sta screen+0
//SEG14 [7] phi from main::@1 to main::sum2 [phi:main::@1->main::sum2]
//SEG15 main::sum2
//SEG16 main::@2
//SEG17 [8] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (const byte) main::sum2_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum2_return
sta screen+1
//SEG18 [9] phi from main::@2 to main::sum3 [phi:main::@2->main::sum3]
//SEG19 main::sum3
//SEG20 main::@3
//SEG21 [10] *((const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (const byte) main::sum3_return#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2
lda #sum3_return
sta screen+2
//SEG22 main::@return
//SEG23 [11] return [ ] ( main:2 [ ] )
rts
}

View File

@ -0,0 +1,35 @@
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(label) main::sum1
(byte~) main::sum1_$0
(byte) main::sum1_a
(const byte) main::sum1_a#0 sum1_a = (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::sum1_b
(const byte) main::sum1_b#0 sum1_b = (byte/signed byte/word/signed word/dword/signed dword) 1
(byte) main::sum1_return
(const byte) main::sum1_return#0 sum1_return = (const byte) main::sum1_a#0+(const byte) main::sum1_b#0
(label) main::sum2
(byte~) main::sum2_$0
(byte) main::sum2_a
(const byte) main::sum2_a#0 sum2_a = (byte/signed byte/word/signed word/dword/signed dword) 10
(byte) main::sum2_b
(const byte) main::sum2_b#0 sum2_b = (byte/signed byte/word/signed word/dword/signed dword) 3
(byte) main::sum2_return
(const byte) main::sum2_return#0 sum2_return = (const byte) main::sum2_a#0+(const byte) main::sum2_b#0
(label) main::sum3
(byte~) main::sum3_$0
(byte) main::sum3_a
(const byte) main::sum3_a#0 sum3_a = (byte/signed byte/word/signed word/dword/signed dword) 4
(byte) main::sum3_b
(const byte) main::sum3_b#0 sum3_b = (byte/signed byte/word/signed word/dword/signed dword) 8
(byte) main::sum3_return
(const byte) main::sum3_return#0 sum3_return = (const byte) main::sum3_a#0+(const byte) main::sum3_b#0
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024

View File

@ -0,0 +1,32 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label screen = $400
jsr main
main: {
.label print2_at = screen+2*$28
ldx #0
ldy #0
print1_b1:
lda print1_msg,y
sta screen,x
inx
inx
iny
lda print1_msg,y
cmp #'@'
bne print1_b1
ldx #0
ldy #0
print2_b1:
lda print1_msg,y
sta print2_at,x
inx
inx
iny
lda print1_msg,y
cmp #'@'
bne print2_b1
rts
print1_msg: .text "hello world!@"
}

View File

@ -0,0 +1,37 @@
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::print1
main::print1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::print1_@1
main::print1_@1: scope:[main] from main::print1 main::print1_@1
[6] (byte) main::print1_j#2 ← phi( main::print1/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print1_@1/(byte) main::print1_j#1 ) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[6] (byte) main::print1_i#2 ← phi( main::print1/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print1_@1/(byte) main::print1_i#1 ) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[8] (byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print1_i#2 main::print1_j#1 ] ( main:2 [ main::print1_i#2 main::print1_j#1 ] )
[9] (byte) main::print1_i#1 ← ++ (byte) main::print1_i#2 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] )
[10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] )
to:main::print2
main::print2: scope:[main] from main::print1_@1
[11] phi() [ ] ( main:2 [ ] )
to:main::print2_@1
main::print2_@1: scope:[main] from main::print2 main::print2_@1
[12] (byte) main::print2_j#2 ← phi( main::print2/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print2_@1/(byte) main::print2_j#1 ) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[12] (byte) main::print2_i#2 ← phi( main::print2/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print2_@1/(byte) main::print2_i#1 ) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[14] (byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print2_i#2 main::print2_j#1 ] ( main:2 [ main::print2_i#2 main::print2_j#1 ] )
[15] (byte) main::print2_i#1 ← ++ (byte) main::print2_i#2 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] )
[16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] )
to:main::@return
main::@return: scope:[main] from main::print2_@1
[17] return [ ] ( main:2 [ ] )
to:@return

View File

@ -0,0 +1,815 @@
PARSING src/test/java/dk/camelot64/kickc/test/kc/inline-function-print.kc
// TEst inlining a slightly complex print function (containing a loop)
byte* screen = $400;
void main() {
byte* hello = "hello world!@";
print(screen, hello);
print(screen+2*40, hello);
}
inline void print(byte* at, byte* msg) {
byte j=0;
for(byte i=0; msg[i]!='@'; i++) {
at[j] = msg[i];
j += 2;
}
}
Adding pre/post-modifier (byte) print::i ← ++ (byte) print::i
SYMBOLS
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(void~) main::$0
(byte/signed byte/word/signed word/dword/signed dword~) main::$1
(byte*~) main::$2
(void~) main::$3
(label) main::@return
(byte*) main::hello
inline (void()) print((byte*) print::at , (byte*) print::msg)
(bool~) print::$0
(label) print::@1
(label) print::@2
(label) print::@return
(byte*) print::at
(byte) print::i
(byte) print::j
(byte*) print::msg
(byte*) screen
Promoting word/signed word/dword/signed dword to byte* in screen ← ((byte*)) 1024
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
(byte*) screen ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@1
main: scope:[main] from
(byte*) main::hello ← (string) "hello world!@"
(void~) main::$0 ← call print (byte*) screen (byte*) main::hello
(byte/signed byte/word/signed word/dword/signed dword~) main::$1 ← (byte/signed byte/word/signed word/dword/signed dword) 2 * (byte/signed byte/word/signed word/dword/signed dword) 40
(byte*~) main::$2 ← (byte*) screen + (byte/signed byte/word/signed word/dword/signed dword~) main::$1
(void~) main::$3 ← call print (byte*~) main::$2 (byte*) main::hello
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
to:@2
print: scope:[print] from
(byte) print::j ← (byte/signed byte/word/signed word/dword/signed dword) 0
(byte) print::i ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:print::@1
print::@1: scope:[print] from print print::@1
*((byte*) print::at + (byte) print::j) ← *((byte*) print::msg + (byte) print::i)
(byte) print::j ← (byte) print::j + (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) print::i ← ++ (byte) print::i
(bool~) print::$0 ← *((byte*) print::msg + (byte) print::i) != (byte) '@'
if((bool~) print::$0) goto print::@1
to:print::@2
print::@2: scope:[print] from print::@1
to:print::@return
print::@return: scope:[print] from print::@2
return
to:@return
@2: scope:[] from @1
call main
to:@end
@end: scope:[] from @2
Inlined call call print (byte*) screen (byte*) main::hello
Inlined call call print (byte*~) main::$2 (byte*) main::hello
Removing unused procedure print
Creating constant string variable for inline (const string) main::$4 "hello world!@"
Removing empty block main::print1_@2
Removing empty block main::print1_@return
Removing empty block main::print2_@2
Removing empty block main::print2_@return
Removing empty block main::@2
Removing empty block @1
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN
@begin: scope:[] from
(byte*) screen#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024
to:@2
main: scope:[main] from @2
(byte*) screen#1 ← phi( @2/(byte*) screen#3 )
(byte*) main::hello#0 ← (const string) main::$4
(byte*) main::print1_at#0 ← (byte*) screen#1
(byte*) main::print1_msg#0 ← (byte*) main::hello#0
to:main::print1
main::print1: scope:[main] from main
(byte*) main::hello#3 ← phi( main/(byte*) main::hello#0 )
(byte*) screen#5 ← phi( main/(byte*) screen#1 )
(byte*) main::print1_at#2 ← phi( main/(byte*) main::print1_at#0 )
(byte*) main::print1_msg#2 ← phi( main/(byte*) main::print1_msg#0 )
(byte) main::print1_j#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
(byte) main::print1_i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::print1_@1
main::print1_@1: scope:[main] from main::print1 main::print1_@1
(byte*) main::hello#2 ← phi( main::print1/(byte*) main::hello#3 main::print1_@1/(byte*) main::hello#2 )
(byte*) screen#4 ← phi( main::print1/(byte*) screen#5 main::print1_@1/(byte*) screen#4 )
(byte) main::print1_j#2 ← phi( main::print1/(byte) main::print1_j#0 main::print1_@1/(byte) main::print1_j#1 )
(byte*) main::print1_at#1 ← phi( main::print1/(byte*) main::print1_at#2 main::print1_@1/(byte*) main::print1_at#1 )
(byte) main::print1_i#2 ← phi( main::print1/(byte) main::print1_i#0 main::print1_@1/(byte) main::print1_i#1 )
(byte*) main::print1_msg#1 ← phi( main::print1/(byte*) main::print1_msg#2 main::print1_@1/(byte*) main::print1_msg#1 )
*((byte*) main::print1_at#1 + (byte) main::print1_j#2) ← *((byte*) main::print1_msg#1 + (byte) main::print1_i#2)
(byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::print1_i#1 ← ++ (byte) main::print1_i#2
(bool) main::print1_$0#0 ← *((byte*) main::print1_msg#1 + (byte) main::print1_i#1) != (byte) '@'
if((bool) main::print1_$0#0) goto main::print1_@1
to:main::@1
main::@1: scope:[main] from main::print1_@1
(byte*) main::hello#1 ← phi( main::print1_@1/(byte*) main::hello#2 )
(byte*) screen#2 ← phi( main::print1_@1/(byte*) screen#4 )
(byte/signed byte/word/signed word/dword/signed dword~) main::$1 ← (byte/signed byte/word/signed word/dword/signed dword) 2 * (byte/signed byte/word/signed word/dword/signed dword) 40
(byte*~) main::$2 ← (byte*) screen#2 + (byte/signed byte/word/signed word/dword/signed dword~) main::$1
(byte*) main::print2_at#0 ← (byte*~) main::$2
(byte*) main::print2_msg#0 ← (byte*) main::hello#1
to:main::print2
main::print2: scope:[main] from main::@1
(byte*) main::print2_at#2 ← phi( main::@1/(byte*) main::print2_at#0 )
(byte*) main::print2_msg#2 ← phi( main::@1/(byte*) main::print2_msg#0 )
(byte) main::print2_j#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
(byte) main::print2_i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::print2_@1
main::print2_@1: scope:[main] from main::print2 main::print2_@1
(byte) main::print2_j#2 ← phi( main::print2/(byte) main::print2_j#0 main::print2_@1/(byte) main::print2_j#1 )
(byte*) main::print2_at#1 ← phi( main::print2/(byte*) main::print2_at#2 main::print2_@1/(byte*) main::print2_at#1 )
(byte) main::print2_i#2 ← phi( main::print2/(byte) main::print2_i#0 main::print2_@1/(byte) main::print2_i#1 )
(byte*) main::print2_msg#1 ← phi( main::print2/(byte*) main::print2_msg#2 main::print2_@1/(byte*) main::print2_msg#1 )
*((byte*) main::print2_at#1 + (byte) main::print2_j#2) ← *((byte*) main::print2_msg#1 + (byte) main::print2_i#2)
(byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2
(byte) main::print2_i#1 ← ++ (byte) main::print2_i#2
(bool) main::print2_$0#0 ← *((byte*) main::print2_msg#1 + (byte) main::print2_i#1) != (byte) '@'
if((bool) main::print2_$0#0) goto main::print2_@1
to:main::@return
main::@return: scope:[main] from main::print2_@1
return
to:@return
@2: scope:[] from @begin
(byte*) screen#3 ← phi( @begin/(byte*) screen#0 )
call main param-assignment
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(void()) main()
(byte/signed byte/word/signed word/dword/signed dword~) main::$1
(byte*~) main::$2
(const string) main::$4 = (string) "hello world!@"
(label) main::@1
(label) main::@return
(byte*) main::hello
(byte*) main::hello#0
(byte*) main::hello#1
(byte*) main::hello#2
(byte*) main::hello#3
(label) main::print1
(bool~) main::print1_$0
(bool) main::print1_$0#0
(label) main::print1_@1
(byte*) main::print1_at
(byte*) main::print1_at#0
(byte*) main::print1_at#1
(byte*) main::print1_at#2
(byte) main::print1_i
(byte) main::print1_i#0
(byte) main::print1_i#1
(byte) main::print1_i#2
(byte) main::print1_j
(byte) main::print1_j#0
(byte) main::print1_j#1
(byte) main::print1_j#2
(byte*) main::print1_msg
(byte*) main::print1_msg#0
(byte*) main::print1_msg#1
(byte*) main::print1_msg#2
(label) main::print2
(bool~) main::print2_$0
(bool) main::print2_$0#0
(label) main::print2_@1
(byte*) main::print2_at
(byte*) main::print2_at#0
(byte*) main::print2_at#1
(byte*) main::print2_at#2
(byte) main::print2_i
(byte) main::print2_i#0
(byte) main::print2_i#1
(byte) main::print2_i#2
(byte) main::print2_j
(byte) main::print2_j#0
(byte) main::print2_j#1
(byte) main::print2_j#2
(byte*) main::print2_msg
(byte*) main::print2_msg#0
(byte*) main::print2_msg#1
(byte*) main::print2_msg#2
(byte*) screen
(byte*) screen#0
(byte*) screen#1
(byte*) screen#2
(byte*) screen#3
(byte*) screen#4
(byte*) screen#5
OPTIMIZING CONTROL FLOW GRAPH
Culled Empty Block (label) @3
Succesful SSA optimization Pass2CullEmptyBlocks
Not aliassing across scopes: screen#1 screen#3
Not aliassing across scopes: main::print1_at#0 screen#1
Alias (byte*) main::print1_msg#0 = (byte*) main::hello#0 (byte*) main::print1_msg#2 (byte*) main::hello#3
Alias (byte*) main::print1_at#0 = (byte*) main::print1_at#2
Alias (byte*) screen#1 = (byte*) screen#5
Alias (byte*) screen#2 = (byte*) screen#4
Alias (byte*) main::hello#1 = (byte*) main::hello#2 (byte*) main::print2_msg#0 (byte*) main::print2_msg#2
Alias (byte*) main::print2_at#0 = (byte*~) main::$2 (byte*) main::print2_at#2
Alias (byte*) screen#0 = (byte*) screen#3
Succesful SSA optimization Pass2AliasElimination
Not aliassing across scopes: screen#1 screen#0
Not aliassing across scopes: main::print1_at#0 screen#1
Self Phi Eliminated (byte*) main::print1_msg#1
Self Phi Eliminated (byte*) main::print1_at#1
Self Phi Eliminated (byte*) screen#2
Self Phi Eliminated (byte*) main::hello#1
Self Phi Eliminated (byte*) main::print2_msg#1
Self Phi Eliminated (byte*) main::print2_at#1
Succesful SSA optimization Pass2SelfPhiElimination
Redundant Phi (byte*) screen#1 (byte*) screen#0
Redundant Phi (byte*) main::print1_msg#1 (byte*) main::print1_msg#0
Redundant Phi (byte*) main::print1_at#1 (byte*) main::print1_at#0
Redundant Phi (byte*) screen#2 (byte*) screen#1
Redundant Phi (byte*) main::hello#1 (byte*) main::print1_msg#0
Redundant Phi (byte*) main::print2_msg#1 (byte*) main::hello#1
Redundant Phi (byte*) main::print2_at#1 (byte*) main::print2_at#0
Succesful SSA optimization Pass2RedundantPhiElimination
Simple Condition (bool) main::print1_$0#0 if(*((byte*) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1
Simple Condition (bool) main::print2_$0#0 if(*((byte*) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1
Succesful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) screen#0 = ((byte*))1024
Constant (const string) main::print1_msg#0 = main::$4
Constant (const byte) main::print1_j#0 = 0
Constant (const byte) main::print1_i#0 = 0
Constant (const byte/signed byte/word/signed word/dword/signed dword) main::$1 = 2*40
Constant (const byte) main::print2_j#0 = 0
Constant (const byte) main::print2_i#0 = 0
Succesful SSA optimization Pass2ConstantIdentification
Constant (const byte*) main::print1_at#0 = screen#0
Constant (const byte*) main::print2_at#0 = screen#0+main::$1
Succesful SSA optimization Pass2ConstantIdentification
Culled Empty Block (label) main::@1
Succesful SSA optimization Pass2CullEmptyBlocks
OPTIMIZING CONTROL FLOW GRAPH
Inlining constant with var siblings (const byte) main::print1_j#0
Inlining constant with var siblings (const byte) main::print1_j#0
Inlining constant with var siblings (const byte) main::print1_i#0
Inlining constant with var siblings (const byte) main::print1_i#0
Inlining constant with var siblings (const byte) main::print2_j#0
Inlining constant with var siblings (const byte) main::print2_j#0
Inlining constant with var siblings (const byte) main::print2_i#0
Inlining constant with var siblings (const byte) main::print2_i#0
Constant inlined main::print2_j#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::print1_at#0 = (const byte*) screen#0
Constant inlined main::print2_i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::$1 = (byte/signed byte/word/signed word/dword/signed dword) 2*(byte/signed byte/word/signed word/dword/signed dword) 40
Constant inlined main::$4 = (const string) main::print1_msg#0
Constant inlined main::print1_i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::print1_j#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Succesful SSA optimization Pass2ConstantInlining
Block Sequence Planned @begin @2 @end main main::print1 main::print1_@1 main::print2 main::print2_@1 main::@return
Added new block during phi lifting main::@3(between main::print1_@1 and main::print1_@1)
Added new block during phi lifting main::@4(between main::print2_@1 and main::print2_@1)
Block Sequence Planned @begin @2 @end main main::print1 main::print1_@1 main::print2 main::print2_@1 main::@return main::@4 main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::print1
Adding NOP phi() at start of main::print2
CALL GRAPH
Calls in [] to main:2
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
Created 4 initial phi equivalence classes
Coalesced [18] main::print2_i#3 ← main::print2_i#1
Coalesced [19] main::print2_j#3 ← main::print2_j#1
Coalesced [20] main::print1_i#3 ← main::print1_i#1
Coalesced [21] main::print1_j#3 ← main::print1_j#1
Coalesced down to 4 phi equivalence classes
Culled Empty Block (label) main::@4
Culled Empty Block (label) main::@3
Block Sequence Planned @begin @2 @end main main::print1 main::print1_@1 main::print2 main::print2_@1 main::@return
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::print1
Adding NOP phi() at start of main::print2
Propagating live ranges...
Propagating live ranges...
Propagating live ranges...
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi() [ ] ( )
to:@2
@2: scope:[] from @begin
[1] phi() [ ] ( )
[2] call main param-assignment [ ] ( )
to:@end
@end: scope:[] from @2
[3] phi() [ ] ( )
main: scope:[main] from @2
[4] phi() [ ] ( main:2 [ ] )
to:main::print1
main::print1: scope:[main] from main
[5] phi() [ ] ( main:2 [ ] )
to:main::print1_@1
main::print1_@1: scope:[main] from main::print1 main::print1_@1
[6] (byte) main::print1_j#2 ← phi( main::print1/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print1_@1/(byte) main::print1_j#1 ) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[6] (byte) main::print1_i#2 ← phi( main::print1/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print1_@1/(byte) main::print1_i#1 ) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] )
[8] (byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print1_i#2 main::print1_j#1 ] ( main:2 [ main::print1_i#2 main::print1_j#1 ] )
[9] (byte) main::print1_i#1 ← ++ (byte) main::print1_i#2 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] )
[10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] )
to:main::print2
main::print2: scope:[main] from main::print1_@1
[11] phi() [ ] ( main:2 [ ] )
to:main::print2_@1
main::print2_@1: scope:[main] from main::print2 main::print2_@1
[12] (byte) main::print2_j#2 ← phi( main::print2/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print2_@1/(byte) main::print2_j#1 ) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[12] (byte) main::print2_i#2 ← phi( main::print2/(byte/signed byte/word/signed word/dword/signed dword) 0 main::print2_@1/(byte) main::print2_i#1 ) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] )
[14] (byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print2_i#2 main::print2_j#1 ] ( main:2 [ main::print2_i#2 main::print2_j#1 ] )
[15] (byte) main::print2_i#1 ← ++ (byte) main::print2_i#2 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] )
[16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] )
to:main::@return
main::@return: scope:[main] from main::print2_@1
[17] return [ ] ( main:2 [ ] )
to:@return
DOMINATORS
@begin dominated by @begin
@2 dominated by @2 @begin
@end dominated by @2 @begin @end
main dominated by @2 @begin main
main::print1 dominated by @2 @begin main main::print1
main::print1_@1 dominated by @2 @begin main::print1_@1 main main::print1
main::print2 dominated by @2 @begin main::print1_@1 main::print2 main main::print1
main::print2_@1 dominated by @2 @begin main::print1_@1 main::print2_@1 main::print2 main main::print1
main::@return dominated by main::@return @2 @begin main::print1_@1 main::print2_@1 main::print2 main main::print1
NATURAL LOOPS
Found back edge: Loop head: main::print1_@1 tails: main::print1_@1 blocks: null
Found back edge: Loop head: main::print2_@1 tails: main::print2_@1 blocks: null
Populated: Loop head: main::print1_@1 tails: main::print1_@1 blocks: main::print1_@1
Populated: Loop head: main::print2_@1 tails: main::print2_@1 blocks: main::print2_@1
Loop head: main::print1_@1 tails: main::print1_@1 blocks: main::print1_@1
Loop head: main::print2_@1 tails: main::print2_@1 blocks: main::print2_@1
NATURAL LOOPS WITH DEPTH
Found 0 loops in scope []
Found 2 loops in scope [main]
Loop head: main::print1_@1 tails: main::print1_@1 blocks: main::print1_@1
Loop head: main::print2_@1 tails: main::print2_@1 blocks: main::print2_@1
Loop head: main::print1_@1 tails: main::print1_@1 blocks: main::print1_@1 depth: 1
Loop head: main::print2_@1 tails: main::print2_@1 blocks: main::print2_@1 depth: 1
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::hello
(bool~) main::print1_$0
(byte*) main::print1_at
(byte) main::print1_i
(byte) main::print1_i#1 16.5
(byte) main::print1_i#2 11.0
(byte) main::print1_j
(byte) main::print1_j#1 7.333333333333333
(byte) main::print1_j#2 16.5
(byte*) main::print1_msg
(bool~) main::print2_$0
(byte*) main::print2_at
(byte) main::print2_i
(byte) main::print2_i#1 16.5
(byte) main::print2_i#2 11.0
(byte) main::print2_j
(byte) main::print2_j#1 7.333333333333333
(byte) main::print2_j#2 16.5
(byte*) main::print2_msg
(byte*) screen
Initial phi equivalence classes
[ main::print1_i#2 main::print1_i#1 ]
[ main::print1_j#2 main::print1_j#1 ]
[ main::print2_i#2 main::print2_i#1 ]
[ main::print2_j#2 main::print2_j#1 ]
Complete equivalence classes
[ main::print1_i#2 main::print1_i#1 ]
[ main::print1_j#2 main::print1_j#1 ]
[ main::print2_i#2 main::print2_i#1 ]
[ main::print2_j#2 main::print2_j#1 ]
Allocated zp ZP_BYTE:2 [ main::print1_i#2 main::print1_i#1 ]
Allocated zp ZP_BYTE:3 [ main::print1_j#2 main::print1_j#1 ]
Allocated zp ZP_BYTE:4 [ main::print2_i#2 main::print2_i#1 ]
Allocated zp ZP_BYTE:5 [ main::print2_j#2 main::print2_j#1 ]
INITIAL ASM
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label print2_at = screen+2*$28
.label print1_j = 3
.label print1_i = 2
.label print2_j = 5
.label print2_i = 4
//SEG10 [5] phi from main to main::print1 [phi:main->main::print1]
print1_from_main:
jmp print1
//SEG11 main::print1
print1:
//SEG12 [6] phi from main::print1 to main::print1_@1 [phi:main::print1->main::print1_@1]
print1_b1_from_print1:
//SEG13 [6] phi (byte) main::print1_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#0] -- vbuz1=vbuc1
lda #0
sta print1_j
//SEG14 [6] phi (byte) main::print1_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#1] -- vbuz1=vbuc1
lda #0
sta print1_i
jmp print1_b1
//SEG15 [6] phi from main::print1_@1 to main::print1_@1 [phi:main::print1_@1->main::print1_@1]
print1_b1_from_print1_b1:
//SEG16 [6] phi (byte) main::print1_j#2 = (byte) main::print1_j#1 [phi:main::print1_@1->main::print1_@1#0] -- register_copy
//SEG17 [6] phi (byte) main::print1_i#2 = (byte) main::print1_i#1 [phi:main::print1_@1->main::print1_@1#1] -- register_copy
jmp print1_b1
//SEG18 main::print1_@1
print1_b1:
//SEG19 [7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] ) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
ldy print1_i
lda print1_msg,y
ldy print1_j
sta screen,y
//SEG20 [8] (byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print1_i#2 main::print1_j#1 ] ( main:2 [ main::print1_i#2 main::print1_j#1 ] ) -- vbuz1=vbuz1_plus_2
lda print1_j
clc
adc #2
sta print1_j
//SEG21 [9] (byte) main::print1_i#1 ← ++ (byte) main::print1_i#2 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- vbuz1=_inc_vbuz1
inc print1_i
//SEG22 [10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- pbuc1_derefidx_vbuz1_neq_vbuc2_then_la1
ldy print1_i
lda print1_msg,y
cmp #'@'
bne print1_b1_from_print1_b1
//SEG23 [11] phi from main::print1_@1 to main::print2 [phi:main::print1_@1->main::print2]
print2_from_print1_b1:
jmp print2
//SEG24 main::print2
print2:
//SEG25 [12] phi from main::print2 to main::print2_@1 [phi:main::print2->main::print2_@1]
print2_b1_from_print2:
//SEG26 [12] phi (byte) main::print2_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#0] -- vbuz1=vbuc1
lda #0
sta print2_j
//SEG27 [12] phi (byte) main::print2_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#1] -- vbuz1=vbuc1
lda #0
sta print2_i
jmp print2_b1
//SEG28 [12] phi from main::print2_@1 to main::print2_@1 [phi:main::print2_@1->main::print2_@1]
print2_b1_from_print2_b1:
//SEG29 [12] phi (byte) main::print2_j#2 = (byte) main::print2_j#1 [phi:main::print2_@1->main::print2_@1#0] -- register_copy
//SEG30 [12] phi (byte) main::print2_i#2 = (byte) main::print2_i#1 [phi:main::print2_@1->main::print2_@1#1] -- register_copy
jmp print2_b1
//SEG31 main::print2_@1
print2_b1:
//SEG32 [13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] ) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
ldy print2_i
lda print1_msg,y
ldy print2_j
sta print2_at,y
//SEG33 [14] (byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print2_i#2 main::print2_j#1 ] ( main:2 [ main::print2_i#2 main::print2_j#1 ] ) -- vbuz1=vbuz1_plus_2
lda print2_j
clc
adc #2
sta print2_j
//SEG34 [15] (byte) main::print2_i#1 ← ++ (byte) main::print2_i#2 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- vbuz1=_inc_vbuz1
inc print2_i
//SEG35 [16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- pbuc1_derefidx_vbuz1_neq_vbuc2_then_la1
ldy print2_i
lda print1_msg,y
cmp #'@'
bne print2_b1_from_print2_b1
jmp breturn
//SEG36 main::@return
breturn:
//SEG37 [17] return [ ] ( main:2 [ ] )
rts
print1_msg: .text "hello world!@"
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::print1_i#2 main::print1_i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::print1_j#2 main::print1_j#1 ]
Statement [10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) always clobbers reg byte a
Statement [13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ main::print2_i#2 main::print2_i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ main::print2_j#2 main::print2_j#1 ]
Statement [16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) always clobbers reg byte a
Statement [7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] ) always clobbers reg byte a
Statement [10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) always clobbers reg byte a
Statement [13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] ) always clobbers reg byte a
Statement [16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::print1_i#2 main::print1_i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ main::print1_j#2 main::print1_j#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:4 [ main::print2_i#2 main::print2_i#1 ] : zp ZP_BYTE:4 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:5 [ main::print2_j#2 main::print2_j#1 ] : zp ZP_BYTE:5 , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::print1_i#2 main::print1_i#1 ] 27.5: zp ZP_BYTE:4 [ main::print2_i#2 main::print2_i#1 ] 23.83: zp ZP_BYTE:3 [ main::print1_j#2 main::print1_j#1 ] 23.83: zp ZP_BYTE:5 [ main::print2_j#2 main::print2_j#1 ]
Uplift Scope []
Uplifting [main] best 744 combination reg byte y [ main::print1_i#2 main::print1_i#1 ] reg byte y [ main::print2_i#2 main::print2_i#1 ] reg byte x [ main::print1_j#2 main::print1_j#1 ] reg byte x [ main::print2_j#2 main::print2_j#1 ]
Uplifting [] best 744 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
bbegin:
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
b2_from_bbegin:
jmp b2
//SEG4 @2
b2:
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
main_from_b2:
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label print2_at = screen+2*$28
//SEG10 [5] phi from main to main::print1 [phi:main->main::print1]
print1_from_main:
jmp print1
//SEG11 main::print1
print1:
//SEG12 [6] phi from main::print1 to main::print1_@1 [phi:main::print1->main::print1_@1]
print1_b1_from_print1:
//SEG13 [6] phi (byte) main::print1_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#0] -- vbuxx=vbuc1
ldx #0
//SEG14 [6] phi (byte) main::print1_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#1] -- vbuyy=vbuc1
ldy #0
jmp print1_b1
//SEG15 [6] phi from main::print1_@1 to main::print1_@1 [phi:main::print1_@1->main::print1_@1]
print1_b1_from_print1_b1:
//SEG16 [6] phi (byte) main::print1_j#2 = (byte) main::print1_j#1 [phi:main::print1_@1->main::print1_@1#0] -- register_copy
//SEG17 [6] phi (byte) main::print1_i#2 = (byte) main::print1_i#1 [phi:main::print1_@1->main::print1_@1#1] -- register_copy
jmp print1_b1
//SEG18 main::print1_@1
print1_b1:
//SEG19 [7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] ) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
lda print1_msg,y
sta screen,x
//SEG20 [8] (byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print1_i#2 main::print1_j#1 ] ( main:2 [ main::print1_i#2 main::print1_j#1 ] ) -- vbuxx=vbuxx_plus_2
inx
inx
//SEG21 [9] (byte) main::print1_i#1 ← ++ (byte) main::print1_i#2 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- vbuyy=_inc_vbuyy
iny
//SEG22 [10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- pbuc1_derefidx_vbuyy_neq_vbuc2_then_la1
lda print1_msg,y
cmp #'@'
bne print1_b1_from_print1_b1
//SEG23 [11] phi from main::print1_@1 to main::print2 [phi:main::print1_@1->main::print2]
print2_from_print1_b1:
jmp print2
//SEG24 main::print2
print2:
//SEG25 [12] phi from main::print2 to main::print2_@1 [phi:main::print2->main::print2_@1]
print2_b1_from_print2:
//SEG26 [12] phi (byte) main::print2_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#0] -- vbuxx=vbuc1
ldx #0
//SEG27 [12] phi (byte) main::print2_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#1] -- vbuyy=vbuc1
ldy #0
jmp print2_b1
//SEG28 [12] phi from main::print2_@1 to main::print2_@1 [phi:main::print2_@1->main::print2_@1]
print2_b1_from_print2_b1:
//SEG29 [12] phi (byte) main::print2_j#2 = (byte) main::print2_j#1 [phi:main::print2_@1->main::print2_@1#0] -- register_copy
//SEG30 [12] phi (byte) main::print2_i#2 = (byte) main::print2_i#1 [phi:main::print2_@1->main::print2_@1#1] -- register_copy
jmp print2_b1
//SEG31 main::print2_@1
print2_b1:
//SEG32 [13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] ) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
lda print1_msg,y
sta print2_at,x
//SEG33 [14] (byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print2_i#2 main::print2_j#1 ] ( main:2 [ main::print2_i#2 main::print2_j#1 ] ) -- vbuxx=vbuxx_plus_2
inx
inx
//SEG34 [15] (byte) main::print2_i#1 ← ++ (byte) main::print2_i#2 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- vbuyy=_inc_vbuyy
iny
//SEG35 [16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- pbuc1_derefidx_vbuyy_neq_vbuc2_then_la1
lda print1_msg,y
cmp #'@'
bne print2_b1_from_print2_b1
jmp breturn
//SEG36 main::@return
breturn:
//SEG37 [17] return [ ] ( main:2 [ ] )
rts
print1_msg: .text "hello world!@"
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp print1
Removing instruction jmp print1_b1
Removing instruction jmp print2
Removing instruction jmp print2_b1
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label print1_b1_from_print1_b1 with print1_b1
Replacing label print2_b1_from_print2_b1 with print2_b1
Removing instruction bbegin:
Removing instruction b2_from_bbegin:
Removing instruction main_from_b2:
Removing instruction bend_from_b2:
Removing instruction print1_from_main:
Removing instruction print1_b1_from_print1:
Removing instruction print1_b1_from_print1_b1:
Removing instruction print2_from_print1_b1:
Removing instruction print2_b1_from_print2:
Removing instruction print2_b1_from_print2_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction print1:
Removing instruction print2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp print1_b1
Removing instruction jmp print2_b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@return
(byte*) main::hello
(label) main::print1
(bool~) main::print1_$0
(label) main::print1_@1
(byte*) main::print1_at
(byte) main::print1_i
(byte) main::print1_i#1 reg byte y 16.5
(byte) main::print1_i#2 reg byte y 11.0
(byte) main::print1_j
(byte) main::print1_j#1 reg byte x 7.333333333333333
(byte) main::print1_j#2 reg byte x 16.5
(byte*) main::print1_msg
(const string) main::print1_msg#0 print1_msg = (string) "hello world!@"
(label) main::print2
(bool~) main::print2_$0
(label) main::print2_@1
(byte*) main::print2_at
(const byte*) main::print2_at#0 print2_at = (const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(byte/signed byte/word/signed word/dword/signed dword) 40
(byte) main::print2_i
(byte) main::print2_i#1 reg byte y 16.5
(byte) main::print2_i#2 reg byte y 11.0
(byte) main::print2_j
(byte) main::print2_j#1 reg byte x 7.333333333333333
(byte) main::print2_j#2 reg byte x 16.5
(byte*) main::print2_msg
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
reg byte y [ main::print1_i#2 main::print1_i#1 ]
reg byte x [ main::print1_j#2 main::print1_j#1 ]
reg byte y [ main::print2_i#2 main::print2_i#1 ]
reg byte x [ main::print2_j#2 main::print2_j#1 ]
FINAL ASSEMBLER
Score: 582
//SEG0 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG1 Global Constants & labels
.label screen = $400
//SEG2 @begin
//SEG3 [1] phi from @begin to @2 [phi:@begin->@2]
//SEG4 @2
//SEG5 [2] call main param-assignment [ ] ( )
//SEG6 [4] phi from @2 to main [phi:@2->main]
jsr main
//SEG7 [3] phi from @2 to @end [phi:@2->@end]
//SEG8 @end
//SEG9 main
main: {
.label print2_at = screen+2*$28
//SEG10 [5] phi from main to main::print1 [phi:main->main::print1]
//SEG11 main::print1
//SEG12 [6] phi from main::print1 to main::print1_@1 [phi:main::print1->main::print1_@1]
//SEG13 [6] phi (byte) main::print1_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#0] -- vbuxx=vbuc1
ldx #0
//SEG14 [6] phi (byte) main::print1_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print1->main::print1_@1#1] -- vbuyy=vbuc1
ldy #0
//SEG15 [6] phi from main::print1_@1 to main::print1_@1 [phi:main::print1_@1->main::print1_@1]
//SEG16 [6] phi (byte) main::print1_j#2 = (byte) main::print1_j#1 [phi:main::print1_@1->main::print1_@1#0] -- register_copy
//SEG17 [6] phi (byte) main::print1_i#2 = (byte) main::print1_i#1 [phi:main::print1_@1->main::print1_@1#1] -- register_copy
//SEG18 main::print1_@1
print1_b1:
//SEG19 [7] *((const byte*) screen#0 + (byte) main::print1_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print1_i#2) [ main::print1_i#2 main::print1_j#2 ] ( main:2 [ main::print1_i#2 main::print1_j#2 ] ) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
lda print1_msg,y
sta screen,x
//SEG20 [8] (byte) main::print1_j#1 ← (byte) main::print1_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print1_i#2 main::print1_j#1 ] ( main:2 [ main::print1_i#2 main::print1_j#1 ] ) -- vbuxx=vbuxx_plus_2
inx
inx
//SEG21 [9] (byte) main::print1_i#1 ← ++ (byte) main::print1_i#2 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- vbuyy=_inc_vbuyy
iny
//SEG22 [10] if(*((const string) main::print1_msg#0 + (byte) main::print1_i#1)!=(byte) '@') goto main::print1_@1 [ main::print1_i#1 main::print1_j#1 ] ( main:2 [ main::print1_i#1 main::print1_j#1 ] ) -- pbuc1_derefidx_vbuyy_neq_vbuc2_then_la1
lda print1_msg,y
cmp #'@'
bne print1_b1
//SEG23 [11] phi from main::print1_@1 to main::print2 [phi:main::print1_@1->main::print2]
//SEG24 main::print2
//SEG25 [12] phi from main::print2 to main::print2_@1 [phi:main::print2->main::print2_@1]
//SEG26 [12] phi (byte) main::print2_j#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#0] -- vbuxx=vbuc1
ldx #0
//SEG27 [12] phi (byte) main::print2_i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main::print2->main::print2_@1#1] -- vbuyy=vbuc1
ldy #0
//SEG28 [12] phi from main::print2_@1 to main::print2_@1 [phi:main::print2_@1->main::print2_@1]
//SEG29 [12] phi (byte) main::print2_j#2 = (byte) main::print2_j#1 [phi:main::print2_@1->main::print2_@1#0] -- register_copy
//SEG30 [12] phi (byte) main::print2_i#2 = (byte) main::print2_i#1 [phi:main::print2_@1->main::print2_@1#1] -- register_copy
//SEG31 main::print2_@1
print2_b1:
//SEG32 [13] *((const byte*) main::print2_at#0 + (byte) main::print2_j#2) ← *((const string) main::print1_msg#0 + (byte) main::print2_i#2) [ main::print2_i#2 main::print2_j#2 ] ( main:2 [ main::print2_i#2 main::print2_j#2 ] ) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuyy
lda print1_msg,y
sta print2_at,x
//SEG33 [14] (byte) main::print2_j#1 ← (byte) main::print2_j#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::print2_i#2 main::print2_j#1 ] ( main:2 [ main::print2_i#2 main::print2_j#1 ] ) -- vbuxx=vbuxx_plus_2
inx
inx
//SEG34 [15] (byte) main::print2_i#1 ← ++ (byte) main::print2_i#2 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- vbuyy=_inc_vbuyy
iny
//SEG35 [16] if(*((const string) main::print1_msg#0 + (byte) main::print2_i#1)!=(byte) '@') goto main::print2_@1 [ main::print2_i#1 main::print2_j#1 ] ( main:2 [ main::print2_i#1 main::print2_j#1 ] ) -- pbuc1_derefidx_vbuyy_neq_vbuc2_then_la1
lda print1_msg,y
cmp #'@'
bne print2_b1
//SEG36 main::@return
//SEG37 [17] return [ ] ( main:2 [ ] )
rts
print1_msg: .text "hello world!@"
}

View File

@ -0,0 +1,37 @@
(label) @2
(label) @begin
(label) @end
(void()) main()
(label) main::@return
(byte*) main::hello
(label) main::print1
(bool~) main::print1_$0
(label) main::print1_@1
(byte*) main::print1_at
(byte) main::print1_i
(byte) main::print1_i#1 reg byte y 16.5
(byte) main::print1_i#2 reg byte y 11.0
(byte) main::print1_j
(byte) main::print1_j#1 reg byte x 7.333333333333333
(byte) main::print1_j#2 reg byte x 16.5
(byte*) main::print1_msg
(const string) main::print1_msg#0 print1_msg = (string) "hello world!@"
(label) main::print2
(bool~) main::print2_$0
(label) main::print2_@1
(byte*) main::print2_at
(const byte*) main::print2_at#0 print2_at = (const byte*) screen#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(byte/signed byte/word/signed word/dword/signed dword) 40
(byte) main::print2_i
(byte) main::print2_i#1 reg byte y 16.5
(byte) main::print2_i#2 reg byte y 11.0
(byte) main::print2_j
(byte) main::print2_j#1 reg byte x 7.333333333333333
(byte) main::print2_j#2 reg byte x 16.5
(byte*) main::print2_msg
(byte*) screen
(const byte*) screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024
reg byte y [ main::print1_i#2 main::print1_i#1 ]
reg byte x [ main::print1_j#2 main::print1_j#1 ]
reg byte y [ main::print2_i#2 main::print2_i#1 ]
reg byte x [ main::print2_j#2 main::print2_j#1 ]