Inlined call call __init

CONTROL FLOW GRAPH SSA

void main()
main: scope:[main]  from __start::@1
  idx#15 = phi( __start::@1/idx#16 )
  out::c#0 = 'c'
  call out
  to:main::@1
main::@1: scope:[main]  from main
  idx#8 = phi( main/idx#4 )
  idx#0 = idx#8
  out::c#1 = 'm'
  call out
  to:main::@2
main::@2: scope:[main]  from main::@1
  idx#9 = phi( main::@1/idx#4 )
  idx#1 = idx#9
  to:main::@return
main::@return: scope:[main]  from main::@2
  idx#10 = phi( main::@2/idx#1 )
  idx#2 = idx#10
  return 
  to:@return

void out(char c)
out: scope:[out]  from main main::@1
  idx#11 = phi( main/idx#15, main::@1/idx#0 )
  out::c#2 = phi( main/out::c#0, main::@1/out::c#1 )
  SCREEN[idx#11] = out::c#2
  idx#3 = ++ idx#11
  to:out::@return
out::@return: scope:[out]  from out
  idx#12 = phi( out/idx#3 )
  idx#4 = idx#12
  return 
  to:@return

void __start()
__start: scope:[__start]  from
  to:__start::__init1
__start::__init1: scope:[__start]  from __start
  idx#5 = 0
  to:__start::@1
__start::@1: scope:[__start]  from __start::__init1
  idx#16 = phi( __start::__init1/idx#5 )
  call main
  to:__start::@2
__start::@2: scope:[__start]  from __start::@1
  idx#13 = phi( __start::@1/idx#2 )
  idx#6 = idx#13
  to:__start::@return
__start::@return: scope:[__start]  from __start::@2
  idx#14 = phi( __start::@2/idx#6 )
  idx#7 = idx#14
  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#2
char idx#3
char idx#4
char idx#5
char idx#6
char idx#7
char idx#8
char idx#9
void main()
void out(char c)
char out::c
char out::c#0
char out::c#1
char out::c#2

Simplifying constant pointer cast (char *) 1024
Successful SSA optimization PassNCastSimplification
Alias idx#0 = idx#8 
Alias idx#1 = idx#9 idx#10 idx#2 
Alias idx#12 = idx#3 idx#4 
Alias idx#16 = idx#5 
Alias idx#13 = idx#6 idx#14 idx#7 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values idx#15 idx#16
Identical Phi Values idx#0 idx#12
Identical Phi Values idx#1 idx#12
Identical Phi Values idx#13 idx#1
Successful SSA optimization Pass2IdenticalPhiElimination
Constant out::c#0 = 'c'
Constant out::c#1 = 'm'
Constant idx#16 = 0
Successful SSA optimization Pass2ConstantIdentification
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
Inlining constant with var siblings out::c#0
Inlining constant with var siblings out::c#1
Inlining constant with var siblings idx#16
Constant inlined out::c#0 = 'c'
Constant inlined out::c#1 = 'm'
Constant inlined idx#16 = 0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@2
CALL GRAPH
Calls in [main] to out:1 out:3 

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

FINAL CONTROL FLOW GRAPH

void main()
main: scope:[main]  from
  [0] phi()
  [1] call out
  to:main::@1
main::@1: scope:[main]  from main
  [2] phi()
  [3] call out
  to:main::@return
main::@return: scope:[main]  from main::@1
  [4] return 
  to:@return

void out(char c)
out: scope:[out]  from main main::@1
  [5] idx#11 = phi( main/0, main::@1/idx#12 )
  [5] out::c#2 = phi( main/'c', main::@1/'m' )
  [6] SCREEN[idx#11] = out::c#2
  [7] idx#12 = ++ idx#11
  to:out::@return
out::@return: scope:[out]  from out
  [8] return 
  to:@return


VARIABLE REGISTER WEIGHTS
char idx
char idx#11 // 12.0
char idx#12 // 3.25
void main()
void out(char c)
char out::c
char out::c#2 // 11.0

Initial phi equivalence classes
[ out::c#2 ]
[ idx#11 idx#12 ]
Complete equivalence classes
[ out::c#2 ]
[ idx#11 idx#12 ]
Allocated zp[1]:2 [ idx#11 idx#12 ]
Allocated zp[1]:3 [ out::c#2 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp[1]:3 [ out::c#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[1]:2 [ idx#11 idx#12 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , 

REGISTER UPLIFT SCOPES
Uplift Scope [] 15.25: zp[1]:2 [ idx#11 idx#12 ] 
Uplift Scope [out] 11: zp[1]:3 [ out::c#2 ] 
Uplift Scope [main] 

Uplifting [] best 55 combination reg byte x [ idx#11 idx#12 ] 
Uplifting [out] best 46 combination reg byte a [ out::c#2 ] 
Uplifting [main] best 46 combination 

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Test propagation of live ranges back over PHI-calls
// The idx-variable is alive between the two calls to out() - but not before the first call.
  // Upstart
  // Commodore 64 PRG executable file
.file [name="liverange-1.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] call out
    // [5] phi from main to out [phi:main->out]
  out_from_main:
    // [5] phi idx#11 = 0 [phi:main->out#0] -- vbuxx=vbuc1 
    ldx #0
    // [5] phi out::c#2 = 'c' [phi:main->out#1] -- vbuaa=vbuc1 
    lda #'c'
    jsr out
    // [2] phi from main to main::@1 [phi:main->main::@1]
  __b1_from_main:
    jmp __b1
    // main::@1
  __b1:
    // [3] call out
    // [5] phi from main::@1 to out [phi:main::@1->out]
  out_from___b1:
    // [5] phi idx#11 = idx#12 [phi:main::@1->out#0] -- register_copy 
    // [5] phi out::c#2 = 'm' [phi:main::@1->out#1] -- vbuaa=vbuc1 
    lda #'m'
    jsr out
    jmp __breturn
    // main::@return
  __breturn:
    // [4] return 
    rts
}
  // out
// void out(__register(A) char c)
out: {
    // [6] SCREEN[idx#11] = out::c#2 -- pbuc1_derefidx_vbuxx=vbuaa 
    sta SCREEN,x
    // [7] idx#12 = ++ idx#11 -- vbuxx=_inc_vbuxx 
    inx
    jmp __breturn
    // out::@return
  __breturn:
    // [8] return 
    rts
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1_from_main:
Removing instruction out_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction out_from_main:
Removing instruction __b1:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination

FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
char idx
char idx#11 // reg byte x 12.0
char idx#12 // reg byte x 3.25
void main()
void out(char c)
char out::c
char out::c#2 // reg byte a 11.0

reg byte a [ out::c#2 ]
reg byte x [ idx#11 idx#12 ]


FINAL ASSEMBLER
Score: 37

  // File Comments
// Test propagation of live ranges back over PHI-calls
// The idx-variable is alive between the two calls to out() - but not before the first call.
  // Upstart
  // Commodore 64 PRG executable file
.file [name="liverange-1.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: {
    // out('c')
    // [1] call out
    // [5] phi from main to out [phi:main->out]
    // [5] phi idx#11 = 0 [phi:main->out#0] -- vbuxx=vbuc1 
    ldx #0
    // [5] phi out::c#2 = 'c' [phi:main->out#1] -- vbuaa=vbuc1 
    lda #'c'
    jsr out
    // [2] phi from main to main::@1 [phi:main->main::@1]
    // main::@1
    // out('m')
    // [3] call out
    // [5] phi from main::@1 to out [phi:main::@1->out]
    // [5] phi idx#11 = idx#12 [phi:main::@1->out#0] -- register_copy 
    // [5] phi out::c#2 = 'm' [phi:main::@1->out#1] -- vbuaa=vbuc1 
    lda #'m'
    jsr out
    // main::@return
    // }
    // [4] return 
    rts
}
  // out
// void out(__register(A) char c)
out: {
    // SCREEN[idx++] = c
    // [6] SCREEN[idx#11] = out::c#2 -- pbuc1_derefidx_vbuxx=vbuaa 
    sta SCREEN,x
    // SCREEN[idx++] = c;
    // [7] idx#12 = ++ idx#11 -- vbuxx=_inc_vbuxx 
    inx
    // out::@return
    // }
    // [8] return 
    rts
}
  // File Data

