mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Now supporting more complex functions inlining.
This commit is contained in:
parent
6bd3a2dedf
commit
4e973cebc7
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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
|
607
src/test/java/dk/camelot64/kickc/test/ref/inline-function-if.log
Normal file
607
src/test/java/dk/camelot64/kickc/test/ref/inline-function-if.log
Normal 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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
@ -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
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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!@"
|
||||
}
|
@ -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
|
@ -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!@"
|
||||
}
|
||||
|
@ -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 ]
|
Loading…
Reference in New Issue
Block a user