1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-21 02:24:34 +00:00
kickc/src/test/ref/struct-ptr-30.log

866 lines
32 KiB
Plaintext
Raw Normal View History

Fixing pointer array-indexing *((struct Point[4]) points + (byte) main::i)
Created struct value member variable (byte) print::p_x
Created struct value member variable (signed word) print::p_y
Converted struct value to member variables (struct Point) print::p
Converted procedure struct value parameter to member unwinding (void()) print((byte) print::p_x , (signed word) print::p_y)
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print *((byte*) main::$3 + (byte~) main::$2) *((signed word*) main::$4 + (byte~) main::$2)
Replacing struct member reference (struct Point) print::p.x with member unwinding reference (byte) print::p_x
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (signed word) print::p_y
Replacing struct member reference (struct Point) print::p.y with member unwinding reference (signed word) print::p_y
Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Point[4]) points#0 ← { { (number) 1, (number) $83f }, { (number) 3, (number) $107e } }
to:@1
main: scope:[main] from @2
(byte) idx#16 ← phi( @2/(byte) idx#15 )
(byte) main::i#0 ← (byte) 0
to:main::@1
main::@1: scope:[main] from main main::@3
(byte) idx#14 ← phi( main/(byte) idx#16 main::@3/(byte) idx#0 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
(byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT
(byte) print::p_x#0 ← *((byte*) main::$3 + (byte~) main::$2)
(signed word) print::p_y#0 ← *((signed word*) main::$4 + (byte~) main::$2)
call print
to:main::@3
main::@3: scope:[main] from main::@1
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
(byte) idx#9 ← phi( main::@1/(byte) idx#7 )
(byte) idx#0 ← (byte) idx#9
(byte*) main::$3 ← (byte*)(struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
(signed word*) main::$4 ← (signed word*)(struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
(byte) main::i#1 ← (byte) main::i#3 + rangenext(0,3)
(bool~) main::$1 ← (byte) main::i#1 != rangelast(0,3)
if((bool~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
(byte) idx#10 ← phi( main::@3/(byte) idx#0 )
(byte) idx#1 ← (byte) idx#10
return
to:@return
@1: scope:[] from @begin
(byte*) SCREEN#0 ← ((byte*)) (number) $400
(byte) idx#2 ← (number) 0
to:@2
print: scope:[print] from main::@1
(signed word) print::p_y#1 ← phi( main::@1/(signed word) print::p_y#0 )
(byte) idx#11 ← phi( main::@1/(byte) idx#14 )
(byte) print::p_x#1 ← phi( main::@1/(byte) print::p_x#0 )
*((byte*) SCREEN#0 + (byte) idx#11) ← (byte) print::p_x#1
(byte) idx#3 ← ++ (byte) idx#11
(byte~) print::$0 ← < (signed word) print::p_y#1
*((byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0
(byte) idx#4 ← ++ (byte) idx#3
(byte~) print::$1 ← > (signed word) print::p_y#1
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1
(byte) idx#5 ← ++ (byte) idx#4
*((byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' '
(byte) idx#6 ← ++ (byte) idx#5
to:print::@return
print::@return: scope:[print] from print
(byte) idx#12 ← phi( print/(byte) idx#6 )
(byte) idx#7 ← (byte) idx#12
return
to:@return
@2: scope:[] from @1
(byte) idx#15 ← phi( @1/(byte) idx#2 )
call main
to:@3
@3: scope:[] from @2
(byte) idx#13 ← phi( @2/(byte) idx#1 )
(byte) idx#8 ← (byte) idx#13
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_X = (byte) 0
(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(signed word) Point::y
(byte*) SCREEN
(byte*) SCREEN#0
(const byte) SIZEOF_STRUCT_POINT = (byte) 3
(byte) idx
(byte) idx#0
(byte) idx#1
(byte) idx#10
(byte) idx#11
(byte) idx#12
(byte) idx#13
(byte) idx#14
(byte) idx#15
(byte) idx#16
(byte) idx#2
(byte) idx#3
(byte) idx#4
(byte) idx#5
(byte) idx#6
(byte) idx#7
(byte) idx#8
(byte) idx#9
(void()) main()
(bool~) main::$1
(byte~) main::$2
(byte*) main::$3
(signed word*) main::$4
(label) main::@1
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
(struct Point[4]) points
(struct Point[4]) points#0
(void()) print((byte) print::p_x , (signed word) print::p_y)
(byte~) print::$0
(byte~) print::$1
(label) print::@return
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0
(byte) print::p_x#1
(signed word) print::p_y
(signed word) print::p_y#0
(signed word) print::p_y#1
Adding number conversion cast (unumber) 0 in (byte) idx#2 ← (number) 0
Successful SSA optimization PassNAddNumberTypeConversions
Added casts to value list in (struct Point[4]) points#0 ← (struct Point[4]){ (struct Point){ (byte)(number) 1, (signed word)(number) $83f }, (struct Point){ (byte)(number) 3, (signed word)(number) $107e } }
Successful SSA optimization PassNAddInitializerValueListTypeCasts
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
Inlining cast (byte) idx#2 ← (unumber)(number) 0
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 1
Simplifying constant integer cast $83f
Simplifying constant integer cast 3
Simplifying constant integer cast $107e
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) main::i#2 = (byte) main::i#3
Alias (byte) idx#0 = (byte) idx#9 (byte) idx#10 (byte) idx#1
Alias (byte) idx#12 = (byte) idx#6 (byte) idx#7
Alias (byte) idx#15 = (byte) idx#2
Alias (byte) idx#13 = (byte) idx#8
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) idx#16 (byte) idx#15
Identical Phi Values (byte) idx#0 (byte) idx#12
Identical Phi Values (byte) print::p_x#1 (byte) print::p_x#0
Identical Phi Values (byte) idx#11 (byte) idx#14
Identical Phi Values (signed word) print::p_y#1 (signed word) print::p_y#0
Identical Phi Values (byte) idx#13 (byte) idx#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$1 [14] if((byte) main::i#1!=rangelast(0,3)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Identified constant from value list (struct Point) { x: (byte) 1, y: (signed word) $83f }
Identified constant from value list (struct Point) { x: (byte) 3, y: (signed word) $107e }
Successful SSA optimization Pass2ConstantInitializerValueLists
Identified constant from value list (struct Point[4]) { { x: (byte) 1, y: (signed word) $83f }, { x: (byte) 3, y: (signed word) $107e } }
Successful SSA optimization Pass2ConstantInitializerValueLists
Constant (const struct Point[4]) points#0 = { { x: 1, y: $83f }, { x: 3, y: $107e } }
Constant (const byte) main::i#0 = 0
Constant (const byte*) SCREEN#0 = (byte*) 1024
Constant (const byte) idx#15 = 0
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)points#0 in [10] (byte*) main::$3 ← (byte*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (signed word*)points#0 in [11] (signed word*) main::$4 ← (signed word*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Resolved ranged next value [12] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [14] if(main::i#1!=rangelast(0,3)) goto main::@1 to (number) 4
Simplifying expression containing zero (byte*)points#0 in [10] (byte*) main::$3 ← (byte*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 4 in if((byte) main::i#1!=(number) 4) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 4
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 4
Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant right-side identified [6] (signed word*) main::$4 ← (signed word*)(const struct Point[4]) points#0 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$3 = (byte*)points#0
Constant (const signed word*) main::$4 = (signed word*)points#0+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Rewriting multiplication to use shift and addition[1] (byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const byte) idx#15
Constant inlined main::i#0 = (byte) 0
Constant inlined main::$3 = (byte*)(const struct Point[4]) points#0
Constant inlined main::$4 = (signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y
Constant inlined idx#15 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Alias (byte~) main::$2 = (byte) main::$6
Successful SSA optimization Pass2AliasElimination
Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT
Successful SSA optimization PassNEliminateUnusedVars
Added new block during phi lifting main::@4(between main::@3 and main::@1)
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 @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:3
Calls in [main] to print:12
Created 2 initial phi equivalence classes
Coalesced [16] main::i#4 ← main::i#1
Coalesced [17] idx#17 ← idx#12
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @1
Culled Empty Block (label) @3
Culled Empty Block (label) main::@4
Renumbering block @2 to @1
Renumbering block main::@3 to main::@2
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
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()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[5] (byte) idx#14 ← phi( main/(byte) 0 main::@2/(byte) idx#12 )
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1
[7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2
[8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2)
[9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2)
[10] call print
to:main::@2
main::@2: scope:[main] from main::@1
[11] (byte) main::i#1 ← ++ (byte) main::i#2
[12] if((byte) main::i#1!=(byte) 4) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@2
[13] return
to:@return
print: scope:[print] from main::@1
[14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0
[15] (byte) idx#3 ← ++ (byte) idx#14
[16] (byte~) print::$0 ← < (signed word) print::p_y#0
[17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0
[18] (byte) idx#4 ← ++ (byte) idx#3
[19] (byte~) print::$1 ← > (signed word) print::p_y#0
[20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1
[21] (byte) idx#5 ← ++ (byte) idx#4
[22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' '
[23] (byte) idx#12 ← ++ (byte) idx#5
to:print::@return
print::@return: scope:[print] from print
[24] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(signed word) Point::y
(byte*) SCREEN
(byte) idx
(byte) idx#12 2.6
(byte) idx#14 2.5
(byte) idx#3 2.0
(byte) idx#4 2.0
(byte) idx#5 3.0
(void()) main()
(byte~) main::$2 16.5
(byte) main::$5 22.0
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 7.333333333333333
(struct Point[4]) points
(void()) print((byte) print::p_x , (signed word) print::p_y)
(byte~) print::$0 4.0
(byte~) print::$1 4.0
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0 6.5
(signed word) print::p_y
(signed word) print::p_y#0 2.5
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ idx#14 idx#12 ]
Added variable main::$5 to zero page equivalence class [ main::$5 ]
Added variable main::$2 to zero page equivalence class [ main::$2 ]
Added variable print::p_x#0 to zero page equivalence class [ print::p_x#0 ]
Added variable print::p_y#0 to zero page equivalence class [ print::p_y#0 ]
Added variable idx#3 to zero page equivalence class [ idx#3 ]
Added variable print::$0 to zero page equivalence class [ print::$0 ]
Added variable idx#4 to zero page equivalence class [ idx#4 ]
Added variable print::$1 to zero page equivalence class [ print::$1 ]
Added variable idx#5 to zero page equivalence class [ idx#5 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ idx#14 idx#12 ]
[ main::$5 ]
[ main::$2 ]
[ print::p_x#0 ]
[ print::p_y#0 ]
[ idx#3 ]
[ print::$0 ]
[ idx#4 ]
[ print::$1 ]
[ idx#5 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ idx#14 idx#12 ]
Allocated zp ZP_BYTE:4 [ main::$5 ]
Allocated zp ZP_BYTE:5 [ main::$2 ]
Allocated zp ZP_BYTE:6 [ print::p_x#0 ]
Allocated zp ZP_WORD:7 [ print::p_y#0 ]
Allocated zp ZP_BYTE:9 [ idx#3 ]
Allocated zp ZP_BYTE:10 [ print::$0 ]
Allocated zp ZP_BYTE:11 [ idx#4 ]
Allocated zp ZP_BYTE:12 [ print::$1 ]
Allocated zp ZP_BYTE:13 [ idx#5 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test a struct array initialized with to few members (zero-filled for the rest)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
.label idx = 9
.label idx_4 = $b
.label idx_5 = $d
.label idx_12 = 3
.label idx_14 = 3
// @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: {
.label _2 = 5
.label i = 2
.label _5 = 4
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z idx_14
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
jmp b1
// main::@1
b1:
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuz1=vbuz2_rol_1
lda.z i
asl
sta.z _5
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3
lda.z _5
clc
adc.z i
sta.z _2
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuz2
ldy.z _2
lda points,y
sta.z print.p_x
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuz2
ldy.z _2
lda points+OFFSET_STRUCT_POINT_Y,y
sta.z print.p_y
lda points+OFFSET_STRUCT_POINT_Y+1,y
sta.z print.p_y+1
// [10] call print
jsr print
jmp b2
// main::@2
b2:
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #4
cmp.z i
bne b1_from_b2
jmp breturn
// main::@return
breturn:
// [13] return
rts
}
// print
// print(byte zeropage(6) p_x, signed word zeropage(7) p_y)
print: {
.label _0 = $a
.label _1 = $c
.label p_x = 6
.label p_y = 7
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z p_x
ldy.z idx_14
sta SCREEN,y
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
ldy.z idx_14
iny
sty.z idx
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuz1=_lo_vwsz2
lda.z p_y
sta.z _0
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z _0
ldy.z idx
sta SCREEN,y
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz2
ldy.z idx
iny
sty.z idx_4
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuz1=_hi_vwsz2
lda.z p_y+1
sta.z _1
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z _1
ldy.z idx_4
sta SCREEN,y
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
ldy.z idx_4
iny
sty.z idx_5
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
lda #' '
ldy.z idx_5
sta SCREEN,y
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuz2
ldy.z idx_5
iny
sty.z idx_12
jmp breturn
// print::@return
breturn:
// [24] return
rts
}
// File Data
points:
.byte 1
.word $83f
.byte 3
.word $107e
.byte 0
.word 0
.byte 0
.word 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 [ main::i#2 idx#14 main::$5 ] ( main:2 [ main::i#2 idx#14 main::$5 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ idx#14 idx#12 ]
Statement [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 [ main::i#2 idx#14 main::$2 ] ( main:2 [ main::i#2 idx#14 main::$2 ] ) always clobbers reg byte a
Statement [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ( main:2 [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ print::p_x#0 ]
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 [ idx#14 print::p_y#0 ] ( main:2::print:10 [ main::i#2 idx#14 print::p_y#0 ] ) always clobbers reg byte a
Statement [16] (byte~) print::$0 ← < (signed word) print::p_y#0 [ print::p_y#0 idx#3 print::$0 ] ( main:2::print:10 [ main::i#2 print::p_y#0 idx#3 print::$0 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ idx#3 ]
Statement [19] (byte~) print::$1 ← > (signed word) print::p_y#0 [ idx#4 print::$1 ] ( main:2::print:10 [ main::i#2 idx#4 print::$1 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:11 [ idx#4 ]
Statement [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' [ idx#5 ] ( main:2::print:10 [ main::i#2 idx#5 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:13 [ idx#5 ]
Statement [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 [ main::i#2 idx#14 main::$5 ] ( main:2 [ main::i#2 idx#14 main::$5 ] ) always clobbers reg byte a
Statement [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 [ main::i#2 idx#14 main::$2 ] ( main:2 [ main::i#2 idx#14 main::$2 ] ) always clobbers reg byte a
Statement [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ( main:2 [ main::i#2 idx#14 print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 [ idx#14 print::p_y#0 ] ( main:2::print:10 [ main::i#2 idx#14 print::p_y#0 ] ) always clobbers reg byte a
Statement [16] (byte~) print::$0 ← < (signed word) print::p_y#0 [ print::p_y#0 idx#3 print::$0 ] ( main:2::print:10 [ main::i#2 print::p_y#0 idx#3 print::$0 ] ) always clobbers reg byte a
Statement [19] (byte~) print::$1 ← > (signed word) print::p_y#0 [ idx#4 print::$1 ] ( main:2::print:10 [ main::i#2 idx#4 print::$1 ] ) always clobbers reg byte a
Statement [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' [ idx#5 ] ( main:2::print:10 [ main::i#2 idx#5 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ idx#14 idx#12 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:4 [ main::$5 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:5 [ main::$2 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:6 [ print::p_x#0 ] : zp ZP_BYTE:6 , reg byte x , reg byte y ,
Potential registers zp ZP_WORD:7 [ print::p_y#0 ] : zp ZP_WORD:7 ,
Potential registers zp ZP_BYTE:9 [ idx#3 ] : zp ZP_BYTE:9 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:10 [ print::$0 ] : zp ZP_BYTE:10 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:11 [ idx#4 ] : zp ZP_BYTE:11 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:12 [ print::$1 ] : zp ZP_BYTE:12 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:13 [ idx#5 ] : zp ZP_BYTE:13 , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 23.83: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 22: zp ZP_BYTE:4 [ main::$5 ] 16.5: zp ZP_BYTE:5 [ main::$2 ]
Uplift Scope [print] 6.5: zp ZP_BYTE:6 [ print::p_x#0 ] 4: zp ZP_BYTE:10 [ print::$0 ] 4: zp ZP_BYTE:12 [ print::$1 ] 2.5: zp ZP_WORD:7 [ print::p_y#0 ]
Uplift Scope [] 5.1: zp ZP_BYTE:3 [ idx#14 idx#12 ] 3: zp ZP_BYTE:13 [ idx#5 ] 2: zp ZP_BYTE:9 [ idx#3 ] 2: zp ZP_BYTE:11 [ idx#4 ]
Uplift Scope [Point]
Uplifting [main] best 794 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$5 ] reg byte y [ main::$2 ]
Uplifting [print] best 782 combination zp ZP_BYTE:6 [ print::p_x#0 ] reg byte a [ print::$0 ] reg byte a [ print::$1 ] zp ZP_WORD:7 [ print::p_y#0 ]
Uplifting [] best 755 combination zp ZP_BYTE:3 [ idx#14 idx#12 ] reg byte y [ idx#5 ] reg byte y [ idx#3 ] reg byte y [ idx#4 ]
Uplifting [Point] best 755 combination
Attempting to uplift remaining variables inzp ZP_BYTE:6 [ print::p_x#0 ]
Uplifting [print] best 755 combination zp ZP_BYTE:6 [ print::p_x#0 ]
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ idx#14 idx#12 ]
Uplifting [] best 755 combination zp ZP_BYTE:3 [ idx#14 idx#12 ]
Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ idx#14 idx#12 ]
Allocated (was zp ZP_BYTE:6) zp ZP_BYTE:3 [ print::p_x#0 ]
Allocated (was zp ZP_WORD:7) zp ZP_WORD:4 [ print::p_y#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test a struct array initialized with to few members (zero-filled for the rest)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
.label idx = 2
// @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: {
// [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z idx
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
ldx #0
jmp b1
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
jmp b1
// main::@1
b1:
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
txa
asl
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx
stx.z $ff
clc
adc.z $ff
tay
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuyy
lda points,y
sta.z print.p_x
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuyy
lda points+OFFSET_STRUCT_POINT_Y,y
sta.z print.p_y
lda points+OFFSET_STRUCT_POINT_Y+1,y
sta.z print.p_y+1
// [10] call print
jsr print
jmp b2
// main::@2
b2:
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #4
bne b1_from_b2
jmp breturn
// main::@return
breturn:
// [13] return
rts
}
// print
// print(byte zeropage(3) p_x, signed word zeropage(4) p_y)
print: {
.label p_x = 3
.label p_y = 4
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z p_x
ldy.z idx
sta SCREEN,y
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuz1
ldy.z idx
iny
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuaa=_lo_vwsz1
lda.z p_y
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuyy=_inc_vbuyy
iny
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuaa=_hi_vwsz1
lda.z p_y+1
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuyy=_inc_vbuyy
iny
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2
lda #' '
sta SCREEN,y
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuyy
iny
sty.z idx
jmp breturn
// print::@return
breturn:
// [24] return
rts
}
// File Data
points:
.byte 1
.word $83f
.byte 3
.word $107e
.byte 0
.word 0
.byte 0
.word 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp breturn
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing instruction ldx #0 with TAX
Removing instruction ldy.z idx
Succesful ASM optimization Pass5UnnecesaryLoadElimination
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_b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction b2:
Removing instruction breturn:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(signed word) Point::y
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
(byte) idx
(byte) idx#12 idx zp ZP_BYTE:2 2.6
(byte) idx#14 idx zp ZP_BYTE:2 2.5
(byte) idx#3 reg byte y 2.0
(byte) idx#4 reg byte y 2.0
(byte) idx#5 reg byte y 3.0
(void()) main()
(byte~) main::$2 reg byte y 16.5
(byte) main::$5 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 7.333333333333333
(struct Point[4]) points
(const struct Point[4]) points#0 points = { { x: (byte) 1, y: (signed word) $83f }, { x: (byte) 3, y: (signed word) $107e } }
(void()) print((byte) print::p_x , (signed word) print::p_y)
(byte~) print::$0 reg byte a 4.0
(byte~) print::$1 reg byte a 4.0
(label) print::@return
(struct Point) print::p
(byte) print::p_x
(byte) print::p_x#0 p_x zp ZP_BYTE:3 6.5
(signed word) print::p_y
(signed word) print::p_y#0 p_y zp ZP_WORD:4 2.5
reg byte x [ main::i#2 main::i#1 ]
zp ZP_BYTE:2 [ idx#14 idx#12 ]
reg byte a [ main::$5 ]
reg byte y [ main::$2 ]
zp ZP_BYTE:3 [ print::p_x#0 ]
zp ZP_WORD:4 [ print::p_y#0 ]
reg byte y [ idx#3 ]
reg byte a [ print::$0 ]
reg byte y [ idx#4 ]
reg byte a [ print::$1 ]
reg byte y [ idx#5 ]
FINAL ASSEMBLER
Score: 617
// File Comments
// Test a struct array initialized with to few members (zero-filled for the rest)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
.label idx = 2
// @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: {
// [5] phi from main to main::@1 [phi:main->main::@1]
// [5] phi (byte) idx#14 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta.z idx
// [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1
tax
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [5] phi (byte) idx#14 = (byte) idx#12 [phi:main::@2->main::@1#0] -- register_copy
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#1] -- register_copy
// main::@1
b1:
// print(points[i])
// [6] (byte) main::$5 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1
txa
asl
// [7] (byte~) main::$2 ← (byte) main::$5 + (byte) main::i#2 -- vbuyy=vbuaa_plus_vbuxx
stx.z $ff
clc
adc.z $ff
tay
// [8] (byte) print::p_x#0 ← *((byte*)(const struct Point[4]) points#0 + (byte~) main::$2) -- vbuz1=pbuc1_derefidx_vbuyy
lda points,y
sta.z print.p_x
// [9] (signed word) print::p_y#0 ← *((signed word*)(const struct Point[4]) points#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$2) -- vwsz1=pwsc1_derefidx_vbuyy
lda points+OFFSET_STRUCT_POINT_Y,y
sta.z print.p_y
lda points+OFFSET_STRUCT_POINT_Y+1,y
sta.z print.p_y+1
// [10] call print
jsr print
// main::@2
// for ( char i: 0..3)
// [11] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [12] if((byte) main::i#1!=(byte) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #4
bne b1
// main::@return
// }
// [13] return
rts
}
// print
// print(byte zeropage(3) p_x, signed word zeropage(4) p_y)
print: {
.label p_x = 3
.label p_y = 4
// SCREEN[idx++] = p.x
// [14] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2
lda.z p_x
ldy.z idx
sta SCREEN,y
// SCREEN[idx++] = p.x;
// [15] (byte) idx#3 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuz1
iny
// <p.y
// [16] (byte~) print::$0 ← < (signed word) print::p_y#0 -- vbuaa=_lo_vwsz1
lda.z p_y
// SCREEN[idx++] = <p.y
// [17] *((const byte*) SCREEN#0 + (byte) idx#3) ← (byte~) print::$0 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
// SCREEN[idx++] = <p.y;
// [18] (byte) idx#4 ← ++ (byte) idx#3 -- vbuyy=_inc_vbuyy
iny
// >p.y
// [19] (byte~) print::$1 ← > (signed word) print::p_y#0 -- vbuaa=_hi_vwsz1
lda.z p_y+1
// SCREEN[idx++] = >p.y
// [20] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte~) print::$1 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
// SCREEN[idx++] = >p.y;
// [21] (byte) idx#5 ← ++ (byte) idx#4 -- vbuyy=_inc_vbuyy
iny
// SCREEN[idx++] = ' '
// [22] *((const byte*) SCREEN#0 + (byte) idx#5) ← (byte) ' ' -- pbuc1_derefidx_vbuyy=vbuc2
lda #' '
sta SCREEN,y
// SCREEN[idx++] = ' ';
// [23] (byte) idx#12 ← ++ (byte) idx#5 -- vbuz1=_inc_vbuyy
iny
sty.z idx
// print::@return
// }
// [24] return
rts
}
// File Data
points:
.byte 1
.word $83f
.byte 3
.word $107e
.byte 0
.word 0
.byte 0
.word 0