Setting inferred volatile on symbol affected by address-of (signed word*~) main::$0 ← & (signed word) main::y1
Setting inferred volatile on symbol affected by address-of (signed word*~) main::$2 ← & (signed word) main::y2
Fixing pointer increment (signed word*) main::SCREEN ← ++ (signed word*) main::SCREEN
Fixing pointer increment (signed word*) main::SCREEN ← ++ (signed word*) main::SCREEN
Fixing pointer array-indexing *((signed word[4]) wow + (byte) foo::x)
Culled Empty Block (label) foo::@1
Culled Empty Block (label) @1

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  (signed word[4]) wow#0 ← { (number) $cafe, (number) $babe, (number) $1234, (number) $5678 }
  to:@2
foo: scope:[foo]  from main main::@1
  (signed word*) foo::y#2 ← phi( main/(signed word*) foo::y#0 main::@1/(signed word*) foo::y#1 )
  (byte) foo::x#2 ← phi( main/(byte) foo::x#0 main::@1/(byte) foo::x#1 )
  (byte~) foo::$1 ← (byte) foo::x#2 * (const byte) SIZEOF_SIGNED_WORD
  (signed word~) foo::$0 ← *((signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2)
  (signed word) foo::return#0 ← (signed word~) foo::$0
  to:foo::@return
foo::@return: scope:[foo]  from foo
  (signed word) foo::return#4 ← phi( foo/(signed word) foo::return#0 )
  (signed word) foo::return#1 ← (signed word) foo::return#4
  return 
  to:@return
main: scope:[main]  from @2
  (signed word*) main::SCREEN#0 ← ((signed word*)) (number) $400
  (signed word) main::y1#0 ← (number) $1234
  (signed word) main::y2#0 ← (number) $1234
  (signed word*~) main::$0 ← & (signed word) main::y1#0
  (byte) foo::x#0 ← (number) 1
  (signed word*) foo::y#0 ← (signed word*~) main::$0
  call foo 
  (signed word) foo::return#2 ← (signed word) foo::return#1
  to:main::@1
main::@1: scope:[main]  from main
  (signed word) main::y2#1 ← phi( main/(signed word) main::y2#0 )
  (signed word*) main::SCREEN#3 ← phi( main/(signed word*) main::SCREEN#0 )
  (signed word) foo::return#5 ← phi( main/(signed word) foo::return#2 )
  (signed word~) main::$1 ← (signed word) foo::return#5
  *((signed word*) main::SCREEN#3) ← (signed word~) main::$1
  (signed word*) main::SCREEN#1 ← (signed word*) main::SCREEN#3 + (const byte) SIZEOF_SIGNED_WORD
  (signed word*~) main::$2 ← & (signed word) main::y2#1
  (byte) foo::x#1 ← (number) 2
  (signed word*) foo::y#1 ← (signed word*~) main::$2
  call foo 
  (signed word) foo::return#3 ← (signed word) foo::return#1
  to:main::@2
main::@2: scope:[main]  from main::@1
  (signed word*) main::SCREEN#4 ← phi( main::@1/(signed word*) main::SCREEN#1 )
  (signed word) foo::return#6 ← phi( main::@1/(signed word) foo::return#3 )
  (signed word~) main::$3 ← (signed word) foo::return#6
  *((signed word*) main::SCREEN#4) ← (signed word~) main::$3
  (signed word*) main::SCREEN#2 ← (signed word*) main::SCREEN#4 + (const byte) SIZEOF_SIGNED_WORD
  to:main::@return
main::@return: scope:[main]  from main::@2
  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
(const byte) SIZEOF_SIGNED_WORD = (byte) 2
(signed word()) foo((byte) foo::x , (signed word*) foo::y)
(signed word~) foo::$0
(byte~) foo::$1
(label) foo::@return
(signed word) foo::return
(signed word) foo::return#0
(signed word) foo::return#1
(signed word) foo::return#2
(signed word) foo::return#3
(signed word) foo::return#4
(signed word) foo::return#5
(signed word) foo::return#6
(byte) foo::x
(byte) foo::x#0
(byte) foo::x#1
(byte) foo::x#2
(signed word*) foo::y
(signed word*) foo::y#0
(signed word*) foo::y#1
(signed word*) foo::y#2
(void()) main()
(signed word*~) main::$0
(signed word~) main::$1
(signed word*~) main::$2
(signed word~) main::$3
(label) main::@1
(label) main::@2
(label) main::@return
(signed word*) main::SCREEN
(signed word*) main::SCREEN#0
(signed word*) main::SCREEN#1
(signed word*) main::SCREEN#2
(signed word*) main::SCREEN#3
(signed word*) main::SCREEN#4
(signed word) main::y1
(signed word) main::y1#0
(signed word) main::y2
(signed word) main::y2#0
(signed word) main::y2#1
(signed word[4]) wow
(signed word[4]) wow#0

Adding number conversion cast (snumber) $1234 in (signed word) main::y1#0 ← (number) $1234
Adding number conversion cast (snumber) $1234 in (signed word) main::y2#0 ← (number) $1234
Adding number conversion cast (unumber) 1 in (byte) foo::x#0 ← (number) 1
Adding number conversion cast (unumber) 2 in (byte) foo::x#1 ← (number) 2
Successful SSA optimization PassNAddNumberTypeConversions
Added casts to value list in (signed word[4]) wow#0 ← (signed word[4]){ (signed word)(number) $cafe, (signed word)(number) $babe, (signed word)(number) $1234, (signed word)(number) $5678 }
Successful SSA optimization PassNAddInitializerValueListTypeCasts
Inlining cast (signed word*) main::SCREEN#0 ← (signed word*)(number) $400
Inlining cast (signed word) main::y1#0 ← (snumber)(number) $1234
Inlining cast (signed word) main::y2#0 ← (snumber)(number) $1234
Inlining cast (byte) foo::x#0 ← (unumber)(number) 1
Inlining cast (byte) foo::x#1 ← (unumber)(number) 2
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast $cafe
Simplifying constant integer cast $babe
Simplifying constant integer cast $1234
Simplifying constant integer cast $5678
Simplifying constant pointer cast (signed word*) 1024
Simplifying constant integer cast $1234
Simplifying constant integer cast $1234
Simplifying constant integer cast 1
Simplifying constant integer cast 2
Successful SSA optimization PassNCastSimplification
Finalized signed number type (signed word) $1234
Finalized signed number type (signed word) $1234
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (signed word) foo::return#0 = (signed word~) foo::$0 (signed word) foo::return#4 (signed word) foo::return#1 
Alias (signed word*) foo::y#0 = (signed word*~) main::$0 
Alias (signed word) foo::return#2 = (signed word) foo::return#5 
Alias (signed word*) main::SCREEN#0 = (signed word*) main::SCREEN#3 
Alias (signed word) main::y2#0 = (signed word) main::y2#1 
Alias (signed word*) foo::y#1 = (signed word*~) main::$2 
Alias (signed word) foo::return#3 = (signed word) foo::return#6 
Alias (signed word*) main::SCREEN#1 = (signed word*) main::SCREEN#4 
Successful SSA optimization Pass2AliasElimination
Constant right-side identified [11] (signed word*) foo::y#0 ← & (signed word) main::y1#0
Constant right-side identified [20] (signed word*) foo::y#1 ← & (signed word) main::y2#0
Successful SSA optimization Pass2ConstantRValueConsolidation
Identified constant from value list (signed word[4]) { (signed word) $cafe, (signed word) $babe, (signed word) $1234, (signed word) $5678 }
Successful SSA optimization Pass2ConstantInitializerValueLists
Constant (const signed word[4]) wow#0 = { $cafe, $babe, $1234, $5678 }
Constant (const signed word*) main::SCREEN#0 = (signed word*) 1024
Constant (const signed word*) foo::y#0 = &main::y1#0
Constant (const byte) foo::x#0 = 1
Constant (const signed word*) foo::y#1 = &main::y2#0
Constant (const byte) foo::x#1 = 2
Successful SSA optimization Pass2ConstantIdentification
Converting *(pointer+n) to pointer[n] [27] *((signed word*) main::SCREEN#1) ← (signed word~) main::$3  -- *(main::SCREEN#0 + SIZEOF_SIGNED_WORD)
Successful SSA optimization Pass2InlineDerefIdx
Eliminating unused variable (signed word*) main::SCREEN#2 and assignment [15] (signed word*) main::SCREEN#2 ← (signed word*) main::SCREEN#1 + (const byte) SIZEOF_SIGNED_WORD
Successful SSA optimization PassNEliminateUnusedVars
Eliminating unused variable (signed word*) main::SCREEN#1 and assignment [10] (signed word*) main::SCREEN#1 ← (const signed word*) main::SCREEN#0 + (const byte) SIZEOF_SIGNED_WORD
Successful SSA optimization PassNEliminateUnusedVars
Rewriting multiplication to use shift [1] (byte~) foo::$1 ← (byte) foo::x#2 * (const byte) SIZEOF_SIGNED_WORD
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings (const signed word*) foo::y#0
Inlining constant with var siblings (const byte) foo::x#0
Inlining constant with var siblings (const signed word*) foo::y#1
Inlining constant with var siblings (const byte) foo::x#1
Constant inlined foo::y#0 = &(signed word) main::y1#0
Constant inlined foo::x#1 = (byte) 2
Constant inlined foo::y#1 = &(signed word) main::y2#0
Constant inlined foo::x#0 = (byte) 1
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::SCREEN#0+SIZEOF_SIGNED_WORD)
Successful SSA optimization Pass2ConstantAdditionElimination
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
CALL GRAPH
Calls in [] to main:2 
Calls in [main] to foo:7 foo:11 

Created 2 initial phi equivalence classes
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @3
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

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] (signed word) main::y1#0 ← (signed word) $1234
  [5] (signed word) main::y2#0 ← (signed word) $1234
  [6] call foo 
  [7] (signed word) foo::return#2 ← (signed word) foo::return#0
  to:main::@1
main::@1: scope:[main]  from main
  [8] (signed word~) main::$1 ← (signed word) foo::return#2
  [9] *((const signed word*) main::SCREEN#0) ← (signed word~) main::$1
  [10] call foo 
  [11] (signed word) foo::return#3 ← (signed word) foo::return#0
  to:main::@2
main::@2: scope:[main]  from main::@1
  [12] (signed word~) main::$3 ← (signed word) foo::return#3
  [13] *((const signed word*) main::SCREEN#0+(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$3
  to:main::@return
main::@return: scope:[main]  from main::@2
  [14] return 
  to:@return
foo: scope:[foo]  from main main::@1
  [15] (signed word*) foo::y#2 ← phi( main/&(signed word) main::y1#0 main::@1/&(signed word) main::y2#0 )
  [15] (byte) foo::x#2 ← phi( main/(byte) 1 main::@1/(byte) 2 )
  [16] (byte~) foo::$1 ← (byte) foo::x#2 << (byte) 1
  [17] (signed word) foo::return#0 ← *((const signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2)
  to:foo::@return
foo::@return: scope:[foo]  from foo
  [18] return 
  to:@return


VARIABLE REGISTER WEIGHTS
(signed word()) foo((byte) foo::x , (signed word*) foo::y)
(byte~) foo::$1 4.0
(signed word) foo::return
(signed word) foo::return#0 1.5
(signed word) foo::return#2 4.0
(signed word) foo::return#3 4.0
(byte) foo::x
(byte) foo::x#2 2.0
(signed word*) foo::y
(signed word*) foo::y#2 1.0
(void()) main()
(signed word~) main::$1 4.0
(signed word~) main::$3 4.0
(signed word*) main::SCREEN
(signed word) main::y1
(signed word) main::y1#0 20.0
(signed word) main::y2
(signed word) main::y2#0 20.0
(signed word[4]) wow

Initial phi equivalence classes
[ foo::x#2 ]
[ foo::y#2 ]
Added variable foo::return#2 to zero page equivalence class [ foo::return#2 ]
Added variable main::$1 to zero page equivalence class [ main::$1 ]
Added variable foo::return#3 to zero page equivalence class [ foo::return#3 ]
Added variable main::$3 to zero page equivalence class [ main::$3 ]
Added variable foo::$1 to zero page equivalence class [ foo::$1 ]
Added variable foo::return#0 to zero page equivalence class [ foo::return#0 ]
Complete equivalence classes
[ foo::x#2 ]
[ foo::y#2 ]
[ main::y1#0 ]
[ main::y2#0 ]
[ foo::return#2 ]
[ main::$1 ]
[ foo::return#3 ]
[ main::$3 ]
[ foo::$1 ]
[ foo::return#0 ]
Allocated zp ZP_BYTE:2 [ foo::x#2 ]
Allocated zp ZP_WORD:3 [ foo::y#2 ]
Allocated zp ZP_WORD:5 [ main::y1#0 ]
Allocated zp ZP_WORD:7 [ main::y2#0 ]
Allocated zp ZP_WORD:9 [ foo::return#2 ]
Allocated zp ZP_WORD:11 [ main::$1 ]
Allocated zp ZP_WORD:13 [ foo::return#3 ]
Allocated zp ZP_WORD:15 [ main::$3 ]
Allocated zp ZP_BYTE:17 [ foo::$1 ]
Allocated zp ZP_WORD:18 [ foo::return#0 ]

INITIAL ASM
Target platform is c64basic
  // File Comments
// Test a bit of array code from the NES forum
// https://forums.nesdev.com/viewtopic.php?f=2&t=18735
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_SIGNED_WORD = 2
  // @begin
bbegin:
  // [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
  jmp b1
  // @1
b1:
  // [2] call main 
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
  jmp bend
  // @end
bend:
  // main
main: {
    .label SCREEN = $400
    .label _1 = $b
    .label _3 = $f
    .label y1 = 5
    .label y2 = 7
    // [4] (signed word) main::y1#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y1
    lda #>$1234
    sta.z y1+1
    // [5] (signed word) main::y2#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y2
    lda #>$1234
    sta.z y2+1
    // [6] call foo 
    // [15] phi from main to foo [phi:main->foo]
  foo_from_main:
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y1#0 [phi:main->foo#0] -- pwsz1=pwsc1 
    lda #<y1
    sta.z foo.y
    lda #>y1
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 1 [phi:main->foo#1] -- vbuz1=vbuc1 
    lda #1
    sta.z foo.x
    jsr foo
    // [7] (signed word) foo::return#2 ← (signed word) foo::return#0 -- vwsz1=vwsz2 
    lda.z foo.return
    sta.z foo.return_2
    lda.z foo.return+1
    sta.z foo.return_2+1
    jmp b1
    // main::@1
  b1:
    // [8] (signed word~) main::$1 ← (signed word) foo::return#2 -- vwsz1=vwsz2 
    lda.z foo.return_2
    sta.z _1
    lda.z foo.return_2+1
    sta.z _1+1
    // [9] *((const signed word*) main::SCREEN#0) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 
    lda.z _1
    sta SCREEN
    lda.z _1+1
    sta SCREEN+1
    // [10] call foo 
    // [15] phi from main::@1 to foo [phi:main::@1->foo]
  foo_from_b1:
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y2#0 [phi:main::@1->foo#0] -- pwsz1=pwsc1 
    lda #<y2
    sta.z foo.y
    lda #>y2
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 2 [phi:main::@1->foo#1] -- vbuz1=vbuc1 
    lda #2
    sta.z foo.x
    jsr foo
    // [11] (signed word) foo::return#3 ← (signed word) foo::return#0 -- vwsz1=vwsz2 
    lda.z foo.return
    sta.z foo.return_3
    lda.z foo.return+1
    sta.z foo.return_3+1
    jmp b2
    // main::@2
  b2:
    // [12] (signed word~) main::$3 ← (signed word) foo::return#3 -- vwsz1=vwsz2 
    lda.z foo.return_3
    sta.z _3
    lda.z foo.return_3+1
    sta.z _3+1
    // [13] *((const signed word*) main::SCREEN#0+(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$3 -- _deref_pwsc1=vwsz1 
    lda.z _3
    sta SCREEN+SIZEOF_SIGNED_WORD
    lda.z _3+1
    sta SCREEN+SIZEOF_SIGNED_WORD+1
    jmp breturn
    // main::@return
  breturn:
    // [14] return 
    rts
}
  // foo
// foo(byte zeropage(2) x, signed word* zeropage(3) y)
foo: {
    .label _1 = $11
    .label return = $12
    .label return_2 = 9
    .label return_3 = $d
    .label x = 2
    .label y = 3
    // [16] (byte~) foo::$1 ← (byte) foo::x#2 << (byte) 1 -- vbuz1=vbuz2_rol_1 
    lda.z x
    asl
    sta.z _1
    // [17] (signed word) foo::return#0 ← *((const signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2) -- vwsz1=pwsc1_derefidx_vbuz2_plus__deref_pwsz3 
    ldx.z _1
    clc
    ldy #0
    lda wow,x
    adc (y),y
    sta.z return
    iny
    lda wow+1,x
    adc (y),y
    sta.z return+1
    jmp breturn
    // foo::@return
  breturn:
    // [18] return 
    rts
}
  // File Data
  wow: .word $cafe, $babe, $1234, $5678

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] (signed word) main::y1#0 ← (signed word) $1234 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [5] (signed word) main::y2#0 ← (signed word) $1234 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [7] (signed word) foo::return#2 ← (signed word) foo::return#0 [ foo::return#2 ] ( main:2 [ foo::return#2 ] ) always clobbers reg byte a 
Statement [8] (signed word~) main::$1 ← (signed word) foo::return#2 [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a 
Statement [9] *((const signed word*) main::SCREEN#0) ← (signed word~) main::$1 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [11] (signed word) foo::return#3 ← (signed word) foo::return#0 [ foo::return#3 ] ( main:2 [ foo::return#3 ] ) always clobbers reg byte a 
Statement [12] (signed word~) main::$3 ← (signed word) foo::return#3 [ main::$3 ] ( main:2 [ main::$3 ] ) always clobbers reg byte a 
Statement [13] *((const signed word*) main::SCREEN#0+(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$3 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [16] (byte~) foo::$1 ← (byte) foo::x#2 << (byte) 1 [ foo::y#2 foo::$1 ] ( main:2::foo:6 [ foo::y#2 foo::$1 ] main:2::foo:10 [ foo::y#2 foo::$1 ] ) always clobbers reg byte a 
Statement [17] (signed word) foo::return#0 ← *((const signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2) [ foo::return#0 ] ( main:2::foo:6 [ foo::return#0 ] main:2::foo:10 [ foo::return#0 ] ) always clobbers reg byte a reg byte y 
Potential registers zp ZP_BYTE:2 [ foo::x#2 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , 
Potential registers zp ZP_WORD:3 [ foo::y#2 ] : zp ZP_WORD:3 , 
Potential registers zp ZP_WORD:5 [ main::y1#0 ] : zp ZP_WORD:5 , 
Potential registers zp ZP_WORD:7 [ main::y2#0 ] : zp ZP_WORD:7 , 
Potential registers zp ZP_WORD:9 [ foo::return#2 ] : zp ZP_WORD:9 , 
Potential registers zp ZP_WORD:11 [ main::$1 ] : zp ZP_WORD:11 , 
Potential registers zp ZP_WORD:13 [ foo::return#3 ] : zp ZP_WORD:13 , 
Potential registers zp ZP_WORD:15 [ main::$3 ] : zp ZP_WORD:15 , 
Potential registers zp ZP_BYTE:17 [ foo::$1 ] : zp ZP_BYTE:17 , reg byte a , reg byte x , reg byte y , 
Potential registers zp ZP_WORD:18 [ foo::return#0 ] : zp ZP_WORD:18 , 

REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp ZP_WORD:5 [ main::y1#0 ] 20: zp ZP_WORD:7 [ main::y2#0 ] 4: zp ZP_WORD:11 [ main::$1 ] 4: zp ZP_WORD:15 [ main::$3 ] 
Uplift Scope [foo] 4: zp ZP_WORD:9 [ foo::return#2 ] 4: zp ZP_WORD:13 [ foo::return#3 ] 4: zp ZP_BYTE:17 [ foo::$1 ] 2: zp ZP_BYTE:2 [ foo::x#2 ] 1.5: zp ZP_WORD:18 [ foo::return#0 ] 1: zp ZP_WORD:3 [ foo::y#2 ] 
Uplift Scope [] 

Uplifting [main] best 217 combination zp ZP_WORD:5 [ main::y1#0 ] zp ZP_WORD:7 [ main::y2#0 ] zp ZP_WORD:11 [ main::$1 ] zp ZP_WORD:15 [ main::$3 ] 
Uplifting [foo] best 206 combination zp ZP_WORD:9 [ foo::return#2 ] zp ZP_WORD:13 [ foo::return#3 ] reg byte a [ foo::$1 ] reg byte x [ foo::x#2 ] zp ZP_WORD:18 [ foo::return#0 ] zp ZP_WORD:3 [ foo::y#2 ] 
Uplifting [] best 206 combination 
Coalescing zero page register [ zp ZP_WORD:3 [ foo::y#2 ] ] with [ zp ZP_WORD:18 [ foo::return#0 ] ] - score: 1
Coalescing zero page register [ zp ZP_WORD:9 [ foo::return#2 ] ] with [ zp ZP_WORD:11 [ main::$1 ] ] - score: 1
Coalescing zero page register [ zp ZP_WORD:13 [ foo::return#3 ] ] with [ zp ZP_WORD:15 [ main::$3 ] ] - score: 1
Coalescing zero page register [ zp ZP_WORD:3 [ foo::y#2 foo::return#0 ] ] with [ zp ZP_WORD:9 [ foo::return#2 main::$1 ] ] - score: 1
Coalescing zero page register [ zp ZP_WORD:3 [ foo::y#2 foo::return#0 foo::return#2 main::$1 ] ] with [ zp ZP_WORD:13 [ foo::return#3 main::$3 ] ] - score: 1
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ foo::y#2 foo::return#0 foo::return#2 main::$1 foo::return#3 main::$3 ]
Allocated (was zp ZP_WORD:5) zp ZP_WORD:4 [ main::y1#0 ]
Allocated (was zp ZP_WORD:7) zp ZP_WORD:6 [ main::y2#0 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Test a bit of array code from the NES forum
// https://forums.nesdev.com/viewtopic.php?f=2&t=18735
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_SIGNED_WORD = 2
  // @begin
bbegin:
  // [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
  jmp b1
  // @1
b1:
  // [2] call main 
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
  jmp bend
  // @end
bend:
  // main
main: {
    .label SCREEN = $400
    .label _1 = 2
    .label _3 = 2
    .label y1 = 4
    .label y2 = 6
    // [4] (signed word) main::y1#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y1
    lda #>$1234
    sta.z y1+1
    // [5] (signed word) main::y2#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y2
    lda #>$1234
    sta.z y2+1
    // [6] call foo 
    // [15] phi from main to foo [phi:main->foo]
  foo_from_main:
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y1#0 [phi:main->foo#0] -- pwsz1=pwsc1 
    lda #<y1
    sta.z foo.y
    lda #>y1
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 1 [phi:main->foo#1] -- vbuxx=vbuc1 
    ldx #1
    jsr foo
    // [7] (signed word) foo::return#2 ← (signed word) foo::return#0
    jmp b1
    // main::@1
  b1:
    // [8] (signed word~) main::$1 ← (signed word) foo::return#2
    // [9] *((const signed word*) main::SCREEN#0) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 
    lda.z _1
    sta SCREEN
    lda.z _1+1
    sta SCREEN+1
    // [10] call foo 
    // [15] phi from main::@1 to foo [phi:main::@1->foo]
  foo_from_b1:
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y2#0 [phi:main::@1->foo#0] -- pwsz1=pwsc1 
    lda #<y2
    sta.z foo.y
    lda #>y2
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 2 [phi:main::@1->foo#1] -- vbuxx=vbuc1 
    ldx #2
    jsr foo
    // [11] (signed word) foo::return#3 ← (signed word) foo::return#0
    jmp b2
    // main::@2
  b2:
    // [12] (signed word~) main::$3 ← (signed word) foo::return#3
    // [13] *((const signed word*) main::SCREEN#0+(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$3 -- _deref_pwsc1=vwsz1 
    lda.z _3
    sta SCREEN+SIZEOF_SIGNED_WORD
    lda.z _3+1
    sta SCREEN+SIZEOF_SIGNED_WORD+1
    jmp breturn
    // main::@return
  breturn:
    // [14] return 
    rts
}
  // foo
// foo(byte register(X) x, signed word* zeropage(2) y)
foo: {
    .label return = 2
    .label y = 2
    // [16] (byte~) foo::$1 ← (byte) foo::x#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 
    txa
    asl
    // [17] (signed word) foo::return#0 ← *((const signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2) -- vwsz1=pwsc1_derefidx_vbuaa_plus__deref_pwsz1 
    tax
    clc
    ldy #0
    lda wow,x
    adc (return),y
    pha
    iny
    lda wow+1,x
    adc (return),y
    sta.z return+1
    pla
    sta.z return
    jmp breturn
    // foo::@return
  breturn:
    // [18] return 
    rts
}
  // File Data
  wow: .word $cafe, $babe, $1234, $5678

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp breturn
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction foo_from_main:
Removing instruction b1:
Removing instruction foo_from_b1:
Removing instruction b2:
Removing instruction breturn:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination

FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_SIGNED_WORD SIZEOF_SIGNED_WORD = (byte) 2
(signed word()) foo((byte) foo::x , (signed word*) foo::y)
(byte~) foo::$1 reg byte a 4.0
(label) foo::@return
(signed word) foo::return
(signed word) foo::return#0 return zp ZP_WORD:2 1.5
(signed word) foo::return#2 return zp ZP_WORD:2 4.0
(signed word) foo::return#3 return zp ZP_WORD:2 4.0
(byte) foo::x
(byte) foo::x#2 reg byte x 2.0
(signed word*) foo::y
(signed word*) foo::y#2 y zp ZP_WORD:2 1.0
(void()) main()
(signed word~) main::$1 $1 zp ZP_WORD:2 4.0
(signed word~) main::$3 $3 zp ZP_WORD:2 4.0
(label) main::@1
(label) main::@2
(label) main::@return
(signed word*) main::SCREEN
(const signed word*) main::SCREEN#0 SCREEN = (signed word*) 1024
(signed word) main::y1
(signed word) main::y1#0 y1 zp ZP_WORD:4 20.0
(signed word) main::y2
(signed word) main::y2#0 y2 zp ZP_WORD:6 20.0
(signed word[4]) wow
(const signed word[4]) wow#0 wow = { (signed word) $cafe, (signed word) $babe, (signed word) $1234, (signed word) $5678 }

reg byte x [ foo::x#2 ]
zp ZP_WORD:2 [ foo::y#2 foo::return#0 foo::return#2 main::$1 foo::return#3 main::$3 ]
zp ZP_WORD:4 [ main::y1#0 ]
zp ZP_WORD:6 [ main::y2#0 ]
reg byte a [ foo::$1 ]


FINAL ASSEMBLER
Score: 141

  // File Comments
// Test a bit of array code from the NES forum
// https://forums.nesdev.com/viewtopic.php?f=2&t=18735
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_SIGNED_WORD = 2
  // @begin
  // [1] phi from @begin to @1 [phi:@begin->@1]
  // @1
  // [2] call main 
  // [3] phi from @1 to @end [phi:@1->@end]
  // @end
  // main
main: {
    .label SCREEN = $400
    .label _1 = 2
    .label _3 = 2
    .label y1 = 4
    .label y2 = 6
    // y1 = 0x1234
    // [4] (signed word) main::y1#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y1
    lda #>$1234
    sta.z y1+1
    // y2 = 0x1234
    // [5] (signed word) main::y2#0 ← (signed word) $1234 -- vwsz1=vwsc1 
    lda #<$1234
    sta.z y2
    lda #>$1234
    sta.z y2+1
    // foo(1, &y1)
    // [6] call foo 
    // [15] phi from main to foo [phi:main->foo]
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y1#0 [phi:main->foo#0] -- pwsz1=pwsc1 
    lda #<y1
    sta.z foo.y
    lda #>y1
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 1 [phi:main->foo#1] -- vbuxx=vbuc1 
    ldx #1
    jsr foo
    // foo(1, &y1)
    // [7] (signed word) foo::return#2 ← (signed word) foo::return#0
    // main::@1
    // [8] (signed word~) main::$1 ← (signed word) foo::return#2
    // *SCREEN++ = foo(1, &y1)
    // [9] *((const signed word*) main::SCREEN#0) ← (signed word~) main::$1 -- _deref_pwsc1=vwsz1 
    lda.z _1
    sta SCREEN
    lda.z _1+1
    sta SCREEN+1
    // foo(2, &y2)
    // [10] call foo 
    // [15] phi from main::@1 to foo [phi:main::@1->foo]
    // [15] phi (signed word*) foo::y#2 = &(signed word) main::y2#0 [phi:main::@1->foo#0] -- pwsz1=pwsc1 
    lda #<y2
    sta.z foo.y
    lda #>y2
    sta.z foo.y+1
    // [15] phi (byte) foo::x#2 = (byte) 2 [phi:main::@1->foo#1] -- vbuxx=vbuc1 
    ldx #2
    jsr foo
    // foo(2, &y2)
    // [11] (signed word) foo::return#3 ← (signed word) foo::return#0
    // main::@2
    // [12] (signed word~) main::$3 ← (signed word) foo::return#3
    // *SCREEN++ = foo(2, &y2)
    // [13] *((const signed word*) main::SCREEN#0+(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$3 -- _deref_pwsc1=vwsz1 
    lda.z _3
    sta SCREEN+SIZEOF_SIGNED_WORD
    lda.z _3+1
    sta SCREEN+SIZEOF_SIGNED_WORD+1
    // main::@return
    // }
    // [14] return 
    rts
}
  // foo
// foo(byte register(X) x, signed word* zeropage(2) y)
foo: {
    .label return = 2
    .label y = 2
    // wow[x] + *y
    // [16] (byte~) foo::$1 ← (byte) foo::x#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 
    txa
    asl
    // [17] (signed word) foo::return#0 ← *((const signed word[4]) wow#0 + (byte~) foo::$1) + *((signed word*) foo::y#2) -- vwsz1=pwsc1_derefidx_vbuaa_plus__deref_pwsz1 
    tax
    clc
    ldy #0
    lda wow,x
    adc (return),y
    pha
    iny
    lda wow+1,x
    adc (return),y
    sta.z return+1
    pla
    sta.z return
    // foo::@return
    // }
    // [18] return 
    rts
}
  // File Data
  wow: .word $cafe, $babe, $1234, $5678

