Fixing struct type size struct Tile to 25
Fixing struct type size struct Tile to 25
Fixing struct type size struct Tile to 25
Fixing struct type size struct Tile to 25
Fixing struct type size struct Tile to 25
Fixing struct type size struct Tile to 25
Fixing struct type SIZE_OF struct Tile to 25
Fixing struct type SIZE_OF struct Tile to 25
Setting struct to load/store in variable affected by address-of S1
Setting struct to load/store in variable affected by address-of S2

CONTROL FLOW GRAPH SSA

void main()
main: scope:[main]  from __start
  main::i#0 = 0
  to:main::@1
main::@1: scope:[main]  from main main::@1
  main::i#2 = phi( main/main::i#0, main::@1/main::i#1 )
  main::$1 = main::i#2 * SIZEOF_POINTER
  main::tile#0 = TileDB[main::$1]
  main::$3 = (char *)main::tile#0
  main::$2 = main::$3 + OFFSET_STRUCT_TILE_COUNT
  main::SCREEN[main::i#2] = *main::$2
  main::i#1 = main::i#2 + rangenext(0,1)
  main::$0 = main::i#1 != rangelast(0,1)
  if(main::$0) goto main::@1
  to:main::@return
main::@return: scope:[main]  from main::@1
  return 
  to:@return

void __start()
__start: scope:[__start]  from
  call main
  to:__start::@1
__start::@1: scope:[__start]  from __start
  to:__start::@return
__start::@return: scope:[__start]  from __start::@1
  return 
  to:@return

SYMBOL TABLE SSA
__constant unsigned long Enemy2Sprites[$c] = { fill( $c, 0) }
__constant char OFFSET_STRUCT_TILE_COUNT = 4
__constant unsigned long PlayerSprites[$c] = { fill( $c, 0) }
__loadstore volatile struct Tile S1 = { Tiles: PlayerSprites, Offset: $14, Count: $40, Name: "Sven" }
__loadstore volatile struct Tile S2 = { Tiles: Enemy2Sprites, Offset: $32, Count: $80, Name: "Jesper" }
__constant char SIZEOF_POINTER = 2
__constant struct Tile *TileDB[2] = { &S1, &S2 }
void __start()
void main()
bool main::$0
int main::$1
char *main::$2
char *main::$3
__constant char * const main::SCREEN = (char *)$400
int main::i
int main::i#0
int main::i#1
int main::i#2
struct Tile *main::tile
struct Tile *main::tile#0

Simplifying constant pointer cast (char *) 1024
Successful SSA optimization PassNCastSimplification
Simple Condition main::$0 [9] if(main::i#1!=rangelast(0,1)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [7] main::i#1 = ++ main::i#2 to ++
Resolved ranged comparison value [9] if(main::i#1!=rangelast(0,1)) goto main::@1 to 2
Converting *(pointer+n) to pointer[n] [6] main::SCREEN[main::i#2] = *main::$2  -- main::$3[OFFSET_STRUCT_TILE_COUNT]
Successful SSA optimization Pass2InlineDerefIdx
De-inlining pointer[w] to *(pointer+w)   [3] main::tile#0 = TileDB[main::$1]
De-inlining pointer[w] to *(pointer+w)   [6] main::SCREEN[main::i#2] = main::$3[OFFSET_STRUCT_TILE_COUNT]
Successful SSA optimization Pass2DeInlineWordDerefIdx
Eliminating unused variable main::$2 and assignment [5] main::$2 = main::$3 + OFFSET_STRUCT_TILE_COUNT
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Adding number conversion cast (snumber) 2 in [8] if(main::i#1!=2) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 2
Successful SSA optimization PassNCastSimplification
Finalized signed number type (signed char) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining Noop Cast [4] main::$3 = (char *)main::tile#0 keeping main::tile#0
Successful SSA optimization Pass2NopCastInlining
Rewriting multiplication to use shift [1] main::$1 = main::i#2 * SIZEOF_POINTER
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings main::i#0
Constant inlined main::i#0 = 0
Successful SSA optimization Pass2ConstantInlining
Eliminating unused constant SIZEOF_POINTER
Successful SSA optimization PassNEliminateUnusedVars
Finalized unsigned number type (char) $14
Finalized unsigned number type (char) $14
Finalized unsigned number type (char) $c
Finalized unsigned number type (char) $c
Finalized unsigned number type (char) $c
Finalized unsigned number type (char) $c
Finalized unsigned number type (char) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Added new block during phi lifting main::@2(between main::@1 and main::@1)
Adding NOP phi() at start of main
CALL GRAPH

Created 1 initial phi equivalence classes
Coalesced [10] main::i#3 = main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block label main::@2
Adding NOP phi() at start of main

FINAL CONTROL FLOW GRAPH

void main()
main: scope:[main]  from
  [0] phi()
  to:main::@1
main::@1: scope:[main]  from main main::@1
  [1] main::i#2 = phi( main/0, main::@1/main::i#1 )
  [2] main::$1 = main::i#2 << 1
  [3] main::$4 = TileDB + main::$1
  [4] main::tile#0 = *main::$4
  [5] main::$5 = main::SCREEN + main::i#2
  [6] *main::$5 = ((char *)main::tile#0)[OFFSET_STRUCT_TILE_COUNT]
  [7] main::i#1 = ++ main::i#2
  [8] if(main::i#1!=2) goto main::@1
  to:main::@return
main::@return: scope:[main]  from main::@1
  [9] return 
  to:@return


VARIABLE REGISTER WEIGHTS
__loadstore volatile struct Tile S1 = { Tiles: PlayerSprites, Offset: $14, Count: $40, Name: "Sven" }
__loadstore volatile struct Tile S2 = { Tiles: Enemy2Sprites, Offset: $32, Count: $80, Name: "Jesper" }
void main()
int main::$1 // 22.0
struct Tile **main::$4 // 22.0
char *main::$5 // 22.0
int main::i
int main::i#1 // 16.5
int main::i#2 // 7.333333333333333
struct Tile *main::tile
struct Tile *main::tile#0 // 5.5

Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Added variable main::$1 to live range equivalence class [ main::$1 ]
Added variable main::$4 to live range equivalence class [ main::$4 ]
Added variable main::tile#0 to live range equivalence class [ main::tile#0 ]
Added variable main::$5 to live range equivalence class [ main::$5 ]
Added variable S1 to live range equivalence class [ S1 ]
Added variable S2 to live range equivalence class [ S2 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::$1 ]
[ main::$4 ]
[ main::tile#0 ]
[ main::$5 ]
[ S1 ]
[ S2 ]
Allocated zp[2]:2 [ main::i#2 main::i#1 ]
Allocated zp[2]:4 [ main::$1 ]
Allocated zp[2]:6 [ main::$4 ]
Allocated zp[2]:8 [ main::$5 ]
Allocated zp[2]:10 [ main::tile#0 ]
Allocated mem[25] [ S1 ]
Allocated mem[25] [ S2 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [2] main::$1 = main::i#2 << 1 [ main::i#2 main::$1 ] (  [ main::i#2 main::$1 ] { }  ) always clobbers reg byte a 
Statement [3] main::$4 = TileDB + main::$1 [ main::i#2 main::$4 ] (  [ main::i#2 main::$4 ] { }  ) always clobbers reg byte a 
Statement [4] main::tile#0 = *main::$4 [ main::i#2 main::tile#0 ] (  [ main::i#2 main::tile#0 ] { }  ) always clobbers reg byte a reg byte y 
Statement [5] main::$5 = main::SCREEN + main::i#2 [ main::i#2 main::tile#0 main::$5 ] (  [ main::i#2 main::tile#0 main::$5 ] { }  ) always clobbers reg byte a 
Statement [6] *main::$5 = ((char *)main::tile#0)[OFFSET_STRUCT_TILE_COUNT] [ main::i#2 ] (  [ main::i#2 ] { }  ) always clobbers reg byte a reg byte y 
Statement [8] if(main::i#1!=2) goto main::@1 [ main::i#1 ] (  [ main::i#1 ] { }  ) always clobbers reg byte a 
Potential registers zp[2]:2 [ main::i#2 main::i#1 ] : zp[2]:2 , 
Potential registers zp[2]:4 [ main::$1 ] : zp[2]:4 , 
Potential registers zp[2]:6 [ main::$4 ] : zp[2]:6 , 
Potential registers zp[2]:10 [ main::tile#0 ] : zp[2]:10 , 
Potential registers zp[2]:8 [ main::$5 ] : zp[2]:8 , 
Potential registers mem[25] [ S1 ] : mem[25] , 
Potential registers mem[25] [ S2 ] : mem[25] , 

REGISTER UPLIFT SCOPES
Uplift Scope [main] 23.83: zp[2]:2 [ main::i#2 main::i#1 ] 22: zp[2]:4 [ main::$1 ] 22: zp[2]:6 [ main::$4 ] 22: zp[2]:8 [ main::$5 ] 5.5: zp[2]:10 [ main::tile#0 ] 
Uplift Scope [Tile] 
Uplift Scope [] 0: mem[25] [ S1 ] 0: mem[25] [ S2 ] 

Uplifting [main] best 1356 combination zp[2]:2 [ main::i#2 main::i#1 ] zp[2]:4 [ main::$1 ] zp[2]:6 [ main::$4 ] zp[2]:8 [ main::$5 ] zp[2]:10 [ main::tile#0 ] 
Uplifting [Tile] best 1356 combination 
Uplifting [] best 1356 combination mem[25] [ S1 ] mem[25] [ S2 ] 
Coalescing zero page register [ zp[2]:4 [ main::$1 ] ] with [ zp[2]:6 [ main::$4 ] ] - score: 1
Coalescing zero page register [ zp[2]:4 [ main::$1 main::$4 ] ] with [ zp[2]:10 [ main::tile#0 ] ] - score: 1
Allocated (was zp[2]:4) zp[2]:2 [ main::$1 main::$4 main::tile#0 ]
Allocated (was zp[2]:2) zp[2]:4 [ main::i#2 main::i#1 ]
Allocated (was zp[2]:8) zp[2]:6 [ main::$5 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
  // Upstart
  // Commodore 64 PRG executable file
.file [name="struct-ptr-35.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
  // Global Constants & labels
  .const OFFSET_STRUCT_TILE_COUNT = 4
.segment Code
  // main
main: {
    .label SCREEN = $400
    .label __1 = 2
    .label tile = 2
    .label i = 4
    .label __4 = 2
    .label __5 = 6
    // [1] phi from main to main::@1 [phi:main->main::@1]
  __b1_from_main:
    // [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vwsz1=vwsc1 
    lda #<0
    sta.z i
    lda #>0
    sta.z i+1
    jmp __b1
    // [1] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
  __b1_from___b1:
    // [1] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
    jmp __b1
    // main::@1
  __b1:
    // [2] main::$1 = main::i#2 << 1 -- vwsz1=vwsz2_rol_1 
    lda.z i
    asl
    sta.z __1
    lda.z i+1
    rol
    sta.z __1+1
    // [3] main::$4 = TileDB + main::$1 -- qssz1=qssc1_plus_vwsz1 
    clc
    lda #<TileDB
    adc.z __4
    sta.z __4
    lda #>TileDB
    adc.z __4+1
    sta.z __4+1
    // [4] main::tile#0 = *main::$4 -- pssz1=_deref_qssz1 
    ldy #0
    lda (tile),y
    pha
    iny
    lda (tile),y
    sta.z tile+1
    pla
    sta.z tile
    // [5] main::$5 = main::SCREEN + main::i#2 -- pbuz1=pbuc1_plus_vwsz2 
    lda #<SCREEN
    clc
    adc.z i
    sta.z __5
    lda #>SCREEN
    adc.z i+1
    sta.z __5+1
    // [6] *main::$5 = ((char *)main::tile#0)[OFFSET_STRUCT_TILE_COUNT] -- _deref_pbuz1=pbuz2_derefidx_vbuc1 
    ldy #OFFSET_STRUCT_TILE_COUNT
    lda (tile),y
    ldy #0
    sta (__5),y
    // [7] main::i#1 = ++ main::i#2 -- vwsz1=_inc_vwsz1 
    inc.z i
    bne !+
    inc.z i+1
  !:
    // [8] if(main::i#1!=2) goto main::@1 -- vwsz1_neq_vwuc1_then_la1 
    lda.z i+1
    cmp #>2
    bne __b1_from___b1
    lda.z i
    cmp #<2
    bne __b1_from___b1
    jmp __breturn
    // main::@return
  __breturn:
    // [9] return 
    rts
}
  // File Data
.segment Data
  PlayerSprites: .fill 4*$c, 0
  Enemy2Sprites: .fill 4*$c, 0
  TileDB: .word S1, S2
  S1: .word PlayerSprites, $14
  .byte $40
  .text "Sven"
  .byte 0
  .fill $f, 0
  S2: .word Enemy2Sprites, $32
  .byte $80
  .text "Jesper"
  .byte 0
  .fill $d, 0

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #>0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __b1_from___b1 with __b1
Replacing label __b1_from___b1 with __b1
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1_from_main:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination

FINAL SYMBOL TABLE
__constant unsigned long Enemy2Sprites[$c] = { fill( $c, 0) }
__constant char OFFSET_STRUCT_TILE_COUNT = 4
__constant unsigned long PlayerSprites[$c] = { fill( $c, 0) }
__loadstore volatile struct Tile S1 = { Tiles: PlayerSprites, Offset: $14, Count: $40, Name: "Sven" } // mem[25]
__loadstore volatile struct Tile S2 = { Tiles: Enemy2Sprites, Offset: $32, Count: $80, Name: "Jesper" } // mem[25]
__constant struct Tile *TileDB[2] = { &S1, &S2 }
void main()
int main::$1 // zp[2]:2 22.0
struct Tile **main::$4 // zp[2]:2 22.0
char *main::$5 // zp[2]:6 22.0
__constant char * const main::SCREEN = (char *) 1024
int main::i
int main::i#1 // i zp[2]:4 16.5
int main::i#2 // i zp[2]:4 7.333333333333333
struct Tile *main::tile
struct Tile *main::tile#0 // tile zp[2]:2 5.5

zp[2]:4 [ main::i#2 main::i#1 ]
zp[2]:2 [ main::$1 main::$4 main::tile#0 ]
zp[2]:6 [ main::$5 ]
mem[25] [ S1 ]
mem[25] [ S2 ]


FINAL ASSEMBLER
Score: 1316

  // File Comments
  // Upstart
  // Commodore 64 PRG executable file
.file [name="struct-ptr-35.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
  // Global Constants & labels
  .const OFFSET_STRUCT_TILE_COUNT = 4
.segment Code
  // main
main: {
    .label SCREEN = $400
    .label __1 = 2
    .label tile = 2
    .label i = 4
    .label __4 = 2
    .label __5 = 6
    // [1] phi from main to main::@1 [phi:main->main::@1]
    // [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vwsz1=vwsc1 
    lda #<0
    sta.z i
    sta.z i+1
    // [1] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
    // [1] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
    // main::@1
  __b1:
    // struct Tile *tile = TileDB[i]
    // [2] main::$1 = main::i#2 << 1 -- vwsz1=vwsz2_rol_1 
    lda.z i
    asl
    sta.z __1
    lda.z i+1
    rol
    sta.z __1+1
    // [3] main::$4 = TileDB + main::$1 -- qssz1=qssc1_plus_vwsz1 
    clc
    lda #<TileDB
    adc.z __4
    sta.z __4
    lda #>TileDB
    adc.z __4+1
    sta.z __4+1
    // [4] main::tile#0 = *main::$4 -- pssz1=_deref_qssz1 
    ldy #0
    lda (tile),y
    pha
    iny
    lda (tile),y
    sta.z tile+1
    pla
    sta.z tile
    // SCREEN[i] =  tile->Count
    // [5] main::$5 = main::SCREEN + main::i#2 -- pbuz1=pbuc1_plus_vwsz2 
    lda #<SCREEN
    clc
    adc.z i
    sta.z __5
    lda #>SCREEN
    adc.z i+1
    sta.z __5+1
    // [6] *main::$5 = ((char *)main::tile#0)[OFFSET_STRUCT_TILE_COUNT] -- _deref_pbuz1=pbuz2_derefidx_vbuc1 
    ldy #OFFSET_STRUCT_TILE_COUNT
    lda (tile),y
    ldy #0
    sta (__5),y
    // for(int i:0..1)
    // [7] main::i#1 = ++ main::i#2 -- vwsz1=_inc_vwsz1 
    inc.z i
    bne !+
    inc.z i+1
  !:
    // [8] if(main::i#1!=2) goto main::@1 -- vwsz1_neq_vwuc1_then_la1 
    lda.z i+1
    cmp #>2
    bne __b1
    lda.z i
    cmp #<2
    bne __b1
    // main::@return
    // }
    // [9] return 
    rts
}
  // File Data
.segment Data
  PlayerSprites: .fill 4*$c, 0
  Enemy2Sprites: .fill 4*$c, 0
  TileDB: .word S1, S2
  S1: .word PlayerSprites, $14
  .byte $40
  .text "Sven"
  .byte 0
  .fill $f, 0
  S2: .word Enemy2Sprites, $32
  .byte $80
  .text "Jesper"
  .byte 0
  .fill $d, 0

