Culled Empty Block (label) @1
Culled Empty Block (label) fill::@4

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  to:@2
main: scope:[main]  from @2
  (byte*~) main::$0 ← ((byte*)) (number) $400
  (byte*) fill::screen#0 ← (byte*~) main::$0
  (byte) fill::ch#0 ← (byte) 'a'
  call fill 
  to:main::@1
main::@1: scope:[main]  from main
  (byte*~) main::$2 ← ((byte*)) (number) $2000
  (byte*) fill::screen#1 ← (byte*~) main::$2
  (byte) fill::ch#1 ← (byte) 'b'
  call fill 
  to:main::@2
main::@2: scope:[main]  from main::@1
  to:main::@return
main::@return: scope:[main]  from main::@2
  return 
  to:@return
fill: scope:[fill]  from main main::@1
  (byte) fill::ch#4 ← phi( main/(byte) fill::ch#0 main::@1/(byte) fill::ch#1 )
  (byte*) fill::screen#4 ← phi( main/(byte*) fill::screen#0 main::@1/(byte*) fill::screen#1 )
  (byte) fill::i#0 ← (byte) 0
  to:fill::@1
fill::@1: scope:[fill]  from fill fill::@3
  (byte) fill::i#4 ← phi( fill/(byte) fill::i#0 fill::@3/(byte) fill::i#1 )
  (byte) fill::ch#3 ← phi( fill/(byte) fill::ch#4 fill::@3/(byte) fill::ch#5 )
  (byte*) fill::screen#3 ← phi( fill/(byte*) fill::screen#4 fill::@3/(byte*) fill::screen#5 )
  (byte) fill::j#0 ← (byte) 0
  to:fill::@2
