1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-12 07:31:36 +00:00

Added support for init-value of global load/store memory variables.

This commit is contained in:
jespergravgaard 2020-01-11 13:39:10 +01:00
parent 030a379845
commit 2eb5aaa24f
19 changed files with 162 additions and 254 deletions

View File

@ -569,17 +569,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
initValue = Initializers.constantify(initValue, new Initializers.ValueTypeSpec(declVarType, declArraySpec), program, statementSource); initValue = Initializers.constantify(initValue, new Initializers.ValueTypeSpec(declVarType, declArraySpec), program, statementSource);
VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, declVarType, declArraySpec, declVarDirectives, currentDataSegment); VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), false, declVarType, declArraySpec, declVarDirectives, currentDataSegment);
Variable variable = varBuilder.build(); Variable variable = varBuilder.build();
if(variable.isKindConstant()) { if(variable.isKindConstant() || (variable.isKindLoadStore() && Variable.MemoryArea.MAIN_MEMORY.equals(variable.getMemoryArea()) && initValue instanceof ConstantValue && !declVarStructMember)) {
// Set constant value // Set constant value
ConstantValue constInitValue = getConstInitValue(initValue, initializer, statementSource); ConstantValue constInitValue = getConstInitValue(initValue, initializer, statementSource);
variable.setInitValue(constInitValue); variable.setInitValue(constInitValue);
// Add comments to constant // Add comments to constant
variable.setComments(ensureUnusedComments(declVarComments)); variable.setComments(ensureUnusedComments(declVarComments));
} } else if(!variable.isKindConstant() && !declVarStructMember) {
if(!variable.isKindConstant() && !declVarStructMember) { Statement initStmt = new StatementAssignment(variable.getVariableRef(), initValue, true, statementSource, ensureUnusedComments(declVarComments));
Statement initStmt = new StatementAssignment(variable.getVariableRef(), initValue, true, statementSource, ensureUnusedComments(declVarComments)); sequence.addStatement(initStmt);
sequence.addStatement(initStmt); }
}
if(initializer != null) if(initializer != null)
PrePostModifierHandler.addPostModifiers(this, initializer, statementSource); PrePostModifierHandler.addPostModifiers(this, initializer, statementSource);
return null; return null;

View File

@ -8,6 +8,7 @@ import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator; import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.*; import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.SymbolRef; import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.SymbolVariableRef; import dk.camelot64.kickc.model.values.SymbolVariableRef;
@ -34,7 +35,14 @@ public class Pass1AssertUsedVars extends Pass1Base {
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME)); ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME));
assertUsedVars(beginBlock, null, referenceInfos, new LinkedHashSet<>(), new LinkedHashSet<>()); final LinkedHashSet<SymbolVariableRef> defined = new LinkedHashSet<>();
// Add all variables with an init-value
for(Variable var : getScope().getAllVars(true)) {
if(var.getInitValue()!=null) {
defined.add(var.getRef());
}
}
assertUsedVars(beginBlock, null, referenceInfos, defined, new LinkedHashSet<>());
getProgram().clearVariableReferenceInfos(); getProgram().clearVariableReferenceInfos();
getProgram().clearStatementIndices(); getProgram().clearStatementIndices();
return false; return false;

View File

