1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-02 05:30:53 +00:00

Implemented pointer math (+/-) fixing

This commit is contained in:
jespergravgaard 2019-04-18 01:06:22 +02:00
parent 85317a1c5e
commit 287a6ecb2e
16 changed files with 765 additions and 151 deletions

View File

@ -0,0 +1,4 @@
lda {c1}
sta {z1}
lda {c1}+1
sta {z1}+1

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorSizeOf;
@ -7,7 +8,10 @@ import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ListIterator;
@ -30,28 +34,9 @@ public class Pass1PointerSizeofFix extends Pass1Base {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if((assignment.getrValue1() == null) && (assignment.getOperator() != null) && (assignment.getrValue2() instanceof VariableRef)) {
// Found assignment of unary operator
VariableRef varRef = (VariableRef) assignment.getrValue2();
Variable variable = getScope().getVariable(varRef);
if(variable.getType() instanceof SymbolTypePointer) {
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(pointerType.getElementType().getSizeBytes() > 1) {
// Unary operation on non-byte pointer type - sizeof()-handling is needed!
if(Operators.INCREMENT.equals(assignment.getOperator())) {
// Pointer increment - add sizeof(type) instead
getLog().append("Fixing pointer increment " + statement.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.PLUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
} else if(Operators.DECREMENT.equals(assignment.getOperator())) {
// Pointer Decrement - add sizeof(type) instead
getLog().append("Fixing pointer decrement " + statement.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.MINUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
}
}
}
fixPointerUnary(assignment);
} else if((assignment.getrValue1() instanceof VariableRef) && (assignment.getOperator() != null) && (assignment.getrValue2() != null)) {
fixPointerBinary(block, stmtIt, assignment);
}
}
}
@ -59,5 +44,63 @@ public class Pass1PointerSizeofFix extends Pass1Base {
return false;
}
/**
* Examine if the binary operation in the assignment is a pointer operation - and fix it to reflect sizeof()
*
* @param assignment The assignment statement
*/
public void fixPointerBinary(ControlFlowBlock block, ListIterator<Statement> stmtIt, StatementAssignment assignment) {
VariableRef varRef = (VariableRef) assignment.getrValue1();
Variable variable = getScope().getVariable(varRef);
if(variable.getType() instanceof SymbolTypePointer) {
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(pointerType.getElementType().getSizeBytes() > 1) {
// Binary operation on a non-byte pointer - sizeof()-handling is probably needed!
if(Operators.PLUS.equals(assignment.getOperator()) || Operators.MINUS.equals(assignment.getOperator())) {
// Adding to a pointer - multiply by sizeof()
getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false));
VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
tmpVar.setType(SymbolType.BYTE);
stmtIt.remove();
ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS));
stmtIt.add(assignment);
assignment.setrValue2(tmpVar.getRef());
}
}
}
}
/**
* Examine if the unary operation in the assignment is a pointer operation - and fix it to reflect sizeof()
*
* @param assignment The assignment statement
*/
public void fixPointerUnary(StatementAssignment assignment) {
// Found assignment of unary operator
VariableRef varRef = (VariableRef) assignment.getrValue2();
Variable variable = getScope().getVariable(varRef);
if(variable.getType() instanceof SymbolTypePointer) {
SymbolTypePointer pointerType = (SymbolTypePointer) variable.getType();
if(pointerType.getElementType().getSizeBytes() > 1) {
// Unary operation on non-byte pointer type - sizeof()-handling is needed!
if(Operators.INCREMENT.equals(assignment.getOperator())) {
// Pointer increment - add sizeof(type) instead
getLog().append("Fixing pointer increment " + assignment.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.PLUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
} else if(Operators.DECREMENT.equals(assignment.getOperator())) {
// Pointer Decrement - add sizeof(type) instead
getLog().append("Fixing pointer decrement " + assignment.toString(getProgram(), false));
assignment.setrValue1(assignment.getrValue2());
assignment.setOperator(Operators.MINUS);
assignment.setrValue2(OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()));
}
}
}
}
}

View File

