Identified constant variable (byte*) screen Inlined call (byte~) main::$0 ← call toUpper (byte) 'c' true Inlined call (byte~) main::$1 ← call toUpper (byte) 'm' false Culled Empty Block (label) main::toUpper1_@3 Culled Empty Block (label) main::toUpper2_@3 Culled Empty Block (label) @1 CONTROL FLOW GRAPH SSA @begin: scope:[] from to:@2 (void()) main() main: scope:[main] from @2 (byte) main::toUpper1_ch#0 ← (byte) 'c' (bool) main::toUpper1_bo#0 ← true to:main::toUpper1 main::toUpper1: scope:[main] from main (bool) main::toUpper1_bo#1 ← phi( main/(bool) main::toUpper1_bo#0 ) (byte) main::toUpper1_ch#1 ← phi( main/(byte) main::toUpper1_ch#0 ) (byte) main::toUpper1_res#0 ← (byte) main::toUpper1_ch#1 (bool~) main::toUpper1_$0 ← ! (bool) main::toUpper1_bo#1 if((bool~) main::toUpper1_$0) goto main::toUpper1_@1 to:main::toUpper1_@2 main::toUpper1_@1: scope:[main] from main::toUpper1 main::toUpper1_@2 (byte) main::toUpper1_res#2 ← phi( main::toUpper1/(byte) main::toUpper1_res#0 main::toUpper1_@2/(byte) main::toUpper1_res#1 ) (byte) main::toUpper1_return#0 ← (byte) main::toUpper1_res#2 to:main::toUpper1_@return main::toUpper1_@2: scope:[main] from main::toUpper1 (byte) main::toUpper1_res#3 ← phi( main::toUpper1/(byte) main::toUpper1_res#0 ) (byte) main::toUpper1_res#1 ← (byte) main::toUpper1_res#3 + (number) $40 to:main::toUpper1_@1 main::toUpper1_@return: scope:[main] from main::toUpper1_@1 (byte) main::toUpper1_return#2 ← phi( main::toUpper1_@1/(byte) main::toUpper1_return#0 ) (byte) main::toUpper1_return#1 ← (byte) main::toUpper1_return#2 to:main::@1 main::@1: scope:[main] from main::toUpper1_@return (byte) main::toUpper1_return#3 ← phi( main::toUpper1_@return/(byte) main::toUpper1_return#1 ) (byte~) main::$0 ← (byte) main::toUpper1_return#3 *((const byte*) screen + (number) 0) ← (byte~) main::$0 (byte) main::toUpper2_ch#0 ← (byte) 'm' (bool) main::toUpper2_bo#0 ← false to:main::toUpper2 main::toUpper2: scope:[main] from main::@1 (bool) main::toUpper2_bo#1 ← phi( main::@1/(bool) main::toUpper2_bo#0 ) (byte) main::toUpper2_ch#1 ← phi( main::@1/(byte) main::toUpper2_ch#0 ) (byte) main::toUpper2_res#0 ← (byte) main::toUpper2_ch#1 (bool~) main::toUpper2_$0 ← ! (bool) main::toUpper2_bo#1 if((bool~) main::toUpper2_$0) goto main::toUpper2_@1 to:main::toUpper2_@2 main::toUpper2_@1: scope:[main] from main::toUpper2 main::toUpper2_@2 (byte) main::toUpper2_res#2 ← phi( main::toUpper2/(byte) main::toUpper2_res#0 main::toUpper2_@2/(byte) main::toUpper2_res#1 ) (byte) main::toUpper2_return#0 ← (byte) main::toUpper2_res#2 to:main::toUpper2_@return main::toUpper2_@2: scope:[main] from main::toUpper2 (byte) main::toUpper2_res#3 ← phi( main::toUpper2/(byte) main::toUpper2_res#0 ) (byte) main::toUpper2_res#1 ← (byte) main::toUpper2_res#3 + (number) $40 to:main::toUpper2_@1 main::toUpper2_@return: scope:[main] from main::toUpper2_@1 (byte) main::toUpper2_return#2 ← phi( main::toUpper2_@1/(byte) main::toUpper2_return#0 ) (byte) main::toUpper2_return#1 ← (byte) main::toUpper2_return#2 to:main::@2 main::@2: scope:[main] from main::toUpper2_@return (byte) main::toUpper2_return#3 ← phi( main::toUpper2_@return/(byte) main::toUpper2_return#1 ) (byte~) main::$1 ← (byte) main::toUpper2_return#3 *((const byte*) screen + (number) 1) ← (byte~) main::$1 to:main::@return main::@return: scope:[main] from main::@2 return to:@return @2: scope:[] from @begin call main to:@3 @3: scope:[] from @2 to:@end @end: scope:[] from @3 SYMBOL TABLE SSA (label) @2 (label) @3 (label) @begin (label) @end (void()) main() (byte~) main::$0 (byte~) main::$1 (label) main::@1 (label) main::@2 (label) main::@return (label) main::toUpper1 (bool~) main::toUpper1_$0 (label) main::toUpper1_@1 (label) main::toUpper1_@2 (label) main::toUpper1_@return (bool) main::toUpper1_bo (bool) main::toUpper1_bo#0 (bool) main::toUpper1_bo#1 (byte) main::toUpper1_ch (byte) main::toUpper1_ch#0 (byte) main::toUpper1_ch#1 (byte) main::toUpper1_res (byte) main::toUpper1_res#0 (byte) main::toUpper1_res#1 (byte) main::toUpper1_res#2 (byte) main::toUpper1_res#3 (byte) main::toUpper1_return (byte) main::toUpper1_return#0 (byte) main::toUpper1_return#1 (byte) main::toUpper1_return#2 (byte) main::toUpper1_return#3 (label) main::toUpper2 (bool~) main::toUpper2_$0 (label) main::toUpper2_@1 (label) main::toUpper2_@2 (label) main::toUpper2_@return (bool) main::toUpper2_bo (bool) main::toUpper2_bo#0 (bool) main::toUpper2_bo#1 (byte) main::toUpper2_ch (byte) main::toUpper2_ch#0 (byte) main::toUpper2_ch#1 (byte) main::toUpper2_res (byte) main::toUpper2_res#0 (byte) main::toUpper2_res#1 (byte) main::toUpper2_res#2 (byte) main::toUpper2_res#3 (byte) main::toUpper2_return (byte) main::toUpper2_return#0 (byte) main::toUpper2_return#1 (byte) main::toUpper2_return#2 (byte) main::toUpper2_return#3 (const byte*) screen = (byte*)(number) $400 Adding number conversion cast (unumber) $40 in (byte) main::toUpper1_res#1 ← (byte) main::toUpper1_res#3 + (number) $40 Adding number conversion cast (unumber) 0 in *((const byte*) screen + (number) 0) ← (byte~) main::$0 Adding number conversion cast (unumber) $40 in (byte) main::toUpper2_res#1 ← (byte) main::toUpper2_res#3 + (number) $40 Adding number conversion cast (unumber) 1 in *((const byte*) screen + (number) 1) ← (byte~) main::$1 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast $40 Simplifying constant integer cast 0 Simplifying constant integer cast $40 Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $40 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $40 Finalized unsigned number type (byte) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias main::toUpper1_ch#0 = main::toUpper1_ch#1 main::toUpper1_res#0 main::toUpper1_res#3 Alias main::toUpper1_bo#0 = main::toUpper1_bo#1 Alias main::toUpper1_return#0 = main::toUpper1_res#2 main::toUpper1_return#2 main::toUpper1_return#1 main::toUpper1_return#3 main::$0 Alias main::toUpper2_ch#0 = main::toUpper2_ch#1 main::toUpper2_res#0 main::toUpper2_res#3 Alias main::toUpper2_bo#0 = main::toUpper2_bo#1 Alias main::toUpper2_return#0 = main::toUpper2_res#2 main::toUpper2_return#2 main::toUpper2_return#1 main::toUpper2_return#3 main::$1 Successful SSA optimization Pass2AliasElimination Rewriting ! if()-condition to reversed if() [2] (bool~) main::toUpper1_$0 ← ! (bool) main::toUpper1_bo#0 Rewriting ! if()-condition to reversed if() [9] (bool~) main::toUpper2_$0 ← ! (bool) main::toUpper2_bo#0 Successful SSA optimization Pass2ConditionalAndOrRewriting Constant (const byte) main::toUpper1_ch#0 = 'c' Constant (const bool) main::toUpper1_bo#0 = true Constant (const byte) main::toUpper2_ch#0 = 'm' Constant (const bool) main::toUpper2_bo#0 = false Successful SSA optimization Pass2ConstantIdentification Removing PHI-reference to removed block (main::toUpper1) in block main::toUpper1_@1 if() condition always true - replacing block destination [3] if((const bool) main::toUpper1_bo#0) goto main::toUpper1_@2 if() condition always false - eliminating [10] if((const bool) main::toUpper2_bo#0) goto main::toUpper2_@2 Successful SSA optimization Pass2ConstantIfs Simplifying expression containing zero screen in [6] *((const byte*) screen + (byte) 0) ← (byte) main::toUpper1_return#0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant (const bool) main::toUpper1_bo#0 Eliminating unused constant (const bool) main::toUpper2_bo#0 Successful SSA optimization PassNEliminateUnusedVars Eliminating variable (byte) main::toUpper2_res#1 from unused block main::toUpper2_@2 Removing PHI-reference to removed block (main::toUpper2_@2) in block main::toUpper2_@1 Removing unused block main::toUpper2_@2 Successful SSA optimization Pass2EliminateUnusedBlocks Alias main::toUpper1_return#0 = main::toUpper1_res#1 Successful SSA optimization Pass2AliasElimination Identical Phi Values (byte) main::toUpper2_return#0 (const byte) main::toUpper2_ch#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant right-side identified [0] (byte) main::toUpper1_return#0 ← (const byte) main::toUpper1_ch#0 + (byte) $40 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::toUpper1_return#0 = main::toUpper1_ch#0+$40 Successful SSA optimization Pass2ConstantIdentification Consolidated array index constant in *(screen+1) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::toUpper1 Adding NOP phi() at start of main::toUpper1_@2 Adding NOP phi() at start of main::toUpper1_@1 Adding NOP phi() at start of main::toUpper1_@return Adding NOP phi() at start of main::toUpper2 Adding NOP phi() at start of main::toUpper2_@1 Adding NOP phi() at start of main::toUpper2_@return CALL GRAPH Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @3 Culled Empty Block (label) main::toUpper1_@2 Culled Empty Block (label) main::toUpper1_@1 Culled Empty Block (label) main::toUpper1_@return Culled Empty Block (label) main::toUpper2_@1 Culled Empty Block (label) main::toUpper2_@return Renumbering block @2 to @1 Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::toUpper1 Adding NOP phi() at start of main::toUpper2 FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] phi() to:@1 @1: scope:[] from @begin [1] phi() [2] call main to:@end @end: scope:[] from @1 [3] phi() (void()) main() main: scope:[main] from @1 [4] phi() to:main::toUpper1 main::toUpper1: scope:[main] from main [5] phi() to:main::@1 main::@1: scope:[main] from main::toUpper1 [6] *((const byte*) screen) ← (const byte) main::toUpper1_return#0 to:main::toUpper2 main::toUpper2: scope:[main] from main::@1 [7] phi() to:main::@2 main::@2: scope:[main] from main::toUpper2 [8] *((const byte*) screen+(byte) 1) ← (const byte) main::toUpper2_ch#0 to:main::@return main::@return: scope:[main] from main::@2 [9] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() (bool) main::toUpper1_bo (byte) main::toUpper1_ch (byte) main::toUpper1_res (byte) main::toUpper1_return (bool) main::toUpper2_bo (byte) main::toUpper2_ch (byte) main::toUpper2_res (byte) main::toUpper2_return Initial phi equivalence classes Complete equivalence classes INITIAL ASM Target platform is c64basic / MOS6502X // File Comments // Test inlining a slightly complex print function (containing an if) // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label screen = $400 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main // [4] phi from @1 to main [phi:@1->main] main_from___b1: jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { .const toUpper1_ch = 'c' .const toUpper2_ch = 'm' .const toUpper1_return = toUpper1_ch+$40 // [5] phi from main to main::toUpper1 [phi:main->main::toUpper1] toUpper1_from_main: jmp toUpper1 // main::toUpper1 toUpper1: jmp __b1 // main::@1 __b1: // [6] *((const byte*) screen) ← (const byte) main::toUpper1_return#0 -- _deref_pbuc1=vbuc2 lda #toUpper1_return sta screen // [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2] toUpper2_from___b1: jmp toUpper2 // main::toUpper2 toUpper2: jmp __b2 // main::@2 __b2: // [8] *((const byte*) screen+(byte) 1) ← (const byte) main::toUpper2_ch#0 -- _deref_pbuc1=vbuc2 lda #toUpper2_ch sta screen+1 jmp __breturn // main::@return __breturn: // [9] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [6] *((const byte*) screen) ← (const byte) main::toUpper1_return#0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a Statement [8] *((const byte*) screen+(byte) 1) ← (const byte) main::toUpper2_ch#0 [ ] ( main:2 [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [main] Uplift Scope [] Uplifting [main] best 99 combination Uplifting [] best 99 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Test inlining a slightly complex print function (containing an if) // Upstart .pc = $801 "Basic" :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels .label screen = $400 // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 // @1 __b1: // [2] call main // [4] phi from @1 to main [phi:@1->main] main_from___b1: jsr main // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end __bend: // main main: { .const toUpper1_ch = 'c' .const toUpper2_ch = 'm' .const toUpper1_return = toUpper1_ch+$40 // [5] phi from main to main::toUpper1 [phi:main->main::toUpper1] toUpper1_from_main: jmp toUpper1 // main::toUpper1 toUpper1: jmp __b1 // main::@1 __b1: // [6] *((const byte*) screen) ← (const byte) main::toUpper1_return#0 -- _deref_pbuc1=vbuc2 lda #toUpper1_return sta screen // [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2] toUpper2_from___b1: jmp toUpper2 // main::toUpper2 toUpper2: jmp __b2 // main::@2 __b2: // [8] *((const byte*) screen+(byte) 1) ← (const byte) main::toUpper2_ch#0 -- _deref_pbuc1=vbuc2 lda #toUpper2_ch sta screen+1 jmp __breturn // main::@return __breturn: // [9] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp toUpper1 Removing instruction jmp __b1 Removing instruction jmp toUpper2 Removing instruction jmp __b2 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __b1_from___bbegin: Removing instruction __b1: Removing instruction main_from___b1: Removing instruction __bend_from___b1: Removing instruction toUpper1_from_main: Removing instruction toUpper1: Removing instruction toUpper2_from___b1: Removing instruction toUpper2: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __bend: Removing instruction __b1: Removing instruction __b2: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination Updating BasicUpstart to call main directly Removing instruction jsr main Succesful ASM optimization Pass5SkipBegin Removing instruction __bbegin: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end (void()) main() (label) main::@1 (label) main::@2 (label) main::@return (label) main::toUpper1 (bool) main::toUpper1_bo (byte) main::toUpper1_ch (const byte) main::toUpper1_ch#0 toUpper1_ch = (byte) 'c' (byte) main::toUpper1_res (byte) main::toUpper1_return (const byte) main::toUpper1_return#0 toUpper1_return = (const byte) main::toUpper1_ch#0+(byte) $40 (label) main::toUpper2 (bool) main::toUpper2_bo (byte) main::toUpper2_ch (const byte) main::toUpper2_ch#0 toUpper2_ch = (byte) 'm' (byte) main::toUpper2_res (byte) main::toUpper2_return (const byte*) screen = (byte*) 1024 FINAL ASSEMBLER Score: 18 // File Comments // Test inlining a slightly complex print function (containing an if) // Upstart .pc = $801 "Basic" :BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels .label screen = $400 // @begin // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main // [4] phi from @1 to main [phi:@1->main] // [3] phi from @1 to @end [phi:@1->@end] // @end // main main: { .const toUpper1_ch = 'c' .const toUpper2_ch = 'm' .const toUpper1_return = toUpper1_ch+$40 // [5] phi from main to main::toUpper1 [phi:main->main::toUpper1] // main::toUpper1 // main::@1 // screen[0] = toUpper('c',true) // [6] *((const byte*) screen) ← (const byte) main::toUpper1_return#0 -- _deref_pbuc1=vbuc2 lda #toUpper1_return sta screen // [7] phi from main::@1 to main::toUpper2 [phi:main::@1->main::toUpper2] // main::toUpper2 // main::@2 // screen[1] = toUpper('m',false) // [8] *((const byte*) screen+(byte) 1) ← (const byte) main::toUpper2_ch#0 -- _deref_pbuc1=vbuc2 lda #toUpper2_ch sta screen+1 // main::@return // } // [9] return rts } // File Data