@ -267,10 +267,9 @@ public class Pass1UnwindStructValues extends Pass1Base {
if(lValueUnwinding.isBulkCopyable() && rValueUnwinding.isBulkCopyable()) { if(lValueUnwinding.isBulkCopyable() && rValueUnwinding.isBulkCopyable()) {
// Use bulk unwinding for a struct member that is an array // Use bulk unwinding for a struct member that is an array
stmtIt.previous(); stmtIt.previous();
//RValue lValueMemberVarPointer = lValueUnwinding.getBulkLValue(getScope()); if(lValueUnwinding.getArraySpec()!=null)
//LValue lValueMemberVarRef = new PointerDereferenceSimple(lValueMemberVarPointer); if(rValueUnwinding.getArraySpec()==null || !lValueUnwinding.getArraySpec().equals(rValueUnwinding.getArraySpec()))
//if(rValueUnwinding.getArraySpec()==null || !lValueUnwinding.getArraySpec().equals(rValueUnwinding.getArraySpec())) throw new RuntimeException("ArraySpec mismatch!");
// throw new RuntimeException("ArraySpec mismatch!");
LValue lValueMemberVarRef = lValueUnwinding.getBulkLValue(getScope()); LValue lValueMemberVarRef = lValueUnwinding.getBulkLValue(getScope());
RValue rValueBulkUnwinding = rValueUnwinding.getBulkRValue(getScope()); RValue rValueBulkUnwinding = rValueUnwinding.getBulkRValue(getScope());
if(lValueUnwoundList != null) if(lValueUnwoundList != null)

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.StructDefinition;
import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.model.values.*;
@ -21,6 +22,8 @@ public class Pass3AssertArrayLengths extends Pass2SsaAssertion {
public void check() throws AssertionFailed { public void check() throws AssertionFailed {
Collection<Variable> allConstants = getScope().getAllConstants(true); Collection<Variable> allConstants = getScope().getAllConstants(true);
for(Variable constantVar : allConstants) { for(Variable constantVar : allConstants) {
if(constantVar.getScope() instanceof StructDefinition)
continue;
SymbolType constantType = constantVar.getType(); SymbolType constantType = constantVar.getType();
if(constantVar.isArray() && constantVar.getArraySize() != null) { if(constantVar.isArray() && constantVar.getArraySize() != null) {
ConstantValue declaredSize = constantVar.getArraySize(); ConstantValue declaredSize = constantVar.getArraySize();

View File

@ -539,10 +539,23 @@ public class Pass4CodeGeneration {
String alignment = AsmFormat.getAsmNumber(declaredAlignment); String alignment = AsmFormat.getAsmNumber(declaredAlignment);
asm.addDataAlignment(alignment); asm.addDataAlignment(alignment);
} }
AsmDataChunk asmDataChunk = new AsmDataChunk(); if(variable.getInitValue()!=null) {
ConstantValue zeroValue = Initializers.createZeroValue(new Initializers.ValueTypeSpec(variable.getType(), variable.getArraySpec()), null); // Variable has a constant init Value
addChunkData(asmDataChunk, zeroValue, variable.getType(), variable.getArraySpec(), scopeRef); ConstantValue constantValue = variable.getInitValue();
asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm); 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 {
// Zero-fill variable
AsmDataChunk asmDataChunk = new AsmDataChunk();
ConstantValue zeroValue = Initializers.createZeroValue(new Initializers.ValueTypeSpec(variable.getType(), variable.getArraySpec()), null);
addChunkData(asmDataChunk, zeroValue, variable.getType(), variable.getArraySpec(), scopeRef);
asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm);
}
added.add(variable.getAsmName()); added.add(variable.getAsmName());
} }
} else { } else {

View File

@ -1127,9 +1127,14 @@ public class TestPrograms {
assertError("struct-err-0", "Unknown struct type"); assertError("struct-err-0", "Unknown struct type");
} }
@Test
public void testStruct33() throws IOException, URISyntaxException {
compileAndCompare("struct-33", log());
}
@Test @Test
public void testStruct32() throws IOException, URISyntaxException { public void testStruct32() throws IOException, URISyntaxException {
compileAndCompare("struct-32", log()); compileAndCompare("struct-32");
} }
@Test @Test
@ -1139,7 +1144,7 @@ public class TestPrograms {
@Test @Test
public void testStruct30() throws IOException, URISyntaxException { public void testStruct30() throws IOException, URISyntaxException {
compileAndCompare("struct-30", log()); compileAndCompare("struct-30");
} }
@Test @Test
@ -1229,17 +1234,17 @@ public class TestPrograms {
@Test @Test
public void testStruct12() throws IOException, URISyntaxException { public void testStruct12() throws IOException, URISyntaxException {
compileAndCompare("struct-12", log()); compileAndCompare("struct-12");
} }
@Test @Test
public void testStruct11b() throws IOException, URISyntaxException { public void testStruct11b() throws IOException, URISyntaxException {
compileAndCompare("struct-11b", log()); compileAndCompare("struct-11b");
} }
@Test @Test
public void testStruct11() throws IOException, URISyntaxException { public void testStruct11() throws IOException, URISyntaxException {
compileAndCompare("struct-11", log()); compileAndCompare("struct-11");
} }
@Test @Test

17
src/test/kc/struct-33.kc Normal file
View File

@ -0,0 +1,17 @@
// Minimal struct with C-Standard behavior - declaration, instantiation and usage
struct Point {
char x;
char y;
};
__mem __ma struct Point point;
const char* SCREEN = 0x0400;
void main() {
point.x = 2;
point.y = 3;
SCREEN[0] = point.x;
SCREEN[1] = point.y;
}

View File

@ -1,19 +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 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 struct value // Test a memory variable struct value
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
__bbegin:
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
jsr main
rts
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label barp = bar .label barp = bar
@ -23,5 +13,4 @@ main: {
sta SCREEN+1 sta SCREEN+1
rts rts
} }
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

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

View File

@ -1,12 +1,10 @@
Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar
Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
Rewriting struct pointer member access *((struct foo*) main::barp).thing1 Rewriting struct pointer member access *((struct foo*) main::barp).thing1
Rewriting struct pointer member access *((struct foo*) main::barp).thing2 Rewriting struct pointer member access *((struct foo*) main::barp).thing2
Identified constant variable (struct foo*) main::barp Identified constant variable (struct foo*) main::barp
CONTROL FLOW GRAPH SSA CONTROL FLOW GRAPH SSA
@begin: scope:[] from @begin: scope:[] from
*(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
to:@1 to:@1
(void()) main() (void()) main()
@ -30,15 +28,13 @@ main::@return: scope:[main] from main
@end: scope:[] from @2 @end: scope:[] from @2
SYMBOL TABLE SSA SYMBOL TABLE SSA
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @2 (label) @2
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -54,20 +50,20 @@ SYMBOL TABLE SSA
Simplifying constant pointer cast (byte*) 1024 Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Constant right-side identified [2] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 Constant right-side identified [1] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 Constant right-side identified [4] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#0 = 0 Constant (const byte) main::i#0 = 0
Constant (const byte*) main::$0 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1 Constant (const byte*) main::$0 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1
Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2 Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)main::barp in Simplifying expression containing zero (byte*)main::barp in
Simplifying expression containing zero main::SCREEN in [3] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0) Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0)
Successful SSA optimization PassNSimplifyExpressionWithZero Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte) main::i#2 and assignment [4] (byte) main::i#2 ← ++ (byte) main::i#1 Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
Successful SSA optimization PassNEliminateUnusedVars Successful SSA optimization PassNEliminateUnusedVars
Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#1 = ++main::i#0 Constant (const byte) main::i#1 = ++main::i#0
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
@ -82,6 +78,7 @@ Consolidated array index constant in *(main::SCREEN+++0)
Successful SSA optimization Pass2ConstantAdditionElimination Successful SSA optimization Pass2ConstantAdditionElimination
Simplifying constant integer increment ++0 Simplifying constant integer increment ++0
Successful SSA optimization Pass2ConstantSimplification Successful SSA optimization Pass2ConstantSimplification
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1 Adding NOP phi() at start of @1
Adding NOP phi() at start of @2 Adding NOP phi() at start of @2
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
@ -91,12 +88,13 @@ Calls in [] to main:2
Created 0 initial phi equivalence classes Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2 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 @1
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH FINAL CONTROL FLOW GRAPH
@begin: scope:[] from @begin: scope:[] from
[0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [0] phi()
to:@1 to:@1
@1: scope:[] from @begin @1: scope:[] from @begin
[1] phi() [1] phi()
@ -116,7 +114,7 @@ main::@return: scope:[main] from main
VARIABLE REGISTER WEIGHTS VARIABLE REGISTER WEIGHTS
(struct foo) bar loadstore (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' }
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -138,17 +136,9 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -178,11 +168,9 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0
REGISTER UPLIFT POTENTIAL REGISTERS REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y
Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ bar ] : mem[2] , Potential registers mem[2] [ bar ] : mem[2] ,
@ -192,9 +180,9 @@ Uplift Scope [foo]
Uplift Scope [main] Uplift Scope [main]
Uplift Scope [] 0: mem[2] [ bar ] Uplift Scope [] 0: mem[2] [ bar ]
Uplifting [foo] best 53 combination Uplifting [foo] best 37 combination
Uplifting [main] best 53 combination Uplifting [main] best 37 combination
Uplifting [] best 53 combination mem[2] [ bar ] Uplifting [] best 37 combination mem[2] [ bar ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
@ -205,17 +193,9 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -245,32 +225,33 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0
ASSEMBLER OPTIMIZATIONS ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1 Removing instruction jmp __b1
Removing instruction jmp __bend Removing instruction jmp __bend
Removing instruction jmp __breturn Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin: Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1: Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend: Removing instruction __bend:
Removing instruction __breturn: Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block Updating BasicUpstart to call main directly
Succesful ASM optimization Pass5AddMainRts Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE FINAL SYMBOL TABLE
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore mem[2]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -283,33 +264,21 @@ mem[2] [ bar ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 50 Score: 22
// File Comments // 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 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 struct value // Test a memory variable struct value
// Upstart // Upstart
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin:
// bar = { 'a', 'b' }
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
// @1 // @1
// [2] call main // [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
// @end // @end
// main // main
@ -330,6 +299,5 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

@ -1,10 +1,8 @@
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore mem[2]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()

View File

@ -1,20 +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 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 struct value - containing a fixed size array // Test a memory variable struct value - containing a fixed size array
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
.const SIZEOF_STRUCT_FOO = $e
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
.const OFFSET_STRUCT_FOO_THING3 = 2 .const OFFSET_STRUCT_FOO_THING3 = 2
__bbegin:
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
jsr main
rts
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
.label barp = bar .label barp = bar
@ -33,8 +23,7 @@ main: {
bne __b1 bne __b1
rts rts
} }
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
.text "qwe" .text "qwe"
.byte 0 .byte 0
.fill 8, 0 .fill 8, 0
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

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

View File

@ -3,7 +3,6 @@ Fixing struct type size struct foo to 14
Fixing struct type SIZE_OF struct foo to 14 Fixing struct type SIZE_OF struct foo to 14
Fixing struct type SIZE_OF struct foo to 14 Fixing struct type SIZE_OF struct foo to 14
Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar
Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
Rewriting struct pointer member access *((struct foo*) main::barp).thing1 Rewriting struct pointer member access *((struct foo*) main::barp).thing1
Rewriting struct pointer member access *((struct foo*) main::barp).thing2 Rewriting struct pointer member access *((struct foo*) main::barp).thing2
Rewriting struct pointer member access *((struct foo*) main::barp).thing3 Rewriting struct pointer member access *((struct foo*) main::barp).thing3
@ -12,7 +11,6 @@ Culled Empty Block (label) main::@2
CONTROL FLOW GRAPH SSA CONTROL FLOW GRAPH SSA
@begin: scope:[] from @begin: scope:[] from
*(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
to:@1 to:@1
(void()) main() (void()) main()
@ -47,7 +45,6 @@ main::@return: scope:[main] from main::@1
@end: scope:[] from @2 @end: scope:[] from @2
SYMBOL TABLE SSA SYMBOL TABLE SSA
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(label) @1 (label) @1
(label) @2 (label) @2
(label) @begin (label) @begin
@ -55,8 +52,7 @@ SYMBOL TABLE SSA
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
(const byte) SIZEOF_STRUCT_FOO = (byte) $e (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(struct foo) bar loadstore
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) }
@ -82,11 +78,11 @@ SYMBOL TABLE SSA
Simplifying constant pointer cast (byte*) 1024 Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Simple Condition (bool~) main::$0 [15] if((byte) main::j#1!=rangelast(0,$b)) goto main::@1 Simple Condition (bool~) main::$0 [14] if((byte) main::j#1!=rangelast(0,$b)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [2] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 Constant right-side identified [1] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1
Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 Constant right-side identified [4] (byte*~) main::$2 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2
Constant right-side identified [10] (byte*~) main::$3 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING3 Constant right-side identified [9] (byte*~) main::$3 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING3
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#0 = 0 Constant (const byte) main::i#0 = 0
Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1 Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1
@ -94,10 +90,10 @@ Constant (const byte*) main::$2 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2
Constant (const byte) main::j#0 = 0 Constant (const byte) main::j#0 = 0
Constant (const byte*) main::$3 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING3 Constant (const byte*) main::$3 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING3
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [13] main::j#1 ← ++ main::j#2 to ++ Resolved ranged next value [12] main::j#1 ← ++ main::j#2 to ++
Resolved ranged comparison value [15] if(main::j#1!=rangelast(0,$b)) goto main::@1 to (number) $c Resolved ranged comparison value [14] if(main::j#1!=rangelast(0,$b)) goto main::@1 to (number) $c
Simplifying expression containing zero (byte*)main::barp in Simplifying expression containing zero (byte*)main::barp in
Simplifying expression containing zero main::SCREEN in [3] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$1) Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$1)
Successful SSA optimization PassNSimplifyExpressionWithZero Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
Successful SSA optimization PassNEliminateUnusedVars Successful SSA optimization PassNEliminateUnusedVars
@ -107,11 +103,11 @@ Simplifying constant integer cast $c
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $c Finalized unsigned number type (byte) $c
Successful SSA optimization PassNFinalizeNumberTypeConversions Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#1 = ++main::i#0 Constant (const byte) main::i#1 = ++main::i#0
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [3] (byte) main::i#2 ← ++ (const byte) main::i#1 Constant right-side identified [2] (byte) main::i#2 ← ++ (const byte) main::i#1
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#2 = ++main::i#1 Constant (const byte) main::i#2 = ++main::i#1
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
@ -135,6 +131,7 @@ Successful SSA optimization Pass2ConstantSimplification
Simplifying constant integer increment ++1 Simplifying constant integer increment ++1
Successful SSA optimization Pass2ConstantSimplification Successful SSA optimization Pass2ConstantSimplification
Added new block during phi lifting main::@3(between main::@1 and main::@1) 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 @1
Adding NOP phi() at start of @2 Adding NOP phi() at start of @2
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
@ -147,12 +144,13 @@ Coalesced [14] main::i#5 ← main::i#3
Coalesced down to 2 phi equivalence classes Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @2 Culled Empty Block (label) @2
Culled Empty Block (label) main::@3 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 @1
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH FINAL CONTROL FLOW GRAPH
@begin: scope:[] from @begin: scope:[] from
[0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [0] phi()
to:@1 to:@1
@1: scope:[] from @begin @1: scope:[] from @begin
[1] phi() [1] phi()
@ -180,7 +178,7 @@ main::@return: scope:[main] from main::@1
VARIABLE REGISTER WEIGHTS VARIABLE REGISTER WEIGHTS
(struct foo) bar loadstore (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -213,18 +211,10 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = $e
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
.const OFFSET_STRUCT_FOO_THING3 = 2 .const OFFSET_STRUCT_FOO_THING3 = 2
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -285,20 +275,17 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
.text "qwe" .text "qwe"
.byte 0 .byte 0
.fill 8, 0 .fill 8, 0
bar: .fill SIZEOF_STRUCT_FOO, 0
REGISTER UPLIFT POTENTIAL REGISTERS REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y
Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::j#2 main::j#1 ] Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::j#2 main::j#1 ]
Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::i#4 main::i#3 ] Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::i#4 main::i#3 ]
Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y
Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a
@ -311,9 +298,9 @@ Uplift Scope [main] 27.5: zp[1]:2 [ main::j#2 main::j#1 ] 23.83: zp[1]:3 [ main:
Uplift Scope [foo] Uplift Scope [foo]
Uplift Scope [] 0: mem[14] [ bar ] Uplift Scope [] 0: mem[14] [ bar ]
Uplifting [main] best 360 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ] Uplifting [main] best 344 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ]
Uplifting [foo] best 360 combination Uplifting [foo] best 344 combination
Uplifting [] best 360 combination mem[14] [ bar ] Uplifting [] best 344 combination mem[14] [ bar ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
@ -324,18 +311,10 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = $e
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
.const OFFSET_STRUCT_FOO_THING3 = 2 .const OFFSET_STRUCT_FOO_THING3 = 2
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -389,11 +368,10 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
.text "qwe" .text "qwe"
.byte 0 .byte 0
.fill 8, 0 .fill 8, 0
bar: .fill SIZEOF_STRUCT_FOO, 0
ASSEMBLER OPTIMIZATIONS ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1 Removing instruction jmp __b1
@ -401,30 +379,32 @@ Removing instruction jmp __bend
Removing instruction jmp __b1 Removing instruction jmp __b1
Removing instruction jmp __breturn Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b1 with __b1 Replacing label __b1_from___b1 with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin: Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1: Removing instruction __bend_from___b1:
Removing instruction __b1_from___b1: Removing instruction __b1_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend: Removing instruction __bend:
Removing instruction __b1_from_main: Removing instruction __b1_from_main:
Removing instruction __breturn: Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block Updating BasicUpstart to call main directly
Succesful ASM optimization Pass5AddMainRts Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp __b1 Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE FINAL SYMBOL TABLE
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
(const byte) SIZEOF_STRUCT_FOO = (byte) $e (struct foo) bar loadstore mem[14] = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(struct foo) bar loadstore mem[14]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) }
@ -446,34 +426,22 @@ mem[14] [ bar ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 270 Score: 242
// File Comments // 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 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 struct value - containing a fixed size array // Test a memory variable struct value - containing a fixed size array
// Upstart // Upstart
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = $e
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
.const OFFSET_STRUCT_FOO_THING3 = 2 .const OFFSET_STRUCT_FOO_THING3 = 2
// @begin // @begin
__bbegin:
// bar = { 'a', 'b', "qwe" }
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
// @1 // @1
// [2] call main // [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
// @end // @end
// main // main
@ -517,9 +485,8 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
.text "qwe" .text "qwe"
.byte 0 .byte 0
.fill 8, 0 .fill 8, 0
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

@ -1,11 +1,9 @@
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2
(const byte) SIZEOF_STRUCT_FOO = (byte) $e (struct foo) bar loadstore mem[14] = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" }
(struct foo) bar loadstore mem[14]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) }

View File

@ -1,19 +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 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 struct value // Test a memory variable struct value
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
__bbegin:
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
jsr main
rts
main: { main: {
.label SCREEN = $400 .label SCREEN = $400
lda bar lda bar
@ -22,5 +12,4 @@ main: {
sta SCREEN+1 sta SCREEN+1
rts rts
} }
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

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

View File

@ -1,10 +1,8 @@
Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1) Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1)
Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2)
CONTROL FLOW GRAPH SSA CONTROL FLOW GRAPH SSA
@begin: scope:[] from @begin: scope:[] from
*(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO)
to:@1 to:@1
(void()) main() (void()) main()
@ -26,15 +24,13 @@ main::@return: scope:[main] from main
@end: scope:[] from @2 @end: scope:[] from @2
SYMBOL TABLE SSA SYMBOL TABLE SSA
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @2 (label) @2
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -49,13 +45,13 @@ Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification Successful SSA optimization PassNCastSimplification
Constant (const byte) main::i#0 = 0 Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero (byte*)&bar in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1) Simplifying expression containing zero (byte*)&bar in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1)
Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar) Simplifying expression containing zero main::SCREEN in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar)
Successful SSA optimization PassNSimplifyExpressionWithZero Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte) main::i#2 and assignment [4] (byte) main::i#2 ← ++ (byte) main::i#1 Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1
Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1
Successful SSA optimization PassNEliminateUnusedVars Successful SSA optimization PassNEliminateUnusedVars
Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0
Successful SSA optimization Pass2ConstantRValueConsolidation Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::i#1 = ++main::i#0 Constant (const byte) main::i#1 = ++main::i#0
Successful SSA optimization Pass2ConstantIdentification Successful SSA optimization Pass2ConstantIdentification
@ -68,6 +64,7 @@ Consolidated array index constant in *(main::SCREEN+++0)
Successful SSA optimization Pass2ConstantAdditionElimination Successful SSA optimization Pass2ConstantAdditionElimination
Simplifying constant integer increment ++0 Simplifying constant integer increment ++0
Successful SSA optimization Pass2ConstantSimplification Successful SSA optimization Pass2ConstantSimplification
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1 Adding NOP phi() at start of @1
Adding NOP phi() at start of @2 Adding NOP phi() at start of @2
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
@ -77,12 +74,13 @@ Calls in [] to main:2
Created 0 initial phi equivalence classes Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @2 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 @1
Adding NOP phi() at start of @end Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH FINAL CONTROL FLOW GRAPH
@begin: scope:[] from @begin: scope:[] from
[0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [0] phi()
to:@1 to:@1
@1: scope:[] from @begin @1: scope:[] from @begin
[1] phi() [1] phi()
@ -102,7 +100,7 @@ main::@return: scope:[main] from main
VARIABLE REGISTER WEIGHTS VARIABLE REGISTER WEIGHTS
(struct foo) bar loadstore (struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' }
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -124,17 +122,9 @@ Target platform is c64basic / MOS6502X
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -163,11 +153,9 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0
REGISTER UPLIFT POTENTIAL REGISTERS REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ bar ] ( [ bar ] ) always clobbers reg byte a reg byte y
Statement [4] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) [ bar ] ( main:2 [ bar ] ) always clobbers reg byte a Statement [4] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) [ bar ] ( main:2 [ bar ] ) always clobbers reg byte a
Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a
Potential registers mem[2] [ bar ] : mem[2] , Potential registers mem[2] [ bar ] : mem[2] ,
@ -177,9 +165,9 @@ Uplift Scope [foo]
Uplift Scope [main] Uplift Scope [main]
Uplift Scope [] 0: mem[2] [ bar ] Uplift Scope [] 0: mem[2] [ bar ]
Uplifting [foo] best 53 combination Uplifting [foo] best 37 combination
Uplifting [main] best 53 combination Uplifting [main] best 37 combination
Uplifting [] best 53 combination mem[2] [ bar ] Uplifting [] best 37 combination mem[2] [ bar ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
@ -190,17 +178,9 @@ ASSEMBLER BEFORE OPTIMIZATION
:BasicUpstart(__bbegin) :BasicUpstart(__bbegin)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin: __bbegin:
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin: __b1_from___bbegin:
jmp __b1 jmp __b1
@ -229,32 +209,33 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0
ASSEMBLER OPTIMIZATIONS ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1 Removing instruction jmp __b1
Removing instruction jmp __bend Removing instruction jmp __bend
Removing instruction jmp __breturn Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin: Removing instruction __b1_from___bbegin:
Removing instruction __bend_from___b1: Removing instruction __bend_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Removing instruction __bend: Removing instruction __bend:
Removing instruction __breturn: Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block Updating BasicUpstart to call main directly
Succesful ASM optimization Pass5AddMainRts Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE FINAL SYMBOL TABLE
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore mem[2]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()
@ -266,33 +247,21 @@ mem[2] [ bar ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 50 Score: 22
// File Comments // 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 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 struct value // Test a memory variable struct value
// Upstart // Upstart
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(__bbegin) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.const SIZEOF_STRUCT_FOO = 2
.const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING2 = 1
// @begin // @begin
__bbegin:
// bar = { 'a', 'b' }
// [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #SIZEOF_STRUCT_FOO
!:
lda __0-1,y
sta bar-1,y
dey
bne !-
// [1] phi from @begin to @1 [phi:@begin->@1] // [1] phi from @begin to @1 [phi:@begin->@1]
// @1 // @1
// [2] call main // [2] call main
jsr main
rts
// [3] phi from @1 to @end [phi:@1->@end] // [3] phi from @1 to @end [phi:@1->@end]
// @end // @end
// main // main
@ -312,6 +281,5 @@ main: {
rts rts
} }
// File Data // File Data
__0: .byte 'a', 'b' bar: .byte 'a', 'b'
bar: .fill SIZEOF_STRUCT_FOO, 0

View File

@ -1,10 +1,8 @@
(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' }
(label) @1 (label) @1
(label) @begin (label) @begin
(label) @end (label) @end
(const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1
(const byte) SIZEOF_STRUCT_FOO = (byte) 2 (struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' }
(struct foo) bar loadstore mem[2]
(byte) foo::thing1 (byte) foo::thing1
(byte) foo::thing2 (byte) foo::thing2
(void()) main() (void()) main()