diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java index ce803d9cf..6aa2324d6 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilderConfig.java @@ -1,7 +1,6 @@ package dk.camelot64.kickc.model; import dk.camelot64.kickc.CompileLog; -import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.statements.StatementSource; import java.util.*; @@ -100,8 +99,8 @@ public class VariableBuilderConfig { List types = getTypes(paramElements); Optimization optimization = getOptimization(paramElements); MemoryArea memoryArea = getMemoryArea(paramElements); - if(memoryArea==null || optimization==null || paramElements.size()>0) - throw new CompileError("Warning: Malformed var_model parameter "+pragmaParam, statementSource); + if(memoryArea == null || optimization == null || paramElements.size() > 0) + throw new CompileError("Warning: Malformed var_model parameter " + pragmaParam, statementSource); for(Scope scope : scopes) { for(Type type : types) { settings.put(new ScopeType(scope, type), new Setting(scope, type, memoryArea, optimization)); @@ -216,7 +215,7 @@ public class VariableBuilderConfig { if(isScopeParameter) return Scope.PARAMETER; if(isScopeMember) - return Scope.MEMBER; + return Scope.MEMBER; throw new InternalError("Unknown scope!"); } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 5fa5dc385..6c6110b14 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -37,6 +37,16 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testVarModelMaMem2() throws IOException, URISyntaxException { + compileAndCompare("varmodel-ma_mem-2"); + } + + @Test + public void testVarModelMaMem() throws IOException, URISyntaxException { + compileAndCompare("varmodel-ma_mem"); + } + @Test public void testVarModelUnknown() throws IOException, URISyntaxException { assertError("varmodel-unknown", "Warning: Malformed var_model parameter"); diff --git a/src/test/kc/varmodel-ma_mem-2.kc b/src/test/kc/varmodel-ma_mem-2.kc new file mode 100644 index 000000000..0fd6d5d2c --- /dev/null +++ b/src/test/kc/varmodel-ma_mem-2.kc @@ -0,0 +1,11 @@ +// Test memory model multiple-assignment/main memory for all non-pointer variables + +#pragma var_model(ma_mem, pointer_ma_zp) + +void main() { + // A local pointer + char* screen = 0x0400; + // A local counter + for( char i: 0..5 ) + *(screen++) = 'a'; +} \ No newline at end of file diff --git a/src/test/kc/varmodel-ma_mem.kc b/src/test/kc/varmodel-ma_mem.kc new file mode 100644 index 000000000..9625e3a75 --- /dev/null +++ b/src/test/kc/varmodel-ma_mem.kc @@ -0,0 +1,11 @@ +// Test memory model multiple-assignment/main memory for all variables (here local variables) + +#pragma var_model(ma_mem) + +void main() { + // A local pointer + char* screen = 0x0400; + // A local counter + for( char i: 0..5 ) + *(screen++) = 'a'; +} \ No newline at end of file diff --git a/src/test/ref/varmodel-ma_mem-2.asm b/src/test/ref/varmodel-ma_mem-2.asm new file mode 100644 index 000000000..a670c9fa3 --- /dev/null +++ b/src/test/ref/varmodel-ma_mem-2.asm @@ -0,0 +1,29 @@ +// Test memory model multiple-assignment/main memory for all non-pointer variables +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + .label screen = 2 + // A local pointer + lda #<$400 + sta.z screen + lda #>$400 + sta.z screen+1 + lda #0 + sta i + // A local counter + __b1: + lda #'a' + ldy #0 + sta (screen),y + inc.z screen + bne !+ + inc.z screen+1 + !: + inc i + lda #6 + cmp i + bne __b1 + rts + i: .byte 0 +} diff --git a/src/test/ref/varmodel-ma_mem-2.cfg b/src/test/ref/varmodel-ma_mem-2.cfg new file mode 100644 index 000000000..a44093dca --- /dev/null +++ b/src/test/ref/varmodel-ma_mem-2.cfg @@ -0,0 +1,24 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] (byte*) main::screen ← (byte*) 1024 + [5] (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + [6] *((byte*) main::screen) ← (byte) 'a' + [7] (byte*) main::screen ← ++ (byte*) main::screen + [8] (byte) main::i ← ++ (byte) main::i + [9] if((byte) main::i!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [10] return + to:@return diff --git a/src/test/ref/varmodel-ma_mem-2.log b/src/test/ref/varmodel-ma_mem-2.log new file mode 100644 index 000000000..360d37477 --- /dev/null +++ b/src/test/ref/varmodel-ma_mem-2.log @@ -0,0 +1,342 @@ +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte*) main::screen ← (byte*)(number) $400 + (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + *((byte*) main::screen) ← (byte) 'a' + (byte*) main::screen ← ++ (byte*) main::screen + (byte) main::i ← (byte) main::i + rangenext(0,5) + (bool~) main::$0 ← (byte) main::i != rangelast(0,5) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + 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 +(void()) main() +(bool~) main::$0 +(label) main::@1 +(label) main::@return +(byte) main::i loadstore +(byte*) main::screen loadstore + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Simple Condition (bool~) main::$0 [6] if((byte) main::i!=rangelast(0,5)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Resolved ranged next value [4] main::i ← ++ main::i to ++ +Resolved ranged comparison value [6] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6 +Adding number conversion cast (unumber) 6 in if((byte) main::i!=(number) 6) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 6 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 6 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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() + +(void()) main() +main: scope:[main] from @1 + [4] (byte*) main::screen ← (byte*) 1024 + [5] (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + [6] *((byte*) main::screen) ← (byte) 'a' + [7] (byte*) main::screen ← ++ (byte*) main::screen + [8] (byte) main::i ← ++ (byte) main::i + [9] if((byte) main::i!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [10] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte) main::i loadstore 35.0 +(byte*) main::screen loadstore 7.000000000000001 + +Initial phi equivalence classes +Added variable main::screen to live range equivalence class [ main::screen ] +Added variable main::i to live range equivalence class [ main::i ] +Complete equivalence classes +[ main::screen ] +[ main::i ] +Allocated zp[2]:2 [ main::screen ] +Allocated mem[1] [ main::i ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test memory model multiple-assignment/main memory for all non-pointer variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label screen = 2 + // [4] (byte*) main::screen ← (byte*) 1024 -- pbuz1=pbuc1 + // A local pointer + lda #<$400 + sta.z screen + lda #>$400 + sta.z screen+1 + // [5] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + jmp __b1 + // A local counter + // main::@1 + __b1: + // [6] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbuz1=vbuc1 + lda #'a' + ldy #0 + sta (screen),y + // [7] (byte*) main::screen ← ++ (byte*) main::screen -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [8] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [9] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + jmp __breturn + // main::@return + __breturn: + // [10] return + rts + i: .byte 0 +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] (byte*) main::screen ← (byte*) 1024 [ main::screen ] ( main:2 [ main::screen ] ) always clobbers reg byte a +Statement [5] (byte) main::i ← (byte) 0 [ main::screen ] ( main:2 [ main::screen ] ) always clobbers reg byte a +Statement [6] *((byte*) main::screen) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y +Statement [9] if((byte) main::i!=(byte) 6) goto main::@1 [ main::screen ] ( main:2 [ main::screen ] ) always clobbers reg byte a +Potential registers zp[2]:2 [ main::screen ] : zp[2]:2 , +Potential registers mem[1] [ main::i ] : mem[1] , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 35: mem[1] [ main::i ] 7: zp[2]:2 [ main::screen ] +Uplift Scope [] + +Uplifting [main] best 437 combination mem[1] [ main::i ] zp[2]:2 [ main::screen ] +Uplifting [] best 437 combination +Attempting to uplift remaining variables inmem[1] [ main::i ] +Uplifting [main] best 437 combination mem[1] [ main::i ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test memory model multiple-assignment/main memory for all non-pointer variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label screen = 2 + // [4] (byte*) main::screen ← (byte*) 1024 -- pbuz1=pbuc1 + // A local pointer + lda #<$400 + sta.z screen + lda #>$400 + sta.z screen+1 + // [5] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + jmp __b1 + // A local counter + // main::@1 + __b1: + // [6] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbuz1=vbuc1 + lda #'a' + ldy #0 + sta (screen),y + // [7] (byte*) main::screen ← ++ (byte*) main::screen -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [8] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [9] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + jmp __breturn + // main::@return + __breturn: + // [10] return + rts + i: .byte 0 +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i loadstore mem[1] 35.0 +(byte*) main::screen loadstore zp[2]:2 7.000000000000001 + +zp[2]:2 [ main::screen ] +mem[1] [ main::i ] + + +FINAL ASSEMBLER +Score: 392 + + // File Comments +// Test memory model multiple-assignment/main memory for all non-pointer variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .label screen = 2 + // screen = 0x0400 + // [4] (byte*) main::screen ← (byte*) 1024 -- pbuz1=pbuc1 + // A local pointer + lda #<$400 + sta.z screen + lda #>$400 + sta.z screen+1 + // for( char i: 0..5 ) + // [5] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + // A local counter + // main::@1 + __b1: + // *(screen++) = 'a' + // [6] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbuz1=vbuc1 + lda #'a' + ldy #0 + sta (screen),y + // *(screen++) = 'a'; + // [7] (byte*) main::screen ← ++ (byte*) main::screen -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // for( char i: 0..5 ) + // [8] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [9] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + // main::@return + // } + // [10] return + rts + i: .byte 0 +} + // File Data + diff --git a/src/test/ref/varmodel-ma_mem-2.sym b/src/test/ref/varmodel-ma_mem-2.sym new file mode 100644 index 000000000..c89c6f4be --- /dev/null +++ b/src/test/ref/varmodel-ma_mem-2.sym @@ -0,0 +1,11 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i loadstore mem[1] 35.0 +(byte*) main::screen loadstore zp[2]:2 7.000000000000001 + +zp[2]:2 [ main::screen ] +mem[1] [ main::i ] diff --git a/src/test/ref/varmodel-ma_mem.asm b/src/test/ref/varmodel-ma_mem.asm new file mode 100644 index 000000000..87e75310c --- /dev/null +++ b/src/test/ref/varmodel-ma_mem.asm @@ -0,0 +1,27 @@ +// Test memory model multiple-assignment/main memory for all variables +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + lda #0 + sta i + __b1: + lda #'a' + ldy screen + sty.z $fe + ldy screen+1 + sty.z $ff + ldy #0 + sta ($fe),y + inc screen + bne !+ + inc screen+1 + !: + inc i + lda #6 + cmp i + bne __b1 + rts + screen: .word $400 + i: .byte 0 +} diff --git a/src/test/ref/varmodel-ma_mem.cfg b/src/test/ref/varmodel-ma_mem.cfg new file mode 100644 index 000000000..32c7a39d7 --- /dev/null +++ b/src/test/ref/varmodel-ma_mem.cfg @@ -0,0 +1,23 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] *((byte*) main::screen) ← (byte) 'a' + [6] (byte*) main::screen ← ++ (byte*) main::screen + [7] (byte) main::i ← ++ (byte) main::i + [8] if((byte) main::i!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return + to:@return diff --git a/src/test/ref/varmodel-ma_mem.log b/src/test/ref/varmodel-ma_mem.log new file mode 100644 index 000000000..6a6ee666c --- /dev/null +++ b/src/test/ref/varmodel-ma_mem.log @@ -0,0 +1,329 @@ +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + *((byte*) main::screen) ← (byte) 'a' + (byte*) main::screen ← ++ (byte*) main::screen + (byte) main::i ← (byte) main::i + rangenext(0,5) + (bool~) main::$0 ← (byte) main::i != rangelast(0,5) + if((bool~) main::$0) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + 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 +(void()) main() +(bool~) main::$0 +(label) main::@1 +(label) main::@return +(byte) main::i loadstore +(byte*) main::screen loadstore = (byte*)(number) $400 + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Simple Condition (bool~) main::$0 [5] if((byte) main::i!=rangelast(0,5)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Resolved ranged next value [3] main::i ← ++ main::i to ++ +Resolved ranged comparison value [5] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6 +Adding number conversion cast (unumber) 6 in if((byte) main::i!=(number) 6) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 6 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 6 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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() + +(void()) main() +main: scope:[main] from @1 + [4] (byte) main::i ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + [5] *((byte*) main::screen) ← (byte) 'a' + [6] (byte*) main::screen ← ++ (byte*) main::screen + [7] (byte) main::i ← ++ (byte) main::i + [8] if((byte) main::i!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte) main::i loadstore 35.0 +(byte*) main::screen loadstore 5.5 = (byte*) 1024 + +Initial phi equivalence classes +Added variable main::i to live range equivalence class [ main::i ] +Added variable main::screen to live range equivalence class [ main::screen ] +Complete equivalence classes +[ main::i ] +[ main::screen ] +Allocated mem[1] [ main::i ] +Allocated mem[2] [ main::screen ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test memory model multiple-assignment/main memory for all variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + jmp __b1 + // main::@1 + __b1: + // [5] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbum1=vbuc1 + lda #'a' + ldy screen + sty.z $fe + ldy screen+1 + sty.z $ff + ldy #0 + sta ($fe),y + // [6] (byte*) main::screen ← ++ (byte*) main::screen -- pbum1=_inc_pbum1 + inc screen + bne !+ + inc screen+1 + !: + // [7] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [8] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + jmp __breturn + // main::@return + __breturn: + // [9] return + rts + screen: .word $400 + i: .byte 0 +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] (byte) main::i ← (byte) 0 [ main::screen ] ( main:2 [ main::screen ] ) always clobbers reg byte a +Statement [5] *((byte*) main::screen) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y +Statement [8] if((byte) main::i!=(byte) 6) goto main::@1 [ main::screen ] ( main:2 [ main::screen ] ) always clobbers reg byte a +Potential registers mem[1] [ main::i ] : mem[1] , +Potential registers mem[2] [ main::screen ] : mem[2] , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 35: mem[1] [ main::i ] 5.5: mem[2] [ main::screen ] +Uplift Scope [] + +Uplifting [main] best 587 combination mem[1] [ main::i ] mem[2] [ main::screen ] +Uplifting [] best 587 combination +Attempting to uplift remaining variables inmem[1] [ main::i ] +Uplifting [main] best 587 combination mem[1] [ main::i ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test memory model multiple-assignment/main memory for all variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + // [4] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + jmp __b1 + // main::@1 + __b1: + // [5] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbum1=vbuc1 + lda #'a' + ldy screen + sty.z $fe + ldy screen+1 + sty.z $ff + ldy #0 + sta ($fe),y + // [6] (byte*) main::screen ← ++ (byte*) main::screen -- pbum1=_inc_pbum1 + inc screen + bne !+ + inc screen+1 + !: + // [7] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [8] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + jmp __breturn + // main::@return + __breturn: + // [9] return + rts + screen: .word $400 + i: .byte 0 +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i loadstore mem[1] 35.0 +(byte*) main::screen loadstore mem[2] 5.5 = (byte*) 1024 + +mem[1] [ main::i ] +mem[2] [ main::screen ] + + +FINAL ASSEMBLER +Score: 542 + + // File Comments +// Test memory model multiple-assignment/main memory for all variables + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // for( char i: 0..5 ) + // [4] (byte) main::i ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta i + // main::@1 + __b1: + // *(screen++) = 'a' + // [5] *((byte*) main::screen) ← (byte) 'a' -- _deref_pbum1=vbuc1 + lda #'a' + ldy screen + sty.z $fe + ldy screen+1 + sty.z $ff + ldy #0 + sta ($fe),y + // *(screen++) = 'a'; + // [6] (byte*) main::screen ← ++ (byte*) main::screen -- pbum1=_inc_pbum1 + inc screen + bne !+ + inc screen+1 + !: + // for( char i: 0..5 ) + // [7] (byte) main::i ← ++ (byte) main::i -- vbum1=_inc_vbum1 + inc i + // [8] if((byte) main::i!=(byte) 6) goto main::@1 -- vbum1_neq_vbuc1_then_la1 + lda #6 + cmp i + bne __b1 + // main::@return + // } + // [9] return + rts + screen: .word $400 + i: .byte 0 +} + // File Data + diff --git a/src/test/ref/varmodel-ma_mem.sym b/src/test/ref/varmodel-ma_mem.sym new file mode 100644 index 000000000..f05611c5f --- /dev/null +++ b/src/test/ref/varmodel-ma_mem.sym @@ -0,0 +1,11 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i loadstore mem[1] 35.0 +(byte*) main::screen loadstore mem[2] 5.5 = (byte*) 1024 + +mem[1] [ main::i ] +mem[2] [ main::screen ]