diff --git a/src/main/java/dk/camelot64/kickc/test/ref/immzero.asm b/src/main/java/dk/camelot64/kickc/test/ref/immzero.asm new file mode 100644 index 000000000..a41a7288c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/immzero.asm @@ -0,0 +1,24 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + jsr main +main: { + .label w = 2 + lda #<0 + sta w + lda #>0 + sta w+1 + ldx #0 + b1: + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + inx + cpx #$b + bne b1 + rts +} diff --git a/src/main/java/dk/camelot64/kickc/test/ref/immzero.cfg b/src/main/java/dk/camelot64/kickc/test/ref/immzero.cfg new file mode 100644 index 000000000..5f2461971 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/immzero.cfg @@ -0,0 +1,19 @@ +@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] (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@1/(word) main::w#1 ) [ main::i#1 main::w#2 ] ( main:0 [ main::i#1 main::w#2 ] ) + [2] (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::j#1 ) [ main::i#1 main::w#2 ] ( main:0 [ main::i#1 main::w#2 ] ) + [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) + [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) + [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [6] return [ ] ( main:0 [ ] ) + to:@return diff --git a/src/main/java/dk/camelot64/kickc/test/ref/immzero.log b/src/main/java/dk/camelot64/kickc/test/ref/immzero.log new file mode 100644 index 000000000..e58eb4487 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/immzero.log @@ -0,0 +1,857 @@ +// Tests that immediate zero values are reused - even when assigning to words +void main() { + byte i = 0; + word w = (word)0; + for ( byte j : 0..10) { + i = j; + w = w + j; + } +} +PROGRAM +proc (void()) main() + (byte) main::i ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w ← (word~) main::$0 + (byte) main::j ← (byte/signed byte/word/signed word) 0 +main::@1: + (byte) main::i ← (byte) main::j + (word~) main::$1 ← (word) main::w + (byte) main::j + (word) main::w ← (word~) main::$1 + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$2 ← (byte) main::j != (byte/signed byte/word/signed word) 11 + if((boolean~) main::$2) goto main::@1 +main::@return: + return +endproc // main() + call main + +SYMBOLS +(void()) main() +(word~) main::$0 +(word~) main::$1 +(boolean~) main::$2 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::j +(word) main::w + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from + (byte) main::i ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w ← (word~) main::$0 + (byte) main::j ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i ← (byte) main::j + (word~) main::$1 ← (word) main::w + (byte) main::j + (word) main::w ← (word~) main::$1 + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$2 ← (byte) main::j != (byte/signed byte/word/signed word) 11 + 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 + to:@1 +main: scope:[main] from + (byte) main::i ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w ← (word~) main::$0 + (byte) main::j ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i ← (byte) main::j + (word~) main::$1 ← (word) main::w + (byte) main::j + (word) main::w ← (word~) main::$1 + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$2 ← (byte) main::j != (byte/signed byte/word/signed word) 11 + 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 + to:@1 +main: scope:[main] from @1 + (byte) main::i ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w ← (word~) main::$0 + (byte) main::j ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) main::i ← (byte) main::j + (word~) main::$1 ← (word) main::w + (byte) main::j + (word) main::w ← (word~) main::$1 + (byte) main::j ← ++ (byte) main::j + (boolean~) main::$2 ← (byte) main::j != (byte/signed byte/word/signed word) 11 + 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... +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w#0 ← (word~) main::$0 + (byte) main::j#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (word) main::w#2 ← phi( main/(word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::j#2 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#1 ) + (byte) main::i#1 ← (byte) main::j#2 + (word~) main::$1 ← (word) main::w#2 + (byte) main::j#2 + (word) main::w#1 ← (word~) main::$1 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$2 ← (byte) main::j#1 != (byte/signed byte/word/signed word) 11 + 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 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w#0 ← (word~) main::$0 + (byte) main::j#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (word) main::w#2 ← phi( main/(word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::j#2 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#1 ) + (byte) main::i#1 ← (byte) main::j#2 + (word~) main::$1 ← (word) main::w#2 + (byte) main::j#2 + (word) main::w#1 ← (word~) main::$1 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$2 ← (byte) main::j#1 != (byte/signed byte/word/signed word) 11 + 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 + +INITIAL SSA SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(void()) main() +(word~) main::$0 +(word~) main::$1 +(boolean~) main::$2 +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::j +(byte) main::j#0 +(byte) main::j#1 +(byte) main::j#2 +(word) main::w +(word) main::w#0 +(word) main::w#1 +(word) main::w#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::i#0 ← (byte/signed byte/word/signed word) 0 + (word~) main::$0 ← ((word)) (byte/signed byte/word/signed word) 0 + (word) main::w#0 ← (word~) main::$0 + (byte) main::j#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (word) main::w#2 ← phi( main/(word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::j#2 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#1 ) + (byte) main::i#1 ← (byte) main::j#2 + (word~) main::$1 ← (word) main::w#2 + (byte) main::j#2 + (word) main::w#1 ← (word~) main::$1 + (byte) main::j#1 ← ++ (byte) main::j#2 + (boolean~) main::$2 ← (byte) main::j#1 != (byte/signed byte/word/signed word) 11 + 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 + +Alias (word) main::w#0 = (word~) main::$0 +Alias (byte) main::i#1 = (byte) main::j#2 +Alias (word) main::w#1 = (word~) main::$1 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + (word) main::w#0 ← ((word)) (byte/signed byte/word/signed word) 0 + (byte) main::j#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (word) main::w#2 ← phi( main/(word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::i#1 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#1 ) + (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 + (byte) main::j#1 ← ++ (byte) main::i#1 + (boolean~) main::$2 ← (byte) main::j#1 != (byte/signed byte/word/signed word) 11 + 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::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte) main::i#0 ← (byte/signed byte/word/signed word) 0 + (word) main::w#0 ← ((word)) (byte/signed byte/word/signed word) 0 + (byte) main::j#0 ← (byte/signed byte/word/signed word) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (word) main::w#2 ← phi( main/(word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::i#1 ← phi( main/(byte) main::j#0 main::@1/(byte) main::j#1 ) + (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 + (byte) main::j#1 ← ++ (byte) main::i#1 + if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) 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) main::i#0 = 0 +Constant (const word) main::w#0 = ((word))0 +Constant (const byte) main::j#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::@1 + (word) main::w#2 ← phi( main/(const word) main::w#0 main::@1/(word) main::w#1 ) + (byte) main::i#1 ← phi( main/(const byte) main::j#0 main::@1/(byte) main::j#1 ) + (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 + (byte) main::j#1 ← ++ (byte) main::i#1 + if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) 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 + +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const word) main::w#0 +Inlining constant with var siblings (const word) main::w#0 +Inlining constant with var siblings (const byte) main::j#0 +Constant inlined main::i#0 = (byte/signed byte/word/signed word) 0 +Constant inlined main::j#0 = (byte/signed byte/word/signed word) 0 +Constant inlined main::w#0 = ((word))(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 + (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@1/(word) main::w#1 ) + (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::j#1 ) + (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 + (byte) main::j#1 ← ++ (byte) main::i#1 + if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) 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 +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 +(byte) main::j +(byte) main::j#1 +(word) main::w +(word) main::w#1 +(word) main::w#2 + +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 + (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@3/(word~) main::w#3 ) + (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@3/(byte~) main::j#3 ) + (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 + (byte) main::j#1 ← ++ (byte) main::i#1 + if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) 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::j#3 ← (byte) main::j#1 + (word~) main::w#3 ← (word) main::w#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... +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] (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@3/(word~) main::w#3 ) [ main::i#1 main::w#2 ] + [2] (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@3/(byte~) main::j#3 ) [ main::i#1 main::w#2 ] + [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] + [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::w#1 main::j#1 ] + [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@3 [ main::w#1 main::j#1 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [6] return [ ] + to:@return +main::@3: scope:[main] from main::@1 + [7] (byte~) main::j#3 ← (byte) main::j#1 [ main::j#3 main::w#1 ] + [8] (word~) main::w#3 ← (word) main::w#1 [ main::j#3 main::w#3 ] + to:main::@1 + +Created 2 initial phi equivalence classes +Coalesced [7] main::j#3 ← main::j#1 +Coalesced [8] main::w#3 ← main::w#1 +Coalesced down to 2 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... +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] (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@1/(word) main::w#1 ) [ main::i#1 main::w#2 ] + [2] (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::j#1 ) [ main::i#1 main::w#2 ] + [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] + [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] + [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] + to:main::@return +main::@return: scope:[main] from main::@1 + [6] 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] (word) main::w#2 ← phi( main/((word))(byte/signed byte/word/signed word) 0 main::@1/(word) main::w#1 ) [ main::i#1 main::w#2 ] ( main:0 [ main::i#1 main::w#2 ] ) + [2] (byte) main::i#1 ← phi( main/(byte/signed byte/word/signed word) 0 main::@1/(byte) main::j#1 ) [ main::i#1 main::w#2 ] ( main:0 [ main::i#1 main::w#2 ] ) + [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) + [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) + [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [6] 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 +(void()) main() +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::j +(byte) main::j#1 16.5 +(word) main::w +(word) main::w#1 7.333333333333333 +(word) main::w#2 22.0 + +Initial phi equivalence classes +[ main::i#1 main::j#1 ] +[ main::w#2 main::w#1 ] +Complete equivalence classes +[ main::i#1 main::j#1 ] +[ main::w#2 main::w#1 ] +Allocated zp ZP_BYTE:2 [ main::i#1 main::j#1 ] +Allocated zp ZP_WORD:3 [ main::w#2 main::w#1 ] +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: { + .label i = 2 + .label w = 3 + .label j = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- zpby1=coby1 + lda #0 + sta i + jmp b1 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + jmp b1 + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_zpby1 + lda i + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- zpby1=_inc_zpby1 + inc j + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- zpby1_neq_coby1_then_la1 + lda j + cmp #$b + bne b1_from_b1 + jmp breturn + //SEG18 main::@return + breturn: + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#1 main::j#1 ] +Statement [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::i#1 main::j#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , +Potential registers zp ZP_WORD:3 [ main::w#2 main::w#1 ] : zp ZP_WORD:3 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 33: zp ZP_BYTE:2 [ main::i#1 main::j#1 ] 29.33: zp ZP_WORD:3 [ main::w#2 main::w#1 ] +Uplift Scope [] + +Uplifting [main] best 515 combination reg byte x [ main::i#1 main::j#1 ] zp ZP_WORD:3 [ main::w#2 main::w#1 ] +Uplifting [] best 515 combination +Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::w#2 main::w#1 ] +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: { + .label w = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- xby=coby1 + ldx #0 + jmp b1 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_xby + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby=_inc_xby + inx + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1_from_b1 + //SEG18 main::@return + breturn: + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + +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 +//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: { + .label w = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- xby=coby1 + ldx #0 + jmp b1 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_xby + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby=_inc_xby + inx + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG18 main::@return + breturn: + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + +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 +//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: { + .label w = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- xby=coby1 + ldx #0 + jmp b1 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_xby + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby=_inc_xby + inx + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG18 main::@return + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +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: { + .label w = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- xby=coby1 + ldx #0 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_xby + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby=_inc_xby + inx + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG18 main::@return + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::j +(byte) main::j#1 reg byte x 16.5 +(word) main::w +(word) main::w#1 w zp ZP_WORD:2 7.333333333333333 +(word) main::w#2 w zp ZP_WORD:2 22.0 + +reg byte x [ main::i#1 main::j#1 ] +zp ZP_WORD:2 [ main::w#2 main::w#1 ] + +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: { + .label w = 2 + //SEG8 [2] phi from main to main::@1 [phi:main->main::@1] + //SEG9 [2] phi (word) main::w#2 = ((word))(byte/signed byte/word/signed word) 0 [phi:main->main::@1#0] -- zpwo1=cowo1 + lda #<0 + sta w + lda #>0 + sta w+1 + //SEG10 [2] phi (byte) main::i#1 = (byte/signed byte/word/signed word) 0 [phi:main->main::@1#1] -- xby=coby1 + ldx #0 + //SEG11 [2] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG12 [2] phi (word) main::w#2 = (word) main::w#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG13 [2] phi (byte) main::i#1 = (byte) main::j#1 [phi:main::@1->main::@1#1] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [3] (word) main::w#1 ← (word) main::w#2 + (byte) main::i#1 [ main::i#1 main::w#1 ] ( main:0 [ main::i#1 main::w#1 ] ) -- zpwo1=zpwo1_plus_xby + txa + clc + adc w + sta w + bcc !+ + inc w+1 + !: + //SEG16 [4] (byte) main::j#1 ← ++ (byte) main::i#1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby=_inc_xby + inx + //SEG17 [5] if((byte) main::j#1!=(byte/signed byte/word/signed word) 11) goto main::@1 [ main::j#1 main::w#1 ] ( main:0 [ main::j#1 main::w#1 ] ) -- xby_neq_coby1_then_la1 + cpx #$b + bne b1 + //SEG18 main::@return + //SEG19 [6] return [ ] ( main:0 [ ] ) + rts +} + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/immzero.sym b/src/main/java/dk/camelot64/kickc/test/ref/immzero.sym new file mode 100644 index 000000000..96c04793d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/immzero.sym @@ -0,0 +1,16 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::j +(byte) main::j#1 reg byte x 16.5 +(word) main::w +(word) main::w#1 w zp ZP_WORD:2 7.333333333333333 +(word) main::w#2 w zp ZP_WORD:2 22.0 + +reg byte x [ main::i#1 main::j#1 ] +zp ZP_WORD:2 [ main::w#2 main::w#1 ]