Inlined call call __init

CONTROL FLOW GRAPH SSA

void main()
main: scope:[main]  from __start::@1
  idx#22 = phi( __start::@1/idx#21 )
  main::c#0 = 0
  to:main::@1
main::@1: scope:[main]  from main main::@2
  idx#19 = phi( main/idx#22, main::@2/idx#0 )
  main::c#2 = phi( main/main::c#0, main::@2/main::c#1 )
  out2::c#0 = main::c#2
  call out2
  to:main::@2
main::@2: scope:[main]  from main::@1
  main::c#3 = phi( main::@1/main::c#2 )
  idx#10 = phi( main::@1/idx#4 )
  idx#0 = idx#10
  main::c#1 = main::c#3 + rangenext(0,$27)
  main::$1 = main::c#1 != rangelast(0,$27)
  if(main::$1) goto main::@1
  to:main::@return
main::@return: scope:[main]  from main::@2
  idx#11 = phi( main::@2/idx#0 )
  idx#1 = idx#11
  return 
  to:@return

void out2(char c)
out2: scope:[out2]  from main::@1
  idx#20 = phi( main::@1/idx#19 )
  out2::c#1 = phi( main::@1/out2::c#0 )
  out::c#0 = out2::c#1
  call out
  to:out2::@1
out2::@1: scope:[out2]  from out2
  out2::c#2 = phi( out2/out2::c#1 )
  idx#12 = phi( out2/idx#6 )
  idx#2 = idx#12
  out::c#1 = out2::c#2
  call out
  to:out2::@2
out2::@2: scope:[out2]  from out2::@1
  idx#13 = phi( out2::@1/idx#6 )
  idx#3 = idx#13
  to:out2::@return
out2::@return: scope:[out2]  from out2::@2
  idx#14 = phi( out2::@2/idx#3 )
  idx#4 = idx#14
  return 
  to:@return

