Resolved forward reference irq to interrupt(KERNEL_MIN)(void()) irq() CONTROL FLOW GRAPH SSA @begin: scope:[] from (volatile byte) col ← (byte) 0 to:@1 (void()) main() main: scope:[main] from @1 *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() to:main::@1 main::@1: scope:[main] from main main::@2 main::@3 if(true) goto main::@2 to:main::@return main::@2: scope:[main] from main::@1 (bool~) main::$0 ← (volatile byte) col > (number) $a (bool~) main::$1 ← ! (bool~) main::$0 if((bool~) main::$1) goto main::@1 to:main::@3 main::@3: scope:[main] from main::@2 (volatile byte) col ← (number) 0 to:main::@1 main::@return: scope:[main] from main::@1 return to:@return interrupt(KERNEL_MIN)(void()) irq() irq: scope:[irq] from asm { lda$dc0d } *((const nomodify byte*) BG_COLOR) ← (volatile byte) col (bool~) irq::$0 ← (volatile byte) col != (number) 0 if((bool~) irq::$0) goto irq::@1 to:irq::@2 irq::@1: scope:[irq] from irq (volatile byte) col ← ++ (volatile byte) col to:irq::@return irq::@2: scope:[irq] from irq (volatile byte) col ← (volatile byte) col + (number) 2 to:irq::@return irq::@return: scope:[irq] from irq::@1 irq::@2 return to:@return @1: scope:[] from @begin call main to:@2 @2: scope:[] from @1 to:@end @end: scope:[] from @2 SYMBOL TABLE SSA (label) @1 (label) @2 (label) @begin (label) @end (const nomodify byte*) BG_COLOR = (byte*)(number) $d020 (const nomodify void()**) KERNEL_IRQ = (void()**)(number) $314 (volatile byte) col loadstore interrupt(KERNEL_MIN)(void()) irq() (bool~) irq::$0 (label) irq::@1 (label) irq::@2 (label) irq::@return (void()) main() (bool~) main::$0 (bool~) main::$1 (label) main::@1 (label) main::@2 (label) main::@3 (label) main::@return Adding number conversion cast (unumber) $a in (bool~) main::$0 ← (volatile byte) col > (number) $a Adding number conversion cast (unumber) 0 in (volatile byte) col ← (number) 0 Adding number conversion cast (unumber) 0 in (bool~) irq::$0 ← (volatile byte) col != (number) 0 Adding number conversion cast (unumber) 2 in (volatile byte) col ← (volatile byte) col + (number) 2 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast (volatile byte) col ← (unumber)(number) 0 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (void()**) 788 Simplifying constant pointer cast (byte*) 53280 Simplifying constant integer cast $a Simplifying constant integer cast 0 Simplifying constant integer cast 0 Simplifying constant integer cast 2 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $a Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 2 Successful SSA optimization PassNFinalizeNumberTypeConversions Inversing boolean not [4] (bool~) main::$1 ← (volatile byte) col <= (byte) $a from [3] (bool~) main::$0 ← (volatile byte) col > (byte) $a Successful SSA optimization Pass2UnaryNotSimplification Simple Condition (bool~) main::$1 [4] if((volatile byte) col<=(byte) $a) goto main::@1 Simple Condition (bool~) irq::$0 [10] if((volatile byte) col!=(byte) 0) goto irq::@1 Successful SSA optimization Pass2ConditionalJumpSimplification if() condition always true - replacing block destination [2] if(true) goto main::@2 Successful SSA optimization Pass2ConstantIfs Rewriting conditional comparison [4] if((volatile byte) col<=(byte) $a) goto main::@1 Removing unused block main::@return Successful SSA optimization Pass2EliminateUnusedBlocks Adding number conversion cast (unumber) $a+1 in if((volatile byte) col<(byte) $a+(number) 1) goto main::@1 Adding number conversion cast (unumber) 1 in if((volatile byte) col<(unumber)(byte) $a+(number) 1) goto main::@1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant integer cast (byte) $a+(unumber)(number) 1 Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Adding NOP phi() at start of @1 Adding NOP phi() at start of @2 Adding NOP phi() at start of @end Adding NOP phi() at start of main::@1 CALL GRAPH Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) main::@1 Renumbering block main::@2 to main::@1 Renumbering block main::@3 to main::@2 Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] (volatile byte) col ← (byte) 0 to:@1 @1: scope:[] from @begin [1] phi() [2] call main to:@end @end: scope:[] from @1 [3] phi() (void()) main() main: scope:[main] from @1 [4] *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() to:main::@1 main::@1: scope:[main] from main main::@1 main::@2 [5] if((volatile byte) col<(byte) $a+(byte) 1) goto main::@1 to:main::@2 main::@2: scope:[main] from main::@1 [6] (volatile byte) col ← (byte) 0 to:main::@1 interrupt(KERNEL_MIN)(void()) irq() irq: scope:[irq] from asm { lda$dc0d } [8] *((const nomodify byte*) BG_COLOR) ← (volatile byte) col [9] if((volatile byte) col!=(byte) 0) goto irq::@1 to:irq::@2 irq::@2: scope:[irq] from irq [10] (volatile byte) col ← (volatile byte) col + (byte) 2 to:irq::@return irq::@return: scope:[irq] from irq::@1 irq::@2 [11] return to:@return irq::@1: scope:[irq] from irq [12] (volatile byte) col ← ++ (volatile byte) col to:irq::@return VARIABLE REGISTER WEIGHTS (volatile byte) col loadstore 139.5 interrupt(KERNEL_MIN)(void()) irq() (void()) main() Initial phi equivalence classes Added variable col to live range equivalence class [ col ] Complete equivalence classes [ col ] Allocated zp[1]:2 [ col ] INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Tests that volatile variables can be both read & written inside & outside interrupts // Currently fails because the modification is optimized away // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label KERNEL_IRQ = $314 .label BG_COLOR = $d020 .label col = 2 // @begin __bbegin: // [0] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { // [4] *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 lda #irq sta KERNEL_IRQ+1 jmp __b1 // main::@1 __b1: // [5] if((volatile byte) col<(byte) $a+(byte) 1) goto main::@1 -- vbuz1_lt_vbuc1_then_la1 lda.z col cmp #$a+1 bcc __b1 jmp __b2 // main::@2 __b2: // [6] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col jmp __b1 } // irq irq: { // entry interrupt(KERNEL_MIN) // asm { lda$dc0d } lda $dc0d // [8] *((const nomodify byte*) BG_COLOR) ← (volatile byte) col -- _deref_pbuc1=vbuz1 lda.z col sta BG_COLOR // [9] if((volatile byte) col!=(byte) 0) goto irq::@1 -- vbuz1_neq_0_then_la1 lda.z col cmp #0 bne __b1 jmp __b2 // irq::@2 __b2: // [10] (volatile byte) col ← (volatile byte) col + (byte) 2 -- vbuz1=vbuz1_plus_2 lda.z col clc adc #2 sta.z col jmp __breturn // irq::@return __breturn: // [11] return - exit interrupt(KERNEL_MIN) jmp $ea81 // irq::@1 __b1: // [12] (volatile byte) col ← ++ (volatile byte) col -- vbuz1=_inc_vbuz1 inc.z col jmp __breturn } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] (volatile byte) col ← (byte) 0 [ col ] ( [ col ] { } ) always clobbers reg byte a Statement [4] *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() [ col ] ( main:2 [ col ] { } ) always clobbers reg byte a Statement [5] if((volatile byte) col<(byte) $a+(byte) 1) goto main::@1 [ col ] ( main:2 [ col ] { } ) always clobbers reg byte a Statement [6] (volatile byte) col ← (byte) 0 [ col ] ( main:2 [ col ] { } ) always clobbers reg byte a Statement asm { lda$dc0d } always clobbers reg byte a Statement [8] *((const nomodify byte*) BG_COLOR) ← (volatile byte) col [ col ] ( [ col ] { } ) always clobbers reg byte a Statement [9] if((volatile byte) col!=(byte) 0) goto irq::@1 [ col ] ( [ col ] { } ) always clobbers reg byte a Statement [10] (volatile byte) col ← (volatile byte) col + (byte) 2 [ ] ( [ ] { } ) always clobbers reg byte a Potential registers zp[1]:2 [ col ] : zp[1]:2 , REGISTER UPLIFT SCOPES Uplift Scope [] 139.5: zp[1]:2 [ col ] Uplift Scope [main] Uplift Scope [irq] Uplifting [] best 1207 combination zp[1]:2 [ col ] Uplifting [main] best 1207 combination Uplifting [irq] best 1207 combination Attempting to uplift remaining variables inzp[1]:2 [ col ] Uplifting [] best 1207 combination zp[1]:2 [ col ] ASSEMBLER BEFORE OPTIMIZATION // File Comments // Tests that volatile variables can be both read & written inside & outside interrupts // Currently fails because the modification is optimized away // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label KERNEL_IRQ = $314 .label BG_COLOR = $d020 .label col = 2 // @begin __bbegin: // [0] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { // [4] *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 lda #irq sta KERNEL_IRQ+1 jmp __b1 // main::@1 __b1: // [5] if((volatile byte) col<(byte) $a+(byte) 1) goto main::@1 -- vbuz1_lt_vbuc1_then_la1 lda.z col cmp #$a+1 bcc __b1 jmp __b2 // main::@2 __b2: // [6] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col jmp __b1 } // irq irq: { // entry interrupt(KERNEL_MIN) // asm { lda$dc0d } lda $dc0d // [8] *((const nomodify byte*) BG_COLOR) ← (volatile byte) col -- _deref_pbuc1=vbuz1 lda.z col sta BG_COLOR // [9] if((volatile byte) col!=(byte) 0) goto irq::@1 -- vbuz1_neq_0_then_la1 lda.z col cmp #0 bne __b1 jmp __b2 // irq::@2 __b2: // [10] (volatile byte) col ← (volatile byte) col + (byte) 2 -- vbuz1=vbuz1_plus_2 lda.z col clc adc #2 sta.z col jmp __breturn // irq::@return __breturn: // [11] return - exit interrupt(KERNEL_MIN) jmp $ea81 // irq::@1 __b1: // [12] (volatile byte) col ← ++ (volatile byte) col -- vbuz1=_inc_vbuz1 inc.z col jmp __breturn } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __b2 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: Removing instruction __bend: Removing instruction __b2: Removing instruction __b2: Succesful ASM optimization Pass5UnusedLabelElimination Skipping double jump to $ea81 in jmp __breturn Succesful ASM optimization Pass5DoubleJumpElimination Adding RTS to root block Succesful ASM optimization Pass5AddMainRts Removing instruction lda.z col Succesful ASM optimization Pass5UnnecesaryLoadElimination Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (const nomodify byte*) BG_COLOR = (byte*) 53280 (const nomodify void()**) KERNEL_IRQ = (void()**) 788 (volatile byte) col loadstore zp[1]:2 139.5 interrupt(KERNEL_MIN)(void()) irq() (label) irq::@1 (label) irq::@2 (label) irq::@return (void()) main() (label) main::@1 (label) main::@2 zp[1]:2 [ col ] FINAL ASSEMBLER Score: 895 // File Comments // Tests that volatile variables can be both read & written inside & outside interrupts // Currently fails because the modification is optimized away // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label KERNEL_IRQ = $314 .label BG_COLOR = $d020 .label col = 2 // @begin __bbegin: // col = 0 // [0] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main jsr main rts // [3] phi from @1 to @end [phi:@1->@end] // @end // main main: { // *KERNEL_IRQ = &irq // [4] *((const nomodify void()**) KERNEL_IRQ) ← &interrupt(KERNEL_MIN)(void()) irq() -- _deref_pptc1=pprc2 lda #irq sta KERNEL_IRQ+1 // main::@1 __b1: // if(col>10) // [5] if((volatile byte) col<(byte) $a+(byte) 1) goto main::@1 -- vbuz1_lt_vbuc1_then_la1 lda.z col cmp #$a+1 bcc __b1 // main::@2 // col = 0 // [6] (volatile byte) col ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z col jmp __b1 } // irq irq: { // entry interrupt(KERNEL_MIN) // asm // asm { lda$dc0d } lda $dc0d // *BG_COLOR = col // [8] *((const nomodify byte*) BG_COLOR) ← (volatile byte) col -- _deref_pbuc1=vbuz1 lda.z col sta BG_COLOR // if(col!=0) // [9] if((volatile byte) col!=(byte) 0) goto irq::@1 -- vbuz1_neq_0_then_la1 lda.z col cmp #0 bne __b1 // irq::@2 // col += 2 // [10] (volatile byte) col ← (volatile byte) col + (byte) 2 -- vbuz1=vbuz1_plus_2 clc adc #2 sta.z col // irq::@return // } // [11] return - exit interrupt(KERNEL_MIN) jmp $ea81 // irq::@1 __b1: // col++; // [12] (volatile byte) col ← ++ (volatile byte) col -- vbuz1=_inc_vbuz1 inc.z col jmp $ea81 } // File Data