1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-26 12:49:21 +00:00

Added missing ref files.

This commit is contained in:
jespergravgaard 2020-12-05 23:56:32 +01:00
parent 8b6fabc9c8
commit c1af79cf47
8 changed files with 1342 additions and 0 deletions

View File

@ -0,0 +1,58 @@
// Test combining unwind structs with classic structs
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
main: {
.label p1 = 2
// p1 = { 1, 2 }
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// SCREEN[0] = p1
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN-1,y
dey
bne !-
// p2 = p1
lda.z p1
ldx p1+OFFSET_STRUCT_POINT_Y
// SCREEN[2] = p2
sta SCREEN+2*SIZEOF_STRUCT_POINT
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// p1.x = 3
// Set in classic struct
lda #3
sta.z p1
// SCREEN[4] = p1
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
// SCREEN[6] = p2
lda #4
sta SCREEN+6*SIZEOF_STRUCT_POINT
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// p1 = p2
sta.z p1
stx p1+OFFSET_STRUCT_POINT_Y
// SCREEN[8] = p1
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
// }
rts
}
__0: .byte 1, 2

View File

@ -0,0 +1,20 @@
void main()
main: scope:[main] from
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
[1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[2] main::p2_x#0 = *((byte*)&main::p1)
[3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
[4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0
[5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[6] *((byte*)&main::p1) = 3
[7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4
[9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[10] *((byte*)&main::p1) = 4
[11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
to:main::@return
main::@return: scope:[main] from main
[13] return
to:@return

View File

@ -0,0 +1,423 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
*(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
main::p1 = struct-unwound {*(&main::p1)}
main::$0 = 0 * SIZEOF_STRUCT_POINT
SCREEN[main::$0] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
main::p2_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
main::$1 = 2 * SIZEOF_STRUCT_POINT
main::$5 = (byte*)SCREEN + main::$1
main::$5[OFFSET_STRUCT_POINT_X] = main::p2_x#0
main::$6 = (byte*)SCREEN + main::$1
main::$6[OFFSET_STRUCT_POINT_Y] = main::p2_y#0
*((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
main::$2 = 4 * SIZEOF_STRUCT_POINT
SCREEN[main::$2] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
main::p2_x#1 = 4
main::$3 = 6 * SIZEOF_STRUCT_POINT
main::$7 = (byte*)SCREEN + main::$3
main::$7[OFFSET_STRUCT_POINT_X] = main::p2_x#1
main::$8 = (byte*)SCREEN + main::$3
main::$8[OFFSET_STRUCT_POINT_Y] = main::p2_y#0
*((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = main::p2_x#1
*((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
main::p1 = struct-unwound {*((byte*)&main::p1+OFFSET_STRUCT_POINT_X), *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)}
main::$4 = 8 * SIZEOF_STRUCT_POINT
SCREEN[main::$4] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_X = 0
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*)$400
const byte SIZEOF_STRUCT_POINT = 2
void __start()
void main()
number~ main::$0
number~ main::$1
number~ main::$2
number~ main::$3
number~ main::$4
byte*~ main::$5
byte*~ main::$6
byte*~ main::$7
byte*~ main::$8
struct Point main::p1 loadstore
byte main::p2_x
byte main::p2_x#0
byte main::p2_x#1
byte main::p2_y
byte main::p2_y#0
Adding number conversion cast (unumber) 0 in main::$0 = 0 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$0 in main::$0 = (unumber)0 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 2 in main::$1 = 2 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$1 in main::$1 = (unumber)2 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 3 in *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
Adding number conversion cast (unumber) 4 in main::$2 = 4 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$2 in main::$2 = (unumber)4 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 4 in main::p2_x#1 = 4
Adding number conversion cast (unumber) 6 in main::$3 = 6 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$3 in main::$3 = (unumber)6 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) 8 in main::$4 = 8 * SIZEOF_STRUCT_POINT
Adding number conversion cast (unumber) main::$4 in main::$4 = (unumber)8 * SIZEOF_STRUCT_POINT
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = (unumber)3
Inlining cast main::p2_x#1 = (unumber)4
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (struct Point*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 2
Simplifying constant integer cast 3
Simplifying constant integer cast 4
Simplifying constant integer cast 4
Simplifying constant integer cast 6
Simplifying constant integer cast 8
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type 0
Finalized unsigned number type 2
Finalized unsigned number type 3
Finalized unsigned number type 4
Finalized unsigned number type 4
Finalized unsigned number type 6
Finalized unsigned number type 8
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to byte in main::$0 = 0 * SIZEOF_STRUCT_POINT
Inferred type updated to byte in main::$1 = 2 * SIZEOF_STRUCT_POINT
Inferred type updated to byte in main::$2 = 4 * SIZEOF_STRUCT_POINT
Inferred type updated to byte in main::$3 = 6 * SIZEOF_STRUCT_POINT
Inferred type updated to byte in main::$4 = 8 * SIZEOF_STRUCT_POINT
Removing C-classic struct-unwound assignment [1] main::p1 = struct-unwound {*(&main::p1)}
Removing C-classic struct-unwound assignment [22] main::p1 = struct-unwound {*((byte*)&main::p1+OFFSET_STRUCT_POINT_X), *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)}
Constant right-side identified [2] main::$0 = 0 * SIZEOF_STRUCT_POINT
Constant right-side identified [6] main::$1 = 2 * SIZEOF_STRUCT_POINT
Constant right-side identified [12] main::$2 = 4 * SIZEOF_STRUCT_POINT
Constant right-side identified [15] main::$3 = 6 * SIZEOF_STRUCT_POINT
Constant right-side identified [23] main::$4 = 8 * SIZEOF_STRUCT_POINT
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::$0 = 0*SIZEOF_STRUCT_POINT
Constant main::$1 = 2*SIZEOF_STRUCT_POINT
Constant main::$2 = 4*SIZEOF_STRUCT_POINT
Constant main::p2_x#1 = 4
Constant main::$3 = 6*SIZEOF_STRUCT_POINT
Constant main::$4 = 8*SIZEOF_STRUCT_POINT
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero 0*SIZEOF_STRUCT_POINT in
Successful SSA optimization PassNSimplifyConstantZero
Simplifying expression containing zero SCREEN in [3] SCREEN[main::$0] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
Simplifying expression containing zero (byte*)&main::p1 in [4] main::p2_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero main::$5 in [8] main::$5[OFFSET_STRUCT_POINT_X] = main::p2_x#0
Simplifying expression containing zero (byte*)&main::p1 in [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
Simplifying expression containing zero main::$7 in [17] main::$7[OFFSET_STRUCT_POINT_X] = main::p2_x#1
Simplifying expression containing zero (byte*)&main::p1 in [20] *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = main::p2_x#1
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant main::$0
Eliminating unused constant OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Constant right-side identified [4] main::$5 = (byte*)SCREEN + main::$1
Constant right-side identified [6] main::$6 = (byte*)SCREEN + main::$1
Constant right-side identified [10] main::$7 = (byte*)SCREEN + main::$3
Constant right-side identified [12] main::$8 = (byte*)SCREEN + main::$3
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::$5 = (byte*)SCREEN+main::$1
Constant main::$6 = (byte*)SCREEN+main::$1
Constant main::$7 = (byte*)SCREEN+main::$3
Constant main::$8 = (byte*)SCREEN+main::$3
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings main::p2_x#1
Constant inlined main::$1 = 2*SIZEOF_STRUCT_POINT
Constant inlined main::$2 = 4*SIZEOF_STRUCT_POINT
Constant inlined main::$5 = (byte*)SCREEN+2*SIZEOF_STRUCT_POINT
Constant inlined main::$6 = (byte*)SCREEN+2*SIZEOF_STRUCT_POINT
Constant inlined main::$3 = 6*SIZEOF_STRUCT_POINT
Constant inlined main::$4 = 8*SIZEOF_STRUCT_POINT
Constant inlined main::$7 = (byte*)SCREEN+6*SIZEOF_STRUCT_POINT
Constant inlined main::p2_x#1 = 4
Constant inlined main::$8 = (byte*)SCREEN+6*SIZEOF_STRUCT_POINT
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+4*SIZEOF_STRUCT_POINT)
Consolidated array index constant in *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y)
Consolidated array index constant in *(SCREEN+8*SIZEOF_STRUCT_POINT)
Successful SSA optimization Pass2ConstantAdditionElimination
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
[1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[2] main::p2_x#0 = *((byte*)&main::p1)
[3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
[4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0
[5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[6] *((byte*)&main::p1) = 3
[7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4
[9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[10] *((byte*)&main::p1) = 4
[11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
[12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
to:main::@return
main::@return: scope:[main] from main
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
struct Point main::p1 loadstore
byte main::p2_x
byte main::p2_x#0 2.0
byte main::p2_y
byte main::p2_y#0 1.0
Initial phi equivalence classes
Added variable main::p2_x#0 to live range equivalence class [ main::p2_x#0 ]
Added variable main::p2_y#0 to live range equivalence class [ main::p2_y#0 ]
Added variable main::p1 to live range equivalence class [ main::p1 ]
Complete equivalence classes
[ main::p2_x#0 ]
[ main::p2_y#0 ]
[ main::p1 ]
Allocated zp[1]:2 [ main::p2_x#0 ]
Allocated zp[1]:3 [ main::p2_y#0 ]
Allocated zp[2]:4 [ main::p1 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
Statement [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
Statement [6] *((byte*)&main::p1) = 3 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::p2_y#0 ]
Statement [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte y as potential for zp[1]:3 [ main::p2_y#0 ]
Statement [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)&main::p1) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Statement [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
Statement [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
Statement [6] *((byte*)&main::p1) = 3 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Statement [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a reg byte y
Statement [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)&main::p1) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
Statement [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
Potential registers zp[1]:2 [ main::p2_x#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ main::p2_y#0 ] : zp[1]:3 , reg byte x ,
Potential registers zp[2]:4 [ main::p1 ] : zp[2]:4 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 2: zp[1]:2 [ main::p2_x#0 ] 1: zp[1]:3 [ main::p2_y#0 ] 0: zp[2]:4 [ main::p1 ]
Uplift Scope [Point]
Uplift Scope []
Uplifting [main] best 112 combination reg byte a [ main::p2_x#0 ] reg byte x [ main::p2_y#0 ] zp[2]:4 [ main::p1 ]
Uplifting [Point] best 112 combination
Uplifting [] best 112 combination
Allocated (was zp[2]:4) zp[2]:2 [ main::p1 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test combining unwind structs with classic structs
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
// main
main: {
.label p1 = 2
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN-1,y
dey
bne !-
// [2] main::p2_x#0 = *((byte*)&main::p1) -- vbuaa=_deref_pbuc1
lda.z p1
// [3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx p1+OFFSET_STRUCT_POINT_Y
// [4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0 -- _deref_pbuc1=vbuaa
sta SCREEN+2*SIZEOF_STRUCT_POINT
// [5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// [6] *((byte*)&main::p1) = 3 -- _deref_pbuc1=vbuc2
// Set in classic struct
lda #3
sta.z p1
// [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
// [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 -- _deref_pbuc1=vbuc2
lda #4
sta SCREEN+6*SIZEOF_STRUCT_POINT
// [9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// [10] *((byte*)&main::p1) = 4 -- _deref_pbuc1=vbuc2
lda #4
sta.z p1
// [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx p1+OFFSET_STRUCT_POINT_Y
// [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
jmp __breturn
// main::@return
__breturn:
// [13] return
rts
}
// File Data
__0: .byte 1, 2
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #4
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*) 1024
const byte SIZEOF_STRUCT_POINT = 2
void main()
struct Point main::p1 loadstore zp[2]:2
byte main::p2_x
byte main::p2_x#0 reg byte a 2.0
byte main::p2_y
byte main::p2_y#0 reg byte x 1.0
reg byte a [ main::p2_x#0 ]
reg byte x [ main::p2_y#0 ]
zp[2]:2 [ main::p1 ]
FINAL ASSEMBLER
Score: 107
// File Comments
// Test combining unwind structs with classic structs
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
// main
main: {
.label p1 = 2
// p1 = { 1, 2 }
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// SCREEN[0] = p1
// [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN-1,y
dey
bne !-
// p2 = p1
// [2] main::p2_x#0 = *((byte*)&main::p1) -- vbuaa=_deref_pbuc1
lda.z p1
// [3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx p1+OFFSET_STRUCT_POINT_Y
// SCREEN[2] = p2
// [4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0 -- _deref_pbuc1=vbuaa
sta SCREEN+2*SIZEOF_STRUCT_POINT
// [5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// p1.x = 3
// [6] *((byte*)&main::p1) = 3 -- _deref_pbuc1=vbuc2
// Set in classic struct
lda #3
sta.z p1
// SCREEN[4] = p1
// [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
// SCREEN[6] = p2
// [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 -- _deref_pbuc1=vbuc2
lda #4
sta SCREEN+6*SIZEOF_STRUCT_POINT
// [9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
// p1 = p2
// [10] *((byte*)&main::p1) = 4 -- _deref_pbuc1=vbuc2
sta.z p1
// [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
stx p1+OFFSET_STRUCT_POINT_Y
// SCREEN[8] = p1
// [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
dey
bne !-
// main::@return
// }
// [13] return
rts
}
// File Data
__0: .byte 1, 2

View File

@ -0,0 +1,14 @@
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*) 1024
const byte SIZEOF_STRUCT_POINT = 2
void main()
struct Point main::p1 loadstore zp[2]:2
byte main::p2_x
byte main::p2_x#0 reg byte a 2.0
byte main::p2_y
byte main::p2_y#0 reg byte x 1.0
reg byte a [ main::p2_x#0 ]
reg byte x [ main::p2_y#0 ]
zp[2]:2 [ main::p1 ]

View File

@ -0,0 +1,86 @@
// Test combining unwind structs with classic structs
// Function calls parameter passing
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
main: {
.const p2_x = 3
.const p2_y = 4
.label p1 = 3
// p1 = { 1, 2 }
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// print1(p1, 0)
ldy.z p1
ldx p1+OFFSET_STRUCT_POINT_Y
// Pass classic struct to function taking unwound struct
lda #0
jsr print1
// print2(p1, 2)
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta print2.p-1,y
dey
bne !-
// Pass classic struct to function taking classic struct
lda #2
jsr print2
// print1(p2, 4)
// Pass unwound struct to function taking unwound struct
ldx #p2_y
ldy #p2_x
lda #4
jsr print1
// print2(p2, 6)
lda #p2_x
sta.z print2.p
lda #p2_y
sta print2.p+OFFSET_STRUCT_POINT_Y
// Pass unwound struct to function taking classic struct
lda #6
jsr print2
// }
rts
}
// Function taking unwound struct as parameter
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
print1: {
.label __0 = 2
// SCREEN[idx] = p
asl
sta.z __0
tya
ldy.z __0
sta SCREEN,y
txa
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
// }
rts
}
// Function taking classic struct as parameter
// print2(struct Point zp(5) p, byte register(A) idx)
print2: {
.label p = 5
// SCREEN[idx] = p
asl
tay
ldx #0
!:
lda.z p,x
sta SCREEN,y
iny
inx
cpx #SIZEOF_STRUCT_POINT
bne !-
// }
rts
}
__0: .byte 1, 2

View File

@ -0,0 +1,47 @@
void main()
main: scope:[main] from
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
[1] print1::p_x#0 = *((byte*)&main::p1)
[2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
[3] call print1
to:main::@1
main::@1: scope:[main] from main
[4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[5] call print2
to:main::@2
main::@2: scope:[main] from main::@1
[6] phi()
[7] call print1
to:main::@3
main::@3: scope:[main] from main::@2
[8] *((byte*)&print2::p) = main::p2_x
[9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
[10] call print2
to:main::@return
main::@return: scope:[main] from main::@3
[11] return
to:@return
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
print1: scope:[print1] from main main::@2
[12] print1::p_y#2 = phi( main/print1::p_y#0, main::@2/main::p2_y )
[12] print1::p_x#2 = phi( main/print1::p_x#0, main::@2/main::p2_x )
[12] print1::idx#2 = phi( main/0, main::@2/4 )
[13] print1::$0 = print1::idx#2 << 1
[14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2
[15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
to:print1::@return
print1::@return: scope:[print1] from print1
[16] return
to:@return
void print2(struct Point print2::p , byte print2::idx)
print2: scope:[print2] from main::@1 main::@3
[17] print2::idx#2 = phi( main::@1/2, main::@3/6 )
[18] print2::$0 = print2::idx#2 << 1
[19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
to:print2::@return
print2::@return: scope:[print2] from print2
[20] return
to:@return

View File

@ -0,0 +1,660 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
*(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
main::p1 = struct-unwound {*(&main::p1)}
print1::p_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
print1::idx#0 = 0
call print1
to:main::@1
main::@1: scope:[main] from main
*(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
print2::p = struct-unwound {*(&print2::p)}
print2::idx#0 = 2
call print2
to:main::@2
main::@2: scope:[main] from main::@1
main::p2#0 = struct-unwound {main::p2_x, main::p2_y}
print1::p_x#1 = main::p2_x
print1::p_y#1 = main::p2_y
print1::idx#1 = 4
call print1
to:main::@3
main::@3: scope:[main] from main::@2
*((byte*)&print2::p+OFFSET_STRUCT_POINT_X) = main::p2_x
*((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
print2::p = struct-unwound {*((byte*)&print2::p+OFFSET_STRUCT_POINT_X), *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y)}
print2::idx#1 = 6
call print2
to:main::@4
main::@4: scope:[main] from main::@3
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
print1: scope:[print1] from main main::@2
print1::p_y#2 = phi( main/print1::p_y#0, main::@2/print1::p_y#1 )
print1::p_x#2 = phi( main/print1::p_x#0, main::@2/print1::p_x#1 )
print1::idx#2 = phi( main/print1::idx#0, main::@2/print1::idx#1 )
print1::$0 = print1::idx#2 * SIZEOF_STRUCT_POINT
((byte*)SCREEN+OFFSET_STRUCT_POINT_X)[print1::$0] = print1::p_x#2
((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
to:print1::@return
print1::@return: scope:[print1] from print1
return
to:@return
void print2(struct Point print2::p , byte print2::idx)
print2: scope:[print2] from main::@1 main::@3
print2::idx#2 = phi( main::@1/print2::idx#0, main::@3/print2::idx#1 )
print2::$0 = print2::idx#2 * SIZEOF_STRUCT_POINT
SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
to:print2::@return
print2::@return: scope:[print2] from print2
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_X = 0
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*)$400
const byte SIZEOF_STRUCT_POINT = 2
void __start()
void main()
struct Point main::p1 loadstore
struct Point main::p2
struct Point main::p2#0
const byte main::p2_x = 3
const byte main::p2_y = 4
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
byte~ print1::$0
byte print1::idx
byte print1::idx#0
byte print1::idx#1
byte print1::idx#2
struct Point print1::p
byte print1::p_x
byte print1::p_x#0
byte print1::p_x#1
byte print1::p_x#2
byte print1::p_y
byte print1::p_y#0
byte print1::p_y#1
byte print1::p_y#2
void print2(struct Point print2::p , byte print2::idx)
byte~ print2::$0
byte print2::idx
byte print2::idx#0
byte print2::idx#1
byte print2::idx#2
struct Point print2::p loadstore
Adding number conversion cast (unumber) 0 in print1::idx#0 = 0
Adding number conversion cast (unumber) 2 in print2::idx#0 = 2
Adding number conversion cast (unumber) 4 in print1::idx#1 = 4
Adding number conversion cast (unumber) 6 in print2::idx#1 = 6
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast print1::idx#0 = (unumber)0
Inlining cast print2::idx#0 = (unumber)2
Inlining cast print1::idx#1 = (unumber)4
Inlining cast print2::idx#1 = (unumber)6
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (struct Point*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 2
Simplifying constant integer cast 4
Simplifying constant integer cast 6
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type 0
Finalized unsigned number type 2
Finalized unsigned number type 4
Finalized unsigned number type 6
Successful SSA optimization PassNFinalizeNumberTypeConversions
Removing C-classic struct-unwound assignment [1] main::p1 = struct-unwound {*(&main::p1)}
Removing C-classic struct-unwound assignment [7] print2::p = struct-unwound {*(&print2::p)}
Removing C-classic struct-unwound assignment [17] print2::p = struct-unwound {*((byte*)&print2::p+OFFSET_STRUCT_POINT_X), *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y)}
Constant print1::idx#0 = 0
Constant print2::idx#0 = 2
Constant print1::p_x#1 = main::p2_x
Constant print1::p_y#1 = main::p2_y
Constant print1::idx#1 = 4
Constant print2::idx#1 = 6
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&main::p1 in [2] print1::p_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero (byte*)&print2::p in [15] *((byte*)&print2::p+OFFSET_STRUCT_POINT_X) = main::p2_x
Simplifying expression containing zero (byte*)SCREEN in [23] ((byte*)SCREEN+OFFSET_STRUCT_POINT_X)[print1::$0] = print1::p_x#2
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable main::p2#0 and assignment [6] main::p2#0 = struct-unwound {main::p2_x, main::p2_y}
Eliminating unused constant OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Rewriting multiplication to use shift [12] print1::$0 = print1::idx#2 * SIZEOF_STRUCT_POINT
Rewriting multiplication to use shift [17] print2::$0 = print2::idx#2 * SIZEOF_STRUCT_POINT
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings print1::idx#0
Inlining constant with var siblings print1::p_x#1
Inlining constant with var siblings print1::p_y#1
Inlining constant with var siblings print1::idx#1
Inlining constant with var siblings print2::idx#0
Inlining constant with var siblings print2::idx#1
Constant inlined print1::idx#1 = 4
Constant inlined print1::idx#0 = 0
Constant inlined print1::p_x#1 = main::p2_x
Constant inlined print1::p_y#1 = main::p2_y
Constant inlined print2::idx#0 = 2
Constant inlined print2::idx#1 = 6
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of main::@2
Adding NOP phi() at start of main::@4
CALL GRAPH
Calls in [main] to print1:5 print2:7 print1:9 print2:12
Created 4 initial phi equivalence classes
Coalesced [3] print1::p_x#3 = print1::p_x#0
Coalesced [4] print1::p_y#3 = print1::p_y#0
Coalesced down to 4 phi equivalence classes
Culled Empty Block label main::@4
Adding NOP phi() at start of main::@2
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
[1] print1::p_x#0 = *((byte*)&main::p1)
[2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
[3] call print1
to:main::@1
main::@1: scope:[main] from main
[4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
[5] call print2
to:main::@2
main::@2: scope:[main] from main::@1
[6] phi()
[7] call print1
to:main::@3
main::@3: scope:[main] from main::@2
[8] *((byte*)&print2::p) = main::p2_x
[9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
[10] call print2
to:main::@return
main::@return: scope:[main] from main::@3
[11] return
to:@return
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
print1: scope:[print1] from main main::@2
[12] print1::p_y#2 = phi( main/print1::p_y#0, main::@2/main::p2_y )
[12] print1::p_x#2 = phi( main/print1::p_x#0, main::@2/main::p2_x )
[12] print1::idx#2 = phi( main/0, main::@2/4 )
[13] print1::$0 = print1::idx#2 << 1
[14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2
[15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
to:print1::@return
print1::@return: scope:[print1] from print1
[16] return
to:@return
void print2(struct Point print2::p , byte print2::idx)
print2: scope:[print2] from main::@1 main::@3
[17] print2::idx#2 = phi( main::@1/2, main::@3/6 )
[18] print2::$0 = print2::idx#2 << 1
[19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
to:print2::@return
print2::@return: scope:[print2] from print2
[20] return
to:@return
VARIABLE REGISTER WEIGHTS
void main()
struct Point main::p1 loadstore
struct Point main::p2
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
byte~ print1::$0 16.5
byte print1::idx
byte print1::idx#2 11.0
struct Point print1::p
byte print1::p_x
byte print1::p_x#0 2.0
byte print1::p_x#2 6.5
byte print1::p_y
byte print1::p_y#0 4.0
byte print1::p_y#2 4.333333333333333
void print2(struct Point print2::p , byte print2::idx)
byte~ print2::$0 22.0
byte print2::idx
byte print2::idx#2 11.0
struct Point print2::p loadstore
Initial phi equivalence classes
[ print1::idx#2 ]
[ print1::p_x#2 print1::p_x#0 ]
[ print1::p_y#2 print1::p_y#0 ]
[ print2::idx#2 ]
Added variable print1::$0 to live range equivalence class [ print1::$0 ]
Added variable print2::$0 to live range equivalence class [ print2::$0 ]
Added variable main::p1 to live range equivalence class [ main::p1 ]
Added variable print2::p to live range equivalence class [ print2::p ]
Complete equivalence classes
[ print1::idx#2 ]
[ print1::p_x#2 print1::p_x#0 ]
[ print1::p_y#2 print1::p_y#0 ]
[ print2::idx#2 ]
[ print1::$0 ]
[ print2::$0 ]
[ main::p1 ]
[ print2::p ]
Allocated zp[1]:2 [ print1::idx#2 ]
Allocated zp[1]:3 [ print1::p_x#2 print1::p_x#0 ]
Allocated zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
Allocated zp[1]:5 [ print2::idx#2 ]
Allocated zp[1]:6 [ print1::$0 ]
Allocated zp[1]:7 [ print2::$0 ]
Allocated zp[2]:8 [ main::p1 ]
Allocated zp[2]:10 [ print2::p ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 print2::p ] ( [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } ) always clobbers reg byte a reg byte y
Statement [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a reg byte y
Statement [8] *((byte*)&print2::p) = main::p2_x [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
Statement [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
Statement [13] print1::$0 = print1::idx#2 << 1 [ print1::p_x#2 print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:3 [ print1::p_x#2 print1::p_x#0 ]
Removing always clobbered register reg byte a as potential for zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
Statement [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 [ print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:6 [ print1::$0 ]
Statement [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 [ ] ( print1:3 [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p ] { } ) always clobbers reg byte a
Statement [18] print2::$0 = print2::idx#2 << 1 [ print2::p print2::$0 ] ( print2:5 [ print2::p print2::$0 ] { } print2:10 [ print2::p print2::$0 ] { } ) always clobbers reg byte a
Statement [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( print2:5 [ print2::p ] { } print2:10 [ print2::p ] { } ) always clobbers reg byte a reg byte x reg byte y
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 print2::p ] ( [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } ) always clobbers reg byte a reg byte y
Statement [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a reg byte y
Statement [8] *((byte*)&print2::p) = main::p2_x [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
Statement [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
Statement [13] print1::$0 = print1::idx#2 << 1 [ print1::p_x#2 print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
Statement [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 [ print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
Statement [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 [ ] ( print1:3 [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p ] { } ) always clobbers reg byte a
Statement [18] print2::$0 = print2::idx#2 << 1 [ print2::p print2::$0 ] ( print2:5 [ print2::p print2::$0 ] { } print2:10 [ print2::p print2::$0 ] { } ) always clobbers reg byte a
Statement [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( print2:5 [ print2::p ] { } print2:10 [ print2::p ] { } ) always clobbers reg byte a reg byte x reg byte y
Potential registers zp[1]:2 [ print1::idx#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ print1::p_x#2 print1::p_x#0 ] : zp[1]:3 , reg byte x , reg byte y ,
Potential registers zp[1]:4 [ print1::p_y#2 print1::p_y#0 ] : zp[1]:4 , reg byte x , reg byte y ,
Potential registers zp[1]:5 [ print2::idx#2 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[1]:6 [ print1::$0 ] : zp[1]:6 , reg byte x , reg byte y ,
Potential registers zp[1]:7 [ print2::$0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
Potential registers zp[2]:8 [ main::p1 ] : zp[2]:8 ,
Potential registers zp[2]:10 [ print2::p ] : zp[2]:10 ,
REGISTER UPLIFT SCOPES
Uplift Scope [print1] 16.5: zp[1]:6 [ print1::$0 ] 11: zp[1]:2 [ print1::idx#2 ] 8.5: zp[1]:3 [ print1::p_x#2 print1::p_x#0 ] 8.33: zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
Uplift Scope [print2] 22: zp[1]:7 [ print2::$0 ] 11: zp[1]:5 [ print2::idx#2 ] 0: zp[2]:10 [ print2::p ]
Uplift Scope [Point]
Uplift Scope [main] 0: zp[2]:8 [ main::p1 ]
Uplift Scope []
Uplifting [print1] best 184 combination zp[1]:6 [ print1::$0 ] reg byte a [ print1::idx#2 ] reg byte y [ print1::p_x#2 print1::p_x#0 ] reg byte x [ print1::p_y#2 print1::p_y#0 ]
Limited combination testing to 100 combinations of 108 possible.
Uplifting [print2] best 170 combination reg byte y [ print2::$0 ] reg byte a [ print2::idx#2 ] zp[2]:10 [ print2::p ]
Uplifting [Point] best 170 combination
Uplifting [main] best 170 combination zp[2]:8 [ main::p1 ]
Uplifting [] best 170 combination
Attempting to uplift remaining variables inzp[1]:6 [ print1::$0 ]
Uplifting [print1] best 170 combination zp[1]:6 [ print1::$0 ]
Allocated (was zp[1]:6) zp[1]:2 [ print1::$0 ]
Allocated (was zp[2]:8) zp[2]:3 [ main::p1 ]
Allocated (was zp[2]:10) zp[2]:5 [ print2::p ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test combining unwind structs with classic structs
// Function calls parameter passing
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
// main
main: {
.const p2_x = 3
.const p2_y = 4
.label p1 = 3
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// [1] print1::p_x#0 = *((byte*)&main::p1) -- vbuyy=_deref_pbuc1
ldy.z p1
// [2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx p1+OFFSET_STRUCT_POINT_Y
// [3] call print1
// Pass classic struct to function taking unwound struct
// [12] phi from main to print1 [phi:main->print1]
print1_from_main:
// [12] phi print1::p_y#2 = print1::p_y#0 [phi:main->print1#0] -- register_copy
// [12] phi print1::p_x#2 = print1::p_x#0 [phi:main->print1#1] -- register_copy
// [12] phi print1::idx#2 = 0 [phi:main->print1#2] -- vbuaa=vbuc1
lda #0
jsr print1
jmp __b1
// main::@1
__b1:
// [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta print2.p-1,y
dey
bne !-
// [5] call print2
// Pass classic struct to function taking classic struct
// [17] phi from main::@1 to print2 [phi:main::@1->print2]
print2_from___b1:
// [17] phi print2::idx#2 = 2 [phi:main::@1->print2#0] -- vbuaa=vbuc1
lda #2
jsr print2
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
__b2_from___b1:
jmp __b2
// main::@2
__b2:
// [7] call print1
// Pass unwound struct to function taking unwound struct
// [12] phi from main::@2 to print1 [phi:main::@2->print1]
print1_from___b2:
// [12] phi print1::p_y#2 = main::p2_y [phi:main::@2->print1#0] -- vbuxx=vbuc1
ldx #p2_y
// [12] phi print1::p_x#2 = main::p2_x [phi:main::@2->print1#1] -- vbuyy=vbuc1
ldy #p2_x
// [12] phi print1::idx#2 = 4 [phi:main::@2->print1#2] -- vbuaa=vbuc1
lda #4
jsr print1
jmp __b3
// main::@3
__b3:
// [8] *((byte*)&print2::p) = main::p2_x -- _deref_pbuc1=vbuc2
lda #p2_x
sta.z print2.p
// [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y -- _deref_pbuc1=vbuc2
lda #p2_y
sta print2.p+OFFSET_STRUCT_POINT_Y
// [10] call print2
// Pass unwound struct to function taking classic struct
// [17] phi from main::@3 to print2 [phi:main::@3->print2]
print2_from___b3:
// [17] phi print2::idx#2 = 6 [phi:main::@3->print2#0] -- vbuaa=vbuc1
lda #6
jsr print2
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print1
// Function taking unwound struct as parameter
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
print1: {
.label __0 = 2
// [13] print1::$0 = print1::idx#2 << 1 -- vbuz1=vbuaa_rol_1
asl
sta.z __0
// [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 -- pbuc1_derefidx_vbuz1=vbuyy
tya
ldy.z __0
sta SCREEN,y
// [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 -- pbuc1_derefidx_vbuz1=vbuxx
ldy.z __0
txa
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
jmp __breturn
// print1::@return
__breturn:
// [16] return
rts
}
// print2
// Function taking classic struct as parameter
// print2(struct Point zp(5) p, byte register(A) idx)
print2: {
.label p = 5
// [18] print2::$0 = print2::idx#2 << 1 -- vbuyy=vbuaa_rol_1
asl
tay
// [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) -- pssc1_derefidx_vbuyy=_deref_pssc2_memcpy_vbuc3
ldx #0
!:
lda.z p,x
sta SCREEN,y
iny
inx
cpx #SIZEOF_STRUCT_POINT
bne !-
jmp __breturn
// print2::@return
__breturn:
// [20] return
rts
}
// File Data
__0: .byte 1, 2
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __b3
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldy.z __0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __b2_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction print1_from_main:
Removing instruction __b1:
Removing instruction print2_from___b1:
Removing instruction __b2:
Removing instruction print1_from___b2:
Removing instruction __b3:
Removing instruction print2_from___b3:
Removing instruction __breturn:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*) 1024
const byte SIZEOF_STRUCT_POINT = 2
void main()
struct Point main::p1 loadstore zp[2]:3
struct Point main::p2
const byte main::p2_x = 3
const byte main::p2_y = 4
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
byte~ print1::$0 zp[1]:2 16.5
byte print1::idx
byte print1::idx#2 reg byte a 11.0
struct Point print1::p
byte print1::p_x
byte print1::p_x#0 reg byte y 2.0
byte print1::p_x#2 reg byte y 6.5
byte print1::p_y
byte print1::p_y#0 reg byte x 4.0
byte print1::p_y#2 reg byte x 4.333333333333333
void print2(struct Point print2::p , byte print2::idx)
byte~ print2::$0 reg byte y 22.0
byte print2::idx
byte print2::idx#2 reg byte a 11.0
struct Point print2::p loadstore zp[2]:5
reg byte a [ print1::idx#2 ]
reg byte y [ print1::p_x#2 print1::p_x#0 ]
reg byte x [ print1::p_y#2 print1::p_y#0 ]
reg byte a [ print2::idx#2 ]
zp[1]:2 [ print1::$0 ]
reg byte y [ print2::$0 ]
zp[2]:3 [ main::p1 ]
zp[2]:5 [ print2::p ]
FINAL ASSEMBLER
Score: 149
// File Comments
// Test combining unwind structs with classic structs
// Function calls parameter passing
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const SIZEOF_STRUCT_POINT = 2
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
// main
main: {
.const p2_x = 3
.const p2_y = 4
.label p1 = 3
// p1 = { 1, 2 }
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta p1-1,y
dey
bne !-
// print1(p1, 0)
// [1] print1::p_x#0 = *((byte*)&main::p1) -- vbuyy=_deref_pbuc1
ldy.z p1
// [2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
ldx p1+OFFSET_STRUCT_POINT_Y
// [3] call print1
// Pass classic struct to function taking unwound struct
// [12] phi from main to print1 [phi:main->print1]
// [12] phi print1::p_y#2 = print1::p_y#0 [phi:main->print1#0] -- register_copy
// [12] phi print1::p_x#2 = print1::p_x#0 [phi:main->print1#1] -- register_copy
// [12] phi print1::idx#2 = 0 [phi:main->print1#2] -- vbuaa=vbuc1
lda #0
jsr print1
// main::@1
// print2(p1, 2)
// [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda p1-1,y
sta print2.p-1,y
dey
bne !-
// [5] call print2
// Pass classic struct to function taking classic struct
// [17] phi from main::@1 to print2 [phi:main::@1->print2]
// [17] phi print2::idx#2 = 2 [phi:main::@1->print2#0] -- vbuaa=vbuc1
lda #2
jsr print2
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
// main::@2
// print1(p2, 4)
// [7] call print1
// Pass unwound struct to function taking unwound struct
// [12] phi from main::@2 to print1 [phi:main::@2->print1]
// [12] phi print1::p_y#2 = main::p2_y [phi:main::@2->print1#0] -- vbuxx=vbuc1
ldx #p2_y
// [12] phi print1::p_x#2 = main::p2_x [phi:main::@2->print1#1] -- vbuyy=vbuc1
ldy #p2_x
// [12] phi print1::idx#2 = 4 [phi:main::@2->print1#2] -- vbuaa=vbuc1
lda #4
jsr print1
// main::@3
// print2(p2, 6)
// [8] *((byte*)&print2::p) = main::p2_x -- _deref_pbuc1=vbuc2
lda #p2_x
sta.z print2.p
// [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y -- _deref_pbuc1=vbuc2
lda #p2_y
sta print2.p+OFFSET_STRUCT_POINT_Y
// [10] call print2
// Pass unwound struct to function taking classic struct
// [17] phi from main::@3 to print2 [phi:main::@3->print2]
// [17] phi print2::idx#2 = 6 [phi:main::@3->print2#0] -- vbuaa=vbuc1
lda #6
jsr print2
// main::@return
// }
// [11] return
rts
}
// print1
// Function taking unwound struct as parameter
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
print1: {
.label __0 = 2
// SCREEN[idx] = p
// [13] print1::$0 = print1::idx#2 << 1 -- vbuz1=vbuaa_rol_1
asl
sta.z __0
// [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 -- pbuc1_derefidx_vbuz1=vbuyy
tya
ldy.z __0
sta SCREEN,y
// [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 -- pbuc1_derefidx_vbuz1=vbuxx
txa
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
// print1::@return
// }
// [16] return
rts
}
// print2
// Function taking classic struct as parameter
// print2(struct Point zp(5) p, byte register(A) idx)
print2: {
.label p = 5
// SCREEN[idx] = p
// [18] print2::$0 = print2::idx#2 << 1 -- vbuyy=vbuaa_rol_1
asl
tay
// [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) -- pssc1_derefidx_vbuyy=_deref_pssc2_memcpy_vbuc3
ldx #0
!:
lda.z p,x
sta SCREEN,y
iny
inx
cpx #SIZEOF_STRUCT_POINT
bne !-
// print2::@return
// }
// [20] return
rts
}
// File Data
__0: .byte 1, 2

View File

@ -0,0 +1,34 @@
const struct Point $0 = { x: 1, y: 2 }
const byte OFFSET_STRUCT_POINT_Y = 1
const nomodify struct Point* SCREEN = (struct Point*) 1024
const byte SIZEOF_STRUCT_POINT = 2
void main()
struct Point main::p1 loadstore zp[2]:3
struct Point main::p2
const byte main::p2_x = 3
const byte main::p2_y = 4
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
byte~ print1::$0 zp[1]:2 16.5
byte print1::idx
byte print1::idx#2 reg byte a 11.0
struct Point print1::p
byte print1::p_x
byte print1::p_x#0 reg byte y 2.0
byte print1::p_x#2 reg byte y 6.5
byte print1::p_y
byte print1::p_y#0 reg byte x 4.0
byte print1::p_y#2 reg byte x 4.333333333333333
void print2(struct Point print2::p , byte print2::idx)
byte~ print2::$0 reg byte y 22.0
byte print2::idx
byte print2::idx#2 reg byte a 11.0
struct Point print2::p loadstore zp[2]:5
reg byte a [ print1::idx#2 ]
reg byte y [ print1::p_x#2 print1::p_x#0 ]
reg byte x [ print1::p_y#2 print1::p_y#0 ]
reg byte a [ print2::idx#2 ]
zp[1]:2 [ print1::$0 ]
reg byte y [ print2::$0 ]
zp[2]:3 [ main::p1 ]
zp[2]:5 [ print2::p ]