1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-29 03:56:15 +00:00
kickc/src/test/ref/memcpy-1.log

1354 lines
53 KiB
Plaintext

CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
memcpy: scope:[memcpy] from main::@4 main::@5
(word) memcpy::num#2 ← phi( main::@4/(word) memcpy::num#0 main::@5/(word) memcpy::num#1 )
(void*) memcpy::destination#2 ← phi( main::@4/(void*) memcpy::destination#0 main::@5/(void*) memcpy::destination#1 )
(void*) memcpy::source#2 ← phi( main::@4/(void*) memcpy::source#0 main::@5/(void*) memcpy::source#1 )
(byte*) memcpy::src#0 ← ((byte*)) (void*) memcpy::source#2
(byte*) memcpy::dst#0 ← ((byte*)) (void*) memcpy::destination#2
(byte*~) memcpy::$2 ← (byte*)(void*) memcpy::source#2
(byte*~) memcpy::$0 ← (byte*~) memcpy::$2 + (word) memcpy::num#2
(byte*) memcpy::src_end#0 ← (byte*~) memcpy::$0
to:memcpy::@1
memcpy::@1: scope:[memcpy] from memcpy memcpy::@2
(void*) memcpy::destination#4 ← phi( memcpy/(void*) memcpy::destination#2 memcpy::@2/(void*) memcpy::destination#5 )
(byte*) memcpy::dst#3 ← phi( memcpy/(byte*) memcpy::dst#0 memcpy::@2/(byte*) memcpy::dst#1 )
(byte*) memcpy::src_end#1 ← phi( memcpy/(byte*) memcpy::src_end#0 memcpy::@2/(byte*) memcpy::src_end#2 )
(byte*) memcpy::src#2 ← phi( memcpy/(byte*) memcpy::src#0 memcpy::@2/(byte*) memcpy::src#1 )
(bool~) memcpy::$1 ← (byte*) memcpy::src#2 != (byte*) memcpy::src_end#1
if((bool~) memcpy::$1) goto memcpy::@2
to:memcpy::@3
memcpy::@2: scope:[memcpy] from memcpy::@1
(void*) memcpy::destination#5 ← phi( memcpy::@1/(void*) memcpy::destination#4 )
(byte*) memcpy::src_end#2 ← phi( memcpy::@1/(byte*) memcpy::src_end#1 )
(byte*) memcpy::dst#2 ← phi( memcpy::@1/(byte*) memcpy::dst#3 )
(byte*) memcpy::src#3 ← phi( memcpy::@1/(byte*) memcpy::src#2 )
*((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#3)
(byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
(byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#3
to:memcpy::@1
memcpy::@3: scope:[memcpy] from memcpy::@1
(void*) memcpy::destination#3 ← phi( memcpy::@1/(void*) memcpy::destination#4 )
(void*) memcpy::return#0 ← (void*) memcpy::destination#3
to:memcpy::@return
memcpy::@return: scope:[memcpy] from memcpy::@3
(void*) memcpy::return#4 ← phi( memcpy::@3/(void*) memcpy::return#0 )
(void*) memcpy::return#1 ← (void*) memcpy::return#4
return
to:@return
(void()) main()
main: scope:[main] from @1
(byte*) main::sc#0 ← (const nomodify byte*) SCREEN
(byte*) main::camelot#0 ← (const to_nomodify byte*) CAMELOT
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
(byte*) main::sc#2 ← phi( main/(byte*) main::sc#0 main::@1/(byte*) main::sc#1 )
(byte*) main::camelot#2 ← phi( main/(byte*) main::camelot#0 main::@1/(byte*) main::camelot#1 )
*((byte*) main::sc#2) ← *((byte*) main::camelot#2)
(byte*) main::sc#1 ← ++ (byte*) main::sc#2
(byte*) main::camelot#1 ← ++ (byte*) main::camelot#2
(byte) main::i#1 ← (byte) main::i#2 + rangenext(0,6)
(bool~) main::$2 ← (byte) main::i#1 != rangelast(0,6)
if((bool~) main::$2) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1
(byte*) main::sc2#0 ← (const nomodify byte*) SCREEN+(number) $28
(byte*) main::reigns#0 ← (const byte*) main::$4
(byte) main::i1#0 ← (byte) 0
to:main::@3
main::@3: scope:[main] from main::@2 main::@3
(byte) main::i1#2 ← phi( main::@2/(byte) main::i1#0 main::@3/(byte) main::i1#1 )
(byte*) main::sc2#2 ← phi( main::@2/(byte*) main::sc2#0 main::@3/(byte*) main::sc2#1 )
(byte*) main::reigns#2 ← phi( main::@2/(byte*) main::reigns#0 main::@3/(byte*) main::reigns#1 )
*((byte*) main::sc2#2) ← *((byte*) main::reigns#2)
(byte*) main::sc2#1 ← ++ (byte*) main::sc2#2
(byte*) main::reigns#1 ← ++ (byte*) main::reigns#2
(byte) main::i1#1 ← (byte) main::i1#2 + rangenext(0,5)
(bool~) main::$3 ← (byte) main::i1#1 != rangelast(0,5)
if((bool~) main::$3) goto main::@3
to:main::@4
main::@4: scope:[main] from main::@3
(void*) memcpy::destination#0 ← (void*)(const nomodify byte*) SCREEN+(number) $a
(void*) memcpy::source#0 ← (void*)(const to_nomodify byte*) CAMELOT
(word) memcpy::num#0 ← (number) 7
call memcpy
(void*) memcpy::return#2 ← (void*) memcpy::return#1
to:main::@5
main::@5: scope:[main] from main::@4
(void*) memcpy::destination#1 ← (void*)(const nomodify byte*) SCREEN+(number) $32
(void*) memcpy::source#1 ← (void*)(const byte*) main::$5
(word) memcpy::num#1 ← (number) 5
call memcpy
(void*) memcpy::return#3 ← (void*) memcpy::return#1
to:main::@6
main::@6: scope:[main] from main::@5
to:main::@return
main::@return: scope:[main] from main::@6
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 to_nomodify byte*) CAMELOT[] = (byte*) "camelot"
(const nomodify byte*) SCREEN = (byte*)(number) $400
(void()) main()
(bool~) main::$2
(bool~) main::$3
(const byte*) main::$4[(byte) 7] = (byte*) "reigns"
(const byte*) main::$5[(byte) 6] = (byte*) "rules"
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@return
(byte*) main::camelot
(byte*) main::camelot#0
(byte*) main::camelot#1
(byte*) main::camelot#2
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i1
(byte) main::i1#0
(byte) main::i1#1
(byte) main::i1#2
(byte*) main::reigns
(byte*) main::reigns#0
(byte*) main::reigns#1
(byte*) main::reigns#2
(byte*) main::sc
(byte*) main::sc#0
(byte*) main::sc#1
(byte*) main::sc#2
(byte*) main::sc2
(byte*) main::sc2#0
(byte*) main::sc2#1
(byte*) main::sc2#2
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(byte*~) memcpy::$0
(bool~) memcpy::$1
(byte*~) memcpy::$2
(label) memcpy::@1
(label) memcpy::@2
(label) memcpy::@3
(label) memcpy::@return
(void*) memcpy::destination
(void*) memcpy::destination#0
(void*) memcpy::destination#1
(void*) memcpy::destination#2
(void*) memcpy::destination#3
(void*) memcpy::destination#4
(void*) memcpy::destination#5
(byte*) memcpy::dst
(byte*) memcpy::dst#0
(byte*) memcpy::dst#1
(byte*) memcpy::dst#2
(byte*) memcpy::dst#3
(word) memcpy::num
(word) memcpy::num#0
(word) memcpy::num#1
(word) memcpy::num#2
(void*) memcpy::return
(void*) memcpy::return#0
(void*) memcpy::return#1
(void*) memcpy::return#2
(void*) memcpy::return#3
(void*) memcpy::return#4
(void*) memcpy::source
(void*) memcpy::source#0
(void*) memcpy::source#1
(void*) memcpy::source#2
(byte*) memcpy::src
(byte*) memcpy::src#0
(byte*) memcpy::src#1
(byte*) memcpy::src#2
(byte*) memcpy::src#3
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0
(byte*) memcpy::src_end#1
(byte*) memcpy::src_end#2
Adding number conversion cast (unumber) $28 in (byte*) main::sc2#0 ← (const nomodify byte*) SCREEN+(number) $28
Adding number conversion cast (unumber) $a in (void*) memcpy::destination#0 ← (void*)(const nomodify byte*) SCREEN+(number) $a
Adding number conversion cast (unumber) 7 in (word) memcpy::num#0 ← (number) 7
Adding number conversion cast (unumber) $32 in (void*) memcpy::destination#1 ← (void*)(const nomodify byte*) SCREEN+(number) $32
Adding number conversion cast (unumber) 5 in (word) memcpy::num#1 ← (number) 5
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) memcpy::src#0 ← (byte*)(void*) memcpy::source#2
Inlining cast (byte*) memcpy::dst#0 ← (byte*)(void*) memcpy::destination#2
Inlining cast (word) memcpy::num#0 ← (unumber)(number) 7
Inlining cast (word) memcpy::num#1 ← (unumber)(number) 5
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast $28
Simplifying constant integer cast $a
Simplifying constant integer cast 7
Simplifying constant integer cast $32
Simplifying constant integer cast 5
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $28
Finalized unsigned number type (byte) $a
Finalized unsigned number type (byte) 7
Finalized unsigned number type (byte) $32
Finalized unsigned number type (byte) 5
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias memcpy::src_end#0 = memcpy::$0
Alias memcpy::src#2 = memcpy::src#3
Alias memcpy::dst#2 = memcpy::dst#3
Alias memcpy::src_end#1 = memcpy::src_end#2
Alias memcpy::destination#3 = memcpy::destination#5 memcpy::destination#4 memcpy::return#0 memcpy::return#4 memcpy::return#1
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte*) memcpy::src_end#1 (byte*) memcpy::src_end#0
Identical Phi Values (void*) memcpy::destination#3 (void*) memcpy::destination#2
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) memcpy::$1 [7] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2
Simple Condition (bool~) main::$2 [21] if((byte) main::i#1!=rangelast(0,6)) goto main::@1
Simple Condition (bool~) main::$3 [31] if((byte) main::i1#1!=rangelast(0,5)) goto main::@3
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::sc#0 = SCREEN
Constant (const byte*) main::camelot#0 = CAMELOT
Constant (const byte) main::i#0 = 0
Constant (const byte*) main::sc2#0 = SCREEN+$28
Constant (const byte*) main::reigns#0 = main::$4
Constant (const byte) main::i1#0 = 0
Constant (const void*) memcpy::destination#0 = (void*)SCREEN+$a
Constant (const void*) memcpy::source#0 = (void*)CAMELOT
Constant (const word) memcpy::num#0 = 7
Constant (const void*) memcpy::destination#1 = (void*)SCREEN+$32
Constant (const void*) memcpy::source#1 = (void*)main::$5
Constant (const word) memcpy::num#1 = 5
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [19] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [21] if(main::i#1!=rangelast(0,6)) goto main::@1 to (number) 7
Resolved ranged next value [29] main::i1#1 ← ++ main::i1#2 to ++
Resolved ranged comparison value [31] if(main::i1#1!=rangelast(0,5)) goto main::@3 to (number) 6
Eliminating unused variable (void*) memcpy::return#2 and assignment [24] (void*) memcpy::return#2 ← (void*) memcpy::destination#2
Eliminating unused variable (void*) memcpy::return#3 and assignment [26] (void*) memcpy::return#3 ← (void*) memcpy::destination#2
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 7 in if((byte) main::i#1!=(number) 7) goto main::@1
Adding number conversion cast (unumber) 6 in if((byte) main::i1#1!=(number) 6) goto main::@3
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 7
Simplifying constant integer cast 6
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 7
Finalized unsigned number type (byte) 6
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining Noop Cast [1] (byte*) memcpy::src#0 ← (byte*)(void*) memcpy::source#2 keeping memcpy::source#2
Inlining Noop Cast [2] (byte*) memcpy::dst#0 ← (byte*)(void*) memcpy::destination#2 keeping memcpy::destination#2
Inlining Noop Cast [3] (byte*~) memcpy::$2 ← (byte*)(void*) memcpy::source#2 keeping memcpy::source#2
Successful SSA optimization Pass2NopCastInlining
Inlining constant with var siblings (const void*) memcpy::destination#0
Inlining constant with var siblings (const void*) memcpy::source#0
Inlining constant with var siblings (const word) memcpy::num#0
Inlining constant with var siblings (const void*) memcpy::destination#1
Inlining constant with var siblings (const void*) memcpy::source#1
Inlining constant with var siblings (const word) memcpy::num#1
Inlining constant with var siblings (const byte*) main::sc#0
Inlining constant with var siblings (const byte*) main::camelot#0
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const byte*) main::sc2#0
Inlining constant with var siblings (const byte*) main::reigns#0
Inlining constant with var siblings (const byte) main::i1#0
Constant inlined main::camelot#0 = (const to_nomodify byte*) CAMELOT
Constant inlined main::sc#0 = (const nomodify byte*) SCREEN
Constant inlined memcpy::destination#0 = (void*)(const nomodify byte*) SCREEN+(byte) $a
Constant inlined memcpy::destination#1 = (void*)(const nomodify byte*) SCREEN+(byte) $32
Constant inlined memcpy::source#0 = (void*)(const to_nomodify byte*) CAMELOT
Constant inlined memcpy::num#1 = (byte) 5
Constant inlined memcpy::num#0 = (byte) 7
Constant inlined memcpy::source#1 = (void*)(const byte*) main::$5
Constant inlined main::i#0 = (byte) 0
Constant inlined main::i1#0 = (byte) 0
Constant inlined main::$4 = (const byte*) main::reigns#0
Constant inlined main::sc2#0 = (const nomodify byte*) SCREEN+(byte) $28
Successful SSA optimization Pass2ConstantInlining
Inlining constant with var siblings (const byte*) main::reigns#0
Inlining constant with var siblings (const byte*) main::reigns#0
Added new block during phi lifting main::@7(between main::@1 and main::@1)
Added new block during phi lifting main::@8(between main::@3 and main::@3)
Adding NOP phi() at start of @begin
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
Adding NOP phi() at start of main::@2
Adding NOP phi() at start of main::@4
Adding NOP phi() at start of main::@5
Adding NOP phi() at start of main::@6
Adding NOP phi() at start of memcpy::@3
CALL GRAPH
Calls in [] to main:2
Calls in [main] to memcpy:20 memcpy:22
Created 11 initial phi equivalence classes
Coalesced [25] main::reigns#3 ← main::reigns#1
Coalesced [26] main::sc2#3 ← main::sc2#1
Coalesced [27] main::i1#3 ← main::i1#1
Coalesced [28] main::camelot#3 ← main::camelot#1
Coalesced [29] main::sc#3 ← main::sc#1
Coalesced [30] main::i#3 ← main::i#1
Coalesced [42] memcpy::src#5 ← memcpy::src#1
Coalesced [43] memcpy::dst#5 ← memcpy::dst#1
Coalesced down to 11 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@2
Culled Empty Block (label) main::@6
Culled Empty Block (label) main::@8
Culled Empty Block (label) main::@7
Culled Empty Block (label) memcpy::@3
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
Renumbering block main::@5 to main::@4
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::@3
Adding NOP phi() at start of main::@4
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::@1
main::@1: scope:[main] from main main::@1
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 )
[5] (byte*) main::sc#2 ← phi( main/(const nomodify byte*) SCREEN main::@1/(byte*) main::sc#1 )
[5] (byte*) main::camelot#2 ← phi( main/(const to_nomodify byte*) CAMELOT main::@1/(byte*) main::camelot#1 )
[6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2)
[7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2
[8] (byte*) main::camelot#1 ← ++ (byte*) main::camelot#2
[9] (byte) main::i#1 ← ++ (byte) main::i#2
[10] if((byte) main::i#1!=(byte) 7) goto main::@1
to:main::@2
main::@2: scope:[main] from main::@1 main::@2
[11] (byte) main::i1#2 ← phi( main::@1/(byte) 0 main::@2/(byte) main::i1#1 )
[11] (byte*) main::sc2#2 ← phi( main::@1/(const nomodify byte*) SCREEN+(byte) $28 main::@2/(byte*) main::sc2#1 )
[11] (byte*) main::reigns#2 ← phi( main::@1/(const byte*) main::reigns#0 main::@2/(byte*) main::reigns#1 )
[12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2)
[13] (byte*) main::sc2#1 ← ++ (byte*) main::sc2#2
[14] (byte*) main::reigns#1 ← ++ (byte*) main::reigns#2
[15] (byte) main::i1#1 ← ++ (byte) main::i1#2
[16] if((byte) main::i1#1!=(byte) 6) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@2
[17] phi()
[18] call memcpy
to:main::@4
main::@4: scope:[main] from main::@3
[19] phi()
[20] call memcpy
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
memcpy: scope:[memcpy] from main::@3 main::@4
[22] (word) memcpy::num#2 ← phi( main::@3/(byte) 7 main::@4/(byte) 5 )
[22] (void*) memcpy::destination#2 ← phi( main::@3/(void*)(const nomodify byte*) SCREEN+(byte) $a main::@4/(void*)(const nomodify byte*) SCREEN+(byte) $32 )
[22] (void*) memcpy::source#2 ← phi( main::@3/(void*)(const to_nomodify byte*) CAMELOT main::@4/(void*)(const byte*) main::$5 )
[23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2
[24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
[25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
to:memcpy::@1
memcpy::@1: scope:[memcpy] from memcpy memcpy::@2
[26] (byte*) memcpy::dst#2 ← phi( memcpy/(byte*) memcpy::dst#4 memcpy::@2/(byte*) memcpy::dst#1 )
[26] (byte*) memcpy::src#2 ← phi( memcpy/(byte*) memcpy::src#4 memcpy::@2/(byte*) memcpy::src#1 )
[27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2
to:memcpy::@return
memcpy::@return: scope:[memcpy] from memcpy::@1
[28] return
to:@return
memcpy::@2: scope:[memcpy] from memcpy::@1
[29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2)
[30] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
[31] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2
to:memcpy::@1
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::camelot
(byte*) main::camelot#1 67.33333333333333
(byte*) main::camelot#2 101.0
(byte) main::i
(byte) main::i#1 151.5
(byte) main::i#2 50.5
(byte) main::i1
(byte) main::i1#1 151.5
(byte) main::i1#2 50.5
(byte*) main::reigns
(byte*) main::reigns#1 67.33333333333333
(byte*) main::reigns#2 101.0
(byte*) main::sc
(byte*) main::sc#1 50.5
(byte*) main::sc#2 151.5
(byte*) main::sc2
(byte*) main::sc2#1 50.5
(byte*) main::sc2#2 151.5
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(void*) memcpy::destination
(void*) memcpy::destination#2
(byte*) memcpy::dst
(byte*) memcpy::dst#1 1001.0
(byte*) memcpy::dst#2 1034.6666666666667
(byte*) memcpy::dst#4 202.0
(word) memcpy::num
(word) memcpy::num#2 101.0
(void*) memcpy::return
(void*) memcpy::source
(void*) memcpy::source#2
(byte*) memcpy::src
(byte*) memcpy::src#1 2002.0
(byte*) memcpy::src#2 1026.25
(byte*) memcpy::src#4 101.0
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0 137.75
Initial phi equivalence classes
[ main::camelot#2 main::camelot#1 ]
[ main::sc#2 main::sc#1 ]
[ main::i#2 main::i#1 ]
[ main::reigns#2 main::reigns#1 ]
[ main::sc2#2 main::sc2#1 ]
[ main::i1#2 main::i1#1 ]
[ memcpy::source#2 ]
[ memcpy::destination#2 ]
[ memcpy::num#2 ]
[ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
[ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
Added variable memcpy::src_end#0 to live range equivalence class [ memcpy::src_end#0 ]
Complete equivalence classes
[ main::camelot#2 main::camelot#1 ]
[ main::sc#2 main::sc#1 ]
[ main::i#2 main::i#1 ]
[ main::reigns#2 main::reigns#1 ]
[ main::sc2#2 main::sc2#1 ]
[ main::i1#2 main::i1#1 ]
[ memcpy::source#2 ]
[ memcpy::destination#2 ]
[ memcpy::num#2 ]
[ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
[ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
[ memcpy::src_end#0 ]
Allocated zp[2]:2 [ main::camelot#2 main::camelot#1 ]
Allocated zp[2]:4 [ main::sc#2 main::sc#1 ]
Allocated zp[1]:6 [ main::i#2 main::i#1 ]
Allocated zp[2]:7 [ main::reigns#2 main::reigns#1 ]
Allocated zp[2]:9 [ main::sc2#2 main::sc2#1 ]
Allocated zp[1]:11 [ main::i1#2 main::i1#1 ]
Allocated zp[2]:12 [ memcpy::source#2 ]
Allocated zp[2]:14 [ memcpy::destination#2 ]
Allocated zp[2]:16 [ memcpy::num#2 ]
Allocated zp[2]:18 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
Allocated zp[2]:20 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
Allocated zp[2]:22 [ memcpy::src_end#0 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test memcpy on strings (
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.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: {
// Working memory copy of string
.label sc = 4
.label camelot = 2
.label i = 6
.label sc2 = 9
.label reigns = 7
.label i1 = $b
// [5] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z i
// [5] phi (byte*) main::sc#2 = (const nomodify byte*) SCREEN [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<SCREEN
sta.z sc
lda #>SCREEN
sta.z sc+1
// [5] phi (byte*) main::camelot#2 = (const to_nomodify byte*) CAMELOT [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<CAMELOT
sta.z camelot
lda #>CAMELOT
sta.z camelot+1
jmp __b1
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
__b1_from___b1:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
// [5] phi (byte*) main::sc#2 = (byte*) main::sc#1 [phi:main::@1->main::@1#1] -- register_copy
// [5] phi (byte*) main::camelot#2 = (byte*) main::camelot#1 [phi:main::@1->main::@1#2] -- register_copy
jmp __b1
// main::@1
__b1:
// [6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (camelot),y
ldy #0
sta (sc),y
// [7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2 -- pbuz1=_inc_pbuz1
inc.z sc
bne !+
inc.z sc+1
!:
// [8] (byte*) main::camelot#1 ← ++ (byte*) main::camelot#2 -- pbuz1=_inc_pbuz1
inc.z camelot
bne !+
inc.z camelot+1
!:
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [10] if((byte) main::i#1!=(byte) 7) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #7
cmp.z i
bne __b1_from___b1
// [11] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
__b2_from___b1:
// [11] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1
lda #0
sta.z i1
// [11] phi (byte*) main::sc2#2 = (const nomodify byte*) SCREEN+(byte) $28 [phi:main::@1->main::@2#1] -- pbuz1=pbuc1
lda #<SCREEN+$28
sta.z sc2
lda #>SCREEN+$28
sta.z sc2+1
// [11] phi (byte*) main::reigns#2 = (const byte*) main::reigns#0 [phi:main::@1->main::@2#2] -- pbuz1=pbuc1
lda #<reigns_1
sta.z reigns
lda #>reigns_1
sta.z reigns+1
jmp __b2
// [11] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
__b2_from___b2:
// [11] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy
// [11] phi (byte*) main::sc2#2 = (byte*) main::sc2#1 [phi:main::@2->main::@2#1] -- register_copy
// [11] phi (byte*) main::reigns#2 = (byte*) main::reigns#1 [phi:main::@2->main::@2#2] -- register_copy
jmp __b2
// main::@2
__b2:
// [12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (reigns),y
ldy #0
sta (sc2),y
// [13] (byte*) main::sc2#1 ← ++ (byte*) main::sc2#2 -- pbuz1=_inc_pbuz1
inc.z sc2
bne !+
inc.z sc2+1
!:
// [14] (byte*) main::reigns#1 ← ++ (byte*) main::reigns#2 -- pbuz1=_inc_pbuz1
inc.z reigns
bne !+
inc.z reigns+1
!:
// [15] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuz1=_inc_vbuz1
inc.z i1
// [16] if((byte) main::i1#1!=(byte) 6) goto main::@2 -- vbuz1_neq_vbuc1_then_la1
lda #6
cmp.z i1
bne __b2_from___b2
// [17] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
__b3_from___b2:
jmp __b3
// main::@3
__b3:
// [18] call memcpy
// [22] phi from main::@3 to memcpy [phi:main::@3->memcpy]
memcpy_from___b3:
// [22] phi (word) memcpy::num#2 = (byte) 7 [phi:main::@3->memcpy#0] -- vwuz1=vbuc1
lda #<7
sta.z memcpy.num
lda #>7
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $a [phi:main::@3->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$a
sta.z memcpy.destination
lda #>SCREEN+$a
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const to_nomodify byte*) CAMELOT [phi:main::@3->memcpy#2] -- pvoz1=pvoc1
lda #<CAMELOT
sta.z memcpy.source
lda #>CAMELOT
sta.z memcpy.source+1
jsr memcpy
// [19] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
__b4_from___b3:
jmp __b4
// main::@4
__b4:
// [20] call memcpy
// [22] phi from main::@4 to memcpy [phi:main::@4->memcpy]
memcpy_from___b4:
// [22] phi (word) memcpy::num#2 = (byte) 5 [phi:main::@4->memcpy#0] -- vwuz1=vbuc1
lda #<5
sta.z memcpy.num
lda #>5
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $32 [phi:main::@4->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$32
sta.z memcpy.destination
lda #>SCREEN+$32
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const byte*) main::$5 [phi:main::@4->memcpy#2] -- pvoz1=pvoc1
lda #<__5
sta.z memcpy.source
lda #>__5
sta.z memcpy.source+1
jsr memcpy
jmp __breturn
// main::@return
__breturn:
// [21] return
rts
__5: .text "rules"
.byte 0
reigns_1: .text "reigns"
.byte 0
}
// memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp($e) destination, void* zp($c) source, word zp($10) num)
memcpy: {
.label src_end = $16
.label dst = $14
.label src = $12
.label source = $c
.label destination = $e
.label num = $10
// [23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz3
lda.z source
clc
adc.z num
sta.z src_end
lda.z source+1
adc.z num+1
sta.z src_end+1
// [24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2 -- pbuz1=pbuz2
lda.z source
sta.z src
lda.z source+1
sta.z src+1
// [25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2 -- pbuz1=pbuz2
lda.z destination
sta.z dst
lda.z destination+1
sta.z dst+1
// [26] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
__b1_from_memcpy:
__b1_from___b2:
// [26] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy
// [26] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy
jmp __b1
// memcpy::@1
__b1:
// [27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1
lda.z src+1
cmp.z src_end+1
bne __b2
lda.z src
cmp.z src_end
bne __b2
jmp __breturn
// memcpy::@return
__breturn:
// [28] return
rts
// memcpy::@2
__b2:
// [29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (src),y
ldy #0
sta (dst),y
// [30] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1
inc.z dst
bne !+
inc.z dst+1
!:
// [31] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1
inc.z src
bne !+
inc.z src+1
!:
jmp __b1_from___b2
}
// File Data
CAMELOT: .text "camelot"
.byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2) [ main::camelot#2 main::sc#2 main::i#2 ] ( main:2 [ main::camelot#2 main::sc#2 main::i#2 ] { } ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp[1]:6 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp[1]:6 [ main::i#2 main::i#1 ]
Statement [12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2) [ main::reigns#2 main::sc2#2 main::i1#2 ] ( main:2 [ main::reigns#2 main::sc2#2 main::i1#2 ] { } ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp[1]:11 [ main::i1#2 main::i1#1 ]
Removing always clobbered register reg byte y as potential for zp[1]:11 [ main::i1#2 main::i1#1 ]
Statement [23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] ( main:2::memcpy:18 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] { } main:2::memcpy:20 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] { } ) always clobbers reg byte a
Statement [24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] ( main:2::memcpy:18 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] { } main:2::memcpy:20 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] { } ) always clobbers reg byte a
Statement [25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] { } ) always clobbers reg byte a
Statement [27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } ) always clobbers reg byte a
Statement [29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } ) always clobbers reg byte a reg byte y
Statement [6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2) [ main::camelot#2 main::sc#2 main::i#2 ] ( main:2 [ main::camelot#2 main::sc#2 main::i#2 ] { } ) always clobbers reg byte a reg byte y
Statement [12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2) [ main::reigns#2 main::sc2#2 main::i1#2 ] ( main:2 [ main::reigns#2 main::sc2#2 main::i1#2 ] { } ) always clobbers reg byte a reg byte y
Statement [23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] ( main:2::memcpy:18 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] { } main:2::memcpy:20 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] { } ) always clobbers reg byte a
Statement [24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] ( main:2::memcpy:18 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] { } main:2::memcpy:20 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] { } ) always clobbers reg byte a
Statement [25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] { } ) always clobbers reg byte a
Statement [27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } ) always clobbers reg byte a
Statement [29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:18 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } main:2::memcpy:20 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] { } ) always clobbers reg byte a reg byte y
Potential registers zp[2]:2 [ main::camelot#2 main::camelot#1 ] : zp[2]:2 ,
Potential registers zp[2]:4 [ main::sc#2 main::sc#1 ] : zp[2]:4 ,
Potential registers zp[1]:6 [ main::i#2 main::i#1 ] : zp[1]:6 , reg byte x ,
Potential registers zp[2]:7 [ main::reigns#2 main::reigns#1 ] : zp[2]:7 ,
Potential registers zp[2]:9 [ main::sc2#2 main::sc2#1 ] : zp[2]:9 ,
Potential registers zp[1]:11 [ main::i1#2 main::i1#1 ] : zp[1]:11 , reg byte x ,
Potential registers zp[2]:12 [ memcpy::source#2 ] : zp[2]:12 ,
Potential registers zp[2]:14 [ memcpy::destination#2 ] : zp[2]:14 ,
Potential registers zp[2]:16 [ memcpy::num#2 ] : zp[2]:16 ,
Potential registers zp[2]:18 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] : zp[2]:18 ,
Potential registers zp[2]:20 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] : zp[2]:20 ,
Potential registers zp[2]:22 [ memcpy::src_end#0 ] : zp[2]:22 ,
REGISTER UPLIFT SCOPES
Uplift Scope [memcpy] 3,129.25: zp[2]:18 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] 2,237.67: zp[2]:20 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] 137.75: zp[2]:22 [ memcpy::src_end#0 ] 101: zp[2]:16 [ memcpy::num#2 ] 0: zp[2]:12 [ memcpy::source#2 ] 0: zp[2]:14 [ memcpy::destination#2 ]
Uplift Scope [main] 202: zp[2]:4 [ main::sc#2 main::sc#1 ] 202: zp[1]:6 [ main::i#2 main::i#1 ] 202: zp[2]:9 [ main::sc2#2 main::sc2#1 ] 202: zp[1]:11 [ main::i1#2 main::i1#1 ] 168.33: zp[2]:2 [ main::camelot#2 main::camelot#1 ] 168.33: zp[2]:7 [ main::reigns#2 main::reigns#1 ]
Uplift Scope []
Uplifting [memcpy] best 2494 combination zp[2]:18 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] zp[2]:20 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] zp[2]:22 [ memcpy::src_end#0 ] zp[2]:16 [ memcpy::num#2 ] zp[2]:12 [ memcpy::source#2 ] zp[2]:14 [ memcpy::destination#2 ]
Uplifting [main] best 2314 combination zp[2]:4 [ main::sc#2 main::sc#1 ] reg byte x [ main::i#2 main::i#1 ] zp[2]:9 [ main::sc2#2 main::sc2#1 ] reg byte x [ main::i1#2 main::i1#1 ] zp[2]:2 [ main::camelot#2 main::camelot#1 ] zp[2]:7 [ main::reigns#2 main::reigns#1 ]
Uplifting [] best 2314 combination
Coalescing zero page register [ zp[2]:12 [ memcpy::source#2 ] ] with [ zp[2]:18 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] ] - score: 1
Coalescing zero page register [ zp[2]:14 [ memcpy::destination#2 ] ] with [ zp[2]:20 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] ] - score: 1
Coalescing zero page register [ zp[2]:16 [ memcpy::num#2 ] ] with [ zp[2]:22 [ memcpy::src_end#0 ] ] - score: 1
Allocated (was zp[2]:7) zp[2]:6 [ main::reigns#2 main::reigns#1 ]
Allocated (was zp[2]:9) zp[2]:8 [ main::sc2#2 main::sc2#1 ]
Allocated (was zp[2]:12) zp[2]:10 [ memcpy::source#2 memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
Allocated (was zp[2]:14) zp[2]:12 [ memcpy::destination#2 memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
Allocated (was zp[2]:16) zp[2]:14 [ memcpy::num#2 memcpy::src_end#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test memcpy on strings (
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.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: {
// Working memory copy of string
.label sc = 4
.label camelot = 2
.label sc2 = 8
.label reigns = 6
// [5] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
// [5] phi (byte*) main::sc#2 = (const nomodify byte*) SCREEN [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<SCREEN
sta.z sc
lda #>SCREEN
sta.z sc+1
// [5] phi (byte*) main::camelot#2 = (const to_nomodify byte*) CAMELOT [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<CAMELOT
sta.z camelot
lda #>CAMELOT
sta.z camelot+1
jmp __b1
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
__b1_from___b1:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
// [5] phi (byte*) main::sc#2 = (byte*) main::sc#1 [phi:main::@1->main::@1#1] -- register_copy
// [5] phi (byte*) main::camelot#2 = (byte*) main::camelot#1 [phi:main::@1->main::@1#2] -- register_copy
jmp __b1
// main::@1
__b1:
// [6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (camelot),y
ldy #0
sta (sc),y
// [7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2 -- pbuz1=_inc_pbuz1
inc.z sc
bne !+
inc.z sc+1
!:
// [8] (byte*) main::camelot#1 ← ++ (byte*) main::camelot#2 -- pbuz1=_inc_pbuz1
inc.z camelot
bne !+
inc.z camelot+1
!:
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [10] if((byte) main::i#1!=(byte) 7) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #7
bne __b1_from___b1
// [11] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
__b2_from___b1:
// [11] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
ldx #0
// [11] phi (byte*) main::sc2#2 = (const nomodify byte*) SCREEN+(byte) $28 [phi:main::@1->main::@2#1] -- pbuz1=pbuc1
lda #<SCREEN+$28
sta.z sc2
lda #>SCREEN+$28
sta.z sc2+1
// [11] phi (byte*) main::reigns#2 = (const byte*) main::reigns#0 [phi:main::@1->main::@2#2] -- pbuz1=pbuc1
lda #<reigns_1
sta.z reigns
lda #>reigns_1
sta.z reigns+1
jmp __b2
// [11] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
__b2_from___b2:
// [11] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy
// [11] phi (byte*) main::sc2#2 = (byte*) main::sc2#1 [phi:main::@2->main::@2#1] -- register_copy
// [11] phi (byte*) main::reigns#2 = (byte*) main::reigns#1 [phi:main::@2->main::@2#2] -- register_copy
jmp __b2
// main::@2
__b2:
// [12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (reigns),y
ldy #0
sta (sc2),y
// [13] (byte*) main::sc2#1 ← ++ (byte*) main::sc2#2 -- pbuz1=_inc_pbuz1
inc.z sc2
bne !+
inc.z sc2+1
!:
// [14] (byte*) main::reigns#1 ← ++ (byte*) main::reigns#2 -- pbuz1=_inc_pbuz1
inc.z reigns
bne !+
inc.z reigns+1
!:
// [15] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuxx=_inc_vbuxx
inx
// [16] if((byte) main::i1#1!=(byte) 6) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
cpx #6
bne __b2_from___b2
// [17] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
__b3_from___b2:
jmp __b3
// main::@3
__b3:
// [18] call memcpy
// [22] phi from main::@3 to memcpy [phi:main::@3->memcpy]
memcpy_from___b3:
// [22] phi (word) memcpy::num#2 = (byte) 7 [phi:main::@3->memcpy#0] -- vwuz1=vbuc1
lda #<7
sta.z memcpy.num
lda #>7
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $a [phi:main::@3->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$a
sta.z memcpy.destination
lda #>SCREEN+$a
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const to_nomodify byte*) CAMELOT [phi:main::@3->memcpy#2] -- pvoz1=pvoc1
lda #<CAMELOT
sta.z memcpy.source
lda #>CAMELOT
sta.z memcpy.source+1
jsr memcpy
// [19] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
__b4_from___b3:
jmp __b4
// main::@4
__b4:
// [20] call memcpy
// [22] phi from main::@4 to memcpy [phi:main::@4->memcpy]
memcpy_from___b4:
// [22] phi (word) memcpy::num#2 = (byte) 5 [phi:main::@4->memcpy#0] -- vwuz1=vbuc1
lda #<5
sta.z memcpy.num
lda #>5
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $32 [phi:main::@4->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$32
sta.z memcpy.destination
lda #>SCREEN+$32
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const byte*) main::$5 [phi:main::@4->memcpy#2] -- pvoz1=pvoc1
lda #<__5
sta.z memcpy.source
lda #>__5
sta.z memcpy.source+1
jsr memcpy
jmp __breturn
// main::@return
__breturn:
// [21] return
rts
__5: .text "rules"
.byte 0
reigns_1: .text "reigns"
.byte 0
}
// memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp($c) destination, void* zp($a) source, word zp($e) num)
memcpy: {
.label src_end = $e
.label dst = $c
.label src = $a
.label source = $a
.label destination = $c
.label num = $e
// [23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz1
lda.z src_end
clc
adc.z source
sta.z src_end
lda.z src_end+1
adc.z source+1
sta.z src_end+1
// [24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
// [25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
// [26] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
__b1_from_memcpy:
__b1_from___b2:
// [26] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy
// [26] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy
jmp __b1
// memcpy::@1
__b1:
// [27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1
lda.z src+1
cmp.z src_end+1
bne __b2
lda.z src
cmp.z src_end
bne __b2
jmp __breturn
// memcpy::@return
__breturn:
// [28] return
rts
// memcpy::@2
__b2:
// [29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (src),y
ldy #0
sta (dst),y
// [30] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1
inc.z dst
bne !+
inc.z dst+1
!:
// [31] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1
inc.z src
bne !+
inc.z src+1
!:
jmp __b1_from___b2
}
// File Data
CAMELOT: .text "camelot"
.byte 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __b3
Removing instruction jmp __b4
Removing instruction jmp __breturn
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldy #0
Removing instruction ldy #0
Removing instruction ldy #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __b1_from___b1 with __b1
Replacing label __b2_from___b2 with __b2
Replacing label __b1_from___b2 with __b1
Removing instruction __b1_from___bbegin:
Removing instruction __b1:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Removing instruction __b1_from___b1:
Removing instruction __b2_from___b2:
Removing instruction __b3_from___b2:
Removing instruction memcpy_from___b3:
Removing instruction __b4_from___b3:
Removing instruction memcpy_from___b4:
Removing instruction __b1_from_memcpy:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bbegin:
Removing instruction __bend:
Removing instruction __b1_from_main:
Removing instruction __b2_from___b1:
Removing instruction __b3:
Removing instruction __b4:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp __b1
Removing instruction jmp __b2
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const to_nomodify byte*) CAMELOT[] = (byte*) "camelot"
(const nomodify byte*) SCREEN = (byte*) 1024
(void()) main()
(const byte*) main::$5[(byte) 6] = (byte*) "rules"
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte*) main::camelot
(byte*) main::camelot#1 camelot zp[2]:2 67.33333333333333
(byte*) main::camelot#2 camelot zp[2]:2 101.0
(byte) main::i
(byte) main::i#1 reg byte x 151.5
(byte) main::i#2 reg byte x 50.5
(byte) main::i1
(byte) main::i1#1 reg byte x 151.5
(byte) main::i1#2 reg byte x 50.5
(byte*) main::reigns
(const byte*) main::reigns#0 reigns_1 = (byte*) "reigns"
(byte*) main::reigns#1 reigns zp[2]:6 67.33333333333333
(byte*) main::reigns#2 reigns zp[2]:6 101.0
(byte*) main::sc
(byte*) main::sc#1 sc zp[2]:4 50.5
(byte*) main::sc#2 sc zp[2]:4 151.5
(byte*) main::sc2
(byte*) main::sc2#1 sc2 zp[2]:8 50.5
(byte*) main::sc2#2 sc2 zp[2]:8 151.5
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(label) memcpy::@1
(label) memcpy::@2
(label) memcpy::@return
(void*) memcpy::destination
(void*) memcpy::destination#2 destination zp[2]:12
(byte*) memcpy::dst
(byte*) memcpy::dst#1 dst zp[2]:12 1001.0
(byte*) memcpy::dst#2 dst zp[2]:12 1034.6666666666667
(byte*) memcpy::dst#4 dst zp[2]:12 202.0
(word) memcpy::num
(word) memcpy::num#2 num zp[2]:14 101.0
(void*) memcpy::return
(void*) memcpy::source
(void*) memcpy::source#2 source zp[2]:10
(byte*) memcpy::src
(byte*) memcpy::src#1 src zp[2]:10 2002.0
(byte*) memcpy::src#2 src zp[2]:10 1026.25
(byte*) memcpy::src#4 src zp[2]:10 101.0
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0 src_end zp[2]:14 137.75
zp[2]:2 [ main::camelot#2 main::camelot#1 ]
zp[2]:4 [ main::sc#2 main::sc#1 ]
reg byte x [ main::i#2 main::i#1 ]
zp[2]:6 [ main::reigns#2 main::reigns#1 ]
zp[2]:8 [ main::sc2#2 main::sc2#1 ]
reg byte x [ main::i1#2 main::i1#1 ]
zp[2]:10 [ memcpy::source#2 memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
zp[2]:12 [ memcpy::destination#2 memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
zp[2]:14 [ memcpy::num#2 memcpy::src_end#0 ]
FINAL ASSEMBLER
Score: 2029
// File Comments
// Test memcpy on strings (
// 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: {
// Working memory copy of string
.label sc = 4
.label camelot = 2
.label sc2 = 8
.label reigns = 6
// [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
// [5] phi (byte*) main::sc#2 = (const nomodify byte*) SCREEN [phi:main->main::@1#1] -- pbuz1=pbuc1
lda #<SCREEN
sta.z sc
lda #>SCREEN
sta.z sc+1
// [5] phi (byte*) main::camelot#2 = (const to_nomodify byte*) CAMELOT [phi:main->main::@1#2] -- pbuz1=pbuc1
lda #<CAMELOT
sta.z camelot
lda #>CAMELOT
sta.z camelot+1
// [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
// [5] phi (byte*) main::sc#2 = (byte*) main::sc#1 [phi:main::@1->main::@1#1] -- register_copy
// [5] phi (byte*) main::camelot#2 = (byte*) main::camelot#1 [phi:main::@1->main::@1#2] -- register_copy
// main::@1
__b1:
// *sc++ = *camelot++
// [6] *((byte*) main::sc#2) ← *((byte*) main::camelot#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (camelot),y
sta (sc),y
// *sc++ = *camelot++;
// [7] (byte*) main::sc#1 ← ++ (byte*) main::sc#2 -- pbuz1=_inc_pbuz1
inc.z sc
bne !+
inc.z sc+1
!:
// [8] (byte*) main::camelot#1 ← ++ (byte*) main::camelot#2 -- pbuz1=_inc_pbuz1
inc.z camelot
bne !+
inc.z camelot+1
!:
// for( char i: 0..6)
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [10] if((byte) main::i#1!=(byte) 7) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #7
bne __b1
// [11] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
// [11] phi (byte) main::i1#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
ldx #0
// [11] phi (byte*) main::sc2#2 = (const nomodify byte*) SCREEN+(byte) $28 [phi:main::@1->main::@2#1] -- pbuz1=pbuc1
lda #<SCREEN+$28
sta.z sc2
lda #>SCREEN+$28
sta.z sc2+1
// [11] phi (byte*) main::reigns#2 = (const byte*) main::reigns#0 [phi:main::@1->main::@2#2] -- pbuz1=pbuc1
lda #<reigns_1
sta.z reigns
lda #>reigns_1
sta.z reigns+1
// [11] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
// [11] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@2->main::@2#0] -- register_copy
// [11] phi (byte*) main::sc2#2 = (byte*) main::sc2#1 [phi:main::@2->main::@2#1] -- register_copy
// [11] phi (byte*) main::reigns#2 = (byte*) main::reigns#1 [phi:main::@2->main::@2#2] -- register_copy
// main::@2
__b2:
// *sc2++ = *reigns++
// [12] *((byte*) main::sc2#2) ← *((byte*) main::reigns#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (reigns),y
sta (sc2),y
// *sc2++ = *reigns++;
// [13] (byte*) main::sc2#1 ← ++ (byte*) main::sc2#2 -- pbuz1=_inc_pbuz1
inc.z sc2
bne !+
inc.z sc2+1
!:
// [14] (byte*) main::reigns#1 ← ++ (byte*) main::reigns#2 -- pbuz1=_inc_pbuz1
inc.z reigns
bne !+
inc.z reigns+1
!:
// for( char i: 0..5)
// [15] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuxx=_inc_vbuxx
inx
// [16] if((byte) main::i1#1!=(byte) 6) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
cpx #6
bne __b2
// [17] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
// main::@3
// memcpy(SCREEN+10, CAMELOT, 7)
// [18] call memcpy
// [22] phi from main::@3 to memcpy [phi:main::@3->memcpy]
// [22] phi (word) memcpy::num#2 = (byte) 7 [phi:main::@3->memcpy#0] -- vwuz1=vbuc1
lda #<7
sta.z memcpy.num
lda #>7
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $a [phi:main::@3->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$a
sta.z memcpy.destination
lda #>SCREEN+$a
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const to_nomodify byte*) CAMELOT [phi:main::@3->memcpy#2] -- pvoz1=pvoc1
lda #<CAMELOT
sta.z memcpy.source
lda #>CAMELOT
sta.z memcpy.source+1
jsr memcpy
// [19] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
// main::@4
// memcpy(SCREEN+50, "rules", 5)
// [20] call memcpy
// [22] phi from main::@4 to memcpy [phi:main::@4->memcpy]
// [22] phi (word) memcpy::num#2 = (byte) 5 [phi:main::@4->memcpy#0] -- vwuz1=vbuc1
lda #<5
sta.z memcpy.num
lda #>5
sta.z memcpy.num+1
// [22] phi (void*) memcpy::destination#2 = (void*)(const nomodify byte*) SCREEN+(byte) $32 [phi:main::@4->memcpy#1] -- pvoz1=pvoc1
lda #<SCREEN+$32
sta.z memcpy.destination
lda #>SCREEN+$32
sta.z memcpy.destination+1
// [22] phi (void*) memcpy::source#2 = (void*)(const byte*) main::$5 [phi:main::@4->memcpy#2] -- pvoz1=pvoc1
lda #<__5
sta.z memcpy.source
lda #>__5
sta.z memcpy.source+1
jsr memcpy
// main::@return
// }
// [21] return
rts
__5: .text "rules"
.byte 0
reigns_1: .text "reigns"
.byte 0
}
// memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp($c) destination, void* zp($a) source, word zp($e) num)
memcpy: {
.label src_end = $e
.label dst = $c
.label src = $a
.label source = $a
.label destination = $c
.label num = $e
// src_end = (char*)source+num
// [23] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz1
lda.z src_end
clc
adc.z source
sta.z src_end
lda.z src_end+1
adc.z source+1
sta.z src_end+1
// [24] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
// [25] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
// [26] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
// [26] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy
// [26] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy
// memcpy::@1
__b1:
// while(src!=src_end)
// [27] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1
lda.z src+1
cmp.z src_end+1
bne __b2
lda.z src
cmp.z src_end
bne __b2
// memcpy::@return
// }
// [28] return
rts
// memcpy::@2
__b2:
// *dst++ = *src++
// [29] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2
ldy #0
lda (src),y
sta (dst),y
// *dst++ = *src++;
// [30] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1
inc.z dst
bne !+
inc.z dst+1
!:
// [31] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1
inc.z src
bne !+
inc.z src+1
!:
jmp __b1
}
// File Data
CAMELOT: .text "camelot"
.byte 0