Added struct type cast to parameter value list main::$0 = call print('c', (struct format){ '-', '-' }) Inlined call call __init CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start::@1 idx#15 = phi( __start::@1/idx#16 ) print::c#0 = 'c' print::fmt_prefix#0 = '-' print::fmt_postfix#0 = '-' call print to:main::@1 main::@1: scope:[main] from main idx#9 = phi( main/idx#5 ) idx#0 = idx#9 to:main::@return main::@return: scope:[main] from main::@1 idx#10 = phi( main::@1/idx#0 ) idx#1 = idx#10 return to:@return void print(char c , char fmt_prefix , char fmt_postfix) print: scope:[print] from main print::fmt_postfix#1 = phi( main/print::fmt_postfix#0 ) print::c#1 = phi( main/print::c#0 ) idx#11 = phi( main/idx#15 ) print::fmt_prefix#1 = phi( main/print::fmt_prefix#0 ) SCREEN[idx#11] = print::fmt_prefix#1 idx#2 = ++ idx#11 SCREEN[idx#2] = print::c#1 idx#3 = ++ idx#2 SCREEN[idx#3] = print::fmt_postfix#1 idx#4 = ++ idx#3 to:print::@return print::@return: scope:[print] from print idx#12 = phi( print/idx#4 ) idx#5 = idx#12 return to:@return void __start() __start: scope:[__start] from to:__start::__init1 __start::__init1: scope:[__start] from __start idx#6 = 0 to:__start::@1 __start::@1: scope:[__start] from __start::__init1 idx#16 = phi( __start::__init1/idx#6 ) call main to:__start::@2 __start::@2: scope:[__start] from __start::@1 idx#13 = phi( __start::@1/idx#1 ) idx#7 = idx#13 to:__start::@return __start::@return: scope:[__start] from __start::@2 idx#14 = phi( __start::@2/idx#7 ) idx#8 = idx#14 return to:@return SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() char idx char idx#0 char idx#1 char idx#10 char idx#11 char idx#12 char idx#13 char idx#14 char idx#15 char idx#16 char idx#2 char idx#3 char idx#4 char idx#5 char idx#6 char idx#7 char idx#8 char idx#9 void main() void print(char c , char fmt_prefix , char fmt_postfix) char print::c char print::c#0 char print::c#1 struct format print::fmt char print::fmt_postfix char print::fmt_postfix#0 char print::fmt_postfix#1 char print::fmt_prefix char print::fmt_prefix#0 char print::fmt_prefix#1 Simplifying constant pointer cast (char *) 1024 Successful SSA optimization PassNCastSimplification Alias idx#0 = idx#9 idx#10 idx#1 Alias idx#12 = idx#4 idx#5 Alias idx#16 = idx#6 Alias idx#13 = idx#7 idx#14 idx#8 Successful SSA optimization Pass2AliasElimination Identical Phi Values idx#15 idx#16 Identical Phi Values idx#0 idx#12 Identical Phi Values print::fmt_prefix#1 print::fmt_prefix#0 Identical Phi Values idx#11 idx#15 Identical Phi Values print::c#1 print::c#0 Identical Phi Values print::fmt_postfix#1 print::fmt_postfix#0 Identical Phi Values idx#13 idx#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant print::c#0 = 'c' Constant print::fmt_prefix#0 = '-' Constant print::fmt_postfix#0 = '-' Constant idx#16 = 0 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [8] SCREEN[idx#16] = print::fmt_prefix#0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable idx#12 and assignment [7] idx#12 = ++ idx#3 Successful SSA optimization PassNEliminateUnusedVars Removing unused procedure __start Removing unused procedure block __start Removing unused procedure block __start::__init1 Removing unused procedure block __start::@1 Removing unused procedure block __start::@2 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart Constant right-side identified [3] idx#2 = ++ idx#16 Successful SSA optimization Pass2ConstantRValueConsolidation Constant idx#2 = ++idx#16 Successful SSA optimization Pass2ConstantIdentification Constant right-side identified [4] idx#3 = ++ idx#2 Successful SSA optimization Pass2ConstantRValueConsolidation Constant idx#3 = ++idx#2 Successful SSA optimization Pass2ConstantIdentification Inlining constant with different constant siblings idx#16 Inlining constant with different constant siblings idx#2 Inlining constant with different constant siblings idx#3 Constant inlined idx#2 = ++0 Constant inlined idx#16 = 0 Constant inlined idx#3 = ++++0 Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *(SCREEN+++0) Consolidated array index constant in *(SCREEN+++++0) Successful SSA optimization Pass2ConstantAdditionElimination Simplifying constant integer increment ++0 Simplifying constant integer increment ++0 Successful SSA optimization Pass2ConstantSimplification Simplifying constant integer increment ++1 Successful SSA optimization Pass2ConstantSimplification Adding NOP phi() at start of main Adding NOP phi() at start of main::@1 CALL GRAPH Calls in [main] to print:1 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block label main::@1 Adding NOP phi() at start of main FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] phi() [1] call print to:main::@return main::@return: scope:[main] from main [2] return to:@return void print(char c , char fmt_prefix , char fmt_postfix) print: scope:[print] from main [3] *SCREEN = print::fmt_prefix#0 [4] *(SCREEN+1) = print::c#0 [5] *(SCREEN+2) = print::fmt_postfix#0 to:print::@return print::@return: scope:[print] from print [6] return to:@return VARIABLE REGISTER WEIGHTS char idx void main() void print(char c , char fmt_prefix , char fmt_postfix) char print::c struct format print::fmt char print::fmt_postfix char print::fmt_prefix Initial phi equivalence classes Complete equivalence classes REGISTER UPLIFT POTENTIAL REGISTERS Statement [3] *SCREEN = print::fmt_prefix#0 [ ] ( print:1 [ ] { } ) always clobbers reg byte a Statement [4] *(SCREEN+1) = print::c#0 [ ] ( print:1 [ ] { } ) always clobbers reg byte a Statement [5] *(SCREEN+2) = print::fmt_postfix#0 [ ] ( print:1 [ ] { } ) always clobbers reg byte a REGISTER UPLIFT SCOPES Uplift Scope [format] Uplift Scope [main] Uplift Scope [print] Uplift Scope [] Uplifting [format] best 42 combination Uplifting [main] best 42 combination Uplifting [print] best 42 combination Uplifting [] best 42 combination ASSEMBLER BEFORE OPTIMIZATION // File Comments // Illustrates problem with passing an inline struct value as a parameter // Upstart // Commodore 64 PRG executable file .file [name="problem-struct-inline-parameter-1.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) // Global Constants & labels .label SCREEN = $400 .segment Code // main main: { // [1] call print jsr print jmp __breturn // main::@return __breturn: // [2] return rts } // print // void print(char c, char fmt_prefix, char fmt_postfix) print: { .const c = 'c' .const fmt_prefix = '-' .const fmt_postfix = '-' // [3] *SCREEN = print::fmt_prefix#0 -- _deref_pbuc1=vbuc2 lda #fmt_prefix sta SCREEN // [4] *(SCREEN+1) = print::c#0 -- _deref_pbuc1=vbuc2 lda #c sta SCREEN+1 // [5] *(SCREEN+2) = print::fmt_postfix#0 -- _deref_pbuc1=vbuc2 lda #fmt_postfix sta SCREEN+2 jmp __breturn // print::@return __breturn: // [6] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 char idx void main() void print(char c , char fmt_prefix , char fmt_postfix) char print::c __constant char print::c#0 = 'c' // c struct format print::fmt char print::fmt_postfix __constant char print::fmt_postfix#0 = '-' // fmt_postfix char print::fmt_prefix __constant char print::fmt_prefix#0 = '-' // fmt_prefix FINAL ASSEMBLER Score: 36 // File Comments // Illustrates problem with passing an inline struct value as a parameter // Upstart // Commodore 64 PRG executable file .file [name="problem-struct-inline-parameter-1.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) // Global Constants & labels .label SCREEN = $400 .segment Code // main main: { // print('c', { '-', '-' } ) // [1] call print jsr print // main::@return // } // [2] return rts } // print // void print(char c, char fmt_prefix, char fmt_postfix) print: { .const c = 'c' .const fmt_prefix = '-' .const fmt_postfix = '-' // SCREEN[idx++] = fmt.prefix // [3] *SCREEN = print::fmt_prefix#0 -- _deref_pbuc1=vbuc2 lda #fmt_prefix sta SCREEN // SCREEN[idx++] = c // [4] *(SCREEN+1) = print::c#0 -- _deref_pbuc1=vbuc2 lda #c sta SCREEN+1 // SCREEN[idx++] = fmt.postfix // [5] *(SCREEN+2) = print::fmt_postfix#0 -- _deref_pbuc1=vbuc2 lda #fmt_postfix sta SCREEN+2 // print::@return // } // [6] return rts } // File Data