Inlined call call __init
Eliminating unused variable with no statement malloc::$0
Eliminating unused variable with no statement main::$0
Eliminating unused variable with no statement main::$1

CONTROL FLOW GRAPH SSA

void * malloc(unsigned int size)
malloc: scope:[malloc]  from main main::@3
  malloc::size#2 = phi( main/malloc::size#0, main::@3/malloc::size#1 )
  heap_head#8 = phi( main/heap_head#15, main::@3/heap_head#2 )
  malloc::mem#0 = heap_head#8 - malloc::size#2
  heap_head#0 = malloc::mem#0
  malloc::return#0 = ((void *)) malloc::mem#0
  to:malloc::@return
malloc::@return: scope:[malloc]  from malloc
  heap_head#9 = phi( malloc/heap_head#0 )
  malloc::return#4 = phi( malloc/malloc::return#0 )
  malloc::return#1 = malloc::return#4
  heap_head#1 = heap_head#9
  return 
  to:@return

void free(void *ptr)
free: scope:[free]  from main::@2 main::@5
  to:free::@return
free::@return: scope:[free]  from free
  return 
  to:@return

void main()
main: scope:[main]  from __start::@1
  heap_head#15 = phi( __start::@1/heap_head#17 )
  malloc::size#0 = $64
  call malloc
  malloc::return#2 = malloc::return#1
  to:main::@3
main::@3: scope:[main]  from main
  heap_head#10 = phi( main/heap_head#1 )
  malloc::return#5 = phi( main/malloc::return#2 )
  main::buf1#0 = ((char *)) malloc::return#5
  heap_head#2 = heap_head#10
  malloc::size#1 = $64
  call malloc
  malloc::return#3 = malloc::return#1
  to:main::@4
main::@4: scope:[main]  from main::@3
  main::buf1#4 = phi( main::@3/main::buf1#0 )
  heap_head#11 = phi( main::@3/heap_head#1 )
  malloc::return#6 = phi( main::@3/malloc::return#3 )
  main::buf2#0 = ((char *)) malloc::return#6
  heap_head#3 = heap_head#11
  main::i#0 = 0
  to:main::@1
main::@1: scope:[main]  from main::@1 main::@4
  heap_head#20 = phi( main::@1/heap_head#20, main::@4/heap_head#3 )
  main::buf2#1 = phi( main::@1/main::buf2#1, main::@4/main::buf2#0 )
  main::buf1#1 = phi( main::@1/main::buf1#1, main::@4/main::buf1#4 )
  main::i#2 = phi( main::@1/main::i#1, main::@4/main::i#0 )
  main::buf1#1[main::i#2] = main::i#2
  main::$4 = $ff - main::i#2
  main::buf2#1[main::i#2] = main::$4
  main::i#1 = main::i#2 + rangenext(0,$63)
  main::$5 = main::i#1 != rangelast(0,$63)
  if(main::$5) goto main::@1
  to:main::@2
main::@2: scope:[main]  from main::@1
  heap_head#19 = phi( main::@1/heap_head#20 )
  main::buf2#4 = phi( main::@1/main::buf2#1 )
  main::buf1#2 = phi( main::@1/main::buf1#1 )
  free::ptr#0 = (void *)main::buf1#2
  call free
  to:main::@5
main::@5: scope:[main]  from main::@2
  heap_head#18 = phi( main::@2/heap_head#19 )
  main::buf1#5 = phi( main::@2/main::buf1#2 )
  main::buf2#2 = phi( main::@2/main::buf2#4 )
  free::ptr#1 = (void *)main::buf2#2
  call free
  to:main::@6
main::@6: scope:[main]  from main::@5
  heap_head#16 = phi( main::@5/heap_head#18 )
  main::buf2#3 = phi( main::@5/main::buf2#2 )
  main::buf1#3 = phi( main::@5/main::buf1#5 )
  main::screen[0] = *main::buf1#3
  main::screen[1] = *main::buf2#3
  to:main::@return
main::@return: scope:[main]  from main::@6
  heap_head#12 = phi( main::@6/heap_head#16 )
  heap_head#4 = heap_head#12
  return 
  to:@return

