diff --git a/src/main/kc/stdlib/stdlib.kc b/src/main/kc/stdlib/stdlib.kc index 5b9fe2dd3..312d71dfa 100644 --- a/src/main/kc/stdlib/stdlib.kc +++ b/src/main/kc/stdlib/stdlib.kc @@ -1,5 +1,4 @@ // Implementation of functions found int C stdlib.h / stdlib.c - import "string" // Top of the heap used by malloc() @@ -36,10 +35,10 @@ void *calloc(size_t nitems, size_t size) { // - items - Pointer to the start of the array to search in // - num - The number of items in the array // Returns pointer to an entry in the array that matches the search key -word* bsearch16u(word key, word* items, byte num) { +unsigned int* bsearch16u(unsigned int key, unsigned int* items, char num) { while (num > 0) { word* pivot = items + (num >> 1); - signed word result = (signed word)key-(signed word)*pivot; + signed int result = (signed int)key-(signed int)*pivot; if (result == 0) return pivot; if (result > 0) { @@ -50,4 +49,99 @@ word* bsearch16u(word key, word* items, byte num) { } // not found - return closest lower value return *items<=key?items:items-1; +} + +// The different supported radix +enum RADIX { BINARY, OCTAL, DECIMAL, HEXADECIMAL }; + +// Awaits fix https://gitlab.com/camelot/kickc/issues/230 +// Information about a radix +//struct RadixInfo { +// // Maximal number of digits needed to represent the number in the radix +// char max_digits; +// // Pointer to array containing the 1-value for each digit. The size of the array is max_digits-1. +// unsigned int* digit_values; +//}; + +// Values of binary digits +unsigned int[] RADIX_BINARY_VALUES = { 0b1000000000000000, 0b0100000000000000, 0b0010000000000000, 0b0001000000000000, 0b0000100000000000, 0b0000010000000000, 0b0000001000000000, 0b0000000100000000, 0b0000000010000000, 0b0000000001000000, 0b0000000000100000, 0b0000000000010000, 0b0000000000001000, 0b0000000000000100, 0b0000000000000010 }; +// Information about the hexadecimal radix +// struct RadixInfo RADIXINFO_BINARY = { 16, RADIX_BINARY_VALUES }; +// Values of octal digits +unsigned int[] RADIX_OCTAL_VALUES = { 0x8000, 0x1000, 0x200, 0x40, 0x8 }; +// Information about the octal radix +// struct RadixInfo RADIXINFO_OCTAL = { 6, RADIX_OCTAL_VALUES }; +// Values of decimal digits +unsigned int[] RADIX_DECIMAL_VALUES = { 10000, 1000, 100, 10 }; +// Information about the decimal radix +// struct RadixInfo RADIXINFO_DECIMAL = { 5, RADIX_DECIMAL_VALUES }; +// Values of hexadecimal digits +unsigned int[] RADIX_HEXADECIMAL_VALUES = { 0x1000, 0x100, 0x10 }; +// Information about the hexadecimal radix +// struct RadixInfo RADIXINFO_HEXADECIMAL = { 4, RADIX_HEXADECIMAL_VALUES }; + +// Awaits fix https://gitlab.com/camelot/kickc/issues/223 +// Information about each radix. Can be retrieved using RADIXINFOS[radix] +// struct RadixInfo[] RADIXINFOS = { RADIXINFO_OCTAL, RADIXINFO_OCTAL, RADIXINFO_DECIMAL, RADIXINFO_HEXADECIMAL }; + +// The digits used for numbers +char[] DIGITS = "0123456789abcdef"z; + +// Converts unsigned number value to a string representing it in RADIX format. +// If the leading digits are zero they are not included in the string. +// - value : The number to be converted to RADIX +// - buffer : receives the string representing the number and zero-termination. +// - radix : The radix to convert the number to (from the enum RADIX) +void utoa(unsigned int value, char* buffer, enum RADIX radix){ + // struct RadixInfo info = RADIXINFOS[radix] ; + char max_digits; + unsigned int* digit_values; + if(radix==DECIMAL) { + //info = RADIXINFO_DECIMAL; + max_digits = 5; + digit_values = RADIX_DECIMAL_VALUES; + } else if(radix==HEXADECIMAL) { + //info = RADIXINFO_HEXADECIMAL; + max_digits = 4; + digit_values = RADIX_HEXADECIMAL_VALUES; + } else if(radix==OCTAL) { + //info = RADIXINFO_OCTAL; + max_digits = 6; + digit_values = RADIX_OCTAL_VALUES; + } else if(radix==BINARY) { + //info = RADIXINFO_BINARY; + max_digits = 16; + digit_values = RADIX_BINARY_VALUES; + } else { + // Unknown radix + *buffer++ = 'n'; + *buffer++ = 'a'; + *buffer = 0; + return; + } + byte started = 0; + for( char digit=0; digit= digit_value){ + value = utoa_append(buffer++, value, digit_value); + started = 1; + } + } + *buffer++ = DIGITS[(char)value]; + *buffer = 0; +} + +// Used to convert a single digit of an unsigned number value to a string representation +// Counts a single digit up from '0' as long as the value is larger than sub. +// Each time the digit is increased sub is subtracted from value. +// - buffer : pointer to the char that receives the digit +// - value : The value where the digit will be derived from +// - sub : the value of a '1' in the digit. Subtracted continually while the digit is increased. +// (For decimal the subs used are 10000, 1000, 100, 10, 1) +// returns : the value reduced by sub * digit so that it is less than sub. +unsigned int utoa_append(char *buffer, unsigned int value, unsigned int sub){ + char digit = 0; + while (value >= sub){ digit++; value -= sub; } + *buffer = DIGITS[digit]; + return value; } \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 5b677bf81..df9a2fb92 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -35,6 +35,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testProblemPointerInsideStructSizeofRewriting() throws IOException, URISyntaxException { + compileAndCompare("problem-pointer-inside-struct-sizeof-rewriting"); + } + /* @Test public void testProblemStructPointerParam() throws IOException, URISyntaxException { diff --git a/src/test/kc/problem-pointer-inside-struct-sizeof-rewriting.kc b/src/test/kc/problem-pointer-inside-struct-sizeof-rewriting.kc new file mode 100644 index 000000000..2466c6f6d --- /dev/null +++ b/src/test/kc/problem-pointer-inside-struct-sizeof-rewriting.kc @@ -0,0 +1,18 @@ +// Illustrates a problem with pointer sizeof()-rewriting for pointers inside structs + +unsigned int[] RADIX_DECIMAL_VALUES = { 10000, 1000, 100, 10 }; + +struct RadixInfo { + unsigned int* values; +}; + +void main() { + const unsigned int* SCREEN = 0x400; + for( byte radix: 0..1) { + struct RadixInfo info = { RADIX_DECIMAL_VALUES }; + for( char digit: 0..4 ) { + unsigned int digit_value = info.values[digit]; + SCREEN[digit] = digit_value; + } + } +} \ No newline at end of file diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc index e5dce106a..670bd8c7d 100644 --- a/src/test/kc/sandbox.kc +++ b/src/test/kc/sandbox.kc @@ -14,6 +14,7 @@ word append(byte *dst, word value, word sub){ while (value >= sub){ ++*dst; value -= sub; } return value; } + void utoa(word value, byte *dst){ byte bStarted = 0; if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; } diff --git a/src/test/kc/sieve.kc b/src/test/kc/sieve.kc new file mode 100644 index 000000000..6650a1e93 --- /dev/null +++ b/src/test/kc/sieve.kc @@ -0,0 +1,53 @@ +import "print" +import "string" +import "time" + +typedef unsigned char uint8_t; +typedef unsigned int uint16_t; + +const uint16_t COUNT = 16384; /* Up to what number? */ +const uint8_t SQRT_COUNT = 128; /* Sqrt of COUNT */ + +uint8_t* sieve = 0x1000; + +void main (void) { + print_str("Sieve benchmark - calculating primes"); + print_ln(); + print_str("between 2 and "); + print_word(COUNT); + print_ln(); + + // Fill sieve with zeros + memset(sieve, 0, COUNT); + + clock_start(); + + unsigned int i = 2; + char* sieve_i = sieve+i; + while (i < SQRT_COUNT) { + if (!*sieve_i) { + /* Prime number - mark all multiples */ + unsigned int j = i*2; + unsigned char* s = sieve+j; + while (j < COUNT) { + *s = 1; + s += i; + j += i; + } + } + i++; + sieve_i++; + } + + clock_t cyclecount = clock()-CLOCKS_PER_INIT; + + print_str("Cycles used: "); + print_dword(cyclecount); + print_ln(); + for (i = 2; i < 1024; ++i) + if (!sieve[i]) { + print_word(i); + print_char(' '); + } + +} diff --git a/src/test/kc/test-utoa.kc b/src/test/kc/test-utoa.kc new file mode 100644 index 000000000..537fbc31a --- /dev/null +++ b/src/test/kc/test-utoa.kc @@ -0,0 +1,39 @@ +// Tests the utoa10() function that converts unsigned int to DECIMAL string +import "stdlib" +import "print" + +// buffer for number +char[17] buf; + +void main() { + print_cls(); + print_utoas(0xffff); + print_utoas(59999); + print_utoas(0xaaaa); + print_utoas(0x5555); + print_utoas(9999); + print_utoas(0x0fff); + print_utoas(999); + print_utoas(0x0ff); + print_utoas(99); + print_utoas(0x0f); + print_utoas(1); + utoa(1, buf, 10); + print_str(buf); + print_ln(); +} + +void print_utoas(unsigned int value) { + utoa(value, buf, HEXADECIMAL); + print_str(buf); + print_char(' '); + utoa(value, buf, DECIMAL); + print_str(buf); + print_char(' '); + utoa(value, buf, OCTAL); + print_str(buf); + print_char(' '); + utoa(value, buf, BINARY); + print_str(buf); + print_ln(); +} \ No newline at end of file diff --git a/src/test/ref/complex/clearscreen/clearscreen.log b/src/test/ref/complex/clearscreen/clearscreen.log index 3197926fc..724c44278 100644 --- a/src/test/ref/complex/clearscreen/clearscreen.log +++ b/src/test/ref/complex/clearscreen/clearscreen.log @@ -8,6 +8,7 @@ Fixing pointer addition (word*~) bsearch16u::$1 ← (word*) bsearch16u::items - Fixing pointer increment (word*) init_squares::squares ← ++ (word*) init_squares::squares Fixing pointer addition (word~) sqrt::$1 ← (word*) sqrt::found - (word*) SQUARES Fixing pointer addition (struct ProcessingSprite*~) processChars::$2 ← (struct ProcessingSprite[NUM_PROCESSING]) PROCESSING + (byte) processChars::i +Fixing pointer array-indexing *((word*) utoa::digit_values + (byte) utoa::digit) Fixing pointer array-indexing *((word*) SQUARES + (byte) sqr::val) Fixing pointer array-indexing *((word[CORDIC_ITERATIONS_16]) CORDIC_ATAN2_ANGLES_16 + (byte) atan2_16::i) Fixing pointer array-indexing *((word[CORDIC_ITERATIONS_16]) CORDIC_ATAN2_ANGLES_16 + (byte) atan2_16::i) @@ -124,6 +125,8 @@ Culled Empty Block (label) @7 Culled Empty Block (label) @8 Culled Empty Block (label) @9 Culled Empty Block (label) @10 +Culled Empty Block (label) @11 +Culled Empty Block (label) @12 Culled Empty Block (label) atan2_16::@9 Culled Empty Block (label) atan2_16::@10 Culled Empty Block (label) atan2_16::@11 @@ -136,33 +139,33 @@ Culled Empty Block (label) atan2_16::@23 Culled Empty Block (label) atan2_16::@31 Culled Empty Block (label) atan2_16::@32 Culled Empty Block (label) atan2_16::@14 -Culled Empty Block (label) @12 -Culled Empty Block (label) @13 Culled Empty Block (label) @14 Culled Empty Block (label) @15 Culled Empty Block (label) @16 Culled Empty Block (label) @17 +Culled Empty Block (label) @18 Culled Empty Block (label) @19 -Culled Empty Block (label) @20 Culled Empty Block (label) @21 +Culled Empty Block (label) @22 +Culled Empty Block (label) @23 Culled Empty Block (label) main::@8 Culled Empty Block (label) main::@9 Culled Empty Block (label) main::@10 Culled Empty Block (label) main::@12 -Culled Empty Block (label) @23 +Culled Empty Block (label) @25 Culled Empty Block (label) getCharToProcess::@6 Culled Empty Block (label) getCharToProcess::@2 -Culled Empty Block (label) @24 +Culled Empty Block (label) @26 Culled Empty Block (label) startProcessing::@6 Culled Empty Block (label) startProcessing::@7 Culled Empty Block (label) processChars::@10 Culled Empty Block (label) processChars::@12 Culled Empty Block (label) processChars::@1 -Culled Empty Block (label) @26 -Culled Empty Block (label) @27 -Culled Empty Block (label) init_angle_screen::@4 Culled Empty Block (label) @28 Culled Empty Block (label) @29 +Culled Empty Block (label) init_angle_screen::@4 +Culled Empty Block (label) @30 +Culled Empty Block (label) @31 Culled Empty Block (label) setupRasterIrq::@4 Unwinding list assignment { (byte) main::$9_x, (byte) main::$9_y, (byte) main::$9_dist } ← { (byte) getCharToProcess::return_x, (byte) getCharToProcess::return_y, (byte) getCharToProcess::return_dist } Unwinding list assignment { (byte) getCharToProcess::return_x#0, (byte) getCharToProcess::return_y#0, (byte) getCharToProcess::return_dist#0 } ← { (byte) getCharToProcess::return_x#2, (byte) getCharToProcess::return_y#2, (byte) getCharToProcess::return_dist#2 } @@ -175,10 +178,10 @@ CONTROL FLOW GRAPH SSA @4: scope:[] from @begin (byte*) HEAP_TOP#0 ← ((byte*)) (number) $a000 (byte*) heap_head#0 ← (byte*) HEAP_TOP#0 - to:@11 -malloc: scope:[malloc] from @22 @33 - (word) malloc::size#2 ← phi( @22/(word) malloc::size#0 @33/(word) malloc::size#1 ) - (byte*) heap_head#5 ← phi( @22/(byte*) heap_head#9 @33/(byte*) heap_head#3 ) + to:@13 +malloc: scope:[malloc] from @24 @35 + (word) malloc::size#2 ← phi( @24/(word) malloc::size#0 @35/(word) malloc::size#1 ) + (byte*) heap_head#5 ← phi( @24/(byte*) heap_head#9 @35/(byte*) heap_head#3 ) (byte*~) malloc::$0 ← (byte*) heap_head#5 - (word) malloc::size#2 (byte*) malloc::mem#0 ← (byte*~) malloc::$0 (byte*) heap_head#1 ← (byte*) malloc::mem#0 @@ -191,13 +194,13 @@ malloc::@return: scope:[malloc] from malloc (byte*) heap_head#2 ← (byte*) heap_head#6 return to:@return -@11: scope:[] from @4 +@13: scope:[] from @4 (byte*) heap_head#11 ← phi( @4/(byte*) heap_head#0 ) (byte) CORDIC_ITERATIONS_16#0 ← (number) $f (word[CORDIC_ITERATIONS_16#0]) CORDIC_ATAN2_ANGLES_16#0 ← kickasm {{ .for (var i=0; i@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + .label SCREEN = $400 + .label _2 = 6 + .label digit_value = 4 + .label digit = 3 + .label radix = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta radix + jmp b1 + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + // [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 + // main::@1 + b1: + // [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + // [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1 + lda #0 + sta digit + jmp b2 + // [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2] + b2_from_b2: + // [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy + jmp b2 + // main::@2 + b2: + // [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuz2 + ldy digit + lda RADIX_DECIMAL_VALUES,y + sta digit_value + lda RADIX_DECIMAL_VALUES+1,y + sta digit_value+1 + // [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuz1=vbuz2_rol_1 + lda digit + asl + sta _2 + // [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuz1=vwuz2 + ldy _2 + lda digit_value + sta SCREEN,y + lda digit_value+1 + sta SCREEN+1,y + // [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuz1=_inc_vbuz1 + inc digit + // [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuz1_neq_vbuc1_then_la1 + lda #5 + cmp digit + bne b2_from_b2 + jmp b3 + // main::@3 + b3: + // [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1 + inc radix + // [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp radix + bne b1_from_b3 + jmp breturn + // main::@return + breturn: + // [14] return + rts +} + // File Data + RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) [ main::radix#4 main::digit#2 main::digit_value#0 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ] +Statement [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ) always clobbers reg byte a +Statement [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 [ main::radix#4 main::digit#2 ] ( main:2 [ main::radix#4 main::digit#2 ] ) always clobbers reg byte a +Statement [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) [ main::radix#4 main::digit#2 main::digit_value#0 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 ] ) always clobbers reg byte a +Statement [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ( main:2 [ main::radix#4 main::digit#2 main::digit_value#0 main::$2 ] ) always clobbers reg byte a +Statement [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 [ main::radix#4 main::digit#2 ] ( main:2 [ main::radix#4 main::digit#2 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y , +Potential registers zp ZP_WORD:4 [ main::digit_value#0 ] : zp ZP_WORD:4 , +Potential registers zp ZP_BYTE:6 [ main::$2 ] : zp ZP_BYTE:6 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 252.5: zp ZP_BYTE:3 [ main::digit#2 main::digit#1 ] 202: zp ZP_BYTE:6 [ main::$2 ] 101: zp ZP_WORD:4 [ main::digit_value#0 ] 19.64: zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +Uplift Scope [RadixInfo] +Uplift Scope [] + +Uplifting [main] best 5733 combination reg byte x [ main::digit#2 main::digit#1 ] reg byte a [ main::$2 ] zp ZP_WORD:4 [ main::digit_value#0 ] zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +Uplifting [RadixInfo] best 5733 combination +Uplifting [] best 5733 combination +Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +Uplifting [main] best 5733 combination zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +Allocated (was zp ZP_WORD:4) zp ZP_WORD:3 [ main::digit_value#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Illustrates a problem with pointer sizeof()-rewriting for pointers inside structs + // Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + .label SCREEN = $400 + .label digit_value = 3 + .label radix = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta radix + jmp b1 + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + // [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 + // main::@1 + b1: + // [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + // [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1 + ldx #0 + jmp b2 + // [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2] + b2_from_b2: + // [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy + jmp b2 + // main::@2 + b2: + // [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuxx + lda RADIX_DECIMAL_VALUES,x + sta digit_value + lda RADIX_DECIMAL_VALUES+1,x + sta digit_value+1 + // [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 + txa + asl + // [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuaa=vwuz1 + tay + lda digit_value + sta SCREEN,y + lda digit_value+1 + sta SCREEN+1,y + // [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuxx=_inc_vbuxx + inx + // [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuxx_neq_vbuc1_then_la1 + cpx #5 + bne b2_from_b2 + jmp b3 + // main::@3 + b3: + // [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1 + inc radix + // [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp radix + bne b1_from_b3 + jmp breturn + // main::@return + breturn: + // [14] return + rts +} + // File Data + RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label b2_from_b2 with b2 +Replacing label b1_from_b3 with b1 +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b3: +Removing instruction b2_from_b1: +Removing instruction b2_from_b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction b3: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp b1 +Removing instruction jmp b2 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(word[]) RADIX_DECIMAL_VALUES +(const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a } +(word*) RadixInfo::values +(void()) main() +(byte~) main::$2 reg byte a 202.0 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(word*) main::SCREEN +(const word*) main::SCREEN#0 SCREEN = (word*) 1024 +(byte) main::digit +(byte) main::digit#1 reg byte x 151.5 +(byte) main::digit#2 reg byte x 101.0 +(word) main::digit_value +(word) main::digit_value#0 digit_value zp ZP_WORD:3 101.0 +(word*) main::info_values +(byte) main::radix +(byte) main::radix#1 radix zp ZP_BYTE:2 16.5 +(byte) main::radix#4 radix zp ZP_BYTE:2 3.142857142857143 + +zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +reg byte x [ main::digit#2 main::digit#1 ] +zp ZP_WORD:3 [ main::digit_value#0 ] +reg byte a [ main::$2 ] + + +FINAL ASSEMBLER +Score: 4731 + + // File Comments +// Illustrates a problem with pointer sizeof()-rewriting for pointers inside structs + // Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [4] phi from @1 to main [phi:@1->main] + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .label SCREEN = $400 + .label digit_value = 3 + .label radix = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::radix#4 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta radix + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + // [5] phi (byte) main::radix#4 = (byte) main::radix#1 [phi:main::@3->main::@1#0] -- register_copy + // main::@1 + b1: + // [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + // [6] phi (byte) main::digit#2 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1 + ldx #0 + // [6] phi from main::@2 to main::@2 [phi:main::@2->main::@2] + // [6] phi (byte) main::digit#2 = (byte) main::digit#1 [phi:main::@2->main::@2#0] -- register_copy + // main::@2 + b2: + // digit_value = info.values[digit] + // [7] (word) main::digit_value#0 ← *((const word[]) RADIX_DECIMAL_VALUES#0 + (byte) main::digit#2) -- vwuz1=pwuc1_derefidx_vbuxx + lda RADIX_DECIMAL_VALUES,x + sta digit_value + lda RADIX_DECIMAL_VALUES+1,x + sta digit_value+1 + // SCREEN[digit] = digit_value + // [8] (byte~) main::$2 ← (byte) main::digit#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 + txa + asl + // [9] *((const word*) main::SCREEN#0 + (byte~) main::$2) ← (word) main::digit_value#0 -- pwuc1_derefidx_vbuaa=vwuz1 + tay + lda digit_value + sta SCREEN,y + lda digit_value+1 + sta SCREEN+1,y + // for( char digit: 0..4 ) + // [10] (byte) main::digit#1 ← ++ (byte) main::digit#2 -- vbuxx=_inc_vbuxx + inx + // [11] if((byte) main::digit#1!=(byte) 5) goto main::@2 -- vbuxx_neq_vbuc1_then_la1 + cpx #5 + bne b2 + // main::@3 + // for( byte radix: 0..1) + // [12] (byte) main::radix#1 ← ++ (byte) main::radix#4 -- vbuz1=_inc_vbuz1 + inc radix + // [13] if((byte) main::radix#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp radix + bne b1 + // main::@return + // } + // [14] return + rts +} + // File Data + RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a + diff --git a/src/test/ref/problem-pointer-inside-struct-sizeof-rewriting.sym b/src/test/ref/problem-pointer-inside-struct-sizeof-rewriting.sym new file mode 100644 index 000000000..00bd9e75a --- /dev/null +++ b/src/test/ref/problem-pointer-inside-struct-sizeof-rewriting.sym @@ -0,0 +1,28 @@ +(label) @1 +(label) @begin +(label) @end +(word[]) RADIX_DECIMAL_VALUES +(const word[]) RADIX_DECIMAL_VALUES#0 RADIX_DECIMAL_VALUES = { (word) $2710, (word) $3e8, (word) $64, (word) $a } +(word*) RadixInfo::values +(void()) main() +(byte~) main::$2 reg byte a 202.0 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(word*) main::SCREEN +(const word*) main::SCREEN#0 SCREEN = (word*) 1024 +(byte) main::digit +(byte) main::digit#1 reg byte x 151.5 +(byte) main::digit#2 reg byte x 101.0 +(word) main::digit_value +(word) main::digit_value#0 digit_value zp ZP_WORD:3 101.0 +(word*) main::info_values +(byte) main::radix +(byte) main::radix#1 radix zp ZP_BYTE:2 16.5 +(byte) main::radix#4 radix zp ZP_BYTE:2 3.142857142857143 + +zp ZP_BYTE:2 [ main::radix#4 main::radix#1 ] +reg byte x [ main::digit#2 main::digit#1 ] +zp ZP_WORD:3 [ main::digit_value#0 ] +reg byte a [ main::$2 ] diff --git a/src/test/ref/screen-center-angle.log b/src/test/ref/screen-center-angle.log index e0fb90661..2f4018d7d 100644 --- a/src/test/ref/screen-center-angle.log +++ b/src/test/ref/screen-center-angle.log @@ -3,6 +3,7 @@ Resolved forward reference FONT_HEX_PROTO to (byte[]) FONT_HEX_PROTO Fixing pointer addition (word*~) bsearch16u::$7 ← (word*) bsearch16u::items + (byte~) bsearch16u::$6 Fixing pointer addition (word*~) bsearch16u::$15 ← (word*) bsearch16u::pivot + (number) 1 Fixing pointer addition (word*~) bsearch16u::$1 ← (word*) bsearch16u::items - (number) 1 +Fixing pointer array-indexing *((word*) utoa::digit_values + (byte) utoa::digit) Fixing pointer array-indexing *((word[CORDIC_ITERATIONS_16]) CORDIC_ATAN2_ANGLES_16 + (byte) atan2_16::i) Fixing pointer array-indexing *((word[CORDIC_ITERATIONS_16]) CORDIC_ATAN2_ANGLES_16 + (byte) atan2_16::i) Warning! Adding boolean cast to non-boolean condition *((byte*) strcpy::src) @@ -20,10 +21,12 @@ Culled Empty Block (label) @4 Culled Empty Block (label) @5 Culled Empty Block (label) @6 Culled Empty Block (label) @7 +Culled Empty Block (label) @8 Culled Empty Block (label) @9 -Culled Empty Block (label) @10 Culled Empty Block (label) @11 Culled Empty Block (label) @12 +Culled Empty Block (label) @13 +Culled Empty Block (label) @14 Culled Empty Block (label) init_font_hex::@6 Culled Empty Block (label) atan2_16::@9 Culled Empty Block (label) atan2_16::@10 @@ -37,10 +40,8 @@ Culled Empty Block (label) atan2_16::@23 Culled Empty Block (label) atan2_16::@31 Culled Empty Block (label) atan2_16::@32 Culled Empty Block (label) atan2_16::@14 -Culled Empty Block (label) @14 -Culled Empty Block (label) clock::@1 Culled Empty Block (label) @16 -Culled Empty Block (label) @17 +Culled Empty Block (label) clock::@1 Culled Empty Block (label) @18 Culled Empty Block (label) @19 Culled Empty Block (label) @20 @@ -54,21 +55,23 @@ Culled Empty Block (label) @27 Culled Empty Block (label) @28 Culled Empty Block (label) @29 Culled Empty Block (label) @30 +Culled Empty Block (label) @31 Culled Empty Block (label) @32 -Culled Empty Block (label) @33 Culled Empty Block (label) @34 Culled Empty Block (label) @35 Culled Empty Block (label) @36 Culled Empty Block (label) @37 +Culled Empty Block (label) @38 +Culled Empty Block (label) @39 Culled Empty Block (label) main::toD0181_@1 Culled Empty Block (label) main::toD0182_@1 -Culled Empty Block (label) @39 +Culled Empty Block (label) @41 Culled Empty Block (label) init_angle_screen::@4 CONTROL FLOW GRAPH SSA @begin: scope:[] from - to:@8 -@8: scope:[] from @begin + to:@10 +@10: scope:[] from @begin (byte*) D018#0 ← ((byte*)) (number) $d018 (dword*) CIA2_TIMER_AB#0 ← ((dword*)) (number) $dd04 (byte*) CIA2_TIMER_A_CONTROL#0 ← ((byte*)) (number) $dd0e @@ -78,7 +81,7 @@ CONTROL FLOW GRAPH SSA (byte) CIA_TIMER_CONTROL_CONTINUOUS#0 ← (number) 0 (byte) CIA_TIMER_CONTROL_A_COUNT_CYCLES#0 ← (number) 0 (byte) CIA_TIMER_CONTROL_B_COUNT_UNDERFLOW_A#0 ← (number) $40 - to:@13 + to:@15 init_font_hex: scope:[init_font_hex] from main (byte*) init_font_hex::charset#6 ← phi( main/(byte*) init_font_hex::charset#1 ) (byte*) init_font_hex::proto_hi#0 ← (byte[]) FONT_HEX_PROTO#0 @@ -148,13 +151,13 @@ init_font_hex::@5: scope:[init_font_hex] from init_font_hex::@4 init_font_hex::@return: scope:[init_font_hex] from init_font_hex::@5 return to:@return -@13: scope:[] from @8 +@15: scope:[] from @10 (byte[]) FONT_HEX_PROTO#0 ← { (number) 2, (number) 5, (number) 5, (number) 5, (number) 2, (number) 6, (number) 2, (number) 2, (number) 2, (number) 7, (number) 6, (number) 1, (number) 2, (number) 4, (number) 7, (number) 6, (number) 1, (number) 2, (number) 1, (number) 6, (number) 5, (number) 5, (number) 7, (number) 1, (number) 1, (number) 7, (number) 4, (number) 6, (number) 1, (number) 6, (number) 3, (number) 4, (number) 6, (number) 5, (number) 2, (number) 7, (number) 1, (number) 1, (number) 1, (number) 1, (number) 2, (number) 5, (number) 2, (number) 5, (number) 2, (number) 2, (number) 5, (number) 3, (number) 1, (number) 1, (number) 2, (number) 5, (number) 7, (number) 5, (number) 5, (number) 6, (number) 5, (number) 6, (number) 5, (number) 6, (number) 2, (number) 5, (number) 4, (number) 5, (number) 2, (number) 6, (number) 5, (number) 5, (number) 5, (number) 6, (number) 7, (number) 4, (number) 6, (number) 4, (number) 7, (number) 7, (number) 4, (number) 6, (number) 4, (number) 4 } (byte) CORDIC_ITERATIONS_16#0 ← (number) $f (word[CORDIC_ITERATIONS_16#0]) CORDIC_ATAN2_ANGLES_16#0 ← kickasm {{ .for (var i=0; icircles - adc #0 sta ptr+1 + b1: ldy #OFFSET_STRUCT_CIRCLE_CENTER lda (ptr),y sta x tya clc - adc _16 - sta _16 - bcc !+ - inc _16+1 - !: + adc ptr + sta _14 + lda #0 + adc ptr+1 + sta _14+1 ldy #OFFSET_STRUCT_POINT_Y - lda (_16),y - sta y + lda (_14),y + tay lda x - ldy idx - sta SCREEN,y - iny - lda y - sta SCREEN,y - iny - sty idx + sta SCREEN,x inx - cpx #2 + tya + sta SCREEN,x + inx + lda #SIZEOF_STRUCT_CIRCLE + clc + adc ptr + sta ptr + bcc !+ + inc ptr+1 + !: + inc i + lda #2 + cmp i bne b1 rts } diff --git a/src/test/ref/struct-ptr-15.cfg b/src/test/ref/struct-ptr-15.cfg index e70ee730b..5bc7c569d 100644 --- a/src/test/ref/struct-ptr-15.cfg +++ b/src/test/ref/struct-ptr-15.cfg @@ -16,21 +16,20 @@ main: scope:[main] from @1 [9] *((byte*)(const struct Circle[2]) circles#0+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) $f to:main::@1 main::@1: scope:[main] from main main::@1 - [10] (byte) main::idx#3 ← phi( main/(byte) 0 main::@1/(byte) main::idx#2 ) [10] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) - [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 - [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 - [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 - [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) - [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) - [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 - [18] (byte) main::idx#1 ← ++ (byte) main::idx#3 - [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 - [20] (byte) main::idx#2 ← ++ (byte) main::idx#1 - [21] (byte) main::i#1 ← ++ (byte) main::i#2 - [22] if((byte) main::i#1!=(byte) 2) goto main::@1 + [10] (byte) main::idx#3 ← phi( main/(byte) 0 main::@1/(byte) main::idx#2 ) + [10] (struct Circle*) main::ptr#2 ← phi( main/(const struct Circle[2]) circles#0 main::@1/(struct Circle*) main::ptr#1 ) + [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) + [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) + [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 + [15] (byte) main::idx#1 ← ++ (byte) main::idx#3 + [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 + [17] (byte) main::idx#2 ← ++ (byte) main::idx#1 + [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE + [19] (byte) main::i#1 ← ++ (byte) main::i#2 + [20] if((byte) main::i#1!=(byte) 2) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [23] return + [21] return to:@return diff --git a/src/test/ref/struct-ptr-15.log b/src/test/ref/struct-ptr-15.log index 707391c04..6d4801924 100644 --- a/src/test/ref/struct-ptr-15.log +++ b/src/test/ref/struct-ptr-15.log @@ -1,24 +1,24 @@ -Fixing pointer addition (struct Circle*~) main::$0 ← (struct Circle[2]) circles + (byte) main::i +Fixing pointer increment (struct Circle*) main::ptr ← ++ (struct Circle*) main::ptr Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 0) Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 0) Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 0) Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 1) Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 1) Fixing pointer array-indexing *((struct Circle[2]) circles + (number) 1) -Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$3).center +Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$1).center +Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$2).center +Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$3).radius Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$4).center -Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$5).radius -Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$6).center -Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$7).center -Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$8).radius +Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$5).center +Rewriting struct pointer member access *((struct Circle[2]) circles + (number~) main::$6).radius Rewriting struct pointer member access *((struct Circle*) main::ptr).center Rewriting struct pointer member access *((struct Circle*) main::ptr).center -Rewriting struct pointer member access *((struct Point*) main::$9 + (number~) main::$3).x -Rewriting struct pointer member access *((struct Point*) main::$10 + (number~) main::$4).y -Rewriting struct pointer member access *((struct Point*) main::$12 + (number~) main::$6).x -Rewriting struct pointer member access *((struct Point*) main::$13 + (number~) main::$7).y -Rewriting struct pointer member access *((struct Point*) main::$15).x -Rewriting struct pointer member access *((struct Point*) main::$16).y +Rewriting struct pointer member access *((struct Point*) main::$7 + (number~) main::$1).x +Rewriting struct pointer member access *((struct Point*) main::$8 + (number~) main::$2).y +Rewriting struct pointer member access *((struct Point*) main::$10 + (number~) main::$4).x +Rewriting struct pointer member access *((struct Point*) main::$11 + (number~) main::$5).y +Rewriting struct pointer member access *((struct Point*) main::$13).x +Rewriting struct pointer member access *((struct Point*) main::$14).y Culled Empty Block (label) main::@2 CONTROL FLOW GRAPH SSA @@ -26,51 +26,51 @@ CONTROL FLOW GRAPH SSA (struct Circle[2]) circles#0 ← { fill( 2, 0) } to:@1 main: scope:[main] from @1 + (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE + (struct Point*) main::$7 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + (byte*) main::$15 ← (byte*)(struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X + *((byte*) main::$15 + (number~) main::$1) ← (number) 2 + (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE + (struct Point*) main::$8 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + (byte*) main::$16 ← (byte*)(struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*) main::$16 + (number~) main::$2) ← (number) 3 (number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE - (struct Point*) main::$9 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$17 ← (byte*)(struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_X - *((byte*) main::$17 + (number~) main::$3) ← (number) 2 - (number~) main::$4 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE + (byte*) main::$9 ← (byte*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS + *((byte*) main::$9 + (number~) main::$3) ← (number) 5 + (number~) main::$4 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE (struct Point*) main::$10 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$18 ← (byte*)(struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_Y - *((byte*) main::$18 + (number~) main::$4) ← (number) 3 - (number~) main::$5 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE - (byte*) main::$11 ← (byte*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS - *((byte*) main::$11 + (number~) main::$5) ← (number) 5 + (byte*) main::$17 ← (byte*)(struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X + *((byte*) main::$17 + (number~) main::$4) ← (number) 8 + (number~) main::$5 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE + (struct Point*) main::$11 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + (byte*) main::$18 ← (byte*)(struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*) main::$18 + (number~) main::$5) ← (number) 9 (number~) main::$6 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE - (struct Point*) main::$12 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$19 ← (byte*)(struct Point*) main::$12 + (const byte) OFFSET_STRUCT_POINT_X - *((byte*) main::$19 + (number~) main::$6) ← (number) 8 - (number~) main::$7 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE - (struct Point*) main::$13 ← (struct Point*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$20 ← (byte*)(struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_Y - *((byte*) main::$20 + (number~) main::$7) ← (number) 9 - (number~) main::$8 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE - (byte*) main::$14 ← (byte*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS - *((byte*) main::$14 + (number~) main::$8) ← (number) $f + (byte*) main::$12 ← (byte*)(struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS + *((byte*) main::$12 + (number~) main::$6) ← (number) $f (byte*) main::SCREEN#0 ← ((byte*)) (number) $400 (byte) main::idx#0 ← (number) 0 + (struct Circle*) main::ptr#0 ← (struct Circle[2]) circles#0 (byte) main::i#0 ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@1 - (byte) main::idx#3 ← phi( main/(byte) main::idx#0 main::@1/(byte) main::idx#2 ) (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 ) - (byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_CIRCLE - (struct Circle*~) main::$0 ← (struct Circle[2]) circles#0 + (byte~) main::$2 - (struct Circle*) main::ptr#0 ← (struct Circle*~) main::$0 - (struct Point*) main::$15 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$21 ← (byte*)(struct Point*) main::$15 + (const byte) OFFSET_STRUCT_POINT_X - (byte) main::x#0 ← *((byte*) main::$21) - (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - (byte*) main::$22 ← (byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y - (byte) main::y#0 ← *((byte*) main::$22) + (byte) main::idx#3 ← phi( main/(byte) main::idx#0 main::@1/(byte) main::idx#2 ) + (struct Circle*) main::ptr#2 ← phi( main/(struct Circle*) main::ptr#0 main::@1/(struct Circle*) main::ptr#1 ) + (struct Point*) main::$13 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + (byte*) main::$19 ← (byte*)(struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_X + (byte) main::x#0 ← *((byte*) main::$19) + (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + (byte*) main::$20 ← (byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y + (byte) main::y#0 ← *((byte*) main::$20) *((byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 (byte) main::idx#1 ← ++ (byte) main::idx#3 *((byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 (byte) main::idx#2 ← ++ (byte) main::idx#1 + (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,1) - (bool~) main::$1 ← (byte) main::i#1 != rangelast(0,1) - if((bool~) main::$1) goto main::@1 + (bool~) main::$0 ← (byte) main::i#1 != rangelast(0,1) + if((bool~) main::$0) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 return @@ -99,29 +99,27 @@ SYMBOL TABLE SSA (struct Circle[2]) circles (struct Circle[2]) circles#0 (void()) main() -(struct Circle*~) main::$0 -(bool~) main::$1 +(bool~) main::$0 +(number~) main::$1 (struct Point*) main::$10 -(byte*) main::$11 -(struct Point*) main::$12 +(struct Point*) main::$11 +(byte*) main::$12 (struct Point*) main::$13 -(byte*) main::$14 -(struct Point*) main::$15 -(struct Point*) main::$16 +(struct Point*) main::$14 +(byte*) main::$15 +(byte*) main::$16 (byte*) main::$17 (byte*) main::$18 (byte*) main::$19 -(byte~) main::$2 +(number~) main::$2 (byte*) main::$20 -(byte*) main::$21 -(byte*) main::$22 (number~) main::$3 (number~) main::$4 (number~) main::$5 (number~) main::$6 -(number~) main::$7 -(number~) main::$8 -(struct Point*) main::$9 +(struct Point*) main::$7 +(struct Point*) main::$8 +(byte*) main::$9 (label) main::@1 (label) main::@return (byte*) main::SCREEN @@ -137,37 +135,39 @@ SYMBOL TABLE SSA (byte) main::idx#3 (struct Circle*) main::ptr (struct Circle*) main::ptr#0 +(struct Circle*) main::ptr#1 +(struct Circle*) main::ptr#2 (byte) main::x (byte) main::x#0 (byte) main::y (byte) main::y#0 +Adding number conversion cast (unumber) 0 in (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) main::$1 in (number~) main::$1 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) 2 in *((byte*) main::$15 + (unumber~) main::$1) ← (number) 2 +Adding number conversion cast (unumber) 0 in (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) main::$2 in (number~) main::$2 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) 3 in *((byte*) main::$16 + (unumber~) main::$2) ← (number) 3 Adding number conversion cast (unumber) 0 in (number~) main::$3 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE Adding number conversion cast (unumber) main::$3 in (number~) main::$3 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) 2 in *((byte*) main::$17 + (unumber~) main::$3) ← (number) 2 -Adding number conversion cast (unumber) 0 in (number~) main::$4 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) main::$4 in (number~) main::$4 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) 3 in *((byte*) main::$18 + (unumber~) main::$4) ← (number) 3 -Adding number conversion cast (unumber) 0 in (number~) main::$5 ← (number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) main::$5 in (number~) main::$5 ← (unumber)(number) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) 5 in *((byte*) main::$11 + (unumber~) main::$5) ← (number) 5 +Adding number conversion cast (unumber) 5 in *((byte*) main::$9 + (unumber~) main::$3) ← (number) 5 +Adding number conversion cast (unumber) 1 in (number~) main::$4 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) main::$4 in (number~) main::$4 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) 8 in *((byte*) main::$17 + (unumber~) main::$4) ← (number) 8 +Adding number conversion cast (unumber) 1 in (number~) main::$5 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) main::$5 in (number~) main::$5 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Adding number conversion cast (unumber) 9 in *((byte*) main::$18 + (unumber~) main::$5) ← (number) 9 Adding number conversion cast (unumber) 1 in (number~) main::$6 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE Adding number conversion cast (unumber) main::$6 in (number~) main::$6 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) 8 in *((byte*) main::$19 + (unumber~) main::$6) ← (number) 8 -Adding number conversion cast (unumber) 1 in (number~) main::$7 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) main::$7 in (number~) main::$7 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) 9 in *((byte*) main::$20 + (unumber~) main::$7) ← (number) 9 -Adding number conversion cast (unumber) 1 in (number~) main::$8 ← (number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) main::$8 in (number~) main::$8 ← (unumber)(number) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Adding number conversion cast (unumber) $f in *((byte*) main::$14 + (unumber~) main::$8) ← (number) $f +Adding number conversion cast (unumber) $f in *((byte*) main::$12 + (unumber~) main::$6) ← (number) $f Adding number conversion cast (unumber) 0 in (byte) main::idx#0 ← (number) 0 Successful SSA optimization PassNAddNumberTypeConversions -Inlining cast *((byte*) main::$17 + (unumber~) main::$3) ← (unumber)(number) 2 -Inlining cast *((byte*) main::$18 + (unumber~) main::$4) ← (unumber)(number) 3 -Inlining cast *((byte*) main::$11 + (unumber~) main::$5) ← (unumber)(number) 5 -Inlining cast *((byte*) main::$19 + (unumber~) main::$6) ← (unumber)(number) 8 -Inlining cast *((byte*) main::$20 + (unumber~) main::$7) ← (unumber)(number) 9 -Inlining cast *((byte*) main::$14 + (unumber~) main::$8) ← (unumber)(number) $f +Inlining cast *((byte*) main::$15 + (unumber~) main::$1) ← (unumber)(number) 2 +Inlining cast *((byte*) main::$16 + (unumber~) main::$2) ← (unumber)(number) 3 +Inlining cast *((byte*) main::$9 + (unumber~) main::$3) ← (unumber)(number) 5 +Inlining cast *((byte*) main::$17 + (unumber~) main::$4) ← (unumber)(number) 8 +Inlining cast *((byte*) main::$18 + (unumber~) main::$5) ← (unumber)(number) 9 +Inlining cast *((byte*) main::$12 + (unumber~) main::$6) ← (unumber)(number) $f Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400 Inlining cast (byte) main::idx#0 ← (unumber)(number) 0 Successful SSA optimization Pass2InlineCast @@ -200,66 +200,66 @@ Finalized unsigned number type (byte) 1 Finalized unsigned number type (byte) $f Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Inferred type updated to byte in (unumber~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE Inferred type updated to byte in (unumber~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Inferred type updated to byte in (unumber~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Inferred type updated to byte in (unumber~) main::$5 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Inferred type updated to byte in (unumber~) main::$4 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Inferred type updated to byte in (unumber~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE Inferred type updated to byte in (unumber~) main::$6 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Inferred type updated to byte in (unumber~) main::$7 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Inferred type updated to byte in (unumber~) main::$8 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Alias (struct Circle*) main::ptr#0 = (struct Circle*~) main::$0 -Successful SSA optimization Pass2AliasElimination -Simple Condition (bool~) main::$1 [42] if((byte) main::i#1!=rangelast(0,1)) goto main::@1 +Simple Condition (bool~) main::$0 [41] if((byte) main::i#1!=rangelast(0,1)) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification Constant right-side identified [0] (struct Circle[2]) circles#0 ← { fill( 2, 0) } -Constant right-side identified [1] (byte~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Constant right-side identified [5] (byte~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Constant right-side identified [9] (byte~) main::$5 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE -Constant right-side identified [12] (byte~) main::$6 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Constant right-side identified [16] (byte~) main::$7 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE -Constant right-side identified [20] (byte~) main::$8 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [1] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [5] (byte~) main::$2 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [9] (byte~) main::$3 ← (byte) 0 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [12] (byte~) main::$4 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [16] (byte~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE +Constant right-side identified [20] (byte~) main::$6 ← (byte) 1 * (const byte) SIZEOF_STRUCT_CIRCLE Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const struct Circle[2]) circles#0 = { fill( 2, 0) } +Constant (const byte) main::$1 = 0*SIZEOF_STRUCT_CIRCLE +Constant (const byte) main::$2 = 0*SIZEOF_STRUCT_CIRCLE Constant (const byte) main::$3 = 0*SIZEOF_STRUCT_CIRCLE -Constant (const byte) main::$4 = 0*SIZEOF_STRUCT_CIRCLE -Constant (const byte) main::$5 = 0*SIZEOF_STRUCT_CIRCLE +Constant (const byte) main::$4 = 1*SIZEOF_STRUCT_CIRCLE +Constant (const byte) main::$5 = 1*SIZEOF_STRUCT_CIRCLE Constant (const byte) main::$6 = 1*SIZEOF_STRUCT_CIRCLE -Constant (const byte) main::$7 = 1*SIZEOF_STRUCT_CIRCLE -Constant (const byte) main::$8 = 1*SIZEOF_STRUCT_CIRCLE Constant (const byte*) main::SCREEN#0 = (byte*) 1024 Constant (const byte) main::idx#0 = 0 Constant (const byte) main::i#0 = 0 Successful SSA optimization Pass2ConstantIdentification -Constant value identified (struct Point*)circles#0 in [2] (struct Point*) main::$9 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant value identified (struct Point*)circles#0 in [6] (struct Point*) main::$10 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant value identified (byte*)circles#0 in [10] (byte*) main::$11 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS -Constant value identified (struct Point*)circles#0 in [13] (struct Point*) main::$12 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant value identified (struct Point*)circles#0 in [17] (struct Point*) main::$13 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant value identified (byte*)circles#0 in [21] (byte*) main::$14 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS +Constant (const struct Circle*) main::ptr#0 = circles#0 +Successful SSA optimization Pass2ConstantIdentification +Constant value identified (struct Point*)circles#0 in [2] (struct Point*) main::$7 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant value identified (struct Point*)circles#0 in [6] (struct Point*) main::$8 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant value identified (byte*)circles#0 in [10] (byte*) main::$9 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS +Constant value identified (struct Point*)circles#0 in [13] (struct Point*) main::$10 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant value identified (struct Point*)circles#0 in [17] (struct Point*) main::$11 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant value identified (byte*)circles#0 in [21] (byte*) main::$12 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS Successful SSA optimization Pass2ConstantValues -Resolved ranged next value [40] main::i#1 ← ++ main::i#2 to ++ -Resolved ranged comparison value [42] if(main::i#1!=rangelast(0,1)) goto main::@1 to (number) 2 -Converting *(pointer+n) to pointer[n] [32] (byte) main::x#0 ← *((byte*) main::$21) -- *((byte*)main::$15 + OFFSET_STRUCT_POINT_X) -Converting *(pointer+n) to pointer[n] [35] (byte) main::y#0 ← *((byte*) main::$22) -- *((byte*)main::$16 + OFFSET_STRUCT_POINT_Y) +Resolved ranged next value [39] main::i#1 ← ++ main::i#2 to ++ +Resolved ranged comparison value [41] if(main::i#1!=rangelast(0,1)) goto main::@1 to (number) 2 +Converting *(pointer+n) to pointer[n] [30] (byte) main::x#0 ← *((byte*) main::$19) -- *((byte*)main::$13 + OFFSET_STRUCT_POINT_X) +Converting *(pointer+n) to pointer[n] [33] (byte) main::y#0 ← *((byte*) main::$20) -- *((byte*)main::$14 + OFFSET_STRUCT_POINT_Y) Successful SSA optimization Pass2InlineDerefIdx Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_CIRCLE in Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_CIRCLE in Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_CIRCLE in Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero (byte*)main::$9 in [3] (byte*) main::$17 ← (byte*)(struct Point*) main::$9 + (const byte) OFFSET_STRUCT_POINT_X -Simplifying expression containing zero main::$17 in [4] *((byte*) main::$17 + (const byte) main::$3) ← (byte) 2 -Simplifying expression containing zero main::$18 in [8] *((byte*) main::$18 + (const byte) main::$4) ← (byte) 3 -Simplifying expression containing zero (byte*)circles#0 in [10] (byte*) main::$11 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS -Simplifying expression containing zero main::$11 in [11] *((byte*) main::$11 + (const byte) main::$5) ← (byte) 5 -Simplifying expression containing zero (byte*)main::$12 in [14] (byte*) main::$19 ← (byte*)(struct Point*) main::$12 + (const byte) OFFSET_STRUCT_POINT_X -Simplifying expression containing zero (byte*)circles#0 in [21] (byte*) main::$14 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS -Simplifying expression containing zero (byte*)main::$15 in [31] (byte*) main::$21 ← (byte*)(struct Point*) main::$15 + (const byte) OFFSET_STRUCT_POINT_X -Simplifying expression containing zero (byte*)main::$15 in [32] (byte) main::x#0 ← *((byte*)(struct Point*) main::$15 + (const byte) OFFSET_STRUCT_POINT_X) +Simplifying expression containing zero (byte*)main::$7 in [3] (byte*) main::$15 ← (byte*)(struct Point*) main::$7 + (const byte) OFFSET_STRUCT_POINT_X +Simplifying expression containing zero main::$15 in [4] *((byte*) main::$15 + (const byte) main::$1) ← (byte) 2 +Simplifying expression containing zero main::$16 in [8] *((byte*) main::$16 + (const byte) main::$2) ← (byte) 3 +Simplifying expression containing zero (byte*)circles#0 in [10] (byte*) main::$9 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS +Simplifying expression containing zero main::$9 in [11] *((byte*) main::$9 + (const byte) main::$3) ← (byte) 5 +Simplifying expression containing zero (byte*)main::$10 in [14] (byte*) main::$17 ← (byte*)(struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_X +Simplifying expression containing zero (byte*)circles#0 in [21] (byte*) main::$12 ← (byte*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_RADIUS +Simplifying expression containing zero (byte*)main::$13 in [29] (byte*) main::$19 ← (byte*)(struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_X +Simplifying expression containing zero (byte*)main::$13 in [30] (byte) main::x#0 ← *((byte*)(struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_X) Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte*) main::$21 and assignment [20] (byte*) main::$21 ← (byte*)(struct Point*) main::$15 -Eliminating unused variable (byte*) main::$22 and assignment [23] (byte*) main::$22 ← (byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y +Eliminating unused variable (byte*) main::$19 and assignment [18] (byte*) main::$19 ← (byte*)(struct Point*) main::$13 +Eliminating unused variable (byte*) main::$20 and assignment [21] (byte*) main::$20 ← (byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y +Eliminating unused constant (const byte) main::$1 +Eliminating unused constant (const byte) main::$2 Eliminating unused constant (const byte) main::$3 -Eliminating unused constant (const byte) main::$4 -Eliminating unused constant (const byte) main::$5 Eliminating unused constant (const byte) OFFSET_STRUCT_CIRCLE_RADIUS Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars @@ -269,60 +269,59 @@ Simplifying constant integer cast 2 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 2 Successful SSA optimization PassNFinalizeNumberTypeConversions -Constant right-side identified [0] (struct Point*) main::$9 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant right-side identified [3] (struct Point*) main::$10 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant right-side identified [8] (struct Point*) main::$12 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant right-side identified [11] (struct Point*) main::$13 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant right-side identified [0] (struct Point*) main::$7 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant right-side identified [3] (struct Point*) main::$8 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant right-side identified [8] (struct Point*) main::$10 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant right-side identified [11] (struct Point*) main::$11 ← (struct Point*)(const struct Circle[2]) circles#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const struct Point*) main::$9 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER +Constant (const struct Point*) main::$7 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER +Constant (const struct Point*) main::$8 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER +Constant (const byte*) main::$9 = (byte*)circles#0 Constant (const struct Point*) main::$10 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER -Constant (const byte*) main::$11 = (byte*)circles#0 -Constant (const struct Point*) main::$12 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER -Constant (const struct Point*) main::$13 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER -Constant (const byte*) main::$14 = (byte*)circles#0 +Constant (const struct Point*) main::$11 = (struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER +Constant (const byte*) main::$12 = (byte*)circles#0 Successful SSA optimization Pass2ConstantIdentification -Constant value identified (byte*)main::$9 in [1] (byte*) main::$17 ← (byte*)(const struct Point*) main::$9 -Constant value identified (byte*)main::$10 in [4] (byte*) main::$18 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_Y -Constant value identified (byte*)main::$12 in [9] (byte*) main::$19 ← (byte*)(const struct Point*) main::$12 -Constant value identified (byte*)main::$13 in [12] (byte*) main::$20 ← (byte*)(const struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_Y +Constant value identified (byte*)main::$7 in [1] (byte*) main::$15 ← (byte*)(const struct Point*) main::$7 +Constant value identified (byte*)main::$8 in [4] (byte*) main::$16 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_Y +Constant value identified (byte*)main::$10 in [9] (byte*) main::$17 ← (byte*)(const struct Point*) main::$10 +Constant value identified (byte*)main::$11 in [12] (byte*) main::$18 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y Successful SSA optimization Pass2ConstantValues -Converting *(pointer+n) to pointer[n] [5] *((byte*) main::$18) ← (byte) 3 -- *((byte*)main::$10 + OFFSET_STRUCT_POINT_Y) -Converting *(pointer+n) to pointer[n] [20] (byte) main::x#0 ← *((byte*)(struct Point*) main::$15) -- *((byte*)(struct Point*)main::ptr#0 + OFFSET_STRUCT_CIRCLE_CENTER) +Converting *(pointer+n) to pointer[n] [5] *((byte*) main::$16) ← (byte) 3 -- *((byte*)main::$8 + OFFSET_STRUCT_POINT_Y) +Converting *(pointer+n) to pointer[n] [18] (byte) main::x#0 ← *((byte*)(struct Point*) main::$13) -- *((byte*)(struct Point*)main::ptr#2 + OFFSET_STRUCT_CIRCLE_CENTER) Successful SSA optimization Pass2InlineDerefIdx -Eliminating unused variable (byte*) main::$18 and assignment [2] (byte*) main::$18 ← (byte*)(const struct Point*) main::$10 + (const byte) OFFSET_STRUCT_POINT_Y -Eliminating unused variable (struct Point*) main::$15 and assignment [13] (struct Point*) main::$15 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER +Eliminating unused variable (byte*) main::$16 and assignment [2] (byte*) main::$16 ← (byte*)(const struct Point*) main::$8 + (const byte) OFFSET_STRUCT_POINT_Y +Eliminating unused variable (struct Point*) main::$13 and assignment [11] (struct Point*) main::$13 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER Successful SSA optimization PassNEliminateUnusedVars -Constant right-side identified [6] (byte*) main::$20 ← (byte*)(const struct Point*) main::$13 + (const byte) OFFSET_STRUCT_POINT_Y +Constant right-side identified [6] (byte*) main::$18 ← (byte*)(const struct Point*) main::$11 + (const byte) OFFSET_STRUCT_POINT_Y Successful SSA optimization Pass2ConstantRValueConsolidation -Constant (const byte*) main::$17 = (byte*)main::$9 -Constant (const byte*) main::$19 = (byte*)main::$12 -Constant (const byte*) main::$20 = (byte*)main::$13+OFFSET_STRUCT_POINT_Y +Constant (const byte*) main::$15 = (byte*)main::$7 +Constant (const byte*) main::$17 = (byte*)main::$10 +Constant (const byte*) main::$18 = (byte*)main::$11+OFFSET_STRUCT_POINT_Y Successful SSA optimization Pass2ConstantIdentification -Rewriting multiplication to use shift and addition[7] (byte~) main::$2 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_CIRCLE Inlining constant with var siblings (const byte) main::idx#0 Inlining constant with var siblings (const byte) main::i#0 -Constant inlined main::$12 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant inlined main::$13 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant inlined main::$14 = (byte*)(const struct Circle[2]) circles#0 -Constant inlined main::$20 = (byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(const byte) OFFSET_STRUCT_POINT_Y +Inlining constant with var siblings (const struct Circle*) main::ptr#0 +Constant inlined main::$12 = (byte*)(const struct Circle[2]) circles#0 +Constant inlined main::ptr#0 = (const struct Circle[2]) circles#0 +Constant inlined main::$15 = (byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER Constant inlined main::$10 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant inlined main::$11 = (byte*)(const struct Circle[2]) circles#0 +Constant inlined main::$11 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER Constant inlined main::idx#0 = (byte) 0 Constant inlined main::$17 = (byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant inlined main::$19 = (byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant inlined main::$18 = (byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(const byte) OFFSET_STRUCT_POINT_Y +Constant inlined main::$5 = (byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE Constant inlined main::i#0 = (byte) 0 Constant inlined main::$6 = (byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE -Constant inlined main::$9 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER -Constant inlined main::$7 = (byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE -Constant inlined main::$8 = (byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE +Constant inlined main::$4 = (byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE +Constant inlined main::$9 = (byte*)(const struct Circle[2]) circles#0 +Constant inlined main::$7 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER +Constant inlined main::$8 = (struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER Successful SSA optimization Pass2ConstantInlining Consolidated array index constant in *((byte*)(struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER+OFFSET_STRUCT_POINT_Y) Consolidated array index constant in *((byte*)(struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER+1*SIZEOF_STRUCT_CIRCLE) Consolidated array index constant in *((byte*)(struct Point*)circles#0+OFFSET_STRUCT_CIRCLE_CENTER+OFFSET_STRUCT_POINT_Y+1*SIZEOF_STRUCT_CIRCLE) Consolidated array index constant in *((byte*)circles#0+1*SIZEOF_STRUCT_CIRCLE) Successful SSA optimization Pass2ConstantAdditionElimination -Alias (byte~) main::$2 = (byte) main::$24 -Successful SSA optimization Pass2AliasElimination Added new block during phi lifting main::@3(between main::@1 and main::@1) Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 @@ -331,10 +330,11 @@ Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 -Created 2 initial phi equivalence classes +Created 3 initial phi equivalence classes +Coalesced [23] main::ptr#3 ← main::ptr#1 +Coalesced [24] main::idx#4 ← main::idx#2 Coalesced [25] main::i#3 ← main::i#1 -Coalesced [26] main::idx#4 ← main::idx#2 -Coalesced down to 2 phi equivalence classes +Coalesced down to 3 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) main::@3 Adding NOP phi() at start of @begin @@ -360,23 +360,22 @@ main: scope:[main] from @1 [9] *((byte*)(const struct Circle[2]) circles#0+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) $f to:main::@1 main::@1: scope:[main] from main main::@1 - [10] (byte) main::idx#3 ← phi( main/(byte) 0 main::@1/(byte) main::idx#2 ) [10] (byte) main::i#2 ← phi( main/(byte) 0 main::@1/(byte) main::i#1 ) - [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 - [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 - [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 - [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) - [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER - [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) - [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 - [18] (byte) main::idx#1 ← ++ (byte) main::idx#3 - [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 - [20] (byte) main::idx#2 ← ++ (byte) main::idx#1 - [21] (byte) main::i#1 ← ++ (byte) main::i#2 - [22] if((byte) main::i#1!=(byte) 2) goto main::@1 + [10] (byte) main::idx#3 ← phi( main/(byte) 0 main::@1/(byte) main::idx#2 ) + [10] (struct Circle*) main::ptr#2 ← phi( main/(const struct Circle[2]) circles#0 main::@1/(struct Circle*) main::ptr#1 ) + [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) + [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER + [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) + [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 + [15] (byte) main::idx#1 ← ++ (byte) main::idx#3 + [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 + [17] (byte) main::idx#2 ← ++ (byte) main::idx#1 + [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE + [19] (byte) main::i#1 ← ++ (byte) main::i#2 + [20] if((byte) main::i#1!=(byte) 2) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [23] return + [21] return to:@return @@ -387,53 +386,46 @@ VARIABLE REGISTER WEIGHTS (byte) Point::y (struct Circle[2]) circles (void()) main() -(struct Point*) main::$16 11.0 -(byte~) main::$2 22.0 -(byte) main::$23 22.0 +(struct Point*) main::$14 11.0 (byte*) main::SCREEN (byte) main::i (byte) main::i#1 16.5 -(byte) main::i#2 4.0 +(byte) main::i#2 2.4444444444444446 (byte) main::idx (byte) main::idx#1 16.5 -(byte) main::idx#2 7.333333333333333 -(byte) main::idx#3 4.125 +(byte) main::idx#2 5.5 +(byte) main::idx#3 6.6000000000000005 (struct Circle*) main::ptr -(struct Circle*) main::ptr#0 5.5 +(struct Circle*) main::ptr#1 7.333333333333333 +(struct Circle*) main::ptr#2 2.75 (byte) main::x (byte) main::x#0 7.333333333333333 (byte) main::y (byte) main::y#0 7.333333333333333 Initial phi equivalence classes -[ main::i#2 main::i#1 ] +[ main::ptr#2 main::ptr#1 ] [ main::idx#3 main::idx#2 ] -Added variable main::$23 to zero page equivalence class [ main::$23 ] -Added variable main::$2 to zero page equivalence class [ main::$2 ] -Added variable main::ptr#0 to zero page equivalence class [ main::ptr#0 ] +[ main::i#2 main::i#1 ] Added variable main::x#0 to zero page equivalence class [ main::x#0 ] -Added variable main::$16 to zero page equivalence class [ main::$16 ] +Added variable main::$14 to zero page equivalence class [ main::$14 ] Added variable main::y#0 to zero page equivalence class [ main::y#0 ] Added variable main::idx#1 to zero page equivalence class [ main::idx#1 ] Complete equivalence classes -[ main::i#2 main::i#1 ] +[ main::ptr#2 main::ptr#1 ] [ main::idx#3 main::idx#2 ] -[ main::$23 ] -[ main::$2 ] -[ main::ptr#0 ] +[ main::i#2 main::i#1 ] [ main::x#0 ] -[ main::$16 ] +[ main::$14 ] [ main::y#0 ] [ main::idx#1 ] -Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Allocated zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] -Allocated zp ZP_BYTE:4 [ main::$23 ] -Allocated zp ZP_BYTE:5 [ main::$2 ] -Allocated zp ZP_WORD:6 [ main::ptr#0 ] -Allocated zp ZP_BYTE:8 [ main::x#0 ] -Allocated zp ZP_WORD:9 [ main::$16 ] -Allocated zp ZP_BYTE:11 [ main::y#0 ] -Allocated zp ZP_BYTE:12 [ main::idx#1 ] +Allocated zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] +Allocated zp ZP_BYTE:4 [ main::idx#3 main::idx#2 ] +Allocated zp ZP_BYTE:5 [ main::i#2 main::i#1 ] +Allocated zp ZP_BYTE:6 [ main::x#0 ] +Allocated zp ZP_WORD:7 [ main::$14 ] +Allocated zp ZP_BYTE:9 [ main::y#0 ] +Allocated zp ZP_BYTE:10 [ main::idx#1 ] INITIAL ASM // File Comments @@ -463,16 +455,14 @@ bend: // main main: { .label SCREEN = $400 - .label _2 = 5 - .label _16 = 9 - .label ptr = 6 - .label x = 8 - .label y = $b - .label idx = $c - .label idx_2 = 3 - .label i = 2 - .label idx_3 = 3 - .label _23 = 4 + .label _14 = 7 + .label x = 6 + .label y = 9 + .label idx = $a + .label idx_2 = 4 + .label ptr = 2 + .label i = 5 + .label idx_3 = 4 // [4] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER) ← (byte) 2 -- _deref_pbuc1=vbuc2 lda #2 sta circles+OFFSET_STRUCT_CIRCLE_CENTER @@ -493,79 +483,76 @@ main: { sta circles+1*SIZEOF_STRUCT_CIRCLE // [10] phi from main to main::@1 [phi:main->main::@1] b1_from_main: - // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 - lda #0 - sta idx_3 - // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 sta i + // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta idx_3 + // [10] phi (struct Circle*) main::ptr#2 = (const struct Circle[2]) circles#0 [phi:main->main::@1#2] -- pssz1=pssc1 + lda #circles + sta ptr+1 jmp b1 // [10] phi from main::@1 to main::@1 [phi:main::@1->main::@1] b1_from_b1: - // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#0] -- register_copy - // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#1] -- register_copy + // [10] phi (struct Circle*) main::ptr#2 = (struct Circle*) main::ptr#1 [phi:main::@1->main::@1#2] -- register_copy jmp b1 // main::@1 b1: - // [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 -- vbuz1=vbuz2_rol_1 - lda i - asl - sta _23 - // [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 -- vbuz1=vbuz2_plus_vbuz3 - lda _23 - clc - adc i - sta _2 - // [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 -- pssz1=pssc1_plus_vbuz2 - lda _2 - clc - adc #circles - adc #0 - sta ptr+1 - // [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 + // [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 ldy #OFFSET_STRUCT_CIRCLE_CENTER lda (ptr),y sta x - // [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz2_plus_vbuc1 + // [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz2_plus_vbuc1 lda #OFFSET_STRUCT_CIRCLE_CENTER clc adc ptr - sta _16 + sta _14 lda #0 adc ptr+1 - sta _16+1 - // [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=pbuz2_derefidx_vbuc1 + sta _14+1 + // [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=pbuz2_derefidx_vbuc1 ldy #OFFSET_STRUCT_POINT_Y - lda (_16),y + lda (_14),y sta y - // [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + // [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuz1=vbuz2 lda x ldy idx_3 sta SCREEN,y - // [18] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuz1=_inc_vbuz2 + // [15] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuz1=_inc_vbuz2 ldy idx_3 iny sty idx - // [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuz1=vbuz2 + // [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuz1=vbuz2 lda y ldy idx sta SCREEN,y - // [20] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuz2 + // [17] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuz2 ldy idx iny sty idx_2 - // [21] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + // [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE -- pssz1=pssz1_plus_vbuc1 + lda #SIZEOF_STRUCT_CIRCLE + clc + adc ptr + sta ptr + bcc !+ + inc ptr+1 + !: + // [19] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 inc i - // [22] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [20] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #2 cmp i bne b1_from_b1 jmp breturn // main::@return breturn: - // [23] return + // [21] return rts } // File Data @@ -578,68 +565,57 @@ Statement [6] *((byte*)(const struct Circle[2]) circles#0) ← (byte) 5 [ ] ( ma Statement [7] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) 8 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [8] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(const byte) OFFSET_STRUCT_POINT_Y+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) 9 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [9] *((byte*)(const struct Circle[2]) circles#0+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) $f [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::idx#3 main::$23 ] ( main:2 [ main::i#2 main::idx#3 main::$23 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] -Statement [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 [ main::i#2 main::idx#3 main::$2 ] ( main:2 [ main::i#2 main::idx#3 main::$2 ] ) always clobbers reg byte a -Statement [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 [ main::i#2 main::idx#3 main::ptr#0 ] ( main:2 [ main::i#2 main::idx#3 main::ptr#0 ] ) always clobbers reg byte a -Statement [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) [ main::i#2 main::idx#3 main::ptr#0 main::x#0 ] ( main:2 [ main::i#2 main::idx#3 main::ptr#0 main::x#0 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ] -Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] -Statement [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER [ main::i#2 main::idx#3 main::x#0 main::$16 ] ( main:2 [ main::i#2 main::idx#3 main::x#0 main::$16 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:8 [ main::x#0 ] -Statement [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) [ main::i#2 main::idx#3 main::x#0 main::y#0 ] ( main:2 [ main::i#2 main::idx#3 main::x#0 main::y#0 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte y as potential for zp ZP_BYTE:8 [ main::x#0 ] -Statement [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 [ main::i#2 main::idx#3 main::y#0 ] ( main:2 [ main::i#2 main::idx#3 main::y#0 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:11 [ main::y#0 ] -Statement [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 [ main::i#2 main::idx#1 ] ( main:2 [ main::i#2 main::idx#1 ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp ZP_BYTE:12 [ main::idx#1 ] +Statement [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) [ main::ptr#2 main::idx#3 main::i#2 main::x#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ main::idx#3 main::idx#2 ] +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:4 [ main::idx#3 main::idx#2 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:5 [ main::i#2 main::i#1 ] +Statement [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::$14 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::$14 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ main::x#0 ] +Statement [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::y#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::y#0 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:6 [ main::x#0 ] +Statement [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 [ main::ptr#2 main::idx#3 main::i#2 main::y#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::y#0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ main::y#0 ] +Statement [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 [ main::ptr#2 main::i#2 main::idx#1 ] ( main:2 [ main::ptr#2 main::i#2 main::idx#1 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:10 [ main::idx#1 ] +Statement [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE [ main::i#2 main::ptr#1 main::idx#2 ] ( main:2 [ main::i#2 main::ptr#1 main::idx#2 ] ) always clobbers reg byte a Statement [4] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER) ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [6] *((byte*)(const struct Circle[2]) circles#0) ← (byte) 5 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) 8 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [8] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER+(const byte) OFFSET_STRUCT_POINT_Y+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) 9 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [9] *((byte*)(const struct Circle[2]) circles#0+(byte) 1*(const byte) SIZEOF_STRUCT_CIRCLE) ← (byte) $f [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::idx#3 main::$23 ] ( main:2 [ main::i#2 main::idx#3 main::$23 ] ) always clobbers reg byte a -Statement [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 [ main::i#2 main::idx#3 main::$2 ] ( main:2 [ main::i#2 main::idx#3 main::$2 ] ) always clobbers reg byte a -Statement [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 [ main::i#2 main::idx#3 main::ptr#0 ] ( main:2 [ main::i#2 main::idx#3 main::ptr#0 ] ) always clobbers reg byte a -Statement [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) [ main::i#2 main::idx#3 main::ptr#0 main::x#0 ] ( main:2 [ main::i#2 main::idx#3 main::ptr#0 main::x#0 ] ) always clobbers reg byte a reg byte y -Statement [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER [ main::i#2 main::idx#3 main::x#0 main::$16 ] ( main:2 [ main::i#2 main::idx#3 main::x#0 main::$16 ] ) always clobbers reg byte a -Statement [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) [ main::i#2 main::idx#3 main::x#0 main::y#0 ] ( main:2 [ main::i#2 main::idx#3 main::x#0 main::y#0 ] ) always clobbers reg byte a reg byte y -Statement [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 [ main::i#2 main::idx#3 main::y#0 ] ( main:2 [ main::i#2 main::idx#3 main::y#0 ] ) always clobbers reg byte a -Statement [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 [ main::i#2 main::idx#1 ] ( main:2 [ main::i#2 main::idx#1 ] ) always clobbers reg byte a -Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , -Potential registers zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] : zp ZP_BYTE:3 , reg byte x , -Potential registers zp ZP_BYTE:4 [ main::$23 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , -Potential registers zp ZP_BYTE:5 [ main::$2 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , -Potential registers zp ZP_WORD:6 [ main::ptr#0 ] : zp ZP_WORD:6 , -Potential registers zp ZP_BYTE:8 [ main::x#0 ] : zp ZP_BYTE:8 , reg byte x , -Potential registers zp ZP_WORD:9 [ main::$16 ] : zp ZP_WORD:9 , -Potential registers zp ZP_BYTE:11 [ main::y#0 ] : zp ZP_BYTE:11 , reg byte x , reg byte y , -Potential registers zp ZP_BYTE:12 [ main::idx#1 ] : zp ZP_BYTE:12 , reg byte x , reg byte y , +Statement [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) [ main::ptr#2 main::idx#3 main::i#2 main::x#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 ] ) always clobbers reg byte a reg byte y +Statement [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::$14 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::$14 ] ) always clobbers reg byte a +Statement [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::y#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::x#0 main::y#0 ] ) always clobbers reg byte a reg byte y +Statement [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 [ main::ptr#2 main::idx#3 main::i#2 main::y#0 ] ( main:2 [ main::ptr#2 main::idx#3 main::i#2 main::y#0 ] ) always clobbers reg byte a +Statement [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 [ main::ptr#2 main::i#2 main::idx#1 ] ( main:2 [ main::ptr#2 main::i#2 main::idx#1 ] ) always clobbers reg byte a +Statement [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE [ main::i#2 main::ptr#1 main::idx#2 ] ( main:2 [ main::i#2 main::ptr#1 main::idx#2 ] ) always clobbers reg byte a +Potential registers zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] : zp ZP_WORD:2 , +Potential registers zp ZP_BYTE:4 [ main::idx#3 main::idx#2 ] : zp ZP_BYTE:4 , reg byte x , +Potential registers zp ZP_BYTE:5 [ main::i#2 main::i#1 ] : zp ZP_BYTE:5 , reg byte x , +Potential registers zp ZP_BYTE:6 [ main::x#0 ] : zp ZP_BYTE:6 , reg byte x , +Potential registers zp ZP_WORD:7 [ main::$14 ] : zp ZP_WORD:7 , +Potential registers zp ZP_BYTE:9 [ main::y#0 ] : zp ZP_BYTE:9 , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:10 [ main::idx#1 ] : zp ZP_BYTE:10 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] 22: zp ZP_BYTE:4 [ main::$23 ] 22: zp ZP_BYTE:5 [ main::$2 ] 20.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 16.5: zp ZP_BYTE:12 [ main::idx#1 ] 11.46: zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] 11: zp ZP_WORD:9 [ main::$16 ] 7.33: zp ZP_BYTE:8 [ main::x#0 ] 7.33: zp ZP_BYTE:11 [ main::y#0 ] 5.5: zp ZP_WORD:6 [ main::ptr#0 ] +Uplift Scope [main] 18.94: zp ZP_BYTE:5 [ main::i#2 main::i#1 ] 16.5: zp ZP_BYTE:10 [ main::idx#1 ] 12.1: zp ZP_BYTE:4 [ main::idx#3 main::idx#2 ] 11: zp ZP_WORD:7 [ main::$14 ] 10.08: zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] 7.33: zp ZP_BYTE:6 [ main::x#0 ] 7.33: zp ZP_BYTE:9 [ main::y#0 ] Uplift Scope [Point] Uplift Scope [Circle] Uplift Scope [] -Uplifting [main] best 1219 combination reg byte a [ main::$23 ] reg byte a [ main::$2 ] reg byte x [ main::i#2 main::i#1 ] reg byte y [ main::idx#1 ] zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] zp ZP_WORD:9 [ main::$16 ] zp ZP_BYTE:8 [ main::x#0 ] zp ZP_BYTE:11 [ main::y#0 ] zp ZP_WORD:6 [ main::ptr#0 ] -Limited combination testing to 100 combinations of 1152 possible. -Uplifting [Point] best 1219 combination -Uplifting [Circle] best 1219 combination -Uplifting [] best 1219 combination -Attempting to uplift remaining variables inzp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] -Uplifting [main] best 1219 combination zp ZP_BYTE:3 [ main::idx#3 main::idx#2 ] -Attempting to uplift remaining variables inzp ZP_BYTE:8 [ main::x#0 ] -Uplifting [main] best 1219 combination zp ZP_BYTE:8 [ main::x#0 ] -Attempting to uplift remaining variables inzp ZP_BYTE:11 [ main::y#0 ] -Uplifting [main] best 1219 combination zp ZP_BYTE:11 [ main::y#0 ] -Coalescing zero page register with common assignment [ zp ZP_WORD:6 [ main::ptr#0 ] ] with [ zp ZP_WORD:9 [ main::$16 ] ] - score: 1 -Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ main::idx#3 main::idx#2 ] -Allocated (was zp ZP_WORD:6) zp ZP_WORD:3 [ main::ptr#0 main::$16 ] -Allocated (was zp ZP_BYTE:8) zp ZP_BYTE:5 [ main::x#0 ] -Allocated (was zp ZP_BYTE:11) zp ZP_BYTE:6 [ main::y#0 ] +Uplifting [main] best 1184 combination zp ZP_BYTE:5 [ main::i#2 main::i#1 ] reg byte x [ main::idx#1 ] reg byte x [ main::idx#3 main::idx#2 ] zp ZP_WORD:7 [ main::$14 ] zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] zp ZP_BYTE:6 [ main::x#0 ] reg byte y [ main::y#0 ] +Uplifting [Point] best 1184 combination +Uplifting [Circle] best 1184 combination +Uplifting [] best 1184 combination +Attempting to uplift remaining variables inzp ZP_BYTE:5 [ main::i#2 main::i#1 ] +Uplifting [main] best 1184 combination zp ZP_BYTE:5 [ main::i#2 main::i#1 ] +Attempting to uplift remaining variables inzp ZP_BYTE:6 [ main::x#0 ] +Uplifting [main] best 1184 combination zp ZP_BYTE:6 [ main::x#0 ] +Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ main::i#2 main::i#1 ] +Allocated (was zp ZP_BYTE:6) zp ZP_BYTE:5 [ main::x#0 ] +Allocated (was zp ZP_WORD:7) zp ZP_WORD:6 [ main::$14 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -669,11 +645,10 @@ bend: // main main: { .label SCREEN = $400 - .label _16 = 3 - .label ptr = 3 + .label _14 = 6 .label x = 5 - .label y = 6 - .label idx = 2 + .label ptr = 2 + .label i = 4 // [4] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER) ← (byte) 2 -- _deref_pbuc1=vbuc2 lda #2 sta circles+OFFSET_STRUCT_CIRCLE_CENTER @@ -694,71 +669,69 @@ main: { sta circles+1*SIZEOF_STRUCT_CIRCLE // [10] phi from main to main::@1 [phi:main->main::@1] b1_from_main: - // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 - sta idx - // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + sta i + // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 ldx #0 + // [10] phi (struct Circle*) main::ptr#2 = (const struct Circle[2]) circles#0 [phi:main->main::@1#2] -- pssz1=pssc1 + lda #circles + sta ptr+1 jmp b1 // [10] phi from main::@1 to main::@1 [phi:main::@1->main::@1] b1_from_b1: - // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#0] -- register_copy - // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy + // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#1] -- register_copy + // [10] phi (struct Circle*) main::ptr#2 = (struct Circle*) main::ptr#1 [phi:main::@1->main::@1#2] -- register_copy jmp b1 // main::@1 b1: - // [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 - txa - asl - // [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuxx - stx $ff - clc - adc $ff - // [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 -- pssz1=pssc1_plus_vbuaa - clc - adc #circles - adc #0 - sta ptr+1 - // [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 + // [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 ldy #OFFSET_STRUCT_CIRCLE_CENTER lda (ptr),y sta x - // [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz1_plus_vbuc1 + // [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz2_plus_vbuc1 lda #OFFSET_STRUCT_CIRCLE_CENTER clc - adc _16 - sta _16 - bcc !+ - inc _16+1 - !: - // [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=pbuz2_derefidx_vbuc1 + adc ptr + sta _14 + lda #0 + adc ptr+1 + sta _14+1 + // [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=pbuz1_derefidx_vbuc1 ldy #OFFSET_STRUCT_POINT_Y - lda (_16),y - sta y - // [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + lda (_14),y + tay + // [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuxx=vbuz1 lda x - ldy idx - sta SCREEN,y - // [18] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuyy=_inc_vbuz1 - ldy idx - iny - // [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuyy=vbuz1 - lda y - sta SCREEN,y - // [20] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuyy - iny - sty idx - // [21] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + sta SCREEN,x + // [15] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuxx=_inc_vbuxx inx - // [22] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #2 + // [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta SCREEN,x + // [17] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuxx=_inc_vbuxx + inx + // [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE -- pssz1=pssz1_plus_vbuc1 + lda #SIZEOF_STRUCT_CIRCLE + clc + adc ptr + sta ptr + bcc !+ + inc ptr+1 + !: + // [19] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc i + // [20] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp i bne b1_from_b1 jmp breturn // main::@return breturn: - // [23] return + // [21] return rts } // File Data @@ -772,8 +745,6 @@ Removing instruction jmp breturn Succesful ASM optimization Pass5NextJumpElimination Replacing instruction ldx #0 with TAX Replacing instruction lda #OFFSET_STRUCT_CIRCLE_CENTER with TYA -Removing instruction ldy idx -Succesful ASM optimization Pass5UnnecesaryLoadElimination Replacing label b1_from_b1 with b1 Removing instruction b1_from_bbegin: Removing instruction b1: @@ -806,35 +777,33 @@ FINAL SYMBOL TABLE (struct Circle[2]) circles (const struct Circle[2]) circles#0 circles = { fill( 2, 0) } (void()) main() -(struct Point*) main::$16 $16 zp ZP_WORD:3 11.0 -(byte~) main::$2 reg byte a 22.0 -(byte) main::$23 reg byte a 22.0 +(struct Point*) main::$14 $14 zp ZP_WORD:6 11.0 (label) main::@1 (label) main::@return (byte*) main::SCREEN (const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 (byte) main::i -(byte) main::i#1 reg byte x 16.5 -(byte) main::i#2 reg byte x 4.0 +(byte) main::i#1 i zp ZP_BYTE:4 16.5 +(byte) main::i#2 i zp ZP_BYTE:4 2.4444444444444446 (byte) main::idx -(byte) main::idx#1 reg byte y 16.5 -(byte) main::idx#2 idx zp ZP_BYTE:2 7.333333333333333 -(byte) main::idx#3 idx zp ZP_BYTE:2 4.125 +(byte) main::idx#1 reg byte x 16.5 +(byte) main::idx#2 reg byte x 5.5 +(byte) main::idx#3 reg byte x 6.6000000000000005 (struct Circle*) main::ptr -(struct Circle*) main::ptr#0 ptr zp ZP_WORD:3 5.5 +(struct Circle*) main::ptr#1 ptr zp ZP_WORD:2 7.333333333333333 +(struct Circle*) main::ptr#2 ptr zp ZP_WORD:2 2.75 (byte) main::x (byte) main::x#0 x zp ZP_BYTE:5 7.333333333333333 (byte) main::y -(byte) main::y#0 y zp ZP_BYTE:6 7.333333333333333 +(byte) main::y#0 reg byte y 7.333333333333333 -reg byte x [ main::i#2 main::i#1 ] -zp ZP_BYTE:2 [ main::idx#3 main::idx#2 ] -reg byte a [ main::$23 ] -reg byte a [ main::$2 ] -zp ZP_WORD:3 [ main::ptr#0 main::$16 ] +zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] +reg byte x [ main::idx#3 main::idx#2 ] +zp ZP_BYTE:4 [ main::i#2 main::i#1 ] zp ZP_BYTE:5 [ main::x#0 ] -zp ZP_BYTE:6 [ main::y#0 ] -reg byte y [ main::idx#1 ] +zp ZP_WORD:6 [ main::$14 ] +reg byte y [ main::y#0 ] +reg byte x [ main::idx#1 ] FINAL ASSEMBLER @@ -859,11 +828,10 @@ Score: 1082 // main main: { .label SCREEN = $400 - .label _16 = 3 - .label ptr = 3 + .label _14 = 6 .label x = 5 - .label y = 6 - .label idx = 2 + .label ptr = 2 + .label i = 4 // circles[0].center.x = 2 // [4] *((byte*)(struct Point*)(const struct Circle[2]) circles#0+(const byte) OFFSET_STRUCT_CIRCLE_CENTER) ← (byte) 2 -- _deref_pbuc1=vbuc2 lda #2 @@ -889,75 +857,73 @@ main: { lda #$f sta circles+1*SIZEOF_STRUCT_CIRCLE // [10] phi from main to main::@1 [phi:main->main::@1] - // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 lda #0 - sta idx - // [10] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 + sta i + // [10] phi (byte) main::idx#3 = (byte) 0 [phi:main->main::@1#1] -- vbuxx=vbuc1 tax - // [10] phi from main::@1 to main::@1 [phi:main::@1->main::@1] - // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#0] -- register_copy - // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy - // main::@1 - b1: - // circles+i - // [11] (byte) main::$23 ← (byte) main::i#2 << (byte) 1 -- vbuaa=vbuxx_rol_1 - txa - asl - // [12] (byte~) main::$2 ← (byte) main::$23 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuxx - stx $ff - clc - adc $ff - // ptr = circles+i - // [13] (struct Circle*) main::ptr#0 ← (const struct Circle[2]) circles#0 + (byte~) main::$2 -- pssz1=pssc1_plus_vbuaa - clc - adc #main::@1#2] -- pssz1=pssc1 + lda #circles - adc #0 sta ptr+1 + // [10] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [10] phi (byte) main::idx#3 = (byte) main::idx#2 [phi:main::@1->main::@1#1] -- register_copy + // [10] phi (struct Circle*) main::ptr#2 = (struct Circle*) main::ptr#1 [phi:main::@1->main::@1#2] -- register_copy + // main::@1 + b1: // x = ptr->center.x - // [14] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 + // [11] (byte) main::x#0 ← *((byte*)(struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER) -- vbuz1=pbuz2_derefidx_vbuc1 ldy #OFFSET_STRUCT_CIRCLE_CENTER lda (ptr),y sta x // y = ptr->center.y - // [15] (struct Point*) main::$16 ← (struct Point*)(struct Circle*) main::ptr#0 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz1_plus_vbuc1 + // [12] (struct Point*) main::$14 ← (struct Point*)(struct Circle*) main::ptr#2 + (const byte) OFFSET_STRUCT_CIRCLE_CENTER -- pssz1=pssz2_plus_vbuc1 tya clc - adc _16 - sta _16 - bcc !+ - inc _16+1 - !: - // [16] (byte) main::y#0 ← *((byte*)(struct Point*) main::$16 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=pbuz2_derefidx_vbuc1 + adc ptr + sta _14 + lda #0 + adc ptr+1 + sta _14+1 + // [13] (byte) main::y#0 ← *((byte*)(struct Point*) main::$14 + (const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=pbuz1_derefidx_vbuc1 ldy #OFFSET_STRUCT_POINT_Y - lda (_16),y - sta y + lda (_14),y + tay // SCREEN[idx++] = x - // [17] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + // [14] *((const byte*) main::SCREEN#0 + (byte) main::idx#3) ← (byte) main::x#0 -- pbuc1_derefidx_vbuxx=vbuz1 lda x - ldy idx - sta SCREEN,y + sta SCREEN,x // SCREEN[idx++] = x; - // [18] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuyy=_inc_vbuz1 - iny - // SCREEN[idx++] = y - // [19] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuyy=vbuz1 - lda y - sta SCREEN,y - // SCREEN[idx++] = y; - // [20] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuyy - iny - sty idx - // for(byte i:0..1) - // [21] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + // [15] (byte) main::idx#1 ← ++ (byte) main::idx#3 -- vbuxx=_inc_vbuxx inx - // [22] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 - cpx #2 + // SCREEN[idx++] = y + // [16] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte) main::y#0 -- pbuc1_derefidx_vbuxx=vbuyy + tya + sta SCREEN,x + // SCREEN[idx++] = y; + // [17] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuxx=_inc_vbuxx + inx + // ptr++; + // [18] (struct Circle*) main::ptr#1 ← (struct Circle*) main::ptr#2 + (const byte) SIZEOF_STRUCT_CIRCLE -- pssz1=pssz1_plus_vbuc1 + lda #SIZEOF_STRUCT_CIRCLE + clc + adc ptr + sta ptr + bcc !+ + inc ptr+1 + !: + // for(byte i:0..1) + // [19] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc i + // [20] if((byte) main::i#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp i bne b1 // main::@return // } - // [23] return + // [21] return rts } // File Data diff --git a/src/test/ref/struct-ptr-15.sym b/src/test/ref/struct-ptr-15.sym index f86a29e23..5a0352f60 100644 --- a/src/test/ref/struct-ptr-15.sym +++ b/src/test/ref/struct-ptr-15.sym @@ -11,32 +11,30 @@ (struct Circle[2]) circles (const struct Circle[2]) circles#0 circles = { fill( 2, 0) } (void()) main() -(struct Point*) main::$16 $16 zp ZP_WORD:3 11.0 -(byte~) main::$2 reg byte a 22.0 -(byte) main::$23 reg byte a 22.0 +(struct Point*) main::$14 $14 zp ZP_WORD:6 11.0 (label) main::@1 (label) main::@return (byte*) main::SCREEN (const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 (byte) main::i -(byte) main::i#1 reg byte x 16.5 -(byte) main::i#2 reg byte x 4.0 +(byte) main::i#1 i zp ZP_BYTE:4 16.5 +(byte) main::i#2 i zp ZP_BYTE:4 2.4444444444444446 (byte) main::idx -(byte) main::idx#1 reg byte y 16.5 -(byte) main::idx#2 idx zp ZP_BYTE:2 7.333333333333333 -(byte) main::idx#3 idx zp ZP_BYTE:2 4.125 +(byte) main::idx#1 reg byte x 16.5 +(byte) main::idx#2 reg byte x 5.5 +(byte) main::idx#3 reg byte x 6.6000000000000005 (struct Circle*) main::ptr -(struct Circle*) main::ptr#0 ptr zp ZP_WORD:3 5.5 +(struct Circle*) main::ptr#1 ptr zp ZP_WORD:2 7.333333333333333 +(struct Circle*) main::ptr#2 ptr zp ZP_WORD:2 2.75 (byte) main::x (byte) main::x#0 x zp ZP_BYTE:5 7.333333333333333 (byte) main::y -(byte) main::y#0 y zp ZP_BYTE:6 7.333333333333333 +(byte) main::y#0 reg byte y 7.333333333333333 -reg byte x [ main::i#2 main::i#1 ] -zp ZP_BYTE:2 [ main::idx#3 main::idx#2 ] -reg byte a [ main::$23 ] -reg byte a [ main::$2 ] -zp ZP_WORD:3 [ main::ptr#0 main::$16 ] +zp ZP_WORD:2 [ main::ptr#2 main::ptr#1 ] +reg byte x [ main::idx#3 main::idx#2 ] +zp ZP_BYTE:4 [ main::i#2 main::i#1 ] zp ZP_BYTE:5 [ main::x#0 ] -zp ZP_BYTE:6 [ main::y#0 ] -reg byte y [ main::idx#1 ] +zp ZP_WORD:6 [ main::$14 ] +reg byte y [ main::y#0 ] +reg byte x [ main::idx#1 ]