1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-02 00:41:42 +00:00

Upgraded to KickAss 5.8. Closes #243

This commit is contained in:
jespergravgaard 2019-08-01 12:58:40 +02:00
parent 129cad782b
commit a006e67f82
20 changed files with 1087 additions and 9 deletions

View 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>

View File

@ -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>

View File

@ -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>

View 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>=

View File

@ -0,0 +1 @@
5c5c7a9f305f009118b22f0e25b257f4

View File

@ -0,0 +1 @@
454b72d68d048b3fc97fd9c2318f5221652bb48d

View 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>

View File

@ -0,0 +1 @@
fa0980ad846135161a96dc65f6db5636

View File

@ -0,0 +1 @@
a5d6a538b0c23f5961cdf244d4965b7d87f07c29

View File

@ -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>

View File

@ -1 +1 @@
371050487d0341b8ad5e5115a28669c1
8517ec37e2b087a9649bb383e5fe7ba3

View File

@ -1 +1 @@
9e1e537f5927907ac635f4784fc82d467d20b70e
9764bad67bbb3de5e80811b8ae6a551d4d66a147

2
src/main/repo/mvn-repo-install.sh Normal file → Executable file
View 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

View File

@ -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");

View 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;
}
}

View 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

View 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

View 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

View 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 ]