From 3e5529c0f1b6e55e2a569bf6a4f0923bc9978c73 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 2 Feb 2020 22:24:25 +0100 Subject: [PATCH] Added 2 complex struct copy tests. --- .../passes/unwinding/RValueUnwinding.java | 2 +- .../dk/camelot64/kickc/test/TestPrograms.java | 10 + src/test/kc/struct-40.kc | 37 + src/test/kc/struct-41.kc | 42 + src/test/ref/struct-40.asm | 48 + src/test/ref/struct-40.cfg | 32 + src/test/ref/struct-40.log | 807 +++++++++++ src/test/ref/struct-40.sym | 28 + src/test/ref/struct-41.asm | 88 ++ src/test/ref/struct-41.cfg | 45 + src/test/ref/struct-41.log | 1194 +++++++++++++++++ src/test/ref/struct-41.sym | 35 + 12 files changed, 2367 insertions(+), 1 deletion(-) create mode 100644 src/test/kc/struct-40.kc create mode 100644 src/test/kc/struct-41.kc create mode 100644 src/test/ref/struct-40.asm create mode 100644 src/test/ref/struct-40.cfg create mode 100644 src/test/ref/struct-40.log create mode 100644 src/test/ref/struct-40.sym create mode 100644 src/test/ref/struct-41.asm create mode 100644 src/test/ref/struct-41.cfg create mode 100644 src/test/ref/struct-41.log create mode 100644 src/test/ref/struct-41.sym diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwinding.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwinding.java index 62dc51c7e..a7d2b5d1d 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwinding.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/RValueUnwinding.java @@ -46,7 +46,7 @@ public interface RValueUnwinding { LValue getBulkLValue(ProgramScope scope); /** - * Get Rvalue to use when for copying/setting a bulk value at once. Typically returns a memset/memcpy commands. + * Get Rvalue to use when for copying/setting a bulk value at once. Typically returns a memset/memcpy command. * @param scope The program scope * @return The value to use as RValue */ diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index f24b14bd6..9f2db66a5 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1153,6 +1153,16 @@ public class TestPrograms { assertError("struct-err-0", "Unknown struct type"); } + @Test + public void testStruct41() throws IOException, URISyntaxException { + compileAndCompare("struct-41"); + } + + @Test + public void testStruct40() throws IOException, URISyntaxException { + compileAndCompare("struct-40"); + } + @Test public void testStruct39() throws IOException, URISyntaxException { compileAndCompare("struct-39"); diff --git a/src/test/kc/struct-40.kc b/src/test/kc/struct-40.kc new file mode 100644 index 000000000..8cb64a71a --- /dev/null +++ b/src/test/kc/struct-40.kc @@ -0,0 +1,37 @@ +// Minimal struct with Unwound behavior - struct containing struct copying + +struct Point { + char x; + char y; +}; + +struct Vector { + struct Point p; + struct Point q; +}; + +const char* SCREEN = 0x0400; + +void main() { + char idx = 0; + __ssa struct Vector v1 = { {2, 3}, { 4, 5 } }; + __ssa struct Vector v2 = v1; + __ssa struct Vector v3 = { v1.p, {6, 7} }; + __ssa struct Vector v4 = { {v1.p.x, v1.p.y }, {8, 9} }; + SCREEN[idx++] = v1.p.x; + SCREEN[idx++] = v1.p.y; + SCREEN[idx++] = v1.q.x; + SCREEN[idx++] = v1.q.y; + SCREEN[idx++] = v2.p.x; + SCREEN[idx++] = v2.p.y; + SCREEN[idx++] = v2.q.x; + SCREEN[idx++] = v2.q.y; + SCREEN[idx++] = v3.p.x; + SCREEN[idx++] = v3.p.y; + SCREEN[idx++] = v3.q.x; + SCREEN[idx++] = v3.q.y; + SCREEN[idx++] = v4.p.x; + SCREEN[idx++] = v4.p.y; + SCREEN[idx++] = v4.q.x; + SCREEN[idx++] = v4.q.y; +} \ No newline at end of file diff --git a/src/test/kc/struct-41.kc b/src/test/kc/struct-41.kc new file mode 100644 index 000000000..4551d302c --- /dev/null +++ b/src/test/kc/struct-41.kc @@ -0,0 +1,42 @@ +// Minimal struct with Unwound behavior - struct containing struct copying + +struct Point { + char x; + char y; +}; + +struct Vector { + struct Point p; + struct Point q; +}; + +const char* SCREEN = 0x0400; + +void main() { + char idx = 0; + __ssa struct Vector v1 = { {2, 3}, { 4, 5 } }; + __ma struct Vector v2 = v1; + __ma struct Vector v3 = { v2.p, {6, 7} }; + __ma struct Vector v4 = v3; + __ssa struct Vector v5 = { {v4.p.x, v4.p.y }, {8, 9} }; + SCREEN[idx++] = v1.p.x; + SCREEN[idx++] = v1.p.y; + SCREEN[idx++] = v1.q.x; + SCREEN[idx++] = v1.q.y; + SCREEN[idx++] = v2.p.x; + SCREEN[idx++] = v2.p.y; + SCREEN[idx++] = v2.q.x; + SCREEN[idx++] = v2.q.y; + SCREEN[idx++] = v3.p.x; + SCREEN[idx++] = v3.p.y; + SCREEN[idx++] = v3.q.x; + SCREEN[idx++] = v3.q.y; + SCREEN[idx++] = v4.p.x; + SCREEN[idx++] = v4.p.y; + SCREEN[idx++] = v4.q.x; + SCREEN[idx++] = v4.q.y; + SCREEN[idx++] = v5.p.x; + SCREEN[idx++] = v5.p.y; + SCREEN[idx++] = v5.q.x; + SCREEN[idx++] = v5.q.y; +} \ No newline at end of file diff --git a/src/test/ref/struct-40.asm b/src/test/ref/struct-40.asm new file mode 100644 index 000000000..286465ba6 --- /dev/null +++ b/src/test/ref/struct-40.asm @@ -0,0 +1,48 @@ +// Minimal struct with Unwound behavior - struct containing struct copying +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v3_q_x = 6 + .const v3_q_y = 7 + .const v4_q_x = 8 + .const v4_q_y = 9 + lda #v1_p_x + sta SCREEN + lda #v1_p_y + sta SCREEN+1 + lda #v1_q_x + sta SCREEN+2 + lda #v1_q_y + sta SCREEN+3 + lda #v1_p_x + sta SCREEN+4 + lda #v1_p_y + sta SCREEN+5 + lda #v1_q_x + sta SCREEN+6 + lda #v1_q_y + sta SCREEN+7 + lda #v1_p_x + sta SCREEN+8 + lda #v1_p_y + sta SCREEN+9 + lda #v3_q_x + sta SCREEN+$a + lda #v3_q_y + sta SCREEN+$b + lda #v1_p_x + sta SCREEN+$c + lda #v1_p_y + sta SCREEN+$d + lda #v4_q_x + sta SCREEN+$e + lda #v4_q_y + sta SCREEN+$f + rts +} diff --git a/src/test/ref/struct-40.cfg b/src/test/ref/struct-40.cfg new file mode 100644 index 000000000..6738ad223 --- /dev/null +++ b/src/test/ref/struct-40.cfg @@ -0,0 +1,32 @@ +@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] *((const byte*) SCREEN) ← (const byte) main::v1_p_x + [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y + [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x + [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y + [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x + [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y + [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x + [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y + [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x + [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y + [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x + [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y + [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x + [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y + [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x + [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y + to:main::@return +main::@return: scope:[main] from main + [20] return + to:@return diff --git a/src/test/ref/struct-40.log b/src/test/ref/struct-40.log new file mode 100644 index 000000000..f210a119f --- /dev/null +++ b/src/test/ref/struct-40.log @@ -0,0 +1,807 @@ +Created struct value member variable (struct Point) main::v1_p +Created struct value member variable (struct Point) main::v1_q +Converted struct value to member variables (struct Vector) main::v1 +Created struct value member variable (struct Point) main::v2_p +Created struct value member variable (struct Point) main::v2_q +Converted struct value to member variables (struct Vector) main::v2 +Created struct value member variable (struct Point) main::v3_p +Created struct value member variable (struct Point) main::v3_q +Converted struct value to member variables (struct Vector) main::v3 +Created struct value member variable (struct Point) main::v4_p +Created struct value member variable (struct Point) main::v4_q +Converted struct value to member variables (struct Vector) main::v4 +Created struct value member variable (byte) main::v1_p_x +Created struct value member variable (byte) main::v1_p_y +Converted struct value to member variables (struct Point) main::v1_p +Created struct value member variable (byte) main::v1_q_x +Created struct value member variable (byte) main::v1_q_y +Converted struct value to member variables (struct Point) main::v1_q +Created struct value member variable (byte) main::v2_p_x +Created struct value member variable (byte) main::v2_p_y +Converted struct value to member variables (struct Point) main::v2_p +Created struct value member variable (byte) main::v2_q_x +Created struct value member variable (byte) main::v2_q_y +Converted struct value to member variables (struct Point) main::v2_q +Created struct value member variable (byte) main::v3_p_x +Created struct value member variable (byte) main::v3_p_y +Converted struct value to member variables (struct Point) main::v3_p +Created struct value member variable (byte) main::v3_q_x +Created struct value member variable (byte) main::v3_q_y +Converted struct value to member variables (struct Point) main::v3_q +Created struct value member variable (byte) main::v4_p_x +Created struct value member variable (byte) main::v4_p_y +Converted struct value to member variables (struct Point) main::v4_p +Created struct value member variable (byte) main::v4_q_x +Created struct value member variable (byte) main::v4_q_y +Converted struct value to member variables (struct Point) main::v4_q +Adding struct value member variable copy (struct Point) main::v1_p ← { x: (byte) 2, y: (byte) 3 } +Adding struct value member variable copy (struct Point) main::v1_q ← { x: (byte) 4, y: (byte) 5 } +Adding struct value member variable copy (struct Point) main::v2_p ← (struct Point) main::v1_p +Adding struct value member variable copy (struct Point) main::v2_q ← (struct Point) main::v1_q +Adding struct value member variable copy (struct Point) main::v3_p ← (struct Vector) main::v1.p +Adding struct value member variable copy (struct Point) main::v3_q ← { x: (byte) 6, y: (byte) 7 } +Adding struct value member variable copy (struct Point) main::v4_p ← (struct Point){ (struct Vector) main::v1.p.x, (struct Vector) main::v1.p.y } +Adding struct value member variable copy (struct Point) main::v4_q ← { x: (byte) 8, y: (byte) 9 } +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.q with member unwinding reference (struct Point) main::v1_q +Replacing struct member reference (struct Vector) main::v1.q with member unwinding reference (struct Point) main::v1_q +Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference (struct Point) main::v2_p +Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference (struct Point) main::v2_p +Replacing struct member reference (struct Vector) main::v2.q with member unwinding reference (struct Point) main::v2_q +Replacing struct member reference (struct Vector) main::v2.q with member unwinding reference (struct Point) main::v2_q +Replacing struct member reference (struct Vector) main::v3.p with member unwinding reference (struct Point) main::v3_p +Replacing struct member reference (struct Vector) main::v3.p with member unwinding reference (struct Point) main::v3_p +Replacing struct member reference (struct Vector) main::v3.q with member unwinding reference (struct Point) main::v3_q +Replacing struct member reference (struct Vector) main::v3.q with member unwinding reference (struct Point) main::v3_q +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference (struct Point) main::v4_p +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference (struct Point) main::v4_p +Replacing struct member reference (struct Vector) main::v4.q with member unwinding reference (struct Point) main::v4_q +Replacing struct member reference (struct Vector) main::v4.q with member unwinding reference (struct Point) main::v4_q +Adding struct value member variable copy (byte) main::v1_p_x ← (byte) 2 +Adding struct value member variable copy (byte) main::v1_p_y ← (byte) 3 +Adding struct value member variable copy (byte) main::v1_q_x ← (byte) 4 +Adding struct value member variable copy (byte) main::v1_q_y ← (byte) 5 +Adding struct value member variable copy (byte) main::v2_p_x ← (byte) main::v1_p_x +Adding struct value member variable copy (byte) main::v2_p_y ← (byte) main::v1_p_y +Adding struct value member variable copy (byte) main::v2_q_x ← (byte) main::v1_q_x +Adding struct value member variable copy (byte) main::v2_q_y ← (byte) main::v1_q_y +Adding struct value member variable copy (byte) main::v3_p_x ← (byte) main::v1_p_x +Adding struct value member variable copy (byte) main::v3_p_y ← (byte) main::v1_p_y +Adding struct value member variable copy (byte) main::v3_q_x ← (byte) 6 +Adding struct value member variable copy (byte) main::v3_q_y ← (byte) 7 +Adding struct value member variable copy (byte) main::v4_p_x ← (struct Point) main::v1_p.x +Adding struct value member variable copy (byte) main::v4_p_y ← (struct Point) main::v1_p.y +Adding struct value member variable copy (byte) main::v4_q_x ← (byte) 8 +Adding struct value member variable copy (byte) main::v4_q_y ← (byte) 9 +Replacing struct member reference (struct Point) main::v1_p.x with member unwinding reference (byte) main::v1_p_x +Replacing struct member reference (struct Point) main::v1_p.y with member unwinding reference (byte) main::v1_p_y +Replacing struct member reference (struct Point) main::v1_p.x with member unwinding reference (byte) main::v1_p_x +Replacing struct member reference (struct Point) main::v1_p.y with member unwinding reference (byte) main::v1_p_y +Replacing struct member reference (struct Point) main::v1_q.x with member unwinding reference (byte) main::v1_q_x +Replacing struct member reference (struct Point) main::v1_q.y with member unwinding reference (byte) main::v1_q_y +Replacing struct member reference (struct Point) main::v2_p.x with member unwinding reference (byte) main::v2_p_x +Replacing struct member reference (struct Point) main::v2_p.y with member unwinding reference (byte) main::v2_p_y +Replacing struct member reference (struct Point) main::v2_q.x with member unwinding reference (byte) main::v2_q_x +Replacing struct member reference (struct Point) main::v2_q.y with member unwinding reference (byte) main::v2_q_y +Replacing struct member reference (struct Point) main::v3_p.x with member unwinding reference (byte) main::v3_p_x +Replacing struct member reference (struct Point) main::v3_p.y with member unwinding reference (byte) main::v3_p_y +Replacing struct member reference (struct Point) main::v3_q.x with member unwinding reference (byte) main::v3_q_x +Replacing struct member reference (struct Point) main::v3_q.y with member unwinding reference (byte) main::v3_q_y +Replacing struct member reference (struct Point) main::v4_p.x with member unwinding reference (byte) main::v4_p_x +Replacing struct member reference (struct Point) main::v4_p.y with member unwinding reference (byte) main::v4_p_y +Replacing struct member reference (struct Point) main::v4_q.x with member unwinding reference (byte) main::v4_q_x +Replacing struct member reference (struct Point) main::v4_q.y with member unwinding reference (byte) main::v4_q_y +Identified constant variable (byte) main::v1_p_x +Identified constant variable (byte) main::v1_p_y +Identified constant variable (byte) main::v1_q_x +Identified constant variable (byte) main::v1_q_y +Identified constant variable (byte) main::v3_q_x +Identified constant variable (byte) main::v3_q_y +Identified constant variable (byte) main::v4_q_x +Identified constant variable (byte) main::v4_q_y + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::idx#0 ← (byte) 0 + (byte) main::v2_p_x#0 ← (const byte) main::v1_p_x + (byte) main::v2_p_y#0 ← (const byte) main::v1_p_y + (byte) main::v2_q_x#0 ← (const byte) main::v1_q_x + (byte) main::v2_q_y#0 ← (const byte) main::v1_q_y + (byte) main::v3_p_x#0 ← (const byte) main::v1_p_x + (byte) main::v3_p_y#0 ← (const byte) main::v1_p_y + (byte) main::v4_p_x#0 ← (const byte) main::v1_p_x + (byte) main::v4_p_y#0 ← (const byte) main::v1_p_y + *((const byte*) SCREEN + (byte) main::idx#0) ← (const byte) main::v1_p_x + (byte) main::idx#1 ← ++ (byte) main::idx#0 + *((const byte*) SCREEN + (byte) main::idx#1) ← (const byte) main::v1_p_y + (byte) main::idx#2 ← ++ (byte) main::idx#1 + *((const byte*) SCREEN + (byte) main::idx#2) ← (const byte) main::v1_q_x + (byte) main::idx#3 ← ++ (byte) main::idx#2 + *((const byte*) SCREEN + (byte) main::idx#3) ← (const byte) main::v1_q_y + (byte) main::idx#4 ← ++ (byte) main::idx#3 + *((const byte*) SCREEN + (byte) main::idx#4) ← (byte) main::v2_p_x#0 + (byte) main::idx#5 ← ++ (byte) main::idx#4 + *((const byte*) SCREEN + (byte) main::idx#5) ← (byte) main::v2_p_y#0 + (byte) main::idx#6 ← ++ (byte) main::idx#5 + *((const byte*) SCREEN + (byte) main::idx#6) ← (byte) main::v2_q_x#0 + (byte) main::idx#7 ← ++ (byte) main::idx#6 + *((const byte*) SCREEN + (byte) main::idx#7) ← (byte) main::v2_q_y#0 + (byte) main::idx#8 ← ++ (byte) main::idx#7 + *((const byte*) SCREEN + (byte) main::idx#8) ← (byte) main::v3_p_x#0 + (byte) main::idx#9 ← ++ (byte) main::idx#8 + *((const byte*) SCREEN + (byte) main::idx#9) ← (byte) main::v3_p_y#0 + (byte) main::idx#10 ← ++ (byte) main::idx#9 + *((const byte*) SCREEN + (byte) main::idx#10) ← (const byte) main::v3_q_x + (byte) main::idx#11 ← ++ (byte) main::idx#10 + *((const byte*) SCREEN + (byte) main::idx#11) ← (const byte) main::v3_q_y + (byte) main::idx#12 ← ++ (byte) main::idx#11 + *((const byte*) SCREEN + (byte) main::idx#12) ← (byte) main::v4_p_x#0 + (byte) main::idx#13 ← ++ (byte) main::idx#12 + *((const byte*) SCREEN + (byte) main::idx#13) ← (byte) main::v4_p_y#0 + (byte) main::idx#14 ← ++ (byte) main::idx#13 + *((const byte*) SCREEN + (byte) main::idx#14) ← (const byte) main::v4_q_x + (byte) main::idx#15 ← ++ (byte) main::idx#14 + *((const byte*) SCREEN + (byte) main::idx#15) ← (const byte) main::v4_q_y + (byte) main::idx#16 ← ++ (byte) main::idx#15 + to:main::@return +main::@return: scope:[main] from main + 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 +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*)(number) $400 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(label) main::@return +(byte) main::idx +(byte) main::idx#0 +(byte) main::idx#1 +(byte) main::idx#10 +(byte) main::idx#11 +(byte) main::idx#12 +(byte) main::idx#13 +(byte) main::idx#14 +(byte) main::idx#15 +(byte) main::idx#16 +(byte) main::idx#2 +(byte) main::idx#3 +(byte) main::idx#4 +(byte) main::idx#5 +(byte) main::idx#6 +(byte) main::idx#7 +(byte) main::idx#8 +(byte) main::idx#9 +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(byte) main::v2_p_x +(byte) main::v2_p_x#0 +(byte) main::v2_p_y +(byte) main::v2_p_y#0 +(byte) main::v2_q_x +(byte) main::v2_q_x#0 +(byte) main::v2_q_y +(byte) main::v2_q_y#0 +(byte) main::v3_p_x +(byte) main::v3_p_x#0 +(byte) main::v3_p_y +(byte) main::v3_p_y#0 +(const byte) main::v3_q_x = (byte) 6 +(const byte) main::v3_q_y = (byte) 7 +(byte) main::v4_p_x +(byte) main::v4_p_x#0 +(byte) main::v4_p_y +(byte) main::v4_p_y#0 +(const byte) main::v4_q_x = (byte) 8 +(const byte) main::v4_q_y = (byte) 9 + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Constant (const byte) main::idx#0 = 0 +Constant (const byte) main::v2_p_x#0 = main::v1_p_x +Constant (const byte) main::v2_p_y#0 = main::v1_p_y +Constant (const byte) main::v2_q_x#0 = main::v1_q_x +Constant (const byte) main::v2_q_y#0 = main::v1_q_y +Constant (const byte) main::v3_p_x#0 = main::v1_p_x +Constant (const byte) main::v3_p_y#0 = main::v1_p_y +Constant (const byte) main::v4_p_x#0 = main::v1_p_x +Constant (const byte) main::v4_p_y#0 = main::v1_p_y +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [9] *((const byte*) SCREEN + (const byte) main::idx#0) ← (const byte) main::v1_p_x +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (byte) main::idx#16 and assignment [31] (byte) main::idx#16 ← ++ (byte) main::idx#15 +Successful SSA optimization PassNEliminateUnusedVars +Constant right-side identified [1] (byte) main::idx#1 ← ++ (const byte) main::idx#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#1 = ++main::idx#0 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [2] (byte) main::idx#2 ← ++ (const byte) main::idx#1 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#2 = ++main::idx#1 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [3] (byte) main::idx#3 ← ++ (const byte) main::idx#2 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#3 = ++main::idx#2 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [4] (byte) main::idx#4 ← ++ (const byte) main::idx#3 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#4 = ++main::idx#3 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [5] (byte) main::idx#5 ← ++ (const byte) main::idx#4 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#5 = ++main::idx#4 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [6] (byte) main::idx#6 ← ++ (const byte) main::idx#5 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#6 = ++main::idx#5 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [7] (byte) main::idx#7 ← ++ (const byte) main::idx#6 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#7 = ++main::idx#6 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [8] (byte) main::idx#8 ← ++ (const byte) main::idx#7 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#8 = ++main::idx#7 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [9] (byte) main::idx#9 ← ++ (const byte) main::idx#8 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#9 = ++main::idx#8 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [10] (byte) main::idx#10 ← ++ (const byte) main::idx#9 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#10 = ++main::idx#9 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [11] (byte) main::idx#11 ← ++ (const byte) main::idx#10 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#11 = ++main::idx#10 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [12] (byte) main::idx#12 ← ++ (const byte) main::idx#11 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#12 = ++main::idx#11 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [13] (byte) main::idx#13 ← ++ (const byte) main::idx#12 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#13 = ++main::idx#12 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [14] (byte) main::idx#14 ← ++ (const byte) main::idx#13 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#14 = ++main::idx#13 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [15] (byte) main::idx#15 ← ++ (const byte) main::idx#14 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#15 = ++main::idx#14 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings (const byte) main::idx#0 +Inlining constant with different constant siblings (const byte) main::idx#1 +Inlining constant with different constant siblings (const byte) main::idx#2 +Inlining constant with different constant siblings (const byte) main::idx#3 +Inlining constant with different constant siblings (const byte) main::idx#4 +Inlining constant with different constant siblings (const byte) main::idx#5 +Inlining constant with different constant siblings (const byte) main::idx#6 +Inlining constant with different constant siblings (const byte) main::idx#7 +Inlining constant with different constant siblings (const byte) main::idx#8 +Inlining constant with different constant siblings (const byte) main::idx#9 +Inlining constant with different constant siblings (const byte) main::idx#10 +Inlining constant with different constant siblings (const byte) main::idx#11 +Inlining constant with different constant siblings (const byte) main::idx#12 +Inlining constant with different constant siblings (const byte) main::idx#13 +Inlining constant with different constant siblings (const byte) main::idx#14 +Inlining constant with different constant siblings (const byte) main::idx#15 +Constant inlined main::idx#12 = ++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#13 = ++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#14 = ++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#15 = ++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::v2_q_y#0 = (const byte) main::v1_q_y +Constant inlined main::idx#0 = (byte) 0 +Constant inlined main::v4_p_y#0 = (const byte) main::v1_p_y +Constant inlined main::idx#1 = ++(byte) 0 +Constant inlined main::v2_q_x#0 = (const byte) main::v1_q_x +Constant inlined main::v4_p_x#0 = (const byte) main::v1_p_x +Constant inlined main::idx#2 = ++++(byte) 0 +Constant inlined main::idx#3 = ++++++(byte) 0 +Constant inlined main::idx#4 = ++++++++(byte) 0 +Constant inlined main::idx#5 = ++++++++++(byte) 0 +Constant inlined main::idx#6 = ++++++++++++(byte) 0 +Constant inlined main::v3_p_y#0 = (const byte) main::v1_p_y +Constant inlined main::idx#7 = ++++++++++++++(byte) 0 +Constant inlined main::idx#8 = ++++++++++++++++(byte) 0 +Constant inlined main::idx#9 = ++++++++++++++++++(byte) 0 +Constant inlined main::idx#10 = ++++++++++++++++++++(byte) 0 +Constant inlined main::v3_p_x#0 = (const byte) main::v1_p_x +Constant inlined main::idx#11 = ++++++++++++++++++++++(byte) 0 +Constant inlined main::v2_p_x#0 = (const byte) main::v1_p_x +Constant inlined main::v2_p_y#0 = (const byte) main::v1_p_y +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+++0) +Consolidated array index constant in *(SCREEN+++++0) +Consolidated array index constant in *(SCREEN+++++++0) +Consolidated array index constant in *(SCREEN+++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++0) +Successful SSA optimization Pass2ConstantAdditionElimination +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$d +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$d +Simplifying constant integer increment ++$e +Successful SSA optimization Pass2ConstantSimplification +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 +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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] *((const byte*) SCREEN) ← (const byte) main::v1_p_x + [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y + [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x + [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y + [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x + [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y + [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x + [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y + [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x + [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y + [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x + [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y + [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x + [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y + [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x + [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y + to:main::@return +main::@return: scope:[main] from main + [20] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) Point::x +(byte) Point::y +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(byte) main::idx +(byte) main::v2_p_x +(byte) main::v2_p_y +(byte) main::v2_q_x +(byte) main::v2_q_y +(byte) main::v3_p_x +(byte) main::v3_p_y +(byte) main::v4_p_x +(byte) main::v4_p_y + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v3_q_x = 6 + .const v3_q_y = 7 + .const v4_q_x = 8 + .const v4_q_y = 9 + // [4] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+4 + // [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+5 + // [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+6 + // [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+7 + // [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+8 + // [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+9 + // [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x -- _deref_pbuc1=vbuc2 + lda #v3_q_x + sta SCREEN+$a + // [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y -- _deref_pbuc1=vbuc2 + lda #v3_q_y + sta SCREEN+$b + // [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+$c + // [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+$d + // [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x -- _deref_pbuc1=vbuc2 + lda #v4_q_x + sta SCREEN+$e + // [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y -- _deref_pbuc1=vbuc2 + lda #v4_q_y + sta SCREEN+$f + jmp __breturn + // main::@return + __breturn: + // [20] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((const byte*) SCREEN) ← (const byte) main::v1_p_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [Point] +Uplift Scope [Vector] +Uplift Scope [main] +Uplift Scope [] + +Uplifting [Point] best 117 combination +Uplifting [Vector] best 117 combination +Uplifting [main] best 117 combination +Uplifting [] best 117 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v3_q_x = 6 + .const v3_q_y = 7 + .const v4_q_x = 8 + .const v4_q_y = 9 + // [4] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+4 + // [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+5 + // [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+6 + // [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+7 + // [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+8 + // [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+9 + // [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x -- _deref_pbuc1=vbuc2 + lda #v3_q_x + sta SCREEN+$a + // [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y -- _deref_pbuc1=vbuc2 + lda #v3_q_y + sta SCREEN+$b + // [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+$c + // [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+$d + // [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x -- _deref_pbuc1=vbuc2 + lda #v4_q_x + sta SCREEN+$e + // [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y -- _deref_pbuc1=vbuc2 + lda #v4_q_y + sta SCREEN+$f + jmp __breturn + // main::@return + __breturn: + // [20] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*) 1024 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(label) main::@return +(byte) main::idx +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(byte) main::v2_p_x +(byte) main::v2_p_y +(byte) main::v2_q_x +(byte) main::v2_q_y +(byte) main::v3_p_x +(byte) main::v3_p_y +(const byte) main::v3_q_x = (byte) 6 +(const byte) main::v3_q_y = (byte) 7 +(byte) main::v4_p_x +(byte) main::v4_p_y +(const byte) main::v4_q_x = (byte) 8 +(const byte) main::v4_q_y = (byte) 9 + + + +FINAL ASSEMBLER +Score: 102 + + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // 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 + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v3_q_x = 6 + .const v3_q_y = 7 + .const v4_q_x = 8 + .const v4_q_y = 9 + // SCREEN[idx++] = v1.p.x + // [4] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // SCREEN[idx++] = v1.p.y + // [5] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // SCREEN[idx++] = v1.q.x + // [6] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // SCREEN[idx++] = v1.q.y + // [7] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // SCREEN[idx++] = v2.p.x + // [8] *((const byte*) SCREEN+(byte) 4) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+4 + // SCREEN[idx++] = v2.p.y + // [9] *((const byte*) SCREEN+(byte) 5) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+5 + // SCREEN[idx++] = v2.q.x + // [10] *((const byte*) SCREEN+(byte) 6) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+6 + // SCREEN[idx++] = v2.q.y + // [11] *((const byte*) SCREEN+(byte) 7) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+7 + // SCREEN[idx++] = v3.p.x + // [12] *((const byte*) SCREEN+(byte) 8) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+8 + // SCREEN[idx++] = v3.p.y + // [13] *((const byte*) SCREEN+(byte) 9) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+9 + // SCREEN[idx++] = v3.q.x + // [14] *((const byte*) SCREEN+(byte) $a) ← (const byte) main::v3_q_x -- _deref_pbuc1=vbuc2 + lda #v3_q_x + sta SCREEN+$a + // SCREEN[idx++] = v3.q.y + // [15] *((const byte*) SCREEN+(byte) $b) ← (const byte) main::v3_q_y -- _deref_pbuc1=vbuc2 + lda #v3_q_y + sta SCREEN+$b + // SCREEN[idx++] = v4.p.x + // [16] *((const byte*) SCREEN+(byte) $c) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN+$c + // SCREEN[idx++] = v4.p.y + // [17] *((const byte*) SCREEN+(byte) $d) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+$d + // SCREEN[idx++] = v4.q.x + // [18] *((const byte*) SCREEN+(byte) $e) ← (const byte) main::v4_q_x -- _deref_pbuc1=vbuc2 + lda #v4_q_x + sta SCREEN+$e + // SCREEN[idx++] = v4.q.y + // [19] *((const byte*) SCREEN+(byte) $f) ← (const byte) main::v4_q_y -- _deref_pbuc1=vbuc2 + lda #v4_q_y + sta SCREEN+$f + // main::@return + // } + // [20] return + rts +} + // File Data + diff --git a/src/test/ref/struct-40.sym b/src/test/ref/struct-40.sym new file mode 100644 index 000000000..c73a0d6b3 --- /dev/null +++ b/src/test/ref/struct-40.sym @@ -0,0 +1,28 @@ +(label) @1 +(label) @begin +(label) @end +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*) 1024 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(label) main::@return +(byte) main::idx +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(byte) main::v2_p_x +(byte) main::v2_p_y +(byte) main::v2_q_x +(byte) main::v2_q_y +(byte) main::v3_p_x +(byte) main::v3_p_y +(const byte) main::v3_q_x = (byte) 6 +(const byte) main::v3_q_y = (byte) 7 +(byte) main::v4_p_x +(byte) main::v4_p_y +(const byte) main::v4_q_x = (byte) 8 +(const byte) main::v4_q_y = (byte) 9 + diff --git a/src/test/ref/struct-41.asm b/src/test/ref/struct-41.asm new file mode 100644 index 000000000..b69375c28 --- /dev/null +++ b/src/test/ref/struct-41.asm @@ -0,0 +1,88 @@ +// Minimal struct with Unwound behavior - struct containing struct copying +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 + .const OFFSET_STRUCT_VECTOR_Q = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v5_q_x = 8 + .const v5_q_y = 9 + .label v2 = 2 + .label v3 = 6 + .label v4 = $a + lda #v1_p_x + sta.z v2 + lda #v1_p_y + sta v2+OFFSET_STRUCT_POINT_Y + lda #v1_q_x + sta v2+OFFSET_STRUCT_VECTOR_Q + lda #v1_q_y + sta v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + ldy #SIZEOF_STRUCT_POINT + !: + lda v2-1,y + sta v3-1,y + dey + bne !- + ldy #SIZEOF_STRUCT_POINT + !: + lda __0-1,y + sta v3+OFFSET_STRUCT_VECTOR_Q-1,y + dey + bne !- + ldy #SIZEOF_STRUCT_VECTOR + !: + lda v3-1,y + sta v4-1,y + dey + bne !- + ldy.z v4 + ldx v4+OFFSET_STRUCT_POINT_Y + lda #v1_p_x + sta SCREEN + lda #v1_p_y + sta SCREEN+1 + lda #v1_q_x + sta SCREEN+2 + lda #v1_q_y + sta SCREEN+3 + lda.z v2 + sta SCREEN+4 + lda v2+OFFSET_STRUCT_POINT_Y + sta SCREEN+5 + lda v2+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+6 + lda v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+7 + lda.z v3 + sta SCREEN+8 + lda v3+OFFSET_STRUCT_POINT_Y + sta SCREEN+9 + lda v3+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$a + lda v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$b + tya + sta SCREEN+$c + txa + sta SCREEN+$d + lda v4+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$e + lda v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$f + sty SCREEN+$10 + stx SCREEN+$11 + lda #v5_q_x + sta SCREEN+$12 + lda #v5_q_y + sta SCREEN+$13 + rts +} + __0: .byte 6, 7 diff --git a/src/test/ref/struct-41.cfg b/src/test/ref/struct-41.cfg new file mode 100644 index 000000000..6aeeadcc9 --- /dev/null +++ b/src/test/ref/struct-41.cfg @@ -0,0 +1,45 @@ +@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] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x + [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y + [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x + [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y + [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) + [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) + [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + [11] (byte) main::v5_p_x#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4) + [12] (byte) main::v5_p_y#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) + [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x + [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y + [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x + [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y + [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) + [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) + [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) + [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) + [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) + [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) + [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) + [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) + [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) + [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [29] *((const byte*) SCREEN+(byte) $10) ← (byte) main::v5_p_x#0 + [30] *((const byte*) SCREEN+(byte) $11) ← (byte) main::v5_p_y#0 + [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x + [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y + to:main::@return +main::@return: scope:[main] from main + [33] return + to:@return diff --git a/src/test/ref/struct-41.log b/src/test/ref/struct-41.log new file mode 100644 index 000000000..042fc5169 --- /dev/null +++ b/src/test/ref/struct-41.log @@ -0,0 +1,1194 @@ +Created struct value member variable (struct Point) main::v1_p +Created struct value member variable (struct Point) main::v1_q +Converted struct value to member variables (struct Vector) main::v1 +Created struct value member variable (struct Point) main::v5_p +Created struct value member variable (struct Point) main::v5_q +Converted struct value to member variables (struct Vector) main::v5 +Created struct value member variable (byte) main::v1_p_x +Created struct value member variable (byte) main::v1_p_y +Converted struct value to member variables (struct Point) main::v1_p +Created struct value member variable (byte) main::v1_q_x +Created struct value member variable (byte) main::v1_q_y +Converted struct value to member variables (struct Point) main::v1_q +Created struct value member variable (byte) main::v5_p_x +Created struct value member variable (byte) main::v5_p_y +Converted struct value to member variables (struct Point) main::v5_p +Created struct value member variable (byte) main::v5_q_x +Created struct value member variable (byte) main::v5_q_y +Converted struct value to member variables (struct Point) main::v5_q +Adding struct value member variable copy (struct Point) main::v1_p ← { x: (byte) 2, y: (byte) 3 } +Adding struct value member variable copy (struct Point) main::v1_q ← { x: (byte) 4, y: (byte) 5 } +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P) ← (struct Point) main::v1_p +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (struct Point) main::v1_q +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← (struct Vector) main::v2.p +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← { x: (byte) 6, y: (byte) 7 } +Adding struct value member variable copy *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) +Adding struct value member variable copy (struct Point) main::v5_p ← (struct Point){ (struct Vector) main::v4.p.x, (struct Vector) main::v4.p.y } +Adding struct value member variable copy (struct Point) main::v5_q ← { x: (byte) 8, y: (byte) 9 } +Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.p with member unwinding reference (struct Point) main::v1_p +Replacing struct member reference (struct Vector) main::v1.q with member unwinding reference (struct Point) main::v1_q +Replacing struct member reference (struct Vector) main::v1.q with member unwinding reference (struct Point) main::v1_q +Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v2.p with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v2.q with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v2.q with member unwinding reference *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v3.p with member unwinding reference *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v3.p with member unwinding reference *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v3.q with member unwinding reference *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v3.q with member unwinding reference *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v4.p with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P) +Replacing struct member reference (struct Vector) main::v4.q with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v4.q with member unwinding reference *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) +Replacing struct member reference (struct Vector) main::v5.p with member unwinding reference (struct Point) main::v5_p +Replacing struct member reference (struct Vector) main::v5.p with member unwinding reference (struct Point) main::v5_p +Replacing struct member reference (struct Vector) main::v5.q with member unwinding reference (struct Point) main::v5_q +Replacing struct member reference (struct Vector) main::v5.q with member unwinding reference (struct Point) main::v5_q +Adding struct value member variable copy (byte) main::v1_p_x ← (byte) 2 +Adding struct value member variable copy (byte) main::v1_p_y ← (byte) 3 +Adding struct value member variable copy (byte) main::v1_q_x ← (byte) 4 +Adding struct value member variable copy (byte) main::v1_q_y ← (byte) 5 +Adding struct value member variable copy *((byte*~) main::$0) ← (byte) main::v1_p_x +Adding struct value member variable copy *((byte*~) main::$1) ← (byte) main::v1_p_y +Adding struct value member variable copy *((byte*~) main::$2) ← (byte) main::v1_q_x +Adding struct value member variable copy *((byte*~) main::$3) ← (byte) main::v1_q_y +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), struct Point, (const byte) SIZEOF_STRUCT_POINT) +Adding struct value member variable copy *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) +Adding struct value member variable copy (byte) main::v5_p_x ← *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).x +Adding struct value member variable copy (byte) main::v5_p_y ← *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).y +Adding struct value member variable copy (byte) main::v5_q_x ← (byte) 8 +Adding struct value member variable copy (byte) main::v5_q_y ← (byte) 9 +Replacing struct member reference (struct Point) main::v1_p.x with member unwinding reference (byte) main::v1_p_x +Replacing struct member reference (struct Point) main::v1_p.y with member unwinding reference (byte) main::v1_p_y +Replacing struct member reference (struct Point) main::v1_q.x with member unwinding reference (byte) main::v1_q_x +Replacing struct member reference (struct Point) main::v1_q.y with member unwinding reference (byte) main::v1_q_y +Replacing struct member reference (struct Point) main::v5_p.x with member unwinding reference (byte) main::v5_p_x +Replacing struct member reference (struct Point) main::v5_p.y with member unwinding reference (byte) main::v5_p_y +Replacing struct member reference (struct Point) main::v5_q.x with member unwinding reference (byte) main::v5_q_x +Replacing struct member reference (struct Point) main::v5_q.y with member unwinding reference (byte) main::v5_q_y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P).y +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q).x +Rewriting struct pointer member access *((struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q).y +Identified constant variable (byte) main::v1_p_x +Identified constant variable (byte) main::v1_p_y +Identified constant variable (byte) main::v1_q_x +Identified constant variable (byte) main::v1_q_y +Identified constant variable (byte) main::v5_q_x +Identified constant variable (byte) main::v5_q_y + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::idx#0 ← (byte) 0 + (byte*~) main::$0 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X + *((byte*~) main::$0) ← (const byte) main::v1_p_x + (byte*~) main::$1 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*~) main::$1) ← (const byte) main::v1_p_y + (byte*~) main::$2 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X + *((byte*~) main::$2) ← (const byte) main::v1_q_x + (byte*~) main::$3 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*~) main::$3) ← (const byte) main::v1_q_y + (struct Vector) main::v2 ← struct-unwound {*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q)} + *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), struct Point, (const byte) SIZEOF_STRUCT_POINT) + *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) + (struct Vector) main::v3 ← struct-unwound {*((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q)} + *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + (byte*~) main::$4 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X + (byte) main::v5_p_x#0 ← *((byte*~) main::$4) + (byte*~) main::$5 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y + (byte) main::v5_p_y#0 ← *((byte*~) main::$5) + *((const byte*) SCREEN + (byte) main::idx#0) ← (const byte) main::v1_p_x + (byte) main::idx#1 ← ++ (byte) main::idx#0 + *((const byte*) SCREEN + (byte) main::idx#1) ← (const byte) main::v1_p_y + (byte) main::idx#2 ← ++ (byte) main::idx#1 + *((const byte*) SCREEN + (byte) main::idx#2) ← (const byte) main::v1_q_x + (byte) main::idx#3 ← ++ (byte) main::idx#2 + *((const byte*) SCREEN + (byte) main::idx#3) ← (const byte) main::v1_q_y + (byte) main::idx#4 ← ++ (byte) main::idx#3 + (byte*~) main::$6 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#4) ← *((byte*~) main::$6) + (byte) main::idx#5 ← ++ (byte) main::idx#4 + (byte*~) main::$7 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#5) ← *((byte*~) main::$7) + (byte) main::idx#6 ← ++ (byte) main::idx#5 + (byte*~) main::$8 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#6) ← *((byte*~) main::$8) + (byte) main::idx#7 ← ++ (byte) main::idx#6 + (byte*~) main::$9 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#7) ← *((byte*~) main::$9) + (byte) main::idx#8 ← ++ (byte) main::idx#7 + (byte*~) main::$10 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#8) ← *((byte*~) main::$10) + (byte) main::idx#9 ← ++ (byte) main::idx#8 + (byte*~) main::$11 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#9) ← *((byte*~) main::$11) + (byte) main::idx#10 ← ++ (byte) main::idx#9 + (byte*~) main::$12 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#10) ← *((byte*~) main::$12) + (byte) main::idx#11 ← ++ (byte) main::idx#10 + (byte*~) main::$13 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#11) ← *((byte*~) main::$13) + (byte) main::idx#12 ← ++ (byte) main::idx#11 + (byte*~) main::$14 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#12) ← *((byte*~) main::$14) + (byte) main::idx#13 ← ++ (byte) main::idx#12 + (byte*~) main::$15 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#13) ← *((byte*~) main::$15) + (byte) main::idx#14 ← ++ (byte) main::idx#13 + (byte*~) main::$16 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X + *((const byte*) SCREEN + (byte) main::idx#14) ← *((byte*~) main::$16) + (byte) main::idx#15 ← ++ (byte) main::idx#14 + (byte*~) main::$17 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y + *((const byte*) SCREEN + (byte) main::idx#15) ← *((byte*~) main::$17) + (byte) main::idx#16 ← ++ (byte) main::idx#15 + *((const byte*) SCREEN + (byte) main::idx#16) ← (byte) main::v5_p_x#0 + (byte) main::idx#17 ← ++ (byte) main::idx#16 + *((const byte*) SCREEN + (byte) main::idx#17) ← (byte) main::v5_p_y#0 + (byte) main::idx#18 ← ++ (byte) main::idx#17 + *((const byte*) SCREEN + (byte) main::idx#18) ← (const byte) main::v5_q_x + (byte) main::idx#19 ← ++ (byte) main::idx#18 + *((const byte*) SCREEN + (byte) main::idx#19) ← (const byte) main::v5_q_y + (byte) main::idx#20 ← ++ (byte) main::idx#19 + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(const struct Point) $0 = { x: (byte) 6, y: (byte) 7 } +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_POINT_X = (byte) 0 +(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_P = (byte) 0 +(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2 +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*)(number) $400 +(const byte) SIZEOF_STRUCT_POINT = (byte) 2 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(byte*~) main::$0 +(byte*~) main::$1 +(byte*~) main::$10 +(byte*~) main::$11 +(byte*~) main::$12 +(byte*~) main::$13 +(byte*~) main::$14 +(byte*~) main::$15 +(byte*~) main::$16 +(byte*~) main::$17 +(byte*~) main::$2 +(byte*~) main::$3 +(byte*~) main::$4 +(byte*~) main::$5 +(byte*~) main::$6 +(byte*~) main::$7 +(byte*~) main::$8 +(byte*~) main::$9 +(label) main::@return +(byte) main::idx +(byte) main::idx#0 +(byte) main::idx#1 +(byte) main::idx#10 +(byte) main::idx#11 +(byte) main::idx#12 +(byte) main::idx#13 +(byte) main::idx#14 +(byte) main::idx#15 +(byte) main::idx#16 +(byte) main::idx#17 +(byte) main::idx#18 +(byte) main::idx#19 +(byte) main::idx#2 +(byte) main::idx#20 +(byte) main::idx#3 +(byte) main::idx#4 +(byte) main::idx#5 +(byte) main::idx#6 +(byte) main::idx#7 +(byte) main::idx#8 +(byte) main::idx#9 +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(struct Vector) main::v2 loadstore +(struct Vector) main::v3 loadstore +(struct Vector) main::v4 loadstore +(byte) main::v5_p_x +(byte) main::v5_p_x#0 +(byte) main::v5_p_y +(byte) main::v5_p_y#0 +(const byte) main::v5_q_x = (byte) 8 +(const byte) main::v5_q_y = (byte) 9 + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Removing C-classic struct-unwound assignment [9] (struct Vector) main::v2 ← struct-unwound {*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q)} +Removing C-classic struct-unwound assignment [12] (struct Vector) main::v3 ← struct-unwound {*((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P), *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q)} +Constant right-side identified [1] (byte*~) main::$0 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [3] (byte*~) main::$1 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [7] (byte*~) main::$3 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [14] (byte*~) main::$4 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [16] (byte*~) main::$5 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [26] (byte*~) main::$6 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [29] (byte*~) main::$7 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [32] (byte*~) main::$8 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [35] (byte*~) main::$9 ← (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [38] (byte*~) main::$10 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [41] (byte*~) main::$11 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [44] (byte*~) main::$12 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [47] (byte*~) main::$13 ← (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [50] (byte*~) main::$14 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [53] (byte*~) main::$15 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_P + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [56] (byte*~) main::$16 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_X +Constant right-side identified [59] (byte*~) main::$17 ← (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q + (const byte) OFFSET_STRUCT_POINT_Y +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#0 = 0 +Constant (const byte*) main::$0 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$1 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$2 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$3 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$4 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$5 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$6 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$7 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$8 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$9 = (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$10 = (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$11 = (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$12 = (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$13 = (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$14 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$15 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$16 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_X +Constant (const byte*) main::$17 = (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P in +Simplifying expression containing zero (struct Point*)&main::v2 in +Simplifying expression containing zero (struct Point*)&main::v2 in +Simplifying expression containing zero (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q in +Simplifying expression containing zero (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P in +Simplifying expression containing zero (struct Point*)&main::v4 in +Simplifying expression containing zero (struct Point*)&main::v4 in +Simplifying expression containing zero (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_P in +Simplifying expression containing zero (struct Point*)&main::v2 in +Simplifying expression containing zero (struct Point*)&main::v2 in +Simplifying expression containing zero (byte*)(struct Point*)&main::v2+OFFSET_STRUCT_VECTOR_Q in +Simplifying expression containing zero (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_P in +Simplifying expression containing zero (struct Point*)&main::v3 in +Simplifying expression containing zero (struct Point*)&main::v3 in +Simplifying expression containing zero (byte*)(struct Point*)&main::v3+OFFSET_STRUCT_VECTOR_Q in +Simplifying expression containing zero (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_P in +Simplifying expression containing zero (struct Point*)&main::v4 in +Simplifying expression containing zero (struct Point*)&main::v4 in +Simplifying expression containing zero (byte*)(struct Point*)&main::v4+OFFSET_STRUCT_VECTOR_Q in +Simplifying expression containing zero (struct Point*)&main::v2 in [10] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_P), struct Point, (const byte) SIZEOF_STRUCT_POINT) +Simplifying expression containing zero (struct Point*)&main::v3 in [10] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_P) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) +Simplifying expression containing zero SCREEN in [18] *((const byte*) SCREEN + (const byte) main::idx#0) ← (const byte) main::v1_p_x +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (byte) main::idx#20 and assignment [48] (byte) main::idx#20 ← ++ (byte) main::idx#19 +Eliminating unused constant (const byte) OFFSET_STRUCT_VECTOR_P +Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X +Successful SSA optimization PassNEliminateUnusedVars +Constant right-side identified [10] (byte) main::idx#1 ← ++ (const byte) main::idx#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#1 = ++main::idx#0 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [11] (byte) main::idx#2 ← ++ (const byte) main::idx#1 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#2 = ++main::idx#1 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [12] (byte) main::idx#3 ← ++ (const byte) main::idx#2 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#3 = ++main::idx#2 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [13] (byte) main::idx#4 ← ++ (const byte) main::idx#3 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#4 = ++main::idx#3 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [14] (byte) main::idx#5 ← ++ (const byte) main::idx#4 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#5 = ++main::idx#4 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [15] (byte) main::idx#6 ← ++ (const byte) main::idx#5 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#6 = ++main::idx#5 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [16] (byte) main::idx#7 ← ++ (const byte) main::idx#6 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#7 = ++main::idx#6 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [17] (byte) main::idx#8 ← ++ (const byte) main::idx#7 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#8 = ++main::idx#7 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [18] (byte) main::idx#9 ← ++ (const byte) main::idx#8 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#9 = ++main::idx#8 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [19] (byte) main::idx#10 ← ++ (const byte) main::idx#9 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#10 = ++main::idx#9 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [20] (byte) main::idx#11 ← ++ (const byte) main::idx#10 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#11 = ++main::idx#10 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [21] (byte) main::idx#12 ← ++ (const byte) main::idx#11 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#12 = ++main::idx#11 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [22] (byte) main::idx#13 ← ++ (const byte) main::idx#12 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#13 = ++main::idx#12 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [23] (byte) main::idx#14 ← ++ (const byte) main::idx#13 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#14 = ++main::idx#13 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [24] (byte) main::idx#15 ← ++ (const byte) main::idx#14 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#15 = ++main::idx#14 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [25] (byte) main::idx#16 ← ++ (const byte) main::idx#15 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#16 = ++main::idx#15 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [26] (byte) main::idx#17 ← ++ (const byte) main::idx#16 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#17 = ++main::idx#16 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [27] (byte) main::idx#18 ← ++ (const byte) main::idx#17 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#18 = ++main::idx#17 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [28] (byte) main::idx#19 ← ++ (const byte) main::idx#18 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::idx#19 = ++main::idx#18 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings (const byte) main::idx#0 +Inlining constant with different constant siblings (const byte) main::idx#1 +Inlining constant with different constant siblings (const byte) main::idx#2 +Inlining constant with different constant siblings (const byte) main::idx#3 +Inlining constant with different constant siblings (const byte) main::idx#4 +Inlining constant with different constant siblings (const byte) main::idx#5 +Inlining constant with different constant siblings (const byte) main::idx#6 +Inlining constant with different constant siblings (const byte) main::idx#7 +Inlining constant with different constant siblings (const byte) main::idx#8 +Inlining constant with different constant siblings (const byte) main::idx#9 +Inlining constant with different constant siblings (const byte) main::idx#10 +Inlining constant with different constant siblings (const byte) main::idx#11 +Inlining constant with different constant siblings (const byte) main::idx#12 +Inlining constant with different constant siblings (const byte) main::idx#13 +Inlining constant with different constant siblings (const byte) main::idx#14 +Inlining constant with different constant siblings (const byte) main::idx#15 +Inlining constant with different constant siblings (const byte) main::idx#16 +Inlining constant with different constant siblings (const byte) main::idx#17 +Inlining constant with different constant siblings (const byte) main::idx#18 +Inlining constant with different constant siblings (const byte) main::idx#19 +Constant inlined main::idx#16 = ++++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#17 = ++++++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#18 = ++++++++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#19 = ++++++++++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#12 = ++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#13 = ++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#14 = ++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::idx#15 = ++++++++++++++++++++++++++++++(byte) 0 +Constant inlined main::$12 = (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q +Constant inlined main::$13 = (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$14 = (byte*)(struct Point*)&(struct Vector) main::v4 +Constant inlined main::$15 = (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$10 = (byte*)(struct Point*)&(struct Vector) main::v3 +Constant inlined main::$11 = (byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$16 = (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q +Constant inlined main::$17 = (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::idx#0 = (byte) 0 +Constant inlined main::idx#1 = ++(byte) 0 +Constant inlined main::idx#2 = ++++(byte) 0 +Constant inlined main::$1 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::idx#3 = ++++++(byte) 0 +Constant inlined main::$2 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q +Constant inlined main::idx#4 = ++++++++(byte) 0 +Constant inlined main::idx#5 = ++++++++++(byte) 0 +Constant inlined main::$0 = (byte*)(struct Point*)&(struct Vector) main::v2 +Constant inlined main::idx#6 = ++++++++++++(byte) 0 +Constant inlined main::$5 = (byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::idx#7 = ++++++++++++++(byte) 0 +Constant inlined main::$6 = (byte*)(struct Point*)&(struct Vector) main::v2 +Constant inlined main::idx#8 = ++++++++++++++++(byte) 0 +Constant inlined main::$3 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::idx#9 = ++++++++++++++++++(byte) 0 +Constant inlined main::idx#10 = ++++++++++++++++++++(byte) 0 +Constant inlined main::$4 = (byte*)(struct Point*)&(struct Vector) main::v4 +Constant inlined main::idx#11 = ++++++++++++++++++++++(byte) 0 +Constant inlined main::$9 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$7 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$8 = (byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+++0) +Consolidated array index constant in *(SCREEN+++++0) +Consolidated array index constant in *(SCREEN+++++++0) +Consolidated array index constant in *(SCREEN+++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++++++++0) +Consolidated array index constant in *(SCREEN+++++++++++++++++++++++++++++++++++++++0) +Successful SSA optimization Pass2ConstantAdditionElimination +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++0 +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$d +Simplifying constant integer increment ++$e +Simplifying constant integer increment ++$f +Simplifying constant integer increment ++$10 +Simplifying constant integer increment ++$11 +Successful SSA optimization Pass2ConstantSimplification +Simplifying constant integer increment ++1 +Simplifying constant integer increment ++2 +Simplifying constant integer increment ++3 +Simplifying constant integer increment ++4 +Simplifying constant integer increment ++5 +Simplifying constant integer increment ++6 +Simplifying constant integer increment ++7 +Simplifying constant integer increment ++8 +Simplifying constant integer increment ++9 +Simplifying constant integer increment ++$a +Simplifying constant integer increment ++$b +Simplifying constant integer increment ++$c +Simplifying constant integer increment ++$d +Simplifying constant integer increment ++$e +Simplifying constant integer increment ++$f +Simplifying constant integer increment ++$10 +Simplifying constant integer increment ++$11 +Simplifying constant integer increment ++$12 +Successful SSA optimization Pass2ConstantSimplification +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 +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x + [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y + [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x + [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y + [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) + [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) + [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) + [11] (byte) main::v5_p_x#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4) + [12] (byte) main::v5_p_y#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) + [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x + [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y + [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x + [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y + [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) + [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) + [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) + [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) + [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) + [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) + [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) + [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) + [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) + [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) + [29] *((const byte*) SCREEN+(byte) $10) ← (byte) main::v5_p_x#0 + [30] *((const byte*) SCREEN+(byte) $11) ← (byte) main::v5_p_y#0 + [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x + [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y + to:main::@return +main::@return: scope:[main] from main + [33] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) Point::x +(byte) Point::y +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(byte) main::idx +(struct Vector) main::v2 loadstore +(struct Vector) main::v3 loadstore +(struct Vector) main::v4 loadstore +(byte) main::v5_p_x +(byte) main::v5_p_x#0 0.2222222222222222 +(byte) main::v5_p_y +(byte) main::v5_p_y#0 0.2222222222222222 + +Initial phi equivalence classes +Added variable main::v5_p_x#0 to live range equivalence class [ main::v5_p_x#0 ] +Added variable main::v5_p_y#0 to live range equivalence class [ main::v5_p_y#0 ] +Added variable main::v2 to live range equivalence class [ main::v2 ] +Added variable main::v3 to live range equivalence class [ main::v3 ] +Added variable main::v4 to live range equivalence class [ main::v4 ] +Complete equivalence classes +[ main::v5_p_x#0 ] +[ main::v5_p_y#0 ] +[ main::v2 ] +[ main::v3 ] +[ main::v4 ] +Allocated zp[1]:2 [ main::v5_p_x#0 ] +Allocated zp[1]:3 [ main::v5_p_y#0 ] +Allocated zp[4]:4 [ main::v2 ] +Allocated zp[4]:8 [ main::v3 ] +Allocated zp[4]:12 [ main::v4 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .const OFFSET_STRUCT_VECTOR_Q = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v5_q_x = 8 + .const v5_q_y = 9 + .label v2 = 4 + .label v3 = 8 + .label v4 = $c + .label v5_p_x = 2 + .label v5_p_y = 3 + // [4] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta.z v2 + // [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta v2+OFFSET_STRUCT_POINT_Y + // [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta v2+OFFSET_STRUCT_VECTOR_Q + // [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + // [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda v2-1,y + sta v3-1,y + dey + bne !- + // [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda __0-1,y + sta v3+OFFSET_STRUCT_VECTOR_Q-1,y + dey + bne !- + // [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_VECTOR + !: + lda v3-1,y + sta v4-1,y + dey + bne !- + // [11] (byte) main::v5_p_x#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- vbuz1=_deref_pbuc1 + lda.z v4 + sta.z v5_p_x + // [12] (byte) main::v5_p_y#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 + lda v4+OFFSET_STRUCT_POINT_Y + sta.z v5_p_y + // [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) -- _deref_pbuc1=_deref_pbuc2 + lda.z v2 + sta SCREEN+4 + // [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_POINT_Y + sta SCREEN+5 + // [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+6 + // [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+7 + // [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) -- _deref_pbuc1=_deref_pbuc2 + lda.z v3 + sta SCREEN+8 + // [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_POINT_Y + sta SCREEN+9 + // [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$a + // [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$b + // [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- _deref_pbuc1=_deref_pbuc2 + lda.z v4 + sta SCREEN+$c + // [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_POINT_Y + sta SCREEN+$d + // [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$e + // [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$f + // [29] *((const byte*) SCREEN+(byte) $10) ← (byte) main::v5_p_x#0 -- _deref_pbuc1=vbuz1 + lda.z v5_p_x + sta SCREEN+$10 + // [30] *((const byte*) SCREEN+(byte) $11) ← (byte) main::v5_p_y#0 -- _deref_pbuc1=vbuz1 + lda.z v5_p_y + sta SCREEN+$11 + // [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x -- _deref_pbuc1=vbuc2 + lda #v5_q_x + sta SCREEN+$12 + // [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y -- _deref_pbuc1=vbuc2 + lda #v5_q_y + sta SCREEN+$13 + jmp __breturn + // main::@return + __breturn: + // [33] return + rts +} + // File Data + __0: .byte 6, 7 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::v5_p_x#0 ] +Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::v5_p_y#0 ] +Statement [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [4] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a +Statement [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) [ main::v2 main::v3 main::v4 ] ( main:2 [ main::v2 main::v3 main::v4 ] ) always clobbers reg byte a reg byte y +Statement [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v2 main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v3 main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v4 main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) [ main::v5_p_x#0 main::v5_p_y#0 ] ( main:2 [ main::v5_p_x#0 main::v5_p_y#0 ] ) always clobbers reg byte a +Statement [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y [ ] ( main:2 [ ] ) always clobbers reg byte a +Potential registers zp[1]:2 [ main::v5_p_x#0 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ main::v5_p_y#0 ] : zp[1]:3 , reg byte x , reg byte y , +Potential registers zp[4]:4 [ main::v2 ] : zp[4]:4 , +Potential registers zp[4]:8 [ main::v3 ] : zp[4]:8 , +Potential registers zp[4]:12 [ main::v4 ] : zp[4]:12 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 0.22: zp[1]:2 [ main::v5_p_x#0 ] 0.22: zp[1]:3 [ main::v5_p_y#0 ] 0: zp[4]:4 [ main::v2 ] 0: zp[4]:8 [ main::v3 ] 0: zp[4]:12 [ main::v4 ] +Uplift Scope [Point] +Uplift Scope [Vector] +Uplift Scope [] + +Uplifting [main] best 236 combination reg byte y [ main::v5_p_x#0 ] reg byte x [ main::v5_p_y#0 ] zp[4]:4 [ main::v2 ] zp[4]:8 [ main::v3 ] zp[4]:12 [ main::v4 ] +Uplifting [Point] best 236 combination +Uplifting [Vector] best 236 combination +Uplifting [] best 236 combination +Allocated (was zp[4]:4) zp[4]:2 [ main::v2 ] +Allocated (was zp[4]:8) zp[4]:6 [ main::v3 ] +Allocated (was zp[4]:12) zp[4]:10 [ main::v4 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .const OFFSET_STRUCT_VECTOR_Q = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v5_q_x = 8 + .const v5_q_y = 9 + .label v2 = 2 + .label v3 = 6 + .label v4 = $a + // [4] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta.z v2 + // [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta v2+OFFSET_STRUCT_POINT_Y + // [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta v2+OFFSET_STRUCT_VECTOR_Q + // [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + // [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda v2-1,y + sta v3-1,y + dey + bne !- + // [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda __0-1,y + sta v3+OFFSET_STRUCT_VECTOR_Q-1,y + dey + bne !- + // [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_VECTOR + !: + lda v3-1,y + sta v4-1,y + dey + bne !- + // [11] (byte) main::v5_p_x#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- vbuyy=_deref_pbuc1 + ldy.z v4 + // [12] (byte) main::v5_p_y#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1 + ldx v4+OFFSET_STRUCT_POINT_Y + // [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) -- _deref_pbuc1=_deref_pbuc2 + lda.z v2 + sta SCREEN+4 + // [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_POINT_Y + sta SCREEN+5 + // [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+6 + // [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+7 + // [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) -- _deref_pbuc1=_deref_pbuc2 + lda.z v3 + sta SCREEN+8 + // [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_POINT_Y + sta SCREEN+9 + // [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$a + // [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$b + // [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- _deref_pbuc1=_deref_pbuc2 + lda.z v4 + sta SCREEN+$c + // [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_POINT_Y + sta SCREEN+$d + // [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$e + // [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$f + // [29] *((const byte*) SCREEN+(byte) $10) ← (byte) main::v5_p_x#0 -- _deref_pbuc1=vbuyy + sty SCREEN+$10 + // [30] *((const byte*) SCREEN+(byte) $11) ← (byte) main::v5_p_y#0 -- _deref_pbuc1=vbuxx + stx SCREEN+$11 + // [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x -- _deref_pbuc1=vbuc2 + lda #v5_q_x + sta SCREEN+$12 + // [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y -- _deref_pbuc1=vbuc2 + lda #v5_q_y + sta SCREEN+$13 + jmp __breturn + // main::@return + __breturn: + // [33] return + rts +} + // File Data + __0: .byte 6, 7 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction lda.z v4 with TYA +Replacing instruction lda v4+OFFSET_STRUCT_POINT_Y with TXA +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b1_from___bbegin: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(const struct Point) $0 = { x: (byte) 6, y: (byte) 7 } +(label) @1 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2 +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*) 1024 +(const byte) SIZEOF_STRUCT_POINT = (byte) 2 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(label) main::@return +(byte) main::idx +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(struct Vector) main::v2 loadstore zp[4]:2 +(struct Vector) main::v3 loadstore zp[4]:6 +(struct Vector) main::v4 loadstore zp[4]:10 +(byte) main::v5_p_x +(byte) main::v5_p_x#0 reg byte y 0.2222222222222222 +(byte) main::v5_p_y +(byte) main::v5_p_y#0 reg byte x 0.2222222222222222 +(const byte) main::v5_q_x = (byte) 8 +(const byte) main::v5_q_y = (byte) 9 + +reg byte y [ main::v5_p_x#0 ] +reg byte x [ main::v5_p_y#0 ] +zp[4]:2 [ main::v2 ] +zp[4]:6 [ main::v3 ] +zp[4]:10 [ main::v4 ] + + +FINAL ASSEMBLER +Score: 218 + + // File Comments +// Minimal struct with Unwound behavior - struct containing struct copying + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .const OFFSET_STRUCT_VECTOR_Q = 2 + .const SIZEOF_STRUCT_VECTOR = 4 + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .const v1_p_x = 2 + .const v1_p_y = 3 + .const v1_q_x = 4 + .const v1_q_y = 5 + .const v5_q_x = 8 + .const v5_q_y = 9 + .label v2 = 2 + .label v3 = 6 + .label v4 = $a + // v2 = v1 + // [4] *((byte*)(struct Point*)&(struct Vector) main::v2) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta.z v2 + // [5] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta v2+OFFSET_STRUCT_POINT_Y + // [6] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta v2+OFFSET_STRUCT_VECTOR_Q + // [7] *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + // v3 = { v2.p, {6, 7} } + // [8] *((struct Point*)&(struct Vector) main::v3) ← memcpy(*((struct Point*)&(struct Vector) main::v2), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda v2-1,y + sta v3-1,y + dey + bne !- + // [9] *((struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda __0-1,y + sta v3+OFFSET_STRUCT_VECTOR_Q-1,y + dey + bne !- + // v4 = v3 + // [10] *(&(struct Vector) main::v4) ← memcpy(*(&(struct Vector) main::v3), struct Vector, (const byte) SIZEOF_STRUCT_VECTOR) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_VECTOR + !: + lda v3-1,y + sta v4-1,y + dey + bne !- + // v5 = { {v4.p.x, v4.p.y }, {8, 9} } + // [11] (byte) main::v5_p_x#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- vbuyy=_deref_pbuc1 + ldy.z v4 + // [12] (byte) main::v5_p_y#0 ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1 + ldx v4+OFFSET_STRUCT_POINT_Y + // SCREEN[idx++] = v1.p.x + // [13] *((const byte*) SCREEN) ← (const byte) main::v1_p_x -- _deref_pbuc1=vbuc2 + lda #v1_p_x + sta SCREEN + // SCREEN[idx++] = v1.p.y + // [14] *((const byte*) SCREEN+(byte) 1) ← (const byte) main::v1_p_y -- _deref_pbuc1=vbuc2 + lda #v1_p_y + sta SCREEN+1 + // SCREEN[idx++] = v1.q.x + // [15] *((const byte*) SCREEN+(byte) 2) ← (const byte) main::v1_q_x -- _deref_pbuc1=vbuc2 + lda #v1_q_x + sta SCREEN+2 + // SCREEN[idx++] = v1.q.y + // [16] *((const byte*) SCREEN+(byte) 3) ← (const byte) main::v1_q_y -- _deref_pbuc1=vbuc2 + lda #v1_q_y + sta SCREEN+3 + // SCREEN[idx++] = v2.p.x + // [17] *((const byte*) SCREEN+(byte) 4) ← *((byte*)(struct Point*)&(struct Vector) main::v2) -- _deref_pbuc1=_deref_pbuc2 + lda.z v2 + sta SCREEN+4 + // SCREEN[idx++] = v2.p.y + // [18] *((const byte*) SCREEN+(byte) 5) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_POINT_Y + sta SCREEN+5 + // SCREEN[idx++] = v2.q.x + // [19] *((const byte*) SCREEN+(byte) 6) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+6 + // SCREEN[idx++] = v2.q.y + // [20] *((const byte*) SCREEN+(byte) 7) ← *((byte*)(struct Point*)&(struct Vector) main::v2+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v2+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+7 + // SCREEN[idx++] = v3.p.x + // [21] *((const byte*) SCREEN+(byte) 8) ← *((byte*)(struct Point*)&(struct Vector) main::v3) -- _deref_pbuc1=_deref_pbuc2 + lda.z v3 + sta SCREEN+8 + // SCREEN[idx++] = v3.p.y + // [22] *((const byte*) SCREEN+(byte) 9) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_POINT_Y + sta SCREEN+9 + // SCREEN[idx++] = v3.q.x + // [23] *((const byte*) SCREEN+(byte) $a) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$a + // SCREEN[idx++] = v3.q.y + // [24] *((const byte*) SCREEN+(byte) $b) ← *((byte*)(struct Point*)&(struct Vector) main::v3+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v3+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$b + // SCREEN[idx++] = v4.p.x + // [25] *((const byte*) SCREEN+(byte) $c) ← *((byte*)(struct Point*)&(struct Vector) main::v4) -- _deref_pbuc1=_deref_pbuc2 + tya + sta SCREEN+$c + // SCREEN[idx++] = v4.p.y + // [26] *((const byte*) SCREEN+(byte) $d) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + txa + sta SCREEN+$d + // SCREEN[idx++] = v4.q.x + // [27] *((const byte*) SCREEN+(byte) $e) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q + sta SCREEN+$e + // SCREEN[idx++] = v4.q.y + // [28] *((const byte*) SCREEN+(byte) $f) ← *((byte*)(struct Point*)&(struct Vector) main::v4+(const byte) OFFSET_STRUCT_VECTOR_Q+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda v4+OFFSET_STRUCT_VECTOR_Q+OFFSET_STRUCT_POINT_Y + sta SCREEN+$f + // SCREEN[idx++] = v5.p.x + // [29] *((const byte*) SCREEN+(byte) $10) ← (byte) main::v5_p_x#0 -- _deref_pbuc1=vbuyy + sty SCREEN+$10 + // SCREEN[idx++] = v5.p.y + // [30] *((const byte*) SCREEN+(byte) $11) ← (byte) main::v5_p_y#0 -- _deref_pbuc1=vbuxx + stx SCREEN+$11 + // SCREEN[idx++] = v5.q.x + // [31] *((const byte*) SCREEN+(byte) $12) ← (const byte) main::v5_q_x -- _deref_pbuc1=vbuc2 + lda #v5_q_x + sta SCREEN+$12 + // SCREEN[idx++] = v5.q.y + // [32] *((const byte*) SCREEN+(byte) $13) ← (const byte) main::v5_q_y -- _deref_pbuc1=vbuc2 + lda #v5_q_y + sta SCREEN+$13 + // main::@return + // } + // [33] return + rts +} + // File Data + __0: .byte 6, 7 + diff --git a/src/test/ref/struct-41.sym b/src/test/ref/struct-41.sym new file mode 100644 index 000000000..8dccadb18 --- /dev/null +++ b/src/test/ref/struct-41.sym @@ -0,0 +1,35 @@ +(const struct Point) $0 = { x: (byte) 6, y: (byte) 7 } +(label) @1 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 +(const byte) OFFSET_STRUCT_VECTOR_Q = (byte) 2 +(byte) Point::x +(byte) Point::y +(const byte*) SCREEN = (byte*) 1024 +(const byte) SIZEOF_STRUCT_POINT = (byte) 2 +(const byte) SIZEOF_STRUCT_VECTOR = (byte) 4 +(struct Point) Vector::p +(struct Point) Vector::q +(void()) main() +(label) main::@return +(byte) main::idx +(const byte) main::v1_p_x = (byte) 2 +(const byte) main::v1_p_y = (byte) 3 +(const byte) main::v1_q_x = (byte) 4 +(const byte) main::v1_q_y = (byte) 5 +(struct Vector) main::v2 loadstore zp[4]:2 +(struct Vector) main::v3 loadstore zp[4]:6 +(struct Vector) main::v4 loadstore zp[4]:10 +(byte) main::v5_p_x +(byte) main::v5_p_x#0 reg byte y 0.2222222222222222 +(byte) main::v5_p_y +(byte) main::v5_p_y#0 reg byte x 0.2222222222222222 +(const byte) main::v5_q_x = (byte) 8 +(const byte) main::v5_q_y = (byte) 9 + +reg byte y [ main::v5_p_x#0 ] +reg byte x [ main::v5_p_y#0 ] +zp[4]:2 [ main::v2 ] +zp[4]:6 [ main::v3 ] +zp[4]:10 [ main::v4 ]