diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index a40c03ad9..1d171bf00 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -48,6 +48,7 @@ public class Pass4CodeGeneration { for (ControlFlowBlock block : getGraph().getAllBlocks()) { if (!block.getScope().equals(currentScope)) { if (!ScopeRef.ROOT.equals(currentScope)) { + addData(asm, currentScope); asm.addScopeEnd(); } currentScope = block.getScope(); @@ -56,7 +57,6 @@ public class Pass4CodeGeneration { // Add all ZP labels for the scope addConstants(asm, currentScope); addZpLabels(asm, currentScope); - addData(asm, currentScope); } // Generate entry points (if needed) genBlockEntryPoints(asm, block); @@ -87,6 +87,7 @@ public class Pass4CodeGeneration { } } if (!ScopeRef.ROOT.equals(currentScope)) { + addData(asm, currentScope); asm.addScopeEnd(); } program.setAsm(asm); diff --git a/src/main/java/dk/camelot64/kickc/test/TestErrors.java b/src/main/java/dk/camelot64/kickc/test/TestErrors.java index c1ae6ce89..f127515b7 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestErrors.java +++ b/src/main/java/dk/camelot64/kickc/test/TestErrors.java @@ -24,10 +24,6 @@ public class TestErrors extends TestCase { helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); } - public void testLocalString() throws IOException, URISyntaxException { - compileAndCompare("local-string"); - } - public void testInlineString() throws IOException, URISyntaxException { compileAndCompare("inline-string"); } @@ -54,11 +50,6 @@ public class TestErrors extends TestCase { compileAndCompare(filename); } - public void testInlineArrayProblem() throws IOException, URISyntaxException { - String filename = "inlinearrayproblem"; - compileAndCompare(filename); - } - public void testForIncrementAssign() throws IOException, URISyntaxException { String filename = "forincrementassign"; compileAndCompare(filename); diff --git a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java index 250df5442..e4d5c99d1 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java @@ -24,6 +24,15 @@ public class TestPrograms extends TestCase { helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); } + public void testLocalString() throws IOException, URISyntaxException { + compileAndCompare("local-string"); + } + + public void testInlineArrayProblem() throws IOException, URISyntaxException { + String filename = "inlinearrayproblem"; + compileAndCompare(filename); + } + public void testImmZero() throws IOException, URISyntaxException { compileAndCompare("immzero"); } diff --git a/src/main/java/dk/camelot64/kickc/test/inlinearrayproblem.kc b/src/main/java/dk/camelot64/kickc/test/inlinearrayproblem.kc index ff7a26d6b..cbae1c676 100644 --- a/src/main/java/dk/camelot64/kickc/test/inlinearrayproblem.kc +++ b/src/main/java/dk/camelot64/kickc/test/inlinearrayproblem.kc @@ -2,9 +2,12 @@ // The following places the text at the start of the main-function - and JSR's straight into the text - not the code. byte* SCREEN = $0400; +byte* SCREEN2 = $0400+$28; void main() { byte[] txt = "qwe"; + byte[] data = { 1, 2, 3 }; for( byte i : 0..3) { SCREEN[i] = txt[i]; + SCREEN2[i] = data[i]; } } \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.asm b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.asm new file mode 100644 index 000000000..1d08a5c8d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.asm @@ -0,0 +1,20 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SCREEN = $400 + .const SCREEN2 = $400+$28 + jsr main +main: { + ldx #0 + b1: + lda txt,x + sta SCREEN,x + lda data,x + sta SCREEN2,x + inx + cpx #4 + bne b1 + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.cfg b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.cfg new file mode 100644 index 000000000..d23ed301b --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.cfg @@ -0,0 +1,21 @@ +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] ( main:0 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@1 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::i#1 ) [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) + [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) + [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] ( main:0 [ ] ) + to:@return diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.log b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.log new file mode 100644 index 000000000..697a16c21 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.log @@ -0,0 +1,1046 @@ +// Arrays / strings allocated inline destroy functions (because they are allocated where the call enters. +// The following places the text at the start of the main-function - and JSR's straight into the text - not the code. + +byte* SCREEN = $0400; +byte* SCREEN2 = $0400+$28; +void main() { + byte[] txt = "qwe"; + byte[] data = { 1, 2, 3 }; + for( byte i : 0..3) { + SCREEN[i] = txt[i]; + SCREEN2[i] = data[i]; + } +} +PROGRAM + (byte*) SCREEN ← (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2 ← (word/signed word~) $0 +proc (void()) main() + (byte[]) main::txt ← (string) "qwe" + (byte[]) main::data ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i ← (byte/signed byte/word/signed word) 0 +main::@1: + (byte~) main::$0 ← (byte[]) main::txt *idx (byte) main::i + *((byte*) SCREEN + (byte) main::i) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data *idx (byte) main::i + *((byte*) SCREEN2 + (byte) main::i) ← (byte~) main::$1 + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$2 ← (byte) main::i != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 +main::@return: + return +endproc // main() + call main + +SYMBOLS +(word/signed word~) $0 +(byte*) SCREEN +(byte*) SCREEN2 +(void()) main() +(byte~) main::$0 +(byte~) main::$1 +(boolean~) main::$2 +(label) main::@1 +(label) main::@return +(byte[]) main::data +(byte) main::i +(byte[]) main::txt + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from + (byte[]) main::txt ← (string) "qwe" + (byte[]) main::data ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte~) main::$0 ← (byte[]) main::txt *idx (byte) main::i + *((byte*) SCREEN + (byte) main::i) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data *idx (byte) main::i + *((byte*) SCREEN2 + (byte) main::i) ← (byte~) main::$1 + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$2 ← (byte) main::i != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +Removing empty block main::@2 +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from + (byte[]) main::txt ← (string) "qwe" + (byte[]) main::data ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte~) main::$0 ← (byte[]) main::txt *idx (byte) main::i + *((byte*) SCREEN + (byte) main::i) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data *idx (byte) main::i + *((byte*) SCREEN2 + (byte) main::i) ← (byte~) main::$1 + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$2 ← (byte) main::i != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +PROCEDURE MODIFY VARIABLE ANALYSIS + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL +@begin: scope:[] from + (byte*) SCREEN ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte[]) main::txt ← (string) "qwe" + (byte[]) main::data ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte~) main::$0 ← (byte[]) main::txt *idx (byte) main::i + *((byte*) SCREEN + (byte) main::i) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data *idx (byte) main::i + *((byte*) SCREEN2 + (byte) main::i) ← (byte~) main::$1 + (byte) main::i ← ++ (byte) main::i + (boolean~) main::$2 ← (byte) main::i != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte*) SCREEN2#2 ← phi( @1/(byte*) SCREEN2#3 ) + (byte*) SCREEN#2 ← phi( @1/(byte*) SCREEN#3 ) + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte*) SCREEN2#1 ← phi( main/(byte*) SCREEN2#2 main::@1/(byte*) SCREEN2#1 ) + (byte[]) main::data#1 ← phi( main/(byte[]) main::data#0 main::@1/(byte[]) main::data#1 ) + (byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#2 main::@1/(byte*) SCREEN#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte[]) main::txt#1 ← phi( main/(byte[]) main::txt#0 main::@1/(byte[]) main::txt#1 ) + (byte~) main::$0 ← (byte[]) main::txt#1 *idx (byte) main::i#2 + *((byte*) SCREEN#1 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#1 *idx (byte) main::i#2 + *((byte*) SCREEN2#1 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + (byte*) SCREEN2#3 ← phi( @begin/(byte*) SCREEN2#0 ) + (byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte*) SCREEN2#2 ← phi( @1/(byte*) SCREEN2#3 ) + (byte*) SCREEN#2 ← phi( @1/(byte*) SCREEN#3 ) + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte*) SCREEN2#1 ← phi( main/(byte*) SCREEN2#2 main::@1/(byte*) SCREEN2#1 ) + (byte[]) main::data#1 ← phi( main/(byte[]) main::data#0 main::@1/(byte[]) main::data#1 ) + (byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#2 main::@1/(byte*) SCREEN#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte[]) main::txt#1 ← phi( main/(byte[]) main::txt#0 main::@1/(byte[]) main::txt#1 ) + (byte~) main::$0 ← (byte[]) main::txt#1 *idx (byte) main::i#2 + *((byte*) SCREEN#1 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#1 *idx (byte) main::i#2 + *((byte*) SCREEN2#1 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + (byte*) SCREEN2#3 ← phi( @begin/(byte*) SCREEN2#0 ) + (byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +INITIAL SSA SYMBOL TABLE +(word/signed word~) $0 +(label) @1 +(label) @2 +(label) @begin +(label) @end +(byte*) SCREEN +(byte*) SCREEN#0 +(byte*) SCREEN#1 +(byte*) SCREEN#2 +(byte*) SCREEN#3 +(byte*) SCREEN2 +(byte*) SCREEN2#0 +(byte*) SCREEN2#1 +(byte*) SCREEN2#2 +(byte*) SCREEN2#3 +(void()) main() +(byte~) main::$0 +(byte~) main::$1 +(boolean~) main::$2 +(label) main::@1 +(label) main::@return +(byte[]) main::data +(byte[]) main::data#0 +(byte[]) main::data#1 +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte[]) main::txt +(byte[]) main::txt#0 +(byte[]) main::txt#1 + +Culled Empty Block (label) @2 +Succesful SSA optimization Pass2CullEmptyBlocks +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte*) SCREEN2#2 ← phi( @1/(byte*) SCREEN2#3 ) + (byte*) SCREEN#2 ← phi( @1/(byte*) SCREEN#3 ) + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte*) SCREEN2#1 ← phi( main/(byte*) SCREEN2#2 main::@1/(byte*) SCREEN2#1 ) + (byte[]) main::data#1 ← phi( main/(byte[]) main::data#0 main::@1/(byte[]) main::data#1 ) + (byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#2 main::@1/(byte*) SCREEN#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte[]) main::txt#1 ← phi( main/(byte[]) main::txt#0 main::@1/(byte[]) main::txt#1 ) + (byte~) main::$0 ← (byte[]) main::txt#1 *idx (byte) main::i#2 + *((byte*) SCREEN#1 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#1 *idx (byte) main::i#2 + *((byte*) SCREEN2#1 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + (byte*) SCREEN2#3 ← phi( @begin/(byte*) SCREEN2#0 ) + (byte*) SCREEN#3 ← phi( @begin/(byte*) SCREEN#0 ) + call main param-assignment + to:@end +@end: scope:[] from @1 + +Alias (byte*) SCREEN#0 = (byte*) SCREEN#2 (byte*) SCREEN#3 +Alias (byte*) SCREEN2#0 = (byte*) SCREEN2#2 (byte*) SCREEN2#3 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte*) SCREEN2#1 ← phi( main/(byte*) SCREEN2#0 main::@1/(byte*) SCREEN2#1 ) + (byte[]) main::data#1 ← phi( main/(byte[]) main::data#0 main::@1/(byte[]) main::data#1 ) + (byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#0 main::@1/(byte*) SCREEN#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte[]) main::txt#1 ← phi( main/(byte[]) main::txt#0 main::@1/(byte[]) main::txt#1 ) + (byte~) main::$0 ← (byte[]) main::txt#1 *idx (byte) main::i#2 + *((byte*) SCREEN#1 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#1 *idx (byte) main::i#2 + *((byte*) SCREEN2#1 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Self Phi Eliminated (byte[]) main::txt#1 +Self Phi Eliminated (byte*) SCREEN#1 +Self Phi Eliminated (byte[]) main::data#1 +Self Phi Eliminated (byte*) SCREEN2#1 +Succesful SSA optimization Pass2SelfPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte*) SCREEN2#1 ← phi( main/(byte*) SCREEN2#0 ) + (byte[]) main::data#1 ← phi( main/(byte[]) main::data#0 ) + (byte*) SCREEN#1 ← phi( main/(byte*) SCREEN#0 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte[]) main::txt#1 ← phi( main/(byte[]) main::txt#0 ) + (byte~) main::$0 ← (byte[]) main::txt#1 *idx (byte) main::i#2 + *((byte*) SCREEN#1 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#1 *idx (byte) main::i#2 + *((byte*) SCREEN2#1 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Redundant Phi (byte[]) main::txt#1 (byte[]) main::txt#0 +Redundant Phi (byte*) SCREEN#1 (byte*) SCREEN#0 +Redundant Phi (byte[]) main::data#1 (byte[]) main::data#0 +Redundant Phi (byte*) SCREEN2#1 (byte*) SCREEN2#0 +Succesful SSA optimization Pass2RedundantPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$0 ← (byte[]) main::txt#0 *idx (byte) main::i#2 + *((byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#0 *idx (byte) main::i#2 + *((byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + (boolean~) main::$2 ← (byte) main::i#1 != (byte/signed byte/word/signed word) 4 + if((boolean~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Simple Condition (boolean~) main::$2 if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN#0 ← ((byte*)) (word/signed word) 1024 + (word/signed word~) $0 ← (word/signed word) 1024 + (byte/signed byte/word/signed word) 40 + (byte*) SCREEN2#0 ← ((byte*)) (word/signed word~) $0 + to:@1 +main: scope:[main] from @1 + (byte[]) main::txt#0 ← (string) "qwe" + (byte[]) main::data#0 ← { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$0 ← (byte[]) main::txt#0 *idx (byte) main::i#2 + *((byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (byte[]) main::data#0 *idx (byte) main::i#2 + *((byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Constant (const byte*) SCREEN#0 = ((byte*))1024 +Constant (const word/signed word) $0 = 1024+40 +Constant (const byte[]) main::txt#0 = "qwe" +Constant (const byte[]) main::data#0 = { 1, 2, 3 } +Constant (const byte) main::i#0 = 0 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte*) SCREEN2#0 ← ((byte*)) (const word/signed word) $0 + to:@1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 + *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 + *((byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Constant (const byte*) SCREEN2#0 = ((byte*))$0 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@1/(byte) main::i#1 ) + (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 + *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 + *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined $0 = (word/signed word) 1024+(byte/signed byte/word/signed word) 40 +Constant inlined main::i#0 = (byte/signed byte/word/signed word) 0 +Succesful SSA optimization Pass2ConstantInlining +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::i#1 ) + (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 + *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 + *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 = ((byte*))(word/signed word) 1024 +(byte*) SCREEN2 +(const byte*) SCREEN2#0 = ((byte*))(word/signed word) 1024+(byte/signed byte/word/signed word) 40 +(void()) main() +(byte~) main::$0 +(byte~) main::$1 +(label) main::@1 +(label) main::@return +(byte[]) main::data +(const byte[]) main::data#0 = { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } +(byte) main::i +(byte) main::i#1 +(byte) main::i#2 +(byte[]) main::txt +(const byte[]) main::txt#0 = (string) "qwe" + +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@3 +CONTROL FLOW GRAPH - PHI LIFTED +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@3 + (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@3/(byte~) main::i#3 ) + (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 + *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 + (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 + *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 + (byte) main::i#1 ← ++ (byte) main::i#2 + if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@3 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +main::@3: scope:[main] from main::@1 + (byte~) main::i#3 ← (byte) main::i#1 + to:main::@1 + +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:0 + +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES FOUND +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@3 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@3/(byte~) main::i#3 ) [ main::i#2 ] + [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] + [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] + [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] + [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] + [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@3 [ main::i#1 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] + to:@return +main::@3: scope:[main] from main::@1 + [10] (byte~) main::i#3 ← (byte) main::i#1 [ main::i#3 ] + to:main::@1 + +Created 1 initial phi equivalence classes +Coalesced [10] main::i#3 ← main::i#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) main::@3 +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Adding NOP phi() at start of main +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@1 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::i#1 ) [ main::i#2 ] + [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] + [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] + [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] + [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] + [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] + to:@return + +CONTROL FLOW GRAPH - PHI MEM COALESCED +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] ( main:0 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@1 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::i#1 ) [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) + [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) + [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] ( main:0 [ ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@1 dominated by @1 @begin +@end dominated by @1 @begin @end +main dominated by @1 @begin main +main::@1 dominated by @1 @begin main::@1 main +main::@return dominated by main::@return @1 @begin main::@1 main + +Found back edge: Loop head: main::@1 tails: main::@1 blocks: null +Populated: Loop head: main::@1 tails: main::@1 blocks: main::@1 +NATURAL LOOPS +Loop head: main::@1 tails: main::@1 blocks: main::@1 + +Found 0 loops in scope [] +Found 1 loops in scope [main] + Loop head: main::@1 tails: main::@1 blocks: main::@1 +NATURAL LOOPS WITH DEPTH +Loop head: main::@1 tails: main::@1 blocks: main::@1 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(byte*) SCREEN +(byte*) SCREEN2 +(void()) main() +(byte~) main::$0 22.0 +(byte~) main::$1 22.0 +(byte[]) main::data +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 13.2 +(byte[]) main::txt + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +Added variable main::$0 to zero page equivalence class [ main::$0 ] +Added variable main::$1 to zero page equivalence class [ main::$1 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::$0 ] +[ main::$1 ] +Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Allocated zp ZP_BYTE:3 [ main::$0 ] +Allocated zp ZP_BYTE:4 [ main::$1 ] +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +bbegin: + jmp b1 +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + jmp bend +//SEG6 @end +bend: +//SEG7 main +main: { + .label _0 = 3 + .label _1 = 4 + .label i = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpby1=coby1 + lda #0 + sta i + jmp b1 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- zpby1=cowo1_derefidx_zpby2 + ldx i + lda txt,x + sta _0 + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_zpby1=zpby2 + lda _0 + ldx i + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- zpby1=cowo1_derefidx_zpby2 + ldx i + lda data,x + sta _1 + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_zpby1=zpby2 + lda _1 + ldx i + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- zpby1=_inc_zpby1 + inc i + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- zpby1_neq_coby1_then_la1 + lda i + cmp #4 + bne b1_from_b1 + jmp breturn + //SEG19 main::@return + breturn: + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:4 [ main::$1 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 29.7: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:3 [ main::$0 ] 22: zp ZP_BYTE:4 [ main::$1 ] +Uplift Scope [] + +Uplifting [main] best 410 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 410 combination +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +bbegin: +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda txt,x + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- aby=cowo1_derefidx_xby + lda data,x + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #4 + bne b1_from_b1 + //SEG19 main::@return + breturn: + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + +Replacing label b1_from_b1 with b1 +Removing instruction bbegin: +Removing instruction main_from_b1: +Removing instruction b1_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda txt,x + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- aby=cowo1_derefidx_xby + lda data,x + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #4 + bne b1 + //SEG19 main::@return + breturn: + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + +Removing instruction b1: +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +//SEG3 @1 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + jmp b1 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda txt,x + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- aby=cowo1_derefidx_xby + lda data,x + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #4 + bne b1 + //SEG19 main::@return + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +//SEG3 @1 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda txt,x + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- aby=cowo1_derefidx_xby + lda data,x + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #4 + bne b1 + //SEG19 main::@return + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word) 1024 +(byte*) SCREEN2 +(const byte*) SCREEN2#0 SCREEN2 = ((byte*))(word/signed word) 1024+(byte/signed byte/word/signed word) 40 +(void()) main() +(byte~) main::$0 reg byte a 22.0 +(byte~) main::$1 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte[]) main::data +(const byte[]) main::data#0 data = { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 13.2 +(byte[]) main::txt +(const byte[]) main::txt#0 txt = (string) "qwe" + +reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] +reg byte a [ main::$1 ] + +FINAL CODE +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SCREEN = $400 + .const SCREEN2 = $400+$28 +//SEG2 @begin +//SEG3 @1 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG11 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG12 main::@1 + b1: + //SEG13 [3] (byte~) main::$0 ← (const byte[]) main::txt#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda txt,x + //SEG14 [4] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte~) main::$0 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN,x + //SEG15 [5] (byte~) main::$1 ← (const byte[]) main::data#0 *idx (byte) main::i#2 [ main::i#2 main::$1 ] ( main:0 [ main::i#2 main::$1 ] ) -- aby=cowo1_derefidx_xby + lda data,x + //SEG16 [6] *((const byte*) SCREEN2#0 + (byte) main::i#2) ← (byte~) main::$1 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta SCREEN2,x + //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word) 4) goto main::@1 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby_neq_coby1_then_la1 + cpx #4 + bne b1 + //SEG19 main::@return + //SEG20 [9] return [ ] ( main:0 [ ] ) + rts + txt: .text "qwe" + data: .byte 1, 2, 3 +} + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.sym b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.sym new file mode 100644 index 000000000..3bbb78a00 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inlinearrayproblem.sym @@ -0,0 +1,23 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word) 1024 +(byte*) SCREEN2 +(const byte*) SCREEN2#0 SCREEN2 = ((byte*))(word/signed word) 1024+(byte/signed byte/word/signed word) 40 +(void()) main() +(byte~) main::$0 reg byte a 22.0 +(byte~) main::$1 reg byte a 22.0 +(label) main::@1 +(label) main::@return +(byte[]) main::data +(const byte[]) main::data#0 data = { (byte/signed byte/word/signed word) 1, (byte/signed byte/word/signed word) 2, (byte/signed byte/word/signed word) 3 } +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 13.2 +(byte[]) main::txt +(const byte[]) main::txt#0 txt = (string) "qwe" + +reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] +reg byte a [ main::$1 ] diff --git a/src/main/java/dk/camelot64/kickc/test/ref/local-string.asm b/src/main/java/dk/camelot64/kickc/test/ref/local-string.asm new file mode 100644 index 000000000..43138a9c6 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/local-string.asm @@ -0,0 +1,19 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + jsr main +main: { + .const screen = $400 + ldx #0 + b1: + lda msg,x + cmp #'@' + bne b2 + rts + b2: + lda msg,x + sta screen,x + inx + jmp b1 + msg: .text "message 2 @" +} diff --git a/src/main/java/dk/camelot64/kickc/test/ref/local-string.cfg b/src/main/java/dk/camelot64/kickc/test/ref/local-string.cfg new file mode 100644 index 000000000..e4fb1fbf8 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/local-string.cfg @@ -0,0 +1,22 @@ +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] ( main:0 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@2 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte) main::i#1 ) [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) + [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [5] return [ ] ( main:0 [ ] ) + to:@return +main::@2: scope:[main] from main::@1 + [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) + [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + to:main::@1 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/local-string.log b/src/main/java/dk/camelot64/kickc/test/ref/local-string.log new file mode 100644 index 000000000..618c0781e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/local-string.log @@ -0,0 +1,917 @@ +// Local constant strings are placed at the start of the method. This means the generated ASM jumps / calls straignt into the constant string +void main() { + byte* screen = $0400; + byte[] msg = "message 2 @"; + byte i=0; + while(msg[i]!='@') { + screen[i++] = msg[i]; + } +} + +Adding pre/post-modifier (byte) main::i ← ++ (byte) main::i +PROGRAM +proc (void()) main() + (byte*) main::screen ← (word/signed word) 1024 + (byte[]) main::msg ← (string) "message 2 @" + (byte) main::i ← (byte/signed byte/word/signed word) 0 +main::@1: + (byte~) main::$0 ← (byte[]) main::msg *idx (byte) main::i + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + goto main::@3 +main::@2: + (byte~) main::$2 ← (byte[]) main::msg *idx (byte) main::i + *((byte*) main::screen + (byte) main::i) ← (byte~) main::$2 + (byte) main::i ← ++ (byte) main::i + goto main::@1 +main::@3: +main::@return: + return +endproc // main() + call main + +SYMBOLS +(void()) main() +(byte~) main::$0 +(boolean~) main::$1 +(byte~) main::$2 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte) main::i +(byte[]) main::msg +(byte*) main::screen + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from + (byte*) main::screen ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg ← (string) "message 2 @" + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte~) main::$0 ← (byte[]) main::msg *idx (byte) main::i + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@4 +main::@2: scope:[main] from main::@1 main::@5 + (byte~) main::$2 ← (byte[]) main::msg *idx (byte) main::i + *((byte*) main::screen + (byte) main::i) ← (byte~) main::$2 + (byte) main::i ← ++ (byte) main::i + to:main::@1 +main::@4: scope:[main] from main::@1 + to:main::@3 +main::@3: scope:[main] from main::@4 main::@6 + to:main::@return +main::@5: scope:[main] from + to:main::@2 +main::@6: scope:[main] from + to:main::@3 +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +Removing empty block main::@4 +Removing empty block main::@3 +Removing empty block main::@5 +Removing empty block main::@6 +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from + (byte*) main::screen ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg ← (string) "message 2 @" + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte~) main::$0 ← (byte[]) main::msg *idx (byte) main::i + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg *idx (byte) main::i + *((byte*) main::screen + (byte) main::i) ← (byte~) main::$2 + (byte) main::i ← ++ (byte) main::i + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +PROCEDURE MODIFY VARIABLE ANALYSIS + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg ← (string) "message 2 @" + (byte) main::i ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte~) main::$0 ← (byte[]) main::msg *idx (byte) main::i + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg *idx (byte) main::i + *((byte*) main::screen + (byte) main::i) ← (byte~) main::$2 + (byte) main::i ← ++ (byte) main::i + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +Completing Phi functions... +Completing Phi functions... +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte*) main::screen#2 ← phi( main/(byte*) main::screen#0 main::@2/(byte*) main::screen#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte[]) main::msg#1 ← phi( main/(byte[]) main::msg#0 main::@2/(byte[]) main::msg#2 ) + (byte~) main::$0 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte*) main::screen#1 ← phi( main::@1/(byte*) main::screen#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte[]) main::msg#2 ← phi( main::@1/(byte[]) main::msg#1 ) + (byte~) main::$2 ← (byte[]) main::msg#2 *idx (byte) main::i#3 + *((byte*) main::screen#1 + (byte) main::i#3) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#3 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte*) main::screen#2 ← phi( main/(byte*) main::screen#0 main::@2/(byte*) main::screen#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte[]) main::msg#1 ← phi( main/(byte[]) main::msg#0 main::@2/(byte[]) main::msg#2 ) + (byte~) main::$0 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte*) main::screen#1 ← phi( main::@1/(byte*) main::screen#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte[]) main::msg#2 ← phi( main::@1/(byte[]) main::msg#1 ) + (byte~) main::$2 ← (byte[]) main::msg#2 *idx (byte) main::i#3 + *((byte*) main::screen#1 + (byte) main::i#3) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#3 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +INITIAL SSA SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(void()) main() +(byte~) main::$0 +(boolean~) main::$1 +(byte~) main::$2 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::i#3 +(byte[]) main::msg +(byte[]) main::msg#0 +(byte[]) main::msg#1 +(byte[]) main::msg#2 +(byte*) main::screen +(byte*) main::screen#0 +(byte*) main::screen#1 +(byte*) main::screen#2 + +Culled Empty Block (label) @2 +Succesful SSA optimization Pass2CullEmptyBlocks +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte*) main::screen#2 ← phi( main/(byte*) main::screen#0 main::@2/(byte*) main::screen#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte[]) main::msg#1 ← phi( main/(byte[]) main::msg#0 main::@2/(byte[]) main::msg#2 ) + (byte~) main::$0 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte*) main::screen#1 ← phi( main::@1/(byte*) main::screen#2 ) + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte[]) main::msg#2 ← phi( main::@1/(byte[]) main::msg#1 ) + (byte~) main::$2 ← (byte[]) main::msg#2 *idx (byte) main::i#3 + *((byte*) main::screen#1 + (byte) main::i#3) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#3 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Alias (byte[]) main::msg#1 = (byte[]) main::msg#2 +Alias (byte) main::i#2 = (byte) main::i#3 +Alias (byte*) main::screen#1 = (byte*) main::screen#2 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte*) main::screen#1 ← phi( main/(byte*) main::screen#0 main::@2/(byte*) main::screen#1 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte[]) main::msg#1 ← phi( main/(byte[]) main::msg#0 main::@2/(byte[]) main::msg#1 ) + (byte~) main::$0 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + *((byte*) main::screen#1 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Self Phi Eliminated (byte[]) main::msg#1 +Self Phi Eliminated (byte*) main::screen#1 +Succesful SSA optimization Pass2SelfPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte*) main::screen#1 ← phi( main/(byte*) main::screen#0 ) + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte[]) main::msg#1 ← phi( main/(byte[]) main::msg#0 ) + (byte~) main::$0 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg#1 *idx (byte) main::i#2 + *((byte*) main::screen#1 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Redundant Phi (byte[]) main::msg#1 (byte[]) main::msg#0 +Redundant Phi (byte*) main::screen#1 (byte*) main::screen#0 +Succesful SSA optimization Pass2RedundantPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte~) main::$0 ← (byte[]) main::msg#0 *idx (byte) main::i#2 + (boolean~) main::$1 ← (byte~) main::$0 != (byte) '@' + if((boolean~) main::$1) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg#0 *idx (byte) main::i#2 + *((byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Simple Condition (boolean~) main::$1 if((byte~) main::$0!=(byte) '@') goto main::@2 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word) 1024 + (byte[]) main::msg#0 ← (string) "message 2 @" + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte~) main::$0 ← (byte[]) main::msg#0 *idx (byte) main::i#2 + if((byte~) main::$0!=(byte) '@') goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (byte[]) main::msg#0 *idx (byte) main::i#2 + *((byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Constant (const byte*) main::screen#0 = ((byte*))1024 +Constant (const byte[]) main::msg#0 = "message 2 @" +Constant (const byte) main::i#0 = 0 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte) main::i#2 ← phi( main/(const byte) main::i#0 main::@2/(byte) main::i#1 ) + (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + if((byte~) main::$0!=(byte) '@') goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) main::i#2 +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::i#0 = (byte/signed byte/word/signed word) 0 +Succesful SSA optimization Pass2ConstantInlining +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte) main::i#1 ) + (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + if((byte~) main::$0!=(byte) '@') goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(byte~) main::$0 +(byte~) main::$2 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte) main::i +(byte) main::i#1 +(byte) main::i#2 +(byte[]) main::msg +(const byte[]) main::msg#0 = (string) "message 2 @" +(byte*) main::screen +(const byte*) main::screen#0 = ((byte*))(word/signed word) 1024 + +Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@2 +Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@2 +CONTROL FLOW GRAPH - PHI LIFTED +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + to:main::@1 +main::@1: scope:[main] from main main::@2 + (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte~) main::i#4 ) + (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + if((byte~) main::$0!=(byte) '@') goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +main::@2: scope:[main] from main::@1 + (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 + *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 + (byte) main::i#1 ← ++ (byte) main::i#2 + (byte~) main::i#4 ← (byte) main::i#1 + to:main::@1 + +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:0 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES FOUND +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@2 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte~) main::i#4 ) [ main::i#2 ] + [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] + [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [5] return [ ] + to:@return +main::@2: scope:[main] from main::@1 + [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] + [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] + [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + [9] (byte~) main::i#4 ← (byte) main::i#1 [ main::i#4 ] + to:main::@1 + +Created 1 initial phi equivalence classes +Coalesced [9] main::i#4 ← main::i#1 +Coalesced down to 1 phi equivalence classes +Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@2 +Adding NOP phi() at start of main +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] + to:main::@1 +main::@1: scope:[main] from main main::@2 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte) main::i#1 ) [ main::i#2 ] + [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] + [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [5] return [ ] + to:@return +main::@2: scope:[main] from main::@1 + [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] + [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] + [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] + to:main::@1 + +CONTROL FLOW GRAPH - PHI MEM COALESCED +@begin: scope:[] from + to:@1 +@1: scope:[] from @begin + [0] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 +main: scope:[main] from @1 + [1] phi() [ ] ( main:0 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@2 + [2] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word) 0 main::@2/(byte) main::i#1 ) [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) + [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [5] return [ ] ( main:0 [ ] ) + to:@return +main::@2: scope:[main] from main::@1 + [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) + [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) + [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) + to:main::@1 + +DOMINATORS +@begin dominated by @begin +@1 dominated by @1 @begin +@end dominated by @1 @begin @end +main dominated by @1 @begin main +main::@1 dominated by @1 @begin main::@1 main +main::@return dominated by main::@return @1 @begin main::@1 main +main::@2 dominated by @1 @begin main::@1 main::@2 main + +Found back edge: Loop head: main::@1 tails: main::@2 blocks: null +Populated: Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 +NATURAL LOOPS +Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 + +Found 0 loops in scope [] +Found 1 loops in scope [main] + Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 +NATURAL LOOPS WITH DEPTH +Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte~) main::$0 22.0 +(byte~) main::$2 22.0 +(byte) main::i +(byte) main::i#1 22.0 +(byte) main::i#2 11.0 +(byte[]) main::msg +(byte*) main::screen + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +Added variable main::$0 to zero page equivalence class [ main::$0 ] +Added variable main::$2 to zero page equivalence class [ main::$2 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ main::$0 ] +[ main::$2 ] +Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Allocated zp ZP_BYTE:3 [ main::$0 ] +Allocated zp ZP_BYTE:4 [ main::$2 ] +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: + jmp b1 +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + jmp bend +//SEG6 @end +bend: +//SEG7 main +main: { + .const screen = $400 + .label _0 = 3 + .label _2 = 4 + .label i = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpby1=coby1 + lda #0 + sta i + jmp b1 + //SEG10 main::@1 + b1: + //SEG11 [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- zpby1=cowo1_derefidx_zpby2 + ldx i + lda msg,x + sta _0 + //SEG12 [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- zpby1_neq_coby1_then_la1 + lda _0 + cmp #'@' + bne b2 + jmp breturn + //SEG13 main::@return + breturn: + //SEG14 [5] return [ ] ( main:0 [ ] ) + rts + //SEG15 main::@2 + b2: + //SEG16 [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) -- zpby1=cowo1_derefidx_zpby2 + ldx i + lda msg,x + sta _2 + //SEG17 [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_zpby1=zpby2 + lda _2 + ldx i + sta screen,x + //SEG18 [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- zpby1=_inc_zpby1 + inc i + //SEG19 [2] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + b1_from_b2: + //SEG20 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp b1 + msg: .text "message 2 @" +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:4 [ main::$2 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:3 [ main::$0 ] 22: zp ZP_BYTE:4 [ main::$2 ] +Uplift Scope [] + +Uplifting [main] best 360 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] reg byte a [ main::$2 ] +Uplifting [] best 360 combination +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + .const screen = $400 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 main::@1 + b1: + //SEG11 [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG12 [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- aby_neq_coby1_then_la1 + cmp #'@' + bne b2 + //SEG13 main::@return + breturn: + //SEG14 [5] return [ ] ( main:0 [ ] ) + rts + //SEG15 main::@2 + b2: + //SEG16 [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG17 [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta screen,x + //SEG18 [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [2] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + b1_from_b2: + //SEG20 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp b1 + msg: .text "message 2 @" +} + +Removing instruction bbegin: +Removing instruction main_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 @1 +b1: +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +bend: +//SEG7 main +main: { + .const screen = $400 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 main::@1 + b1: + //SEG11 [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG12 [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- aby_neq_coby1_then_la1 + cmp #'@' + bne b2 + //SEG13 main::@return + breturn: + //SEG14 [5] return [ ] ( main:0 [ ] ) + rts + //SEG15 main::@2 + b2: + //SEG16 [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG17 [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta screen,x + //SEG18 [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [2] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + b1_from_b2: + //SEG20 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp b1 + msg: .text "message 2 @" +} + +Removing instruction b1: +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction breturn: +Removing instruction b1_from_b2: +Succesful ASM optimization Pass5UnusedLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 @1 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + .const screen = $400 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 main::@1 + b1: + //SEG11 [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG12 [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- aby_neq_coby1_then_la1 + cmp #'@' + bne b2 + //SEG13 main::@return + //SEG14 [5] return [ ] ( main:0 [ ] ) + rts + //SEG15 main::@2 + b2: + //SEG16 [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG17 [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta screen,x + //SEG18 [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [2] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + //SEG20 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp b1 + msg: .text "message 2 @" +} + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(byte~) main::$0 reg byte a 22.0 +(byte~) main::$2 reg byte a 22.0 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 22.0 +(byte) main::i#2 reg byte x 11.0 +(byte[]) main::msg +(const byte[]) main::msg#0 msg = (string) "message 2 @" +(byte*) main::screen +(const byte*) main::screen#0 screen = ((byte*))(word/signed word) 1024 + +reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] +reg byte a [ main::$2 ] + +FINAL CODE +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 @1 +//SEG4 [0] call main param-assignment [ ] ( ) +//SEG5 [1] phi from @1 to main [phi:@1->main] + jsr main +//SEG6 @end +//SEG7 main +main: { + .const screen = $400 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (byte) main::i#2 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- xby=coby1 + ldx #0 + //SEG10 main::@1 + b1: + //SEG11 [3] (byte~) main::$0 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$0 ] ( main:0 [ main::i#2 main::$0 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG12 [4] if((byte~) main::$0!=(byte) '@') goto main::@2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- aby_neq_coby1_then_la1 + cmp #'@' + bne b2 + //SEG13 main::@return + //SEG14 [5] return [ ] ( main:0 [ ] ) + rts + //SEG15 main::@2 + b2: + //SEG16 [6] (byte~) main::$2 ← (const byte[]) main::msg#0 *idx (byte) main::i#2 [ main::i#2 main::$2 ] ( main:0 [ main::i#2 main::$2 ] ) -- aby=cowo1_derefidx_xby + lda msg,x + //SEG17 [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte~) main::$2 [ main::i#2 ] ( main:0 [ main::i#2 ] ) -- cowo1_derefidx_xby=aby + sta screen,x + //SEG18 [8] (byte) main::i#1 ← ++ (byte) main::i#2 [ main::i#1 ] ( main:0 [ main::i#1 ] ) -- xby=_inc_xby + inx + //SEG19 [2] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + //SEG20 [2] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp b1 + msg: .text "message 2 @" +} + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/local-string.sym b/src/main/java/dk/camelot64/kickc/test/ref/local-string.sym new file mode 100644 index 000000000..a6bb69c17 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/local-string.sym @@ -0,0 +1,20 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(byte~) main::$0 reg byte a 22.0 +(byte~) main::$2 reg byte a 22.0 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 22.0 +(byte) main::i#2 reg byte x 11.0 +(byte[]) main::msg +(const byte[]) main::msg#0 msg = (string) "message 2 @" +(byte*) main::screen +(const byte*) main::screen#0 screen = ((byte*))(word/signed word) 1024 + +reg byte x [ main::i#2 main::i#1 ] +reg byte a [ main::$0 ] +reg byte a [ main::$2 ]