void __start()
__start: scope:[__start]  from
  to:__start::__init1
__start::__init1: scope:[__start]  from __start
  heap_head#5 = HEAP_TOP
  to:__start::@1
__start::@1: scope:[__start]  from __start::__init1
  heap_head#17 = phi( __start::__init1/heap_head#5 )
  call main
  to:__start::@2
__start::@2: scope:[__start]  from __start::@1
  heap_head#13 = phi( __start::@1/heap_head#4 )
  heap_head#6 = heap_head#13
  to:__start::@return
__start::@return: scope:[__start]  from __start::@2
  heap_head#14 = phi( __start::@2/heap_head#6 )
  heap_head#7 = heap_head#14
  return 
  to:@return

SYMBOL TABLE SSA
__constant char *HEAP_TOP = (char *)$a000
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
void __start()
void free(void *ptr)
void *free::ptr
void *free::ptr#0
void *free::ptr#1
char *heap_head
char *heap_head#0
char *heap_head#1
char *heap_head#10
char *heap_head#11
char *heap_head#12
char *heap_head#13
char *heap_head#14
char *heap_head#15
char *heap_head#16
char *heap_head#17
char *heap_head#18
char *heap_head#19
char *heap_head#2
char *heap_head#20
char *heap_head#3
char *heap_head#4
char *heap_head#5
char *heap_head#6
char *heap_head#7
char *heap_head#8
char *heap_head#9
void main()
number main::$4
bool main::$5
char *main::buf1
char *main::buf1#0
char *main::buf1#1
char *main::buf1#2
char *main::buf1#3
char *main::buf1#4
char *main::buf1#5
char *main::buf2
char *main::buf2#0
char *main::buf2#1
char *main::buf2#2
char *main::buf2#3
char *main::buf2#4
char main::i
char main::i#0
char main::i#1
char main::i#2
__constant char *main::screen = (char *)$400
void * malloc(unsigned int size)
char *malloc::mem
char *malloc::mem#0
void *malloc::return
void *malloc::return#0
void *malloc::return#1
void *malloc::return#2
void *malloc::return#3
void *malloc::return#4
void *malloc::return#5
void *malloc::return#6
unsigned int malloc::size
unsigned int malloc::size#0
unsigned int malloc::size#1
unsigned int malloc::size#2

