1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-26 18:29:54 +00:00

Init-value of global load/store memory variables is now output directly into data-statements.

This commit is contained in:
jespergravgaard 2020-01-11 14:55:27 +01:00
parent 2eb5aaa24f
commit d5f4b1f690
23 changed files with 144 additions and 222 deletions

View File

@ -0,0 +1,6 @@
ldy {m1}
sty $fe
ldy {m1}+1
sty $ff
ldy #{c1}
sta ($fe),y

View File

@ -0,0 +1,7 @@
sty $fd
ldy {m1}
sty $fe
ldy {m1}+1
sty $ff
ldy $fd
sta ($fe),y

View File

@ -569,7 +569,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
initValue = Initializers.constantify(initValue, new Initializers.ValueTypeSpec(declVarType, declArraySpec), program, statementSource);
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, declVarType, declArraySpec, declVarDirectives, currentDataSegment);
Variable variable = varBuilder.build();
if(variable.isKindConstant() || (variable.isKindLoadStore() && Variable.MemoryArea.MAIN_MEMORY.equals(variable.getMemoryArea()) && initValue instanceof ConstantValue && !declVarStructMember)) {
if(variable.isKindConstant() || (variable.isKindLoadStore() && Variable.MemoryArea.MAIN_MEMORY.equals(variable.getMemoryArea()) && initValue instanceof ConstantValue && !declVarStructMember && variable.getRegister()==null)) {
// Set constant value
ConstantValue constInitValue = getConstInitValue(initValue, initializer, statementSource);
variable.setInitValue(constInitValue);

View File

@ -11,6 +11,7 @@ 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.statements.StatementLValue;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.*;
import java.util.Collection;
@ -190,6 +191,9 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
//getLog().append("Multiple usages for variable. Not optimizing sub-constant " + variable.toString(getProgram()));
return null;
}
final Variable var = getScope().getVar(variable);
if(var.isKindLoadStore())
return null;
StatementLValue statementLValue = getGraph().getAssignment(variable);
if(statementLValue instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statementLValue;

View File

@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.operators.OperatorCastPtr;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
@ -48,6 +49,9 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization {
public RValue attemptInlineDeref(RValue pointer) {
if(pointer instanceof VariableRef) {
VariableRef derefVar = (VariableRef) pointer;
final Variable var = getScope().getVar(derefVar);
if(var.isKindLoadStore())
return null;
StatementLValue derefVarDefined = getGraph().getAssignment(derefVar);
if(derefVarDefined instanceof StatementAssignment) {
StatementAssignment derefAssignment = (StatementAssignment) derefVarDefined;

View File

@ -539,17 +539,13 @@ public class Pass4CodeGeneration {
String alignment = AsmFormat.getAsmNumber(declaredAlignment);
asm.addDataAlignment(alignment);
}
if(variable.getInitValue()!=null) {
if(variable.getInitValue() != null) {
// Variable has a constant init Value
ConstantValue constantValue = variable.getInitValue();
if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString || constantValue instanceof ConstantStructValue || constantValue instanceof StructZero) {
AsmDataChunk asmDataChunk = new AsmDataChunk();
addChunkData(asmDataChunk, constantValue, variable.getType(), variable.getArraySpec(), scopeRef);
asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm);
} else {
throw new InternalError("Constant Variable not handled " + variable.toString(program));
}
} else {
AsmDataChunk asmDataChunk = new AsmDataChunk();
addChunkData(asmDataChunk, constantValue, variable.getType(), variable.getArraySpec(), scopeRef);
asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm);
} else {
// Zero-fill variable
AsmDataChunk asmDataChunk = new AsmDataChunk();
ConstantValue zeroValue = Initializers.createZeroValue(new Initializers.ValueTypeSpec(variable.getType(), variable.getArraySpec()), null);

View File

@ -55,10 +55,13 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
equivalenceClassAdder.visitGraph(getGraph());
// Add any remaining struct load/store variables
for(Variable variable : getSymbols().getAllVariables(true))
if(variable.isStructClassic())
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet );
// Add any load/store variables with an initializer - and load/store struct variables
for(Variable variable : getSymbols().getAllVariables(true)) {
if(variable.isKindLoadStore() && variable.getInitValue()!=null)
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet);
else if(variable.isStructClassic())
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet);
}
getLog().append("Complete equivalence classes");
for(LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {

View File

@ -1,13 +1,8 @@
// Test declaring a variable as "__mem __notssa", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
__bbegin:
lda #0
sta idx
jsr main
rts
main: {
ldx #0
__b1:

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] (byte) idx ← (byte) 0
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -2,7 +2,6 @@ Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) idx ← (byte) 0
to:@1
(void()) main()
@ -33,7 +32,7 @@ SYMBOL TABLE SSA
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte) idx loadstore
(byte) idx loadstore = (byte) 0
(void()) main()
(bool~) main::$0
(label) main::@1
@ -45,12 +44,12 @@ SYMBOL TABLE SSA
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Simple Condition (bool~) main::$0 [7] if((byte) main::i#1!=rangelast(0,5)) goto main::@1
Simple Condition (bool~) main::$0 [6] if((byte) main::i#1!=rangelast(0,5)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [5] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [7] if(main::i#1!=rangelast(0,5)) goto main::@1 to (number) 6
Resolved ranged next value [4] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [6] if(main::i#1!=rangelast(0,5)) goto main::@1 to (number) 6
Adding number conversion cast (unumber) 6 in if((byte) main::i#1!=(number) 6) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 6
@ -61,6 +60,7 @@ Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
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
@ -73,13 +73,14 @@ Coalesced [12] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@3
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] (byte) idx ← (byte) 0
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -105,7 +106,7 @@ main::@return: scope:[main] from main::@1
VARIABLE REGISTER WEIGHTS
(byte) idx loadstore 5.0
(byte) idx loadstore 4.714285714285714 = (byte) 0
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
@ -132,9 +133,6 @@ Target platform is c64basic / MOS6502X
.label SCREEN = $400
// @begin
__bbegin:
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -189,24 +187,22 @@ main: {
idx: .byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ main::i#2 idx ] ( main:2 [ main::i#2 idx ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← (byte) idx [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ idx main::i#2 ] ( main:2 [ idx main::i#2 ] ) always clobbers reg byte a
Statement [7] (byte) idx ← (byte) idx + (byte) main::i#2 [ main::i#2 idx ] ( main:2 [ main::i#2 idx ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
Potential registers mem[1] [ idx ] : mem[1] ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 31.17: zp[1]:2 [ main::i#2 main::i#1 ]
Uplift Scope [] 5: mem[1] [ idx ]
Uplift Scope [] 4.71: mem[1] [ idx ]
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 409 combination mem[1] [ idx ]
Uplifting [main] best 403 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 403 combination mem[1] [ idx ]
Attempting to uplift remaining variables inmem[1] [ idx ]
Uplifting [] best 409 combination mem[1] [ idx ]
Uplifting [] best 403 combination mem[1] [ idx ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -219,9 +215,6 @@ ASSEMBLER BEFORE OPTIMIZATION
.label SCREEN = $400
// @begin
__bbegin:
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -277,28 +270,32 @@ Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b1 with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __b1_from_main:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore mem[1] 5.0
(byte) idx loadstore mem[1] 4.714285714285714 = (byte) 0
(void()) main()
(label) main::@1
(label) main::@return
@ -311,28 +308,21 @@ mem[1] [ idx ]
FINAL ASSEMBLER
Score: 319
Score: 301
// File Comments
// Test declaring a variable as "__mem __notssa", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
__bbegin:
// idx
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main

View File

@ -2,7 +2,7 @@
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore mem[1] 5.0
(byte) idx loadstore mem[1] 4.714285714285714 = (byte) 0
(void()) main()
(label) main::@1
(label) main::@return

View File

@ -1,15 +1,10 @@
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
// Test a pointer to a memory variable
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.label idx_p = idx
__bbegin:
lda #0
sta idx
jsr main
rts
main: {
ldx #0
__b1:

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] (byte) idx ← (byte) 0
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -4,7 +4,6 @@ Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte) idx ← (byte) 0
to:@1
(void()) main()
@ -35,7 +34,7 @@ SYMBOL TABLE SSA
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte) idx loadstore
(byte) idx loadstore = (byte) 0
(const byte*) idx_p = &(byte) idx
(void()) main()
(bool~) main::$0
@ -48,12 +47,12 @@ SYMBOL TABLE SSA
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Simple Condition (bool~) main::$0 [7] if((byte) main::i#1!=rangelast(0,5)) goto main::@1
Simple Condition (bool~) main::$0 [6] if((byte) main::i#1!=rangelast(0,5)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [5] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [7] if(main::i#1!=rangelast(0,5)) goto main::@1 to (number) 6
Resolved ranged next value [4] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [6] if(main::i#1!=rangelast(0,5)) goto main::@1 to (number) 6
Adding number conversion cast (unumber) 6 in if((byte) main::i#1!=(number) 6) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 6
@ -64,6 +63,7 @@ Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
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
@ -76,13 +76,14 @@ Coalesced [12] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@3
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] (byte) idx ← (byte) 0
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -108,7 +109,7 @@ main::@return: scope:[main] from main::@1
VARIABLE REGISTER WEIGHTS
(byte) idx loadstore 20.0
(byte) idx loadstore = (byte) 0
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
@ -137,9 +138,6 @@ Target platform is c64basic / MOS6502X
.label idx_p = idx
// @begin
__bbegin:
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -194,11 +192,9 @@ main: {
idx: .byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte) idx ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [7] *((const byte*) idx_p) ← *((const byte*) idx_p) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [0] (byte) idx ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN + (byte) main::i#2) ← *((const byte*) idx_p) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [7] *((const byte*) idx_p) ← *((const byte*) idx_p) + (byte) main::i#2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
@ -206,12 +202,12 @@ Potential registers mem[1] [ idx ] : mem[1] ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 31.17: zp[1]:2 [ main::i#2 main::i#1 ]
Uplift Scope [] 20: mem[1] [ idx ]
Uplift Scope [] 0: mem[1] [ idx ]
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 409 combination mem[1] [ idx ]
Uplifting [main] best 403 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 403 combination mem[1] [ idx ]
Attempting to uplift remaining variables inmem[1] [ idx ]
Uplifting [] best 409 combination mem[1] [ idx ]
Uplifting [] best 403 combination mem[1] [ idx ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -226,9 +222,6 @@ ASSEMBLER BEFORE OPTIMIZATION
.label idx_p = idx
// @begin
__bbegin:
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -284,28 +277,32 @@ Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b1 with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __b1_from_main:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore mem[1] 20.0
(byte) idx loadstore mem[1] = (byte) 0
(const byte*) idx_p = &(byte) idx
(void()) main()
(label) main::@1
@ -319,30 +316,23 @@ mem[1] [ idx ]
FINAL ASSEMBLER
Score: 319
Score: 301
// File Comments
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
// Test a pointer to a memory variable
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx_p = idx
// @begin
__bbegin:
// idx
// [0] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main

View File

@ -2,7 +2,7 @@
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore mem[1] 20.0
(byte) idx loadstore mem[1] = (byte) 0
(const byte*) idx_p = &(byte) idx
(void()) main()
(label) main::@1

View File

@ -1,16 +1,9 @@
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
// Test a memory variable containing a pointer
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
__bbegin:
lda #<SCREEN
sta cursor
lda #>SCREEN
sta cursor+1
jsr main
rts
main: {
ldx #0
__b1:
@ -33,4 +26,4 @@ main: {
bne __b1
rts
}
cursor: .word 0
cursor: .word SCREEN

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] (byte*) cursor ← (const byte*) SCREEN
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -2,7 +2,6 @@ Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte*) cursor ← (const byte*) SCREEN
to:@1
(void()) main()
@ -33,7 +32,7 @@ SYMBOL TABLE SSA
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte*) cursor loadstore
(byte*) cursor loadstore = (const byte*) SCREEN
(void()) main()
(bool~) main::$0
(label) main::@1
@ -50,12 +49,12 @@ Simplifying constant integer cast $29
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $29
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) main::$0 [7] if((byte) main::i#1!=rangelast(0,$18)) goto main::@1
Simple Condition (bool~) main::$0 [6] if((byte) main::i#1!=rangelast(0,$18)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [5] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [7] if(main::i#1!=rangelast(0,$18)) goto main::@1 to (number) $19
Resolved ranged next value [4] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [6] if(main::i#1!=rangelast(0,$18)) goto main::@1 to (number) $19
Adding number conversion cast (unumber) $19 in if((byte) main::i#1!=(number) $19) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast $19
@ -66,6 +65,7 @@ Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
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
@ -78,13 +78,14 @@ Coalesced [12] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@3
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] (byte*) cursor ← (const byte*) SCREEN
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -110,7 +111,7 @@ main::@return: scope:[main] from main::@1
VARIABLE REGISTER WEIGHTS
(byte*) cursor loadstore 5.0
(byte*) cursor loadstore 4.714285714285714 = (const byte*) SCREEN
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
@ -138,11 +139,6 @@ Target platform is c64basic / MOS6502X
.label SCREEN = $400
// @begin
__bbegin:
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
lda #<SCREEN
sta cursor
lda #>SCREEN
sta cursor+1
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -201,26 +197,24 @@ main: {
rts
}
// File Data
cursor: .word 0
cursor: .word SCREEN
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] (byte*) cursor ← (const byte*) SCREEN [ cursor ] ( [ cursor ] ) always clobbers reg byte a
Statement [6] *((byte*) cursor) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ cursor main::i#2 ] ( main:2 [ cursor main::i#2 ] ) always clobbers reg byte a
Statement [0] (byte*) cursor ← (const byte*) SCREEN [ cursor ] ( [ cursor ] ) always clobbers reg byte a
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ main::i#2 cursor ] ( main:2 [ main::i#2 cursor ] ) always clobbers reg byte a
Statement [6] *((byte*) cursor) ← (byte) '*' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a reg byte y
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ cursor main::i#2 ] ( main:2 [ cursor main::i#2 ] ) always clobbers reg byte a
Statement [7] (byte*) cursor ← (byte*) cursor + (byte) $29 [ main::i#2 cursor ] ( main:2 [ main::i#2 cursor ] ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x ,
Potential registers mem[2] [ cursor ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 23.83: zp[1]:2 [ main::i#2 main::i#1 ]
Uplift Scope [] 5: mem[2] [ cursor ]
Uplift Scope [] 4.71: mem[2] [ cursor ]
Uplifting [main] best 650 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 650 combination mem[2] [ cursor ]
Uplifting [main] best 638 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 638 combination mem[2] [ cursor ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -234,11 +228,6 @@ ASSEMBLER BEFORE OPTIMIZATION
.label SCREEN = $400
// @begin
__bbegin:
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
lda #<SCREEN
sta cursor
lda #>SCREEN
sta cursor+1
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -294,7 +283,7 @@ main: {
rts
}
// File Data
cursor: .word 0
cursor: .word SCREEN
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
@ -302,28 +291,32 @@ Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b1 with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __b1_from_main:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte*) cursor loadstore mem[2] 5.0
(byte*) cursor loadstore mem[2] 4.714285714285714 = (const byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@return
@ -336,31 +329,22 @@ mem[2] [ cursor ]
FINAL ASSEMBLER
Score: 560
Score: 536
// File Comments
// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store)
// Test a memory variable containing a pointer
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// @begin
__bbegin:
// cursor = SCREEN
// [0] (byte*) cursor ← (const byte*) SCREEN -- pbum1=pbuc1
lda #<SCREEN
sta cursor
lda #>SCREEN
sta cursor+1
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [4] phi from @1 to main [phi:@1->main]
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
@ -402,5 +386,5 @@ main: {
rts
}
// File Data
cursor: .word 0
cursor: .word SCREEN

View File

@ -2,7 +2,7 @@
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte*) cursor loadstore mem[2] 5.0
(byte*) cursor loadstore mem[2] 4.714285714285714 = (const byte*) SCREEN
(void()) main()
(label) main::@1
(label) main::@return

View File

@ -1,19 +1,9 @@
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 3
.const OFFSET_STRUCT_POINT_INITIALS = 1
__bbegin:
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta point1-1,y
dey
bne !-
jsr main
rts
main: {
lda point1
sta SCREEN
@ -23,5 +13,4 @@ main: {
sta SCREEN+2
rts
}
__0: .byte 2, 'j', 'g'
point1: .fill SIZEOF_STRUCT_POINT, 0
point1: .byte 2, 'j', 'g'

View File

@ -1,5 +1,5 @@
@begin: scope:[] from
[0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT)
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()

View File

@ -1,14 +1,12 @@
Fixing struct type size struct Point to 3
Fixing struct type SIZE_OF struct Point to 3
Fixing struct type SIZE_OF struct Point to 3
Adding struct value member variable copy *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT)
Replacing struct member reference (struct Point) point1.x with member unwinding reference *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Replacing struct member reference (struct Point) point1.initials with member unwinding reference (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
Replacing struct member reference (struct Point) point1.initials with member unwinding reference (byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
*(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT)
to:@1
(void()) main()
@ -28,7 +26,6 @@ main::@return: scope:[main] from main
@end: scope:[] from @2
SYMBOL TABLE SSA
(const struct Point) $0 = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
(label) @1
(label) @2
(label) @begin
@ -38,10 +35,9 @@ SYMBOL TABLE SSA
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
(byte) Point::x
(const byte*) SCREEN = (byte*)(number) $400
(const byte) SIZEOF_STRUCT_POINT = (byte) 3
(void()) main()
(label) main::@return
(struct Point) point1 loadstore
(struct Point) point1 loadstore = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Adding number conversion cast (unumber) 0 in *((const byte*) SCREEN + (number) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (number) 0)
@ -62,9 +58,9 @@ Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 1
Finalized unsigned number type (byte) 2
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (byte*)&point1 in [1] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [1] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
Simplifying expression containing zero (byte*)&point1+OFFSET_STRUCT_POINT_INITIALS in [2] *((const byte*) SCREEN + (byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (byte) 0)
Simplifying expression containing zero (byte*)&point1 in [0] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_X)
Simplifying expression containing zero SCREEN in [0] *((const byte*) SCREEN + (byte) 0) ← *((byte*)&(struct Point) point1)
Simplifying expression containing zero (byte*)&point1+OFFSET_STRUCT_POINT_INITIALS in [1] *((const byte*) SCREEN + (byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS + (byte) 0)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
@ -72,6 +68,7 @@ Consolidated array index constant in *(SCREEN+1)
Consolidated array index constant in *((byte*)&point1+OFFSET_STRUCT_POINT_INITIALS+1)
Consolidated array index constant in *(SCREEN+2)
Successful SSA optimization Pass2ConstantAdditionElimination
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
@ -81,12 +78,13 @@ Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT)
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
@ -109,7 +107,7 @@ main::@return: scope:[main] from main
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(void()) main()
(struct Point) point1 loadstore
(struct Point) point1 loadstore = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
Initial phi equivalence classes
Added variable point1 to live range equivalence class [ point1 ]
@ -127,17 +125,9 @@ Target platform is c64basic / MOS6502X
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 3
.const OFFSET_STRUCT_POINT_INITIALS = 1
// @begin
__bbegin:
// [0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta point1-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -168,11 +158,9 @@ main: {
rts
}
// File Data
__0: .byte 2, 'j', 'g'
point1: .fill SIZEOF_STRUCT_POINT, 0
point1: .byte 2, 'j', 'g'
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) [ point1 ] ( [ point1 ] ) always clobbers reg byte a reg byte y
Statement [4] *((const byte*) SCREEN) ← *((byte*)&(struct Point) point1) [ point1 ] ( main:2 [ point1 ] ) always clobbers reg byte a
Statement [5] *((const byte*) SCREEN+(byte) 1) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS) [ point1 ] ( main:2 [ point1 ] ) always clobbers reg byte a
Statement [6] *((const byte*) SCREEN+(byte) 2) ← *((byte*)&(struct Point) point1+(const byte) OFFSET_STRUCT_POINT_INITIALS+(byte) 1) [ ] ( main:2 [ ] ) always clobbers reg byte a
@ -183,9 +171,9 @@ Uplift Scope [Point]
Uplift Scope [main]
Uplift Scope [] 0: mem[3] [ point1 ]
Uplifting [Point] best 61 combination
Uplifting [main] best 61 combination
Uplifting [] best 61 combination mem[3] [ point1 ]
Uplifting [Point] best 45 combination
Uplifting [main] best 45 combination
Uplifting [] best 45 combination mem[3] [ point1 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -196,17 +184,9 @@ ASSEMBLER BEFORE OPTIMIZATION
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 3
.const OFFSET_STRUCT_POINT_INITIALS = 1
// @begin
__bbegin:
// [0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta point1-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
jmp __b1
@ -237,26 +217,28 @@ main: {
rts
}
// File Data
__0: .byte 2, 'j', 'g'
point1: .fill SIZEOF_STRUCT_POINT, 0
point1: .byte 2, 'j', 'g'
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(const struct Point) $0 = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
(label) @1
(label) @begin
(label) @end
@ -264,42 +246,29 @@ FINAL SYMBOL TABLE
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
(byte) Point::x
(const byte*) SCREEN = (byte*) 1024
(const byte) SIZEOF_STRUCT_POINT = (byte) 3
(void()) main()
(label) main::@return
(struct Point) point1 loadstore mem[3]
(struct Point) point1 loadstore mem[3] = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
mem[3] [ point1 ]
FINAL ASSEMBLER
Score: 58
Score: 30
// File Comments
// Minimal struct with C-Standard behavior - global main-mem struct should be initialized in data, not code
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.const SIZEOF_STRUCT_POINT = 3
.const OFFSET_STRUCT_POINT_INITIALS = 1
// @begin
__bbegin:
// point1 = { 2, { 'j', 'g' } }
// [0] *(&(struct Point) point1) ← memcpy(*(&(const struct Point) $0), struct Point, (const byte) SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_POINT
!:
lda __0-1,y
sta point1-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
@ -322,6 +291,5 @@ main: {
rts
}
// File Data
__0: .byte 2, 'j', 'g'
point1: .fill SIZEOF_STRUCT_POINT, 0
point1: .byte 2, 'j', 'g'

View File

@ -1,4 +1,3 @@
(const struct Point) $0 = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
(label) @1
(label) @begin
(label) @end
@ -6,9 +5,8 @@
(const byte*) Point::initials[(number) 2] = { fill( 2, 0) }
(byte) Point::x
(const byte*) SCREEN = (byte*) 1024
(const byte) SIZEOF_STRUCT_POINT = (byte) 3
(void()) main()
(label) main::@return
(struct Point) point1 loadstore mem[3]
(struct Point) point1 loadstore mem[3] = { x: (byte) 2, initials: { (byte) 'j', (byte) 'g' } }
mem[3] [ point1 ]