Resolved forward reference table_driven_irq to interrupt(KERNEL_MIN)(void()) table_driven_irq()
Inlined call (byte~) vicSelectGfxBank::$0 ← call toDd00 (byte*) vicSelectGfxBank::gfx 
Culled Empty Block (label) @1
Culled Empty Block (label) @2
Culled Empty Block (label) @3
Culled Empty Block (label) table_driven_irq::@4
Culled Empty Block (label) table_driven_irq::@5
Culled Empty Block (label) table_driven_irq::@7
Culled Empty Block (label) table_driven_irq::@6
Culled Empty Block (label) table_driven_irq::@12
Culled Empty Block (label) table_driven_irq::@13

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  (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*) CIA1_INTERRUPT#0 ← ((byte*)) (number) $dc0d
  (byte) CIA_INTERRUPT_CLEAR#0 ← (number) $7f
  (void()**) KERNEL_IRQ#0 ← ((void()**)) (number) $314
  to:@4
@4: scope:[]  from @begin
  (byte*) SCREEN#0 ← ((byte*)) (number) $400
  to:@5
main: scope:[main]  from @6
  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) $60
  *((byte*) IRQ_ENABLE#0) ← (byte) IRQ_RASTER#0
  *((byte*) IRQ_STATUS#0) ← (byte) IRQ_RASTER#0
  (void()*~) main::$0 ← & interrupt(KERNEL_MIN)(void()) table_driven_irq()
  *((void()**) KERNEL_IRQ#0) ← (void()*~) main::$0
  asm { cli  }
  to:main::@return
main::@return: scope:[main]  from main
  return 
  to:@return
@5: scope:[]  from @4
  (byte*) VIC_BASE#0 ← ((byte*)) (number) $d000
  (byte) VIC_SIZE#0 ← (number) $30
  (byte) IRQ_CHANGE_NEXT#0 ← (number) $7f
  (byte[]) IRQ_CHANGE_IDX#0 ← { (number) $20, (number) $21, (byte) IRQ_CHANGE_NEXT#0, (number) $20, (number) $21, (byte) IRQ_CHANGE_NEXT#0, (number) $20, (number) $21, (byte) IRQ_CHANGE_NEXT#0, (number) $20, (number) $21, (byte) IRQ_CHANGE_NEXT#0 }
  (byte[]) IRQ_CHANGE_VAL#0 ← { (number) $b, (number) $b, (number) $63, (number) 0, (number) 0, (number) $80, (number) 7, (number) 7, (number) $83, (number) 0, (number) 0, (number) $60 }
  (byte) irq_idx#0 ← (number) 0
  to:@6
table_driven_irq: scope:[table_driven_irq]  from
  (byte) irq_idx#6 ← phi( @6/(byte) irq_idx#9 )
  to:table_driven_irq::@1
table_driven_irq::@1: scope:[table_driven_irq]  from table_driven_irq table_driven_irq::@8
  (byte) irq_idx#4 ← phi( table_driven_irq/(byte) irq_idx#6 table_driven_irq::@8/(byte) irq_idx#7 )
  (byte) table_driven_irq::idx#0 ← *((byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4)
  (byte) table_driven_irq::val#0 ← *((byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4)
  (byte) irq_idx#1 ← ++ (byte) irq_idx#4
  (bool~) table_driven_irq::$0 ← (byte) table_driven_irq::idx#0 < (byte) VIC_SIZE#0
  if((bool~) table_driven_irq::$0) goto table_driven_irq::@2
  to:table_driven_irq::@9
table_driven_irq::@2: scope:[table_driven_irq]  from table_driven_irq::@1
  (byte) irq_idx#11 ← phi( table_driven_irq::@1/(byte) irq_idx#1 )
  (byte) table_driven_irq::idx#1 ← phi( table_driven_irq::@1/(byte) table_driven_irq::idx#0 )
  (byte) table_driven_irq::val#1 ← phi( table_driven_irq::@1/(byte) table_driven_irq::val#0 )
  *((byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#1) ← (byte) table_driven_irq::val#1
  to:table_driven_irq::@8
table_driven_irq::@9: scope:[table_driven_irq]  from table_driven_irq::@1
  (byte) irq_idx#10 ← phi( table_driven_irq::@1/(byte) irq_idx#1 )
  (byte) table_driven_irq::val#4 ← phi( table_driven_irq::@1/(byte) table_driven_irq::val#0 )
  (byte) table_driven_irq::idx#2 ← phi( table_driven_irq::@1/(byte) table_driven_irq::idx#0 )
  (number~) table_driven_irq::$1 ← (byte) VIC_SIZE#0 + (number) 8
  (bool~) table_driven_irq::$2 ← (byte) table_driven_irq::idx#2 < (number~) table_driven_irq::$1
  if((bool~) table_driven_irq::$2) goto table_driven_irq::@3
  to:table_driven_irq::@10
table_driven_irq::@3: scope:[table_driven_irq]  from table_driven_irq::@9
  (byte) irq_idx#12 ← phi( table_driven_irq::@9/(byte) irq_idx#10 )
  (byte) table_driven_irq::val#2 ← phi( table_driven_irq::@9/(byte) table_driven_irq::val#4 )
  (byte) table_driven_irq::idx#3 ← phi( table_driven_irq::@9/(byte) table_driven_irq::idx#2 )
  (number~) table_driven_irq::$5 ← (byte) table_driven_irq::idx#3 + (number) $3f8
  (number~) table_driven_irq::$6 ← (number~) table_driven_irq::$5 - (byte) VIC_SIZE#0
  *((byte*) SCREEN#0 + (number~) table_driven_irq::$6) ← (byte) table_driven_irq::val#2
  to:table_driven_irq::@8
table_driven_irq::@10: scope:[table_driven_irq]  from table_driven_irq::@9
  (byte) irq_idx#8 ← phi( table_driven_irq::@9/(byte) irq_idx#10 )
  (byte) table_driven_irq::val#3 ← phi( table_driven_irq::@9/(byte) table_driven_irq::val#4 )
  *((byte*) IRQ_STATUS#0) ← (byte) IRQ_RASTER#0
  *((byte*) RASTER#0) ← (byte) table_driven_irq::val#3
  (bool~) table_driven_irq::$3 ← (byte) table_driven_irq::val#3 < *((byte*) RASTER#0)
  (bool~) table_driven_irq::$4 ← ! (bool~) table_driven_irq::$3
  if((bool~) table_driven_irq::$4) goto table_driven_irq::@return
  to:table_driven_irq::@11
table_driven_irq::@11: scope:[table_driven_irq]  from table_driven_irq::@10
  (byte) irq_idx#2 ← (number) 0
  to:table_driven_irq::@return
table_driven_irq::@return: scope:[table_driven_irq]  from table_driven_irq::@10 table_driven_irq::@11 table_driven_irq::@8
  (byte) irq_idx#5 ← phi( table_driven_irq::@10/(byte) irq_idx#8 table_driven_irq::@11/(byte) irq_idx#2 table_driven_irq::@8/(byte) irq_idx#7 )
  (byte) irq_idx#3 ← (byte) irq_idx#5
  return 
  to:@return
table_driven_irq::@8: scope:[table_driven_irq]  from table_driven_irq::@2 table_driven_irq::@3
  (byte) irq_idx#7 ← phi( table_driven_irq::@2/(byte) irq_idx#11 table_driven_irq::@3/(byte) irq_idx#12 )
  if(true) goto table_driven_irq::@1
  to:table_driven_irq::@return
@6: scope:[]  from @5
  (byte) irq_idx#9 ← phi( @5/(byte) irq_idx#0 )
  call main 
  to:@7
@7: scope:[]  from @6
  to:@end
@end: scope:[]  from @7

SYMBOL TABLE SSA
(label) @4
(label) @5
(label) @6
(label) @7
(label) @begin
(label) @end
(byte*) CIA1_INTERRUPT
(byte*) CIA1_INTERRUPT#0
(byte) CIA_INTERRUPT_CLEAR
(byte) CIA_INTERRUPT_CLEAR#0
(byte[]) IRQ_CHANGE_IDX
(byte[]) IRQ_CHANGE_IDX#0
(byte) IRQ_CHANGE_NEXT
(byte) IRQ_CHANGE_NEXT#0
(byte[]) IRQ_CHANGE_VAL
(byte[]) IRQ_CHANGE_VAL#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*) SCREEN
(byte*) SCREEN#0
(byte*) VIC_BASE
(byte*) VIC_BASE#0
(byte*) VIC_CONTROL
(byte*) VIC_CONTROL#0
(byte) VIC_SIZE
(byte) VIC_SIZE#0
(byte) irq_idx
(byte) irq_idx#0
(byte) irq_idx#1
(byte) irq_idx#10
(byte) irq_idx#11
(byte) irq_idx#12
(byte) irq_idx#2
(byte) irq_idx#3
(byte) irq_idx#4
(byte) irq_idx#5
(byte) irq_idx#6
(byte) irq_idx#7
(byte) irq_idx#8
(byte) irq_idx#9
(void()) main()
(void()*~) main::$0
(label) main::@return
interrupt(KERNEL_MIN)(void()) table_driven_irq()
(bool~) table_driven_irq::$0
(number~) table_driven_irq::$1
(bool~) table_driven_irq::$2
(bool~) table_driven_irq::$3
(bool~) table_driven_irq::$4
(number~) table_driven_irq::$5
(number~) table_driven_irq::$6
(label) table_driven_irq::@1
(label) table_driven_irq::@10
(label) table_driven_irq::@11
(label) table_driven_irq::@2
(label) table_driven_irq::@3
(label) table_driven_irq::@8
(label) table_driven_irq::@9
(label) table_driven_irq::@return
(byte) table_driven_irq::idx
(byte) table_driven_irq::idx#0
(byte) table_driven_irq::idx#1
(byte) table_driven_irq::idx#2
(byte) table_driven_irq::idx#3
(byte) table_driven_irq::val
(byte) table_driven_irq::val#0
(byte) table_driven_irq::val#1
(byte) table_driven_irq::val#2
(byte) table_driven_irq::val#3
(byte) table_driven_irq::val#4

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) $60 in *((byte*) RASTER#0) ← (number) $60
Adding number conversion cast (unumber) $30 in (byte) VIC_SIZE#0 ← (number) $30
Adding number conversion cast (unumber) $7f in (byte) IRQ_CHANGE_NEXT#0 ← (number) $7f
Adding number conversion cast (unumber) 0 in (byte) irq_idx#0 ← (number) 0
Adding number conversion cast (unumber) 8 in (number~) table_driven_irq::$1 ← (byte) VIC_SIZE#0 + (number) 8
Adding number conversion cast (unumber) table_driven_irq::$1 in (number~) table_driven_irq::$1 ← (byte) VIC_SIZE#0 + (unumber)(number) 8
Adding number conversion cast (unumber) $3f8 in (number~) table_driven_irq::$5 ← (byte) table_driven_irq::idx#3 + (number) $3f8
Adding number conversion cast (unumber) table_driven_irq::$5 in (number~) table_driven_irq::$5 ← (byte) table_driven_irq::idx#3 + (unumber)(number) $3f8
Adding number conversion cast (unumber) table_driven_irq::$6 in (number~) table_driven_irq::$6 ← (unumber~) table_driven_irq::$5 - (byte) VIC_SIZE#0
Adding number conversion cast (unumber) 0 in (byte) irq_idx#2 ← (number) 0
Successful SSA optimization PassNAddNumberTypeConversions
Added casts to value list in (byte[]) IRQ_CHANGE_IDX#0 ← (byte[]){ (byte)(number) $20, (byte)(number) $21, (byte) IRQ_CHANGE_NEXT#0, (byte)(number) $20, (byte)(number) $21, (byte) IRQ_CHANGE_NEXT#0, (byte)(number) $20, (byte)(number) $21, (byte) IRQ_CHANGE_NEXT#0, (byte)(number) $20, (byte)(number) $21, (byte) IRQ_CHANGE_NEXT#0 }
Added casts to value list in (byte[]) IRQ_CHANGE_VAL#0 ← (byte[]){ (byte)(number) $b, (byte)(number) $b, (byte)(number) $63, (byte)(number) 0, (byte)(number) 0, (byte)(number) $80, (byte)(number) 7, (byte)(number) 7, (byte)(number) $83, (byte)(number) 0, (byte)(number) 0, (byte)(number) $60 }
Successful SSA optimization PassNAddInitializerValueListTypeCasts
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*) CIA1_INTERRUPT#0 ← (byte*)(number) $dc0d
Inlining cast (byte) CIA_INTERRUPT_CLEAR#0 ← (unumber)(number) $7f
Inlining cast (void()**) KERNEL_IRQ#0 ← (void()**)(number) $314
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
Inlining cast *((byte*) RASTER#0) ← (unumber)(number) $60
Inlining cast (byte*) VIC_BASE#0 ← (byte*)(number) $d000
Inlining cast (byte) VIC_SIZE#0 ← (unumber)(number) $30
Inlining cast (byte) IRQ_CHANGE_NEXT#0 ← (unumber)(number) $7f
Inlining cast (byte) irq_idx#0 ← (unumber)(number) 0
Inlining cast (byte) irq_idx#2 ← (unumber)(number) 0
Successful SSA optimization Pass2InlineCast
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*) 56333
Simplifying constant integer cast $7f
Simplifying constant pointer cast (void()**) 788
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast $7f
Simplifying constant integer cast $60
Simplifying constant pointer cast (byte*) 53248
Simplifying constant integer cast $30
Simplifying constant integer cast $7f
Simplifying constant integer cast $20
Simplifying constant integer cast $21
Simplifying constant integer cast $20
Simplifying constant integer cast $21
Simplifying constant integer cast $20
Simplifying constant integer cast $21
Simplifying constant integer cast $20
Simplifying constant integer cast $21
Simplifying constant integer cast $b
Simplifying constant integer cast $b
Simplifying constant integer cast $63
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $80
Simplifying constant integer cast 7
Simplifying constant integer cast 7
Simplifying constant integer cast $83
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $60
Simplifying constant integer cast 0
Simplifying constant integer cast 8
Simplifying constant integer cast $3f8
Simplifying constant integer cast 0
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) $60
Finalized unsigned number type (byte) $30
Finalized unsigned number type (byte) $7f
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 8
Finalized unsigned number type (word) $3f8
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in (unumber~) table_driven_irq::$1 ← (byte) VIC_SIZE#0 + (byte) 8
Inferred type updated to word in (unumber~) table_driven_irq::$5 ← (byte) table_driven_irq::idx#3 + (word) $3f8
Inferred type updated to word in (unumber~) table_driven_irq::$6 ← (word~) table_driven_irq::$5 - (byte) VIC_SIZE#0
Inversing boolean not [46] (bool~) table_driven_irq::$4 ← (byte) table_driven_irq::val#3 >= *((byte*) RASTER#0) from [45] (bool~) table_driven_irq::$3 ← (byte) table_driven_irq::val#3 < *((byte*) RASTER#0)
Successful SSA optimization Pass2UnaryNotSimplification
Alias (byte) table_driven_irq::val#0 = (byte) table_driven_irq::val#1 (byte) table_driven_irq::val#4 (byte) table_driven_irq::val#2 (byte) table_driven_irq::val#3 
Alias (byte) table_driven_irq::idx#0 = (byte) table_driven_irq::idx#1 (byte) table_driven_irq::idx#2 (byte) table_driven_irq::idx#3 
Alias (byte) irq_idx#1 = (byte) irq_idx#11 (byte) irq_idx#10 (byte) irq_idx#12 (byte) irq_idx#8 
Alias (byte) irq_idx#3 = (byte) irq_idx#5 
Alias (byte) irq_idx#0 = (byte) irq_idx#9 
Successful SSA optimization Pass2AliasElimination
Alias (byte) irq_idx#1 = (byte) irq_idx#7 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) irq_idx#6 (byte) irq_idx#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) table_driven_irq::$0 [31] if((byte) table_driven_irq::idx#0<(byte) VIC_SIZE#0) goto table_driven_irq::@2
Simple Condition (bool~) table_driven_irq::$2 [37] if((byte) table_driven_irq::idx#0<(byte~) table_driven_irq::$1) goto table_driven_irq::@3
Simple Condition (bool~) table_driven_irq::$4 [47] if((byte) table_driven_irq::val#0>=*((byte*) RASTER#0)) goto table_driven_irq::@return
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [15] (void()*~) main::$0 ← & interrupt(KERNEL_MIN)(void()) table_driven_irq()
Successful SSA optimization Pass2ConstantRValueConsolidation
Identified constant from value list (byte[]) { (byte) $b, (byte) $b, (byte) $63, (byte) 0, (byte) 0, (byte) $80, (byte) 7, (byte) 7, (byte) $83, (byte) 0, (byte) 0, (byte) $60 }
Successful SSA optimization Pass2ConstantInitializerValueLists
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*) CIA1_INTERRUPT#0 = (byte*) 56333
Constant (const byte) CIA_INTERRUPT_CLEAR#0 = $7f
Constant (const void()**) KERNEL_IRQ#0 = (void()**) 788
Constant (const byte*) SCREEN#0 = (byte*) 1024
Constant (const void()*) main::$0 = &table_driven_irq
Constant (const byte*) VIC_BASE#0 = (byte*) 53248
Constant (const byte) VIC_SIZE#0 = $30
Constant (const byte) IRQ_CHANGE_NEXT#0 = $7f
Constant (const byte[]) IRQ_CHANGE_VAL#0 = { $b, $b, $63, 0, 0, $80, 7, 7, $83, 0, 0, $60 }
Successful SSA optimization Pass2ConstantIdentification
Removing PHI-reference to removed block (table_driven_irq::@8) in block table_driven_irq::@return
if() condition always true - replacing block destination [53] if(true) goto table_driven_irq::@1
Successful SSA optimization Pass2ConstantIfs
De-inlining pointer[w] to *(pointer+w)   [41] *((const byte*) SCREEN#0 + (word~) table_driven_irq::$6) ← (byte) table_driven_irq::val#0
Successful SSA optimization Pass2DeInlineWordDerefIdx
Constant right-side identified [17] (byte~) table_driven_irq::$1 ← (const byte) VIC_SIZE#0 + (byte) 8
Successful SSA optimization Pass2ConstantRValueConsolidation
Identified constant from value list (byte[]) { (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0 }
Successful SSA optimization Pass2ConstantInitializerValueLists
Constant (const byte[]) IRQ_CHANGE_IDX#0 = { $20, $21, IRQ_CHANGE_NEXT#0, $20, $21, IRQ_CHANGE_NEXT#0, $20, $21, IRQ_CHANGE_NEXT#0, $20, $21, IRQ_CHANGE_NEXT#0 }
Constant (const byte) table_driven_irq::$1 = VIC_SIZE#0+8
Successful SSA optimization Pass2ConstantIdentification
Constant inlined table_driven_irq::$1 = (const byte) VIC_SIZE#0+(byte) 8
Constant inlined main::$0 = &interrupt(KERNEL_MIN)(void()) table_driven_irq()
Successful SSA optimization Pass2ConstantInlining
Consolidated constant in assignment table_driven_irq::$7
Successful SSA optimization Pass2ConstantAdditionElimination
Alias (word~) table_driven_irq::$6 = (word~) table_driven_irq::$5 
Successful SSA optimization Pass2AliasElimination
Consolidated constant in assignment table_driven_irq::$7
Successful SSA optimization Pass2ConstantAdditionElimination
Alias (byte) table_driven_irq::idx#0 = (word~) table_driven_irq::$6 
Successful SSA optimization Pass2AliasElimination
Converting *(pointer+n) to pointer[n] [19] *((byte*~) table_driven_irq::$7) ← (byte) table_driven_irq::val#0  -- *(SCREEN#0+-VIC_SIZE#0+$3f8 + table_driven_irq::idx#0)
Successful SSA optimization Pass2InlineDerefIdx
Eliminating unused variable (byte*~) table_driven_irq::$7 and assignment [17] (byte*~) table_driven_irq::$7 ← (const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0
Successful SSA optimization PassNEliminateUnusedVars
Added new block during phi lifting table_driven_irq::@14(between table_driven_irq::@10 and table_driven_irq::@return)
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @4
Adding NOP phi() at start of @6
Adding NOP phi() at start of @7
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:4 

Created 2 initial phi equivalence classes
Coalesced [16] irq_idx#13 ← irq_idx#0
Coalesced [27] irq_idx#16 ← irq_idx#2
Coalesced [30] irq_idx#15 ← irq_idx#1
Coalesced [32] irq_idx#14 ← irq_idx#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @4
Culled Empty Block (label) @7
Culled Empty Block (label) table_driven_irq::@14
Culled Empty Block (label) table_driven_irq::@8
Renumbering block @5 to @1
Renumbering block @6 to @2
Renumbering block table_driven_irq::@9 to table_driven_irq::@4
Renumbering block table_driven_irq::@10 to table_driven_irq::@5
Renumbering block table_driven_irq::@11 to table_driven_irq::@6
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of table_driven_irq

FINAL CONTROL FLOW GRAPH
@begin: scope:[]  from
  [0] phi()
  to:@1
@1: scope:[]  from @begin
  [1] (byte) irq_idx#0 ← (byte) 0
  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) $60
  [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0
  [10] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
  [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq()
  asm { cli  }
  to:main::@return
main::@return: scope:[main]  from main
  [13] return 
  to:@return
table_driven_irq: scope:[table_driven_irq]  from
  [14] phi()
  to:table_driven_irq::@1
table_driven_irq::@1: scope:[table_driven_irq]  from table_driven_irq table_driven_irq::@2 table_driven_irq::@3
  [15] (byte) irq_idx#4 ← phi( table_driven_irq/(byte) irq_idx#0 table_driven_irq::@2/(byte) irq_idx#1 table_driven_irq::@3/(byte) irq_idx#1 )
  [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4)
  [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4)
  [18] (byte) irq_idx#1 ← ++ (byte) irq_idx#4
  [19] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0) goto table_driven_irq::@2
  to:table_driven_irq::@4
table_driven_irq::@4: scope:[table_driven_irq]  from table_driven_irq::@1
  [20] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0+(byte) 8) goto table_driven_irq::@3
  to:table_driven_irq::@5
table_driven_irq::@5: scope:[table_driven_irq]  from table_driven_irq::@4
  [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0
  [22] *((const byte*) RASTER#0) ← (byte) table_driven_irq::val#0
  [23] if((byte) table_driven_irq::val#0>=*((const byte*) RASTER#0)) goto table_driven_irq::@return
  to:table_driven_irq::@6
table_driven_irq::@6: scope:[table_driven_irq]  from table_driven_irq::@5
  [24] (byte) irq_idx#2 ← (byte) 0
  to:table_driven_irq::@return
table_driven_irq::@return: scope:[table_driven_irq]  from table_driven_irq::@5 table_driven_irq::@6
  [25] (byte) irq_idx#3 ← phi( table_driven_irq::@5/(byte) irq_idx#1 table_driven_irq::@6/(byte) irq_idx#2 )
  [26] return 
  to:@return
table_driven_irq::@3: scope:[table_driven_irq]  from table_driven_irq::@4
  [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0
  to:table_driven_irq::@1
table_driven_irq::@2: scope:[table_driven_irq]  from table_driven_irq::@1
  [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0
  to:table_driven_irq::@1


VARIABLE REGISTER WEIGHTS
(byte*) CIA1_INTERRUPT
(byte) CIA_INTERRUPT_CLEAR
(byte[]) IRQ_CHANGE_IDX
(byte) IRQ_CHANGE_NEXT
(byte[]) IRQ_CHANGE_VAL
(byte*) IRQ_ENABLE
(byte) IRQ_RASTER
(byte*) IRQ_STATUS
(void()**) KERNEL_IRQ
(byte*) RASTER
(byte*) SCREEN
(byte*) VIC_BASE
(byte*) VIC_CONTROL
(byte) VIC_SIZE
(byte) irq_idx
(byte) irq_idx#0 4.0
(byte) irq_idx#1 4.375
(byte) irq_idx#2 4.0
(byte) irq_idx#3 40.0
(byte) irq_idx#4 19.0
(void()) main()
interrupt(KERNEL_MIN)(void()) table_driven_irq()
(byte) table_driven_irq::idx
(byte) table_driven_irq::idx#0 11.0
(byte) table_driven_irq::val
(byte) table_driven_irq::val#0 6.166666666666666

Initial phi equivalence classes
[ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ]
Added variable table_driven_irq::idx#0 to zero page equivalence class [ table_driven_irq::idx#0 ]
Added variable table_driven_irq::val#0 to zero page equivalence class [ table_driven_irq::val#0 ]
Complete equivalence classes
[ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ]
[ table_driven_irq::idx#0 ]
[ table_driven_irq::val#0 ]
Allocated zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ]
Allocated zp ZP_BYTE:3 [ table_driven_irq::idx#0 ]
Allocated zp ZP_BYTE:4 [ table_driven_irq::val#0 ]

INITIAL ASM
Target platform is c64basic
  // File Comments
// Test interrupt routine using a variable between calls (irq_idx)
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  // VIC II IRQ Status Register
  .label IRQ_STATUS = $d019
  // VIC II IRQ Enable Register
  .label IRQ_ENABLE = $d01a
  // Bits for the IRQ Status/Enable Registers
  .const IRQ_RASTER = 1
  // CIA#1 Interrupt Status & Control Register
  .label CIA1_INTERRUPT = $dc0d
  // Value that disables all CIA interrupts when stored to the CIA Interrupt registers
  .const CIA_INTERRUPT_CLEAR = $7f
  // The vector used when the KERNAL serves IRQ interrupts
  .label KERNEL_IRQ = $314
  .label SCREEN = $400
  .label VIC_BASE = $d000
  .const VIC_SIZE = $30
  .const IRQ_CHANGE_NEXT = $7f
  .label irq_idx = 2
  // @begin
bbegin:
  jmp b1
  // @1
b1:
  // [1] (byte) irq_idx#0 ← (byte) 0 -- vbuz1=vbuc1 
  lda #0
  sta.z irq_idx
  // [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 $60
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // [8] *((const byte*) RASTER#0) ← (byte) $60 -- _deref_pbuc1=vbuc2 
    lda #$60
    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 byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Acknowledge any IRQ
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq() -- _deref_pptc1=pprc2 
    // Setup the table driven IRQ routine
    lda #<table_driven_irq
    sta KERNEL_IRQ
    lda #>table_driven_irq
    sta KERNEL_IRQ+1
    // asm { cli  }
    cli
    jmp breturn
    // main::@return
  breturn:
    // [13] return 
    rts
}
  // table_driven_irq
table_driven_irq: {
    .label idx = 3
    .label val = 4
    // entry interrupt(KERNEL_MIN)
    // [15] phi from table_driven_irq table_driven_irq::@2 table_driven_irq::@3 to table_driven_irq::@1 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1]
  b1_from_table_driven_irq:
  b1_from_b2:
  b1_from_b3:
    // [15] phi (byte) irq_idx#4 = (byte) irq_idx#0 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1#0] -- register_copy 
    jmp b1
    // table_driven_irq::@1
  b1:
    // [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4) -- vbuz1=pbuc1_derefidx_vbuz2 
    ldy.z irq_idx
    lda IRQ_CHANGE_IDX,y
    sta.z idx
    // [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4) -- vbuz1=pbuc1_derefidx_vbuz2 
    ldy.z irq_idx
    lda IRQ_CHANGE_VAL,y
    sta.z val
    // [18] (byte) irq_idx#1 ← ++ (byte) irq_idx#4 -- vbuz1=_inc_vbuz1 
    inc.z irq_idx
    // [19] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0) goto table_driven_irq::@2 -- vbuz1_lt_vbuc1_then_la1 
    lda.z idx
    cmp #VIC_SIZE
    bcc b2
    jmp b4
    // table_driven_irq::@4
  b4:
    // [20] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0+(byte) 8) goto table_driven_irq::@3 -- vbuz1_lt_vbuc1_then_la1 
    lda.z idx
    cmp #VIC_SIZE+8
    bcc b3
    jmp b5
    // table_driven_irq::@5
  b5:
    // [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [22] *((const byte*) RASTER#0) ← (byte) table_driven_irq::val#0 -- _deref_pbuc1=vbuz1 
    lda.z val
    sta RASTER
    // [23] if((byte) table_driven_irq::val#0>=*((const byte*) RASTER#0)) goto table_driven_irq::@return -- vbuz1_ge__deref_pbuc1_then_la1 
    lda RASTER
    ldy.z val
    sta.z $ff
    cpy.z $ff
    bcs breturn_from_b5
    jmp b6
    // table_driven_irq::@6
  b6:
    // [24] (byte) irq_idx#2 ← (byte) 0 -- vbuz1=vbuc1 
    lda #0
    sta.z irq_idx
    // [25] phi from table_driven_irq::@5 table_driven_irq::@6 to table_driven_irq::@return [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return]
  breturn_from_b5:
  breturn_from_b6:
    // [25] phi (byte) irq_idx#3 = (byte) irq_idx#1 [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return#0] -- register_copy 
    jmp breturn
    // table_driven_irq::@return
  breturn:
    // [26] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
    // table_driven_irq::@3
  b3:
    // [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuz1=vbuz2 
    lda.z val
    ldy.z idx
    sta SCREEN+-VIC_SIZE+$3f8,y
    jmp b1_from_b3
    // table_driven_irq::@2
  b2:
    // [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuz1=vbuz2 
    lda.z val
    ldy.z idx
    sta VIC_BASE,y
    jmp b1_from_b2
}
  // File Data
  IRQ_CHANGE_VAL: .byte $b, $b, $63, 0, 0, $80, 7, 7, $83, 0, 0, $60
  IRQ_CHANGE_IDX: .byte $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (byte) irq_idx#0 ← (byte) 0 [ ] (  [ ] ) always clobbers reg byte a 
Statement [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [8] *((const byte*) RASTER#0) ← (byte) $60 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [10] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq() [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4) [ irq_idx#4 table_driven_irq::idx#0 ] (  [ irq_idx#4 table_driven_irq::idx#0 ] ) always clobbers reg byte y 
Statement [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4) [ irq_idx#4 table_driven_irq::idx#0 table_driven_irq::val#0 ] (  [ irq_idx#4 table_driven_irq::idx#0 table_driven_irq::val#0 ] ) always clobbers reg byte y 
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ table_driven_irq::idx#0 ]
Statement [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ irq_idx#1 table_driven_irq::val#0 ] (  [ irq_idx#1 table_driven_irq::val#0 ] ) always clobbers reg byte a 
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ table_driven_irq::val#0 ]
Statement [24] (byte) irq_idx#2 ← (byte) 0 [ irq_idx#2 ] (  [ irq_idx#2 ] ) always clobbers reg byte a 
Statement [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 [ irq_idx#1 ] (  [ irq_idx#1 ] ) always clobbers reg byte a 
Statement [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 [ irq_idx#1 ] (  [ irq_idx#1 ] ) always clobbers reg byte a 
Statement [1] (byte) irq_idx#0 ← (byte) 0 [ ] (  [ ] ) always clobbers reg byte a 
Statement [6] *((const byte*) CIA1_INTERRUPT#0) ← (const byte) CIA_INTERRUPT_CLEAR#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [7] *((const byte*) VIC_CONTROL#0) ← *((const byte*) VIC_CONTROL#0) & (byte) $7f [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [8] *((const byte*) RASTER#0) ← (byte) $60 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [9] *((const byte*) IRQ_ENABLE#0) ← (const byte) IRQ_RASTER#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [10] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq() [ ] ( main:3 [ ] ) always clobbers reg byte a 
Statement [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4) [ irq_idx#4 table_driven_irq::idx#0 ] (  [ irq_idx#4 table_driven_irq::idx#0 ] ) always clobbers reg byte y 
Statement [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4) [ irq_idx#4 table_driven_irq::idx#0 table_driven_irq::val#0 ] (  [ irq_idx#4 table_driven_irq::idx#0 table_driven_irq::val#0 ] ) always clobbers reg byte y 
Statement [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 [ irq_idx#1 table_driven_irq::val#0 ] (  [ irq_idx#1 table_driven_irq::val#0 ] ) always clobbers reg byte a 
Statement [24] (byte) irq_idx#2 ← (byte) 0 [ irq_idx#2 ] (  [ irq_idx#2 ] ) always clobbers reg byte a 
Statement [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 [ irq_idx#1 ] (  [ irq_idx#1 ] ) always clobbers reg byte a 
Statement [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 [ irq_idx#1 ] (  [ irq_idx#1 ] ) always clobbers reg byte a 
Potential registers zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ] : zp ZP_BYTE:2 , 
Potential registers zp ZP_BYTE:3 [ table_driven_irq::idx#0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , 
Potential registers zp ZP_BYTE:4 [ table_driven_irq::val#0 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , 

REGISTER UPLIFT SCOPES
Uplift Scope [] 71.38: zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ] 
Uplift Scope [table_driven_irq] 11: zp ZP_BYTE:3 [ table_driven_irq::idx#0 ] 6.17: zp ZP_BYTE:4 [ table_driven_irq::val#0 ] 
Uplift Scope [main] 

Uplifting [] best 928 combination zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ] 
Uplifting [table_driven_irq] best 762 combination reg byte a [ table_driven_irq::idx#0 ] reg byte x [ table_driven_irq::val#0 ] 
Uplifting [main] best 762 combination 
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ]
Uplifting [] best 762 combination zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ] 

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Test interrupt routine using a variable between calls (irq_idx)
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  // VIC II IRQ Status Register
  .label IRQ_STATUS = $d019
  // VIC II IRQ Enable Register
  .label IRQ_ENABLE = $d01a
  // Bits for the IRQ Status/Enable Registers
  .const IRQ_RASTER = 1
  // CIA#1 Interrupt Status & Control Register
  .label CIA1_INTERRUPT = $dc0d
  // Value that disables all CIA interrupts when stored to the CIA Interrupt registers
  .const CIA_INTERRUPT_CLEAR = $7f
  // The vector used when the KERNAL serves IRQ interrupts
  .label KERNEL_IRQ = $314
  .label SCREEN = $400
  .label VIC_BASE = $d000
  .const VIC_SIZE = $30
  .const IRQ_CHANGE_NEXT = $7f
  .label irq_idx = 2
  // @begin
bbegin:
  jmp b1
  // @1
b1:
  // [1] (byte) irq_idx#0 ← (byte) 0 -- vbuz1=vbuc1 
  lda #0
  sta.z irq_idx
  // [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 $60
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // [8] *((const byte*) RASTER#0) ← (byte) $60 -- _deref_pbuc1=vbuc2 
    lda #$60
    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 byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Acknowledge any IRQ
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq() -- _deref_pptc1=pprc2 
    // Setup the table driven IRQ routine
    lda #<table_driven_irq
    sta KERNEL_IRQ
    lda #>table_driven_irq
    sta KERNEL_IRQ+1
    // asm { cli  }
    cli
    jmp breturn
    // main::@return
  breturn:
    // [13] return 
    rts
}
  // table_driven_irq
table_driven_irq: {
    // entry interrupt(KERNEL_MIN)
    // [15] phi from table_driven_irq table_driven_irq::@2 table_driven_irq::@3 to table_driven_irq::@1 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1]
  b1_from_table_driven_irq:
  b1_from_b2:
  b1_from_b3:
    // [15] phi (byte) irq_idx#4 = (byte) irq_idx#0 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1#0] -- register_copy 
    jmp b1
    // table_driven_irq::@1
  b1:
    // [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4) -- vbuaa=pbuc1_derefidx_vbuz1 
    ldy.z irq_idx
    lda IRQ_CHANGE_IDX,y
    // [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4) -- vbuxx=pbuc1_derefidx_vbuz1 
    ldy.z irq_idx
    ldx IRQ_CHANGE_VAL,y
    // [18] (byte) irq_idx#1 ← ++ (byte) irq_idx#4 -- vbuz1=_inc_vbuz1 
    inc.z irq_idx
    // [19] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0) goto table_driven_irq::@2 -- vbuaa_lt_vbuc1_then_la1 
    cmp #VIC_SIZE
    bcc b2
    jmp b4
    // table_driven_irq::@4
  b4:
    // [20] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0+(byte) 8) goto table_driven_irq::@3 -- vbuaa_lt_vbuc1_then_la1 
    cmp #VIC_SIZE+8
    bcc b3
    jmp b5
    // table_driven_irq::@5
  b5:
    // [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // [22] *((const byte*) RASTER#0) ← (byte) table_driven_irq::val#0 -- _deref_pbuc1=vbuxx 
    stx RASTER
    // [23] if((byte) table_driven_irq::val#0>=*((const byte*) RASTER#0)) goto table_driven_irq::@return -- vbuxx_ge__deref_pbuc1_then_la1 
    ldy RASTER
    sty.z $ff
    cpx.z $ff
    bcs breturn_from_b5
    jmp b6
    // table_driven_irq::@6
  b6:
    // [24] (byte) irq_idx#2 ← (byte) 0 -- vbuz1=vbuc1 
    lda #0
    sta.z irq_idx
    // [25] phi from table_driven_irq::@5 table_driven_irq::@6 to table_driven_irq::@return [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return]
  breturn_from_b5:
  breturn_from_b6:
    // [25] phi (byte) irq_idx#3 = (byte) irq_idx#1 [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return#0] -- register_copy 
    jmp breturn
    // table_driven_irq::@return
  breturn:
    // [26] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
    // table_driven_irq::@3
  b3:
    // [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuaa=vbuxx 
    tay
    txa
    sta SCREEN+-VIC_SIZE+$3f8,y
    jmp b1_from_b3
    // table_driven_irq::@2
  b2:
    // [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuaa=vbuxx 
    tay
    txa
    sta VIC_BASE,y
    jmp b1_from_b2
}
  // File Data
  IRQ_CHANGE_VAL: .byte $b, $b, $63, 0, 0, $80, 7, 7, $83, 0, 0, $60
  IRQ_CHANGE_IDX: .byte $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp bend
Removing instruction jmp breturn
Removing instruction jmp b1
Removing instruction jmp b4
Removing instruction jmp b5
Removing instruction jmp b6
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #IRQ_RASTER
Removing instruction ldy.z irq_idx
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label breturn_from_b5 with breturn
Replacing label b1_from_b3 with b1
Replacing label b1_from_b2 with b1
Removing instruction b1:
Removing instruction b2_from_b1:
Removing instruction bend_from_b2:
Removing instruction b1_from_table_driven_irq:
Removing instruction b1_from_b2:
Removing instruction b1_from_b3:
Removing instruction breturn_from_b5:
Removing instruction breturn_from_b6:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction b2:
Removing instruction bend:
Removing instruction breturn:
Removing instruction b4:
Removing instruction b5:
Removing instruction b6:
Succesful ASM optimization Pass5UnusedLabelElimination
Skipping double jump to $ea81 in bcs breturn
Succesful ASM optimization Pass5DoubleJumpElimination
Adding RTS to root block 
Succesful ASM optimization Pass5AddMainRts
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Fixing long branch [68] bcs $ea81 to bcc

FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(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_CHANGE_IDX
(const byte[]) IRQ_CHANGE_IDX#0 IRQ_CHANGE_IDX = { (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0, (byte) $20, (byte) $21, (const byte) IRQ_CHANGE_NEXT#0 }
(byte) IRQ_CHANGE_NEXT
(const byte) IRQ_CHANGE_NEXT#0 IRQ_CHANGE_NEXT = (byte) $7f
(byte[]) IRQ_CHANGE_VAL
(const byte[]) IRQ_CHANGE_VAL#0 IRQ_CHANGE_VAL = { (byte) $b, (byte) $b, (byte) $63, (byte) 0, (byte) 0, (byte) $80, (byte) 7, (byte) 7, (byte) $83, (byte) 0, (byte) 0, (byte) $60 }
(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*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
(byte*) VIC_BASE
(const byte*) VIC_BASE#0 VIC_BASE = (byte*) 53248
(byte*) VIC_CONTROL
(const byte*) VIC_CONTROL#0 VIC_CONTROL = (byte*) 53265
(byte) VIC_SIZE
(const byte) VIC_SIZE#0 VIC_SIZE = (byte) $30
(byte) irq_idx
(byte) irq_idx#0 irq_idx zp ZP_BYTE:2 4.0
(byte) irq_idx#1 irq_idx zp ZP_BYTE:2 4.375
(byte) irq_idx#2 irq_idx zp ZP_BYTE:2 4.0
(byte) irq_idx#3 irq_idx zp ZP_BYTE:2 40.0
(byte) irq_idx#4 irq_idx zp ZP_BYTE:2 19.0
(void()) main()
(label) main::@return
interrupt(KERNEL_MIN)(void()) table_driven_irq()
(label) table_driven_irq::@1
(label) table_driven_irq::@2
(label) table_driven_irq::@3
(label) table_driven_irq::@4
(label) table_driven_irq::@5
(label) table_driven_irq::@6
(label) table_driven_irq::@return
(byte) table_driven_irq::idx
(byte) table_driven_irq::idx#0 reg byte a 11.0
(byte) table_driven_irq::val
(byte) table_driven_irq::val#0 reg byte x 6.166666666666666

zp ZP_BYTE:2 [ irq_idx#3 irq_idx#4 irq_idx#0 irq_idx#1 irq_idx#2 ]
reg byte a [ table_driven_irq::idx#0 ]
reg byte x [ table_driven_irq::val#0 ]


FINAL ASSEMBLER
Score: 604

  // File Comments
// Test interrupt routine using a variable between calls (irq_idx)
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  .label RASTER = $d012
  .label VIC_CONTROL = $d011
  // VIC II IRQ Status Register
  .label IRQ_STATUS = $d019
  // VIC II IRQ Enable Register
  .label IRQ_ENABLE = $d01a
  // Bits for the IRQ Status/Enable Registers
  .const IRQ_RASTER = 1
  // CIA#1 Interrupt Status & Control Register
  .label CIA1_INTERRUPT = $dc0d
  // Value that disables all CIA interrupts when stored to the CIA Interrupt registers
  .const CIA_INTERRUPT_CLEAR = $7f
  // The vector used when the KERNAL serves IRQ interrupts
  .label KERNEL_IRQ = $314
  .label SCREEN = $400
  .label VIC_BASE = $d000
  .const VIC_SIZE = $30
  .const IRQ_CHANGE_NEXT = $7f
  .label irq_idx = 2
  // @begin
bbegin:
  // @1
  // irq_idx = 0
  // [1] (byte) irq_idx#0 ← (byte) 0 -- vbuz1=vbuc1 
  lda #0
  sta.z irq_idx
  // [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 $60
    lda #$7f
    and VIC_CONTROL
    sta VIC_CONTROL
    // *RASTER = $60
    // [8] *((const byte*) RASTER#0) ← (byte) $60 -- _deref_pbuc1=vbuc2 
    lda #$60
    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
    // *IRQ_STATUS = IRQ_RASTER
    // [10] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    // Acknowledge any IRQ
    sta IRQ_STATUS
    // *KERNEL_IRQ = &table_driven_irq
    // [11] *((const void()**) KERNEL_IRQ#0) ← &interrupt(KERNEL_MIN)(void()) table_driven_irq() -- _deref_pptc1=pprc2 
    // Setup the table driven IRQ routine
    lda #<table_driven_irq
    sta KERNEL_IRQ
    lda #>table_driven_irq
    sta KERNEL_IRQ+1
    // asm
    // asm { cli  }
    cli
    // main::@return
    // }
    // [13] return 
    rts
}
  // table_driven_irq
table_driven_irq: {
    // entry interrupt(KERNEL_MIN)
    // [15] phi from table_driven_irq table_driven_irq::@2 table_driven_irq::@3 to table_driven_irq::@1 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1]
    // [15] phi (byte) irq_idx#4 = (byte) irq_idx#0 [phi:table_driven_irq/table_driven_irq::@2/table_driven_irq::@3->table_driven_irq::@1#0] -- register_copy 
    // table_driven_irq::@1
  b1:
    // idx = IRQ_CHANGE_IDX[irq_idx]
    // [16] (byte) table_driven_irq::idx#0 ← *((const byte[]) IRQ_CHANGE_IDX#0 + (byte) irq_idx#4) -- vbuaa=pbuc1_derefidx_vbuz1 
    ldy.z irq_idx
    lda IRQ_CHANGE_IDX,y
    // val = IRQ_CHANGE_VAL[irq_idx]
    // [17] (byte) table_driven_irq::val#0 ← *((const byte[]) IRQ_CHANGE_VAL#0 + (byte) irq_idx#4) -- vbuxx=pbuc1_derefidx_vbuz1 
    ldx IRQ_CHANGE_VAL,y
    // irq_idx++;
    // [18] (byte) irq_idx#1 ← ++ (byte) irq_idx#4 -- vbuz1=_inc_vbuz1 
    inc.z irq_idx
    // if (idx < VIC_SIZE)
    // [19] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0) goto table_driven_irq::@2 -- vbuaa_lt_vbuc1_then_la1 
    cmp #VIC_SIZE
    bcc b2
    // table_driven_irq::@4
    // if (idx < VIC_SIZE + 8)
    // [20] if((byte) table_driven_irq::idx#0<(const byte) VIC_SIZE#0+(byte) 8) goto table_driven_irq::@3 -- vbuaa_lt_vbuc1_then_la1 
    cmp #VIC_SIZE+8
    bcc b3
    // table_driven_irq::@5
    // *IRQ_STATUS = IRQ_RASTER
    // [21] *((const byte*) IRQ_STATUS#0) ← (const byte) IRQ_RASTER#0 -- _deref_pbuc1=vbuc2 
    lda #IRQ_RASTER
    sta IRQ_STATUS
    // *RASTER = val
    // [22] *((const byte*) RASTER#0) ← (byte) table_driven_irq::val#0 -- _deref_pbuc1=vbuxx 
    stx RASTER
    // if (val < *RASTER)
    // [23] if((byte) table_driven_irq::val#0>=*((const byte*) RASTER#0)) goto table_driven_irq::@return -- vbuxx_ge__deref_pbuc1_then_la1 
    ldy RASTER
    sty.z $ff
    cpx.z $ff
    bcc !_ea81+
    jmp $ea81
  !_ea81:
    // table_driven_irq::@6
    // irq_idx = 0
    // [24] (byte) irq_idx#2 ← (byte) 0 -- vbuz1=vbuc1 
    lda #0
    sta.z irq_idx
    // [25] phi from table_driven_irq::@5 table_driven_irq::@6 to table_driven_irq::@return [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return]
    // [25] phi (byte) irq_idx#3 = (byte) irq_idx#1 [phi:table_driven_irq::@5/table_driven_irq::@6->table_driven_irq::@return#0] -- register_copy 
    // table_driven_irq::@return
    // }
    // [26] return  - exit interrupt(KERNEL_MIN)
    jmp $ea81
    // table_driven_irq::@3
  b3:
    // SCREEN[idx + $3f8 - VIC_SIZE] = val
    // [27] *((const byte*) SCREEN#0+-(const byte) VIC_SIZE#0+(word) $3f8 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuaa=vbuxx 
    tay
    txa
    sta SCREEN+-VIC_SIZE+$3f8,y
    jmp b1
    // table_driven_irq::@2
  b2:
    // VIC_BASE[idx] = val
    // [28] *((const byte*) VIC_BASE#0 + (byte) table_driven_irq::idx#0) ← (byte) table_driven_irq::val#0 -- pbuc1_derefidx_vbuaa=vbuxx 
    tay
    txa
    sta VIC_BASE,y
    jmp b1
}
  // File Data
  IRQ_CHANGE_VAL: .byte $b, $b, $63, 0, 0, $80, 7, 7, $83, 0, 0, $60
  IRQ_CHANGE_IDX: .byte $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT, $20, $21, IRQ_CHANGE_NEXT

