From 2b1bc3c11df9bd57f7ebd77fffc805cddabf256f Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 23 Apr 2023 16:00:52 +0200 Subject: [PATCH] Increased complexity of examples. Fixed A-clobber problems. --- .../call_phi_close_cx16_ram.asm | 6 +- .../call_phi_close_cx16_rom.asm | 6 +- .../kickc/test/TestProgramsFast.java | 5 + src/test/kc/call-banked-phi-case-1-near-0.c | 1 + src/test/kc/call-banked-phi-case-1-near-1.c | 5 +- src/test/kc/call-banked-phi-case-2-close-0.c | 4 +- src/test/kc/call-banked-phi-case-2-close-1.c | 9 +- src/test/kc/call-banked-phi-case-3-near-0.c | 6 +- src/test/kc/call-banked-phi-case-3-near-1.c | 5 +- src/test/kc/call-banked-phi-case-4-near-0.c | 6 +- src/test/kc/call-banked-phi-case-4-near-1.c | 8 +- src/test/kc/call-banked-phi-case-5-far-0.c | 5 +- src/test/kc/call-banked-phi-case-5-far-1.c | 8 +- src/test/kc/call-banked-phi-case-6-close-0.c | 5 +- src/test/kc/call-banked-phi-case-6-close-1.c | 8 +- .../banking/cx16-banking-recursive-near.c | 38 -- .../kc/examples/cx16/banking/cx16-banking.c | 1 + .../ref/call-banked-phi-case-1-near-0.asm | 22 +- .../ref/call-banked-phi-case-1-near-0.cfg | 22 +- .../ref/call-banked-phi-case-1-near-0.log | 259 ++++++--- .../ref/call-banked-phi-case-1-near-0.sym | 17 +- .../ref/call-banked-phi-case-1-near-1.asm | 31 +- .../ref/call-banked-phi-case-1-near-1.cfg | 43 +- .../ref/call-banked-phi-case-1-near-1.log | 467 +++++++++++----- .../ref/call-banked-phi-case-1-near-1.sym | 33 +- .../ref/call-banked-phi-case-2-close-0.asm | 39 +- .../ref/call-banked-phi-case-2-close-0.cfg | 22 +- .../ref/call-banked-phi-case-2-close-0.log | 300 +++++++--- .../ref/call-banked-phi-case-2-close-0.sym | 17 +- .../ref/call-banked-phi-case-2-close-1.asm | 39 +- .../ref/call-banked-phi-case-2-close-1.cfg | 22 +- .../ref/call-banked-phi-case-2-close-1.log | 300 +++++++--- .../ref/call-banked-phi-case-2-close-1.sym | 17 +- .../ref/call-banked-phi-case-3-near-0.asm | 49 +- .../ref/call-banked-phi-case-3-near-0.cfg | 43 +- .../ref/call-banked-phi-case-3-near-0.log | 507 ++++++++++++----- .../ref/call-banked-phi-case-3-near-0.sym | 33 +- .../ref/call-banked-phi-case-3-near-1.asm | 49 +- .../ref/call-banked-phi-case-3-near-1.cfg | 43 +- .../ref/call-banked-phi-case-3-near-1.log | 507 ++++++++++++----- .../ref/call-banked-phi-case-3-near-1.sym | 33 +- .../ref/call-banked-phi-case-4-near-0.asm | 49 +- .../ref/call-banked-phi-case-4-near-0.cfg | 43 +- .../ref/call-banked-phi-case-4-near-0.log | 507 ++++++++++++----- .../ref/call-banked-phi-case-4-near-0.sym | 33 +- .../ref/call-banked-phi-case-4-near-1.asm | 49 +- .../ref/call-banked-phi-case-4-near-1.cfg | 43 +- .../ref/call-banked-phi-case-4-near-1.log | 507 ++++++++++++----- .../ref/call-banked-phi-case-4-near-1.sym | 33 +- src/test/ref/call-banked-phi-case-5-far-0.asm | 51 +- src/test/ref/call-banked-phi-case-5-far-0.cfg | 43 +- src/test/ref/call-banked-phi-case-5-far-0.log | 511 +++++++++++------ src/test/ref/call-banked-phi-case-5-far-0.sym | 33 +- src/test/ref/call-banked-phi-case-5-far-1.asm | 51 +- src/test/ref/call-banked-phi-case-5-far-1.cfg | 43 +- src/test/ref/call-banked-phi-case-5-far-1.log | 511 +++++++++++------ src/test/ref/call-banked-phi-case-5-far-1.sym | 33 +- .../ref/call-banked-phi-case-6-close-0.asm | 55 +- .../ref/call-banked-phi-case-6-close-0.cfg | 43 +- .../ref/call-banked-phi-case-6-close-0.log | 523 +++++++++++++----- .../ref/call-banked-phi-case-6-close-0.sym | 33 +- .../ref/call-banked-phi-case-6-close-1.asm | 55 +- .../ref/call-banked-phi-case-6-close-1.cfg | 43 +- .../ref/call-banked-phi-case-6-close-1.log | 523 +++++++++++++----- .../ref/call-banked-phi-case-6-close-1.sym | 33 +- 65 files changed, 4923 insertions(+), 1965 deletions(-) delete mode 100644 src/test/kc/examples/cx16/banking/cx16-banking-recursive-near.c diff --git a/src/main/fragment/mos6502-common/call_phi_close_cx16_ram.asm b/src/main/fragment/mos6502-common/call_phi_close_cx16_ram.asm index fda09c03e..87678c012 100644 --- a/src/main/fragment/mos6502-common/call_phi_close_cx16_ram.asm +++ b/src/main/fragment/mos6502-common/call_phi_close_cx16_ram.asm @@ -1,7 +1,11 @@ +sta $ff lda $0 pha lda #{c1} sta $0 +lda $ff jsr {la1} +sta $ff pla -sta $0 \ No newline at end of file +sta $0 +lda $ff \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/call_phi_close_cx16_rom.asm b/src/main/fragment/mos6502-common/call_phi_close_cx16_rom.asm index 6d0c8e9c2..5eb46e849 100644 --- a/src/main/fragment/mos6502-common/call_phi_close_cx16_rom.asm +++ b/src/main/fragment/mos6502-common/call_phi_close_cx16_rom.asm @@ -1,7 +1,11 @@ +sta $ff lda $1 pha lda #{c1} sta $1 +lda $ff jsr {la1} +sta $ff pla -sta $1 \ No newline at end of file +sta $1 +lda $ff \ No newline at end of file diff --git a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java index 95ae83112..7b2bc53a8 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java +++ b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java @@ -767,6 +767,11 @@ public class TestProgramsFast extends TestPrograms { compileAndCompare("examples/cx16/cx16-rasterbars.c"); } + //@Test + //public void testCx16Banking() throws IOException { + // compileAndCompare("examples/cx16/banking/cx16-banking.c"); + //} + @Test public void testMega65Camelot1536Dots() throws IOException { compileAndCompare("examples/mega65/camelot-1536dots.c"); diff --git a/src/test/kc/call-banked-phi-case-1-near-0.c b/src/test/kc/call-banked-phi-case-1-near-0.c index 090483c52..07b4a9513 100644 --- a/src/test/kc/call-banked-phi-case-1-near-0.c +++ b/src/test/kc/call-banked-phi-case-1-near-0.c @@ -32,6 +32,7 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // near call + SCREEN[1] = plus('1', 6); // near call } #pragma code_seg(Code) diff --git a/src/test/kc/call-banked-phi-case-1-near-1.c b/src/test/kc/call-banked-phi-case-1-near-1.c index e33afe4ea..7b5b79ef6 100644 --- a/src/test/kc/call-banked-phi-case-1-near-1.c +++ b/src/test/kc/call-banked-phi-case-1-near-1.c @@ -32,14 +32,15 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // near call + SCREEN[1] = plus('1', 6); // near call } #pragma code_seg(Code) char plus(char a, char b) { - return min(a, b); // near call + return add(a, b); // near call } #pragma code_seg(Code) -char min(char a, char b) { +char add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-2-close-0.c b/src/test/kc/call-banked-phi-case-2-close-0.c index b82015898..ed836b407 100644 --- a/src/test/kc/call-banked-phi-case-2-close-0.c +++ b/src/test/kc/call-banked-phi-case-2-close-0.c @@ -33,10 +33,10 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) __bank(cx16_ram,1) char plus(char a, char b) { return a+b; -} - +} \ No newline at end of file diff --git a/src/test/kc/call-banked-phi-case-2-close-1.c b/src/test/kc/call-banked-phi-case-2-close-1.c index 86512ae43..038007c95 100644 --- a/src/test/kc/call-banked-phi-case-2-close-1.c +++ b/src/test/kc/call-banked-phi-case-2-close-1.c @@ -28,21 +28,16 @@ #pragma link("call-banked-phi.ld") - char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) char plus(char a, char b) { return a+b; -} - -#pragma code_seg(Code) -#pragma nobank - - +} \ No newline at end of file diff --git a/src/test/kc/call-banked-phi-case-3-near-0.c b/src/test/kc/call-banked-phi-case-3-near-0.c index 30229c425..76812ead5 100644 --- a/src/test/kc/call-banked-phi-case-3-near-0.c +++ b/src/test/kc/call-banked-phi-case-3-near-0.c @@ -33,15 +33,17 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) __bank(cx16_ram,1) char plus(char a, char b) { - return min(a, b); // near call + return add(a, b); // near call } #pragma code_seg(Code) -char min(char a, char b) { +#pragma nobank +char add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-3-near-1.c b/src/test/kc/call-banked-phi-case-3-near-1.c index 2743d4b5c..25bce37f7 100644 --- a/src/test/kc/call-banked-phi-case-3-near-1.c +++ b/src/test/kc/call-banked-phi-case-3-near-1.c @@ -33,17 +33,18 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // near call + return add(a, b); // near call } #pragma code_seg(Code) #pragma nobank -char min(char a, char b) { +char add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-4-near-0.c b/src/test/kc/call-banked-phi-case-4-near-0.c index 2bf1f4c8a..5c7ffc1f0 100644 --- a/src/test/kc/call-banked-phi-case-4-near-0.c +++ b/src/test/kc/call-banked-phi-case-4-near-0.c @@ -28,20 +28,20 @@ #pragma link("call-banked-phi.ld") - char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) char __bank(cx16_ram, 1) plus(char a, char b) { - return min(a, b); // near call + return add(a, b); // near call } #pragma code_seg(RAM_Bank1) -char __bank(cx16_ram, 1) min(char a, char b) { +char __bank(cx16_ram, 1) add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-4-near-1.c b/src/test/kc/call-banked-phi-case-4-near-1.c index 369c1d675..319ac2483 100644 --- a/src/test/kc/call-banked-phi-case-4-near-1.c +++ b/src/test/kc/call-banked-phi-case-4-near-1.c @@ -33,19 +33,17 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // near call + return add(a, b); // near call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) -char min(char a, char b) { +char add(char a, char b) { return a+b; } - -#pragma code_seg(Code) -#pragma nobank diff --git a/src/test/kc/call-banked-phi-case-5-far-0.c b/src/test/kc/call-banked-phi-case-5-far-0.c index 7ae33a034..dceba3f63 100644 --- a/src/test/kc/call-banked-phi-case-5-far-0.c +++ b/src/test/kc/call-banked-phi-case-5-far-0.c @@ -33,14 +33,15 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) __bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // far call + return add(a, b); // far call } #pragma code_seg(RAM_Bank2) -__bank(cx16_ram, 2) char min(char a, char b) { +__bank(cx16_ram, 2) char add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-5-far-1.c b/src/test/kc/call-banked-phi-case-5-far-1.c index 3c1e3fbc9..754dd1402 100644 --- a/src/test/kc/call-banked-phi-case-5-far-1.c +++ b/src/test/kc/call-banked-phi-case-5-far-1.c @@ -33,19 +33,17 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // far call + return add(a, b); // far call } #pragma code_seg(RAM_Bank2) #pragma bank(cx16_ram, 2) -char min(char a, char b) { +char add(char a, char b) { return a+b; } - -#pragma code_seg(RAM_Bank2) -#pragma nobank diff --git a/src/test/kc/call-banked-phi-case-6-close-0.c b/src/test/kc/call-banked-phi-case-6-close-0.c index db2dc5973..8fada9193 100644 --- a/src/test/kc/call-banked-phi-case-6-close-0.c +++ b/src/test/kc/call-banked-phi-case-6-close-0.c @@ -33,14 +33,15 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) __bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // close call + return add(a, b); // close call } #pragma code_seg(ROM_Bank1) -__bank(cx16_rom, 1) char min(char a, char b) { +__bank(cx16_rom, 1) char add(char a, char b) { return a+b; } diff --git a/src/test/kc/call-banked-phi-case-6-close-1.c b/src/test/kc/call-banked-phi-case-6-close-1.c index 484ad2c06..5f8141443 100644 --- a/src/test/kc/call-banked-phi-case-6-close-1.c +++ b/src/test/kc/call-banked-phi-case-6-close-1.c @@ -33,19 +33,17 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(Code) void main(void) { SCREEN[0] = plus('0', 7); // close call + SCREEN[1] = plus('1', 6); // close call } #pragma code_seg(RAM_Bank1) #pragma bank(cx16_ram, 1) char plus(char a, char b) { - return min(a, b); // close call + return add(a, b); // close call } #pragma code_seg(ROM_Bank1) #pragma bank(cx16_rom, 1) -char min(char a, char b) { +char add(char a, char b) { return a+b; } - -#pragma code_seg(Code) -#pragma nobank diff --git a/src/test/kc/examples/cx16/banking/cx16-banking-recursive-near.c b/src/test/kc/examples/cx16/banking/cx16-banking-recursive-near.c deleted file mode 100644 index e1987ae9d..000000000 --- a/src/test/kc/examples/cx16/banking/cx16-banking-recursive-near.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file cx16-banking-1.c - * @author your name (you@domain.com) - * @brief This program demonstrates a simple example of a banked call. - * @version 0.1 - * @date 2023-04-05 - * - * @copyright Copyright (c) 2023 - * - */ - -// The linker specification of the different segments. -#pragma var_model(mem) - -#include -#include -#include -#include - -// The target computer platform is the Commander X16, -// which implements banking in ram between 0xA0000 and 0xBFFF, -// and in ram between 0xC000 and 0xFFFF. -#pragma target(cx16) - -char __stackcall plus(char a, char b) { - if (a > 0) { - return a + plus(a - b, b); - } else { - return 0; - } -} - -void main(void) { - - char result = plus(4, 1); - printf("result = %u\n", result); -} - diff --git a/src/test/kc/examples/cx16/banking/cx16-banking.c b/src/test/kc/examples/cx16/banking/cx16-banking.c index a9726c229..8648d45d1 100644 --- a/src/test/kc/examples/cx16/banking/cx16-banking.c +++ b/src/test/kc/examples/cx16/banking/cx16-banking.c @@ -10,6 +10,7 @@ */ // The linker specification of the different segments. +#pragma target(cx16) #pragma link("cx16-banking.ld") #pragma var_model(mem) diff --git a/src/test/ref/call-banked-phi-case-1-near-0.asm b/src/test/ref/call-banked-phi-case-1-near-0.asm index 0b157633e..9c88aba31 100644 --- a/src/test/ref/call-banked-phi-case-1-near-0.asm +++ b/src/test/ref/call-banked-phi-case-1-near-0.asm @@ -42,17 +42,29 @@ .segment Code main: { // plus('0', 7) + lda #7 + ldx #'0' jsr plus + // plus('0', 7) // SCREEN[0] = plus('0', 7) - lda #plus.return sta SCREEN + // plus('1', 6) + lda #6 + ldx #'1' + jsr plus + // plus('1', 6) + // SCREEN[1] = plus('1', 6) + // near call + sta SCREEN+1 // } rts } -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + stx.z $ff + clc + adc.z $ff + // } rts } diff --git a/src/test/ref/call-banked-phi-case-1-near-0.cfg b/src/test/ref/call-banked-phi-case-1-near-0.cfg index bfaa7082a..936abd391 100644 --- a/src/test/ref/call-banked-phi-case-1-near-0.cfg +++ b/src/test/ref/call-banked-phi-case-1-near-0.cfg @@ -3,18 +3,28 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return diff --git a/src/test/ref/call-banked-phi-case-1-near-0.log b/src/test/ref/call-banked-phi-case-1-near-0.log index 6cc252f0c..2ffa84883 100644 --- a/src/test/ref/call-banked-phi-case-1-near-0.log +++ b/src/test/ref/call-banked-phi-case-1-near-0.log @@ -7,27 +7,36 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - plus::$0 = plus::a#1 + plus::b#1 - plus::return#1 = plus::$0 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + plus::$0 = plus::a#2 + plus::b#2 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus - plus::return#4 = phi( plus/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return @@ -46,41 +55,53 @@ __constant char * const SCREEN = (char *)$400 void __start() void main() char main::$0 +char main::$1 char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -89,27 +110,24 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant plus::return#1 = plus::a#0+plus::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings plus::return#0 -Constant inlined plus::return#0 = plus::return#1 -Constant inlined main::$0 = plus::return#1 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus CALL GRAPH -Calls in [main] to plus:1 +Calls in [main] to plus:1 plus:5 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus FINAL CONTROL FLOW GRAPH @@ -117,43 +135,91 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return VARIABLE REGISTER WEIGHTS void main() +char main::$0 // 4.0 +char main::$1 // 4.0 char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 11.0 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ plus::return#2 ] +Allocated zp[1]:2 [ plus::a#2 ] +Allocated zp[1]:3 [ plus::b#2 ] +Allocated zp[1]:4 [ plus::return#0 ] +Allocated zp[1]:5 [ main::$0 ] +Allocated zp[1]:6 [ plus::return#1 ] +Allocated zp[1]:7 [ main::$1 ] +Allocated zp[1]:8 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [11] plus::return#2 = plus::a#2 + plus::b#2 [ plus::return#2 ] ( plus:1 [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } plus:5 [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Potential registers zp[1]:2 [ plus::a#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ plus::b#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ plus::return#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ plus::return#1 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ main::$1 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#2 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] +Uplift Scope [plus] 11: zp[1]:2 [ plus::a#2 ] 11: zp[1]:3 [ plus::b#2 ] 4: zp[1]:4 [ plus::return#0 ] 4: zp[1]:6 [ plus::return#1 ] 3.75: zp[1]:8 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] 4: zp[1]:7 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 60 combination -Uplifting [plus] best 60 combination -Uplifting [] best 60 combination +Uplifting [plus] best 81 combination reg byte x [ plus::a#2 ] reg byte a [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:8 [ plus::return#2 ] +Limited combination testing to 100 combinations of 1024 possible. +Uplifting [main] best 69 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 69 combination +Attempting to uplift remaining variables inzp[1]:8 [ plus::return#2 ] +Uplifting [plus] best 60 combination reg byte a [ plus::return#2 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -204,42 +270,67 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuaa=vbuc1 + lda #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- vbuxx=vbuc1 + ldx #'0' jsr plus + // [2] plus::return#0 = plus::return#2 jmp __b1 // main::@1 __b1: - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuaa=vbuc1 + lda #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- vbuxx=vbuc1 + ldx #'1' + jsr plus + // [6] plus::return#1 = plus::return#2 + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } // plus -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff jmp __breturn // plus::@return __breturn: - // [5] return + // [12] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination @@ -247,18 +338,29 @@ Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte x 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte a 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte a 3.75 +reg byte x [ plus::a#2 ] +reg byte a [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte a [ plus::return#2 ] FINAL ASSEMBLER -Score: 24 +Score: 48 // File Comments /** @@ -309,26 +411,51 @@ Score: 24 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuaa=vbuc1 + lda #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- vbuxx=vbuc1 + ldx #'0' jsr plus + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuaa=vbuc1 + lda #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- vbuxx=vbuc1 + ldx #'1' + jsr plus + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } // plus -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff // plus::@return - // [5] return + // } + // [12] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-1-near-0.sym b/src/test/ref/call-banked-phi-case-1-near-0.sym index 70d3c4d1f..aad9eb173 100644 --- a/src/test/ref/call-banked-phi-case-1-near-0.sym +++ b/src/test/ref/call-banked-phi-case-1-near-0.sym @@ -1,10 +1,21 @@ __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte x 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte a 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte a 3.75 +reg byte x [ plus::a#2 ] +reg byte a [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte a [ plus::return#2 ] diff --git a/src/test/ref/call-banked-phi-case-1-near-1.asm b/src/test/ref/call-banked-phi-case-1-near-1.asm index 3f285d651..c5395e6ac 100644 --- a/src/test/ref/call-banked-phi-case-1-near-1.asm +++ b/src/test/ref/call-banked-phi-case-1-near-1.asm @@ -42,24 +42,37 @@ .segment Code main: { // plus('0', 7) + lda #7 + ldx #'0' jsr plus + // plus('0', 7) // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + lda #6 + ldx #'1' + jsr plus + // plus('1', 6) + // SCREEN[1] = plus('1', 6) + // near call + sta SCREEN+1 // } rts } -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - jsr min + // add(a, b) + stx.z add.a + jsr add // } rts } -// char min(char a, char b) -min: { - .label return = plus.a+plus.b +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-1-near-1.cfg b/src/test/ref/call-banked-phi-case-1-near-1.cfg index 0ae888575..bd8833228 100644 --- a/src/test/ref/call-banked-phi-case-1-near-1.cfg +++ b/src/test/ref/call-banked-phi-case-1-near-1.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-1-near-1.log b/src/test/ref/call-banked-phi-case-1-near-1.log index 6d479c599..916bd8ab3 100644 --- a/src/test/ref/call-banked-phi-case-1-near-1.log +++ b/src/test/ref/call-banked-phi-case-1-near-1.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,58 +175,135 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 75 combination -Uplifting [plus] best 75 combination -Uplifting [min] best 75 combination -Uplifting [] best 75 combination +Uplifting [add] best 129 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 99 combination reg byte x [ plus::a#2 ] reg byte a [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 1024 possible. +Uplifting [main] best 87 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 87 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 87 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 78 combination reg byte a [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -273,81 +354,133 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuaa=vbuc1 + lda #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- vbuxx=vbuc1 + ldx #'0' jsr plus + // [2] plus::return#0 = plus::return#2 jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuaa=vbuc1 + lda #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- vbuxx=vbuc1 + ldx #'1' + jsr plus + // [6] plus::return#1 = plus::return#2 + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } // plus -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] - min_from_plus: - jsr min + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuxx + stx.z add.a + // [12] add::b#0 = plus::b#2 + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: -Removing instruction __breturn: +Removing instruction __b1: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte x 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte a 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte a 3.75 +reg byte x [ plus::a#2 ] +reg byte a [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte a [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 36 +Score: 60 // File Comments /** @@ -398,38 +531,68 @@ Score: 36 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuaa=vbuc1 + lda #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- vbuxx=vbuc1 + ldx #'0' jsr plus + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuaa=vbuc1 + lda #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- vbuxx=vbuc1 + ldx #'1' + jsr plus + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } // plus -// char plus(char a, char b) +// __register(A) char plus(__register(X) char a, __register(A) char b) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] - jsr min + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuxx + stx.z add.a + // [12] add::b#0 = plus::b#2 + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 // plus::@return // } - // [6] return + // [16] return rts } - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-1-near-1.sym b/src/test/ref/call-banked-phi-case-1-near-1.sym index 168bcee58..bfa554ac0 100644 --- a/src/test/ref/call-banked-phi-case-1-near-1.sym +++ b/src/test/ref/call-banked-phi-case-1-near-1.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte x 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte a 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte a 3.75 +reg byte x [ plus::a#2 ] +reg byte a [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte a [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-2-close-0.asm b/src/test/ref/call-banked-phi-case-2-close-0.asm index 992a24726..efdf5fdb6 100644 --- a/src/test/ref/call-banked-phi-case-2-close-0.asm +++ b/src/test/ref/call-banked-phi-case-2-close-0.asm @@ -43,25 +43,54 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #plus.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + stx.z $ff + clc + adc.z $ff + tax + // } rts } diff --git a/src/test/ref/call-banked-phi-case-2-close-0.cfg b/src/test/ref/call-banked-phi-case-2-close-0.cfg index 47114a8a3..b5f3a4af5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-0.cfg +++ b/src/test/ref/call-banked-phi-case-2-close-0.cfg @@ -3,18 +3,28 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return diff --git a/src/test/ref/call-banked-phi-case-2-close-0.log b/src/test/ref/call-banked-phi-case-2-close-0.log index 2fb184a72..96e2fadd5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-0.log +++ b/src/test/ref/call-banked-phi-case-2-close-0.log @@ -7,27 +7,36 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - plus::$0 = plus::a#1 + plus::b#1 - plus::return#1 = plus::$0 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + plus::$0 = plus::a#2 + plus::b#2 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus - plus::return#4 = phi( plus/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return @@ -46,41 +55,53 @@ __constant char * const SCREEN = (char *)$400 void __start() void main() char main::$0 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -89,27 +110,24 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant plus::return#1 = plus::a#0+plus::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings plus::return#0 -Constant inlined plus::return#0 = plus::return#1 -Constant inlined main::$0 = plus::return#1 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus CALL GRAPH -Calls in [main] to plus:1 +Calls in [main] to plus:1 plus:5 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus FINAL CONTROL FLOW GRAPH @@ -117,44 +135,97 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return VARIABLE REGISTER WEIGHTS void main() +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 11.0 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ plus::return#2 ] +Allocated zp[1]:2 [ plus::a#2 ] +Allocated zp[1]:3 [ plus::b#2 ] +Allocated zp[1]:4 [ plus::return#0 ] +Allocated zp[1]:5 [ main::$0 ] +Allocated zp[1]:6 [ plus::return#1 ] +Allocated zp[1]:7 [ main::$1 ] +Allocated zp[1]:8 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [11] plus::return#2 = plus::a#2 + plus::b#2 [ plus::return#2 ] ( plus:1 [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } plus:5 [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [11] plus::return#2 = plus::a#2 + plus::b#2 [ plus::return#2 ] ( plus:1 [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } plus:5 [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Potential registers zp[1]:2 [ plus::a#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ plus::b#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ plus::return#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ plus::return#1 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ main::$1 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#2 ] : zp[1]:8 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] +Uplift Scope [plus] 11: zp[1]:2 [ plus::a#2 ] 11: zp[1]:3 [ plus::b#2 ] 4: zp[1]:4 [ plus::return#0 ] 4: zp[1]:6 [ plus::return#1 ] 3.75: zp[1]:8 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] 4: zp[1]:7 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 78 combination -Uplifting [plus] best 78 combination -Uplifting [] best 78 combination +Uplifting [plus] best 141 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:8 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 129 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 129 combination +Attempting to uplift remaining variables inzp[1]:8 [ plus::return#2 ] +Uplifting [plus] best 126 combination reg byte x [ plus::return#2 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -206,50 +277,92 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuxx=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tax jmp __breturn // plus::@return __breturn: - // [5] return + // [12] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination @@ -257,18 +370,29 @@ Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte x [ plus::return#2 ] FINAL ASSEMBLER -Score: 42 +Score: 114 // File Comments /** @@ -320,34 +444,76 @@ Score: 42 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuxx=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tax // plus::@return - // [5] return + // } + // [12] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-2-close-0.sym b/src/test/ref/call-banked-phi-case-2-close-0.sym index 45d8d7108..00ee4aca5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-0.sym +++ b/src/test/ref/call-banked-phi-case-2-close-0.sym @@ -1,10 +1,21 @@ __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte x [ plus::return#2 ] diff --git a/src/test/ref/call-banked-phi-case-2-close-1.asm b/src/test/ref/call-banked-phi-case-2-close-1.asm index 937d2243f..5a15ee9a6 100644 --- a/src/test/ref/call-banked-phi-case-2-close-1.asm +++ b/src/test/ref/call-banked-phi-case-2-close-1.asm @@ -43,25 +43,54 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #plus.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + stx.z $ff + clc + adc.z $ff + tax + // } rts } diff --git a/src/test/ref/call-banked-phi-case-2-close-1.cfg b/src/test/ref/call-banked-phi-case-2-close-1.cfg index 47114a8a3..b5f3a4af5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-1.cfg +++ b/src/test/ref/call-banked-phi-case-2-close-1.cfg @@ -3,18 +3,28 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return diff --git a/src/test/ref/call-banked-phi-case-2-close-1.log b/src/test/ref/call-banked-phi-case-2-close-1.log index 3738f423b..9f7544ae5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-1.log +++ b/src/test/ref/call-banked-phi-case-2-close-1.log @@ -7,27 +7,36 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - plus::$0 = plus::a#1 + plus::b#1 - plus::return#1 = plus::$0 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + plus::$0 = plus::a#2 + plus::b#2 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus - plus::return#4 = phi( plus/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return @@ -46,41 +55,53 @@ __constant char * const SCREEN = (char *)$400 void __start() void main() char main::$0 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -89,27 +110,24 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant plus::return#1 = plus::a#0+plus::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings plus::return#0 -Constant inlined plus::return#0 = plus::return#1 -Constant inlined main::$0 = plus::return#1 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus CALL GRAPH -Calls in [main] to plus:1 +Calls in [main] to plus:1 plus:5 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus FINAL CONTROL FLOW GRAPH @@ -117,44 +135,97 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = plus::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] plus::return#2 = plus::a#2 + plus::b#2 to:plus::@return plus::@return: scope:[plus] from plus - [5] return + [12] return to:@return VARIABLE REGISTER WEIGHTS void main() +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 11.0 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ plus::return#2 ] +Allocated zp[1]:2 [ plus::a#2 ] +Allocated zp[1]:3 [ plus::b#2 ] +Allocated zp[1]:4 [ plus::return#0 ] +Allocated zp[1]:5 [ main::$0 ] +Allocated zp[1]:6 [ plus::return#1 ] +Allocated zp[1]:7 [ main::$1 ] +Allocated zp[1]:8 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:8 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [11] plus::return#2 = plus::a#2 + plus::b#2 [ plus::return#2 ] ( plus:1 [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } plus:5 [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [11] plus::return#2 = plus::a#2 + plus::b#2 [ plus::return#2 ] ( plus:1 [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } plus:5 [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Potential registers zp[1]:2 [ plus::a#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ plus::b#2 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ plus::return#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ plus::return#1 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ main::$1 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#2 ] : zp[1]:8 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] +Uplift Scope [plus] 11: zp[1]:2 [ plus::a#2 ] 11: zp[1]:3 [ plus::b#2 ] 4: zp[1]:4 [ plus::return#0 ] 4: zp[1]:6 [ plus::return#1 ] 3.75: zp[1]:8 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] 4: zp[1]:7 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 78 combination -Uplifting [plus] best 78 combination -Uplifting [] best 78 combination +Uplifting [plus] best 141 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:8 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 129 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 129 combination +Attempting to uplift remaining variables inzp[1]:8 [ plus::return#2 ] +Uplifting [plus] best 126 combination reg byte x [ plus::return#2 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -206,50 +277,92 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuxx=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tax jmp __breturn // plus::@return __breturn: - // [5] return + // [12] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination @@ -257,18 +370,29 @@ Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte x [ plus::return#2 ] FINAL ASSEMBLER -Score: 42 +Score: 114 // File Comments /** @@ -320,34 +444,76 @@ Score: 42 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 - lda #plus.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .const a = '0' - .const b = 7 - .label return = a+b + // a+b + // [11] plus::return#2 = plus::a#2 + plus::b#2 -- vbuxx=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + tax // plus::@return - // [5] return + // } + // [12] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-2-close-1.sym b/src/test/ref/call-banked-phi-case-2-close-1.sym index 45d8d7108..00ee4aca5 100644 --- a/src/test/ref/call-banked-phi-case-2-close-1.sym +++ b/src/test/ref/call-banked-phi-case-2-close-1.sym @@ -1,10 +1,21 @@ __constant char * const SCREEN = (char *) 1024 void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 11.0 char plus::return -__constant char plus::return#1 = plus::a#0+plus::b#0 // return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +reg byte x [ plus::return#2 ] diff --git a/src/test/ref/call-banked-phi-case-3-near-0.asm b/src/test/ref/call-banked-phi-case-3-near-0.asm index 36effde7d..60fa654fa 100644 --- a/src/test/ref/call-banked-phi-case-3-near-0.asm +++ b/src/test/ref/call-banked-phi-case-3-near-0.asm @@ -43,33 +43,64 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - jsr min + // add(a, b) + sta.z add.a + txa + jsr add + tax // } rts } .segment Code -// char min(char a, char b) -min: { - .label return = plus.a+plus.b +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-3-near-0.cfg b/src/test/ref/call-banked-phi-case-3-near-0.cfg index 4a0b60f9d..f7ec35c09 100644 --- a/src/test/ref/call-banked-phi-case-3-near-0.cfg +++ b/src/test/ref/call-banked-phi-case-3-near-0.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-3-near-0.log b/src/test/ref/call-banked-phi-case-3-near-0.log index 7b0249d61..63c05360e 100644 --- a/src/test/ref/call-banked-phi-case-3-near-0.log +++ b/src/test/ref/call-banked-phi-case-3-near-0.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,90 +361,159 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] - min_from_plus: - jsr min + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment Code - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -410,47 +565,95 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] - jsr min + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment Code - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-3-near-0.sym b/src/test/ref/call-banked-phi-case-3-near-0.sym index 9e4219f22..658eb6563 100644 --- a/src/test/ref/call-banked-phi-case-3-near-0.sym +++ b/src/test/ref/call-banked-phi-case-3-near-0.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-3-near-1.asm b/src/test/ref/call-banked-phi-case-3-near-1.asm index dc45fa7ff..9ffca6b4a 100644 --- a/src/test/ref/call-banked-phi-case-3-near-1.asm +++ b/src/test/ref/call-banked-phi-case-3-near-1.asm @@ -43,33 +43,64 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - jsr min + // add(a, b) + sta.z add.a + txa + jsr add + tax // } rts } .segment Code -// char min(char a, char b) -min: { - .label return = plus.a+plus.b +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-3-near-1.cfg b/src/test/ref/call-banked-phi-case-3-near-1.cfg index 4a0b60f9d..f7ec35c09 100644 --- a/src/test/ref/call-banked-phi-case-3-near-1.cfg +++ b/src/test/ref/call-banked-phi-case-3-near-1.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-3-near-1.log b/src/test/ref/call-banked-phi-case-3-near-1.log index 6409550db..7b34ab84a 100644 --- a/src/test/ref/call-banked-phi-case-3-near-1.log +++ b/src/test/ref/call-banked-phi-case-3-near-1.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,90 +361,159 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] - min_from_plus: - jsr min + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment Code - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -410,47 +565,95 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] - jsr min + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment Code - // min -// char min(char a, char b) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-3-near-1.sym b/src/test/ref/call-banked-phi-case-3-near-1.sym index 9e4219f22..658eb6563 100644 --- a/src/test/ref/call-banked-phi-case-3-near-1.sym +++ b/src/test/ref/call-banked-phi-case-3-near-1.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-4-near-0.asm b/src/test/ref/call-banked-phi-case-4-near-0.asm index d9e6ece5d..a7a1cbbf4 100644 --- a/src/test/ref/call-banked-phi-case-4-near-0.asm +++ b/src/test/ref/call-banked-phi-case-4-near-0.asm @@ -43,33 +43,64 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - jsr min + // add(a, b) + sta.z add.a + txa + jsr add + tax // } rts } -// char min(char a, char b) +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-4-near-0.cfg b/src/test/ref/call-banked-phi-case-4-near-0.cfg index 3a2aea220..bb224fbfe 100644 --- a/src/test/ref/call-banked-phi-case-4-near-0.cfg +++ b/src/test/ref/call-banked-phi-case-4-near-0.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-4-near-0.log b/src/test/ref/call-banked-phi-case-4-near-0.log index c5c7e65c3..5532553ee 100644 --- a/src/test/ref/call-banked-phi-case-4-near-0.log +++ b/src/test/ref/call-banked-phi-case-4-near-0.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_ram, 1) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_ram, 1) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,90 +361,159 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] - min_from_plus: - jsr min + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -410,47 +565,95 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] - jsr min + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-4-near-0.sym b/src/test/ref/call-banked-phi-case-4-near-0.sym index 09b563343..4267f6a35 100644 --- a/src/test/ref/call-banked-phi-case-4-near-0.sym +++ b/src/test/ref/call-banked-phi-case-4-near-0.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-4-near-1.asm b/src/test/ref/call-banked-phi-case-4-near-1.asm index 961e21569..97f10c7d0 100644 --- a/src/test/ref/call-banked-phi-case-4-near-1.asm +++ b/src/test/ref/call-banked-phi-case-4-near-1.asm @@ -43,33 +43,64 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - jsr min + // add(a, b) + sta.z add.a + txa + jsr add + tax // } rts } -// char min(char a, char b) +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-4-near-1.cfg b/src/test/ref/call-banked-phi-case-4-near-1.cfg index 3a2aea220..bb224fbfe 100644 --- a/src/test/ref/call-banked-phi-case-4-near-1.cfg +++ b/src/test/ref/call-banked-phi-case-4-near-1.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-4-near-1.log b/src/test/ref/call-banked-phi-case-4-near-1.log index fd0d233ce..4205fd77c 100644 --- a/src/test/ref/call-banked-phi-case-4-near-1.log +++ b/src/test/ref/call-banked-phi-case-4-near-1.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_ram, 1) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_ram, 1) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,90 +361,159 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] - min_from_plus: - jsr min + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -410,47 +565,95 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] - jsr min + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add + jsr add + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 1) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-4-near-1.sym b/src/test/ref/call-banked-phi-case-4-near-1.sym index 09b563343..4267f6a35 100644 --- a/src/test/ref/call-banked-phi-case-4-near-1.sym +++ b/src/test/ref/call-banked-phi-case-4-near-1.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-5-far-0.asm b/src/test/ref/call-banked-phi-case-5-far-0.asm index d4144fb7c..c8603afdc 100644 --- a/src/test/ref/call-banked-phi-case-5-far-0.asm +++ b/src/test/ref/call-banked-phi-case-5-far-0.asm @@ -43,37 +43,68 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) + // add(a, b) + sta.z add.a + txa jsr $ff6e - .byte min + .byte add .byte 2 + tax // } rts } .segment RAM_Bank2 -// char min(char a, char b) +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-5-far-0.cfg b/src/test/ref/call-banked-phi-case-5-far-0.cfg index 1bdaac9fb..03dfaf36c 100644 --- a/src/test/ref/call-banked-phi-case-5-far-0.cfg +++ b/src/test/ref/call-banked-phi-case-5-far-0.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-5-far-0.log b/src/test/ref/call-banked-phi-case-5-far-0.log index b4699672c..d1d83e6e3 100644 --- a/src/test/ref/call-banked-phi-case-5-far-0.log +++ b/src/test/ref/call-banked-phi-case-5-far-0.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_ram, 2) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_ram, 2) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,94 +361,163 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram - min_from_plus: + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_far_cx16_ram jsr $ff6e - .byte min + .byte add .byte 2 + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment RAM_Bank2 - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -414,51 +569,99 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_far_cx16_ram jsr $ff6e - .byte min + .byte add .byte 2 + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment RAM_Bank2 - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-5-far-0.sym b/src/test/ref/call-banked-phi-case-5-far-0.sym index 7c061e559..f777cf8ef 100644 --- a/src/test/ref/call-banked-phi-case-5-far-0.sym +++ b/src/test/ref/call-banked-phi-case-5-far-0.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-5-far-1.asm b/src/test/ref/call-banked-phi-case-5-far-1.asm index 3f168055b..93f4f13c5 100644 --- a/src/test/ref/call-banked-phi-case-5-far-1.asm +++ b/src/test/ref/call-banked-phi-case-5-far-1.asm @@ -43,37 +43,68 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) + // add(a, b) + sta.z add.a + txa jsr $ff6e - .byte min + .byte add .byte 2 + tax // } rts } .segment RAM_Bank2 -// char min(char a, char b) +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + // } rts } diff --git a/src/test/ref/call-banked-phi-case-5-far-1.cfg b/src/test/ref/call-banked-phi-case-5-far-1.cfg index 1bdaac9fb..03dfaf36c 100644 --- a/src/test/ref/call-banked-phi-case-5-far-1.cfg +++ b/src/test/ref/call-banked-phi-case-5-far-1.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-5-far-1.log b/src/test/ref/call-banked-phi-case-5-far-1.log index 0be8f5ff7..8844e959f 100644 --- a/src/test/ref/call-banked-phi-case-5-far-1.log +++ b/src/test/ref/call-banked-phi-case-5-far-1.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_ram, 2) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_ram, 2) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,59 +175,141 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_ram, 2) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_ram, 2) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 93 combination -Uplifting [plus] best 93 combination -Uplifting [min] best 93 combination -Uplifting [] best 93 combination +Uplifting [add] best 189 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte a [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [plus] best 161 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 149 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 149 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 149 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 146 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -275,94 +361,163 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram - min_from_plus: + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_far_cx16_ram jsr $ff6e - .byte min + .byte add .byte 2 + // [14] add::return#0 = add::return#1 + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment RAM_Bank2 - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] FINAL ASSEMBLER -Score: 54 +Score: 128 // File Comments /** @@ -414,51 +569,99 @@ Score: 54 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_far_cx16_ram jsr $ff6e - .byte min + .byte add .byte 2 + // [14] add::return#0 = add::return#1 + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment RAM_Bank2 - // min -// char min(char a, char b) + // add +// __register(A) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_ram, 2) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-5-far-1.sym b/src/test/ref/call-banked-phi-case-5-far-1.sym index 7c061e559..f777cf8ef 100644 --- a/src/test/ref/call-banked-phi-case-5-far-1.sym +++ b/src/test/ref/call-banked-phi-case-5-far-1.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_ram, 2) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte a 37.33333333333333 void main() -__bank(cx16_ram, 2) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte a [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-6-close-0.asm b/src/test/ref/call-banked-phi-case-6-close-0.asm index 32a709284..160ff45fa 100644 --- a/src/test/ref/call-banked-phi-case-6-close-0.asm +++ b/src/test/ref/call-banked-phi-case-6-close-0.asm @@ -43,40 +43,77 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) + // add(a, b) + sta.z add.a + txa + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + txa + tax // } rts } .segment ROM_Bank1 -// char min(char a, char b) +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + tax + // } rts } diff --git a/src/test/ref/call-banked-phi-case-6-close-0.cfg b/src/test/ref/call-banked-phi-case-6-close-0.cfg index 62e999ce1..c10c5c2f7 100644 --- a/src/test/ref/call-banked-phi-case-6-close-0.cfg +++ b/src/test/ref/call-banked-phi-case-6-close-0.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-6-close-0.log b/src/test/ref/call-banked-phi-case-6-close-0.log index d18801d0d..b81bf7d9a 100644 --- a/src/test/ref/call-banked-phi-case-6-close-0.log +++ b/src/test/ref/call-banked-phi-case-6-close-0.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_rom, 1) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_rom, 1) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,60 +175,144 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a -Statement [5] call min [ ] ( plus:1 [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [13] call add [ add::return#1 ] ( plus:1 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:4 [ add::return#1 ] +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [13] call add [ add::return#1 ] ( plus:1 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 111 combination -Uplifting [plus] best 111 combination -Uplifting [min] best 111 combination -Uplifting [] best 111 combination +Uplifting [add] best 223 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte x [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 192 possible. +Uplifting [plus] best 195 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 183 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 183 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 183 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 180 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -276,97 +364,172 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_close_cx16_rom - min_from_plus: + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_close_cx16_rom + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + // [14] add::return#0 = add::return#1 -- vbuaa=vbuxx + txa + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment ROM_Bank1 - // min -// char min(char a, char b) + // add +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuxx=vbuz1_plus_vbuaa + clc + adc.z a + tax jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte x 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte x [ add::return#1 ] FINAL ASSEMBLER -Score: 72 +Score: 162 // File Comments /** @@ -418,54 +581,108 @@ Score: 72 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_close_cx16_rom + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_close_cx16_rom + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + // [14] add::return#0 = add::return#1 -- vbuaa=vbuxx + txa + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment ROM_Bank1 - // min -// char min(char a, char b) + // add +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuxx=vbuz1_plus_vbuaa + clc + adc.z a + tax + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-6-close-0.sym b/src/test/ref/call-banked-phi-case-6-close-0.sym index ada067df8..26eed0f1c 100644 --- a/src/test/ref/call-banked-phi-case-6-close-0.sym +++ b/src/test/ref/call-banked-phi-case-6-close-0.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte x 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte x [ add::return#1 ] diff --git a/src/test/ref/call-banked-phi-case-6-close-1.asm b/src/test/ref/call-banked-phi-case-6-close-1.asm index 15769f0b8..89f99c527 100644 --- a/src/test/ref/call-banked-phi-case-6-close-1.asm +++ b/src/test/ref/call-banked-phi-case-6-close-1.asm @@ -43,40 +43,77 @@ .segment Code main: { // plus('0', 7) + ldx #7 + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + txa // SCREEN[0] = plus('0', 7) - lda #min.return sta SCREEN + // plus('1', 6) + ldx #6 + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + txa + // SCREEN[1] = plus('1', 6) + // close call + sta SCREEN+1 // } rts } .segment RAM_Bank1 -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) + // add(a, b) + sta.z add.a + txa + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + txa + tax // } rts } .segment ROM_Bank1 -// char min(char a, char b) +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // a+b + clc + adc.z a + tax + // } rts } diff --git a/src/test/ref/call-banked-phi-case-6-close-1.cfg b/src/test/ref/call-banked-phi-case-6-close-1.cfg index 62e999ce1..c10c5c2f7 100644 --- a/src/test/ref/call-banked-phi-case-6-close-1.cfg +++ b/src/test/ref/call-banked-phi-case-6-close-1.cfg @@ -3,27 +3,42 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return diff --git a/src/test/ref/call-banked-phi-case-6-close-1.log b/src/test/ref/call-banked-phi-case-6-close-1.log index ffe2cc66e..c64b16fba 100644 --- a/src/test/ref/call-banked-phi-case-6-close-1.log +++ b/src/test/ref/call-banked-phi-case-6-close-1.log @@ -7,47 +7,56 @@ main: scope:[main] from __start plus::a#0 = '0' plus::b#0 = 7 call plus - plus::return#0 = plus::return#2 + plus::return#0 = plus::return#3 to:main::@1 main::@1: scope:[main] from main - plus::return#3 = phi( main/plus::return#0 ) - main::$0 = plus::return#3 + plus::return#4 = phi( main/plus::return#0 ) + main::$0 = plus::return#4 SCREEN[0] = main::$0 + plus::a#1 = '1' + plus::b#1 = 6 + call plus + plus::return#1 = plus::return#3 + to:main::@2 +main::@2: scope:[main] from main::@1 + plus::return#5 = phi( main::@1/plus::return#1 ) + main::$1 = plus::return#5 + SCREEN[1] = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 +main::@return: scope:[main] from main::@2 return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - plus::b#1 = phi( main/plus::b#0 ) - plus::a#1 = phi( main/plus::a#0 ) - min::a#0 = plus::a#1 - min::b#0 = plus::b#1 - call min - min::return#0 = min::return#2 +plus: scope:[plus] from main main::@1 + plus::b#2 = phi( main/plus::b#0, main::@1/plus::b#1 ) + plus::a#2 = phi( main/plus::a#0, main::@1/plus::a#1 ) + add::a#0 = plus::a#2 + add::b#0 = plus::b#2 + call add + add::return#0 = add::return#2 to:plus::@1 plus::@1: scope:[plus] from plus - min::return#3 = phi( plus/min::return#0 ) - plus::$0 = min::return#3 - plus::return#1 = plus::$0 + add::return#3 = phi( plus/add::return#0 ) + plus::$0 = add::return#3 + plus::return#2 = plus::$0 to:plus::@return plus::@return: scope:[plus] from plus::@1 - plus::return#4 = phi( plus::@1/plus::return#1 ) - plus::return#2 = plus::return#4 + plus::return#6 = phi( plus::@1/plus::return#2 ) + plus::return#3 = plus::return#6 return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - min::b#1 = phi( plus/min::b#0 ) - min::a#1 = phi( plus/min::a#0 ) - min::$0 = min::a#1 + min::b#1 - min::return#1 = min::$0 - to:min::@return -min::@return: scope:[min] from min - min::return#4 = phi( min/min::return#1 ) - min::return#2 = min::return#4 +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + add::b#1 = phi( plus/add::b#0 ) + add::a#1 = phi( plus/add::a#0 ) + add::$0 = add::a#1 + add::b#1 + add::return#1 = add::$0 + to:add::@return +add::@return: scope:[add] from add + add::return#4 = phi( add/add::return#1 ) + add::return#2 = add::return#4 return to:@return @@ -64,64 +73,74 @@ __start::@return: scope:[__start] from __start::@1 SYMBOL TABLE SSA __constant char * const SCREEN = (char *)$400 void __start() +__bank(cx16_rom, 1) char add(char a , char b) +char add::$0 +char add::a +char add::a#0 +char add::a#1 +char add::b +char add::b#0 +char add::b#1 +char add::return +char add::return#0 +char add::return#1 +char add::return#2 +char add::return#3 +char add::return#4 void main() char main::$0 -__bank(cx16_rom, 1) char min(char a , char b) -char min::$0 -char min::a -char min::a#0 -char min::a#1 -char min::b -char min::b#0 -char min::b#1 -char min::return -char min::return#0 -char min::return#1 -char min::return#2 -char min::return#3 -char min::return#4 +char main::$1 __bank(cx16_ram, 1) char plus(char a , char b) char plus::$0 char plus::a char plus::a#0 char plus::a#1 +char plus::a#2 char plus::b char plus::b#0 char plus::b#1 +char plus::b#2 char plus::return char plus::return#0 char plus::return#1 char plus::return#2 char plus::return#3 char plus::return#4 +char plus::return#5 +char plus::return#6 Adding number conversion cast (unumber) 7 in plus::b#0 = 7 Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 6 in plus::b#1 = 6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = main::$1 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast plus::b#0 = (unumber)7 +Inlining cast plus::b#1 = (unumber)6 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 7 Simplifying constant integer cast 0 +Simplifying constant integer cast 6 +Simplifying constant integer cast 1 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 7 Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 1 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias plus::return#0 = plus::return#3 -Alias min::return#0 = min::return#3 -Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 -Alias min::return#1 = min::$0 min::return#4 min::return#2 +Alias plus::return#0 = plus::return#4 +Alias plus::return#1 = plus::return#5 +Alias add::return#0 = add::return#3 +Alias plus::return#2 = plus::$0 plus::return#6 plus::return#3 +Alias add::return#1 = add::$0 add::return#4 add::return#2 Successful SSA optimization Pass2AliasElimination -Identical Phi Values plus::a#1 plus::a#0 -Identical Phi Values plus::b#1 plus::b#0 -Identical Phi Values min::a#1 min::a#0 -Identical Phi Values min::b#1 min::b#0 +Identical Phi Values add::a#1 add::a#0 +Identical Phi Values add::b#1 add::b#0 Successful SSA optimization Pass2IdenticalPhiElimination Constant plus::a#0 = '0' Constant plus::b#0 = 7 -Successful SSA optimization Pass2ConstantIdentification -Constant min::a#0 = plus::a#0 -Constant min::b#0 = plus::b#0 +Constant plus::a#1 = '1' +Constant plus::b#1 = 6 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero @@ -130,40 +149,25 @@ Removing unused procedure block __start Removing unused procedure block __start::@1 Removing unused procedure block __start::@return Successful SSA optimization PassNEliminateEmptyStart -Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0 -Successful SSA optimization Pass2ConstantRValueConsolidation -Constant min::return#1 = min::a#0+min::b#0 -Successful SSA optimization Pass2ConstantIdentification -Constant min::return#0 = min::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#1 = min::return#0 -Successful SSA optimization Pass2ConstantIdentification -Constant plus::return#0 = plus::return#1 -Successful SSA optimization Pass2ConstantIdentification -Constant main::$0 = plus::return#0 -Successful SSA optimization Pass2ConstantIdentification -Inlining constant with different constant siblings min::return#0 -Constant inlined plus::return#0 = min::return#1 -Constant inlined main::$0 = min::return#1 -Constant inlined plus::return#1 = min::return#1 -Constant inlined min::a#0 = plus::a#0 -Constant inlined min::return#0 = min::return#1 -Constant inlined min::b#0 = plus::b#0 +Inlining constant with var siblings plus::a#0 +Inlining constant with var siblings plus::b#0 +Inlining constant with var siblings plus::a#1 +Inlining constant with var siblings plus::b#1 +Constant inlined plus::b#1 = 6 +Constant inlined plus::b#0 = 7 +Constant inlined plus::a#1 = '1' +Constant inlined plus::a#0 = '0' Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of plus::@1 -Adding NOP phi() at start of min CALL GRAPH -Calls in [main] to plus:1 -Calls in [plus] to min:5 +Calls in [main] to plus:1 plus:5 +Calls in [plus] to add:13 -Created 0 initial phi equivalence classes -Coalesced down to 0 phi equivalence classes -Culled Empty Block label plus::@1 +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes Adding NOP phi() at start of main -Adding NOP phi() at start of plus -Adding NOP phi() at start of min FINAL CONTROL FLOW GRAPH @@ -171,60 +175,144 @@ void main() main: scope:[main] from [0] phi() [1] call plus + [2] plus::return#0 = plus::return#2 to:main::@1 main::@1: scope:[main] from main - [2] *SCREEN = min::return#1 + [3] main::$0 = plus::return#0 + [4] *SCREEN = main::$0 + [5] call plus + [6] plus::return#1 = plus::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = plus::return#1 + [8] *(SCREEN+1) = main::$1 to:main::@return -main::@return: scope:[main] from main::@1 - [3] return +main::@return: scope:[main] from main::@2 + [9] return to:@return __bank(cx16_ram, 1) char plus(char a , char b) -plus: scope:[plus] from main - [4] phi() - [5] call min +plus: scope:[plus] from main main::@1 + [10] plus::b#2 = phi( main/7, main::@1/6 ) + [10] plus::a#2 = phi( main/'0', main::@1/'1' ) + [11] add::a#0 = plus::a#2 + [12] add::b#0 = plus::b#2 + [13] call add + [14] add::return#0 = add::return#1 + to:plus::@1 +plus::@1: scope:[plus] from plus + [15] plus::return#2 = add::return#0 to:plus::@return -plus::@return: scope:[plus] from plus - [6] return +plus::@return: scope:[plus] from plus::@1 + [16] return to:@return -__bank(cx16_rom, 1) char min(char a , char b) -min: scope:[min] from plus - [7] phi() - to:min::@return -min::@return: scope:[min] from min - [8] return +__bank(cx16_rom, 1) char add(char a , char b) +add: scope:[add] from plus + [17] add::return#1 = add::a#0 + add::b#0 + to:add::@return +add::@return: scope:[add] from add + [18] return to:@return VARIABLE REGISTER WEIGHTS +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // 56.0 +char add::b +char add::b#0 // 112.0 +char add::return +char add::return#0 // 22.0 +char add::return#1 // 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return +char main::$0 // 4.0 +char main::$1 // 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a +char plus::a#2 // 11.0 char plus::b +char plus::b#2 // 5.5 char plus::return +char plus::return#0 // 4.0 +char plus::return#1 // 4.0 +char plus::return#2 // 3.75 Initial phi equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable plus::return#1 to live range equivalence class [ plus::return#1 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable add::a#0 to live range equivalence class [ add::a#0 ] +Added variable add::b#0 to live range equivalence class [ add::b#0 ] +Added variable add::return#0 to live range equivalence class [ add::return#0 ] +Added variable plus::return#2 to live range equivalence class [ plus::return#2 ] +Added variable add::return#1 to live range equivalence class [ add::return#1 ] Complete equivalence classes +[ plus::a#2 ] +[ plus::b#2 ] +[ plus::return#0 ] +[ main::$0 ] +[ plus::return#1 ] +[ main::$1 ] +[ add::a#0 ] +[ add::b#0 ] +[ add::return#0 ] +[ plus::return#2 ] +[ add::return#1 ] +Allocated zp[1]:2 [ add::b#0 ] +Allocated zp[1]:3 [ add::a#0 ] +Allocated zp[1]:4 [ add::return#1 ] +Allocated zp[1]:5 [ add::return#0 ] +Allocated zp[1]:6 [ plus::a#2 ] +Allocated zp[1]:7 [ plus::b#2 ] +Allocated zp[1]:8 [ plus::return#0 ] +Allocated zp[1]:9 [ main::$0 ] +Allocated zp[1]:10 [ plus::return#1 ] +Allocated zp[1]:11 [ main::$1 ] +Allocated zp[1]:12 [ plus::return#2 ] REGISTER UPLIFT POTENTIAL REGISTERS -Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a -Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a -Statement [5] call min [ ] ( plus:1 [ ] { } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:12 [ plus::return#2 ] +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [13] call add [ add::return#1 ] ( plus:1 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:4 [ add::return#1 ] +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [1] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#0 = plus::return#2 } } ) always clobbers reg byte a +Statement [5] call plus [ plus::return#2 ] ( [ plus::return#2 ] { { plus::return#1 = plus::return#2 } } ) always clobbers reg byte a +Statement [13] call add [ add::return#1 ] ( plus:1 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Statement [17] add::return#1 = add::a#0 + add::b#0 [ add::return#1 ] ( plus:1::add:13 [ add::return#1 ] { { plus::return#0 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } plus:5::add:13 [ add::return#1 ] { { plus::return#1 = plus::return#2 } { add::a#0 = plus::a#2 } { add::b#0 = plus::b#2 } { add::return#0 = add::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:6 [ plus::a#2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ plus::b#2 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ plus::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ add::a#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ add::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ add::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ plus::return#2 ] : zp[1]:12 , reg byte x , reg byte y , +Potential registers zp[1]:4 [ add::return#1 ] : zp[1]:4 , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] -Uplift Scope [plus] -Uplift Scope [min] +Uplift Scope [add] 112: zp[1]:2 [ add::b#0 ] 56: zp[1]:3 [ add::a#0 ] 37.33: zp[1]:4 [ add::return#1 ] 22: zp[1]:5 [ add::return#0 ] +Uplift Scope [plus] 11: zp[1]:6 [ plus::a#2 ] 5.5: zp[1]:7 [ plus::b#2 ] 4: zp[1]:8 [ plus::return#0 ] 4: zp[1]:10 [ plus::return#1 ] 3.75: zp[1]:12 [ plus::return#2 ] +Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:11 [ main::$1 ] Uplift Scope [] -Uplifting [main] best 111 combination -Uplifting [plus] best 111 combination -Uplifting [min] best 111 combination -Uplifting [] best 111 combination +Uplifting [add] best 223 combination reg byte a [ add::b#0 ] zp[1]:3 [ add::a#0 ] reg byte x [ add::return#1 ] reg byte a [ add::return#0 ] +Limited combination testing to 100 combinations of 192 possible. +Uplifting [plus] best 195 combination reg byte a [ plus::a#2 ] reg byte x [ plus::b#2 ] reg byte a [ plus::return#0 ] reg byte a [ plus::return#1 ] zp[1]:12 [ plus::return#2 ] +Limited combination testing to 100 combinations of 768 possible. +Uplifting [main] best 183 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] +Uplifting [] best 183 combination +Attempting to uplift remaining variables inzp[1]:3 [ add::a#0 ] +Uplifting [add] best 183 combination zp[1]:3 [ add::a#0 ] +Attempting to uplift remaining variables inzp[1]:12 [ plus::return#2 ] +Uplifting [plus] best 180 combination reg byte x [ plus::return#2 ] +Allocated (was zp[1]:3) zp[1]:2 [ add::a#0 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -276,97 +364,172 @@ ASSEMBLER BEFORE OPTIMIZATION // main main: { // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] plus_from_main: + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa jmp __b1 // main::@1 __b1: - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [3] main::$0 = plus::return#0 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + plus_from___b1: + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = plus::return#1 + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 jmp __breturn // main::@return __breturn: - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_close_cx16_rom - min_from_plus: + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_close_cx16_rom + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + // [14] add::return#0 = add::return#1 -- vbuaa=vbuxx + txa + jmp __b1 + // plus::@1 + __b1: + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax jmp __breturn // plus::@return __breturn: - // [6] return + // [16] return rts } .segment ROM_Bank1 - // min -// char min(char a, char b) + // add +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b +add: { + .label a = 2 + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuxx=vbuz1_plus_vbuaa + clc + adc.z a + tax jmp __breturn - // min::@return + // add::@return __breturn: - // [8] return + // [18] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __breturn +Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction plus_from_main: Removing instruction __b1: +Removing instruction plus_from___b1: +Removing instruction __b2: Removing instruction __breturn: -Removing instruction min_from_plus: +Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE __constant char * const SCREEN = (char *) 1024 +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte x 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte x [ add::return#1 ] FINAL ASSEMBLER -Score: 72 +Score: 162 // File Comments /** @@ -418,54 +581,108 @@ Score: 72 main: { // plus('0', 7) // [1] call plus - // [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram + // [10] phi from main to plus [phi:main->plus] + // [10] phi plus::b#2 = 7 [phi:main->plus#0] -- vbuxx=vbuc1 + ldx #7 + // [10] phi plus::a#2 = '0' [phi:main->plus#1] -- call_phi_close_cx16_ram + lda #'0' + sta.z $ff lda.z 0 pha lda #1 sta.z 0 + lda.z $ff jsr plus + sta.z $ff pla sta.z 0 + lda.z $ff + // plus('0', 7) + // [2] plus::return#0 = plus::return#2 -- vbuaa=vbuxx + txa // main::@1 + // [3] main::$0 = plus::return#0 // SCREEN[0] = plus('0', 7) - // [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2 - lda #min.return + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa sta SCREEN + // plus('1', 6) + // [5] call plus + // [10] phi from main::@1 to plus [phi:main::@1->plus] + // [10] phi plus::b#2 = 6 [phi:main::@1->plus#0] -- vbuxx=vbuc1 + ldx #6 + // [10] phi plus::a#2 = '1' [phi:main::@1->plus#1] -- call_phi_close_cx16_ram + lda #'1' + sta.z $ff + lda.z 0 + pha + lda #1 + sta.z 0 + lda.z $ff + jsr plus + sta.z $ff + pla + sta.z 0 + lda.z $ff + // plus('1', 6) + // [6] plus::return#1 = plus::return#2 -- vbuaa=vbuxx + txa + // main::@2 + // [7] main::$1 = plus::return#1 + // SCREEN[1] = plus('1', 6) + // [8] *(SCREEN+1) = main::$1 -- _deref_pbuc1=vbuaa + // close call + sta SCREEN+1 // main::@return // } - // [3] return + // [9] return rts } .segment RAM_Bank1 // plus -// char plus(char a, char b) +// __register(X) char plus(__register(A) char a, __register(X) char b) // __bank(cx16_ram, 1) plus: { - .label a = '0' - .label b = 7 - // min(a, b) - // [5] call min - // [7] phi from plus to min [phi:plus->min] -- call_phi_close_cx16_rom + // add(a, b) + // [11] add::a#0 = plus::a#2 -- vbuz1=vbuaa + sta.z add.a + // [12] add::b#0 = plus::b#2 -- vbuaa=vbuxx + txa + // [13] call add -- call_phi_close_cx16_rom + sta.z $ff lda.z 1 pha lda #1 sta.z 1 - jsr min + lda.z $ff + jsr add + sta.z $ff pla sta.z 1 + lda.z $ff + // [14] add::return#0 = add::return#1 -- vbuaa=vbuxx + txa + // plus::@1 + // [15] plus::return#2 = add::return#0 -- vbuxx=vbuaa + tax // plus::@return // } - // [6] return + // [16] return rts } .segment ROM_Bank1 - // min -// char min(char a, char b) + // add +// __register(X) char add(__zp(2) char a, __register(A) char b) // __bank(cx16_rom, 1) -min: { - .label return = plus.a+plus.b - // min::@return - // [8] return +add: { + .label a = 2 + // a+b + // [17] add::return#1 = add::a#0 + add::b#0 -- vbuxx=vbuz1_plus_vbuaa + clc + adc.z a + tax + // add::@return + // } + // [18] return rts } // File Data diff --git a/src/test/ref/call-banked-phi-case-6-close-1.sym b/src/test/ref/call-banked-phi-case-6-close-1.sym index ada067df8..26eed0f1c 100644 --- a/src/test/ref/call-banked-phi-case-6-close-1.sym +++ b/src/test/ref/call-banked-phi-case-6-close-1.sym @@ -1,14 +1,33 @@ __constant char * const SCREEN = (char *) 1024 +__bank(cx16_rom, 1) char add(char a , char b) +char add::a +char add::a#0 // a zp[1]:2 56.0 +char add::b +char add::b#0 // reg byte a 112.0 +char add::return +char add::return#0 // reg byte a 22.0 +char add::return#1 // reg byte x 37.33333333333333 void main() -__bank(cx16_rom, 1) char min(char a , char b) -char min::a -char min::b -char min::return -__constant char min::return#1 = plus::a#0+plus::b#0 // return +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 __bank(cx16_ram, 1) char plus(char a , char b) char plus::a -__constant char plus::a#0 = '0' // a +char plus::a#2 // reg byte a 11.0 char plus::b -__constant char plus::b#0 = 7 // b +char plus::b#2 // reg byte x 5.5 char plus::return +char plus::return#0 // reg byte a 4.0 +char plus::return#1 // reg byte a 4.0 +char plus::return#2 // reg byte x 3.75 +reg byte a [ plus::a#2 ] +reg byte x [ plus::b#2 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] +reg byte a [ plus::return#1 ] +reg byte a [ main::$1 ] +zp[1]:2 [ add::a#0 ] +reg byte a [ add::b#0 ] +reg byte a [ add::return#0 ] +reg byte x [ plus::return#2 ] +reg byte x [ add::return#1 ]