Setting inferred volatile on symbol affected by address-of (byte**~) main::$0 ← & (byte*) screen
Setting inferred volatile on symbol affected by address-of (byte**~) main::$2 ← & (byte*) screen
Identified constant variable (byte*) screen1
Identified constant variable (byte*) screen2
Culled Empty Block (label) @1

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  (byte*) screen#0 ← ((byte*)) (number) $400
  (byte*) screen1#0 ← ((byte*)) (number) $400
  (byte*) screen2#0 ← ((byte*)) (number) $400+(number) $28
  to:@2
main: scope:[main]  from @2
  (byte*) screen#1 ← phi( @2/(byte*) screen#4 )
  (byte**~) main::$0 ← & (byte*) screen#1
  (byte**) setscreen::screen#0 ← (byte**~) main::$0
  (byte*) setscreen::val#0 ← (byte*) screen1#0
  call setscreen 
  to:main::@1
main::@1: scope:[main]  from main
  (byte*) screen#2 ← phi( main/(byte*) screen#1 )
  *((byte*) screen#2 + (number) 0) ← (byte) 'a'
  (byte**~) main::$2 ← & (byte*) screen#2
  (byte**) setscreen::screen#1 ← (byte**~) main::$2
  (byte*) setscreen::val#1 ← (byte*) screen2#0
  call setscreen 
  to:main::@2
main::@2: scope:[main]  from main::@1
  (byte*) screen#3 ← phi( main::@1/(byte*) screen#2 )
  *((byte*) screen#3 + (number) 0) ← (byte) 'a'
  to:main::@return
main::@return: scope:[main]  from main::@2
  return 
  to:@return
setscreen: scope:[setscreen]  from main main::@1
  (byte**) setscreen::screen#2 ← phi( main/(byte**) setscreen::screen#0 main::@1/(byte**) setscreen::screen#1 )
  (byte*) setscreen::val#2 ← phi( main/(byte*) setscreen::val#0 main::@1/(byte*) setscreen::val#1 )
  *((byte**) setscreen::screen#2) ← (byte*) setscreen::val#2
  to:setscreen::@return
setscreen::@return: scope:[setscreen]  from setscreen
  return 
  to:@return
@2: scope:[]  from @begin
  (byte*) screen#4 ← phi( @begin/(byte*) screen#0 )
  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
(void()) main()
(byte**~) main::$0
(byte**~) main::$2
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) screen
(byte*) screen#0
(byte*) screen#1
(byte*) screen#2
(byte*) screen#3
(byte*) screen#4
(byte*) screen1
(byte*) screen1#0
(byte*) screen2
(byte*) screen2#0
(void()) setscreen((byte**) setscreen::screen , (byte*) setscreen::val)
(label) setscreen::@return
(byte**) setscreen::screen
(byte**) setscreen::screen#0
(byte**) setscreen::screen#1
(byte**) setscreen::screen#2
(byte*) setscreen::val
(byte*) setscreen::val#0
(byte*) setscreen::val#1
(byte*) setscreen::val#2

Adding number conversion cast (unumber) 0 in *((byte*) screen#2 + (number) 0) ← (byte) 'a'
Adding number conversion cast (unumber) 0 in *((byte*) screen#3 + (number) 0) ← (byte) 'a'
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) screen#0 ← (byte*)(number) $400
Inlining cast (byte*) screen1#0 ← (byte*)(number) $400
Inlining cast (byte*) screen2#0 ← (byte*)(number) $400+(number) $28
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte**) setscreen::screen#0 = (byte**~) main::$0 
Alias (byte*) screen#1 = (byte*) screen#2 (byte*) screen#3 
Alias (byte**) setscreen::screen#1 = (byte**~) main::$2 
Alias (byte*) screen#0 = (byte*) screen#4 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte*) screen#1 (byte*) screen#0
Successful SSA optimization Pass2IdenticalPhiElimination
Constant right-side identified [2] (byte*) screen2#0 ← (byte*)(number) $400+(number) $28
Constant right-side identified [4] (byte**) setscreen::screen#0 ← & (byte*) screen#0
Constant right-side identified [10] (byte**) setscreen::screen#1 ← & (byte*) screen#0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) screen1#0 = (byte*) 1024
Constant (const byte*) screen2#0 = (byte*)$400+$28
Constant (const byte**) setscreen::screen#0 = &screen#0
Constant (const byte**) setscreen::screen#1 = &screen#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) setscreen::val#0 = screen1#0
Constant (const byte*) setscreen::val#1 = screen2#0
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero screen#0 in [9] *((byte*) screen#0 + (byte) 0) ← (byte) 'a'
Simplifying expression containing zero screen#0 in [15] *((byte*) screen#0 + (byte) 0) ← (byte) 'a'
Successful SSA optimization PassNSimplifyExpressionWithZero
Inlining constant with var siblings (const byte**) setscreen::screen#0
Inlining constant with var siblings (const byte**) setscreen::screen#1
Inlining constant with var siblings (const byte*) setscreen::val#0
Inlining constant with var siblings (const byte*) setscreen::val#1
Constant inlined setscreen::screen#0 = &(byte*) screen#0
Constant inlined setscreen::val#1 = (const byte*) screen2#0
Constant inlined setscreen::screen#1 = &(byte*) screen#0
Constant inlined setscreen::val#0 = (const byte*) screen1#0
Successful SSA optimization Pass2ConstantInlining
Identical Phi Values (byte**) setscreen::screen#2 &(byte*) screen#0
Successful SSA optimization Pass2IdenticalPhiElimination
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 setscreen:6 setscreen:8 

Created 1 initial phi equivalence classes
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Renumbering block @2 to @1
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] (byte*) screen#0 ← (byte*) 1024
  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 setscreen 
  to:main::@1
main::@1: scope:[main]  from main
  [6] *((byte*) screen#0) ← (byte) 'a'
  [7] call setscreen 
  to:main::@2
main::@2: scope:[main]  from main::@1
  [8] *((byte*) screen#0) ← (byte) 'a'
  to:main::@return
main::@return: scope:[main]  from main::@2
  [9] return 
  to:@return
setscreen: scope:[setscreen]  from main main::@1
  [10] (byte*) setscreen::val#2 ← phi( main/(const byte*) screen1#0 main::@1/(const byte*) screen2#0 )
  [11] *(&(byte*) screen#0) ← (byte*) setscreen::val#2
  to:setscreen::@return
setscreen::@return: scope:[setscreen]  from setscreen
  [12] return 
  to:@return


VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) screen
(byte*) screen#0 0.6666666666666666
(byte*) screen1
(byte*) screen2
(void()) setscreen((byte**) setscreen::screen , (byte*) setscreen::val)
(byte**) setscreen::screen
(byte*) setscreen::val
(byte*) setscreen::val#2 2.0

Initial phi equivalence classes
[ setscreen::val#2 ]
Complete equivalence classes
[ setscreen::val#2 ]
[ screen#0 ]
Allocated zp ZP_WORD:2 [ setscreen::val#2 ]
Allocated zp ZP_WORD:4 [ screen#0 ]

INITIAL ASM
Target platform is c64basic
  // File Comments
// Tests pointer to pointer in a more complex setup
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label screen1 = $400
  .label screen2 = $400+$28
  .label screen = 4
  // @begin
bbegin:
  // [0] (byte*) screen#0 ← (byte*) 1024 -- pbuz1=pbuc1 
  lda #<$400
  sta.z screen
  lda #>$400
  sta.z screen+1
  // [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: {
    // [5] call setscreen 
    // [10] phi from main to setscreen [phi:main->setscreen]
  setscreen_from_main:
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen1#0 [phi:main->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen1
    sta.z setscreen.val
    lda #>screen1
    sta.z setscreen.val+1
    jsr setscreen
    jmp b1
    // main::@1
  b1:
    // [6] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    // [7] call setscreen 
    // [10] phi from main::@1 to setscreen [phi:main::@1->setscreen]
  setscreen_from_b1:
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen2#0 [phi:main::@1->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen2
    sta.z setscreen.val
    lda #>screen2
    sta.z setscreen.val+1
    jsr setscreen
    jmp b2
    // main::@2
  b2:
    // [8] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    jmp breturn
    // main::@return
  breturn:
    // [9] return 
    rts
}
  // setscreen
// setscreen(byte* zeropage(2) val)
setscreen: {
    .label val = 2
    // [11] *(&(byte*) screen#0) ← (byte*) setscreen::val#2 -- _deref_pptc1=pbuz1 
    lda.z val
    sta screen
    lda.z val+1
    sta screen+1
    jmp breturn
    // setscreen::@return
  breturn:
    // [12] return 
    rts
}
  // File Data

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte*) screen#0 ← (byte*) 1024 [ screen#0 ] (  [ screen#0 ] ) always clobbers reg byte a 
Statement [6] *((byte*) screen#0) ← (byte) 'a' [ screen#0 ] ( main:2 [ screen#0 ] ) always clobbers reg byte a reg byte y 
Statement [8] *((byte*) screen#0) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte y 
Statement [11] *(&(byte*) screen#0) ← (byte*) setscreen::val#2 [ screen#0 ] ( main:2::setscreen:5 [ screen#0 ] main:2::setscreen:7 [ screen#0 ] ) always clobbers reg byte a 
Potential registers zp ZP_WORD:2 [ setscreen::val#2 ] : zp ZP_WORD:2 , 
Potential registers zp ZP_WORD:4 [ screen#0 ] : zp ZP_WORD:4 , 

REGISTER UPLIFT SCOPES
Uplift Scope [setscreen] 2: zp ZP_WORD:2 [ setscreen::val#2 ] 
Uplift Scope [] 0.67: zp ZP_WORD:4 [ screen#0 ] 
Uplift Scope [main] 

Uplifting [setscreen] best 112 combination zp ZP_WORD:2 [ setscreen::val#2 ] 
Uplifting [] best 112 combination zp ZP_WORD:4 [ screen#0 ] 
Uplifting [main] best 112 combination 

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Tests pointer to pointer in a more complex setup
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label screen1 = $400
  .label screen2 = $400+$28
  .label screen = 4
  // @begin
bbegin:
  // [0] (byte*) screen#0 ← (byte*) 1024 -- pbuz1=pbuc1 
  lda #<$400
  sta.z screen
  lda #>$400
  sta.z screen+1
  // [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: {
    // [5] call setscreen 
    // [10] phi from main to setscreen [phi:main->setscreen]
  setscreen_from_main:
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen1#0 [phi:main->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen1
    sta.z setscreen.val
    lda #>screen1
    sta.z setscreen.val+1
    jsr setscreen
    jmp b1
    // main::@1
  b1:
    // [6] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    // [7] call setscreen 
    // [10] phi from main::@1 to setscreen [phi:main::@1->setscreen]
  setscreen_from_b1:
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen2#0 [phi:main::@1->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen2
    sta.z setscreen.val
    lda #>screen2
    sta.z setscreen.val+1
    jsr setscreen
    jmp b2
    // main::@2
  b2:
    // [8] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    jmp breturn
    // main::@return
  breturn:
    // [9] return 
    rts
}
  // setscreen
// setscreen(byte* zeropage(2) val)
setscreen: {
    .label val = 2
    // [11] *(&(byte*) screen#0) ← (byte*) setscreen::val#2 -- _deref_pptc1=pbuz1 
    lda.z val
    sta screen
    lda.z val+1
    sta screen+1
    jmp breturn
    // setscreen::@return
  breturn:
    // [12] 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 main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b1:
Removing instruction bend:
Removing instruction setscreen_from_main:
Removing instruction b1:
Removing instruction setscreen_from_b1:
Removing instruction b2:
Removing instruction breturn:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block 
Succesful ASM optimization Pass5AddMainRts

FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) screen
(byte*) screen#0 screen zp ZP_WORD:4 0.6666666666666666
(byte*) screen1
(const byte*) screen1#0 screen1 = (byte*) 1024
(byte*) screen2
(const byte*) screen2#0 screen2 = (byte*)(number) $400+(number) $28
(void()) setscreen((byte**) setscreen::screen , (byte*) setscreen::val)
(label) setscreen::@return
(byte**) setscreen::screen
(byte*) setscreen::val
(byte*) setscreen::val#2 val zp ZP_WORD:2 2.0

zp ZP_WORD:2 [ setscreen::val#2 ]
zp ZP_WORD:4 [ screen#0 ]


FINAL ASSEMBLER
Score: 100

  // File Comments
// Tests pointer to pointer in a more complex setup
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label screen1 = $400
  .label screen2 = $400+$28
  .label screen = 4
  // @begin
bbegin:
  // screen = $400
  // [0] (byte*) screen#0 ← (byte*) 1024 -- pbuz1=pbuc1 
  lda #<$400
  sta.z screen
  lda #>$400
  sta.z screen+1
  // [1] phi from @begin to @1 [phi:@begin->@1]
  // @1
  // [2] call main 
  // [4] phi from @1 to main [phi:@1->main]
  jsr main
  rts
  // [3] phi from @1 to @end [phi:@1->@end]
  // @end
  // main
main: {
    // setscreen(&screen, screen1)
    // [5] call setscreen 
    // [10] phi from main to setscreen [phi:main->setscreen]
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen1#0 [phi:main->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen1
    sta.z setscreen.val
    lda #>screen1
    sta.z setscreen.val+1
    jsr setscreen
    // main::@1
    // screen[0] = 'a'
    // [6] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    // setscreen(&screen, screen2)
    // [7] call setscreen 
    // [10] phi from main::@1 to setscreen [phi:main::@1->setscreen]
    // [10] phi (byte*) setscreen::val#2 = (const byte*) screen2#0 [phi:main::@1->setscreen#0] -- pbuz1=pbuc1 
    lda #<screen2
    sta.z setscreen.val
    lda #>screen2
    sta.z setscreen.val+1
    jsr setscreen
    // main::@2
    // screen[0] = 'a'
    // [8] *((byte*) screen#0) ← (byte) 'a' -- _deref_pbuz1=vbuc1 
    lda #'a'
    ldy #0
    sta (screen),y
    // main::@return
    // }
    // [9] return 
    rts
}
  // setscreen
// setscreen(byte* zeropage(2) val)
setscreen: {
    .label val = 2
    // *screen = val
    // [11] *(&(byte*) screen#0) ← (byte*) setscreen::val#2 -- _deref_pptc1=pbuz1 
    lda.z val
    sta screen
    lda.z val+1
    sta screen+1
    // setscreen::@return
    // }
    // [12] return 
    rts
}
  // File Data

