Resolved forward reference irq to interrupt(KERNEL_MIN)(void()) irq()
Resolved forward reference framedone to (bool) framedone
Culled Empty Block (label) main::@5
Culled Empty Block (label) main::@3
Culled Empty Block (label) main::@6
Culled Empty Block (label) main::@4
Culled Empty Block (label) main::@8

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  (void()**) KERNEL_IRQ#0 ← ((void()**)) (number) $314
  (byte*) RASTER#0 ← ((byte*)) (number) $d012
  (byte*) VIC_CONTROL#0 ← ((byte*)) (number) $d011
  (byte*) IRQ_STATUS#0 ← ((byte*)) (number) $d019
  (byte*) IRQ_ENABLE#0 ← ((byte*)) (number) $d01a
  (byte) IRQ_RASTER#0 ← (number) 1
  (byte*) BGCOL#0 ← ((byte*)) (number) $d020
  (byte*) CIA1_INTERRUPT#0 ← ((byte*)) (number) $dc0d
  (byte) CIA_INTERRUPT_CLEAR#0 ← (number) $7f
  to:@1
main: scope:[main]  from @2
  (bool) framedone#12 ← phi( @2/(bool) framedone#11 )
  asm { sei  }
  *((byte*) CIA1_INTERRUPT#0) ← (byte) CIA_INTERRUPT_CLEAR#0
  *((byte*) VIC_CONTROL#0) ← *((byte*) VIC_CONTROL#0) & (number) $7f
  *((byte*) RASTER#0) ← (number) $fd
  *((byte*) IRQ_ENABLE#0) ← (byte) IRQ_RASTER#0
  (void()*~) main::$0 ← & interrupt(KERNEL_MIN)(void()) irq()
  *((void()**) KERNEL_IRQ#0) ← (void()*~) main::$0
  asm { cli  }
  to:main::@1
main::@1: scope:[main]  from main main::@2 main::@7
  (bool) framedone#9 ← phi( main/(bool) framedone#12 main::@2/(bool) framedone#13 main::@7/(bool) framedone#0 )
  if(true) goto main::@2
  to:main::@return
main::@2: scope:[main]  from main::@1
  (bool) framedone#13 ← phi( main::@1/(bool) framedone#9 )
  (bool~) main::$1 ← *((byte*) RASTER#0) < (number) $14
  (bool~) main::$2 ← ! (bool~) main::$1
  if((bool~) main::$2) goto main::@1
  to:main::@7
main::@7: scope:[main]  from main::@2
  (bool) framedone#0 ← true
  to:main::@1
main::@return: scope:[main]  from main::@1
  (bool) framedone#6 ← phi( main::@1/(bool) framedone#9 )
  (bool) framedone#1 ← (bool) framedone#6
  return 
  to:@return
@1: scope:[]  from @begin
  (bool) framedone#2 ← false
  to:@2
irq: scope:[irq]  from
  (bool) framedone#14 ← phi( @2/(bool) framedone#11 )
  *((byte*) BGCOL#0) ← ++ *((byte*) BGCOL#0)
  *((byte*) IRQ_STATUS#0) ← (byte) IRQ_RASTER#0
  (bool~) irq::$0 ← *((byte*) RASTER#0) > (number) $32
  (bool~) irq::$1 ← ! (bool~) irq::$0
  if((bool~) irq::$1) goto irq::@1
  to:irq::@2
irq::@1: scope:[irq]  from irq irq::@2
  (bool) framedone#10 ← phi( irq/(bool) framedone#14 irq::@2/(bool) framedone#3 )
  *((byte*) BGCOL#0) ← -- *((byte*) BGCOL#0)
  to:irq::@return
irq::@2: scope:[irq]  from irq
  (bool) framedone#3 ← false
  to:irq::@1
irq::@return: scope:[irq]  from irq::@1
  (bool) framedone#7 ← phi( irq::@1/(bool) framedone#10 )
  (bool) framedone#4 ← (bool) framedone#7
  return 
  to:@return
@2: scope:[]  from @1
  (bool) framedone#11 ← phi( @1/(bool) framedone#2 )
  call main 
  to:@3
@3: scope:[]  from @2
  (bool) framedone#8 ← phi( @2/(bool) framedone#1 )
  (bool) framedone#5 ← (bool) framedone#8
  to:@end
@end: scope:[]  from @3

SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(byte*) BGCOL
(byte*) BGCOL#0
(byte*) CIA1_INTERRUPT
(byte*) CIA1_INTERRUPT#0
(byte) CIA_INTERRUPT_CLEAR
(byte) CIA_INTERRUPT_CLEAR#0
(byte*) IRQ_ENABLE
(byte*) IRQ_ENABLE#0
(byte) IRQ_RASTER
(byte) IRQ_RASTER#0
(byte*) IRQ_STATUS
(byte*) IRQ_STATUS#0
(void()**) KERNEL_IRQ
(void()**) KERNEL_IRQ#0
(byte*) RASTER
(byte*) RASTER#0
(byte*) VIC_CONTROL
(byte*) VIC_CONTROL#0
(bool) framedone
(bool) framedone#0
(bool) framedone#1
(bool) framedone#10
(bool) framedone#11
(bool) framedone#12
(bool) framedone#13
(bool) framedone#14
(bool) framedone#2
(bool) framedone#3
(bool) framedone#4
(bool) framedone#5
(bool) framedone#6
(bool) framedone#7
(bool) framedone#8
(bool) framedone#9
interrupt(KERNEL_MIN)(void()) irq()
(bool~) irq::$0
(bool~) irq::$1
(label) irq::@1
(label) irq::@2
(label) irq::@return
(void()) main()
(void()*~) main::$0
(bool~) main::$1
(bool~) main::$2
(label) main::@1
(label) main::@2
(label) main::@7
(label) main::@return

Adding number conversion cast (unumber) 1 in (byte) IRQ_RASTER#0 ← (number) 1
Adding number conversion cast (unumber) $7f in (byte) CIA_INTERRUPT_CLEAR#0 ← (number) $7f
Adding number conversion cast (unumber) $7f in *((byte*) VIC_CONTROL#0) ← *((byte*) VIC_CONTROL#0) & (number) $7f
Adding number conversion cast (unumber) $fd in *((byte*) RASTER#0) ← (number) $fd
Adding number conversion cast (unumber) $14 in (bool~) main::$1 ← *((byte*) RASTER#0) < (number) $14
Adding number conversion cast (unumber) $32 in (bool~) irq::$0 ← *((byte*) RASTER#0) > (number) $32
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (void()**) KERNEL_IRQ#0 ← (void()**)(number) $314
Inlining cast (byte*) RASTER#0 ← (byte*)(number) $d012
Inlining cast (byte*) VIC_CONTROL#0 ← (byte*)(number) $d011
Inlining cast (byte*) IRQ_STATUS#0 ← (byte*)(number) $d019
Inlining cast (byte*) IRQ_ENABLE#0 ← (byte*)(number) $d01a
Inlining cast (byte) IRQ_RASTER#0 ← (unumber)(number) 1
Inlining cast (byte*) BGCOL#0 ← (byte*)(number) $d020
Inlining cast (byte*) CIA1_INTERRUPT#0 ← (byte*)(number) $dc0d
Inlining cast (byte) CIA_INTERRUPT_CLEAR#0 ← (unumber)(number) $7f
Inlining cast *((byte*) RASTER#0) ← (unumber)(number) $fd
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (void()**) 788
Simplifying constant pointer cast (byte*) 53266
Simplifying constant pointer cast (byte*) 53265
Simplifying constant pointer cast (byte*) 53273
Simplifying constant pointer cast (byte*) 53274
Simplifying constant integer cast 1
Simplifying constant pointer cast (byte*) 53280
Simplifying constant pointer cast (byte*) 56333
Simplifying constant integer cast $7f
Simplifying constant integer cast $7f
Simplifying constant integer cast $fd
Simplifying constant integer cast $14
Simplifying constant integer cast $32
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) $7f
Finalized unsigned number type (byte) $7f
Finalized unsigned number type (byte) $fd
Finalized unsigned number type (byte) $14
Finalized unsigned number type (byte) $32
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inversing boolean not [22] (bool~) main::$2 ← *((byte*) RASTER#0) >= (byte) $14 from [21] (bool~) main::$1 ← *((byte*) RASTER#0) < (byte) $14
Inversing boolean not [33] (bool~) irq::$1 ← *((byte*) RASTER#0) <= (byte) $32 from [32] (bool~) irq::$0 ← *((byte*) RASTER#0) > (byte) $32
Successful SSA optimization Pass2UnaryNotSimplification
Alias (bool) framedone#1 = (bool) framedone#13 (bool) framedone#9 (bool) framedone#6 
Alias (bool) framedone#10 = (bool) framedone#7 (bool) framedone#4 
Alias (bool) framedone#11 = (bool) framedone#2 
Alias (bool) framedone#5 = (bool) framedone#8 
Successful SSA optimization Pass2AliasElimination
Self Phi Eliminated (bool) framedone#1
Successful SSA optimization Pass2SelfPhiElimination
Identical Phi Values (bool) framedone#12 (bool) framedone#11
Identical Phi Values (bool) framedone#14 (bool) framedone#11
Identical Phi Values (bool) framedone#5 (bool) framedone#1
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$2 [23] if(*((byte*) RASTER#0)>=(byte) $14) goto main::@1
Simple Condition (bool~) irq::$1 [34] if(*((byte*) RASTER#0)<=(byte) $32) goto irq::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [15] (void()*~) main::$0 ← & interrupt(KERNEL_MIN)(void()) irq()
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const void()**) KERNEL_IRQ#0 = (void()**) 788
Constant (const byte*) RASTER#0 = (byte*) 53266
Constant (const byte*) VIC_CONTROL#0 = (byte*) 53265
Constant (const byte*) IRQ_STATUS#0 = (byte*) 53273
Constant (const byte*) IRQ_ENABLE#0 = (byte*) 53274
Constant (const byte) IRQ_RASTER#0 = 1
Constant (const byte*) BGCOL#0 = (byte*) 53280
Constant (const byte*) CIA1_INTERRUPT#0 = (byte*) 56333
Constant (const byte) CIA_INTERRUPT_CLEAR#0 = $7f
Constant (const void()*) main::$0 = &irq
Successful SSA optimization Pass2ConstantIdentification
if() condition always true - replacing block destination [19] if(true) goto main::@2
Successful SSA optimization Pass2ConstantIfs
Rewriting conditional comparison [34] if(*((const byte*) RASTER#0)<=(byte) $32) goto irq::@1
Removing unused block main::@return
Successful SSA optimization Pass2EliminateUnusedBlocks
Adding number conversion cast (unumber) $32+1 in if(*((const byte*) RASTER#0)<(byte) $32+(number) 1) goto irq::@1
Adding number conversion cast (unumber) 1 in if(*((const byte*) RASTER#0)<(unumber)(byte) $32+(number) 1) goto irq::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast (byte) $32+(unumber)(number) 1
Simplifying constant integer cast 1
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 1
Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant inlined main::$0 = &interrupt(KERNEL_MIN)(void()) irq()
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting irq::@3(between irq and irq::@1)
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:3 

Created 2 initial phi equivalence classes
Coalesced [13] framedone#15 ← framedone#11
Coalesced [17] framedone#16 ← framedone#0
Coalesced [22] framedone#18 ← framedone#3
Coalesced [26] framedone#17 ← framedone#11
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) irq::@3
Renumbering block main::@7 to main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end

FINAL CONTROL FLOW GRAPH
@begin: scope:[]  from
  [0] phi()
  to:@1
@1: scope:[]  from @begin
  [1] (bool) framedone#11 ← false
  to:@2
@2: scope:[]  from @1
  [2] phi()
  [3] call main 
  to:@end
@end: scope:[]  from @2
  [4] phi()
main: scope:[main]  from @2
  asm { sei  }
  [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0
  [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f
  [8] *((const byte*) RASTER#0) ← (byte) $fd
  [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0
  [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq()
  asm { cli  }
  to:main::@1
main::@1: scope:[main]  from main main::@2 main::@3
  [12] (bool) framedone#1 ← phi( main/(bool) framedone#11 main::@3/(bool) framedone#0 )
  to:main::@2
main::@2: scope:[main]  from main::@1
  [13] if(*((const byte*) RASTER#0)>=(byte) $14) goto main::@1
  to:main::@3
main::@3: scope:[main]  from main::@2
  [14] (bool) framedone#0 ← true
  to:main::@1
irq: scope:[irq]  from
  [15] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0)
  [16] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
  [17] if(*((const byte*) RASTER#0)<(byte) $32+(byte) 1) goto irq::@1
  to:irq::@2
irq::@2: scope:[irq]  from irq
  [18] (bool) framedone#3 ← false
  to:irq::@1
irq::@1: scope:[irq]  from irq irq::@2
  [19] (bool) framedone#10 ← phi( irq/(bool) framedone#11 irq::@2/(bool) framedone#3 )
  [20] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0)
  to:irq::@return
irq::@return: scope:[irq]  from irq::@1
  [21] return 
  to:@return


VARIABLE REGISTER WEIGHTS
(byte*) BGCOL
(byte*) CIA1_INTERRUPT
(byte) CIA_INTERRUPT_CLEAR
(byte*) IRQ_ENABLE
(byte) IRQ_RASTER
(byte*) IRQ_STATUS
(void()**) KERNEL_IRQ
(byte*) RASTER
(byte*) VIC_CONTROL
(bool) framedone
(bool) framedone#0 22.0
(bool) framedone#1 130.0
(bool) framedone#10 40.0
(bool) framedone#11 0.5
(bool) framedone#3 4.0
interrupt(KERNEL_MIN)(void()) irq()
(void()) main()

Initial phi equivalence classes
[ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ]
Complete equivalence classes
[ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ]
Allocated zp ZP_BOOL:2 [ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ]

INITIAL ASM
  // File Comments
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
// because it is assigned to the A register
  // Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label KERNEL_IRQ = $314
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  .label IRQ_STATUS = $d019
  .label IRQ_ENABLE = $d01a
  .const IRQ_RASTER = 1
  .label BGCOL = $d020
  .label CIA1_INTERRUPT = $dc0d
  .const CIA_INTERRUPT_CLEAR = $7f
  .label framedone = 2
  // @begin
bbegin:
  jmp b1
  // @1
b1:
  // [1] (bool) framedone#11 ← false -- vboz1=vboc1 
  lda #0
  sta framedone
  // [2] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
  jmp b2
  // @2
b2:
  // [3] call main 
  jsr main
  // [4] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
  jmp bend
  // @end
bend:
  // main
main: {
    // asm { sei  }
    sei
    // [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2 
    // Disable CIA 1 Timer IRQ
    lda #CIA_INTERRUPT_CLEAR
    sta CIA1_INTERRUPT
    // [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Set raster line to $0fd
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // [8] *((const byte*) RASTER#0) ← (byte) $fd -- _deref_pbuc1=vbuc2 
    lda #$fd
    sta RASTER
    // [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Enable Raster Interrupt
    lda #IRQ_RASTER
    sta IRQ_ENABLE
    // [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 
    // Set the IRQ routine
    lda #<irq
    sta KERNEL_IRQ
    lda #>irq
    sta KERNEL_IRQ+1
    // asm { cli  }
    cli
    // [12] phi from main main::@3 to main::@1 [phi:main/main::@3->main::@1]
  b1_from_main:
  b1_from_b3:
    // [12] phi (bool) framedone#1 = (bool) framedone#11 [phi:main/main::@3->main::@1#0] -- register_copy 
    jmp b1
    // [12] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
  b1_from_b2:
    jmp b1
    // main::@1
  b1:
    jmp b2
    // main::@2
  b2:
    // [13] if(*((const byte*) RASTER#0)>=(byte) $14) goto main::@1 -- _deref_pbuc1_ge_vbuc2_then_la1 
    lda RASTER
    cmp #$14
    bcs b1_from_b2
    jmp b3
    // main::@3
  b3:
    // [14] (bool) framedone#0 ← true -- vboz1=vboc1 
    lda #1
    sta framedone
    jmp b1_from_b3
}
  // irq
irq: {
    // entry interrupt(KERNEL_MIN)
    // [15] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1 
    inc BGCOL
    // [16] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [17] if(*((const byte*) RASTER#0)<(byte) $32+(byte) 1) goto irq::@1 -- _deref_pbuc1_lt_vbuc2_then_la1 
    lda RASTER
    cmp #$32+1
    bcc b1_from_irq
    jmp b2
    // irq::@2
  b2:
    // [18] (bool) framedone#3 ← false -- vboz1=vboc1 
    lda #0
    sta framedone
    // [19] phi from irq irq::@2 to irq::@1 [phi:irq/irq::@2->irq::@1]
  b1_from_irq:
  b1_from_b2:
    // [19] phi (bool) framedone#10 = (bool) framedone#11 [phi:irq/irq::@2->irq::@1#0] -- register_copy 
    jmp b1
    // irq::@1
  b1:
    // [20] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1 
    dec BGCOL
    jmp breturn
    // irq::@return
  breturn:
    // [21] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
}
  // File Data

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (bool) framedone#11 ← false [ framedone#11 ] (  [ framedone#11 ] ) always clobbers reg byte a 
Statement [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 [ framedone#11 ] ( main:3 [ framedone#11 ] ) always clobbers reg byte a 
Statement [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f [ framedone#11 ] ( main:3 [ framedone#11 ] ) always clobbers reg byte a 
Statement [8] *((const byte*) RASTER#0) ← (byte) $fd [ framedone#11 ] ( main:3 [ framedone#11 ] ) always clobbers reg byte a 
Statement [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 [ framedone#11 ] ( main:3 [ framedone#11 ] ) always clobbers reg byte a 
Statement [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() [ framedone#11 ] ( main:3 [ framedone#11 ] ) always clobbers reg byte a 
Statement [13] if(*((const byte*) RASTER#0)>=(byte) $14) goto main::@1 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [14] (bool) framedone#0 ← true [ framedone#0 ] ( main:3 [ framedone#0 ] ) always clobbers reg byte a 
Statement [16] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ framedone#11 ] (  [ framedone#11 ] ) always clobbers reg byte a 
Statement [17] if(*((const byte*) RASTER#0)<(byte) $32+(byte) 1) goto irq::@1 [ framedone#11 ] (  [ framedone#11 ] ) always clobbers reg byte a 
Statement [18] (bool) framedone#3 ← false [ framedone#3 ] (  [ framedone#3 ] ) always clobbers reg byte a 
Potential registers zp ZP_BOOL:2 [ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ] : zp ZP_BOOL:2 , 

REGISTER UPLIFT SCOPES
Uplift Scope [] 196.5: zp ZP_BOOL:2 [ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ] 
Uplift Scope [main] 
Uplift Scope [irq] 

Uplifting [] best 1994 combination zp ZP_BOOL:2 [ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ] 
Uplifting [main] best 1994 combination 
Uplifting [irq] best 1994 combination 

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
// because it is assigned to the A register
  // Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label KERNEL_IRQ = $314
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  .label IRQ_STATUS = $d019
  .label IRQ_ENABLE = $d01a
  .const IRQ_RASTER = 1
  .label BGCOL = $d020
  .label CIA1_INTERRUPT = $dc0d
  .const CIA_INTERRUPT_CLEAR = $7f
  .label framedone = 2
  // @begin
bbegin:
  jmp b1
  // @1
b1:
  // [1] (bool) framedone#11 ← false -- vboz1=vboc1 
  lda #0
  sta framedone
  // [2] phi from @1 to @2 [phi:@1->@2]
b2_from_b1:
  jmp b2
  // @2
b2:
  // [3] call main 
  jsr main
  // [4] phi from @2 to @end [phi:@2->@end]
bend_from_b2:
  jmp bend
  // @end
bend:
  // main
main: {
    // asm { sei  }
    sei
    // [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2 
    // Disable CIA 1 Timer IRQ
    lda #CIA_INTERRUPT_CLEAR
    sta CIA1_INTERRUPT
    // [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Set raster line to $0fd
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // [8] *((const byte*) RASTER#0) ← (byte) $fd -- _deref_pbuc1=vbuc2 
    lda #$fd
    sta RASTER
    // [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Enable Raster Interrupt
    lda #IRQ_RASTER
    sta IRQ_ENABLE
    // [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 
    // Set the IRQ routine
    lda #<irq
    sta KERNEL_IRQ
    lda #>irq
    sta KERNEL_IRQ+1
    // asm { cli  }
    cli
    // [12] phi from main main::@3 to main::@1 [phi:main/main::@3->main::@1]
  b1_from_main:
  b1_from_b3:
    // [12] phi (bool) framedone#1 = (bool) framedone#11 [phi:main/main::@3->main::@1#0] -- register_copy 
    jmp b1
    // [12] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
  b1_from_b2:
    jmp b1
    // main::@1
  b1:
    jmp b2
    // main::@2
  b2:
    // [13] if(*((const byte*) RASTER#0)>=(byte) $14) goto main::@1 -- _deref_pbuc1_ge_vbuc2_then_la1 
    lda RASTER
    cmp #$14
    bcs b1_from_b2
    jmp b3
    // main::@3
  b3:
    // [14] (bool) framedone#0 ← true -- vboz1=vboc1 
    lda #1
    sta framedone
    jmp b1_from_b3
}
  // irq
irq: {
    // entry interrupt(KERNEL_MIN)
    // [15] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1 
    inc BGCOL
    // [16] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [17] if(*((const byte*) RASTER#0)<(byte) $32+(byte) 1) goto irq::@1 -- _deref_pbuc1_lt_vbuc2_then_la1 
    lda RASTER
    cmp #$32+1
    bcc b1_from_irq
    jmp b2
    // irq::@2
  b2:
    // [18] (bool) framedone#3 ← false -- vboz1=vboc1 
    lda #0
    sta framedone
    // [19] phi from irq irq::@2 to irq::@1 [phi:irq/irq::@2->irq::@1]
  b1_from_irq:
  b1_from_b2:
    // [19] phi (bool) framedone#10 = (bool) framedone#11 [phi:irq/irq::@2->irq::@1#0] -- register_copy 
    jmp b1
    // irq::@1
  b1:
    // [20] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1 
    dec BGCOL
    jmp breturn
    // irq::@return
  breturn:
    // [21] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp b3
Removing instruction jmp b2
Removing instruction jmp b1
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1 with b2
Replacing label b1_from_b2 with b2
Replacing label b1_from_irq with b1
Removing instruction b1:
Removing instruction b2_from_b1:
Removing instruction bend_from_b2:
Removing instruction b1_from_main:
Removing instruction b1_from_b2:
Removing instruction b1:
Removing instruction b1_from_irq:
Removing instruction b1_from_b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction b3:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Skipping double jump to b2 in jmp b1_from_b3
Succesful ASM optimization Pass5DoubleJumpElimination
Relabelling long label b1_from_b3 to b1
Succesful ASM optimization Pass5RelabelLongLabels
Adding RTS to root block 
Succesful ASM optimization Pass5AddMainRts
Removing instruction jmp b2
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1:
Succesful ASM optimization Pass5RedundantLabelElimination

FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(byte*) BGCOL
(const byte*) BGCOL#0 BGCOL = (byte*) 53280
(byte*) CIA1_INTERRUPT
(const byte*) CIA1_INTERRUPT#0 CIA1_INTERRUPT = (byte*) 56333
(byte) CIA_INTERRUPT_CLEAR
(const byte) CIA_INTERRUPT_CLEAR#0 CIA_INTERRUPT_CLEAR = (byte) $7f
(byte*) IRQ_ENABLE
(const byte*) IRQ_ENABLE#0 IRQ_ENABLE = (byte*) 53274
(byte) IRQ_RASTER
(const byte) IRQ_RASTER#0 IRQ_RASTER = (byte) 1
(byte*) IRQ_STATUS
(const byte*) IRQ_STATUS#0 IRQ_STATUS = (byte*) 53273
(void()**) KERNEL_IRQ
(const void()**) KERNEL_IRQ#0 KERNEL_IRQ = (void()**) 788
(byte*) RASTER
(const byte*) RASTER#0 RASTER = (byte*) 53266
(byte*) VIC_CONTROL
(const byte*) VIC_CONTROL#0 VIC_CONTROL = (byte*) 53265
(bool) framedone
(bool) framedone#0 framedone zp ZP_BOOL:2 22.0
(bool) framedone#1 framedone zp ZP_BOOL:2 130.0
(bool) framedone#10 framedone zp ZP_BOOL:2 40.0
(bool) framedone#11 framedone zp ZP_BOOL:2 0.5
(bool) framedone#3 framedone zp ZP_BOOL:2 4.0
interrupt(KERNEL_MIN)(void()) irq()
(label) irq::@1
(label) irq::@2
(label) irq::@return
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3

zp ZP_BOOL:2 [ framedone#10 framedone#1 framedone#11 framedone#0 framedone#3 ]


FINAL ASSEMBLER
Score: 1025

  // File Comments
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
// because it is assigned to the A register
  // Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label KERNEL_IRQ = $314
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  .label IRQ_STATUS = $d019
  .label IRQ_ENABLE = $d01a
  .const IRQ_RASTER = 1
  .label BGCOL = $d020
  .label CIA1_INTERRUPT = $dc0d
  .const CIA_INTERRUPT_CLEAR = $7f
  .label framedone = 2
  // @begin
bbegin:
  // @1
  // framedone = false
  // [1] (bool) framedone#11 ← false -- vboz1=vboc1 
  lda #0
  sta framedone
  // [2] phi from @1 to @2 [phi:@1->@2]
  // @2
  // [3] call main 
  jsr main
  rts
  // [4] phi from @2 to @end [phi:@2->@end]
  // @end
  // main
main: {
    // asm
    // asm { sei  }
    sei
    // *CIA1_INTERRUPT = CIA_INTERRUPT_CLEAR
    // [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 -- _deref_pbuc1=vbuc2 
    // Disable CIA 1 Timer IRQ
    lda #CIA_INTERRUPT_CLEAR
    sta CIA1_INTERRUPT
    // *VIC_CONTROL &=$7f
    // [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Set raster line to $0fd
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // *RASTER = $fd
    // [8] *((const byte*) RASTER#0) ← (byte) $fd -- _deref_pbuc1=vbuc2 
    lda #$fd
    sta RASTER
    // *IRQ_ENABLE = IRQ_RASTER
    // [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Enable Raster Interrupt
    lda #IRQ_RASTER
    sta IRQ_ENABLE
    // *KERNEL_IRQ = &irq
    // [10] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 
    // Set the IRQ routine
    lda #<irq
    sta KERNEL_IRQ
    lda #>irq
    sta KERNEL_IRQ+1
    // asm
    // asm { cli  }
    cli
    // [12] phi from main main::@3 to main::@1 [phi:main/main::@3->main::@1]
    // [12] phi (bool) framedone#1 = (bool) framedone#11 [phi:main/main::@3->main::@1#0] -- register_copy 
    // [12] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
    // main::@1
    // main::@2
  b2:
    // if(*RASTER<20)
    // [13] if(*((const byte*) RASTER#0)>=(byte) $14) goto main::@1 -- _deref_pbuc1_ge_vbuc2_then_la1 
    lda RASTER
    cmp #$14
    bcs b2
    // main::@3
    // framedone = true
    // [14] (bool) framedone#0 ← true -- vboz1=vboc1 
    lda #1
    sta framedone
    jmp b2
}
  // irq
irq: {
    // entry interrupt(KERNEL_MIN)
    // (*BGCOL)++;
    // [15] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1 
    inc BGCOL
    // *IRQ_STATUS = IRQ_RASTER
    // [16] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // if (*RASTER>50)
    // [17] if(*((const byte*) RASTER#0)<(byte) $32+(byte) 1) goto irq::@1 -- _deref_pbuc1_lt_vbuc2_then_la1 
    lda RASTER
    cmp #$32+1
    bcc b1
    // irq::@2
    // framedone = false
    // [18] (bool) framedone#3 ← false -- vboz1=vboc1 
    lda #0
    sta framedone
    // [19] phi from irq irq::@2 to irq::@1 [phi:irq/irq::@2->irq::@1]
    // [19] phi (bool) framedone#10 = (bool) framedone#11 [phi:irq/irq::@2->irq::@1#0] -- register_copy 
    // irq::@1
  b1:
    // (*BGCOL)--;
    // [20] *((const byte*) BGCOL#0) ← -- *((const byte*) BGCOL#0) -- _deref_pbuc1=_dec__deref_pbuc1 
    dec BGCOL
    // irq::@return
    // }
    // [21] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
}
  // File Data

