Fixing pointer array-indexing *((dword*) main::screen + (number) 0)
Fixing pointer array-indexing *((dword*) main::screen + (number) 1)
Identified constant variable (dword*) main::screen
Culled Empty Block (label) @1
Culled Empty Block (label) mul16u::@1

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  to:@2
main: scope:[main]  from @2
  (dword*) main::screen#0 ← ((dword*)) (number) $400
  (word) main::w#0 ← (number) $a
  (word) mul16u::b#0 ← (word) main::w#0
  (word) mul16u::a#0 ← (word) main::w#0
  call mul16u 
  (dword) mul16u::return#0 ← (dword) mul16u::return#3
  to:main::@1
main::@1: scope:[main]  from main
  (dword) mul16u::return#4 ← phi( main/(dword) mul16u::return#0 )
  (dword~) main::$0 ← (dword) mul16u::return#4
  (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_DWORD
  *((dword*) main::screen#0 + (number~) main::$2) ← (dword~) main::$0
  (word) main::w#1 ← (number) $3e8
  (word) mul16u::b#1 ← (word) main::w#1
  (word) mul16u::a#1 ← (word) main::w#1
  call mul16u 
  (dword) mul16u::return#1 ← (dword) mul16u::return#3
  to:main::@2
main::@2: scope:[main]  from main::@1
  (dword) mul16u::return#5 ← phi( main::@1/(dword) mul16u::return#1 )
  (dword~) main::$1 ← (dword) mul16u::return#5
  (number~) main::$3 ← (number) 1 * (const byte) SIZEOF_DWORD
  *((dword*) main::screen#0 + (number~) main::$3) ← (dword~) main::$1
  to:main::@return
main::@return: scope:[main]  from main::@2
  return 
  to:@return
mul16u: scope:[mul16u]  from main main::@1
  (word) mul16u::a#2 ← phi( main/(word) mul16u::a#0 main::@1/(word) mul16u::a#1 )
  (word) mul16u::b#2 ← phi( main/(word) mul16u::b#0 main::@1/(word) mul16u::b#1 )
  (dword) mul16u::mb#0 ← (word) mul16u::b#2
  (dword~) mul16u::$0 ← (dword) mul16u::mb#0 + (word) mul16u::a#2
  (dword) mul16u::return#2 ← (dword~) mul16u::$0
  to:mul16u::@return
mul16u::@return: scope:[mul16u]  from mul16u
  (dword) mul16u::return#6 ← phi( mul16u/(dword) mul16u::return#2 )
  (dword) mul16u::return#3 ← (dword) mul16u::return#6
  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_DWORD = (byte) 4
(void()) main()
(dword~) main::$0
(dword~) main::$1
(number~) main::$2
(number~) main::$3
(label) main::@1
(label) main::@2
(label) main::@return
(dword*) main::screen
(dword*) main::screen#0
(word) main::w
(word) main::w#0
(word) main::w#1
(dword()) mul16u((word) mul16u::b , (word) mul16u::a)
(dword~) mul16u::$0
(label) mul16u::@return
(word) mul16u::a
(word) mul16u::a#0
(word) mul16u::a#1
(word) mul16u::a#2
(word) mul16u::b
(word) mul16u::b#0
(word) mul16u::b#1
(word) mul16u::b#2
(dword) mul16u::mb
(dword) mul16u::mb#0
(dword) mul16u::return
(dword) mul16u::return#0
(dword) mul16u::return#1
(dword) mul16u::return#2
(dword) mul16u::return#3
(dword) mul16u::return#4
(dword) mul16u::return#5
(dword) mul16u::return#6

Adding number conversion cast (unumber) $a in (word) main::w#0 ← (number) $a
Adding number conversion cast (unumber) 0 in (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_DWORD
Adding number conversion cast (unumber) main::$2 in (number~) main::$2 ← (unumber)(number) 0 * (const byte) SIZEOF_DWORD
Adding number conversion cast (unumber) $3e8 in (word) main::w#1 ← (number) $3e8
Adding number conversion cast (unumber) 1 in (number~) main::$3 ← (number) 1 * (const byte) SIZEOF_DWORD
Adding number conversion cast (unumber) main::$3 in (number~) main::$3 ← (unumber)(number) 1 * (const byte) SIZEOF_DWORD
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (dword*) main::screen#0 ← (dword*)(number) $400
Inlining cast (word) main::w#0 ← (unumber)(number) $a
Inlining cast (word) main::w#1 ← (unumber)(number) $3e8
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (dword*) 1024
Simplifying constant integer cast $a
Simplifying constant integer cast 0
Simplifying constant integer cast $3e8
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $a
Finalized unsigned number type (byte) 0
Finalized unsigned number type (word) $3e8
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) main::$2 ← (byte) 0 * (const byte) SIZEOF_DWORD
Inferred type updated to byte in (unumber~) main::$3 ← (byte) 1 * (const byte) SIZEOF_DWORD
Alias (dword) mul16u::return#0 = (dword) mul16u::return#4 
Alias (dword) mul16u::return#1 = (dword) mul16u::return#5 
Alias (dword) mul16u::mb#0 = (word) mul16u::b#2 
Alias (dword) mul16u::return#2 = (dword~) mul16u::$0 (dword) mul16u::return#6 (dword) mul16u::return#3 
Successful SSA optimization Pass2AliasElimination
Constant right-side identified [8] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_DWORD
Constant right-side identified [17] (byte~) main::$3 ← (byte) 1 * (const byte) SIZEOF_DWORD
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const dword*) main::screen#0 = (dword*) 1024
Constant (const word) main::w#0 = $a
Constant (const byte) main::$2 = 0*SIZEOF_DWORD
Constant (const word) main::w#1 = $3e8
Constant (const byte) main::$3 = 1*SIZEOF_DWORD
Successful SSA optimization Pass2ConstantIdentification
Constant (const word) mul16u::b#0 = main::w#0
Constant (const word) mul16u::a#0 = main::w#0
Constant (const word) mul16u::b#1 = main::w#1
Constant (const word) mul16u::a#1 = main::w#1
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_DWORD in 
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero main::screen#0 in [9] *((const dword*) main::screen#0 + (const byte) main::$2) ← (dword~) main::$0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) main::$2
Successful SSA optimization PassNEliminateUnusedVars
Inlining constant with different constant siblings (const word) main::w#0
Inlining constant with different constant siblings (const word) main::w#1
Inlining constant with var siblings (const word) mul16u::a#0
Inlining constant with var siblings (const word) mul16u::a#1
Constant inlined mul16u::b#1 = (word) $3e8
Constant inlined main::$3 = (byte) 1*(const byte) SIZEOF_DWORD
Constant inlined main::w#1 = (word) $3e8
Constant inlined main::w#0 = (byte) $a
Constant inlined mul16u::b#0 = (byte) $a
Constant inlined mul16u::a#1 = (word) $3e8
Constant inlined mul16u::a#0 = (byte) $a
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::screen#0+1*SIZEOF_DWORD)
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
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2 
Calls in [main] to mul16u:6 mul16u:10 

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
Adding NOP phi() at start of main

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 mul16u 
  [6] (dword) mul16u::return#0 ← (dword) mul16u::return#2
  to:main::@1
main::@1: scope:[main]  from main
  [7] (dword~) main::$0 ← (dword) mul16u::return#0
  [8] *((const dword*) main::screen#0) ← (dword~) main::$0
  [9] call mul16u 
  [10] (dword) mul16u::return#1 ← (dword) mul16u::return#2
  to:main::@2
main::@2: scope:[main]  from main::@1
  [11] (dword~) main::$1 ← (dword) mul16u::return#1
  [12] *((const dword*) main::screen#0+(byte) 1*(const byte) SIZEOF_DWORD) ← (dword~) main::$1
  to:main::@return
main::@return: scope:[main]  from main::@2
  [13] return 
  to:@return
mul16u: scope:[mul16u]  from main main::@1
  [14] (word) mul16u::a#2 ← phi( main/(byte) $a main::@1/(word) $3e8 )
  [14] (dword) mul16u::mb#0 ← phi( main/(byte) $a main::@1/(word) $3e8 )
  [15] (dword) mul16u::return#2 ← (dword) mul16u::mb#0 + (word) mul16u::a#2
  to:mul16u::@return
mul16u::@return: scope:[mul16u]  from mul16u
  [16] return 
  to:@return


VARIABLE REGISTER WEIGHTS
(void()) main()
(dword~) main::$0 4.0
(dword~) main::$1 4.0
(dword*) main::screen
(word) main::w
(dword()) mul16u((word) mul16u::b , (word) mul16u::a)
(word) mul16u::a
(word) mul16u::a#2 2.0
(word) mul16u::b
(dword) mul16u::mb
(dword) mul16u::mb#0 2.0
(dword) mul16u::return
(dword) mul16u::return#0 4.0
(dword) mul16u::return#1 4.0
(dword) mul16u::return#2 1.5

Initial phi equivalence classes
[ mul16u::mb#0 ]
[ mul16u::a#2 ]
Added variable mul16u::return#0 to zero page equivalence class [ mul16u::return#0 ]
Added variable main::$0 to zero page equivalence class [ main::$0 ]
Added variable mul16u::return#1 to zero page equivalence class [ mul16u::return#1 ]
Added variable main::$1 to zero page equivalence class [ main::$1 ]
Added variable mul16u::return#2 to zero page equivalence class [ mul16u::return#2 ]
Complete equivalence classes
[ mul16u::mb#0 ]
[ mul16u::a#2 ]
[ mul16u::return#0 ]
[ main::$0 ]
[ mul16u::return#1 ]
[ main::$1 ]
[ mul16u::return#2 ]
Allocated zp ZP_DWORD:2 [ mul16u::mb#0 ]
Allocated zp ZP_WORD:6 [ mul16u::a#2 ]
Allocated zp ZP_DWORD:8 [ mul16u::return#0 ]
Allocated zp ZP_DWORD:12 [ main::$0 ]
Allocated zp ZP_DWORD:16 [ mul16u::return#1 ]
Allocated zp ZP_DWORD:20 [ main::$1 ]
Allocated zp ZP_DWORD:24 [ mul16u::return#2 ]

INITIAL ASM
Target platform is c64basic
  // File Comments
// Tests that ASM fragment variations works
// ASM fragment variations "cast" constants to different types
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_DWORD = 4
  // @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: {
    .label screen = $400
    .label _0 = $c
    .label _1 = $14
    // [5] call mul16u 
    // [14] phi from main to mul16u [phi:main->mul16u]
  mul16u_from_main:
    // [14] phi (word) mul16u::a#2 = (byte) $a [phi:main->mul16u#0] -- vwuz1=vbuc1 
    lda #<$a
    sta.z mul16u.a
    lda #>$a
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (byte) $a [phi:main->mul16u#1] -- vduz1=vbuc1 
    lda #$a
    sta.z mul16u.mb
    lda #0
    sta.z mul16u.mb+1
    sta.z mul16u.mb+2
    sta.z mul16u.mb+3
    jsr mul16u
    // [6] (dword) mul16u::return#0 ← (dword) mul16u::return#2 -- vduz1=vduz2 
    lda.z mul16u.return_2
    sta.z mul16u.return
    lda.z mul16u.return_2+1
    sta.z mul16u.return+1
    lda.z mul16u.return_2+2
    sta.z mul16u.return+2
    lda.z mul16u.return_2+3
    sta.z mul16u.return+3
    jmp b1
    // main::@1
  b1:
    // [7] (dword~) main::$0 ← (dword) mul16u::return#0 -- vduz1=vduz2 
    lda.z mul16u.return
    sta.z _0
    lda.z mul16u.return+1
    sta.z _0+1
    lda.z mul16u.return+2
    sta.z _0+2
    lda.z mul16u.return+3
    sta.z _0+3
    // [8] *((const dword*) main::screen#0) ← (dword~) main::$0 -- _deref_pduc1=vduz1 
    lda.z _0
    sta screen
    lda.z _0+1
    sta screen+1
    lda.z _0+2
    sta screen+2
    lda.z _0+3
    sta screen+3
    // [9] call mul16u 
    // [14] phi from main::@1 to mul16u [phi:main::@1->mul16u]
  mul16u_from_b1:
    // [14] phi (word) mul16u::a#2 = (word) $3e8 [phi:main::@1->mul16u#0] -- vwuz1=vwuc1 
    lda #<$3e8
    sta.z mul16u.a
    lda #>$3e8
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (word) $3e8 [phi:main::@1->mul16u#1] -- vduz1=vduc1 
    lda #<$3e8
    sta.z mul16u.mb
    lda #>$3e8
    sta.z mul16u.mb+1
    lda #<$3e8>>$10
    sta.z mul16u.mb+2
    lda #>$3e8>>$10
    sta.z mul16u.mb+3
    jsr mul16u
    // [10] (dword) mul16u::return#1 ← (dword) mul16u::return#2 -- vduz1=vduz2 
    lda.z mul16u.return_2
    sta.z mul16u.return_1
    lda.z mul16u.return_2+1
    sta.z mul16u.return_1+1
    lda.z mul16u.return_2+2
    sta.z mul16u.return_1+2
    lda.z mul16u.return_2+3
    sta.z mul16u.return_1+3
    jmp b2
    // main::@2
  b2:
    // [11] (dword~) main::$1 ← (dword) mul16u::return#1 -- vduz1=vduz2 
    lda.z mul16u.return_1
    sta.z _1
    lda.z mul16u.return_1+1
    sta.z _1+1
    lda.z mul16u.return_1+2
    sta.z _1+2
    lda.z mul16u.return_1+3
    sta.z _1+3
    // [12] *((const dword*) main::screen#0+(byte) 1*(const byte) SIZEOF_DWORD) ← (dword~) main::$1 -- _deref_pduc1=vduz1 
    lda.z _1
    sta screen+1*SIZEOF_DWORD
    lda.z _1+1
    sta screen+1*SIZEOF_DWORD+1
    lda.z _1+2
    sta screen+1*SIZEOF_DWORD+2
    lda.z _1+3
    sta screen+1*SIZEOF_DWORD+3
    jmp breturn
    // main::@return
  breturn:
    // [13] return 
    rts
}
  // mul16u
// mul16u(word zeropage(6) a)
mul16u: {
    .label return = 8
    .label return_1 = $10
    .label mb = 2
    .label return_2 = $18
    .label a = 6
    // [15] (dword) mul16u::return#2 ← (dword) mul16u::mb#0 + (word) mul16u::a#2 -- vduz1=vduz2_plus_vwuz3 
    lda.z mb
    clc
    adc.z a
    sta.z return_2
    lda.z mb+1
    adc.z a+1
    sta.z return_2+1
    lda.z mb+2
    adc #0
    sta.z return_2+2
    lda.z mb+3
    adc #0
    sta.z return_2+3
    jmp breturn
    // mul16u::@return
  breturn:
    // [16] return 
    rts
}
  // File Data

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (dword) mul16u::return#0 ← (dword) mul16u::return#2 [ mul16u::return#0 ] ( main:2 [ mul16u::return#0 ] ) always clobbers reg byte a 
Statement [7] (dword~) main::$0 ← (dword) mul16u::return#0 [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a 
Statement [8] *((const dword*) main::screen#0) ← (dword~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [10] (dword) mul16u::return#1 ← (dword) mul16u::return#2 [ mul16u::return#1 ] ( main:2 [ mul16u::return#1 ] ) always clobbers reg byte a 
Statement [11] (dword~) main::$1 ← (dword) mul16u::return#1 [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a 
Statement [12] *((const dword*) main::screen#0+(byte) 1*(const byte) SIZEOF_DWORD) ← (dword~) main::$1 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [15] (dword) mul16u::return#2 ← (dword) mul16u::mb#0 + (word) mul16u::a#2 [ mul16u::return#2 ] ( main:2::mul16u:5 [ mul16u::return#2 ] main:2::mul16u:9 [ mul16u::return#2 ] ) always clobbers reg byte a 
Potential registers zp ZP_DWORD:2 [ mul16u::mb#0 ] : zp ZP_DWORD:2 , 
Potential registers zp ZP_WORD:6 [ mul16u::a#2 ] : zp ZP_WORD:6 , 
Potential registers zp ZP_DWORD:8 [ mul16u::return#0 ] : zp ZP_DWORD:8 , 
Potential registers zp ZP_DWORD:12 [ main::$0 ] : zp ZP_DWORD:12 , 
Potential registers zp ZP_DWORD:16 [ mul16u::return#1 ] : zp ZP_DWORD:16 , 
Potential registers zp ZP_DWORD:20 [ main::$1 ] : zp ZP_DWORD:20 , 
Potential registers zp ZP_DWORD:24 [ mul16u::return#2 ] : zp ZP_DWORD:24 , 

REGISTER UPLIFT SCOPES
Uplift Scope [mul16u] 4: zp ZP_DWORD:8 [ mul16u::return#0 ] 4: zp ZP_DWORD:16 [ mul16u::return#1 ] 2: zp ZP_DWORD:2 [ mul16u::mb#0 ] 2: zp ZP_WORD:6 [ mul16u::a#2 ] 1.5: zp ZP_DWORD:24 [ mul16u::return#2 ] 
Uplift Scope [main] 4: zp ZP_DWORD:12 [ main::$0 ] 4: zp ZP_DWORD:20 [ main::$1 ] 
Uplift Scope [] 

Uplifting [mul16u] best 292 combination zp ZP_DWORD:8 [ mul16u::return#0 ] zp ZP_DWORD:16 [ mul16u::return#1 ] zp ZP_DWORD:2 [ mul16u::mb#0 ] zp ZP_WORD:6 [ mul16u::a#2 ] zp ZP_DWORD:24 [ mul16u::return#2 ] 
Uplifting [main] best 292 combination zp ZP_DWORD:12 [ main::$0 ] zp ZP_DWORD:20 [ main::$1 ] 
Uplifting [] best 292 combination 
Coalescing zero page register [ zp ZP_DWORD:2 [ mul16u::mb#0 ] ] with [ zp ZP_DWORD:24 [ mul16u::return#2 ] ] - score: 1
Coalescing zero page register [ zp ZP_DWORD:8 [ mul16u::return#0 ] ] with [ zp ZP_DWORD:12 [ main::$0 ] ] - score: 1
Coalescing zero page register [ zp ZP_DWORD:16 [ mul16u::return#1 ] ] with [ zp ZP_DWORD:20 [ main::$1 ] ] - score: 1
Coalescing zero page register [ zp ZP_DWORD:2 [ mul16u::mb#0 mul16u::return#2 ] ] with [ zp ZP_DWORD:8 [ mul16u::return#0 main::$0 ] ] - score: 1
Coalescing zero page register [ zp ZP_DWORD:2 [ mul16u::mb#0 mul16u::return#2 mul16u::return#0 main::$0 ] ] with [ zp ZP_DWORD:16 [ mul16u::return#1 main::$1 ] ] - score: 1

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Tests that ASM fragment variations works
// ASM fragment variations "cast" constants to different types
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_DWORD = 4
  // @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: {
    .label screen = $400
    .label _0 = 2
    .label _1 = 2
    // [5] call mul16u 
    // [14] phi from main to mul16u [phi:main->mul16u]
  mul16u_from_main:
    // [14] phi (word) mul16u::a#2 = (byte) $a [phi:main->mul16u#0] -- vwuz1=vbuc1 
    lda #<$a
    sta.z mul16u.a
    lda #>$a
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (byte) $a [phi:main->mul16u#1] -- vduz1=vbuc1 
    lda #$a
    sta.z mul16u.mb
    lda #0
    sta.z mul16u.mb+1
    sta.z mul16u.mb+2
    sta.z mul16u.mb+3
    jsr mul16u
    // [6] (dword) mul16u::return#0 ← (dword) mul16u::return#2
    jmp b1
    // main::@1
  b1:
    // [7] (dword~) main::$0 ← (dword) mul16u::return#0
    // [8] *((const dword*) main::screen#0) ← (dword~) main::$0 -- _deref_pduc1=vduz1 
    lda.z _0
    sta screen
    lda.z _0+1
    sta screen+1
    lda.z _0+2
    sta screen+2
    lda.z _0+3
    sta screen+3
    // [9] call mul16u 
    // [14] phi from main::@1 to mul16u [phi:main::@1->mul16u]
  mul16u_from_b1:
    // [14] phi (word) mul16u::a#2 = (word) $3e8 [phi:main::@1->mul16u#0] -- vwuz1=vwuc1 
    lda #<$3e8
    sta.z mul16u.a
    lda #>$3e8
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (word) $3e8 [phi:main::@1->mul16u#1] -- vduz1=vduc1 
    lda #<$3e8
    sta.z mul16u.mb
    lda #>$3e8
    sta.z mul16u.mb+1
    lda #<$3e8>>$10
    sta.z mul16u.mb+2
    lda #>$3e8>>$10
    sta.z mul16u.mb+3
    jsr mul16u
    // [10] (dword) mul16u::return#1 ← (dword) mul16u::return#2
    jmp b2
    // main::@2
  b2:
    // [11] (dword~) main::$1 ← (dword) mul16u::return#1
    // [12] *((const dword*) main::screen#0+(byte) 1*(const byte) SIZEOF_DWORD) ← (dword~) main::$1 -- _deref_pduc1=vduz1 
    lda.z _1
    sta screen+1*SIZEOF_DWORD
    lda.z _1+1
    sta screen+1*SIZEOF_DWORD+1
    lda.z _1+2
    sta screen+1*SIZEOF_DWORD+2
    lda.z _1+3
    sta screen+1*SIZEOF_DWORD+3
    jmp breturn
    // main::@return
  breturn:
    // [13] return 
    rts
}
  // mul16u
// mul16u(word zeropage(6) a)
mul16u: {
    .label return = 2
    .label mb = 2
    .label a = 6
    // [15] (dword) mul16u::return#2 ← (dword) mul16u::mb#0 + (word) mul16u::a#2 -- vduz1=vduz1_plus_vwuz2 
    lda.z return
    clc
    adc.z a
    sta.z return
    lda.z return+1
    adc.z a+1
    sta.z return+1
    lda.z return+2
    adc #0
    sta.z return+2
    lda.z return+3
    adc #0
    sta.z return+3
    jmp breturn
    // mul16u::@return
  breturn:
    // [16] return 
    rts
}
  // File Data

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 main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction mul16u_from_main:
Removing instruction b1:
Removing instruction mul16u_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_DWORD SIZEOF_DWORD = (byte) 4
(void()) main()
(dword~) main::$0 $0 zp ZP_DWORD:2 4.0
(dword~) main::$1 $1 zp ZP_DWORD:2 4.0
(label) main::@1
(label) main::@2
(label) main::@return
(dword*) main::screen
(const dword*) main::screen#0 screen = (dword*) 1024
(word) main::w
(dword()) mul16u((word) mul16u::b , (word) mul16u::a)
(label) mul16u::@return
(word) mul16u::a
(word) mul16u::a#2 a zp ZP_WORD:6 2.0
(word) mul16u::b
(dword) mul16u::mb
(dword) mul16u::mb#0 mb zp ZP_DWORD:2 2.0
(dword) mul16u::return
(dword) mul16u::return#0 return zp ZP_DWORD:2 4.0
(dword) mul16u::return#1 return zp ZP_DWORD:2 4.0
(dword) mul16u::return#2 return zp ZP_DWORD:2 1.5

zp ZP_DWORD:2 [ mul16u::mb#0 mul16u::return#2 mul16u::return#0 main::$0 mul16u::return#1 main::$1 ]
zp ZP_WORD:6 [ mul16u::a#2 ]


FINAL ASSEMBLER
Score: 172

  // File Comments
// Tests that ASM fragment variations works
// ASM fragment variations "cast" constants to different types
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
  // Global Constants & labels
  .const SIZEOF_DWORD = 4
  // @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: {
    .label screen = $400
    .label _0 = 2
    .label _1 = 2
    // mul16u(w, w)
    // [5] call mul16u 
    // [14] phi from main to mul16u [phi:main->mul16u]
    // [14] phi (word) mul16u::a#2 = (byte) $a [phi:main->mul16u#0] -- vwuz1=vbuc1 
    lda #<$a
    sta.z mul16u.a
    lda #>$a
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (byte) $a [phi:main->mul16u#1] -- vduz1=vbuc1 
    lda #$a
    sta.z mul16u.mb
    lda #0
    sta.z mul16u.mb+1
    sta.z mul16u.mb+2
    sta.z mul16u.mb+3
    jsr mul16u
    // mul16u(w, w)
    // [6] (dword) mul16u::return#0 ← (dword) mul16u::return#2
    // main::@1
    // [7] (dword~) main::$0 ← (dword) mul16u::return#0
    // screen[0] = mul16u(w, w)
    // [8] *((const dword*) main::screen#0) ← (dword~) main::$0 -- _deref_pduc1=vduz1 
    lda.z _0
    sta screen
    lda.z _0+1
    sta screen+1
    lda.z _0+2
    sta screen+2
    lda.z _0+3
    sta screen+3
    // mul16u(w, w)
    // [9] call mul16u 
    // [14] phi from main::@1 to mul16u [phi:main::@1->mul16u]
    // [14] phi (word) mul16u::a#2 = (word) $3e8 [phi:main::@1->mul16u#0] -- vwuz1=vwuc1 
    lda #<$3e8
    sta.z mul16u.a
    lda #>$3e8
    sta.z mul16u.a+1
    // [14] phi (dword) mul16u::mb#0 = (word) $3e8 [phi:main::@1->mul16u#1] -- vduz1=vduc1 
    lda #<$3e8
    sta.z mul16u.mb
    lda #>$3e8
    sta.z mul16u.mb+1
    lda #<$3e8>>$10
    sta.z mul16u.mb+2
    lda #>$3e8>>$10
    sta.z mul16u.mb+3
    jsr mul16u
    // mul16u(w, w)
    // [10] (dword) mul16u::return#1 ← (dword) mul16u::return#2
    // main::@2
    // [11] (dword~) main::$1 ← (dword) mul16u::return#1
    // screen[1] = mul16u(w, w)
    // [12] *((const dword*) main::screen#0+(byte) 1*(const byte) SIZEOF_DWORD) ← (dword~) main::$1 -- _deref_pduc1=vduz1 
    lda.z _1
    sta screen+1*SIZEOF_DWORD
    lda.z _1+1
    sta screen+1*SIZEOF_DWORD+1
    lda.z _1+2
    sta screen+1*SIZEOF_DWORD+2
    lda.z _1+3
    sta screen+1*SIZEOF_DWORD+3
    // main::@return
    // }
    // [13] return 
    rts
}
  // mul16u
// mul16u(word zeropage(6) a)
mul16u: {
    .label return = 2
    .label mb = 2
    .label a = 6
    // mb+a
    // [15] (dword) mul16u::return#2 ← (dword) mul16u::mb#0 + (word) mul16u::a#2 -- vduz1=vduz1_plus_vwuz2 
    lda.z return
    clc
    adc.z a
    sta.z return
    lda.z return+1
    adc.z a+1
    sta.z return+1
    lda.z return+2
    adc #0
    sta.z return+2
    lda.z return+3
    adc #0
    sta.z return+3
    // mul16u::@return
    // }
    // [16] return 
    rts
}
  // File Data