fill::@2: scope:[fill]  from fill::@1 fill::@2
  (byte) fill::i#2 ← phi( fill::@1/(byte) fill::i#4 fill::@2/(byte) fill::i#2 )
  (byte) fill::ch#2 ← phi( fill::@1/(byte) fill::ch#3 fill::@2/(byte) fill::ch#2 )
  (byte*) fill::screen#2 ← phi( fill::@1/(byte*) fill::screen#3 fill::@2/(byte*) fill::screen#2 )
  (byte) fill::j#2 ← phi( fill::@1/(byte) fill::j#0 fill::@2/(byte) fill::j#1 )
  (number~) fill::$0 ← (byte) fill::j#2 * (number) $28
  (byte*~) fill::$1 ← (byte*) fill::screen#2 + (number~) fill::$0
  *((byte*~) fill::$1 + (byte) fill::i#2) ← (byte) fill::ch#2
  (byte) fill::j#1 ← (byte) fill::j#2 + rangenext(0,2)
  (bool~) fill::$2 ← (byte) fill::j#1 != rangelast(0,2)
  unroll if((bool~) fill::$2) goto fill::@2
  to:fill::@3
fill::@3: scope:[fill]  from fill::@2
  (byte) fill::ch#5 ← phi( fill::@2/(byte) fill::ch#2 )
  (byte*) fill::screen#5 ← phi( fill::@2/(byte*) fill::screen#2 )
  (byte) fill::i#3 ← phi( fill::@2/(byte) fill::i#2 )
  (byte) fill::i#1 ← (byte) fill::i#3 + rangenext(0,$27)
  (bool~) fill::$3 ← (byte) fill::i#1 != rangelast(0,$27)
  if((bool~) fill::$3) goto fill::@1
  to:fill::@return
fill::@return: scope:[fill]  from fill::@3
  return 
  to:@return
@2: scope:[]  from @begin
  call main 
  to:@3
@3: scope:[]  from @2
  to:@end
@end: scope:[]  from @3

SYMBOL TABLE SSA
(label) @2
(label) @3
(label) @begin
(label) @end
(void()) fill((byte*) fill::screen , (byte) fill::ch)
(number~) fill::$0
(byte*~) fill::$1
(bool~) fill::$2
(bool~) fill::$3
(label) fill::@1
(label) fill::@2
(label) fill::@3
(label) fill::@return
(byte) fill::ch
(byte) fill::ch#0
(byte) fill::ch#1
(byte) fill::ch#2
(byte) fill::ch#3
(byte) fill::ch#4
(byte) fill::ch#5
(byte) fill::i
(byte) fill::i#0
(byte) fill::i#1
(byte) fill::i#2
(byte) fill::i#3
(byte) fill::i#4
(byte) fill::j
(byte) fill::j#0
(byte) fill::j#1
(byte) fill::j#2
(byte*) fill::screen
(byte*) fill::screen#0
(byte*) fill::screen#1
(byte*) fill::screen#2
(byte*) fill::screen#3
(byte*) fill::screen#4
(byte*) fill::screen#5
(void()) main()
(byte*~) main::$0
(byte*~) main::$2
(label) main::@1
(label) main::@2
(label) main::@return

Adding number conversion cast (unumber) $28 in (number~) fill::$0 ← (byte) fill::j#2 * (number) $28
Adding number conversion cast (unumber) fill::$0 in (number~) fill::$0 ← (byte) fill::j#2 * (unumber)(number) $28
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*~) main::$0 ← (byte*)(number) $400
Inlining cast (byte*~) main::$2 ← (byte*)(number) $2000
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant pointer cast (byte*) 8192
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) fill::$0 ← (byte) fill::j#2 * (byte) $28
Alias (byte*) fill::screen#0 = (byte*~) main::$0 
Alias (byte*) fill::screen#1 = (byte*~) main::$2 
Alias (byte) fill::i#2 = (byte) fill::i#3 
Alias (byte*) fill::screen#2 = (byte*) fill::screen#5 
Alias (byte) fill::ch#2 = (byte) fill::ch#5 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte*) fill::screen#2 (byte*) fill::screen#3
Identical Phi Values (byte) fill::ch#2 (byte) fill::ch#3
Identical Phi Values (byte) fill::i#2 (byte) fill::i#4
Successful SSA optimization Pass2IdenticalPhiElimination
Identical Phi Values (byte*) fill::screen#3 (byte*) fill::screen#4
Identical Phi Values (byte) fill::ch#3 (byte) fill::ch#4
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) fill::$2 [19] unroll if((byte) fill::j#1!=rangelast(0,2)) goto fill::@2
Simple Condition (bool~) fill::$3 [23] if((byte) fill::i#1!=rangelast(0,$27)) goto fill::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) fill::screen#0 = (byte*) 1024
Constant (const byte) fill::ch#0 = 'a'
Constant (const byte*) fill::screen#1 = (byte*) 8192
Constant (const byte) fill::ch#1 = 'b'
Constant (const byte) fill::i#0 = 0
Constant (const byte) fill::j#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [17] fill::j#1 ← ++ fill::j#2 to ++
Resolved ranged comparison value [19] unroll if(fill::j#1!=rangelast(0,2)) goto fill::@2 to (number) 3
Resolved ranged next value [21] fill::i#1 ← ++ fill::i#4 to ++
Resolved ranged comparison value [23] if(fill::i#1!=rangelast(0,$27)) goto fill::@1 to (number) $28
Adding number conversion cast (unumber) 3 in unroll if((byte) fill::j#1!=(number) 3) goto fill::@2
Adding number conversion cast (unumber) $28 in if((byte) fill::i#1!=(number) $28) goto fill::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 3
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 3
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Unrolling loop Loop head: fill::@2 tails: fill::@2 blocks: fill::@2 
Successful SSA optimization Pass2LoopUnroll
Identical Phi Values (byte) fill::j#2 (const byte) fill::j#0
Successful SSA optimization Pass2IdenticalPhiElimination
Negating conditional jump and destination [10] if((byte) fill::j#1==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConditionalJumpSequenceImprovement
Constant right-side identified [6] (byte~) fill::$0 ← (const byte) fill::j#0 * (byte) $28
Constant right-side identified [9] (byte) fill::j#1 ← ++ (const byte) fill::j#0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) fill::$0 = fill::j#0*$28
Constant (const byte) fill::j#1 = ++fill::j#0
Successful SSA optimization Pass2ConstantIdentification
if() condition always false - eliminating [10] if((const byte) fill::j#1==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConstantIfs
Simplifying constant evaluating to zero (const byte) fill::j#0*(byte) $28 in 
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero fill::screen#4 in [7] (byte*~) fill::$1 ← (byte*) fill::screen#4 + (const byte) fill::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) fill::$0
Successful SSA optimization PassNEliminateUnusedVars
Alias (byte*) fill::screen#4 = (byte*~) fill::$1 
Successful SSA optimization Pass2AliasElimination
Unrolling loop Loop head: fill::@2_1 tails: fill::@2_1 blocks: fill::@2_1 
Successful SSA optimization Pass2LoopUnroll
Identical Phi Values (byte) fill::j#3 (const byte) fill::j#1
Successful SSA optimization Pass2IdenticalPhiElimination
Negating conditional jump and destination [12] if((byte) fill::j#4==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConditionalJumpSequenceImprovement
Constant right-side identified [8] (byte~) fill::$4 ← (const byte) fill::j#1 * (byte) $28
Constant right-side identified [11] (byte) fill::j#4 ← ++ (const byte) fill::j#1
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) fill::$4 = fill::j#1*$28
Constant (const byte) fill::j#4 = ++fill::j#1
Successful SSA optimization Pass2ConstantIdentification
if() condition always false - eliminating [12] if((const byte) fill::j#4==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConstantIfs
Unrolling loop Loop head: fill::@2_2 tails: fill::@2_2 blocks: fill::@2_2 
Successful SSA optimization Pass2LoopUnroll
Identical Phi Values (byte) fill::j#5 (const byte) fill::j#4
Successful SSA optimization Pass2IdenticalPhiElimination
Negating conditional jump and destination [14] if((byte) fill::j#6==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConditionalJumpSequenceImprovement
Constant right-side identified [10] (byte~) fill::$6 ← (const byte) fill::j#4 * (byte) $28
Constant right-side identified [13] (byte) fill::j#6 ← ++ (const byte) fill::j#4
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) fill::$6 = fill::j#4*$28
Constant (const byte) fill::j#6 = ++fill::j#4
Successful SSA optimization Pass2ConstantIdentification
Removing PHI-reference to removed block (fill::@2_2) in block fill::@2_3
if() condition always true - replacing block destination [14] if((const byte) fill::j#6==(byte) 3) goto fill::@3
Successful SSA optimization Pass2ConstantIfs
Eliminating unused constant (const byte) fill::j#6
Successful SSA optimization PassNEliminateUnusedVars
Eliminating variable (byte) fill::j#7 from unused block fill::@2_3
Eliminating variable (byte~) fill::$8 from unused block fill::@2_3
Eliminating variable (byte*~) fill::$9 from unused block fill::@2_3
Eliminating variable (byte) fill::j#8 from unused block fill::@2_3
Removing unused block fill::@2_3
Successful SSA optimization Pass2EliminateUnusedBlocks
Inlining constant with var siblings (const byte*) fill::screen#0
Inlining constant with var siblings (const byte) fill::ch#0
Inlining constant with var siblings (const byte*) fill::screen#1
Inlining constant with var siblings (const byte) fill::ch#1
Inlining constant with var siblings (const byte) fill::i#0
Inlining constant with different constant siblings (const byte) fill::j#0
Inlining constant with different constant siblings (const byte) fill::j#1
Inlining constant with different constant siblings (const byte) fill::j#4
Constant inlined fill::j#4 = ++++(byte) 0
Constant inlined fill::ch#0 = (byte) 'a'
Constant inlined fill::screen#1 = (byte*) 8192
Constant inlined fill::screen#0 = (byte*) 1024
Constant inlined fill::i#0 = (byte) 0
Constant inlined fill::$6 = ++++(byte) 0*(byte) $28
Constant inlined fill::ch#1 = (byte) 'b'
Constant inlined fill::j#1 = ++(byte) 0
Constant inlined fill::$4 = ++(byte) 0*(byte) $28
Constant inlined fill::j#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Simplifying constant integer increment ++0
Simplifying constant integer increment ++0
Successful SSA optimization Pass2ConstantSimplification
Simplifying constant integer increment ++1
Successful SSA optimization Pass2ConstantSimplification
Added new block during phi lifting fill::@5(between fill::@3 and fill::@1)
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@1
Adding NOP phi() at start of main::@2
CALL GRAPH
Calls in [] to main:2 
Calls in [main] to fill:6 fill:8 

Created 3 initial phi equivalence classes
Coalesced [21] fill::i#5 ← fill::i#1
Coalesced down to 3 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@2
Culled Empty Block (label) fill::@5
Renumbering block @2 to @1
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
Adding NOP phi() at start of main::@1

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()
  [5] call fill 
  to:main::@1
main::@1: scope:[main]  from main
  [6] phi()
  [7] call fill 
  to:main::@return
main::@return: scope:[main]  from main::@1
  [8] return 
  to:@return
fill: scope:[fill]  from main main::@1
  [9] (byte) fill::ch#4 ← phi( main/(byte) 'a' main::@1/(byte) 'b' )
  [9] (byte*) fill::screen#4 ← phi( main/(byte*) 1024 main::@1/(byte*) 8192 )
  to:fill::@1
fill::@1: scope:[fill]  from fill fill::@3
  [10] (byte) fill::i#4 ← phi( fill/(byte) 0 fill::@3/(byte) fill::i#1 )
  to:fill::@2
fill::@2: scope:[fill]  from fill::@1
  [11] *((byte*) fill::screen#4 + (byte) fill::i#4) ← (byte) fill::ch#4
  to:fill::@2_1
fill::@2_1: scope:[fill]  from fill::@2
  [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28
  [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4
  to:fill::@2_2
fill::@2_2: scope:[fill]  from fill::@2_1
  [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28
  [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4
  to:fill::@3
fill::@3: scope:[fill]  from fill::@2_2
  [16] (byte) fill::i#1 ← ++ (byte) fill::i#4
  [17] if((byte) fill::i#1!=(byte) $28) goto fill::@1
  to:fill::@return
fill::@return: scope:[fill]  from fill::@3
  [18] return 
  to:@return


VARIABLE REGISTER WEIGHTS
(void()) fill((byte*) fill::screen , (byte) fill::ch)
(byte*~) fill::$5 22.0
(byte*~) fill::$7 22.0
(byte) fill::ch
(byte) fill::ch#4 3.666666666666667
(byte) fill::i
(byte) fill::i#1 16.5
(byte) fill::i#4 9.166666666666666
(byte) fill::j
(byte*) fill::screen
(byte*) fill::screen#4 3.666666666666667
(void()) main()

Initial phi equivalence classes
[ fill::screen#4 ]
[ fill::ch#4 ]
[ fill::i#4 fill::i#1 ]
Added variable fill::$5 to zero page equivalence class [ fill::$5 ]
Added variable fill::$7 to zero page equivalence class [ fill::$7 ]
Complete equivalence classes
[ fill::screen#4 ]
[ fill::ch#4 ]
[ fill::i#4 fill::i#1 ]
[ fill::$5 ]
[ fill::$7 ]
Allocated zp ZP_WORD:2 [ fill::screen#4 ]
Allocated zp ZP_BYTE:4 [ fill::ch#4 ]
Allocated zp ZP_BYTE:5 [ fill::i#4 fill::i#1 ]
Allocated zp ZP_WORD:6 [ fill::$5 ]
Allocated zp ZP_WORD:8 [ fill::$7 ]

INITIAL ASM
Target platform is c64basic
  // File Comments
// Tests elimination of plus 0
  // 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 
  // [4] phi from @1 to main [phi:@1->main]
main_from_b1:
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
  jmp bend
  // @end
bend:
  // main
main: {
    // [5] call fill 
    // [9] phi from main to fill [phi:main->fill]
  fill_from_main:
    // [9] phi (byte) fill::ch#4 = (byte) 'a' [phi:main->fill#0] -- vbuz1=vbuc1 
    lda #'a'
    sta.z fill.ch
    // [9] phi (byte*) fill::screen#4 = (byte*) 1024 [phi:main->fill#1] -- pbuz1=pbuc1 
    lda #<$400
    sta.z fill.screen
    lda #>$400
    sta.z fill.screen+1
    jsr fill
    // [6] phi from main to main::@1 [phi:main->main::@1]
  b1_from_main:
    jmp b1
    // main::@1
  b1:
    // [7] call fill 
    // [9] phi from main::@1 to fill [phi:main::@1->fill]
  fill_from_b1:
    // [9] phi (byte) fill::ch#4 = (byte) 'b' [phi:main::@1->fill#0] -- vbuz1=vbuc1 
    lda #'b'
    sta.z fill.ch
    // [9] phi (byte*) fill::screen#4 = (byte*) 8192 [phi:main::@1->fill#1] -- pbuz1=pbuc1 
    lda #<$2000
    sta.z fill.screen
    lda #>$2000
    sta.z fill.screen+1
    jsr fill
    jmp breturn
    // main::@return
  breturn:
    // [8] return 
    rts
}
  // fill
// fill(byte* zeropage(2) screen, byte zeropage(4) ch)
fill: {
    .label i = 5
    .label screen = 2
    .label ch = 4
    .label _5 = 6
    .label _7 = 8
    // [10] phi from fill to fill::@1 [phi:fill->fill::@1]
  b1_from_fill:
    // [10] phi (byte) fill::i#4 = (byte) 0 [phi:fill->fill::@1#0] -- vbuz1=vbuc1 
    lda #0
    sta.z i
    jmp b1
    // [10] phi from fill::@3 to fill::@1 [phi:fill::@3->fill::@1]
  b1_from_b3:
    // [10] phi (byte) fill::i#4 = (byte) fill::i#1 [phi:fill::@3->fill::@1#0] -- register_copy 
    jmp b1
    // fill::@1
  b1:
    jmp b2
    // fill::@2
  b2:
    // [11] *((byte*) fill::screen#4 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuz2=vbuz3 
    lda.z ch
    ldy.z i
    sta (screen),y
    jmp b2_1
    // fill::@2_1
  b2_1:
    // [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #1*$28
    clc
    adc.z screen
    sta.z _5
    lda #0
    adc.z screen+1
    sta.z _5+1
    // [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuz2=vbuz3 
    lda.z ch
    ldy.z i
    sta (_5),y
    jmp b2_2
    // fill::@2_2
  b2_2:
    // [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #2*$28
    clc
    adc.z screen
    sta.z _7
    lda #0
    adc.z screen+1
    sta.z _7+1
    // [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuz2=vbuz3 
    lda.z ch
    ldy.z i
    sta (_7),y
    jmp b3
    // fill::@3
  b3:
    // [16] (byte) fill::i#1 ← ++ (byte) fill::i#4 -- vbuz1=_inc_vbuz1 
    inc.z i
    // [17] if((byte) fill::i#1!=(byte) $28) goto fill::@1 -- vbuz1_neq_vbuc1_then_la1 
    lda #$28
    cmp.z i
    bne b1_from_b3
    jmp breturn
    // fill::@return
  breturn:
    // [18] return 
    rts
}
  // File Data

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] ) always clobbers reg byte a 
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ fill::ch#4 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ fill::i#4 fill::i#1 ]
Statement [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4 [ fill::screen#4 fill::ch#4 fill::i#4 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 ] ) always clobbers reg byte a 
Statement [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] ) always clobbers reg byte a 
Statement [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4 [ fill::screen#4 fill::ch#4 fill::i#4 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 ] ) always clobbers reg byte a 
Statement [11] *((byte*) fill::screen#4 + (byte) fill::i#4) ← (byte) fill::ch#4 [ fill::screen#4 fill::ch#4 fill::i#4 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 ] ) always clobbers reg byte a 
Statement [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$5 ] ) always clobbers reg byte a 
Statement [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4 [ fill::screen#4 fill::ch#4 fill::i#4 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 ] ) always clobbers reg byte a 
Statement [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 fill::$7 ] ) always clobbers reg byte a 
Statement [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4 [ fill::screen#4 fill::ch#4 fill::i#4 ] ( main:2::fill:5 [ fill::screen#4 fill::ch#4 fill::i#4 ] main:2::fill:7 [ fill::screen#4 fill::ch#4 fill::i#4 ] ) always clobbers reg byte a 
Potential registers zp ZP_WORD:2 [ fill::screen#4 ] : zp ZP_WORD:2 , 
Potential registers zp ZP_BYTE:4 [ fill::ch#4 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , 
Potential registers zp ZP_BYTE:5 [ fill::i#4 fill::i#1 ] : zp ZP_BYTE:5 , reg byte x , reg byte y , 
Potential registers zp ZP_WORD:6 [ fill::$5 ] : zp ZP_WORD:6 , 
Potential registers zp ZP_WORD:8 [ fill::$7 ] : zp ZP_WORD:8 , 

REGISTER UPLIFT SCOPES
Uplift Scope [fill] 25.67: zp ZP_BYTE:5 [ fill::i#4 fill::i#1 ] 22: zp ZP_WORD:6 [ fill::$5 ] 22: zp ZP_WORD:8 [ fill::$7 ] 3.67: zp ZP_WORD:2 [ fill::screen#4 ] 3.67: zp ZP_BYTE:4 [ fill::ch#4 ] 
Uplift Scope [main] 
Uplift Scope [] 

Uplifting [fill] best 961 combination reg byte y [ fill::i#4 fill::i#1 ] zp ZP_WORD:6 [ fill::$5 ] zp ZP_WORD:8 [ fill::$7 ] zp ZP_WORD:2 [ fill::screen#4 ] reg byte x [ fill::ch#4 ] 
Uplifting [main] best 961 combination 
Uplifting [] best 961 combination 
Allocated (was zp ZP_WORD:6) zp ZP_WORD:4 [ fill::$5 ]
Allocated (was zp ZP_WORD:8) zp ZP_WORD:6 [ fill::$7 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Tests elimination of plus 0
  // 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 
  // [4] phi from @1 to main [phi:@1->main]
main_from_b1:
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
  jmp bend
  // @end
bend:
  // main
main: {
    // [5] call fill 
    // [9] phi from main to fill [phi:main->fill]
  fill_from_main:
    // [9] phi (byte) fill::ch#4 = (byte) 'a' [phi:main->fill#0] -- vbuxx=vbuc1 
    ldx #'a'
    // [9] phi (byte*) fill::screen#4 = (byte*) 1024 [phi:main->fill#1] -- pbuz1=pbuc1 
    lda #<$400
    sta.z fill.screen
    lda #>$400
    sta.z fill.screen+1
    jsr fill
    // [6] phi from main to main::@1 [phi:main->main::@1]
  b1_from_main:
    jmp b1
    // main::@1
  b1:
    // [7] call fill 
    // [9] phi from main::@1 to fill [phi:main::@1->fill]
  fill_from_b1:
    // [9] phi (byte) fill::ch#4 = (byte) 'b' [phi:main::@1->fill#0] -- vbuxx=vbuc1 
    ldx #'b'
    // [9] phi (byte*) fill::screen#4 = (byte*) 8192 [phi:main::@1->fill#1] -- pbuz1=pbuc1 
    lda #<$2000
    sta.z fill.screen
    lda #>$2000
    sta.z fill.screen+1
    jsr fill
    jmp breturn
    // main::@return
  breturn:
    // [8] return 
    rts
}
  // fill
// fill(byte* zeropage(2) screen, byte register(X) ch)
fill: {
    .label screen = 2
    .label _5 = 4
    .label _7 = 6
    // [10] phi from fill to fill::@1 [phi:fill->fill::@1]
  b1_from_fill:
    // [10] phi (byte) fill::i#4 = (byte) 0 [phi:fill->fill::@1#0] -- vbuyy=vbuc1 
    ldy #0
    jmp b1
    // [10] phi from fill::@3 to fill::@1 [phi:fill::@3->fill::@1]
  b1_from_b3:
    // [10] phi (byte) fill::i#4 = (byte) fill::i#1 [phi:fill::@3->fill::@1#0] -- register_copy 
    jmp b1
    // fill::@1
  b1:
    jmp b2
    // fill::@2
  b2:
    // [11] *((byte*) fill::screen#4 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (screen),y
    jmp b2_1
    // fill::@2_1
  b2_1:
    // [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #1*$28
    clc
    adc.z screen
    sta.z _5
    lda #0
    adc.z screen+1
    sta.z _5+1
    // [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (_5),y
    jmp b2_2
    // fill::@2_2
  b2_2:
    // [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #2*$28
    clc
    adc.z screen
    sta.z _7
    lda #0
    adc.z screen+1
    sta.z _7+1
    // [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (_7),y
    jmp b3
    // fill::@3
  b3:
    // [16] (byte) fill::i#1 ← ++ (byte) fill::i#4 -- vbuyy=_inc_vbuyy 
    iny
    // [17] if((byte) fill::i#1!=(byte) $28) goto fill::@1 -- vbuyy_neq_vbuc1_then_la1 
    cpy #$28
    bne b1_from_b3
    jmp breturn
    // fill::@return
  breturn:
    // [18] return 
    rts
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp b2_1
Removing instruction jmp b2_2
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1 with b2
Replacing label b1_from_b3 with b2
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_main:
Removing instruction fill_from_b1:
Removing instruction b1_from_b3:
Removing instruction b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction fill_from_main:
Removing instruction b1:
Removing instruction breturn:
Removing instruction b1_from_fill:
Removing instruction b2_1:
Removing instruction b2_2:
Removing instruction b3:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp b2
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination

FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) fill((byte*) fill::screen , (byte) fill::ch)
(byte*~) fill::$5 $5 zp ZP_WORD:4 22.0
(byte*~) fill::$7 $7 zp ZP_WORD:6 22.0
(label) fill::@1
(label) fill::@2
(label) fill::@2_1
(label) fill::@2_2
(label) fill::@3
(label) fill::@return
(byte) fill::ch
(byte) fill::ch#4 reg byte x 3.666666666666667
(byte) fill::i
(byte) fill::i#1 reg byte y 16.5
(byte) fill::i#4 reg byte y 9.166666666666666
(byte) fill::j
(byte*) fill::screen
(byte*) fill::screen#4 screen zp ZP_WORD:2 3.666666666666667
(void()) main()
(label) main::@1
(label) main::@return

zp ZP_WORD:2 [ fill::screen#4 ]
reg byte x [ fill::ch#4 ]
reg byte y [ fill::i#4 fill::i#1 ]
zp ZP_WORD:4 [ fill::$5 ]
zp ZP_WORD:6 [ fill::$7 ]


FINAL ASSEMBLER
Score: 733

  // File Comments
// Tests elimination of plus 0
  // 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 
  // [4] phi from @1 to main [phi:@1->main]
  // [3] phi from @1 to @end [phi:@1->@end]
  // @end
  // main
main: {
    // fill((byte*)$400,'a')
    // [5] call fill 
    // [9] phi from main to fill [phi:main->fill]
    // [9] phi (byte) fill::ch#4 = (byte) 'a' [phi:main->fill#0] -- vbuxx=vbuc1 
    ldx #'a'
    // [9] phi (byte*) fill::screen#4 = (byte*) 1024 [phi:main->fill#1] -- pbuz1=pbuc1 
    lda #<$400
    sta.z fill.screen
    lda #>$400
    sta.z fill.screen+1
    jsr fill
    // [6] phi from main to main::@1 [phi:main->main::@1]
    // main::@1
    // fill((byte*)$2000,'b')
    // [7] call fill 
    // [9] phi from main::@1 to fill [phi:main::@1->fill]
    // [9] phi (byte) fill::ch#4 = (byte) 'b' [phi:main::@1->fill#0] -- vbuxx=vbuc1 
    ldx #'b'
    // [9] phi (byte*) fill::screen#4 = (byte*) 8192 [phi:main::@1->fill#1] -- pbuz1=pbuc1 
    lda #<$2000
    sta.z fill.screen
    lda #>$2000
    sta.z fill.screen+1
    jsr fill
    // main::@return
    // }
    // [8] return 
    rts
}
  // fill
// fill(byte* zeropage(2) screen, byte register(X) ch)
fill: {
    .label screen = 2
    .label _5 = 4
    .label _7 = 6
    // [10] phi from fill to fill::@1 [phi:fill->fill::@1]
    // [10] phi (byte) fill::i#4 = (byte) 0 [phi:fill->fill::@1#0] -- vbuyy=vbuc1 
    ldy #0
    // [10] phi from fill::@3 to fill::@1 [phi:fill::@3->fill::@1]
    // [10] phi (byte) fill::i#4 = (byte) fill::i#1 [phi:fill::@3->fill::@1#0] -- register_copy 
    // fill::@1
    // fill::@2
  b2:
    // (screen+j*40)[i] = ch
    // [11] *((byte*) fill::screen#4 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (screen),y
    // fill::@2_1
    // screen+j*40
    // [12] (byte*~) fill::$5 ← (byte*) fill::screen#4 + (byte) 1*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #1*$28
    clc
    adc.z screen
    sta.z _5
    lda #0
    adc.z screen+1
    sta.z _5+1
    // (screen+j*40)[i] = ch
    // [13] *((byte*~) fill::$5 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (_5),y
    // fill::@2_2
    // screen+j*40
    // [14] (byte*~) fill::$7 ← (byte*) fill::screen#4 + (byte) 2*(byte) $28 -- pbuz1=pbuz2_plus_vbuc1 
    lda #2*$28
    clc
    adc.z screen
    sta.z _7
    lda #0
    adc.z screen+1
    sta.z _7+1
    // (screen+j*40)[i] = ch
    // [15] *((byte*~) fill::$7 + (byte) fill::i#4) ← (byte) fill::ch#4 -- pbuz1_derefidx_vbuyy=vbuxx 
    txa
    sta (_7),y
    // fill::@3
    // for(byte i: 0..39)
    // [16] (byte) fill::i#1 ← ++ (byte) fill::i#4 -- vbuyy=_inc_vbuyy 
    iny
    // [17] if((byte) fill::i#1!=(byte) $28) goto fill::@1 -- vbuyy_neq_vbuc1_then_la1 
    cpy #$28
    bne b2
    // fill::@return
    // }
    // [18] return 
    rts
}
  // File Data

