From d40ff86b03067791b4f03d9bfe6c218d85d7923e Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sat, 6 Jun 2020 08:48:00 +0200 Subject: [PATCH] Added a const parenthesis test. #470 --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/const-parenthesis.c | 13 + src/test/ref/const-parenthesis.asm | 19 ++ src/test/ref/const-parenthesis.cfg | 18 ++ src/test/ref/const-parenthesis.log | 268 ++++++++++++++++++ src/test/ref/const-parenthesis.sym | 8 + 6 files changed, 331 insertions(+) create mode 100644 src/test/kc/const-parenthesis.c create mode 100644 src/test/ref/const-parenthesis.asm create mode 100644 src/test/ref/const-parenthesis.cfg create mode 100644 src/test/ref/const-parenthesis.log create mode 100644 src/test/ref/const-parenthesis.sym diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 9111b960c..33e39f2e2 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -42,6 +42,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testConstParenthesis() throws IOException, URISyntaxException { + compileAndCompare("const-parenthesis.c"); + } + @Test public void testGlobalLabelProblem() throws IOException, URISyntaxException { compileAndCompare("global-label-problem.c"); diff --git a/src/test/kc/const-parenthesis.c b/src/test/kc/const-parenthesis.c new file mode 100644 index 000000000..3a8590f72 --- /dev/null +++ b/src/test/kc/const-parenthesis.c @@ -0,0 +1,13 @@ +// Test parenthesising of constants +// See https://gitlab.com/camelot/kickc/-/issues/470#note_356486132 + +char * const SCREEN = 0x0400; + +void main() { + const char dy = 128; + // A parenthesis should be added in the ASM to ensure operator precedence + SCREEN[0] = (dy-1)/16; + // No parenthesis should be added in the ASM because minus (-) has higher precedence than shift (>>) + SCREEN[1] = (dy-1)>>4; +} + diff --git a/src/test/ref/const-parenthesis.asm b/src/test/ref/const-parenthesis.asm new file mode 100644 index 000000000..3b1dfa363 --- /dev/null +++ b/src/test/ref/const-parenthesis.asm @@ -0,0 +1,19 @@ +// Test parenthesising of constants +// See https://gitlab.com/camelot/kickc/-/issues/470#note_356486132 +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label SCREEN = $400 +main: { + .const dy = $80 + // SCREEN[0] = (dy-1)/16 + // A parenthesis should be added in the ASM to ensure operator precedence + lda #(dy-1)/$10 + sta SCREEN + // SCREEN[1] = (dy-1)>>4 + // No parenthesis should be added in the ASM because minus (-) has higher precedence than shift (>>) + lda #dy-1>>4 + sta SCREEN+1 + // } + rts +} diff --git a/src/test/ref/const-parenthesis.cfg b/src/test/ref/const-parenthesis.cfg new file mode 100644 index 000000000..2391efe22 --- /dev/null +++ b/src/test/ref/const-parenthesis.cfg @@ -0,0 +1,18 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 + [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return diff --git a/src/test/ref/const-parenthesis.log b/src/test/ref/const-parenthesis.log new file mode 100644 index 000000000..e1861e14d --- /dev/null +++ b/src/test/ref/const-parenthesis.log @@ -0,0 +1,268 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + *((const nomodify byte*) SCREEN + (number) 0) ← (const nomodify byte) main::dy-(number) 1/(number) $10 + *((const nomodify byte*) SCREEN + (number) 1) ← (const nomodify byte) main::dy-(number) 1>>(number) 4 + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*)(number) $400 +(void()) main() +(label) main::@return +(const nomodify byte) main::dy = (byte) $80 + +Adding number conversion cast (unumber) main::dy-1/$10 in *((const nomodify byte*) SCREEN + (number) 0) ← (const nomodify byte) main::dy-(number) 1/(number) $10 +Adding number conversion cast (unumber) 1 in *((const nomodify byte*) SCREEN + (number) 0) ← ((unumber)) (const nomodify byte) main::dy-(number) 1/(number) $10 +Adding number conversion cast (unumber) 0 in *((const nomodify byte*) SCREEN + (number) 0) ← ((unumber)) (const nomodify byte) main::dy-(unumber)(number) 1/(number) $10 +Adding number conversion cast (unumber) main::dy-1>>4 in *((const nomodify byte*) SCREEN + (number) 1) ← (const nomodify byte) main::dy-(number) 1>>(number) 4 +Adding number conversion cast (unumber) 1 in *((const nomodify byte*) SCREEN + (number) 1) ← ((unumber)) (const nomodify byte) main::dy-(number) 1>>(number) 4 +Adding number conversion cast (unumber) 1 in *((const nomodify byte*) SCREEN + (number) 1) ← ((unumber)) (const nomodify byte) main::dy-(unumber)(number) 1>>(number) 4 +Successful SSA optimization PassNAddNumberTypeConversions +Adding number conversion cast (unumber) $10 in *((const nomodify byte*) SCREEN + (unumber)(number) 0) ← ((unumber)) (const nomodify byte) main::dy-(unumber)(number) 1/(number) $10 +Adding number conversion cast (unumber) 4 in *((const nomodify byte*) SCREEN + (unumber)(number) 1) ← ((unumber)) (const nomodify byte) main::dy-(unumber)(number) 1>>(number) 4 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast *((const nomodify byte*) SCREEN + (unumber)(number) 0) ← (unumber)(const nomodify byte) main::dy-(unumber)(number) 1/(unumber)(number) $10 +Inlining cast *((const nomodify byte*) SCREEN + (unumber)(number) 1) ← (unumber)(const nomodify byte) main::dy-(unumber)(number) 1>>(unumber)(number) 4 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast (const nomodify byte) main::dy-(unumber)(number) 1/(unumber)(number) $10 +Simplifying constant integer cast 1 +Simplifying constant integer cast $10 +Simplifying constant integer cast 0 +Simplifying constant integer cast (const nomodify byte) main::dy-(unumber)(number) 1>>(unumber)(number) 4 +Simplifying constant integer cast 1 +Simplifying constant integer cast 4 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) $10 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Simplifying expression containing zero SCREEN in [0] *((const nomodify byte*) SCREEN + (byte) 0) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 +Successful SSA optimization PassNSimplifyExpressionWithZero +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 + [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test parenthesising of constants +// See https://gitlab.com/camelot/kickc/-/issues/470#note_356486132 + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const dy = $80 + // [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 -- _deref_pbuc1=vbuc2 + // A parenthesis should be added in the ASM to ensure operator precedence + lda #(dy-1)/$10 + sta SCREEN + // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 -- _deref_pbuc1=vbuc2 + // No parenthesis should be added in the ASM because minus (-) has higher precedence than shift (>>) + lda #dy-1>>4 + sta SCREEN+1 + jmp __breturn + // main::@return + __breturn: + // [6] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 [ ] ( main:2 [ ] { } ) always clobbers reg byte a +Statement [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 [ ] ( main:2 [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 33 combination +Uplifting [] best 33 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test parenthesising of constants +// See https://gitlab.com/camelot/kickc/-/issues/470#note_356486132 + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .const dy = $80 + // [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 -- _deref_pbuc1=vbuc2 + // A parenthesis should be added in the ASM to ensure operator precedence + lda #(dy-1)/$10 + sta SCREEN + // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 -- _deref_pbuc1=vbuc2 + // No parenthesis should be added in the ASM because minus (-) has higher precedence than shift (>>) + lda #dy-1>>4 + sta SCREEN+1 + jmp __breturn + // main::@return + __breturn: + // [6] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1_from___bbegin: +Removing instruction __b1: +Removing instruction __bend_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bbegin: +Removing instruction __bend: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 1024 +(void()) main() +(label) main::@return +(const nomodify byte) main::dy = (byte) $80 + + + +FINAL ASSEMBLER +Score: 18 + + // File Comments +// Test parenthesising of constants +// See https://gitlab.com/camelot/kickc/-/issues/470#note_356486132 + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .const dy = $80 + // SCREEN[0] = (dy-1)/16 + // [4] *((const nomodify byte*) SCREEN) ← (const nomodify byte) main::dy-(byte) 1/(byte) $10 -- _deref_pbuc1=vbuc2 + // A parenthesis should be added in the ASM to ensure operator precedence + lda #(dy-1)/$10 + sta SCREEN + // SCREEN[1] = (dy-1)>>4 + // [5] *((const nomodify byte*) SCREEN+(byte) 1) ← (const nomodify byte) main::dy-(byte) 1>>(byte) 4 -- _deref_pbuc1=vbuc2 + // No parenthesis should be added in the ASM because minus (-) has higher precedence than shift (>>) + lda #dy-1>>4 + sta SCREEN+1 + // main::@return + // } + // [6] return + rts +} + // File Data + diff --git a/src/test/ref/const-parenthesis.sym b/src/test/ref/const-parenthesis.sym new file mode 100644 index 000000000..b3facfd15 --- /dev/null +++ b/src/test/ref/const-parenthesis.sym @@ -0,0 +1,8 @@ +(label) @1 +(label) @begin +(label) @end +(const nomodify byte*) SCREEN = (byte*) 1024 +(void()) main() +(label) main::@return +(const nomodify byte) main::dy = (byte) $80 +