void out(char c)
out: scope:[out]  from out2 out2::@1
  out::c#2 = phi( out2/out::c#0, out2::@1/out::c#1 )
  idx#15 = phi( out2/idx#20, out2::@1/idx#2 )
  idx#5 = ++ idx#15
  SCREEN[idx#5] = out::c#2
  to:out::@return
out::@return: scope:[out]  from out
  idx#16 = phi( out/idx#5 )
  idx#6 = idx#16
  return 
  to:@return

void __start()
__start: scope:[__start]  from
  to:__start::__init1
__start::__init1: scope:[__start]  from __start
  idx#7 = 0
  to:__start::@1
__start::@1: scope:[__start]  from __start::__init1
  idx#21 = phi( __start::__init1/idx#7 )
  call main
  to:__start::@2
__start::@2: scope:[__start]  from __start::@1
  idx#17 = phi( __start::@1/idx#1 )
  idx#8 = idx#17
  to:__start::@return
__start::@return: scope:[__start]  from __start::@2
  idx#18 = phi( __start::@2/idx#8 )
  idx#9 = idx#18
  return 
  to:@return

SYMBOL TABLE SSA
__constant char * const SCREEN = (char *)$400
void __start()
char idx
char idx#0
char idx#1
char idx#10
char idx#11
char idx#12
char idx#13
char idx#14
char idx#15
char idx#16
char idx#17
char idx#18
char idx#19
char idx#2
char idx#20
char idx#21
char idx#22
char idx#3
char idx#4
char idx#5
char idx#6
char idx#7
char idx#8
char idx#9
void main()
bool main::$1
char main::c
char main::c#0
char main::c#1
char main::c#2
char main::c#3
void out(char c)
char out::c
char out::c#0
char out::c#1
char out::c#2
void out2(char c)
char out2::c
char out2::c#0
char out2::c#1
char out2::c#2

Simplifying constant pointer cast (char *) 1024
Successful SSA optimization PassNCastSimplification
Alias main::c#2 = main::c#3 
Alias idx#0 = idx#10 idx#11 idx#1 
Alias out2::c#1 = out2::c#2 
Alias idx#12 = idx#2 
Alias idx#13 = idx#3 idx#14 idx#4 
Alias idx#16 = idx#5 idx#6 
Alias idx#21 = idx#7 
Alias idx#17 = idx#8 idx#18 idx#9 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values idx#22 idx#21
Identical Phi Values idx#0 idx#13
Identical Phi Values out2::c#1 out2::c#0
Identical Phi Values idx#20 idx#19
Identical Phi Values idx#12 idx#16
Identical Phi Values idx#13 idx#16
Identical Phi Values idx#17 idx#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition main::$1 [8] if(main::c#1!=rangelast(0,$27)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant main::c#0 = 0
Constant idx#21 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [6] main::c#1 = ++ main::c#2 to ++
Resolved ranged comparison value [8] if(main::c#1!=rangelast(0,$27)) goto main::@1 to $28
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) $28 in [4] if(main::c#1!=$28) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining constant with var siblings main::c#0
Inlining constant with var siblings idx#21
Constant inlined idx#21 = 0
Constant inlined main::c#0 = 0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@2 and main::@1)
Adding NOP phi() at start of main
Adding NOP phi() at start of out2::@2
CALL GRAPH
Calls in [main] to out2:3 
Calls in [out2] to out:12 out:16 

Created 4 initial phi equivalence classes
Coalesced [7] main::c#4 = main::c#1
Coalesced [8] idx#23 = idx#16
Coalesced [10] idx#24 = idx#19
Coalesced [11] out::c#3 = out::c#0
Coalesced (already) [14] idx#25 = idx#16
Coalesced [15] out::c#4 = out::c#1
Coalesced down to 3 phi equivalence classes
Culled Empty Block label main::@3
Culled Empty Block label out2::@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::@2
  [1] idx#19 = phi( main/0, main::@2/idx#16 )
  [1] main::c#2 = phi( main/0, main::@2/main::c#1 )
  [2] out2::c#0 = main::c#2
  [3] call out2
  to:main::@2
main::@2: scope:[main]  from main::@1
  [4] main::c#1 = ++ main::c#2
  [5] if(main::c#1!=$28) goto main::@1
  to:main::@return
main::@return: scope:[main]  from main::@2
  [6] return 
  to:@return

void out2(char c)
out2: scope:[out2]  from main::@1
  [7] out::c#0 = out2::c#0
  [8] call out
  to:out2::@1
out2::@1: scope:[out2]  from out2
  [9] out::c#1 = out2::c#0
  [10] call out
  to:out2::@return
out2::@return: scope:[out2]  from out2::@1
  [11] return 
  to:@return

void out(char c)
out: scope:[out]  from out2 out2::@1
  [12] out::c#2 = phi( out2/out::c#0, out2::@1/out::c#1 )
  [12] idx#15 = phi( out2/idx#19, out2::@1/idx#16 )
  [13] idx#16 = ++ idx#15
  [14] SCREEN[idx#16] = out::c#2
  to:out::@return
out::@return: scope:[out]  from out
  [15] return 
  to:@return


VARIABLE REGISTER WEIGHTS
char idx
char idx#15 // 1203.0
char idx#16 // 211.39999999999998
char idx#19 // 37.33333333333333
void main()
char main::c
char main::c#1 // 16.5
char main::c#2 // 11.0
void out(char c)
char out::c
char out::c#0 // 202.0
char out::c#1 // 202.0
char out::c#2 // 601.5
void out2(char c)
char out2::c
char out2::c#0 // 71.0

Initial phi equivalence classes
[ main::c#2 main::c#1 ]
[ idx#15 idx#19 idx#16 ]
[ out::c#2 out::c#0 out::c#1 ]
Added variable out2::c#0 to live range equivalence class [ out2::c#0 ]
Complete equivalence classes
[ main::c#2 main::c#1 ]
[ idx#15 idx#19 idx#16 ]
[ out::c#2 out::c#0 out::c#1 ]
[ out2::c#0 ]
Allocated zp[1]:2 [ idx#15 idx#19 idx#16 ]
Allocated zp[1]:3 [ out::c#2 out::c#0 out::c#1 ]
Allocated zp[1]:4 [ out2::c#0 ]
Allocated zp[1]:5 [ main::c#2 main::c#1 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp[1]:5 [ main::c#2 main::c#1 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[1]:2 [ idx#15 idx#19 idx#16 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[1]:3 [ out::c#2 out::c#0 out::c#1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[1]:4 [ out2::c#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , 

REGISTER UPLIFT SCOPES
Uplift Scope [] 1,451.73: zp[1]:2 [ idx#15 idx#19 idx#16 ] 
Uplift Scope [out] 1,005.5: zp[1]:3 [ out::c#2 out::c#0 out::c#1 ] 
Uplift Scope [out2] 71: zp[1]:4 [ out2::c#0 ] 
Uplift Scope [main] 27.5: zp[1]:5 [ main::c#2 main::c#1 ] 

Uplifting [] best 496 combination reg byte x [ idx#15 idx#19 idx#16 ] 
Uplifting [out] best 487 combination reg byte a [ out::c#2 out::c#0 out::c#1 ] 
Uplifting [out2] best 451 combination reg byte a [ out2::c#0 ] 
Uplifting [main] best 351 combination reg byte a [ main::c#2 main::c#1 ] 

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Test effective live range and register allocation
// Here main::c, out2::c and out::c can all have the same allocation - and the global idx can be allocated to a hardware register.
  // Upstart
  // Commodore 64 PRG executable file
.file [name="liverange-8.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
  .label SCREEN = $400
.segment Code
  // main
main: {
    // [1] phi from main to main::@1 [phi:main->main::@1]
  __b1_from_main:
    // [1] phi idx#19 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 
    ldx #0
    // [1] phi main::c#2 = 0 [phi:main->main::@1#1] -- vbuaa=vbuc1 
    lda #0
    jmp __b1
    // [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
  __b1_from___b2:
    // [1] phi idx#19 = idx#16 [phi:main::@2->main::@1#0] -- register_copy 
    // [1] phi main::c#2 = main::c#1 [phi:main::@2->main::@1#1] -- register_copy 
    jmp __b1
    // main::@1
  __b1:
    // [2] out2::c#0 = main::c#2
    // [3] call out2
    jsr out2
    jmp __b2
    // main::@2
  __b2:
    // [4] main::c#1 = ++ main::c#2 -- vbuaa=_inc_vbuaa 
    clc
    adc #1
    // [5] if(main::c#1!=$28) goto main::@1 -- vbuaa_neq_vbuc1_then_la1 
    cmp #$28
    bne __b1_from___b2
    jmp __breturn
    // main::@return
  __breturn:
    // [6] return 
    rts
}
  // out2
// void out2(__register(A) char c)
out2: {
    // [7] out::c#0 = out2::c#0
    // [8] call out
    // [12] phi from out2 to out [phi:out2->out]
  out_from_out2:
    // [12] phi out::c#2 = out::c#0 [phi:out2->out#0] -- register_copy 
    // [12] phi idx#15 = idx#19 [phi:out2->out#1] -- register_copy 
    jsr out
    jmp __b1
    // out2::@1
  __b1:
    // [9] out::c#1 = out2::c#0
    // [10] call out
    // [12] phi from out2::@1 to out [phi:out2::@1->out]
  out_from___b1:
    // [12] phi out::c#2 = out::c#1 [phi:out2::@1->out#0] -- register_copy 
    // [12] phi idx#15 = idx#16 [phi:out2::@1->out#1] -- register_copy 
    jsr out
    jmp __breturn
    // out2::@return
  __breturn:
    // [11] return 
    rts
}
  // out
// void out(__register(A) char c)
out: {
    // [13] idx#16 = ++ idx#15 -- vbuxx=_inc_vbuxx 
    inx
    // [14] SCREEN[idx#16] = out::c#2 -- pbuc1_derefidx_vbuxx=vbuaa 
    sta SCREEN,x
    jmp __breturn
    // out::@return
  __breturn:
    // [15] return 
    rts
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing instruction lda #0 with TXA
Replacing label __b1_from___b2 with __b1
Removing instruction __b1_from___b2:
Removing instruction out_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1_from_main:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction out_from_out2:
Removing instruction __b1:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination

FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
char idx
char idx#15 // reg byte x 1203.0
char idx#16 // reg byte x 211.39999999999998
char idx#19 // reg byte x 37.33333333333333
void main()
char main::c
char main::c#1 // reg byte a 16.5
char main::c#2 // reg byte a 11.0
void out(char c)
char out::c
char out::c#0 // reg byte a 202.0
char out::c#1 // reg byte a 202.0
char out::c#2 // reg byte a 601.5
void out2(char c)
char out2::c
char out2::c#0 // reg byte a 71.0

reg byte a [ main::c#2 main::c#1 ]
reg byte x [ idx#15 idx#19 idx#16 ]
reg byte a [ out::c#2 out::c#0 out::c#1 ]
reg byte a [ out2::c#0 ]


FINAL ASSEMBLER
Score: 222

  // File Comments
// Test effective live range and register allocation
// Here main::c, out2::c and out::c can all have the same allocation - and the global idx can be allocated to a hardware register.
  // Upstart
  // Commodore 64 PRG executable file
.file [name="liverange-8.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
  .label SCREEN = $400
.segment Code
  // main
main: {
    // [1] phi from main to main::@1 [phi:main->main::@1]
    // [1] phi idx#19 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 
    ldx #0
    // [1] phi main::c#2 = 0 [phi:main->main::@1#1] -- vbuaa=vbuc1 
    txa
    // [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
    // [1] phi idx#19 = idx#16 [phi:main::@2->main::@1#0] -- register_copy 
    // [1] phi main::c#2 = main::c#1 [phi:main::@2->main::@1#1] -- register_copy 
    // main::@1
  __b1:
    // out2(c)
    // [2] out2::c#0 = main::c#2
    // [3] call out2
    jsr out2
    // main::@2
    // for(char c: 0..39 )
    // [4] main::c#1 = ++ main::c#2 -- vbuaa=_inc_vbuaa 
    clc
    adc #1
    // [5] if(main::c#1!=$28) goto main::@1 -- vbuaa_neq_vbuc1_then_la1 
    cmp #$28
    bne __b1
    // main::@return
    // }
    // [6] return 
    rts
}
  // out2
// void out2(__register(A) char c)
out2: {
    // out(c)
    // [7] out::c#0 = out2::c#0
    // [8] call out
    // [12] phi from out2 to out [phi:out2->out]
    // [12] phi out::c#2 = out::c#0 [phi:out2->out#0] -- register_copy 
    // [12] phi idx#15 = idx#19 [phi:out2->out#1] -- register_copy 
    jsr out
    // out2::@1
    // out(c)
    // [9] out::c#1 = out2::c#0
    // [10] call out
    // [12] phi from out2::@1 to out [phi:out2::@1->out]
    // [12] phi out::c#2 = out::c#1 [phi:out2::@1->out#0] -- register_copy 
    // [12] phi idx#15 = idx#16 [phi:out2::@1->out#1] -- register_copy 
    jsr out
    // out2::@return
    // }
    // [11] return 
    rts
}
  // out
// void out(__register(A) char c)
out: {
    // idx++;
    // [13] idx#16 = ++ idx#15 -- vbuxx=_inc_vbuxx 
    inx
    // SCREEN[idx] = c
    // [14] SCREEN[idx#16] = out::c#2 -- pbuc1_derefidx_vbuxx=vbuaa 
    sta SCREEN,x
    // out::@return
    // }
    // [15] return 
    rts
}
  // File Data