@ -42,6 +42,11 @@ public class TestPrograms {
compileAndCompare("word-pointer-math");
}
@Test
public void testWordPointerMath0() throws IOException, URISyntaxException {
compileAndCompare("word-pointer-math-0");
}
@Test
public void testWordPointerIteration() throws IOException, URISyntaxException {
compileAndCompare("word-pointer-iteration");

View File

@ -0,0 +1,11 @@
// Tests simple word pointer math
void main() {
word* words = $0400;
const byte* SCREEN = $400+6*40;
word w1 = *(words+1);
SCREEN[0] = <w1;
SCREEN[1] = >w1;
word w2 = *(words+2);
SCREEN[2] = <w2;
SCREEN[3] = >w2;
}

View File

@ -2,6 +2,7 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_WORD = 2
main: {
.label SCREEN = $400
.label w = 5
@ -21,8 +22,11 @@ main: {
iny
lda (wp),y
sta w+1
inc wp
bne !+
lda #SIZEOF_WORD
clc
adc wp
sta wp
bcc !+
inc wp+1
!:
lda w

View File

@ -15,7 +15,7 @@ main::@1: scope:[main] from main main::@1
[5] (byte) main::idx#4 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::idx#3 )
[5] (word*) main::wp#2 ← phi( main/(const word[]) main::words#0 main::@1/(word*) main::wp#1 )
[6] (word) main::w#0 ← *((word*) main::wp#2)
[7] (word*) main::wp#1 ← ++ (word*) main::wp#2
[7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD
[8] (byte~) main::$0 ← < (word) main::w#0
[9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$0
[10] (byte) main::idx#1 ← ++ (byte) main::idx#4

View File

@ -1,3 +1,4 @@
Fixing pointer increment (word*) main::wp ← ++ (word*) main::wp
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -14,7 +15,7 @@ main::@1: scope:[main] from main main::@1
(byte) main::idx#4 ← phi( main/(byte) main::idx#0 main::@1/(byte) main::idx#3 )
(word*) main::wp#2 ← phi( main/(word*) main::wp#0 main::@1/(word*) main::wp#1 )
(word) main::w#0 ← *((word*) main::wp#2)
(word*) main::wp#1 ← ++ (word*) main::wp#2
(word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD
(byte~) main::$0 ← < (word) main::w#0
*((byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$0
(byte) main::idx#1 ← ++ (byte) main::idx#4
@ -41,6 +42,7 @@ SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte) SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte~) main::$0
(byte~) main::$1
@ -123,7 +125,7 @@ main::@1: scope:[main] from main main::@1
[5] (byte) main::idx#4 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::idx#3 )
[5] (word*) main::wp#2 ← phi( main/(const word[]) main::words#0 main::@1/(word*) main::wp#1 )
[6] (word) main::w#0 ← *((word*) main::wp#2)
[7] (word*) main::wp#1 ← ++ (word*) main::wp#2
[7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD
[8] (byte~) main::$0 ← < (word) main::w#0
[9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$0
[10] (byte) main::idx#1 ← ++ (byte) main::idx#4
@ -194,6 +196,7 @@ INITIAL ASM
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
@ -251,9 +254,12 @@ main: {
iny
lda (wp),y
sta w+1
//SEG21 [7] (word*) main::wp#1 ← ++ (word*) main::wp#2 -- pwuz1=_inc_pwuz1
inc wp
bne !+
//SEG21 [7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc wp
sta wp
bcc !+
inc wp+1
!:
//SEG22 [8] (byte~) main::$0 ← < (word) main::w#0 -- vbuz1=_lo_vwuz2
@ -303,10 +309,12 @@ Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ ma
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:5 [ main::i#2 main::i#1 ]
Statement [7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD [ main::idx#4 main::i#2 main::wp#1 main::w#0 ] ( main:2 [ main::idx#4 main::i#2 main::wp#1 main::w#0 ] ) always clobbers reg byte a
Statement [8] (byte~) main::$0 ← < (word) main::w#0 [ main::idx#4 main::i#2 main::wp#1 main::w#0 main::$0 ] ( main:2 [ main::idx#4 main::i#2 main::wp#1 main::w#0 main::$0 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$1 ← > (word) main::w#0 [ main::i#2 main::wp#1 main::idx#1 main::$1 ] ( main:2 [ main::i#2 main::wp#1 main::idx#1 main::$1 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ main::idx#1 ]
Statement [6] (word) main::w#0 ← *((word*) main::wp#2) [ main::wp#2 main::idx#4 main::i#2 main::w#0 ] ( main:2 [ main::wp#2 main::idx#4 main::i#2 main::w#0 ] ) always clobbers reg byte a reg byte y
Statement [7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD [ main::idx#4 main::i#2 main::wp#1 main::w#0 ] ( main:2 [ main::idx#4 main::i#2 main::wp#1 main::w#0 ] ) always clobbers reg byte a
Statement [8] (byte~) main::$0 ← < (word) main::w#0 [ main::idx#4 main::i#2 main::wp#1 main::w#0 main::$0 ] ( main:2 [ main::idx#4 main::i#2 main::wp#1 main::w#0 main::$0 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$1 ← > (word) main::w#0 [ main::i#2 main::wp#1 main::idx#1 main::$1 ] ( main:2 [ main::i#2 main::wp#1 main::idx#1 main::$1 ] ) always clobbers reg byte a
Potential registers zp ZP_WORD:2 [ main::wp#2 main::wp#1 ] : zp ZP_WORD:2 ,
@ -322,13 +330,13 @@ REGISTER UPLIFT SCOPES
Uplift Scope [main] 22: zp ZP_BYTE:8 [ main::$0 ] 22: zp ZP_BYTE:10 [ main::$1 ] 22: zp ZP_BYTE:11 [ main::idx#2 ] 18.7: zp ZP_WORD:2 [ main::wp#2 main::wp#1 ] 18.7: zp ZP_BYTE:5 [ main::i#2 main::i#1 ] 13.93: zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ] 11: zp ZP_BYTE:9 [ main::idx#1 ] 6.6: zp ZP_WORD:6 [ main::w#0 ]
Uplift Scope []
Uplifting [main] best 1118 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::idx#2 ] zp ZP_WORD:2 [ main::wp#2 main::wp#1 ] reg byte x [ main::i#2 main::i#1 ] zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ] zp ZP_BYTE:9 [ main::idx#1 ] zp ZP_WORD:6 [ main::w#0 ]
Uplifting [main] best 1168 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::idx#2 ] zp ZP_WORD:2 [ main::wp#2 main::wp#1 ] reg byte x [ main::i#2 main::i#1 ] zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ] zp ZP_BYTE:9 [ main::idx#1 ] zp ZP_WORD:6 [ main::w#0 ]
Limited combination testing to 100 combinations of 768 possible.
Uplifting [] best 1118 combination
Uplifting [] best 1168 combination
Attempting to uplift remaining variables inzp ZP_BYTE:4 [ main::idx#4 main::idx#3 ]
Uplifting [main] best 1118 combination zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ]
Uplifting [main] best 1168 combination zp ZP_BYTE:4 [ main::idx#4 main::idx#3 ]
Attempting to uplift remaining variables inzp ZP_BYTE:9 [ main::idx#1 ]
Uplifting [main] best 1028 combination reg byte y [ main::idx#1 ]
Uplifting [main] best 1078 combination reg byte y [ main::idx#1 ]
Allocated (was zp ZP_WORD:6) zp ZP_WORD:5 [ main::w#0 ]
ASSEMBLER BEFORE OPTIMIZATION
@ -339,6 +347,7 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
@ -389,9 +398,12 @@ main: {
iny
lda (wp),y
sta w+1
//SEG21 [7] (word*) main::wp#1 ← ++ (word*) main::wp#2 -- pwuz1=_inc_pwuz1
inc wp
bne !+
//SEG21 [7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc wp
sta wp
bcc !+
inc wp+1
!:
//SEG22 [8] (byte~) main::$0 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1
@ -459,6 +471,7 @@ FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte~) main::$0 reg byte a 22.0
(byte~) main::$1 reg byte a 22.0
@ -493,7 +506,7 @@ reg byte a [ main::idx#2 ]
FINAL ASSEMBLER
Score: 896
Score: 946
//SEG0 File Comments
// Tests simple word pointer iteration
@ -502,6 +515,7 @@ Score: 896
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
@ -539,9 +553,12 @@ main: {
iny
lda (wp),y
sta w+1
//SEG21 [7] (word*) main::wp#1 ← ++ (word*) main::wp#2 -- pwuz1=_inc_pwuz1
inc wp
bne !+
//SEG21 [7] (word*) main::wp#1 ← (word*) main::wp#2 + (const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1
lda #SIZEOF_WORD
clc
adc wp
sta wp
bcc !+
inc wp+1
!:
//SEG22 [8] (byte~) main::$0 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1

View File

@ -1,6 +1,7 @@
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte~) main::$0 reg byte a 22.0
(byte~) main::$1 reg byte a 22.0

View File

@ -0,0 +1,28 @@
// Tests simple word pointer math
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const SIZEOF_WORD = 2
main: {
.label words = $400
.label SCREEN = $400+6*$28
.label w1 = 2
.label w2 = 2
lda words+1*SIZEOF_WORD
sta w1
lda words+1*SIZEOF_WORD+1
sta w1+1
lda w1
sta SCREEN
lda w1+1
sta SCREEN+1
lda words+2*SIZEOF_WORD
sta w2
lda words+2*SIZEOF_WORD+1
sta w2+1
lda w2
sta SCREEN+2
lda w2+1
sta SCREEN+3
rts
}

View File

@ -0,0 +1,24 @@
@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] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD)
[5] (byte~) main::$3 ← < (word) main::w1#0
[6] *((const byte*) main::SCREEN#0) ← (byte~) main::$3
[7] (byte~) main::$4 ← > (word) main::w1#0
[8] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4
[9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD)
[10] (byte~) main::$6 ← < (word) main::w2#0
[11] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6
[12] (byte~) main::$7 ← > (word) main::w2#0
[13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7
to:main::@return
main::@return: scope:[main] from main
[14] return
to:@return

View File

@ -0,0 +1,421 @@
Fixing pointer addition (word*~) main::$2 ← (word*) main::words + (byte/signed byte/word/signed word/dword/signed dword) 1
Fixing pointer addition (word*~) main::$5 ← (word*) main::words + (byte/signed byte/word/signed word/dword/signed dword) 2
Identified constant variable (word*) main::words
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(word*) main::words#0 ← ((word*)) (word/signed word/dword/signed dword) $400
(byte/word/signed word/dword/signed dword~) main::$0 ← (byte/signed byte/word/signed word/dword/signed dword) 6 * (byte/signed byte/word/signed word/dword/signed dword) $28
(word/signed dword/dword/signed word~) main::$1 ← (word/signed word/dword/signed dword) $400 + (byte/word/signed word/dword/signed dword~) main::$0
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed dword/dword/signed word~) main::$1
(byte) main::$8 ← (byte/signed byte/word/signed word/dword/signed dword) 1 * (const byte) SIZEOF_WORD
(word*~) main::$2 ← (word*) main::words#0 + (byte) main::$8
(word) main::w1#0 ← *((word*~) main::$2)
(byte~) main::$3 ← < (word) main::w1#0
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$3
(byte~) main::$4 ← > (word) main::w1#0
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4
(byte) main::$9 ← (byte/signed byte/word/signed word/dword/signed dword) 2 * (const byte) SIZEOF_WORD
(word*~) main::$5 ← (word*) main::words#0 + (byte) main::$9
(word) main::w2#0 ← *((word*~) main::$5)
(byte~) main::$6 ← < (word) main::w2#0
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6
(byte~) main::$7 ← > (word) main::w2#0
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7
to:main::@return
main::@return: scope:[main] from main
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte) SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte/word/signed word/dword/signed dword~) main::$0
(word/signed dword/dword/signed word~) main::$1
(word*~) main::$2
(byte~) main::$3
(byte~) main::$4
(word*~) main::$5
(byte~) main::$6
(byte~) main::$7
(byte) main::$8
(byte) main::$9
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(word) main::w1
(word) main::w1#0
(word) main::w2
(word) main::w2#0
(word*) main::words
(word*) main::words#0
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Constant (const word*) main::words#0 = ((word*))$400
Constant (const byte/word/signed word/dword/signed dword) main::$0 = 6*$28
Constant (const byte) main::$8 = 1*SIZEOF_WORD
Constant (const byte) main::$9 = 2*SIZEOF_WORD
Successful SSA optimization Pass2ConstantIdentification
Constant (const word/signed dword/dword/signed word) main::$1 = $400+main::$0
Constant (const word*) main::$2 = main::words#0+main::$8
Constant (const word*) main::$5 = main::words#0+main::$9
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte*) main::SCREEN#0 = ((byte*))main::$1
Successful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+0)
Consolidated array index constant in *(main::SCREEN#0+1)
Consolidated array index constant in *(main::SCREEN#0+2)
Consolidated array index constant in *(main::SCREEN#0+3)
Successful SSA optimization Pass2ConstantAdditionElimination
Constant inlined main::$1 = (word/signed word/dword/signed dword) $400+(byte/signed byte/word/signed word/dword/signed dword) 6*(byte/signed byte/word/signed word/dword/signed dword) $28
Constant inlined main::$2 = (const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD
Constant inlined main::$0 = (byte/signed byte/word/signed word/dword/signed dword) 6*(byte/signed byte/word/signed word/dword/signed dword) $28
Constant inlined main::$5 = (const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD
Constant inlined main::$9 = (byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD
Constant inlined main::$8 = (byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD
Successful SSA optimization Pass2ConstantInlining
Simplifying constant plus zero main::SCREEN#0+0
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
CALL GRAPH
Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD)
[5] (byte~) main::$3 ← < (word) main::w1#0
[6] *((const byte*) main::SCREEN#0) ← (byte~) main::$3
[7] (byte~) main::$4 ← > (word) main::w1#0
[8] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4
[9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD)
[10] (byte~) main::$6 ← < (word) main::w2#0
[11] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6
[12] (byte~) main::$7 ← > (word) main::w2#0
[13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7
to:main::@return
main::@return: scope:[main] from main
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::$3 4.0
(byte~) main::$4 4.0
(byte~) main::$6 4.0
(byte~) main::$7 4.0
(byte*) main::SCREEN
(word) main::w1
(word) main::w1#0 2.0
(word) main::w2
(word) main::w2#0 2.0
(word*) main::words
Initial phi equivalence classes
Added variable main::w1#0 to zero page equivalence class [ main::w1#0 ]
Added variable main::$3 to zero page equivalence class [ main::$3 ]
Added variable main::$4 to zero page equivalence class [ main::$4 ]
Added variable main::w2#0 to zero page equivalence class [ main::w2#0 ]
Added variable main::$6 to zero page equivalence class [ main::$6 ]
Added variable main::$7 to zero page equivalence class [ main::$7 ]
Complete equivalence classes
[ main::w1#0 ]
[ main::$3 ]
[ main::$4 ]
[ main::w2#0 ]
[ main::$6 ]
[ main::$7 ]
Allocated zp ZP_WORD:2 [ main::w1#0 ]
Allocated zp ZP_BYTE:4 [ main::$3 ]
Allocated zp ZP_BYTE:5 [ main::$4 ]
Allocated zp ZP_WORD:6 [ main::w2#0 ]
Allocated zp ZP_BYTE:8 [ main::$6 ]
Allocated zp ZP_BYTE:9 [ main::$7 ]
INITIAL ASM
//SEG0 File Comments
// Tests simple word pointer math
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label words = $400
.label SCREEN = $400+6*$28
.label _3 = 4
.label _4 = 5
.label _6 = 8
.label _7 = 9
.label w1 = 2
.label w2 = 6
//SEG10 [4] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+1*SIZEOF_WORD
sta w1
lda words+1*SIZEOF_WORD+1
sta w1+1
//SEG11 [5] (byte~) main::$3 ← < (word) main::w1#0 -- vbuz1=_lo_vwuz2
lda w1
sta _3
//SEG12 [6] *((const byte*) main::SCREEN#0) ← (byte~) main::$3 -- _deref_pbuc1=vbuz1
lda _3
sta SCREEN
//SEG13 [7] (byte~) main::$4 ← > (word) main::w1#0 -- vbuz1=_hi_vwuz2
lda w1+1
sta _4
//SEG14 [8] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4 -- _deref_pbuc1=vbuz1
lda _4
sta SCREEN+1
//SEG15 [9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+2*SIZEOF_WORD
sta w2
lda words+2*SIZEOF_WORD+1
sta w2+1
//SEG16 [10] (byte~) main::$6 ← < (word) main::w2#0 -- vbuz1=_lo_vwuz2
lda w2
sta _6
//SEG17 [11] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6 -- _deref_pbuc1=vbuz1
lda _6
sta SCREEN+2
//SEG18 [12] (byte~) main::$7 ← > (word) main::w2#0 -- vbuz1=_hi_vwuz2
lda w2+1
sta _7
//SEG19 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7 -- _deref_pbuc1=vbuz1
lda _7
sta SCREEN+3
jmp breturn
//SEG20 main::@return
breturn:
//SEG21 [14] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD) [ main::w1#0 ] ( main:2 [ main::w1#0 ] ) always clobbers reg byte a
Statement [5] (byte~) main::$3 ← < (word) main::w1#0 [ main::w1#0 main::$3 ] ( main:2 [ main::w1#0 main::$3 ] ) always clobbers reg byte a
Statement [7] (byte~) main::$4 ← > (word) main::w1#0 [ main::$4 ] ( main:2 [ main::$4 ] ) always clobbers reg byte a
Statement [9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD) [ main::w2#0 ] ( main:2 [ main::w2#0 ] ) always clobbers reg byte a
Statement [10] (byte~) main::$6 ← < (word) main::w2#0 [ main::w2#0 main::$6 ] ( main:2 [ main::w2#0 main::$6 ] ) always clobbers reg byte a
Statement [12] (byte~) main::$7 ← > (word) main::w2#0 [ main::$7 ] ( main:2 [ main::$7 ] ) always clobbers reg byte a
Potential registers zp ZP_WORD:2 [ main::w1#0 ] : zp ZP_WORD:2 ,
Potential registers zp ZP_BYTE:4 [ main::$3 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:5 [ main::$4 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_WORD:6 [ main::w2#0 ] : zp ZP_WORD:6 ,
Potential registers zp ZP_BYTE:8 [ main::$6 ] : zp ZP_BYTE:8 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:9 [ main::$7 ] : zp ZP_BYTE:9 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 4: zp ZP_BYTE:4 [ main::$3 ] 4: zp ZP_BYTE:5 [ main::$4 ] 4: zp ZP_BYTE:8 [ main::$6 ] 4: zp ZP_BYTE:9 [ main::$7 ] 2: zp ZP_WORD:2 [ main::w1#0 ] 2: zp ZP_WORD:6 [ main::w2#0 ]
Uplift Scope []
Uplifting [main] best 77 combination reg byte a [ main::$3 ] reg byte a [ main::$4 ] reg byte a [ main::$6 ] reg byte a [ main::$7 ] zp ZP_WORD:2 [ main::w1#0 ] zp ZP_WORD:6 [ main::w2#0 ]
Limited combination testing to 100 combinations of 256 possible.
Uplifting [] best 77 combination
Coalescing zero page register [ zp ZP_WORD:2 [ main::w1#0 ] ] with [ zp ZP_WORD:6 [ main::w2#0 ] ]
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Tests simple word pointer math
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label words = $400
.label SCREEN = $400+6*$28
.label w1 = 2
.label w2 = 2
//SEG10 [4] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+1*SIZEOF_WORD
sta w1
lda words+1*SIZEOF_WORD+1
sta w1+1
//SEG11 [5] (byte~) main::$3 ← < (word) main::w1#0 -- vbuaa=_lo_vwuz1
lda w1
//SEG12 [6] *((const byte*) main::SCREEN#0) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa
sta SCREEN
//SEG13 [7] (byte~) main::$4 ← > (word) main::w1#0 -- vbuaa=_hi_vwuz1
lda w1+1
//SEG14 [8] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4 -- _deref_pbuc1=vbuaa
sta SCREEN+1
//SEG15 [9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+2*SIZEOF_WORD
sta w2
lda words+2*SIZEOF_WORD+1
sta w2+1
//SEG16 [10] (byte~) main::$6 ← < (word) main::w2#0 -- vbuaa=_lo_vwuz1
lda w2
//SEG17 [11] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6 -- _deref_pbuc1=vbuaa
sta SCREEN+2
//SEG18 [12] (byte~) main::$7 ← > (word) main::w2#0 -- vbuaa=_hi_vwuz1
lda w2+1
//SEG19 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7 -- _deref_pbuc1=vbuaa
sta SCREEN+3
jmp breturn
//SEG20 main::@return
breturn:
//SEG21 [14] return
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte~) main::$3 reg byte a 4.0
(byte~) main::$4 reg byte a 4.0
(byte~) main::$6 reg byte a 4.0
(byte~) main::$7 reg byte a 4.0
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400+(byte/signed byte/word/signed word/dword/signed dword) 6*(byte/signed byte/word/signed word/dword/signed dword) $28
(word) main::w1
(word) main::w1#0 w1 zp ZP_WORD:2 2.0
(word) main::w2
(word) main::w2#0 w2 zp ZP_WORD:2 2.0
(word*) main::words
(const word*) main::words#0 words = ((word*))(word/signed word/dword/signed dword) $400
zp ZP_WORD:2 [ main::w1#0 main::w2#0 ]
reg byte a [ main::$3 ]
reg byte a [ main::$4 ]
reg byte a [ main::$6 ]
reg byte a [ main::$7 ]
FINAL ASSEMBLER
Score: 62
//SEG0 File Comments
// Tests simple word pointer math
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
.const SIZEOF_WORD = 2
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label words = $400
.label SCREEN = $400+6*$28
.label w1 = 2
.label w2 = 2
//SEG10 [4] (word) main::w1#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 1*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+1*SIZEOF_WORD
sta w1
lda words+1*SIZEOF_WORD+1
sta w1+1
//SEG11 [5] (byte~) main::$3 ← < (word) main::w1#0 -- vbuaa=_lo_vwuz1
lda w1
//SEG12 [6] *((const byte*) main::SCREEN#0) ← (byte~) main::$3 -- _deref_pbuc1=vbuaa
sta SCREEN
//SEG13 [7] (byte~) main::$4 ← > (word) main::w1#0 -- vbuaa=_hi_vwuz1
lda w1+1
//SEG14 [8] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$4 -- _deref_pbuc1=vbuaa
sta SCREEN+1
//SEG15 [9] (word) main::w2#0 ← *((const word*) main::words#0+(byte/signed byte/word/signed word/dword/signed dword) 2*(const byte) SIZEOF_WORD) -- vwuz1=_deref_pwuc1
lda words+2*SIZEOF_WORD
sta w2
lda words+2*SIZEOF_WORD+1
sta w2+1
//SEG16 [10] (byte~) main::$6 ← < (word) main::w2#0 -- vbuaa=_lo_vwuz1
lda w2
//SEG17 [11] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte~) main::$6 -- _deref_pbuc1=vbuaa
sta SCREEN+2
//SEG18 [12] (byte~) main::$7 ← > (word) main::w2#0 -- vbuaa=_hi_vwuz1
lda w2+1
//SEG19 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 3) ← (byte~) main::$7 -- _deref_pbuc1=vbuaa
sta SCREEN+3
//SEG20 main::@return
//SEG21 [14] return
rts
}

View File

@ -0,0 +1,24 @@
(label) @1
(label) @begin
(label) @end
(const byte) SIZEOF_WORD SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(byte~) main::$3 reg byte a 4.0
(byte~) main::$4 reg byte a 4.0
(byte~) main::$6 reg byte a 4.0
(byte~) main::$7 reg byte a 4.0
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400+(byte/signed byte/word/signed word/dword/signed dword) 6*(byte/signed byte/word/signed word/dword/signed dword) $28
(word) main::w1
(word) main::w1#0 w1 zp ZP_WORD:2 2.0
(word) main::w2
(word) main::w2#0 w2 zp ZP_WORD:2 2.0
(word*) main::words
(const word*) main::words#0 words = ((word*))(word/signed word/dword/signed dword) $400
zp ZP_WORD:2 [ main::w1#0 main::w2#0 ]
reg byte a [ main::$3 ]
reg byte a [ main::$4 ]
reg byte a [ main::$6 ]
reg byte a [ main::$7 ]

View File

@ -12,6 +12,7 @@ main: {
tax
b1:
txa
asl
clc
adc #<words
sta _0

View File

@ -13,18 +13,19 @@ main: scope:[main] from @1
main::@1: scope:[main] from main main::@1
[5] (byte) main::idx#4 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::idx#3 )
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
[6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2
[7] (word) main::w#0 ← *((word*~) main::$0)
[8] (byte~) main::$1 ← < (word) main::w#0
[9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1
[10] (byte) main::idx#1 ← ++ (byte) main::idx#4
[11] (byte~) main::$2 ← > (word) main::w#0
[12] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2
[13] (byte) main::idx#2 ← ++ (byte) main::idx#1
[14] (byte) main::idx#3 ← ++ (byte) main::idx#2
[15] (byte) main::i#1 ← ++ (byte) main::i#2
[16] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1
[6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1
[7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4
[8] (word) main::w#0 ← *((word*~) main::$0)
[9] (byte~) main::$1 ← < (word) main::w#0
[10] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1
[11] (byte) main::idx#1 ← ++ (byte) main::idx#4
[12] (byte~) main::$2 ← > (word) main::w#0
[13] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2
[14] (byte) main::idx#2 ← ++ (byte) main::idx#1
[15] (byte) main::idx#3 ← ++ (byte) main::idx#2
[16] (byte) main::i#1 ← ++ (byte) main::i#2
[17] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[17] return
[18] return
to:@return

View File

@ -1,3 +1,4 @@
Fixing pointer addition (word*~) main::$0 ← (word[]) main::words + (byte) main::i
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
@ -11,7 +12,8 @@ main: scope:[main] from @1
main::@1: scope:[main] from main main::@1
(byte) main::idx#4 ← phi( main/(byte) main::idx#0 main::@1/(byte) main::idx#3 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
(word*~) main::$0 ← (word[]) main::words#0 + (byte) main::i#2
(byte) main::$4 ← (byte) main::i#2 * (const byte) SIZEOF_WORD
(word*~) main::$0 ← (word[]) main::words#0 + (byte) main::$4
(word) main::w#0 ← *((word*~) main::$0)
(byte~) main::$1 ← < (word) main::w#0
*((byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1
@ -39,11 +41,13 @@ SYMBOL TABLE SSA
(label) @2
(label) @begin
(label) @end
(const byte) SIZEOF_WORD = (byte/signed byte/word/signed word/dword/signed dword) 2
(void()) main()
(word*~) main::$0
(byte~) main::$1
(byte~) main::$2
(bool~) main::$3
(byte) main::$4
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
@ -65,7 +69,7 @@ SYMBOL TABLE SSA
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Simple Condition (bool~) main::$3 [16] if((byte) main::i#1!=rangelast(0,3)) goto main::@1
Simple Condition (bool~) main::$3 [17] if((byte) main::i#1!=rangelast(0,3)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const word[]) main::words#0 = { $3130, $3332, $3534, $3736 }
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
@ -74,6 +78,9 @@ Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value if(main::i#1!=rangelast(0,3)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) 4
Rewriting multiplication to use shift (byte) main::$4 ← (byte) main::i#2 * (const byte) SIZEOF_WORD
Successful SSA optimization Pass2MultiplyToShiftRewriting
Successful SSA optimization PassNEliminateUnusedVars
Inlining constant with var siblings (const byte) main::idx#0
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
@ -88,8 +95,8 @@ CALL GRAPH
Calls in [] to main:2
Created 2 initial phi equivalence classes
Coalesced [18] main::i#3 ← main::i#1
Coalesced [19] main::idx#5 ← main::idx#3
Coalesced [19] main::i#3 ← main::i#1
Coalesced [20] main::idx#5 ← main::idx#3
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) main::@3
Adding NOP phi() at start of @begin
@ -113,20 +120,21 @@ main: scope:[main] from @1
main::@1: scope:[main] from main main::@1
[5] (byte) main::idx#4 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::idx#3 )
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
[6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2
[7] (word) main::w#0 ← *((word*~) main::$0)
[8] (byte~) main::$1 ← < (word) main::w#0
[9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1
[10] (byte) main::idx#1 ← ++ (byte) main::idx#4
[11] (byte~) main::$2 ← > (word) main::w#0
[12] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2
[13] (byte) main::idx#2 ← ++ (byte) main::idx#1
[14] (byte) main::idx#3 ← ++ (byte) main::idx#2
[15] (byte) main::i#1 ← ++ (byte) main::i#2
[16] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1
[6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1
[7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4
[8] (word) main::w#0 ← *((word*~) main::$0)
[9] (byte~) main::$1 ← < (word) main::w#0
[10] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1
[11] (byte) main::idx#1 ← ++ (byte) main::idx#4
[12] (byte~) main::$2 ← > (word) main::w#0
[13] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2
[14] (byte) main::idx#2 ← ++ (byte) main::idx#1
[15] (byte) main::idx#3 ← ++ (byte) main::idx#2
[16] (byte) main::i#1 ← ++ (byte) main::i#2
[17] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[17] return
[18] return
to:@return
@ -135,15 +143,16 @@ VARIABLE REGISTER WEIGHTS
(word*~) main::$0 22.0
(byte~) main::$1 22.0
(byte~) main::$2 22.0
(byte) main::$4 22.0
(byte*) main::SCREEN
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 3.3000000000000003
(byte) main::i#2 3.0
(byte) main::idx
(byte) main::idx#1 11.0
(byte) main::idx#2 22.0
(byte) main::idx#3 7.333333333333333
(byte) main::idx#4 6.6000000000000005
(byte) main::idx#4 5.5
(word) main::w
(word) main::w#0 8.25
(word[]) main::words
@ -151,6 +160,7 @@ VARIABLE REGISTER WEIGHTS
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ main::idx#4 main::idx#3 ]
Added variable main::$4 to zero page equivalence class [ main::$4 ]
Added variable main::$0 to zero page equivalence class [ main::$0 ]
Added variable main::w#0 to zero page equivalence class [ main::w#0 ]
Added variable main::$1 to zero page equivalence class [ main::$1 ]
@ -160,6 +170,7 @@ Added variable main::idx#2 to zero page equivalence class [ main::idx#2 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::idx#4 main::idx#3 ]
[ main::$4 ]
[ main::$0 ]
[ main::w#0 ]
[ main::$1 ]
@ -168,12 +179,13 @@ Complete equivalence classes
[ main::idx#2 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Allocated zp ZP_WORD:4 [ main::$0 ]
Allocated zp ZP_WORD:6 [ main::w#0 ]
Allocated zp ZP_BYTE:8 [ main::$1 ]
Allocated zp ZP_BYTE:9 [ main::idx#1 ]
Allocated zp ZP_BYTE:10 [ main::$2 ]
Allocated zp ZP_BYTE:11 [ main::idx#2 ]
Allocated zp ZP_BYTE:4 [ main::$4 ]
Allocated zp ZP_WORD:5 [ main::$0 ]
Allocated zp ZP_WORD:7 [ main::w#0 ]
Allocated zp ZP_BYTE:9 [ main::$1 ]
Allocated zp ZP_BYTE:10 [ main::idx#1 ]
Allocated zp ZP_BYTE:11 [ main::$2 ]
Allocated zp ZP_BYTE:12 [ main::idx#2 ]
INITIAL ASM
//SEG0 File Comments
@ -202,12 +214,13 @@ bend:
//SEG10 main
main: {
.label SCREEN = $400
.label _0 = 4
.label _1 = 8
.label _2 = $a
.label w = 6
.label idx = 9
.label idx_2 = $b
.label _0 = 5
.label _1 = 9
.label _2 = $b
.label _4 = 4
.label w = 7
.label idx = $a
.label idx_2 = $c
.label idx_3 = 3
.label i = 2
.label idx_4 = 3
@ -227,99 +240,108 @@ main: {
jmp b1
//SEG17 main::@1
b1:
//SEG18 [6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2 -- pwuz1=pwuc1_plus_vbuz2
//SEG18 [6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuz1=vbuz2_rol_1
lda i
asl
sta _4
//SEG19 [7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4 -- pwuz1=pwuc1_plus_vbuz2
lda _4
clc
adc #<words
sta _0
lda #>words
adc #0
sta _0+1
//SEG19 [7] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
//SEG20 [8] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
ldy #0
lda (_0),y
sta w
iny
lda (_0),y
sta w+1
//SEG20 [8] (byte~) main::$1 ← < (word) main::w#0 -- vbuz1=_lo_vwuz2
//SEG21 [9] (byte~) main::$1 ← < (word) main::w#0 -- vbuz1=_lo_vwuz2
lda w
sta _1
//SEG21 [9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuz2
//SEG22 [10] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuz2
lda _1
ldy idx_4
sta SCREEN,y
//SEG22 [10] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuz1=_inc_vbuz2
//SEG23 [11] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuz1=_inc_vbuz2
ldy idx_4
iny
sty idx
//SEG23 [11] (byte~) main::$2 ← > (word) main::w#0 -- vbuz1=_hi_vwuz2
//SEG24 [12] (byte~) main::$2 ← > (word) main::w#0 -- vbuz1=_hi_vwuz2
lda w+1
sta _2
//SEG24 [12] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuz1=vbuz2
//SEG25 [13] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuz1=vbuz2
lda _2
ldy idx
sta SCREEN,y
//SEG25 [13] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuz2
//SEG26 [14] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuz1=_inc_vbuz2
ldy idx
iny
sty idx_2
//SEG26 [14] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuz2
//SEG27 [15] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuz2
ldy idx_2
iny
sty idx_3
//SEG27 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
//SEG28 [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc i
//SEG28 [16] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
//SEG29 [17] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #4
cmp i
bne b1_from_b1
jmp breturn
//SEG29 main::@return
//SEG30 main::@return
breturn:
//SEG30 [17] return
//SEG31 [18] return
rts
// Clever word array that represents C64 numbers 0-7
words: .word $3130, $3332, $3534, $3736
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2 [ main::i#2 main::idx#4 main::$0 ] ( main:2 [ main::i#2 main::idx#4 main::$0 ] ) always clobbers reg byte a
Statement [6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#2 main::idx#4 main::$4 ] ( main:2 [ main::i#2 main::idx#4 main::$4 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Statement [7] (word) main::w#0 ← *((word*~) main::$0) [ main::i#2 main::idx#4 main::w#0 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 ] ) always clobbers reg byte a reg byte y
Statement [7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4 [ main::i#2 main::idx#4 main::$0 ] ( main:2 [ main::i#2 main::idx#4 main::$0 ] ) always clobbers reg byte a
Statement [8] (word) main::w#0 ← *((word*~) main::$0) [ main::i#2 main::idx#4 main::w#0 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Statement [8] (byte~) main::$1 ← < (word) main::w#0 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$2 ← > (word) main::w#0 [ main::i#2 main::idx#1 main::$2 ] ( main:2 [ main::i#2 main::idx#1 main::$2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:9 [ main::idx#1 ]
Statement [6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2 [ main::i#2 main::idx#4 main::$0 ] ( main:2 [ main::i#2 main::idx#4 main::$0 ] ) always clobbers reg byte a
Statement [7] (word) main::w#0 ← *((word*~) main::$0) [ main::i#2 main::idx#4 main::w#0 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 ] ) always clobbers reg byte a reg byte y
Statement [8] (byte~) main::$1 ← < (word) main::w#0 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ) always clobbers reg byte a
Statement [11] (byte~) main::$2 ← > (word) main::w#0 [ main::i#2 main::idx#1 main::$2 ] ( main:2 [ main::i#2 main::idx#1 main::$2 ] ) always clobbers reg byte a
Statement [9] (byte~) main::$1 ← < (word) main::w#0 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ) always clobbers reg byte a
Statement [12] (byte~) main::$2 ← > (word) main::w#0 [ main::i#2 main::idx#1 main::$2 ] ( main:2 [ main::i#2 main::idx#1 main::$2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:10 [ main::idx#1 ]
Statement [6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#2 main::idx#4 main::$4 ] ( main:2 [ main::i#2 main::idx#4 main::$4 ] ) always clobbers reg byte a
Statement [7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4 [ main::i#2 main::idx#4 main::$0 ] ( main:2 [ main::i#2 main::idx#4 main::$0 ] ) always clobbers reg byte a
Statement [8] (word) main::w#0 ← *((word*~) main::$0) [ main::i#2 main::idx#4 main::w#0 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 ] ) always clobbers reg byte a reg byte y
Statement [9] (byte~) main::$1 ← < (word) main::w#0 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ( main:2 [ main::i#2 main::idx#4 main::w#0 main::$1 ] ) always clobbers reg byte a
Statement [12] (byte~) main::$2 ← > (word) main::w#0 [ main::i#2 main::idx#1 main::$2 ] ( main:2 [ main::i#2 main::idx#1 main::$2 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x ,
Potential registers zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ] : zp ZP_BYTE:3 , reg byte x ,
Potential registers zp ZP_WORD:4 [ main::$0 ] : zp ZP_WORD:4 ,
Potential registers zp ZP_WORD:6 [ main::w#0 ] : zp ZP_WORD:6 ,
Potential registers zp ZP_BYTE:8 [ main::$1 ] : zp ZP_BYTE:8 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:9 [ main::idx#1 ] : zp ZP_BYTE:9 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:10 [ main::$2 ] : zp ZP_BYTE:10 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:11 [ main::idx#2 ] : zp ZP_BYTE:11 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:4 [ main::$4 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_WORD:5 [ main::$0 ] : zp ZP_WORD:5 ,
Potential registers zp ZP_WORD:7 [ main::w#0 ] : zp ZP_WORD:7 ,
Potential registers zp ZP_BYTE:9 [ main::$1 ] : zp ZP_BYTE:9 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:10 [ main::idx#1 ] : zp ZP_BYTE:10 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:11 [ main::$2 ] : zp ZP_BYTE:11 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:12 [ main::idx#2 ] : zp ZP_BYTE:12 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 22: zp ZP_WORD:4 [ main::$0 ] 22: zp ZP_BYTE:8 [ main::$1 ] 22: zp ZP_BYTE:10 [ main::$2 ] 22: zp ZP_BYTE:11 [ main::idx#2 ] 19.8: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 13.93: zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ] 11: zp ZP_BYTE:9 [ main::idx#1 ] 8.25: zp ZP_WORD:6 [ main::w#0 ]
Uplift Scope [main] 22: zp ZP_BYTE:4 [ main::$4 ] 22: zp ZP_WORD:5 [ main::$0 ] 22: zp ZP_BYTE:9 [ main::$1 ] 22: zp ZP_BYTE:11 [ main::$2 ] 22: zp ZP_BYTE:12 [ main::idx#2 ] 19.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 12.83: zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ] 11: zp ZP_BYTE:10 [ main::idx#1 ] 8.25: zp ZP_WORD:7 [ main::w#0 ]
Uplift Scope []
Uplifting [main] best 1053 combination zp ZP_WORD:4 [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::idx#2 ] reg byte x [ main::i#2 main::i#1 ] zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ] zp ZP_BYTE:9 [ main::idx#1 ] zp ZP_WORD:6 [ main::w#0 ]
Limited combination testing to 100 combinations of 768 possible.
Uplifting [] best 1053 combination
Uplifting [main] best 1173 combination reg byte a [ main::$4 ] zp ZP_WORD:5 [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::idx#2 ] zp ZP_BYTE:2 [ main::i#2 main::i#1 ] zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ] zp ZP_BYTE:10 [ main::idx#1 ] zp ZP_WORD:7 [ main::w#0 ]
Limited combination testing to 100 combinations of 3072 possible.
Uplifting [] best 1173 combination
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplifting [main] best 1073 combination reg byte x [ main::i#2 main::i#1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Uplifting [main] best 1053 combination zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Attempting to uplift remaining variables inzp ZP_BYTE:9 [ main::idx#1 ]
Uplifting [main] best 963 combination reg byte y [ main::idx#1 ]
Uplifting [main] best 1073 combination zp ZP_BYTE:3 [ main::idx#4 main::idx#3 ]
Attempting to uplift remaining variables inzp ZP_BYTE:10 [ main::idx#1 ]
Uplifting [main] best 983 combination reg byte y [ main::idx#1 ]
Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ main::idx#4 main::idx#3 ]
Allocated (was zp ZP_WORD:4) zp ZP_WORD:3 [ main::$0 ]
Allocated (was zp ZP_WORD:6) zp ZP_WORD:5 [ main::w#0 ]
Allocated (was zp ZP_WORD:5) zp ZP_WORD:3 [ main::$0 ]
Allocated (was zp ZP_WORD:7) zp ZP_WORD:5 [ main::w#0 ]
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
@ -366,49 +388,51 @@ main: {
jmp b1
//SEG17 main::@1
b1:
//SEG18 [6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2 -- pwuz1=pwuc1_plus_vbuxx
//SEG18 [6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_rol_1
txa
asl
//SEG19 [7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4 -- pwuz1=pwuc1_plus_vbuaa
clc
adc #<words
sta _0
lda #>words
adc #0
sta _0+1
//SEG19 [7] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
//SEG20 [8] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
ldy #0
lda (_0),y
sta w
iny
lda (_0),y
sta w+1
//SEG20 [8] (byte~) main::$1 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1
//SEG21 [9] (byte~) main::$1 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1
lda w
//SEG21 [9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuaa
//SEG22 [10] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuaa
ldy idx
sta SCREEN,y
//SEG22 [10] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuyy=_inc_vbuz1
//SEG23 [11] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuyy=_inc_vbuz1
ldy idx
iny
//SEG23 [11] (byte~) main::$2 ← > (word) main::w#0 -- vbuaa=_hi_vwuz1
//SEG24 [12] (byte~) main::$2 ← > (word) main::w#0 -- vbuaa=_hi_vwuz1
lda w+1
//SEG24 [12] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuyy=vbuaa
//SEG25 [13] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
//SEG25 [13] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuaa=_inc_vbuyy
//SEG26 [14] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuaa=_inc_vbuyy
iny
tya
//SEG26 [14] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuaa
//SEG27 [15] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuaa
clc
adc #1
sta idx
//SEG27 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
//SEG28 [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG28 [16] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
//SEG29 [17] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #4
bne b1_from_b1
jmp breturn
//SEG29 main::@return
//SEG30 main::@return
breturn:
//SEG30 [17] return
//SEG31 [18] return
rts
// Clever word array that represents C64 numbers 0-7
words: .word $3130, $3332, $3534, $3736
@ -450,18 +474,19 @@ FINAL SYMBOL TABLE
(word*~) main::$0 $0 zp ZP_WORD:3 22.0
(byte~) main::$1 reg byte a 22.0
(byte~) main::$2 reg byte a 22.0
(byte) main::$4 reg byte a 22.0
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 3.3000000000000003
(byte) main::i#2 reg byte x 3.0
(byte) main::idx
(byte) main::idx#1 reg byte y 11.0
(byte) main::idx#2 reg byte a 22.0
(byte) main::idx#3 idx zp ZP_BYTE:2 7.333333333333333
(byte) main::idx#4 idx zp ZP_BYTE:2 6.6000000000000005
(byte) main::idx#4 idx zp ZP_BYTE:2 5.5
(word) main::w
(word) main::w#0 w zp ZP_WORD:5 8.25
(word[]) main::words
@ -469,6 +494,7 @@ FINAL SYMBOL TABLE
reg byte x [ main::i#2 main::i#1 ]
zp ZP_BYTE:2 [ main::idx#4 main::idx#3 ]
reg byte a [ main::$4 ]
zp ZP_WORD:3 [ main::$0 ]
zp ZP_WORD:5 [ main::w#0 ]
reg byte a [ main::$1 ]
@ -478,7 +504,7 @@ reg byte a [ main::idx#2 ]
FINAL ASSEMBLER
Score: 831
Score: 851
//SEG0 File Comments
// Tests simple word pointer math
@ -511,46 +537,48 @@ main: {
//SEG16 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#1] -- register_copy
//SEG17 main::@1
b1:
//SEG18 [6] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::i#2 -- pwuz1=pwuc1_plus_vbuxx
//SEG18 [6] (byte) main::$4 ← (byte) main::i#2 << (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_rol_1
txa
asl
//SEG19 [7] (word*~) main::$0 ← (const word[]) main::words#0 + (byte) main::$4 -- pwuz1=pwuc1_plus_vbuaa
clc
adc #<words
sta _0
lda #>words
adc #0
sta _0+1
//SEG19 [7] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
//SEG20 [8] (word) main::w#0 ← *((word*~) main::$0) -- vwuz1=_deref_pwuz2
ldy #0
lda (_0),y
sta w
iny
lda (_0),y
sta w+1
//SEG20 [8] (byte~) main::$1 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1
//SEG21 [9] (byte~) main::$1 ← < (word) main::w#0 -- vbuaa=_lo_vwuz1
lda w
//SEG21 [9] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuaa
//SEG22 [10] *((const byte*) main::SCREEN#0 + (byte) main::idx#4) ← (byte~) main::$1 -- pbuc1_derefidx_vbuz1=vbuaa
ldy idx
sta SCREEN,y
//SEG22 [10] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuyy=_inc_vbuz1
//SEG23 [11] (byte) main::idx#1 ← ++ (byte) main::idx#4 -- vbuyy=_inc_vbuz1
iny
//SEG23 [11] (byte~) main::$2 ← > (word) main::w#0 -- vbuaa=_hi_vwuz1
//SEG24 [12] (byte~) main::$2 ← > (word) main::w#0 -- vbuaa=_hi_vwuz1
lda w+1
//SEG24 [12] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuyy=vbuaa
//SEG25 [13] *((const byte*) main::SCREEN#0 + (byte) main::idx#1) ← (byte~) main::$2 -- pbuc1_derefidx_vbuyy=vbuaa
sta SCREEN,y
//SEG25 [13] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuaa=_inc_vbuyy
//SEG26 [14] (byte) main::idx#2 ← ++ (byte) main::idx#1 -- vbuaa=_inc_vbuyy
iny
tya
//SEG26 [14] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuaa
//SEG27 [15] (byte) main::idx#3 ← ++ (byte) main::idx#2 -- vbuz1=_inc_vbuaa
clc
adc #1
sta idx
//SEG27 [15] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
//SEG28 [16] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG28 [16] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
//SEG29 [17] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 4) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #4
bne b1
//SEG29 main::@return
//SEG30 [17] return
//SEG30 main::@return
//SEG31 [18] return
rts
// Clever word array that represents C64 numbers 0-7
words: .word $3130, $3332, $3534, $3736

View File

@ -5,18 +5,19 @@
(word*~) main::$0 $0 zp ZP_WORD:3 22.0
(byte~) main::$1 reg byte a 22.0
(byte~) main::$2 reg byte a 22.0
(byte) main::$4 reg byte a 22.0
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 3.3000000000000003
(byte) main::i#2 reg byte x 3.0
(byte) main::idx
(byte) main::idx#1 reg byte y 11.0
(byte) main::idx#2 reg byte a 22.0
(byte) main::idx#3 idx zp ZP_BYTE:2 7.333333333333333
(byte) main::idx#4 idx zp ZP_BYTE:2 6.6000000000000005
(byte) main::idx#4 idx zp ZP_BYTE:2 5.5
(word) main::w
(word) main::w#0 w zp ZP_WORD:5 8.25
(word[]) main::words
@ -24,6 +25,7 @@
reg byte x [ main::i#2 main::i#1 ]
zp ZP_BYTE:2 [ main::idx#4 main::idx#3 ]
reg byte a [ main::$4 ]
zp ZP_WORD:3 [ main::$0 ]
zp ZP_WORD:5 [ main::w#0 ]
reg byte a [ main::$1 ]