Adding number conversion cast (unumber) $64 in malloc::size#0 = $64
Adding number conversion cast (unumber) $64 in malloc::size#1 = $64
Adding number conversion cast (unumber) $ff in main::$4 = $ff - main::i#2
Adding number conversion cast (unumber) main::$4 in main::$4 = (unumber)$ff - main::i#2
Adding number conversion cast (unumber) 0 in main::screen[0] = *main::buf1#3
Adding number conversion cast (unumber) 1 in main::screen[1] = *main::buf2#3
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast malloc::return#0 = (void *)malloc::mem#0
Inlining cast malloc::size#0 = (unumber)$64
Inlining cast main::buf1#0 = (char *)malloc::return#5
Inlining cast malloc::size#1 = (unumber)$64
Inlining cast main::buf2#0 = (char *)malloc::return#6
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (char *) 1024
Simplifying constant pointer cast (char *) 40960
Simplifying constant integer cast $64
Simplifying constant integer cast $64
Simplifying constant integer cast $ff
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $64
Finalized unsigned number type (char) $64
Finalized unsigned number type (char) $ff
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to char in main::$4 = $ff - main::i#2
Alias malloc::return#0 = malloc::return#4 malloc::return#1 
Alias heap_head#0 = heap_head#9 heap_head#1 
Alias malloc::return#2 = malloc::return#5 
Alias heap_head#10 = heap_head#2 
Alias malloc::return#3 = malloc::return#6 
Alias main::buf1#0 = main::buf1#4 
Alias heap_head#11 = heap_head#3 
Alias main::buf1#1 = main::buf1#2 main::buf1#5 main::buf1#3 
Alias main::buf2#1 = main::buf2#4 main::buf2#2 main::buf2#3 
Alias heap_head#12 = heap_head#19 heap_head#20 heap_head#18 heap_head#16 heap_head#4 
Alias heap_head#17 = heap_head#5 
Alias heap_head#13 = heap_head#6 heap_head#14 heap_head#7 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values heap_head#15 heap_head#17
Identical Phi Values heap_head#10 heap_head#0
Identical Phi Values heap_head#11 heap_head#0
Identical Phi Values main::buf1#1 main::buf1#0
Identical Phi Values main::buf2#1 main::buf2#0
Identical Phi Values heap_head#12 heap_head#11
Identical Phi Values heap_head#13 heap_head#12
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition main::$5 [24] if(main::i#1!=rangelast(0,$63)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant malloc::size#0 = $64
Constant malloc::size#1 = $64
Constant main::i#0 = 0
Constant heap_head#17 = HEAP_TOP
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [22] main::i#1 = ++ main::i#2 to ++
Resolved ranged comparison value [24] if(main::i#1!=rangelast(0,$63)) goto main::@1 to $64
Simplifying expression containing zero main::screen in [29] main::screen[0] = *main::buf1#0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable free::ptr#0 and assignment [18] free::ptr#0 = (void *)main::buf1#0
Eliminating unused variable free::ptr#1 and assignment [20] free::ptr#1 = (void *)main::buf2#0
Successful SSA optimization PassNEliminateUnusedVars
Removing call to empty/unused procedure [18] call free
Removing call to empty/unused procedure [19] call free
Removing unused procedure free
Removing unused procedure block free
Removing unused procedure block free::@return
Successful SSA optimization PassNEliminateEmptyProcedure
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Adding number conversion cast (unumber) $64 in [16] if(main::i#1!=$64) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast $64
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $64
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining Noop Cast [3] malloc::return#0 = (void *)malloc::mem#0 keeping malloc::mem#0
Successful SSA optimization Pass2NopCastInlining
Inlining Noop Cast [6] malloc::return#2 = (void *)malloc::mem#0 keeping malloc::mem#0
Inlining Noop Cast [9] malloc::return#3 = (void *)malloc::mem#0 keeping malloc::mem#0
Successful SSA optimization Pass2NopCastInlining
Inlining constant with var siblings malloc::size#0
Inlining constant with var siblings malloc::size#1
Inlining constant with var siblings main::i#0
Inlining constant with var siblings heap_head#17
Constant inlined main::i#0 = 0
Constant inlined malloc::size#1 = $64
Constant inlined malloc::size#0 = $64
Constant inlined heap_head#17 = HEAP_TOP
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::screen+1)
Successful SSA optimization Pass2ConstantAdditionElimination
Identical Phi Values malloc::size#2 $64
Successful SSA optimization Pass2IdenticalPhiElimination
Finalized unsigned number type (char) 2
Finalized unsigned number type (char) 8
Finalized unsigned number type (char) $a
Finalized unsigned number type (char) $10
Successful SSA optimization PassNFinalizeNumberTypeConversions
Added new block during phi lifting main::@7(between main::@1 and main::@1)
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@2
Adding NOP phi() at start of main::@5
CALL GRAPH
Calls in [main] to malloc:1 malloc:4 

Created 2 initial phi equivalence classes
Coalesced [3] heap_head#21 = heap_head#0
Coalesced [17] main::i#3 = main::i#1
Not coalescing [20] heap_head#0 = malloc::mem#0
Coalesced down to 3 phi equivalence classes
Culled Empty Block label main::@2
Culled Empty Block label main::@5
Culled Empty Block label main::@7
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
Renumbering block main::@6 to main::@4
Adding NOP phi() at start of main

FINAL CONTROL FLOW GRAPH

void main()
main: scope:[main]  from
  [0] phi()
  [1] call malloc
  to:main::@2
main::@2: scope:[main]  from main
  [2] main::buf1#0 = (char *)(void *)malloc::mem#0
  [3] call malloc
  to:main::@3
main::@3: scope:[main]  from main::@2
  [4] main::buf2#0 = (char *)(void *)malloc::mem#0
  to:main::@1
main::@1: scope:[main]  from main::@1 main::@3
  [5] main::i#2 = phi( main::@1/main::i#1, main::@3/0 )
  [6] main::buf1#0[main::i#2] = main::i#2
  [7] main::$4 = $ff - main::i#2
  [8] main::buf2#0[main::i#2] = main::$4
  [9] main::i#1 = ++ main::i#2
  [10] if(main::i#1!=$64) goto main::@1
  to:main::@4
main::@4: scope:[main]  from main::@1
  [11] *main::screen = *main::buf1#0
  [12] *(main::screen+1) = *main::buf2#0
  to:main::@return
main::@return: scope:[main]  from main::@4
  [13] return 
  to:@return

void * malloc(unsigned int size)
malloc: scope:[malloc]  from main main::@2
  [14] heap_head#8 = phi( main/HEAP_TOP, main::@2/heap_head#0 )
  [15] malloc::mem#0 = heap_head#8 - $64
  [16] heap_head#0 = malloc::mem#0
  to:malloc::@return
malloc::@return: scope:[malloc]  from malloc
  [17] return 
  to:@return


VARIABLE REGISTER WEIGHTS
char *heap_head
char *heap_head#0 // 3.25
char *heap_head#8 // 13.0
void main()
char main::$4 // 22.0
char *main::buf1
char *main::buf1#0 // 1.666666666666667
char *main::buf2
char *main::buf2#0 // 1.875
char main::i
char main::i#1 // 16.5
char main::i#2 // 16.5
void * malloc(unsigned int size)
char *malloc::mem
char *malloc::mem#0 // 4.4
void *malloc::return
unsigned int malloc::size

Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ heap_head#8 heap_head#0 ]
Added variable main::buf1#0 to live range equivalence class [ main::buf1#0 ]
Added variable main::buf2#0 to live range equivalence class [ main::buf2#0 ]
Added variable main::$4 to live range equivalence class [ main::$4 ]
Added variable malloc::mem#0 to live range equivalence class [ malloc::mem#0 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ heap_head#8 heap_head#0 ]
[ main::buf1#0 ]
[ main::buf2#0 ]
[ main::$4 ]
[ malloc::mem#0 ]
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
Allocated zp[1]:3 [ main::$4 ]
Allocated zp[2]:4 [ heap_head#8 heap_head#0 ]
Allocated zp[2]:6 [ malloc::mem#0 ]
Allocated zp[2]:8 [ main::buf2#0 ]
Allocated zp[2]:10 [ main::buf1#0 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [2] main::buf1#0 = (char *)(void *)malloc::mem#0 [ main::buf1#0 heap_head#0 ] (  [ main::buf1#0 heap_head#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Statement [4] main::buf2#0 = (char *)(void *)malloc::mem#0 [ main::buf1#0 main::buf2#0 ] (  [ main::buf1#0 main::buf2#0 ] { }  ) always clobbers reg byte a 
Statement [7] main::$4 = $ff - main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] (  [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] { }  ) always clobbers reg byte a 
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [11] *main::screen = *main::buf1#0 [ main::buf2#0 ] (  [ main::buf2#0 ] { }  ) always clobbers reg byte a reg byte y 
Statement [12] *(main::screen+1) = *main::buf2#0 [ ] (  [ ] { }  ) always clobbers reg byte a reg byte y 
Statement [15] malloc::mem#0 = heap_head#8 - $64 [ malloc::mem#0 ] ( malloc:1 [ malloc::mem#0 ] { }  malloc:3 [ main::buf1#0 malloc::mem#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Statement [16] heap_head#0 = malloc::mem#0 [ malloc::mem#0 heap_head#0 ] ( malloc:1 [ malloc::mem#0 heap_head#0 ] { }  malloc:3 [ main::buf1#0 malloc::mem#0 heap_head#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Statement [2] main::buf1#0 = (char *)(void *)malloc::mem#0 [ main::buf1#0 heap_head#0 ] (  [ main::buf1#0 heap_head#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Statement [4] main::buf2#0 = (char *)(void *)malloc::mem#0 [ main::buf1#0 main::buf2#0 ] (  [ main::buf1#0 main::buf2#0 ] { }  ) always clobbers reg byte a 
Statement [6] main::buf1#0[main::i#2] = main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 ] (  [ main::buf1#0 main::buf2#0 main::i#2 ] { }  ) always clobbers reg byte a 
Statement [7] main::$4 = $ff - main::i#2 [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] (  [ main::buf1#0 main::buf2#0 main::i#2 main::$4 ] { }  ) always clobbers reg byte a 
Statement [11] *main::screen = *main::buf1#0 [ main::buf2#0 ] (  [ main::buf2#0 ] { }  ) always clobbers reg byte a reg byte y 
Statement [12] *(main::screen+1) = *main::buf2#0 [ ] (  [ ] { }  ) always clobbers reg byte a reg byte y 
Statement [15] malloc::mem#0 = heap_head#8 - $64 [ malloc::mem#0 ] ( malloc:1 [ malloc::mem#0 ] { }  malloc:3 [ main::buf1#0 malloc::mem#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Statement [16] heap_head#0 = malloc::mem#0 [ malloc::mem#0 heap_head#0 ] ( malloc:1 [ malloc::mem#0 heap_head#0 ] { }  malloc:3 [ main::buf1#0 malloc::mem#0 heap_head#0 ] { { heap_head#0 = heap_head#8 } }  ) always clobbers reg byte a 
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y , 
Potential registers zp[2]:4 [ heap_head#8 heap_head#0 ] : zp[2]:4 , 
Potential registers zp[2]:10 [ main::buf1#0 ] : zp[2]:10 , 
Potential registers zp[2]:8 [ main::buf2#0 ] : zp[2]:8 , 
Potential registers zp[1]:3 [ main::$4 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[2]:6 [ malloc::mem#0 ] : zp[2]:6 , 

REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp[1]:2 [ main::i#2 main::i#1 ] 22: zp[1]:3 [ main::$4 ] 1.88: zp[2]:8 [ main::buf2#0 ] 1.67: zp[2]:10 [ main::buf1#0 ] 
Uplift Scope [] 16.25: zp[2]:4 [ heap_head#8 heap_head#0 ] 
Uplift Scope [malloc] 4.4: zp[2]:6 [ malloc::mem#0 ] 
Uplift Scope [RADIX] 

Uplifting [main] best 517 combination reg byte y [ main::i#2 main::i#1 ] reg byte a [ main::$4 ] zp[2]:8 [ main::buf2#0 ] zp[2]:10 [ main::buf1#0 ] 
Uplifting [] best 517 combination zp[2]:4 [ heap_head#8 heap_head#0 ] 
Uplifting [malloc] best 517 combination zp[2]:6 [ malloc::mem#0 ] 
Uplifting [RADIX] best 517 combination 
Coalescing zero page register [ zp[2]:8 [ main::buf2#0 ] ] with [ zp[2]:6 [ malloc::mem#0 ] ] - score: 1
Allocated (was zp[2]:4) zp[2]:2 [ heap_head#8 heap_head#0 ]
Allocated (was zp[2]:8) zp[2]:4 [ main::buf2#0 malloc::mem#0 ]
Allocated (was zp[2]:10) zp[2]:6 [ main::buf1#0 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Experiments with malloc()
  // Upstart
  // Commodore 64 PRG executable file
.file [name="memory-heap.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
  // Top of the heap used by malloc()
  .label HEAP_TOP = $a000
  // Head of the heap. Moved backward each malloc()
  .label heap_head = 2
.segment Code
  // main
main: {
    .label screen = $400
    .label buf1 = 6
    .label buf2 = 4
    // [1] call malloc
    // [14] phi from main to malloc [phi:main->malloc]
  malloc_from_main:
    // [14] phi heap_head#8 = HEAP_TOP [phi:main->malloc#0] -- pbuz1=pbuc1 
    lda #<HEAP_TOP
    sta.z heap_head
    lda #>HEAP_TOP
    sta.z heap_head+1
    jsr malloc
    jmp __b2
    // main::@2
  __b2:
    // [2] main::buf1#0 = (char *)(void *)malloc::mem#0 -- pbuz1=pbuz2 
    lda.z malloc.mem
    sta.z buf1
    lda.z malloc.mem+1
    sta.z buf1+1
    // [3] call malloc
    // [14] phi from main::@2 to malloc [phi:main::@2->malloc]
  malloc_from___b2:
    // [14] phi heap_head#8 = heap_head#0 [phi:main::@2->malloc#0] -- register_copy 
    jsr malloc
    jmp __b3
    // main::@3
  __b3:
    // [4] main::buf2#0 = (char *)(void *)malloc::mem#0
    // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
  __b1_from___b3:
    // [5] phi main::i#2 = 0 [phi:main::@3->main::@1#0] -- vbuyy=vbuc1 
    ldy #0
    jmp __b1
    // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
  __b1_from___b1:
    // [5] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
    jmp __b1
    // main::@1
  __b1:
    // [6] main::buf1#0[main::i#2] = main::i#2 -- pbuz1_derefidx_vbuyy=vbuyy 
    tya
    sta (buf1),y
    // [7] main::$4 = $ff - main::i#2 -- vbuaa=vbuc1_minus_vbuyy 
    tya
    eor #$ff
    sec
    adc #$ff
    // [8] main::buf2#0[main::i#2] = main::$4 -- pbuz1_derefidx_vbuyy=vbuaa 
    sta (buf2),y
    // [9] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy 
    iny
    // [10] if(main::i#1!=$64) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 
    cpy #$64
    bne __b1_from___b1
    jmp __b4
    // main::@4
  __b4:
    // [11] *main::screen = *main::buf1#0 -- _deref_pbuc1=_deref_pbuz1 
    ldy #0
    lda (buf1),y
    sta screen
    // [12] *(main::screen+1) = *main::buf2#0 -- _deref_pbuc1=_deref_pbuz1 
    ldy #0
    lda (buf2),y
    sta screen+1
    jmp __breturn
    // main::@return
  __breturn:
    // [13] return 
    rts
}
  // malloc
// Allocates a block of size chars of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
// void * malloc(unsigned int size)
malloc: {
    .label mem = 4
    // [15] malloc::mem#0 = heap_head#8 - $64 -- pbuz1=pbuz2_minus_vbuc1 
    sec
    lda.z heap_head
    sbc #$64
    sta.z mem
    lda.z heap_head+1
    sbc #0
    sta.z mem+1
    // [16] heap_head#0 = malloc::mem#0 -- pbuz1=pbuz2 
    lda.z mem
    sta.z heap_head
    lda.z mem+1
    sta.z heap_head+1
    jmp __breturn
    // malloc::@return
  __breturn:
    // [17] return 
    rts
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b2
Removing instruction jmp __b3
Removing instruction jmp __b1
Removing instruction jmp __b4
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldy #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __b1_from___b1 with __b1
Removing instruction __b1_from___b3:
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction malloc_from_main:
Removing instruction __b2:
Removing instruction malloc_from___b2:
Removing instruction __b3:
Removing instruction __b4:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination

FINAL SYMBOL TABLE
__constant char *HEAP_TOP = (char *) 40960
__constant char RADIX::BINARY = 2
__constant char RADIX::DECIMAL = $a
__constant char RADIX::HEXADECIMAL = $10
__constant char RADIX::OCTAL = 8
char *heap_head
char *heap_head#0 // heap_head zp[2]:2 3.25
char *heap_head#8 // heap_head zp[2]:2 13.0
void main()
char main::$4 // reg byte a 22.0
char *main::buf1
char *main::buf1#0 // buf1 zp[2]:6 1.666666666666667
char *main::buf2
char *main::buf2#0 // buf2 zp[2]:4 1.875
char main::i
char main::i#1 // reg byte y 16.5
char main::i#2 // reg byte y 16.5
__constant char *main::screen = (char *) 1024
void * malloc(unsigned int size)
char *malloc::mem
char *malloc::mem#0 // mem zp[2]:4 4.4
void *malloc::return
unsigned int malloc::size

reg byte y [ main::i#2 main::i#1 ]
zp[2]:2 [ heap_head#8 heap_head#0 ]
zp[2]:6 [ main::buf1#0 ]
zp[2]:4 [ main::buf2#0 malloc::mem#0 ]
reg byte a [ main::$4 ]


FINAL ASSEMBLER
Score: 401

  // File Comments
// Experiments with malloc()
  // Upstart
  // Commodore 64 PRG executable file
.file [name="memory-heap.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
  // Top of the heap used by malloc()
  .label HEAP_TOP = $a000
  // Head of the heap. Moved backward each malloc()
  .label heap_head = 2
.segment Code
  // main
main: {
    .label screen = $400
    .label buf1 = 6
    .label buf2 = 4
    // unsigned char* buf1 = malloc(100)
    // [1] call malloc
    // [14] phi from main to malloc [phi:main->malloc]
    // [14] phi heap_head#8 = HEAP_TOP [phi:main->malloc#0] -- pbuz1=pbuc1 
    lda #<HEAP_TOP
    sta.z heap_head
    lda #>HEAP_TOP
    sta.z heap_head+1
    jsr malloc
    // main::@2
    // unsigned char* buf1 = malloc(100)
    // [2] main::buf1#0 = (char *)(void *)malloc::mem#0 -- pbuz1=pbuz2 
    lda.z malloc.mem
    sta.z buf1
    lda.z malloc.mem+1
    sta.z buf1+1
    // unsigned char* buf2 = malloc(100)
    // [3] call malloc
    // [14] phi from main::@2 to malloc [phi:main::@2->malloc]
    // [14] phi heap_head#8 = heap_head#0 [phi:main::@2->malloc#0] -- register_copy 
    jsr malloc
    // main::@3
    // unsigned char* buf2 = malloc(100)
    // [4] main::buf2#0 = (char *)(void *)malloc::mem#0
    // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
    // [5] phi main::i#2 = 0 [phi:main::@3->main::@1#0] -- vbuyy=vbuc1 
    ldy #0
    // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
    // [5] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
    // main::@1
  __b1:
    // buf1[i] = i
    // [6] main::buf1#0[main::i#2] = main::i#2 -- pbuz1_derefidx_vbuyy=vbuyy 
    tya
    sta (buf1),y
    // 255-i
    // [7] main::$4 = $ff - main::i#2 -- vbuaa=vbuc1_minus_vbuyy 
    tya
    eor #$ff
    sec
    adc #$ff
    // buf2[i] = 255-i
    // [8] main::buf2#0[main::i#2] = main::$4 -- pbuz1_derefidx_vbuyy=vbuaa 
    sta (buf2),y
    // for(unsigned char i:0..99)
    // [9] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy 
    iny
    // [10] if(main::i#1!=$64) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 
    cpy #$64
    bne __b1
    // main::@4
    // screen[0] = *buf1
    // [11] *main::screen = *main::buf1#0 -- _deref_pbuc1=_deref_pbuz1 
    ldy #0
    lda (buf1),y
    sta screen
    // screen[1] = *buf2
    // [12] *(main::screen+1) = *main::buf2#0 -- _deref_pbuc1=_deref_pbuz1 
    lda (buf2),y
    sta screen+1
    // main::@return
    // }
    // [13] return 
    rts
}
  // malloc
// Allocates a block of size chars of memory, returning a pointer to the beginning of the block.
// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
// void * malloc(unsigned int size)
malloc: {
    .label mem = 4
    // unsigned char* mem = heap_head-size
    // [15] malloc::mem#0 = heap_head#8 - $64 -- pbuz1=pbuz2_minus_vbuc1 
    sec
    lda.z heap_head
    sbc #$64
    sta.z mem
    lda.z heap_head+1
    sbc #0
    sta.z mem+1
    // heap_head = mem
    // [16] heap_head#0 = malloc::mem#0 -- pbuz1=pbuz2 
    lda.z mem
    sta.z heap_head
    lda.z mem+1
    sta.z heap_head+1
    // malloc::@return
    // }
    // [17] return 
    rts
}
  // File Data

