mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-09 20:31:44 +00:00
Upgraded to KickAss 5.8. Closes #243
This commit is contained in:
parent
129cad782b
commit
a006e67f82
.idea/libraries
kickc.imlpom.xmlrepo/cml/kickass/kickassembler
5.8
_remote.repositorieskickassembler-5.8.jarkickassembler-5.8.jar.md5kickassembler-5.8.jar.sha1kickassembler-5.8.pomkickassembler-5.8.pom.md5kickassembler-5.8.pom.sha1
maven-metadata.xmlmaven-metadata.xml.md5maven-metadata.xml.sha1src
main/repo
test
java/dk/camelot64/kickc/test
kc
ref
13
.idea/libraries/Maven__cml_kickass_kickassembler_5_8.xml
generated
Normal file
13
.idea/libraries/Maven__cml_kickass_kickassembler_5_8.xml
generated
Normal file
@ -0,0 +1,13 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: cml.kickass:kickassembler:5.8">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/cml/kickass/kickassembler/5.8/kickassembler-5.8.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/cml/kickass/kickassembler/5.8/kickassembler-5.8-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/cml/kickass/kickassembler/5.8/kickassembler-5.8-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
@ -22,7 +22,7 @@
|
||||
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.7.1" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: cml.kickass:kickassembler:5.7" level="project" />
|
||||
<orderEntry type="library" name="Maven: cml.kickass:kickassembler:5.8" level="project" />
|
||||
<orderEntry type="library" name="Maven: info.picocli:picocli:3.6.0" level="project" />
|
||||
</component>
|
||||
</module>
|
2
pom.xml
2
pom.xml
@ -44,7 +44,7 @@
|
||||
<dependency>
|
||||
<groupId>cml.kickass</groupId>
|
||||
<artifactId>kickassembler</artifactId>
|
||||
<version>5.7</version>
|
||||
<version>5.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.picocli</groupId>
|
||||
|
4
repo/cml/kickass/kickassembler/5.8/_remote.repositories
Normal file
4
repo/cml/kickass/kickassembler/5.8/_remote.repositories
Normal file
@ -0,0 +1,4 @@
|
||||
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
|
||||
#Thu Aug 01 11:40:01 CEST 2019
|
||||
kickassembler-5.8.jar>=
|
||||
kickassembler-5.8.pom>=
|
BIN
repo/cml/kickass/kickassembler/5.8/kickassembler-5.8.jar
Normal file
BIN
repo/cml/kickass/kickassembler/5.8/kickassembler-5.8.jar
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
||||
5c5c7a9f305f009118b22f0e25b257f4
|
@ -0,0 +1 @@
|
||||
454b72d68d048b3fc97fd9c2318f5221652bb48d
|
9
repo/cml/kickass/kickassembler/5.8/kickassembler-5.8.pom
Normal file
9
repo/cml/kickass/kickassembler/5.8/kickassembler-5.8.pom
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cml.kickass</groupId>
|
||||
<artifactId>kickassembler</artifactId>
|
||||
<version>5.8</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
@ -0,0 +1 @@
|
||||
fa0980ad846135161a96dc65f6db5636
|
@ -0,0 +1 @@
|
||||
a5d6a538b0c23f5961cdf244d4965b7d87f07c29
|
@ -3,11 +3,10 @@
|
||||
<groupId>cml.kickass</groupId>
|
||||
<artifactId>kickassembler</artifactId>
|
||||
<versioning>
|
||||
<release>5.7</release>
|
||||
<release>5.8</release>
|
||||
<versions>
|
||||
<version>5.7</version>
|
||||
<version>4.19</version>
|
||||
<version>5.8</version>
|
||||
</versions>
|
||||
<lastUpdated>20190707111222</lastUpdated>
|
||||
<lastUpdated>20190801094001</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
|
@ -1 +1 @@
|
||||
371050487d0341b8ad5e5115a28669c1
|
||||
8517ec37e2b087a9649bb383e5fe7ba3
|
@ -1 +1 @@
|
||||
9e1e537f5927907ac635f4784fc82d467d20b70e
|
||||
9764bad67bbb3de5e80811b8ae6a551d4d66a147
|
2
src/main/repo/mvn-repo-install.sh
Normal file → Executable file
2
src/main/repo/mvn-repo-install.sh
Normal file → Executable file
@ -1,2 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Applications/KickAssembler/KickAss.jar -DgroupId=cml.kickass -DartifactId=kickassembler -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=5.7
|
||||
mvn install:install-file -Dmaven.repo.local=./repo/ -Dfile=/Applications/KickAssembler/KickAss.jar -DgroupId=cml.kickass -DartifactId=kickassembler -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true -Dversion=5.8
|
||||
|
@ -35,6 +35,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPosFill() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-pos-fill");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDannyJoystickProblem() throws IOException, URISyntaxException {
|
||||
compileAndCompare("danny-joystick-problem");
|
||||
|
31
src/test/kc/struct-pos-fill.kc
Normal file
31
src/test/kc/struct-pos-fill.kc
Normal file
@ -0,0 +1,31 @@
|
||||
// Example of structs that can be optimized by going planar
|
||||
// https://cc65.github.io/mailarchive/2010-09/8593.html?fbclid=IwAR1IF_cTdyWcFeKU93VfL2Un1EuLjkGh7O7dQ4EVj4kpJzJAj01dbmEFQt8
|
||||
|
||||
unsigned char OFFSET = 10;
|
||||
unsigned char XSPACE = 20;
|
||||
unsigned char YSPACE = 20;
|
||||
|
||||
struct pos {
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
};
|
||||
|
||||
struct pos[64] p;
|
||||
|
||||
unsigned char idx,line,row,x,y;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
for (line=0;line<8;++line)
|
||||
{
|
||||
++x;
|
||||
for (row=0;row<8;++row)
|
||||
{
|
||||
p[idx].y=y;
|
||||
p[idx].x=x;
|
||||
++idx;
|
||||
x+=XSPACE;
|
||||
}
|
||||
y+=YSPACE;
|
||||
}
|
||||
}
|
46
src/test/ref/struct-pos-fill.asm
Normal file
46
src/test/ref/struct-pos-fill.asm
Normal file
@ -0,0 +1,46 @@
|
||||
// Example of structs that can be optimized by going planar
|
||||
// https://cc65.github.io/mailarchive/2010-09/8593.html?fbclid=IwAR1IF_cTdyWcFeKU93VfL2Un1EuLjkGh7O7dQ4EVj4kpJzJAj01dbmEFQt8
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const OFFSET_STRUCT_POS_Y = 1
|
||||
.const XSPACE = $14
|
||||
.const YSPACE = $14
|
||||
.label x = 5
|
||||
.label idx = 4
|
||||
.label y = 2
|
||||
.label line = 3
|
||||
main: {
|
||||
lda #0
|
||||
sta line
|
||||
sta y
|
||||
sta idx
|
||||
sta x
|
||||
b1:
|
||||
inc x
|
||||
ldy #0
|
||||
b2:
|
||||
lda idx
|
||||
asl
|
||||
tax
|
||||
lda y
|
||||
sta p+OFFSET_STRUCT_POS_Y,x
|
||||
lda x
|
||||
sta p,x
|
||||
inc idx
|
||||
lax x
|
||||
axs #-[XSPACE]
|
||||
stx x
|
||||
iny
|
||||
cpy #8
|
||||
bcc b2
|
||||
lax y
|
||||
axs #-[YSPACE]
|
||||
stx y
|
||||
inc line
|
||||
lda line
|
||||
cmp #8
|
||||
bcc b1
|
||||
rts
|
||||
}
|
||||
p: .fill 2*$40, 0
|
39
src/test/ref/struct-pos-fill.cfg
Normal file
39
src/test/ref/struct-pos-fill.cfg
Normal file
@ -0,0 +1,39 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[5] (byte) line#10 ← phi( main/(byte) 0 main::@3/(byte) line#2 )
|
||||
[5] (byte) y#8 ← phi( main/(byte) 0 main::@3/(byte) y#1 )
|
||||
[5] (byte) idx#7 ← phi( main/(byte) 0 main::@3/(byte) idx#1 )
|
||||
[5] (byte) x#5 ← phi( main/(byte) 0 main::@3/(byte) x#10 )
|
||||
[6] (byte) x#1 ← ++ (byte) x#5
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@2
|
||||
[7] (byte) row#5 ← phi( main::@1/(byte) 0 main::@2/(byte) row#2 )
|
||||
[7] (byte) x#6 ← phi( main::@1/(byte) x#1 main::@2/(byte) x#10 )
|
||||
[7] (byte) idx#4 ← phi( main::@1/(byte) idx#7 main::@2/(byte) idx#1 )
|
||||
[8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1
|
||||
[9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8
|
||||
[10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6
|
||||
[11] (byte) idx#1 ← ++ (byte) idx#4
|
||||
[12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0
|
||||
[13] (byte) row#2 ← ++ (byte) row#5
|
||||
[14] if((byte) row#2<(byte) 8) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0
|
||||
[16] (byte) line#2 ← ++ (byte) line#10
|
||||
[17] if((byte) line#2<(byte) 8) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[18] return
|
||||
to:@return
|
885
src/test/ref/struct-pos-fill.log
Normal file
885
src/test/ref/struct-pos-fill.log
Normal file
@ -0,0 +1,885 @@
|
||||
Fixing pointer array-indexing *((struct pos[$40]) p + (byte) idx)
|
||||
Fixing pointer array-indexing *((struct pos[$40]) p + (byte) idx)
|
||||
Rewriting struct pointer member access *((struct pos[$40]) p + (byte~) main::$2).y
|
||||
Rewriting struct pointer member access *((struct pos[$40]) p + (byte~) main::$3).x
|
||||
Identified constant variable (byte) OFFSET
|
||||
Identified constant variable (byte) XSPACE
|
||||
Identified constant variable (byte) YSPACE
|
||||
Culled Empty Block (label) main::@4
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) XSPACE#0 ← (number) $14
|
||||
(byte) YSPACE#0 ← (number) $14
|
||||
(struct pos[$40]) p#0 ← { fill( $40, 0) }
|
||||
(byte) idx#0 ← (byte) 0
|
||||
(byte) line#0 ← (byte) 0
|
||||
(byte) row#0 ← (byte) 0
|
||||
(byte) x#0 ← (byte) 0
|
||||
(byte) y#0 ← (byte) 0
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
(byte) y#10 ← phi( @1/(byte) y#9 )
|
||||
(byte) idx#10 ← phi( @1/(byte) idx#9 )
|
||||
(byte) x#9 ← phi( @1/(byte) x#11 )
|
||||
(byte) line#1 ← (number) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
(byte) line#10 ← phi( main/(byte) line#1 main::@3/(byte) line#2 )
|
||||
(byte) y#8 ← phi( main/(byte) y#10 main::@3/(byte) y#1 )
|
||||
(byte) idx#7 ← phi( main/(byte) idx#10 main::@3/(byte) idx#8 )
|
||||
(byte) x#5 ← phi( main/(byte) x#9 main::@3/(byte) x#10 )
|
||||
(byte) x#1 ← ++ (byte) x#5
|
||||
(byte) row#1 ← (number) 0
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@2
|
||||
(byte) line#8 ← phi( main::@1/(byte) line#10 main::@2/(byte) line#8 )
|
||||
(byte) row#5 ← phi( main::@1/(byte) row#1 main::@2/(byte) row#2 )
|
||||
(byte) x#6 ← phi( main::@1/(byte) x#1 main::@2/(byte) x#2 )
|
||||
(byte) y#4 ← phi( main::@1/(byte) y#8 main::@2/(byte) y#4 )
|
||||
(byte) idx#4 ← phi( main::@1/(byte) idx#7 main::@2/(byte) idx#1 )
|
||||
(byte~) main::$2 ← (byte) idx#4 * (const byte) SIZEOF_STRUCT_POS
|
||||
(byte*) main::$4 ← (byte*)(struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_Y
|
||||
*((byte*) main::$4 + (byte~) main::$2) ← (byte) y#4
|
||||
(byte~) main::$3 ← (byte) idx#4 * (const byte) SIZEOF_STRUCT_POS
|
||||
(byte*) main::$5 ← (byte*)(struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_X
|
||||
*((byte*) main::$5 + (byte~) main::$3) ← (byte) x#6
|
||||
(byte) idx#1 ← ++ (byte) idx#4
|
||||
(byte) x#2 ← (byte) x#6 + (byte) XSPACE#0
|
||||
(byte) row#2 ← ++ (byte) row#5
|
||||
(bool~) main::$0 ← (byte) row#2 < (number) 8
|
||||
if((bool~) main::$0) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
(byte) idx#8 ← phi( main::@2/(byte) idx#1 )
|
||||
(byte) row#8 ← phi( main::@2/(byte) row#2 )
|
||||
(byte) x#10 ← phi( main::@2/(byte) x#2 )
|
||||
(byte) line#5 ← phi( main::@2/(byte) line#8 )
|
||||
(byte) y#5 ← phi( main::@2/(byte) y#4 )
|
||||
(byte) y#1 ← (byte) y#5 + (byte) YSPACE#0
|
||||
(byte) line#2 ← ++ (byte) line#5
|
||||
(bool~) main::$1 ← (byte) line#2 < (number) 8
|
||||
if((bool~) main::$1) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
(byte) y#6 ← phi( main::@3/(byte) y#1 )
|
||||
(byte) idx#5 ← phi( main::@3/(byte) idx#8 )
|
||||
(byte) row#6 ← phi( main::@3/(byte) row#8 )
|
||||
(byte) x#7 ← phi( main::@3/(byte) x#10 )
|
||||
(byte) line#6 ← phi( main::@3/(byte) line#2 )
|
||||
(byte) line#3 ← (byte) line#6
|
||||
(byte) x#3 ← (byte) x#7
|
||||
(byte) row#3 ← (byte) row#6
|
||||
(byte) idx#2 ← (byte) idx#5
|
||||
(byte) y#2 ← (byte) y#6
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte) y#9 ← phi( @begin/(byte) y#0 )
|
||||
(byte) idx#9 ← phi( @begin/(byte) idx#0 )
|
||||
(byte) row#9 ← phi( @begin/(byte) row#0 )
|
||||
(byte) x#11 ← phi( @begin/(byte) x#0 )
|
||||
(byte) line#9 ← phi( @begin/(byte) line#0 )
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
(byte) y#7 ← phi( @1/(byte) y#2 )
|
||||
(byte) idx#6 ← phi( @1/(byte) idx#2 )
|
||||
(byte) row#7 ← phi( @1/(byte) row#3 )
|
||||
(byte) x#8 ← phi( @1/(byte) x#3 )
|
||||
(byte) line#7 ← phi( @1/(byte) line#3 )
|
||||
(byte) line#4 ← (byte) line#7
|
||||
(byte) x#4 ← (byte) x#8
|
||||
(byte) row#4 ← (byte) row#7
|
||||
(byte) idx#3 ← (byte) idx#6
|
||||
(byte) y#3 ← (byte) y#7
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POS_X = (byte) 0
|
||||
(const byte) OFFSET_STRUCT_POS_Y = (byte) 1
|
||||
(const byte) SIZEOF_STRUCT_POS = (byte) 2
|
||||
(byte) XSPACE
|
||||
(byte) XSPACE#0
|
||||
(byte) YSPACE
|
||||
(byte) YSPACE#0
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#10
|
||||
(byte) idx#2
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(byte) line
|
||||
(byte) line#0
|
||||
(byte) line#1
|
||||
(byte) line#10
|
||||
(byte) line#2
|
||||
(byte) line#3
|
||||
(byte) line#4
|
||||
(byte) line#5
|
||||
(byte) line#6
|
||||
(byte) line#7
|
||||
(byte) line#8
|
||||
(byte) line#9
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(bool~) main::$1
|
||||
(byte~) main::$2
|
||||
(byte~) main::$3
|
||||
(byte*) main::$4
|
||||
(byte*) main::$5
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(struct pos[$40]) p
|
||||
(struct pos[$40]) p#0
|
||||
(byte) pos::x
|
||||
(byte) pos::y
|
||||
(byte) row
|
||||
(byte) row#0
|
||||
(byte) row#1
|
||||
(byte) row#2
|
||||
(byte) row#3
|
||||
(byte) row#4
|
||||
(byte) row#5
|
||||
(byte) row#6
|
||||
(byte) row#7
|
||||
(byte) row#8
|
||||
(byte) row#9
|
||||
(byte) x
|
||||
(byte) x#0
|
||||
(byte) x#1
|
||||
(byte) x#10
|
||||
(byte) x#11
|
||||
(byte) x#2
|
||||
(byte) x#3
|
||||
(byte) x#4
|
||||
(byte) x#5
|
||||
(byte) x#6
|
||||
(byte) x#7
|
||||
(byte) x#8
|
||||
(byte) x#9
|
||||
(byte) y
|
||||
(byte) y#0
|
||||
(byte) y#1
|
||||
(byte) y#10
|
||||
(byte) y#2
|
||||
(byte) y#3
|
||||
(byte) y#4
|
||||
(byte) y#5
|
||||
(byte) y#6
|
||||
(byte) y#7
|
||||
(byte) y#8
|
||||
(byte) y#9
|
||||
|
||||
Adding number conversion cast (unumber) $14 in (byte) XSPACE#0 ← (number) $14
|
||||
Adding number conversion cast (unumber) $14 in (byte) YSPACE#0 ← (number) $14
|
||||
Adding number conversion cast (unumber) 0 in (byte) line#1 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) row#1 ← (number) 0
|
||||
Adding number conversion cast (unumber) 8 in (bool~) main::$0 ← (byte) row#2 < (number) 8
|
||||
Adding number conversion cast (unumber) 8 in (bool~) main::$1 ← (byte) line#2 < (number) 8
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte) XSPACE#0 ← (unumber)(number) $14
|
||||
Inlining cast (byte) YSPACE#0 ← (unumber)(number) $14
|
||||
Inlining cast (byte) line#1 ← (unumber)(number) 0
|
||||
Inlining cast (byte) row#1 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast $14
|
||||
Simplifying constant integer cast $14
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 8
|
||||
Simplifying constant integer cast 8
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) $14
|
||||
Finalized unsigned number type (byte) $14
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 8
|
||||
Finalized unsigned number type (byte) 8
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte) y#4 = (byte) y#5
|
||||
Alias (byte) line#5 = (byte) line#8
|
||||
Alias (byte) x#10 = (byte) x#2 (byte) x#7 (byte) x#3
|
||||
Alias (byte) row#2 = (byte) row#8 (byte) row#6 (byte) row#3
|
||||
Alias (byte) idx#1 = (byte) idx#8 (byte) idx#5 (byte) idx#2
|
||||
Alias (byte) line#2 = (byte) line#6 (byte) line#3
|
||||
Alias (byte) y#1 = (byte) y#6 (byte) y#2
|
||||
Alias (byte) line#0 = (byte) line#9
|
||||
Alias (byte) x#0 = (byte) x#11
|
||||
Alias (byte) row#0 = (byte) row#9
|
||||
Alias (byte) idx#0 = (byte) idx#9
|
||||
Alias (byte) y#0 = (byte) y#9
|
||||
Alias (byte) line#4 = (byte) line#7
|
||||
Alias (byte) x#4 = (byte) x#8
|
||||
Alias (byte) row#4 = (byte) row#7
|
||||
Alias (byte) idx#3 = (byte) idx#6
|
||||
Alias (byte) y#3 = (byte) y#7
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) x#9 (byte) x#0
|
||||
Identical Phi Values (byte) idx#10 (byte) idx#0
|
||||
Identical Phi Values (byte) y#10 (byte) y#0
|
||||
Identical Phi Values (byte) y#4 (byte) y#8
|
||||
Identical Phi Values (byte) line#5 (byte) line#10
|
||||
Identical Phi Values (byte) line#4 (byte) line#2
|
||||
Identical Phi Values (byte) x#4 (byte) x#10
|
||||
Identical Phi Values (byte) row#4 (byte) row#2
|
||||
Identical Phi Values (byte) idx#3 (byte) idx#1
|
||||
Identical Phi Values (byte) y#3 (byte) y#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Identified duplicate assignment right side [17] (byte~) main::$3 ← (byte) idx#4 * (const byte) SIZEOF_STRUCT_POS
|
||||
Successful SSA optimization Pass2DuplicateRValueIdentification
|
||||
Simple Condition (bool~) main::$0 [24] if((byte) row#2<(byte) 8) goto main::@2
|
||||
Simple Condition (bool~) main::$1 [29] if((byte) line#2<(byte) 8) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant right-side identified [2] (struct pos[$40]) p#0 ← { fill( $40, 0) }
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) XSPACE#0 = $14
|
||||
Constant (const byte) YSPACE#0 = $14
|
||||
Constant (const struct pos[$40]) p#0 = { fill( $40, 0) }
|
||||
Constant (const byte) idx#0 = 0
|
||||
Constant (const byte) line#0 = 0
|
||||
Constant (const byte) row#0 = 0
|
||||
Constant (const byte) x#0 = 0
|
||||
Constant (const byte) y#0 = 0
|
||||
Constant (const byte) line#1 = 0
|
||||
Constant (const byte) row#1 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (byte*)p#0 in [15] (byte*) main::$4 ← (byte*)(const struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_Y
|
||||
Constant value identified (byte*)p#0 in [18] (byte*) main::$5 ← (byte*)(const struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_X
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Simplifying expression containing zero (byte*)p#0 in [18] (byte*) main::$5 ← (byte*)(const struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_X
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_POS_X
|
||||
Eliminating unused constant (const byte) line#0
|
||||
Eliminating unused constant (const byte) row#0
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Alias (byte~) main::$3 = (byte~) main::$2
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Constant right-side identified [4] (byte*) main::$4 ← (byte*)(const struct pos[$40]) p#0 + (const byte) OFFSET_STRUCT_POS_Y
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) main::$4 = (byte*)p#0+OFFSET_STRUCT_POS_Y
|
||||
Constant (const byte*) main::$5 = (byte*)p#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Rewriting multiplication to use shift [3] (byte~) main::$3 ← (byte) idx#4 * (const byte) SIZEOF_STRUCT_POS
|
||||
Successful SSA optimization Pass2MultiplyToShiftRewriting
|
||||
Inlining constant with var siblings (const byte) idx#0
|
||||
Inlining constant with var siblings (const byte) x#0
|
||||
Inlining constant with var siblings (const byte) y#0
|
||||
Inlining constant with var siblings (const byte) line#1
|
||||
Inlining constant with var siblings (const byte) row#1
|
||||
Constant inlined row#1 = (byte) 0
|
||||
Constant inlined x#0 = (byte) 0
|
||||
Constant inlined line#1 = (byte) 0
|
||||
Constant inlined y#0 = (byte) 0
|
||||
Constant inlined main::$5 = (byte*)(const struct pos[$40]) p#0
|
||||
Constant inlined main::$4 = (byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y
|
||||
Constant inlined idx#0 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Eliminating unused constant (const byte) SIZEOF_STRUCT_POS
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Added new block during phi lifting main::@5(between main::@3 and main::@1)
|
||||
Added new block during phi lifting main::@6(between main::@2 and main::@2)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 7 initial phi equivalence classes
|
||||
Coalesced [8] idx#12 ← idx#7
|
||||
Coalesced [9] x#13 ← x#1
|
||||
Coalesced [22] x#12 ← x#10
|
||||
Coalesced [23] idx#11 ← idx#1
|
||||
Coalesced [24] y#11 ← y#1
|
||||
Coalesced [25] line#11 ← line#2
|
||||
Coalesced (already) [26] idx#13 ← idx#1
|
||||
Coalesced [27] x#14 ← x#10
|
||||
Coalesced [28] row#10 ← row#2
|
||||
Coalesced down to 5 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@5
|
||||
Culled Empty Block (label) main::@6
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[5] (byte) line#10 ← phi( main/(byte) 0 main::@3/(byte) line#2 )
|
||||
[5] (byte) y#8 ← phi( main/(byte) 0 main::@3/(byte) y#1 )
|
||||
[5] (byte) idx#7 ← phi( main/(byte) 0 main::@3/(byte) idx#1 )
|
||||
[5] (byte) x#5 ← phi( main/(byte) 0 main::@3/(byte) x#10 )
|
||||
[6] (byte) x#1 ← ++ (byte) x#5
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@2
|
||||
[7] (byte) row#5 ← phi( main::@1/(byte) 0 main::@2/(byte) row#2 )
|
||||
[7] (byte) x#6 ← phi( main::@1/(byte) x#1 main::@2/(byte) x#10 )
|
||||
[7] (byte) idx#4 ← phi( main::@1/(byte) idx#7 main::@2/(byte) idx#1 )
|
||||
[8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1
|
||||
[9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8
|
||||
[10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6
|
||||
[11] (byte) idx#1 ← ++ (byte) idx#4
|
||||
[12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0
|
||||
[13] (byte) row#2 ← ++ (byte) row#5
|
||||
[14] if((byte) row#2<(byte) 8) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0
|
||||
[16] (byte) line#2 ← ++ (byte) line#10
|
||||
[17] if((byte) line#2<(byte) 8) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[18] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) XSPACE
|
||||
(byte) YSPACE
|
||||
(byte) idx
|
||||
(byte) idx#1 30.42857142857143
|
||||
(byte) idx#4 78.5
|
||||
(byte) idx#7 11.0
|
||||
(byte) line
|
||||
(byte) line#10 2.0
|
||||
(byte) line#2 16.5
|
||||
(void()) main()
|
||||
(byte~) main::$3 151.5
|
||||
(struct pos[$40]) p
|
||||
(byte) pos::x
|
||||
(byte) pos::y
|
||||
(byte) row
|
||||
(byte) row#2 151.5
|
||||
(byte) row#5 33.666666666666664
|
||||
(byte) x
|
||||
(byte) x#1 22.0
|
||||
(byte) x#10 35.5
|
||||
(byte) x#5 22.0
|
||||
(byte) x#6 62.8
|
||||
(byte) y
|
||||
(byte) y#1 7.333333333333333
|
||||
(byte) y#8 12.299999999999999
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ y#8 y#1 ]
|
||||
[ line#10 line#2 ]
|
||||
[ idx#4 idx#7 idx#1 ]
|
||||
[ x#6 x#1 x#5 x#10 ]
|
||||
[ row#5 row#2 ]
|
||||
Added variable main::$3 to zero page equivalence class [ main::$3 ]
|
||||
Complete equivalence classes
|
||||
[ y#8 y#1 ]
|
||||
[ line#10 line#2 ]
|
||||
[ idx#4 idx#7 idx#1 ]
|
||||
[ x#6 x#1 x#5 x#10 ]
|
||||
[ row#5 row#2 ]
|
||||
[ main::$3 ]
|
||||
Allocated zp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
Allocated zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
Allocated zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
Allocated zp ZP_BYTE:6 [ row#5 row#2 ]
|
||||
Allocated zp ZP_BYTE:7 [ main::$3 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic
|
||||
// File Comments
|
||||
// Example of structs that can be optimized by going planar
|
||||
// https://cc65.github.io/mailarchive/2010-09/8593.html?fbclid=IwAR1IF_cTdyWcFeKU93VfL2Un1EuLjkGh7O7dQ4EVj4kpJzJAj01dbmEFQt8
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POS_Y = 1
|
||||
.const XSPACE = $14
|
||||
.const YSPACE = $14
|
||||
.label x = 5
|
||||
.label idx = 4
|
||||
.label row = 6
|
||||
.label y = 2
|
||||
.label line = 3
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.label _3 = 7
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte) line#10 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta line
|
||||
// [5] phi (byte) y#8 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta y
|
||||
// [5] phi (byte) idx#7 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
// [5] phi (byte) x#5 = (byte) 0 [phi:main->main::@1#3] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta x
|
||||
jmp b1
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
// [5] phi (byte) line#10 = (byte) line#2 [phi:main::@3->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) y#8 = (byte) y#1 [phi:main::@3->main::@1#1] -- register_copy
|
||||
// [5] phi (byte) idx#7 = (byte) idx#1 [phi:main::@3->main::@1#2] -- register_copy
|
||||
// [5] phi (byte) x#5 = (byte) x#10 [phi:main::@3->main::@1#3] -- register_copy
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] (byte) x#1 ← ++ (byte) x#5 -- vbuz1=_inc_vbuz1
|
||||
inc x
|
||||
// [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
// [7] phi (byte) row#5 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta row
|
||||
// [7] phi (byte) x#6 = (byte) x#1 [phi:main::@1->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#7 [phi:main::@1->main::@2#2] -- register_copy
|
||||
jmp b2
|
||||
// [7] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
|
||||
b2_from_b2:
|
||||
// [7] phi (byte) row#5 = (byte) row#2 [phi:main::@2->main::@2#0] -- register_copy
|
||||
// [7] phi (byte) x#6 = (byte) x#10 [phi:main::@2->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#1 [phi:main::@2->main::@2#2] -- register_copy
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda idx
|
||||
asl
|
||||
sta _3
|
||||
// [9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda y
|
||||
ldy _3
|
||||
sta p+OFFSET_STRUCT_POS_Y,y
|
||||
// [10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6 -- pbuc1_derefidx_vbuz1=vbuz2
|
||||
lda x
|
||||
ldy _3
|
||||
sta p,y
|
||||
// [11] (byte) idx#1 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
// [12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax x
|
||||
axs #-[XSPACE]
|
||||
stx x
|
||||
// [13] (byte) row#2 ← ++ (byte) row#5 -- vbuz1=_inc_vbuz1
|
||||
inc row
|
||||
// [14] if((byte) row#2<(byte) 8) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda row
|
||||
cmp #8
|
||||
bcc b2_from_b2
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax y
|
||||
axs #-[YSPACE]
|
||||
stx y
|
||||
// [16] (byte) line#2 ← ++ (byte) line#10 -- vbuz1=_inc_vbuz1
|
||||
inc line
|
||||
// [17] if((byte) line#2<(byte) 8) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda line
|
||||
cmp #8
|
||||
bcc b1_from_b3
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
p: .fill 2*$40, 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ row#5 row#2 ]
|
||||
Statement [9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:7 [ main::$3 ]
|
||||
Statement [10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6 [ y#8 line#10 idx#4 x#6 row#5 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 ] ) always clobbers reg byte a
|
||||
Statement [12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0 [ y#8 line#10 x#10 idx#1 row#5 ] ( main:2 [ y#8 line#10 x#10 idx#1 row#5 ] ) always clobbers reg byte a
|
||||
Statement [15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0 [ line#10 x#10 idx#1 y#1 ] ( main:2 [ line#10 x#10 idx#1 y#1 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 main::$3 ] ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6 [ y#8 line#10 idx#4 x#6 row#5 ] ( main:2 [ y#8 line#10 idx#4 x#6 row#5 ] ) always clobbers reg byte a
|
||||
Statement [12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0 [ y#8 line#10 x#10 idx#1 row#5 ] ( main:2 [ y#8 line#10 x#10 idx#1 row#5 ] ) always clobbers reg byte a
|
||||
Statement [15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0 [ line#10 x#10 idx#1 y#1 ] ( main:2 [ line#10 x#10 idx#1 y#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ y#8 y#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ line#10 line#2 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ] : zp ZP_BYTE:4 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ] : zp ZP_BYTE:5 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:6 [ row#5 row#2 ] : zp ZP_BYTE:6 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:7 [ main::$3 ] : zp ZP_BYTE:7 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 185.17: zp ZP_BYTE:6 [ row#5 row#2 ] 142.3: zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ] 119.93: zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ] 19.63: zp ZP_BYTE:2 [ y#8 y#1 ] 18.5: zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
Uplift Scope [main] 151.5: zp ZP_BYTE:7 [ main::$3 ]
|
||||
Uplift Scope [pos]
|
||||
|
||||
Uplifting [] best 7513 combination zp ZP_BYTE:6 [ row#5 row#2 ] zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ] zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ] zp ZP_BYTE:2 [ y#8 y#1 ] zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
Limited combination testing to 100 combinations of 243 possible.
|
||||
Uplifting [main] best 6813 combination reg byte x [ main::$3 ]
|
||||
Uplifting [pos] best 6813 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:6 [ row#5 row#2 ]
|
||||
Uplifting [] best 5913 combination reg byte y [ row#5 row#2 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
Uplifting [] best 5913 combination zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
Uplifting [] best 5913 combination zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
Uplifting [] best 5913 combination zp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
Uplifting [] best 5913 combination zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Example of structs that can be optimized by going planar
|
||||
// https://cc65.github.io/mailarchive/2010-09/8593.html?fbclid=IwAR1IF_cTdyWcFeKU93VfL2Un1EuLjkGh7O7dQ4EVj4kpJzJAj01dbmEFQt8
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POS_Y = 1
|
||||
.const XSPACE = $14
|
||||
.const YSPACE = $14
|
||||
.label x = 5
|
||||
.label idx = 4
|
||||
.label y = 2
|
||||
.label line = 3
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
// [5] phi (byte) line#10 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta line
|
||||
// [5] phi (byte) y#8 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta y
|
||||
// [5] phi (byte) idx#7 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
// [5] phi (byte) x#5 = (byte) 0 [phi:main->main::@1#3] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta x
|
||||
jmp b1
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
// [5] phi (byte) line#10 = (byte) line#2 [phi:main::@3->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) y#8 = (byte) y#1 [phi:main::@3->main::@1#1] -- register_copy
|
||||
// [5] phi (byte) idx#7 = (byte) idx#1 [phi:main::@3->main::@1#2] -- register_copy
|
||||
// [5] phi (byte) x#5 = (byte) x#10 [phi:main::@3->main::@1#3] -- register_copy
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [6] (byte) x#1 ← ++ (byte) x#5 -- vbuz1=_inc_vbuz1
|
||||
inc x
|
||||
// [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
b2_from_b1:
|
||||
// [7] phi (byte) row#5 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [7] phi (byte) x#6 = (byte) x#1 [phi:main::@1->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#7 [phi:main::@1->main::@2#2] -- register_copy
|
||||
jmp b2
|
||||
// [7] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
|
||||
b2_from_b2:
|
||||
// [7] phi (byte) row#5 = (byte) row#2 [phi:main::@2->main::@2#0] -- register_copy
|
||||
// [7] phi (byte) x#6 = (byte) x#10 [phi:main::@2->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#1 [phi:main::@2->main::@2#2] -- register_copy
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1 -- vbuxx=vbuz1_rol_1
|
||||
lda idx
|
||||
asl
|
||||
tax
|
||||
// [9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
lda y
|
||||
sta p+OFFSET_STRUCT_POS_Y,x
|
||||
// [10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
lda x
|
||||
sta p,x
|
||||
// [11] (byte) idx#1 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
// [12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax x
|
||||
axs #-[XSPACE]
|
||||
stx x
|
||||
// [13] (byte) row#2 ← ++ (byte) row#5 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] if((byte) row#2<(byte) 8) goto main::@2 -- vbuyy_lt_vbuc1_then_la1
|
||||
cpy #8
|
||||
bcc b2_from_b2
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax y
|
||||
axs #-[YSPACE]
|
||||
stx y
|
||||
// [16] (byte) line#2 ← ++ (byte) line#10 -- vbuz1=_inc_vbuz1
|
||||
inc line
|
||||
// [17] if((byte) line#2<(byte) 8) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda line
|
||||
cmp #8
|
||||
bcc b1_from_b3
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
p: .fill 2*$40, 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label b2_from_b2 with b2
|
||||
Replacing label b1_from_b3 with b1
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_b3:
|
||||
Removing instruction b2_from_b2:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction b3:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POS_Y OFFSET_STRUCT_POS_Y = (byte) 1
|
||||
(byte) XSPACE
|
||||
(const byte) XSPACE#0 XSPACE = (byte) $14
|
||||
(byte) YSPACE
|
||||
(const byte) YSPACE#0 YSPACE = (byte) $14
|
||||
(byte) idx
|
||||
(byte) idx#1 idx zp ZP_BYTE:4 30.42857142857143
|
||||
(byte) idx#4 idx zp ZP_BYTE:4 78.5
|
||||
(byte) idx#7 idx zp ZP_BYTE:4 11.0
|
||||
(byte) line
|
||||
(byte) line#10 line zp ZP_BYTE:3 2.0
|
||||
(byte) line#2 line zp ZP_BYTE:3 16.5
|
||||
(void()) main()
|
||||
(byte~) main::$3 reg byte x 151.5
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(struct pos[$40]) p
|
||||
(const struct pos[$40]) p#0 p = { fill( $40, 0) }
|
||||
(byte) pos::x
|
||||
(byte) pos::y
|
||||
(byte) row
|
||||
(byte) row#2 reg byte y 151.5
|
||||
(byte) row#5 reg byte y 33.666666666666664
|
||||
(byte) x
|
||||
(byte) x#1 x zp ZP_BYTE:5 22.0
|
||||
(byte) x#10 x zp ZP_BYTE:5 35.5
|
||||
(byte) x#5 x zp ZP_BYTE:5 22.0
|
||||
(byte) x#6 x zp ZP_BYTE:5 62.8
|
||||
(byte) y
|
||||
(byte) y#1 y zp ZP_BYTE:2 7.333333333333333
|
||||
(byte) y#8 y zp ZP_BYTE:2 12.299999999999999
|
||||
|
||||
zp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
reg byte y [ row#5 row#2 ]
|
||||
reg byte x [ main::$3 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 4851
|
||||
|
||||
// File Comments
|
||||
// Example of structs that can be optimized by going planar
|
||||
// https://cc65.github.io/mailarchive/2010-09/8593.html?fbclid=IwAR1IF_cTdyWcFeKU93VfL2Un1EuLjkGh7O7dQ4EVj4kpJzJAj01dbmEFQt8
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const OFFSET_STRUCT_POS_Y = 1
|
||||
.const XSPACE = $14
|
||||
.const YSPACE = $14
|
||||
.label x = 5
|
||||
.label idx = 4
|
||||
.label y = 2
|
||||
.label line = 3
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
// [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [5] phi (byte) line#10 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta line
|
||||
// [5] phi (byte) y#8 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1
|
||||
sta y
|
||||
// [5] phi (byte) idx#7 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
|
||||
sta idx
|
||||
// [5] phi (byte) x#5 = (byte) 0 [phi:main->main::@1#3] -- vbuz1=vbuc1
|
||||
sta x
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
// [5] phi (byte) line#10 = (byte) line#2 [phi:main::@3->main::@1#0] -- register_copy
|
||||
// [5] phi (byte) y#8 = (byte) y#1 [phi:main::@3->main::@1#1] -- register_copy
|
||||
// [5] phi (byte) idx#7 = (byte) idx#1 [phi:main::@3->main::@1#2] -- register_copy
|
||||
// [5] phi (byte) x#5 = (byte) x#10 [phi:main::@3->main::@1#3] -- register_copy
|
||||
// main::@1
|
||||
b1:
|
||||
// ++x;
|
||||
// [6] (byte) x#1 ← ++ (byte) x#5 -- vbuz1=_inc_vbuz1
|
||||
inc x
|
||||
// [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
// [7] phi (byte) row#5 = (byte) 0 [phi:main::@1->main::@2#0] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [7] phi (byte) x#6 = (byte) x#1 [phi:main::@1->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#7 [phi:main::@1->main::@2#2] -- register_copy
|
||||
// [7] phi from main::@2 to main::@2 [phi:main::@2->main::@2]
|
||||
// [7] phi (byte) row#5 = (byte) row#2 [phi:main::@2->main::@2#0] -- register_copy
|
||||
// [7] phi (byte) x#6 = (byte) x#10 [phi:main::@2->main::@2#1] -- register_copy
|
||||
// [7] phi (byte) idx#4 = (byte) idx#1 [phi:main::@2->main::@2#2] -- register_copy
|
||||
// main::@2
|
||||
b2:
|
||||
// p[idx].y=y
|
||||
// [8] (byte~) main::$3 ← (byte) idx#4 << (byte) 1 -- vbuxx=vbuz1_rol_1
|
||||
lda idx
|
||||
asl
|
||||
tax
|
||||
// [9] *((byte*)(const struct pos[$40]) p#0+(const byte) OFFSET_STRUCT_POS_Y + (byte~) main::$3) ← (byte) y#8 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
lda y
|
||||
sta p+OFFSET_STRUCT_POS_Y,x
|
||||
// p[idx].x=x
|
||||
// [10] *((byte*)(const struct pos[$40]) p#0 + (byte~) main::$3) ← (byte) x#6 -- pbuc1_derefidx_vbuxx=vbuz1
|
||||
lda x
|
||||
sta p,x
|
||||
// ++idx;
|
||||
// [11] (byte) idx#1 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
// x+=XSPACE
|
||||
// [12] (byte) x#10 ← (byte) x#6 + (const byte) XSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax x
|
||||
axs #-[XSPACE]
|
||||
stx x
|
||||
// for (row=0;row<8;++row)
|
||||
// [13] (byte) row#2 ← ++ (byte) row#5 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] if((byte) row#2<(byte) 8) goto main::@2 -- vbuyy_lt_vbuc1_then_la1
|
||||
cpy #8
|
||||
bcc b2
|
||||
// main::@3
|
||||
// y+=YSPACE
|
||||
// [15] (byte) y#1 ← (byte) y#8 + (const byte) YSPACE#0 -- vbuz1=vbuz1_plus_vbuc1
|
||||
lax y
|
||||
axs #-[YSPACE]
|
||||
stx y
|
||||
// for (line=0;line<8;++line)
|
||||
// [16] (byte) line#2 ← ++ (byte) line#10 -- vbuz1=_inc_vbuz1
|
||||
inc line
|
||||
// [17] if((byte) line#2<(byte) 8) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda line
|
||||
cmp #8
|
||||
bcc b1
|
||||
// main::@return
|
||||
// }
|
||||
// [18] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
p: .fill 2*$40, 0
|
||||
|
43
src/test/ref/struct-pos-fill.sym
Normal file
43
src/test/ref/struct-pos-fill.sym
Normal file
@ -0,0 +1,43 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) OFFSET_STRUCT_POS_Y OFFSET_STRUCT_POS_Y = (byte) 1
|
||||
(byte) XSPACE
|
||||
(const byte) XSPACE#0 XSPACE = (byte) $14
|
||||
(byte) YSPACE
|
||||
(const byte) YSPACE#0 YSPACE = (byte) $14
|
||||
(byte) idx
|
||||
(byte) idx#1 idx zp ZP_BYTE:4 30.42857142857143
|
||||
(byte) idx#4 idx zp ZP_BYTE:4 78.5
|
||||
(byte) idx#7 idx zp ZP_BYTE:4 11.0
|
||||
(byte) line
|
||||
(byte) line#10 line zp ZP_BYTE:3 2.0
|
||||
(byte) line#2 line zp ZP_BYTE:3 16.5
|
||||
(void()) main()
|
||||
(byte~) main::$3 reg byte x 151.5
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@return
|
||||
(struct pos[$40]) p
|
||||
(const struct pos[$40]) p#0 p = { fill( $40, 0) }
|
||||
(byte) pos::x
|
||||
(byte) pos::y
|
||||
(byte) row
|
||||
(byte) row#2 reg byte y 151.5
|
||||
(byte) row#5 reg byte y 33.666666666666664
|
||||
(byte) x
|
||||
(byte) x#1 x zp ZP_BYTE:5 22.0
|
||||
(byte) x#10 x zp ZP_BYTE:5 35.5
|
||||
(byte) x#5 x zp ZP_BYTE:5 22.0
|
||||
(byte) x#6 x zp ZP_BYTE:5 62.8
|
||||
(byte) y
|
||||
(byte) y#1 y zp ZP_BYTE:2 7.333333333333333
|
||||
(byte) y#8 y zp ZP_BYTE:2 12.299999999999999
|
||||
|
||||
zp ZP_BYTE:2 [ y#8 y#1 ]
|
||||
zp ZP_BYTE:3 [ line#10 line#2 ]
|
||||
zp ZP_BYTE:4 [ idx#4 idx#7 idx#1 ]
|
||||
zp ZP_BYTE:5 [ x#6 x#1 x#5 x#10 ]
|
||||
reg byte y [ row#5 row#2 ]
|
||||
reg byte x [ main::$3 ]
|
Loading…
x
Reference in New Issue
Block a user