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:
parent
2eb5aaa24f
commit
d5f4b1f690
@ -0,0 +1,6 @@
|
||||
ldy {m1}
|
||||
sty $fe
|
||||
ldy {m1}+1
|
||||
sty $ff
|
||||
ldy #{c1}
|
||||
sta ($fe),y
|
@ -0,0 +1,7 @@
|
||||
sty $fd
|
||||
ldy {m1}
|
||||
sty $fe
|
||||
ldy {m1}+1
|
||||
sty $ff
|
||||
ldy $fd
|
||||
sta ($fe),y
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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:
|
||||
|
@ -1,5 +1,5 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) idx ← (byte) 0
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -1,5 +1,5 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) idx ← (byte) 0
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte*) cursor ← (const byte*) SCREEN
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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()
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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 ]
|
||||
|
Loading…
Reference in New Issue
Block a user