Inlined call call __init

CONTROL FLOW GRAPH SSA

void main()
main: scope:[main]  from __start::@1
  idx#15 = phi( __start::@1/idx#16 )
  print::m#0 = msg1
  call print
  to:main::@1
main::@1: scope:[main]  from main
  idx#8 = phi( main/idx#4 )
  idx#0 = idx#8
  print::m#1 = msg2
  call print
  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 print(char *m)
print: scope:[print]  from main main::@1
  idx#11 = phi( main/idx#15, main::@1/idx#0 )
  print::m#2 = phi( main/print::m#0, main::@1/print::m#1 )
  print::$0 = print::m#2 + 2
  SCREEN[idx#11] = *print::$0
  idx#3 = ++ idx#11
  to:print::@return
print::@return: scope:[print]  from print
  idx#12 = phi( print/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()
__constant char msg1[] = { 'a', 'b', 'c', 'd' }
__constant char msg2[] = { '1', '2', '3', '4' }
void print(char *m)
char *print::$0
char *print::m
char *print::m#0
char *print::m#1
char *print::m#2

Adding number conversion cast (unumber) 2 in print::$0 = print::m#2 + 2
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 2
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
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 print::m#0 = msg1
Constant print::m#1 = msg2
Constant idx#16 = 0
Successful SSA optimization Pass2ConstantIdentification
Converting *(pointer+n) to pointer[n] [10] SCREEN[idx#11] = *print::$0  -- print::m#2[2]
Successful SSA optimization Pass2InlineDerefIdx
Eliminating unused variable print::$0 and assignment [4] print::$0 = print::m#2 + 2
Successful SSA optimization PassNEliminateUnusedVars
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 print::m#0
Inlining constant with var siblings print::m#1
Inlining constant with var siblings idx#16
Constant inlined print::m#1 = msg2
Constant inlined print::m#0 = msg1
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 print:1 print: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 print
  to:main::@1
main::@1: scope:[main]  from main
  [2] phi()
  [3] call print
  to:main::@return
main::@return: scope:[main]  from main::@1
  [4] return 
  to:@return

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


VARIABLE REGISTER WEIGHTS
char idx
char idx#11 // 12.0
char idx#12 // 3.25
void main()
void print(char *m)
char *print::m
char *print::m#2 // 11.0

Initial phi equivalence classes
[ print::m#2 ]
[ idx#11 idx#12 ]
Complete equivalence classes
[ print::m#2 ]
[ idx#11 idx#12 ]
Allocated zp[1]:2 [ idx#11 idx#12 ]
Allocated zp[2]:3 [ print::m#2 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] SCREEN[idx#11] = print::m#2[2] [ idx#11 ] ( print:1 [ idx#11 ] { }  print:3 [ idx#11 ] { { idx#11 = idx#12 } }  ) always clobbers reg byte a reg byte y 
Removing always clobbered register reg byte a as potential for zp[1]:2 [ idx#11 idx#12 ]
Removing always clobbered register reg byte y as potential for zp[1]:2 [ idx#11 idx#12 ]
Statement [6] SCREEN[idx#11] = print::m#2[2] [ idx#11 ] ( print:1 [ idx#11 ] { }  print:3 [ idx#11 ] { { idx#11 = idx#12 } }  ) always clobbers reg byte a reg byte y 
Potential registers zp[2]:3 [ print::m#2 ] : zp[2]:3 , 
Potential registers zp[1]:2 [ idx#11 idx#12 ] : zp[1]:2 , reg byte x , 

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

Uplifting [] best 69 combination reg byte x [ idx#11 idx#12 ] 
Uplifting [print] best 69 combination zp[2]:3 [ print::m#2 ] 
Uplifting [main] best 69 combination 
Allocated (was zp[2]:3) zp[2]:2 [ print::m#2 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Tests optimizing derefs of *(ptr+b) to ptr[b]
  // Upstart
  // Commodore 64 PRG executable file
.file [name="deref-to-derefidx.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 print
    // [5] phi from main to print [phi:main->print]
  print_from_main:
    // [5] phi idx#11 = 0 [phi:main->print#0] -- vbuxx=vbuc1 
    ldx #0
    // [5] phi print::m#2 = msg1 [phi:main->print#1] -- pbuz1=pbuc1 
    lda #<msg1
    sta.z print.m
    lda #>msg1
    sta.z print.m+1
    jsr print
    // [2] phi from main to main::@1 [phi:main->main::@1]
  __b1_from_main:
    jmp __b1
    // main::@1
  __b1:
    // [3] call print
    // [5] phi from main::@1 to print [phi:main::@1->print]
  print_from___b1:
    // [5] phi idx#11 = idx#12 [phi:main::@1->print#0] -- register_copy 
    // [5] phi print::m#2 = msg2 [phi:main::@1->print#1] -- pbuz1=pbuc1 
    lda #<msg2
    sta.z print.m
    lda #>msg2
    sta.z print.m+1
    jsr print
    jmp __breturn
    // main::@return
  __breturn:
    // [4] return 
    rts
}
  // print
// void print(__zp(2) char *m)
print: {
    .label m = 2
    // [6] SCREEN[idx#11] = print::m#2[2] -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuc2 
    ldy #2
    lda (m),y
    sta SCREEN,x
    // [7] idx#12 = ++ idx#11 -- vbuxx=_inc_vbuxx 
    inx
    jmp __breturn
    // print::@return
  __breturn:
    // [8] return 
    rts
}
  // File Data
.segment Data
  msg1: .byte 'a', 'b', 'c', 'd'
  msg2: .byte '1', '2', '3', '4'

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 print_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction print_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()
__constant char msg1[] = { 'a', 'b', 'c', 'd' }
__constant char msg2[] = { '1', '2', '3', '4' }
void print(char *m)
char *print::m
char *print::m#2 // m zp[2]:2 11.0

zp[2]:2 [ print::m#2 ]
reg byte x [ idx#11 idx#12 ]


FINAL ASSEMBLER
Score: 60

  // File Comments
// Tests optimizing derefs of *(ptr+b) to ptr[b]
  // Upstart
  // Commodore 64 PRG executable file
.file [name="deref-to-derefidx.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: {
    // print(msg1)
    // [1] call print
    // [5] phi from main to print [phi:main->print]
    // [5] phi idx#11 = 0 [phi:main->print#0] -- vbuxx=vbuc1 
    ldx #0
    // [5] phi print::m#2 = msg1 [phi:main->print#1] -- pbuz1=pbuc1 
    lda #<msg1
    sta.z print.m
    lda #>msg1
    sta.z print.m+1
    jsr print
    // [2] phi from main to main::@1 [phi:main->main::@1]
    // main::@1
    // print(msg2)
    // [3] call print
    // [5] phi from main::@1 to print [phi:main::@1->print]
    // [5] phi idx#11 = idx#12 [phi:main::@1->print#0] -- register_copy 
    // [5] phi print::m#2 = msg2 [phi:main::@1->print#1] -- pbuz1=pbuc1 
    lda #<msg2
    sta.z print.m
    lda #>msg2
    sta.z print.m+1
    jsr print
    // main::@return
    // }
    // [4] return 
    rts
}
  // print
// void print(__zp(2) char *m)
print: {
    .label m = 2
    // SCREEN[idx++] = *(m+2)
    // [6] SCREEN[idx#11] = print::m#2[2] -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuc2 
    ldy #2
    lda (m),y
    sta SCREEN,x
    // SCREEN[idx++] = *(m+2);
    // [7] idx#12 = ++ idx#11 -- vbuxx=_inc_vbuxx 
    inx
    // print::@return
    // }
    // [8] return 
    rts
}
  // File Data
.segment Data
  msg1: .byte 'a', 'b', 'c', 'd'
  msg2: .byte '1', '2', '3', '4'

