diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index 62e484011..46522f383 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -13,6 +13,8 @@ import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.VariableUnversioned; import dk.camelot64.kickc.model.symbols.VariableVersion; +import dk.camelot64.kickc.model.types.SymbolType; +import dk.camelot64.kickc.model.types.SymbolTypeArray; import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.values.RValue; @@ -108,6 +110,22 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base { } } } + // Examine if the assigned variable is an array with a fixed size + if(currentStmt instanceof StatementAssignment) { + LValue lValue = ((StatementAssignment) currentStmt).getlValue(); + if(lValue instanceof VariableRef) { + Variable assignedVar = Pass1GenerateSingleStaticAssignmentForm.this.getScope().getVariable((VariableRef) lValue); + SymbolType assignedVarType = assignedVar.getType(); + if(assignedVarType instanceof SymbolTypeArray) { + SymbolTypeArray assignedArrayType = (SymbolTypeArray) assignedVarType; + RValue arraySize = assignedArrayType.getSize(); + VariableVersion vrs = findOrCreateVersion(arraySize, blockVersions, blockNewPhis); + if(vrs != null) { + assignedArrayType.setSize(vrs.getRef()); + } + } + } + } }); // Add new Phi functions to block for(VariableUnversioned symbol : blockNewPhis.keySet()) { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 1b1afa1f4..f675a4270 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -51,6 +51,11 @@ public class TestPrograms { compileAndCompare("forrangedwords"); } + @Test + public void testArrayLengthSymbolicMin() throws IOException, URISyntaxException { + compileAndCompare("array-length-symbolic-min"); + } + @Test public void testArrayLengthSymbolic() throws IOException, URISyntaxException { compileAndCompare("array-length-symbolic"); diff --git a/src/test/java/dk/camelot64/kickc/test/kc/array-length-symbolic-min.kc b/src/test/java/dk/camelot64/kickc/test/kc/array-length-symbolic-min.kc new file mode 100644 index 000000000..a35154081 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/kc/array-length-symbolic-min.kc @@ -0,0 +1,12 @@ +// Illustrates symbolic array lengths + +byte SZ = 15; +byte[SZ] items; + +// Fills the array item by item with $is, where i is the item# and s is the sub# +void main() { + byte* cur_item = items; + for( byte sub: 0..SZ) { + cur_item[sub] = sub; + } +} \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/kc/scrolllogo.kc b/src/test/java/dk/camelot64/kickc/test/kc/scrolllogo.kc index eb537dc48..73b1e5bcc 100644 --- a/src/test/java/dk/camelot64/kickc/test/kc/scrolllogo.kc +++ b/src/test/java/dk/camelot64/kickc/test/kc/scrolllogo.kc @@ -7,7 +7,7 @@ byte* LOGO = $2000; const word XSIN_SIZE = 512; -signed word[512] align($100) xsin; +signed word[XSIN_SIZE] align($100) xsin; void main() { asm { sei } diff --git a/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.asm b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.asm new file mode 100644 index 000000000..481b5424c --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.asm @@ -0,0 +1,16 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SZ = $f + jsr main +main: { + ldx #0 + b1: + txa + sta items,x + inx + cpx #SZ+1 + bne b1 + rts +} + items: .fill SZ, 0 diff --git a/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.cfg b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.cfg new file mode 100644 index 000000000..86cb8a8fc --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.cfg @@ -0,0 +1,21 @@ +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@1 +@1: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main [ ] ( ) + to:@end +@end: scope:[] from @1 + [3] phi() [ ] ( ) +main: scope:[main] from @1 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::sub#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::sub#1 ) [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) + [6] *((const byte[SZ#0]) items#0 + (byte) main::sub#2) ← (byte) main::sub#2 [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) + [7] (byte) main::sub#1 ← ++ (byte) main::sub#2 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) + [8] if((byte) main::sub#1!=(const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@1 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] ( main:2 [ ] ) + to:@return diff --git a/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.log b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.log new file mode 100644 index 000000000..f598f6db3 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.log @@ -0,0 +1,426 @@ +PARSING src/test/java/dk/camelot64/kickc/test/kc/array-length-symbolic-min.kc +// Illustrates symbolic array lengths + +byte SZ = 15; +byte[SZ] items; + +// Fills the array item by item with $is, where i is the item# and s is the sub# +void main() { + byte* cur_item = items; + for( byte sub: 0..SZ) { + cur_item[sub] = sub; + } +} +SYMBOLS +(label) @1 +(label) @begin +(label) @end +(byte) SZ +(byte[SZ]) items +(void()) main() +(bool~) main::$0 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte*) main::cur_item +(byte) main::sub + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + (byte) SZ ← (byte/signed byte/word/signed word/dword/signed dword) 15 + (byte[SZ]) items ← { fill( SZ, 0) } + to:@1 +main: scope:[main] from + (byte*) main::cur_item ← (byte[SZ]) items + (byte) main::sub ← (byte/signed byte/word/signed word/dword/signed dword) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + *((byte*) main::cur_item + (byte) main::sub) ← (byte) main::sub + (byte) main::sub ← (byte) main::sub + rangenext(0,SZ) + (bool~) main::$0 ← (byte) main::sub != rangelast(0,SZ) + if((bool~) main::$0) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +Removing empty block main::@2 +PROCEDURE MODIFY VARIABLE ANALYSIS + +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... + +CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + (byte) SZ#0 ← (byte/signed byte/word/signed word/dword/signed dword) 15 + (byte[SZ#0]) items#0 ← { fill( SZ#0, 0) } + to:@1 +main: scope:[main] from @1 + (byte) SZ#2 ← phi( @1/(byte) SZ#3 ) + (byte*) main::cur_item#0 ← (byte[SZ#0]) items#0 + (byte) main::sub#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (byte) SZ#1 ← phi( main/(byte) SZ#2 main::@1/(byte) SZ#1 ) + (byte*) main::cur_item#1 ← phi( main/(byte*) main::cur_item#0 main::@1/(byte*) main::cur_item#1 ) + (byte) main::sub#2 ← phi( main/(byte) main::sub#0 main::@1/(byte) main::sub#1 ) + *((byte*) main::cur_item#1 + (byte) main::sub#2) ← (byte) main::sub#2 + (byte) main::sub#1 ← (byte) main::sub#2 + rangenext(0,SZ#1) + (bool~) main::$0 ← (byte) main::sub#1 != rangelast(0,SZ#1) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + (byte) SZ#3 ← phi( @begin/(byte) SZ#0 ) + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(byte) SZ +(byte) SZ#0 +(byte) SZ#1 +(byte) SZ#2 +(byte) SZ#3 +(byte[SZ#0]) items +(byte[SZ#0]) items#0 +(void()) main() +(bool~) main::$0 +(label) main::@1 +(label) main::@return +(byte*) main::cur_item +(byte*) main::cur_item#0 +(byte*) main::cur_item#1 +(byte) main::sub +(byte) main::sub#0 +(byte) main::sub#1 +(byte) main::sub#2 + +OPTIMIZING CONTROL FLOW GRAPH +Culled Empty Block (label) @2 +Succesful SSA optimization Pass2CullEmptyBlocks +Not aliassing across scopes: SZ#2 SZ#3 +Not aliassing across scopes: main::cur_item#0 items#0 +Alias (byte) SZ#0 = (byte) SZ#3 +Succesful SSA optimization Pass2AliasElimination +Not aliassing across scopes: SZ#2 SZ#0 +Not aliassing across scopes: main::cur_item#0 items#0 +Self Phi Eliminated (byte*) main::cur_item#1 +Self Phi Eliminated (byte) SZ#1 +Succesful SSA optimization Pass2SelfPhiElimination +Redundant Phi (byte) SZ#2 (byte) SZ#0 +Redundant Phi (byte*) main::cur_item#1 (byte*) main::cur_item#0 +Redundant Phi (byte) SZ#1 (byte) SZ#2 +Succesful SSA optimization Pass2RedundantPhiElimination +Simple Condition (bool~) main::$0 if((byte) main::sub#1!=rangelast(0,SZ#0)) goto main::@1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) SZ#0 = 15 +Constant (const byte) main::sub#0 = 0 +Succesful SSA optimization Pass2ConstantIdentification +Constant (const byte[SZ#0]) items#0 = { fill( SZ#0, 0) } +Succesful SSA optimization Pass2ConstantIdentification +Constant (const byte*) main::cur_item#0 = items#0 +Succesful SSA optimization Pass2ConstantIdentification +Resolved ranged next value main::sub#1 ← ++ main::sub#2 to ++ +Resolved ranged comparison value if(main::sub#1!=rangelast(0,SZ#0)) goto main::@1 to (const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1 +OPTIMIZING CONTROL FLOW GRAPH +Inlining constant with var siblings (const byte) main::sub#0 +Inlining constant with var siblings (const byte) main::sub#0 +Constant inlined main::sub#0 = (byte/signed byte/word/signed word/dword/signed dword) 0 +Constant inlined main::cur_item#0 = (const byte[SZ#0]) items#0 +Succesful SSA optimization Pass2ConstantInlining +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Added new block during phi lifting main::@3(between main::@1 and main::@1) +Block Sequence Planned @begin @1 @end main main::@1 main::@return main::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 + +Propagating live ranges... +Propagating live ranges... +Created 1 initial phi equivalence classes +Coalesced [10] main::sub#3 ← main::sub#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) main::@3 +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Propagating live ranges... +Propagating live ranges... + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@1 +@1: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main [ ] ( ) + to:@end +@end: scope:[] from @1 + [3] phi() [ ] ( ) +main: scope:[main] from @1 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] (byte) main::sub#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::sub#1 ) [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) + [6] *((const byte[SZ#0]) items#0 + (byte) main::sub#2) ← (byte) main::sub#2 [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) + [7] (byte) main::sub#1 ← ++ (byte) main::sub#2 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) + [8] if((byte) main::sub#1!=(const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@1 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return [ ] ( main:2 [ ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@1 dominated by @1 @begin +@end dominated by @1 @begin @end +main dominated by @1 @begin main +main::@1 dominated by @1 @begin main::@1 main +main::@return dominated by main::@return @1 @begin main::@1 main + +NATURAL LOOPS +Found back edge: Loop head: main::@1 tails: main::@1 blocks: null +Populated: Loop head: main::@1 tails: main::@1 blocks: main::@1 +Loop head: main::@1 tails: main::@1 blocks: main::@1 + +NATURAL LOOPS WITH DEPTH +Found 0 loops in scope [] +Found 1 loops in scope [main] + Loop head: main::@1 tails: main::@1 blocks: main::@1 +Loop head: main::@1 tails: main::@1 blocks: main::@1 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(byte) SZ +(byte[SZ#0]) items +(void()) main() +(byte*) main::cur_item +(byte) main::sub +(byte) main::sub#1 16.5 +(byte) main::sub#2 22.0 + +Initial phi equivalence classes +[ main::sub#2 main::sub#1 ] +Complete equivalence classes +[ main::sub#2 main::sub#1 ] +Allocated zp ZP_BYTE:2 [ main::sub#2 main::sub#1 ] + +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SZ = $f +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG4 @1 +b1: +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label sub = 2 + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG11 [5] phi (byte) main::sub#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta sub + jmp b1 + //SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG13 [5] phi (byte) main::sub#2 = (byte) main::sub#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG14 main::@1 + b1: + //SEG15 [6] *((const byte[SZ#0]) items#0 + (byte) main::sub#2) ← (byte) main::sub#2 [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) -- pbuc1_derefidx_vbuz1=vbuz1 + ldy sub + tya + sta items,y + //SEG16 [7] (byte) main::sub#1 ← ++ (byte) main::sub#2 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuz1=_inc_vbuz1 + inc sub + //SEG17 [8] if((byte) main::sub#1!=(const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@1 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuz1_neq_vbuc1_then_la1 + lda sub + cmp #SZ+1 + bne b1_from_b1 + jmp breturn + //SEG18 main::@return + breturn: + //SEG19 [9] return [ ] ( main:2 [ ] ) + rts +} + items: .fill SZ, 0 + +REGISTER UPLIFT POTENTIAL REGISTERS +Potential registers zp ZP_BYTE:2 [ main::sub#2 main::sub#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 38.5: zp ZP_BYTE:2 [ main::sub#2 main::sub#1 ] +Uplift Scope [] + +Uplifting [main] best 263 combination reg byte x [ main::sub#2 main::sub#1 ] +Uplifting [] best 263 combination + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SZ = $f +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG4 @1 +b1: +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG11 [5] phi (byte) main::sub#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp b1 + //SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + //SEG13 [5] phi (byte) main::sub#2 = (byte) main::sub#1 [phi:main::@1->main::@1#0] -- register_copy + jmp b1 + //SEG14 main::@1 + b1: + //SEG15 [6] *((const byte[SZ#0]) items#0 + (byte) main::sub#2) ← (byte) main::sub#2 [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) -- pbuc1_derefidx_vbuxx=vbuxx + txa + sta items,x + //SEG16 [7] (byte) main::sub#1 ← ++ (byte) main::sub#2 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuxx=_inc_vbuxx + inx + //SEG17 [8] if((byte) main::sub#1!=(const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@1 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuxx_neq_vbuc1_then_la1 + cpx #SZ+1 + bne b1_from_b1 + jmp breturn + //SEG18 main::@return + breturn: + //SEG19 [9] return [ ] ( main:2 [ ] ) + rts +} + items: .fill SZ, 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label b1_from_b1 with b1 +Removing instruction bbegin: +Removing instruction b1_from_bbegin: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction b1: +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte) SZ +(const byte) SZ#0 SZ = (byte/signed byte/word/signed word/dword/signed dword) 15 +(byte[SZ#0]) items +(const byte[SZ#0]) items#0 items = { fill( SZ#0, 0) } +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::cur_item +(byte) main::sub +(byte) main::sub#1 reg byte x 16.5 +(byte) main::sub#2 reg byte x 22.0 + +reg byte x [ main::sub#2 main::sub#1 ] + + +FINAL ASSEMBLER +Score: 167 + +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .const SZ = $f +//SEG2 @begin +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG4 @1 +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +//SEG8 @end +//SEG9 main +main: { + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + //SEG11 [5] phi (byte) main::sub#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + //SEG12 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + //SEG13 [5] phi (byte) main::sub#2 = (byte) main::sub#1 [phi:main::@1->main::@1#0] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [6] *((const byte[SZ#0]) items#0 + (byte) main::sub#2) ← (byte) main::sub#2 [ main::sub#2 ] ( main:2 [ main::sub#2 ] ) -- pbuc1_derefidx_vbuxx=vbuxx + txa + sta items,x + //SEG16 [7] (byte) main::sub#1 ← ++ (byte) main::sub#2 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuxx=_inc_vbuxx + inx + //SEG17 [8] if((byte) main::sub#1!=(const byte) SZ#0+(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@1 [ main::sub#1 ] ( main:2 [ main::sub#1 ] ) -- vbuxx_neq_vbuc1_then_la1 + cpx #SZ+1 + bne b1 + //SEG18 main::@return + //SEG19 [9] return [ ] ( main:2 [ ] ) + rts +} + items: .fill SZ, 0 + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.sym b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.sym new file mode 100644 index 000000000..a2ef79d91 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/array-length-symbolic-min.sym @@ -0,0 +1,16 @@ +(label) @1 +(label) @begin +(label) @end +(byte) SZ +(const byte) SZ#0 SZ = (byte/signed byte/word/signed word/dword/signed dword) 15 +(byte[SZ#0]) items +(const byte[SZ#0]) items#0 items = { fill( SZ#0, 0) } +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::cur_item +(byte) main::sub +(byte) main::sub#1 reg byte x 16.5 +(byte) main::sub#2 reg byte x 22.0 + +reg byte x [ main::sub#2 main::sub#1 ] diff --git a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.asm b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.asm index ccde39a18..3d86b14e7 100644 --- a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.asm +++ b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.asm @@ -720,4 +720,4 @@ fill: { rts } .align $100 - xsin: .fill 2*$200, 0 + xsin: .fill 2*XSIN_SIZE, 0 diff --git a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.cfg b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.cfg index be6b5be7f..18cfab684 100644 --- a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.cfg +++ b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.cfg @@ -63,7 +63,7 @@ loop::@4: scope:[loop] from loop::@1 loop::@4 to:loop::@6 loop::@6: scope:[loop] from loop::@4 [27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0) [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) - [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) + [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) [29] (signed word) loop::xpos#0 ← *((signed word*~) loop::$1) [ xsin_idx#11 loop::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 loop::xpos#0 ] ) [30] (signed word) render_logo::xpos#0 ← (signed word) loop::xpos#0 [ xsin_idx#11 render_logo::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 render_logo::xpos#0 ] ) [31] call render_logo [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) @@ -171,7 +171,7 @@ sin16s_gen2::@3: scope:[sin16s_gen2] from sin16s_gen2 to:sin16s_gen2::@1 sin16s_gen2::@1: scope:[sin16s_gen2] from sin16s_gen2::@3 sin16s_gen2::@5 [99] (word) sin16s_gen2::i#2 ← phi( sin16s_gen2::@3/(byte/signed byte/word/signed word/dword/signed dword) 0 sin16s_gen2::@5/(word) sin16s_gen2::i#1 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) - [99] (signed word*) sin16s_gen2::sintab#2 ← phi( sin16s_gen2::@3/(const signed word[512]) xsin#0 sin16s_gen2::@5/(signed word*) sin16s_gen2::sintab#0 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) + [99] (signed word*) sin16s_gen2::sintab#2 ← phi( sin16s_gen2::@3/(const signed word[XSIN_SIZE#0]) xsin#0 sin16s_gen2::@5/(signed word*) sin16s_gen2::sintab#0 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) [99] (dword) sin16s_gen2::x#2 ← phi( sin16s_gen2::@3/(byte/signed byte/word/signed word/dword/signed dword) 0 sin16s_gen2::@5/(dword) sin16s_gen2::x#1 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) [100] (dword) sin16s::x#0 ← (dword) sin16s_gen2::x#2 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::x#0 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::x#0 ] ) [101] call sin16s [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::return#1 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::return#1 ] ) diff --git a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.log b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.log index d8e87f54d..f3e827577 100644 --- a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.log +++ b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.log @@ -8,7 +8,7 @@ byte* LOGO = $2000; const word XSIN_SIZE = 512; -signed word[512] align($100) xsin; +signed word[XSIN_SIZE] align($100) xsin; void main() { asm { sei } @@ -1377,7 +1377,7 @@ inline (void()) vicSelectGfxBank((byte*) vicSelectGfxBank::gfx) (byte~) vicSelectGfxBank::$0 (label) vicSelectGfxBank::@return (byte*) vicSelectGfxBank::gfx -(signed word[512]) xsin +(signed word[XSIN_SIZE]) xsin (word) xsin_idx Fixing lo/hi-lvalue with new tmpVar mul8s::$16 mul8s::$16 ← mul8s::$8 @@ -2302,7 +2302,7 @@ fill::@return: scope:[fill] from fill::@2 (byte*) SCREEN ← ((byte*)) (word/signed word/dword/signed dword) 1024 (byte*) LOGO ← ((byte*)) (word/signed word/dword/signed dword) 8192 (word) XSIN_SIZE ← (word/signed word/dword/signed dword) 512 - (signed word[512]) xsin ← { fill( 512, 0) } + (signed word[XSIN_SIZE]) xsin ← { fill( XSIN_SIZE, 0) } to:@25 main: scope:[main] from asm { sei } @@ -2326,7 +2326,7 @@ main::@1: scope:[main] from main main::@1 to:main::@2 main::@2: scope:[main] from main::@1 (signed word/signed dword~) main::$5 ← - (word/signed word/dword/signed dword) 320 - (void~) main::$6 ← call sin16s_gen2 (signed word[512]) xsin (word) XSIN_SIZE (signed word/signed dword~) main::$5 (word/signed word/dword/signed dword) 320 + (void~) main::$6 ← call sin16s_gen2 (signed word[XSIN_SIZE]) xsin (word) XSIN_SIZE (signed word/signed dword~) main::$5 (word/signed word/dword/signed dword) 320 (void~) main::$7 ← call loop to:main::@return main::@return: scope:[main] from main::@2 @@ -2358,7 +2358,7 @@ loop::@10: scope:[loop] from loop::@4 to:loop::@6 loop::@6: scope:[loop] from loop::@10 loop::@12 *((byte*) BORDERCOL) ← ++ *((byte*) BORDERCOL) - (signed word*~) loop::$1 ← (signed word[512]) xsin + (word) xsin_idx + (signed word*~) loop::$1 ← (signed word[XSIN_SIZE]) xsin + (word) xsin_idx (signed word) loop::xpos ← *((signed word*~) loop::$1) (void~) loop::$2 ← call render_logo (signed word) loop::xpos (word) xsin_idx ← (word) xsin_idx + (byte/signed byte/word/signed word/dword/signed dword) 2 @@ -3240,7 +3240,7 @@ fill::@return: scope:[fill] from fill::@1 (byte*) SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024 (byte*) LOGO#0 ← ((byte*)) (word/signed word/dword/signed dword) 8192 (word) XSIN_SIZE#0 ← (word/signed word/dword/signed dword) 512 - (signed word[512]) xsin#0 ← { fill( 512, 0) } + (signed word[XSIN_SIZE#0]) xsin#0 ← { fill( XSIN_SIZE#0, 0) } to:@25 main: scope:[main] from @27 (word) xsin_idx#28 ← phi( @27/(word) xsin_idx#16 ) @@ -3323,7 +3323,7 @@ main::@2: scope:[main] from main::@1 (word) xsin_idx#17 ← phi( main::@1/(word) xsin_idx#22 ) (word) rem16u#23 ← phi( main::@1/(word) rem16u#27 ) (signed word/signed dword~) main::$5 ← - (word/signed word/dword/signed dword) 320 - (signed word*) sin16s_gen2::sintab#1 ← (signed word[512]) xsin#0 + (signed word*) sin16s_gen2::sintab#1 ← (signed word[XSIN_SIZE#0]) xsin#0 (word) sin16s_gen2::wavelength#0 ← (word) XSIN_SIZE#0 (signed word) sin16s_gen2::min#0 ← (signed word/signed dword~) main::$5 (signed word) sin16s_gen2::max#0 ← (word/signed word/dword/signed dword) 320 @@ -3381,7 +3381,7 @@ loop::@6: scope:[loop] from loop::@4 (byte*) SCREEN#22 ← phi( loop::@4/(byte*) SCREEN#23 ) (word) xsin_idx#9 ← phi( loop::@4/(word) xsin_idx#14 ) *((byte*) BORDERCOL#0) ← ++ *((byte*) BORDERCOL#0) - (signed word*~) loop::$1 ← (signed word[512]) xsin#0 + (word) xsin_idx#9 + (signed word*~) loop::$1 ← (signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#9 (signed word) loop::xpos#0 ← *((signed word*~) loop::$1) (signed word) render_logo::xpos#0 ← (signed word) loop::xpos#0 call render_logo @@ -4344,8 +4344,8 @@ SYMBOL TABLE SSA (dword) sin16s_gen2::x#2 (dword) sin16s_gen2::x#3 (dword) sin16s_gen2::x#4 -(signed word[512]) xsin -(signed word[512]) xsin#0 +(signed word[XSIN_SIZE#0]) xsin +(signed word[XSIN_SIZE#0]) xsin#0 (word) xsin_idx (word) xsin_idx#0 (word) xsin_idx#1 @@ -4924,7 +4924,6 @@ Constant (const byte) mulu16_sel::select#4 = 0 Constant (const byte*) SCREEN#0 = ((byte*))1024 Constant (const byte*) LOGO#0 = ((byte*))8192 Constant (const word) XSIN_SIZE#0 = 512 -Constant (const signed word[512]) xsin#0 = { fill( 512, 0) } Constant (const word) fill::size#0 = 1000 Constant (const word) fill::size#1 = 1000 Constant (const byte) main::ch#0 = 0 @@ -4968,13 +4967,13 @@ Constant (const byte/word/signed word/dword/signed dword) render_logo::$71 = 40* Succesful SSA optimization Pass2ConstantIdentification Constant (const signed word) sin16s_gen2::ampl#0 = sin16s_gen2::max#0-sin16s_gen2::min#0 Constant (const dword) div32u16u::dividend#0 = PI2_u4f28#0 +Constant (const signed word[XSIN_SIZE#0]) xsin#0 = { fill( XSIN_SIZE#0, 0) } Constant (const byte*) main::toD0181_screen#0 = SCREEN#0 Constant (const byte*) main::toD0181_gfx#0 = LOGO#0 Constant (const byte*) fill::start#0 = SCREEN#0 Constant (const byte) fill::val#0 = BLACK#0 Constant (const byte) fill::val#1 = WHITE#0|8 Constant (const byte*) fill::start#1 = COLS#0 -Constant (const signed word*) sin16s_gen2::sintab#1 = xsin#0 Constant (const word) sin16s_gen2::wavelength#0 = XSIN_SIZE#0 Constant (const word/signed dword/dword) loop::$3 = XSIN_SIZE#0*2 Succesful SSA optimization Pass2ConstantIdentification @@ -4985,6 +4984,7 @@ Constant (const word) div32u16u::divisor#0 = sin16s_gen2::wavelength#0 Constant (const signed word) mul16s::b#0 = sin16s_gen2::ampl#0 Constant (const word) main::toD0181_$0#0 = ((word))main::toD0181_screen#0 Constant (const word) main::toD0181_$4#0 = ((word))main::toD0181_gfx#0 +Constant (const signed word*) sin16s_gen2::sintab#1 = xsin#0 Succesful SSA optimization Pass2ConstantIdentification Constant (const word) divr16u::divisor#0 = div32u16u::divisor#0 Constant (const word) divr16u::divisor#1 = div32u16u::divisor#0 @@ -5318,7 +5318,7 @@ Constant inlined fill::size#0 = (word/signed word/dword/signed dword) 1000 Constant inlined main::toD0181_$7#0 = >((word))(const byte*) LOGO#0>>(byte/signed byte/word/signed word/dword/signed dword) 2&(byte/signed byte/word/signed word/dword/signed dword) 15 Constant inlined xsin_idx#16 = (byte/signed byte/word/signed word/dword/signed dword) 0 Constant inlined main::toD0181_$3#0 = >((word))(const byte*) SCREEN#0&(word/signed word/dword/signed dword) 16383<<(byte/signed byte/word/signed word/dword/signed dword) 2 -Constant inlined sin16s_gen2::sintab#1 = (const signed word[512]) xsin#0 +Constant inlined sin16s_gen2::sintab#1 = (const signed word[XSIN_SIZE#0]) xsin#0 Constant inlined render_logo::$44 = (byte/signed byte/word/signed word/dword/signed dword) 40*(byte/signed byte/word/signed word/dword/signed dword) 1 Constant inlined render_logo::$47 = (const byte*) SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 40*(byte/signed byte/word/signed word/dword/signed dword) 2 Constant inlined render_logo::$46 = (byte/signed byte/word/signed word/dword/signed dword) 40*(byte/signed byte/word/signed word/dword/signed dword) 2 @@ -5657,7 +5657,7 @@ loop::@4: scope:[loop] from loop::@1 loop::@4 to:loop::@6 loop::@6: scope:[loop] from loop::@4 [27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0) [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) - [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) + [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) [29] (signed word) loop::xpos#0 ← *((signed word*~) loop::$1) [ xsin_idx#11 loop::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 loop::xpos#0 ] ) [30] (signed word) render_logo::xpos#0 ← (signed word) loop::xpos#0 [ xsin_idx#11 render_logo::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 render_logo::xpos#0 ] ) [31] call render_logo [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) @@ -5765,7 +5765,7 @@ sin16s_gen2::@3: scope:[sin16s_gen2] from sin16s_gen2 to:sin16s_gen2::@1 sin16s_gen2::@1: scope:[sin16s_gen2] from sin16s_gen2::@3 sin16s_gen2::@5 [99] (word) sin16s_gen2::i#2 ← phi( sin16s_gen2::@3/(byte/signed byte/word/signed word/dword/signed dword) 0 sin16s_gen2::@5/(word) sin16s_gen2::i#1 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) - [99] (signed word*) sin16s_gen2::sintab#2 ← phi( sin16s_gen2::@3/(const signed word[512]) xsin#0 sin16s_gen2::@5/(signed word*) sin16s_gen2::sintab#0 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) + [99] (signed word*) sin16s_gen2::sintab#2 ← phi( sin16s_gen2::@3/(const signed word[XSIN_SIZE#0]) xsin#0 sin16s_gen2::@5/(signed word*) sin16s_gen2::sintab#0 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) [99] (dword) sin16s_gen2::x#2 ← phi( sin16s_gen2::@3/(byte/signed byte/word/signed word/dword/signed dword) 0 sin16s_gen2::@5/(dword) sin16s_gen2::x#1 ) [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 ] ) [100] (dword) sin16s::x#0 ← (dword) sin16s_gen2::x#2 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::x#0 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::x#0 ] ) [101] call sin16s [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::return#1 ] ( main:2::sin16s_gen2:20 [ sin16s_gen2::step#0 sin16s_gen2::x#2 sin16s_gen2::sintab#2 sin16s_gen2::i#2 sin16s::return#1 ] ) @@ -6389,7 +6389,7 @@ VARIABLE REGISTER WEIGHTS (dword) sin16s_gen2::x (dword) sin16s_gen2::x#1 7.333333333333333 (dword) sin16s_gen2::x#2 2.75 -(signed word[512]) xsin +(signed word[XSIN_SIZE#0]) xsin (word) xsin_idx (word) xsin_idx#11 4.714285714285714 (word) xsin_idx#19 11.0 @@ -6838,7 +6838,7 @@ loop: { b6: //SEG54 [27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0) [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) -- _deref_pbuc1=_inc__deref_pbuc1 inc BORDERCOL - //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 + //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 lda xsin_idx clc adc #0 sta i+1 - //SEG163 [99] phi (signed word*) sin16s_gen2::sintab#2 = (const signed word[512]) xsin#0 [phi:sin16s_gen2::@3->sin16s_gen2::@1#1] -- pwsz1=pwsc1 + //SEG163 [99] phi (signed word*) sin16s_gen2::sintab#2 = (const signed word[XSIN_SIZE#0]) xsin#0 [phi:sin16s_gen2::@3->sin16s_gen2::@1#1] -- pwsz1=pwsc1 lda #xsin @@ -8246,7 +8246,7 @@ fill: { rts } .align $100 - xsin: .fill 2*$200, 0 + xsin: .fill 2*XSIN_SIZE, 0 REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] *((const byte*) BORDERCOL#0) ← (const byte) WHITE#0 [ ] ( main:2 [ ] ) always clobbers reg byte a @@ -8256,7 +8256,7 @@ Statement [8] *((const byte*) BGCOL3#0) ← (const byte) BLACK#0 [ ] ( main:2 [ Statement [10] *((const byte*) D018#0) ← (const byte) main::toD0181_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [11] *((const byte*) D016#0) ← (const byte) VIC_MCM#0 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [26] if(*((const byte*) RASTER#0)!=(byte/word/signed word/dword/signed dword) 255) goto loop::@4 [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) always clobbers reg byte a -Statement [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) always clobbers reg byte a +Statement [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) always clobbers reg byte a Statement [29] (signed word) loop::xpos#0 ← *((signed word*~) loop::$1) [ xsin_idx#11 loop::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 loop::xpos#0 ] ) always clobbers reg byte a reg byte y Statement [30] (signed word) render_logo::xpos#0 ← (signed word) loop::xpos#0 [ xsin_idx#11 render_logo::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 render_logo::xpos#0 ] ) always clobbers reg byte a Statement [32] (word) xsin_idx#3 ← (word) xsin_idx#11 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ xsin_idx#3 ] ( main:2::loop:22 [ xsin_idx#3 ] ) always clobbers reg byte a @@ -8384,7 +8384,7 @@ Statement [8] *((const byte*) BGCOL3#0) ← (const byte) BLACK#0 [ ] ( main:2 [ Statement [10] *((const byte*) D018#0) ← (const byte) main::toD0181_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [11] *((const byte*) D016#0) ← (const byte) VIC_MCM#0 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [26] if(*((const byte*) RASTER#0)!=(byte/word/signed word/dword/signed dword) 255) goto loop::@4 [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) always clobbers reg byte a -Statement [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) always clobbers reg byte a +Statement [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) always clobbers reg byte a Statement [29] (signed word) loop::xpos#0 ← *((signed word*~) loop::$1) [ xsin_idx#11 loop::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 loop::xpos#0 ] ) always clobbers reg byte a reg byte y Statement [30] (signed word) render_logo::xpos#0 ← (signed word) loop::xpos#0 [ xsin_idx#11 render_logo::xpos#0 ] ( main:2::loop:22 [ xsin_idx#11 render_logo::xpos#0 ] ) always clobbers reg byte a Statement [32] (word) xsin_idx#3 ← (word) xsin_idx#11 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ xsin_idx#3 ] ( main:2::loop:22 [ xsin_idx#3 ] ) always clobbers reg byte a @@ -8880,7 +8880,7 @@ loop: { b6: //SEG54 [27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0) [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) -- _deref_pbuc1=_inc__deref_pbuc1 inc BORDERCOL - //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 + //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 lda xsin_idx clc adc #0 sta i+1 - //SEG163 [99] phi (signed word*) sin16s_gen2::sintab#2 = (const signed word[512]) xsin#0 [phi:sin16s_gen2::@3->sin16s_gen2::@1#1] -- pwsz1=pwsc1 + //SEG163 [99] phi (signed word*) sin16s_gen2::sintab#2 = (const signed word[XSIN_SIZE#0]) xsin#0 [phi:sin16s_gen2::@3->sin16s_gen2::@1#1] -- pwsz1=pwsc1 lda #xsin @@ -10032,7 +10032,7 @@ fill: { rts } .align $100 - xsin: .fill 2*$200, 0 + xsin: .fill 2*XSIN_SIZE, 0 ASSEMBLER OPTIMIZATIONS Removing instruction jmp b27 @@ -10584,8 +10584,8 @@ FINAL SYMBOL TABLE (dword) sin16s_gen2::x (dword) sin16s_gen2::x#1 x zp ZP_DWORD:4 7.333333333333333 (dword) sin16s_gen2::x#2 x zp ZP_DWORD:4 2.75 -(signed word[512]) xsin -(const signed word[512]) xsin#0 xsin = { fill( 512, 0) } +(signed word[XSIN_SIZE#0]) xsin +(const signed word[XSIN_SIZE#0]) xsin#0 xsin = { fill( XSIN_SIZE#0, 0) } (word) xsin_idx (word) xsin_idx#11 xsin_idx zp ZP_WORD:2 4.714285714285714 (word) xsin_idx#19 xsin_idx zp ZP_WORD:2 11.0 @@ -10770,7 +10770,7 @@ loop: { //SEG53 loop::@6 //SEG54 [27] *((const byte*) BORDERCOL#0) ← ++ *((const byte*) BORDERCOL#0) [ xsin_idx#11 ] ( main:2::loop:22 [ xsin_idx#11 ] ) -- _deref_pbuc1=_inc__deref_pbuc1 inc BORDERCOL - //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[512]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 + //SEG55 [28] (signed word*~) loop::$1 ← (const signed word[XSIN_SIZE#0]) xsin#0 + (word) xsin_idx#11 [ xsin_idx#11 loop::$1 ] ( main:2::loop:22 [ xsin_idx#11 loop::$1 ] ) -- pwsz1=pwsc1_plus_vwuz2 lda xsin_idx clc adc #sin16s_gen2::@1#1] -- pwsz1=pwsc1 + //SEG163 [99] phi (signed word*) sin16s_gen2::sintab#2 = (const signed word[XSIN_SIZE#0]) xsin#0 [phi:sin16s_gen2::@3->sin16s_gen2::@1#1] -- pwsz1=pwsc1 lda #xsin @@ -11778,5 +11778,5 @@ fill: { rts } .align $100 - xsin: .fill 2*$200, 0 + xsin: .fill 2*XSIN_SIZE, 0 diff --git a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.sym b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.sym index 8a8fd2c2d..83e12ecbe 100644 --- a/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.sym +++ b/src/test/java/dk/camelot64/kickc/test/ref/scrolllogo.sym @@ -328,8 +328,8 @@ (dword) sin16s_gen2::x (dword) sin16s_gen2::x#1 x zp ZP_DWORD:4 7.333333333333333 (dword) sin16s_gen2::x#2 x zp ZP_DWORD:4 2.75 -(signed word[512]) xsin -(const signed word[512]) xsin#0 xsin = { fill( 512, 0) } +(signed word[XSIN_SIZE#0]) xsin +(const signed word[XSIN_SIZE#0]) xsin#0 xsin = { fill( XSIN_SIZE#0, 0) } (word) xsin_idx (word) xsin_idx#11 xsin_idx zp ZP_WORD:2 4.714285714285714 (word) xsin_idx#19 xsin_idx zp ZP_WORD:2 11.0