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:
parent
030a379845
commit
2eb5aaa24f
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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 {
|
||||||
|
@ -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
17
src/test/kc/struct-33.kc
Normal 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;
|
||||||
|
}
|
@ -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
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
|
@ -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) }
|
||||||
|
@ -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
|
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user