diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d17d2a593..2b53d5fa7 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -144,9 +144,15 @@ public class Compiler { log.append("\nVARIABLE REGISTER WEIGHTS"); log.append(program.getScope().getSymbolTableContents(Variable.class)); + //new Pass3RegisterUplifting(program, log).uplift(); + //log.append("REGISTER UPLIFTING"); + //log.append(program.getScope().getSymbolTableContents(Variable.class)); + new Pass3ZeroPageCoalesce(program, log).allocate(); new Pass3RegistersFinalize(program, log).allocate(); + //new Pass4RegisterAllocationTrivial(program).allocate(); + } diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java index 113b8da51..2ae2f7584 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java @@ -61,7 +61,9 @@ public class AsmFragment { private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) { RValue assignmentRValue2 = assignment.getrValue2(); - RegisterAllocation.Register rVal2Register = symbols.getRegister((Variable) assignmentRValue2); + Variable assignmentVar = symbols.getVariable((VariableRef) assignmentRValue2); + + RegisterAllocation.Register rVal2Register = symbols.getRegister(assignmentVar); if(!rVal2Register.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) { throw new RuntimeException("Error! ALU register only allowed as rValue2. "+assignment); } diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby1.asm new file mode 100644 index 000000000..8fd5e24bf --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=cowo1_staridx_zpby1.asm @@ -0,0 +1,3 @@ +ldy {zpby1} +lda {cowo1},y +sta {zpby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java index f3039f126..a744247a3 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java +++ b/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -72,10 +72,7 @@ public class ControlFlowGraph { * @param variable The variable to find the assignment for * @return The assignment. null if the variable is not assigned. The variable is assigned by a Phi-statement instead. */ - public StatementAssignment getAssignment(Variable variable) { - if(variable instanceof VariableUnversioned) { - throw new RuntimeException("Error attempting to get assignment of unversioned variable, which is not guaranteed to be unique "+variable); - } + public StatementAssignment getAssignment(VariableRef variable) { for (ControlFlowBlock block : getAllBlocks()) { for (Statement statement : block.getStatements()) { if(statement instanceof StatementAssignment) { diff --git a/src/main/java/dk/camelot64/kickc/icl/Scope.java b/src/main/java/dk/camelot64/kickc/icl/Scope.java index f9aaf587a..72d182d96 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Scope.java +++ b/src/main/java/dk/camelot64/kickc/icl/Scope.java @@ -151,12 +151,17 @@ public abstract class Scope implements Symbol { } @JsonIgnore - public Collection getAllVariables() { + public Collection getAllVariables(boolean includeSubScopes) { Collection vars = new ArrayList<>(); for (Symbol symbol : symbols.values()) { if (symbol instanceof Variable) { vars.add((Variable) symbol); } + if(includeSubScopes && symbol instanceof Scope) { + Scope subScope = (Scope) symbol; + vars.addAll(subScope.getAllVariables(true)); + } + } return vars; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java index 259ffff59..2b7ff4621 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java @@ -149,7 +149,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { return null; } Variable var = getSymbols().getVariable(variable); - StatementAssignment assignment = getGraph().getAssignment(var); + StatementAssignment assignment = getGraph().getAssignment(variable); if (assignment != null && assignment.getOperator() != null && "+".equals(assignment.getOperator().getOperator())) { if (assignment.getrValue1() instanceof ConstantInteger) { ConstantInteger constant = (ConstantInteger) assignment.getrValue1(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java new file mode 100644 index 000000000..446f1c856 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java @@ -0,0 +1,55 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.icl.*; + +import java.util.Collection; + +/*** Uplift one variable into the A register - and check if the program still works */ +public class Pass3RegisterUplifting { + + private Program program; + private CompileLog log; + + public Pass3RegisterUplifting(Program program, CompileLog log) { + this.program = program; + this.log = log; + } + + public Program getProgram() { + return program; + } + + public CompileLog getLog() { + return log; + } + + /** Uplift one variable */ + public void uplift() { + + VariableRegisterWeights variableRegisterWeights = program.getScope().getVariableRegisterWeights(); + + double maxWeight = 0.0; + Variable maxVar = null; + + Collection allVars = program.getScope().getAllVariables(true); + for (Variable variable : allVars) { + Double w = variableRegisterWeights.getWeight(variable.getRef()); + if(w!=null && w>maxWeight) { + maxWeight = w; + maxVar = variable; + } + } + // Found max variable! + log.append("Attempting uplift of variable "+maxVar); + + + + + + + + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 30a7bcaf3..8170f3907 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -25,7 +25,7 @@ public class Pass4CodeGeneration { // Generate entry points (if needed) genBlockEntryPoints(asm, block); // Generate label - asm.addLabel(block.getLabel().getFullName().replace('@', 'B').replace(':','_')); + asm.addLabel(block.getLabel().getFullName().replace('@', 'B').replace(':', '_')); // Generate statements genStatements(asm, block); // Generate exit @@ -34,7 +34,7 @@ public class Pass4CodeGeneration { if (defaultSuccessor.hasPhiBlock()) { genBlockPhiTransition(asm, block, defaultSuccessor); } - asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getFullName().replace('@', 'B').replace(':','_')); + asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getFullName().replace('@', 'B').replace(':', '_')); } } return asm; @@ -42,60 +42,107 @@ public class Pass4CodeGeneration { private void genStatements(AsmProgram asm, ControlFlowBlock block) { Iterator statementsIt = block.getStatements().iterator(); + AsmCodegenAluState aluState = new AsmCodegenAluState(); while (statementsIt.hasNext()) { Statement statement = statementsIt.next(); - if (!(statement instanceof StatementPhiBlock)) { - if (statement instanceof StatementAssignment) { - StatementAssignment assignment = (StatementAssignment) statement; - LValue lValue = assignment.getlValue(); - boolean isAlu = false; - if (lValue instanceof VariableRef) { - VariableRef lValueRef = (VariableRef) lValue; - Variable lValueVar = symbols.getVariable(lValueRef); - RegisterAllocation.Register lValRegister = symbols.getRegister(lValueVar); - if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) { - asm.addComment(statement + " // ALU"); - StatementAssignment assignmentAlu = assignment; - statement = statementsIt.next(); - if (!(statement instanceof StatementAssignment)) { - throw new RuntimeException("Error! ALU statement must be followed immediately by assignment using the ALU. " + statement); - } - assignment = (StatementAssignment) statement; - AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols); - asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); - asmFragment.generate(asm); - isAlu = true; - } + generateStatementAsm(asm, block, statement, aluState); + } + } + + /** + * Generate ASM code for a single statement + * + * @param asm The ASM program to generate into + * @param block The block containing the statement + * @param statementsIt The iterator giving access to the next statement + * @param statement The statement to generate ASM code for + */ + public void generateStatementAsm(AsmProgram asm, ControlFlowBlock block, Statement statement, AsmCodegenAluState asmCodeAsmCodegenAluState) { + + // IF the previous statement was added to the ALU register - generate the composite ASM fragment + if (asmCodeAsmCodegenAluState.hasAluAssignment()) { + StatementAssignment assignmentAlu = asmCodeAsmCodegenAluState.getAluAssignment(); + if (!(statement instanceof StatementAssignment)) { + throw new RuntimeException("Error! ALU statement must be followed immediately by assignment using the ALU. " + statement); + } + StatementAssignment assignment = (StatementAssignment) statement; + AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols); + asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); + asmCodeAsmCodegenAluState.clear(); + return; + } + + if (!(statement instanceof StatementPhiBlock)) { + if (statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + LValue lValue = assignment.getlValue(); + boolean isAlu = false; + if (lValue instanceof VariableRef) { + VariableRef lValueRef = (VariableRef) lValue; + Variable lValueVar = symbols.getVariable(lValueRef); + RegisterAllocation.Register lValRegister = symbols.getRegister(lValueVar); + if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) { + asm.addComment(statement + " // ALU"); + StatementAssignment assignmentAlu = assignment; + asmCodeAsmCodegenAluState.setAluAssignment(assignmentAlu); + isAlu = true; } - if (!isAlu) { - if(assignment.getOperator()==null && assignment.getrValue1()==null && isRegisterCopy(lValue, assignment.getrValue2())) { - asm.addComment(lValue.toString(symbols) + " = " + assignment.getrValue2().toString(symbols) + " // register copy "+getRegister(lValue)); - } else { - AsmFragment asmFragment = new AsmFragment(assignment, symbols); - asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); - asmFragment.generate(asm); - } - } - } else if (statement instanceof StatementConditionalJump) { - AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph); - asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); - asmFragment.generate(asm); - } else if (statement instanceof StatementCall) { - StatementCall call = (StatementCall) statement; - ControlFlowBlock callSuccessor = graph.getCallSuccessor(block); - if (callSuccessor != null && callSuccessor.hasPhiBlock()) { - genBlockPhiTransition(asm, block, callSuccessor); - } - asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName()); - } else if (statement instanceof StatementReturn) { - asm.addInstruction("rts", AsmAddressingMode.NON, null); - } else { - throw new RuntimeException("Statement not supported " + statement); } + if (!isAlu) { + if (assignment.getOperator() == null && assignment.getrValue1() == null && isRegisterCopy(lValue, assignment.getrValue2())) { + asm.addComment(lValue.toString(symbols) + " = " + assignment.getrValue2().toString(symbols) + " // register copy " + getRegister(lValue)); + } else { + AsmFragment asmFragment = new AsmFragment(assignment, symbols); + asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); + } + } + } else if (statement instanceof StatementConditionalJump) { + AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph); + asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); + } else if (statement instanceof StatementCall) { + StatementCall call = (StatementCall) statement; + ControlFlowBlock callSuccessor = graph.getCallSuccessor(block); + if (callSuccessor != null && callSuccessor.hasPhiBlock()) { + genBlockPhiTransition(asm, block, callSuccessor); + } + asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName()); + } else if (statement instanceof StatementReturn) { + asm.addInstruction("rts", AsmAddressingMode.NON, null); + } else { + throw new RuntimeException("Statement not supported " + statement); } } } + + /** + * Contains previous assignment added to the ALU register between calls to generateStatementAsm + */ + public static class AsmCodegenAluState { + + private StatementAssignment aluAssignment; + + public void setAluAssignment(StatementAssignment aluAssignment) { + this.aluAssignment = aluAssignment; + } + + public StatementAssignment getAluAssignment() { + return aluAssignment; + } + + public boolean hasAluAssignment() { + return aluAssignment != null; + } + + public void clear() { + aluAssignment = null; + } + } + + private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) { if (block.hasPhiBlock()) { List predecessors = new ArrayList<>(graph.getPredecessors(block)); @@ -108,7 +155,7 @@ public class Pass4CodeGeneration { for (ControlFlowBlock predecessor : predecessors) { if (block.getLabel().equals(predecessor.getConditionalSuccessor())) { genBlockPhiTransition(asm, predecessor, block); - asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getFullName().replace('@', 'B').replace(':','_')); + asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getFullName().replace('@', 'B').replace(':', '_')); } } } @@ -150,7 +197,7 @@ public class Pass4CodeGeneration { private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) { if (isRegisterCopy(lValue, rValue)) { - asm.addComment(lValue.toString(symbols) + " = " + rValue.toString(symbols) + " // register copy "+getRegister(lValue)); + asm.addComment(lValue.toString(symbols) + " = " + rValue.toString(symbols) + " // register copy " + getRegister(lValue)); } else { AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); asm.addComment(lValue.toString(symbols) + " = " + rValue.toString(symbols) + " // " + asmFragment.getSignature()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterAllocationTrivial.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterAllocationTrivial.java index b5fc79c17..e5094f69e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterAllocationTrivial.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterAllocationTrivial.java @@ -21,13 +21,12 @@ public class Pass4RegisterAllocationTrivial { performAllocation(symbols, allocation); // Register allocation for fibmem.kc - /* allocation.allocate(new VariableRef("i#1"), RegisterAllocation.getRegisterX()); allocation.allocate(new VariableRef("i#2"), RegisterAllocation.getRegisterX()); allocation.allocate(new VariableRef("$1"), new RegisterAllocation.RegisterAByte()); allocation.allocate(new VariableRef("$3"), new RegisterAllocation.RegisterALUByte()); - //allocation.allocate(new VariableRef("$4"), new RegisterAllocation.RegisterAByte()); - */ + allocation.allocate(new VariableRef("$4"), new RegisterAllocation.RegisterAByte()); + // Registers for postinc.kc /* diff --git a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java index 02ec1bf4b..2bb110e85 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -62,6 +62,12 @@ public class TestCompilationOutput extends TestCase { tester.testFile("loopnest2"); } + public void testFibMem() throws IOException, URISyntaxException { + TestCompilationOutput tester = new TestCompilationOutput(); + tester.testFile("fibmem"); + } + + private void testFile(String fileName) throws IOException, URISyntaxException { String inputPath = testPath + fileName + ".kc"; diff --git a/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log b/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log index 00ab253ef..9f7907214 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log +++ b/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log @@ -706,8 +706,79 @@ CONTROL FLOW GRAPH to:@END @END: from @3 +Consolidated constant in assignment cursor#0 Multiple usages for variable. Not optimizing sub-constant (byte) y#2 Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 +Succesful SSA optimization Pass2ConstantAdditionElimination +CONTROL FLOW GRAPH +@BEGIN: from + (byte) e#0 ← (byte) 24 / (byte) 2 + (byte~) $3 ← (byte) 0 * (byte) 40 + (byte*~) $4 ← (byte~) $3 + (byte*) cursor#0 ← (byte*~) $4 + (word) 1024 + to:@1 +@1: from @3 @BEGIN + (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) + (byte) xd#1 ← phi( @BEGIN/(byte) 39 ) + (byte) yd#1 ← phi( @BEGIN/(byte) 24 ) + (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) e#0 ) + (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) + (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(byte*) cursor#0 ) + *((byte*) cursor#3) ← (byte) 81 + (byte) x#1 ← (byte) x#2 + (byte) 1 + (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 + (byte) e#1 ← (byte) e#3 + (byte) yd#1 + if((byte) xd#1<(byte) e#1) goto @2 + to:@3 +@2: from @1 + (byte) y#1 ← (byte) y#2 + (byte) 1 + (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 + (byte) e#2 ← (byte) e#1 - (byte) xd#1 + to:@3 +@3: from @1 @2 + (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) + (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) + (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) + (byte~) $13 ← (byte) 39 + (byte) 1 + if((byte) x#1<(byte~) $13) goto @1 + to:@END +@END: from @3 + +Alias (byte~) $3 = (byte*~) $4 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@BEGIN: from + (byte) e#0 ← (byte) 24 / (byte) 2 + (byte~) $3 ← (byte) 0 * (byte) 40 + (byte*) cursor#0 ← (byte~) $3 + (word) 1024 + to:@1 +@1: from @3 @BEGIN + (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) + (byte) xd#1 ← phi( @BEGIN/(byte) 39 ) + (byte) yd#1 ← phi( @BEGIN/(byte) 24 ) + (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) e#0 ) + (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) + (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(byte*) cursor#0 ) + *((byte*) cursor#3) ← (byte) 81 + (byte) x#1 ← (byte) x#2 + (byte) 1 + (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 + (byte) e#1 ← (byte) e#3 + (byte) yd#1 + if((byte) xd#1<(byte) e#1) goto @2 + to:@3 +@2: from @1 + (byte) y#1 ← (byte) y#2 + (byte) 1 + (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 + (byte) e#2 ← (byte) e#1 - (byte) xd#1 + to:@3 +@3: from @1 @2 + (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) + (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) + (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) + (byte~) $13 ← (byte) 39 + (byte) 1 + if((byte) x#1<(byte~) $13) goto @1 + to:@END +@END: from @3 + Redundant Phi (byte) yd#1 (byte) 24 Redundant Phi (byte) xd#1 (byte) 39 Succesful SSA optimization Pass2RedundantPhiElimination @@ -715,8 +786,7 @@ CONTROL FLOW GRAPH @BEGIN: from (byte) e#0 ← (byte) 24 / (byte) 2 (byte~) $3 ← (byte) 0 * (byte) 40 - (byte*~) $4 ← (word) 1024 + (byte~) $3 - (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 + (byte*) cursor#0 ← (byte~) $3 + (word) 1024 to:@1 @1: from @3 @BEGIN (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) @@ -749,40 +819,7 @@ Constant (byte~) $13 (byte) 40 Succesful SSA optimization Pass2ConstantPropagation CONTROL FLOW GRAPH @BEGIN: from - (byte*~) $4 ← (word) 1024 + (byte) 0 - (byte*) cursor#0 ← (byte*~) $4 + (byte) 0 - to:@1 -@1: from @3 @BEGIN - (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) - (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) - (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) - (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(byte*) cursor#0 ) - *((byte*) cursor#3) ← (byte) 81 - (byte) x#1 ← (byte) x#2 + (byte) 1 - (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 - (byte) e#1 ← (byte) e#3 + (byte) 24 - if((byte) 39<(byte) e#1) goto @2 - to:@3 -@2: from @1 - (byte) y#1 ← (byte) y#2 + (byte) 1 - (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 - (byte) e#2 ← (byte) e#1 - (byte) 39 - to:@3 -@3: from @1 @2 - (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) - (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) - (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) - if((byte) x#1<(byte) 40) goto @1 - to:@END -@END: from @3 - -Multiple usages for variable. Not optimizing sub-constant (byte) y#2 -Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 -Constant (byte*~) $4 (word) 1024 -Succesful SSA optimization Pass2ConstantPropagation -CONTROL FLOW GRAPH -@BEGIN: from - (byte*) cursor#0 ← (word) 1024 + (byte) 0 + (byte*) cursor#0 ← (byte) 0 + (word) 1024 to:@1 @1: from @3 @BEGIN (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) diff --git a/src/main/java/dk/camelot64/kickc/test/ref/fibmem.asm b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.asm new file mode 100644 index 000000000..00ae29fef --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.asm @@ -0,0 +1,28 @@ +BBEGIN: + lda #0 + sta 4352 + lda #1 + sta 4353 +B1_from_BBEGIN: + lda #0 + sta 2 +B1_from_B1: +B1: + ldy 2 + lda 4352,y + sta 3 + ldy 2 + lda 4353,y + sta 4 + lda 3 + clc + adc 4 + sta 3 + lda 3 + ldy 2 + sta 4354,y + inc 2 + lda 2 + cmp #15 + bcc B1_from_B1 +BEND: diff --git a/src/main/java/dk/camelot64/kickc/test/ref/fibmem.cfg b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.cfg new file mode 100644 index 000000000..aae01c184 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.cfg @@ -0,0 +1,14 @@ +@BEGIN: from + [0] *((word) 4352) ← (byte) 0 [ ] + [1] *((word) 4353) ← (byte) 1 [ ] + to:@1 +@1: from @1 @BEGIN + [2] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) [ i#2 ] + [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] + [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] + [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] + [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] + [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] + to:@END +@END: from @1 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/fibmem.log b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.log new file mode 100644 index 000000000..c2f1ff917 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.log @@ -0,0 +1,633 @@ +byte[15] fibs = $1100; +fibs[0] = 0; +fibs[1] = 1; +byte i = 0; +do { + fibs[i+2] = fibs[i]+fibs[i+1]; + i = i + 1; +} while(i<15) + +PROGRAM + (byte[15]) fibs ← (word) 4352 + *((byte[15]) fibs + (byte) 0) ← (byte) 0 + *((byte[15]) fibs + (byte) 1) ← (byte) 1 + (byte) i ← (byte) 0 +@1: + (byte~) $0 ← (byte) i + (byte) 2 + (byte~) $1 ← (byte[15]) fibs *idx (byte) i + (byte~) $2 ← (byte) i + (byte) 1 + (byte~) $3 ← (byte[15]) fibs *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i + (byte) 1 + (byte) i ← (byte~) $5 + (boolean~) $6 ← (byte) i < (byte) 15 + if((boolean~) $6) goto @1 + +SYMBOLS +(byte~) $0 +(byte~) $1 +(byte~) $2 +(byte~) $3 +(byte~) $4 +(byte~) $5 +(boolean~) $6 +(label) @1 +(byte[15]) fibs +(byte) i + +INITIAL CONTROL FLOW GRAPH +@BEGIN: from + (byte[15]) fibs ← (word) 4352 + *((byte[15]) fibs + (byte) 0) ← (byte) 0 + *((byte[15]) fibs + (byte) 1) ← (byte) 1 + (byte) i ← (byte) 0 + to:@1 +@1: from @1 @BEGIN + (byte~) $0 ← (byte) i + (byte) 2 + (byte~) $1 ← (byte[15]) fibs *idx (byte) i + (byte~) $2 ← (byte) i + (byte) 1 + (byte~) $3 ← (byte[15]) fibs *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i + (byte) 1 + (byte) i ← (byte~) $5 + (boolean~) $6 ← (byte) i < (byte) 15 + if((boolean~) $6) goto @1 + to:@2 +@2: from @1 + to:@END +@END: from @2 + +Removing empty block @2 +CONTROL FLOW GRAPH +@BEGIN: from + (byte[15]) fibs ← (word) 4352 + *((byte[15]) fibs + (byte) 0) ← (byte) 0 + *((byte[15]) fibs + (byte) 1) ← (byte) 1 + (byte) i ← (byte) 0 + to:@1 +@1: from @1 @BEGIN + (byte~) $0 ← (byte) i + (byte) 2 + (byte~) $1 ← (byte[15]) fibs *idx (byte) i + (byte~) $2 ← (byte) i + (byte) 1 + (byte~) $3 ← (byte[15]) fibs *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i + (byte) 1 + (byte) i ← (byte~) $5 + (boolean~) $6 ← (byte) i < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL +@BEGIN: from + (byte[15]) fibs ← (word) 4352 + *((byte[15]) fibs + (byte) 0) ← (byte) 0 + *((byte[15]) fibs + (byte) 1) ← (byte) 1 + (byte) i ← (byte) 0 + to:@1 +@1: from @1 @BEGIN + (byte~) $0 ← (byte) i + (byte) 2 + (byte~) $1 ← (byte[15]) fibs *idx (byte) i + (byte~) $2 ← (byte) i + (byte) 1 + (byte~) $3 ← (byte[15]) fibs *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i + (byte) 1 + (byte) i ← (byte~) $5 + (boolean~) $6 ← (byte) i < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Completing Phi functions... +CONTROL FLOW GRAPH SSA +@BEGIN: from + (byte[15]) fibs#0 ← (word) 4352 + *((byte[15]) fibs#0 + (byte) 0) ← (byte) 0 + *((byte[15]) fibs#0 + (byte) 1) ← (byte) 1 + (byte) i#0 ← (byte) 0 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @1/(byte[15]) fibs#1 @BEGIN/(byte[15]) fibs#0 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) i#0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i#2 + (byte) 1 + (byte) i#1 ← (byte~) $5 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@BEGIN: from + (byte[15]) fibs#0 ← (word) 4352 + *((byte[15]) fibs#0 + (byte) 0) ← (byte) 0 + *((byte[15]) fibs#0 + (byte) 1) ← (byte) 1 + (byte) i#0 ← (byte) 0 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @1/(byte[15]) fibs#1 @BEGIN/(byte[15]) fibs#0 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) i#0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i#2 + (byte) 1 + (byte) i#1 ← (byte~) $5 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Constant (byte[15]) fibs#0 (word) 4352 +Constant (byte) i#0 (byte) 0 +Succesful SSA optimization Pass2ConstantPropagation +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352 + (byte) 0) ← (byte) 0 + *((word) 4352 + (byte) 1) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @1/(byte[15]) fibs#1 @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i#2 + (byte) 1 + (byte) i#1 ← (byte~) $5 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Consolidated assigned array index constant in assignment *(4352) +Consolidated assigned array index constant in assignment *(4353) +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Succesful SSA optimization Pass2ConstantAdditionElimination +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @1/(byte[15]) fibs#1 @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte~) $5 ← (byte) i#2 + (byte) 1 + (byte) i#1 ← (byte~) $5 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Alias (byte) i#1 = (byte~) $5 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @1/(byte[15]) fibs#1 @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Self Phi Eliminated (byte[15]) fibs#1 +Succesful SSA optimization Pass2SelfPhiElimination +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + (boolean~) $6 ← (byte) i#1 < (byte) 15 + if((boolean~) $6) goto @1 + to:@END +@END: from @1 + +Simple Condition (boolean~) $6 if((byte) i#1<(byte) 15) goto @1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte[15]) fibs#1 ← phi( @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (byte[15]) fibs#1 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (byte[15]) fibs#1 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((byte[15]) fibs#1 + (byte~) $0) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 15) goto @1 + to:@END +@END: from @1 + +Constant (byte[15]) fibs#1 (word) 4352 +Succesful SSA optimization Pass2ConstantPropagation +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte) 2 + (byte~) $1 ← (word) 4352 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte~) $3 ← (word) 4352 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((word) 4352 + (byte~) $0) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 15) goto @1 + to:@END +@END: from @1 + +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Consolidated referenced array index constant in assignment $3 +Consolidated assigned array index constant in assignment *(4354 + $0) +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Succesful SSA optimization Pass2ConstantAdditionElimination +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $0 ← (byte) i#2 + (byte~) $1 ← (word) 4352 *idx (byte) i#2 + (byte~) $2 ← (byte) i#2 + (byte~) $3 ← (word) 4353 *idx (byte~) $2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((word) 4354 + (byte~) $0) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 15) goto @1 + to:@END +@END: from @1 + +Alias (byte) i#2 = (byte~) $0 (byte~) $2 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @1 @BEGIN + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) + (byte~) $1 ← (word) 4352 *idx (byte) i#2 + (byte~) $3 ← (word) 4353 *idx (byte) i#2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((word) 4354 + (byte) i#2) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 15) goto @1 + to:@END +@END: from @1 + +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Block Sequence Planned @BEGIN @1 @END +Added new block during phi lifting @3(between @1 and @1) +Block Sequence Planned @BEGIN @1 @END @3 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + *((word) 4352) ← (byte) 0 + *((word) 4353) ← (byte) 1 + to:@1 +@1: from @3 @BEGIN + (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 0 ) + (byte~) $1 ← (word) 4352 *idx (byte) i#2 + (byte~) $3 ← (word) 4353 *idx (byte) i#2 + (byte~) $4 ← (byte~) $1 + (byte~) $3 + *((word) 4354 + (byte) i#2) ← (byte~) $4 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 15) goto @3 + to:@END +@END: from @1 +@3: from @1 + (byte~) i#3 ← (byte) i#1 + to:@1 + +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + [0] *((word) 4352) ← (byte) 0 [ ] + [1] *((word) 4353) ← (byte) 1 [ ] + to:@1 +@1: from @3 @BEGIN + [2] (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 0 ) [ i#2 ] + [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] + [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] + [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] + [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] + [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [8] if((byte) i#1<(byte) 15) goto @3 [ i#1 ] + to:@END +@END: from @1 +@3: from @1 + [9] (byte~) i#3 ← (byte) i#1 [ i#3 ] + to:@1 + +Created 1 initial phi equivalence classes +Coalesced [9] i#3 ← i#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) @3 +Block Sequence Planned @BEGIN @1 @END +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - PHI MEM COALESCED +@BEGIN: from + [0] *((word) 4352) ← (byte) 0 [ ] + [1] *((word) 4353) ← (byte) 1 [ ] + to:@1 +@1: from @1 @BEGIN + [2] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 0 ) [ i#2 ] + [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] + [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] + [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] + [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] + [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] + to:@END +@END: from @1 + +CALL GRAPH + +DOMINATORS +@BEGIN dominated by @BEGIN +@1 dominated by @1 @BEGIN +@END dominated by @1 @BEGIN @END + +Found back edge: Loop head: @1 tails: @1 blocks: null +Populated: Loop head: @1 tails: @1 blocks: @1 +NATURAL LOOPS +Loop head: @1 tails: @1 blocks: @1 + +Found 1 loops in scope [] + Loop head: @1 tails: @1 blocks: @1 +NATURAL LOOPS WITH DEPTH +Loop head: @1 tails: @1 blocks: @1 depth: 1 + +Initial phi equivalence classes +[ i#2 i#1 ] +Copy Coalesced equivalence classes +[ i#2 i#1 ] +Added variable $1 to zero page equivalence class [ $1 ] +Added variable $3 to zero page equivalence class [ $3 ] +Added variable $4 to zero page equivalence class [ $1 $4 ] +Complete equivalence classes +[ i#2 i#1 ] +[ $1 $4 ] +[ $3 ] +Allocated zp byte:2 to zp byte:2 [ i#2 i#1 ] +Allocated zp byte:3 to zp byte:3 [ $1 $4 ] +Allocated zp byte:4 to zp byte:4 [ $3 ] + +VARIABLE REGISTER WEIGHTS +(byte~) $1 11.0 +(byte~) $3 22.0 +(byte~) $4 22.0 +(byte[15]) fibs +(byte) i +(byte) i#1 16.5 +(byte) i#2 11.0 + +zp byte:2 [ i#2 i#1 ] +zp byte:3 [ $1 $4 ] +zp byte:4 [ $3 ] + +Re-allocated ZP register from zp byte:2 to zp byte:2 +Re-allocated ZP register from zp byte:3 to zp byte:3 +Re-allocated ZP register from zp byte:4 to zp byte:4 +INITIAL ASM +BBEGIN: + // [0] *((word) 4352) ← (byte) 0 [ ] // coptr1=coby2 + lda #0 + sta 4352 + // [1] *((word) 4353) ← (byte) 1 [ ] // coptr1=coby2 + lda #1 + sta 4353 +B1_from_BBEGIN: + // (byte) i#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 2 + jmp B1 +B1_from_B1: + // (byte) i#2 = (byte) i#1 // register copy zp byte:2 + jmp B1 +B1: + // [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4352,y + sta 3 + // [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4353,y + sta 4 + // [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] // zpby1=zpby1_plus_zpby2 + lda 3 + clc + adc 4 + sta 3 + // [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + lda 3 + ldy 2 + sta 4354,y + // [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + inc 2 + // [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + lda 2 + cmp #15 + bcc B1_from_B1 + jmp BEND +BEND: + +Removing instruction jmp B1 +Removing instruction jmp BEND +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +BBEGIN: + // [0] *((word) 4352) ← (byte) 0 [ ] // coptr1=coby2 + lda #0 + sta 4352 + // [1] *((word) 4353) ← (byte) 1 [ ] // coptr1=coby2 + lda #1 + sta 4353 +B1_from_BBEGIN: + // (byte) i#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 2 + jmp B1 +B1_from_B1: + // (byte) i#2 = (byte) i#1 // register copy zp byte:2 +B1: + // [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4352,y + sta 3 + // [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4353,y + sta 4 + // [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] // zpby1=zpby1_plus_zpby2 + lda 3 + clc + adc 4 + sta 3 + // [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + lda 3 + ldy 2 + sta 4354,y + // [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + inc 2 + // [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + lda 2 + cmp #15 + bcc B1_from_B1 +BEND: + +Removing instruction jmp B1 +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +BBEGIN: + // [0] *((word) 4352) ← (byte) 0 [ ] // coptr1=coby2 + lda #0 + sta 4352 + // [1] *((word) 4353) ← (byte) 1 [ ] // coptr1=coby2 + lda #1 + sta 4353 +B1_from_BBEGIN: + // (byte) i#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 2 +B1_from_B1: + // (byte) i#2 = (byte) i#1 // register copy zp byte:2 +B1: + // [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4352,y + sta 3 + // [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4353,y + sta 4 + // [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] // zpby1=zpby1_plus_zpby2 + lda 3 + clc + adc 4 + sta 3 + // [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + lda 3 + ldy 2 + sta 4354,y + // [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + inc 2 + // [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + lda 2 + cmp #15 + bcc B1_from_B1 +BEND: + +FINAL SYMBOL TABLE +(byte~) $1 zp byte:3 11.0 +(byte~) $3 zp byte:4 22.0 +(byte~) $4 zp byte:3 22.0 +(label) @1 +(label) @BEGIN +(label) @END +(byte[15]) fibs +(byte) i +(byte) i#1 zp byte:2 16.5 +(byte) i#2 zp byte:2 11.0 + +zp byte:2 [ i#2 i#1 ] +zp byte:3 [ $1 $4 ] +zp byte:4 [ $3 ] + +FINAL CODE +BBEGIN: + // [0] *((word) 4352) ← (byte) 0 [ ] // coptr1=coby2 + lda #0 + sta 4352 + // [1] *((word) 4353) ← (byte) 1 [ ] // coptr1=coby2 + lda #1 + sta 4353 +B1_from_BBEGIN: + // (byte) i#2 = (byte) 0 // zpby1=coby1 + lda #0 + sta 2 +B1_from_B1: + // (byte) i#2 = (byte) i#1 // register copy zp byte:2 +B1: + // [3] (byte~) $1 ← (word) 4352 *idx (byte) i#2 [ i#2 $1 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4352,y + sta 3 + // [4] (byte~) $3 ← (word) 4353 *idx (byte) i#2 [ i#2 $1 $3 ] // zpby1=cowo1_staridx_zpby2 + ldy 2 + lda 4353,y + sta 4 + // [5] (byte~) $4 ← (byte~) $1 + (byte~) $3 [ i#2 $4 ] // zpby1=zpby1_plus_zpby2 + lda 3 + clc + adc 4 + sta 3 + // [6] *((word) 4354 + (byte) i#2) ← (byte~) $4 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + lda 3 + ldy 2 + sta 4354,y + // [7] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + inc 2 + // [8] if((byte) i#1<(byte) 15) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + lda 2 + cmp #15 + bcc B1_from_B1 +BEND: + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/fibmem.sym b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.sym new file mode 100644 index 000000000..efecb3bd3 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/fibmem.sym @@ -0,0 +1,14 @@ +(byte~) $1 zp byte:3 11.0 +(byte~) $3 zp byte:4 22.0 +(byte~) $4 zp byte:3 22.0 +(label) @1 +(label) @BEGIN +(label) @END +(byte[15]) fibs +(byte) i +(byte) i#1 zp byte:2 16.5 +(byte) i#2 zp byte:2 11.0 + +zp byte:2 [ i#2 i#1 ] +zp byte:3 [ $1 $4 ] +zp byte:4 [ $3 ] diff --git a/src/main/java/dk/camelot64/kickc/test/ref/flipper-rex2.log b/src/main/java/dk/camelot64/kickc/test/ref/flipper-rex2.log index 9ecb42a29..cccb324cd 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/flipper-rex2.log +++ b/src/main/java/dk/camelot64/kickc/test/ref/flipper-rex2.log @@ -1468,6 +1468,204 @@ plot::@return: from plot::@3 to:@RETURN @END: from @BEGIN +Consolidated constant in assignment plot::$2 +Succesful SSA optimization Pass2ConstantAdditionElimination +CONTROL FLOW GRAPH +@BEGIN: from + call main param-assignment + to:@END +main: from @BEGIN + (byte[256]) buffer2#15 ← phi( @BEGIN/(word) 4352 ) + (byte[1000]) SCREEN#11 ← phi( @BEGIN/(word) 1024 ) + (byte*) RASTER#8 ← phi( @BEGIN/(word) 53266 ) + (byte[256]) buffer1#9 ← phi( @BEGIN/(word) 4096 ) + call prepare param-assignment + to:main::@9 +main::@9: from main + (byte[256]) buffer2#14 ← phi( main/(byte[256]) buffer2#15 ) + (byte[256]) buffer1#22 ← phi( main/(byte[256]) buffer1#9 ) + (byte[1000]) SCREEN#10 ← phi( main/(byte[1000]) SCREEN#11 ) + (byte*) RASTER#6 ← phi( main/(byte*) RASTER#8 ) + to:main::@1 +main::@1: from main::@11 main::@9 + (byte[256]) buffer2#11 ← phi( main::@11/(byte[256]) buffer2#13 main::@9/(byte[256]) buffer2#14 ) + (byte[256]) buffer1#19 ← phi( main::@11/(byte[256]) buffer1#21 main::@9/(byte[256]) buffer1#22 ) + (byte[1000]) SCREEN#7 ← phi( main::@11/(byte[1000]) SCREEN#9 main::@9/(byte[1000]) SCREEN#10 ) + (byte*) RASTER#3 ← phi( main::@11/(byte*) RASTER#5 main::@9/(byte*) RASTER#6 ) + to:main::@3 +main::@2: from main::@6 + (byte[256]) buffer2#12 ← phi( main::@6/(byte[256]) buffer2#8 ) + (byte[256]) buffer1#20 ← phi( main::@6/(byte[256]) buffer1#16 ) + (byte[1000]) SCREEN#8 ← phi( main::@6/(byte[1000]) SCREEN#4 ) + (byte) main::c#5 ← phi( main::@6/(byte) main::c#1 ) + (byte*) RASTER#4 ← phi( main::@6/(byte*) RASTER#7 ) + to:main::@3 +main::@3: from main::@1 main::@2 main::@3 + (byte[256]) buffer2#10 ← phi( main::@1/(byte[256]) buffer2#11 main::@2/(byte[256]) buffer2#12 main::@3/(byte[256]) buffer2#10 ) + (byte[256]) buffer1#18 ← phi( main::@1/(byte[256]) buffer1#19 main::@2/(byte[256]) buffer1#20 main::@3/(byte[256]) buffer1#18 ) + (byte[1000]) SCREEN#6 ← phi( main::@1/(byte[1000]) SCREEN#7 main::@2/(byte[1000]) SCREEN#8 main::@3/(byte[1000]) SCREEN#6 ) + (byte) main::c#4 ← phi( main::@1/(byte) 25 main::@2/(byte) main::c#5 main::@3/(byte) main::c#4 ) + (byte*) RASTER#1 ← phi( main::@1/(byte*) RASTER#3 main::@2/(byte*) RASTER#4 main::@3/(byte*) RASTER#1 ) + (byte~) main::$1 ← * (byte*) RASTER#1 + (boolean~) main::$2 ← (byte~) main::$1 != (byte) 254 + if((boolean~) main::$2) goto main::@3 + to:main::@4 +main::@4: from main::@3 main::@4 + (byte[256]) buffer2#9 ← phi( main::@3/(byte[256]) buffer2#10 main::@4/(byte[256]) buffer2#9 ) + (byte[256]) buffer1#17 ← phi( main::@3/(byte[256]) buffer1#18 main::@4/(byte[256]) buffer1#17 ) + (byte[1000]) SCREEN#5 ← phi( main::@3/(byte[1000]) SCREEN#6 main::@4/(byte[1000]) SCREEN#5 ) + (byte) main::c#3 ← phi( main::@3/(byte) main::c#4 main::@4/(byte) main::c#3 ) + (byte*) RASTER#2 ← phi( main::@3/(byte*) RASTER#1 main::@4/(byte*) RASTER#2 ) + (byte~) main::$3 ← * (byte*) RASTER#2 + (boolean~) main::$4 ← (byte~) main::$3 != (byte) 255 + if((boolean~) main::$4) goto main::@4 + to:main::@6 +main::@6: from main::@4 + (byte[256]) buffer2#8 ← phi( main::@4/(byte[256]) buffer2#9 ) + (byte[256]) buffer1#16 ← phi( main::@4/(byte[256]) buffer1#17 ) + (byte[1000]) SCREEN#4 ← phi( main::@4/(byte[1000]) SCREEN#5 ) + (byte*) RASTER#7 ← phi( main::@4/(byte*) RASTER#2 ) + (byte) main::c#2 ← phi( main::@4/(byte) main::c#3 ) + (byte) main::c#1 ← -- (byte) main::c#2 + (boolean~) main::$5 ← (byte) main::c#1 != (byte) 0 + if((boolean~) main::$5) goto main::@2 + to:main::@7 +main::@7: from main::@6 + (byte*) RASTER#10 ← phi( main::@6/(byte*) RASTER#7 ) + (byte[256]) buffer2#7 ← phi( main::@6/(byte[256]) buffer2#8 ) + (byte[256]) buffer1#14 ← phi( main::@6/(byte[256]) buffer1#16 ) + (byte[1000]) SCREEN#3 ← phi( main::@6/(byte[1000]) SCREEN#4 ) + call flip param-assignment + to:main::@10 +main::@10: from main::@7 + (byte[256]) buffer2#16 ← phi( main::@7/(byte[256]) buffer2#7 ) + (byte[256]) buffer1#15 ← phi( main::@7/(byte[256]) buffer1#14 ) + (byte*) RASTER#9 ← phi( main::@7/(byte*) RASTER#10 ) + (byte[1000]) SCREEN#2 ← phi( main::@7/(byte[1000]) SCREEN#3 ) + call plot param-assignment + to:main::@11 +main::@11: from main::@10 + (byte[256]) buffer2#13 ← phi( main::@10/(byte[256]) buffer2#16 ) + (byte[256]) buffer1#21 ← phi( main::@10/(byte[256]) buffer1#15 ) + (byte[1000]) SCREEN#9 ← phi( main::@10/(byte[1000]) SCREEN#2 ) + (byte*) RASTER#5 ← phi( main::@10/(byte*) RASTER#9 ) + if(true) goto main::@1 + to:main::@return +main::@return: from main::@11 + return + to:@RETURN +prepare: from main + (byte[256]) buffer1#5 ← phi( main/(byte[256]) buffer1#9 ) + to:prepare::@1 +prepare::@1: from prepare prepare::@1 + (byte[256]) buffer1#1 ← phi( prepare/(byte[256]) buffer1#5 prepare::@1/(byte[256]) buffer1#1 ) + (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) + *((byte[256]) buffer1#1 + (byte) prepare::i#2) ← (byte) prepare::i#2 + (byte) prepare::i#1 ← ++ (byte) prepare::i#2 + (boolean~) prepare::$0 ← (byte) prepare::i#1 != (byte) 0 + if((boolean~) prepare::$0) goto prepare::@1 + to:prepare::@return +prepare::@return: from prepare::@1 + return + to:@RETURN +flip: from main::@7 + (byte[256]) buffer2#5 ← phi( main::@7/(byte[256]) buffer2#7 ) + (byte[256]) buffer1#10 ← phi( main::@7/(byte[256]) buffer1#14 ) + to:flip::@1 +flip::@1: from flip flip::@4 + (byte) flip::r#4 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 ) + (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 ) + (byte[256]) buffer2#3 ← phi( flip/(byte[256]) buffer2#5 flip::@4/(byte[256]) buffer2#6 ) + (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#4 ) + (byte[256]) buffer1#6 ← phi( flip/(byte[256]) buffer1#10 flip::@4/(byte[256]) buffer1#11 ) + to:flip::@2 +flip::@2: from flip::@1 flip::@2 + (byte) flip::r#3 ← phi( flip::@1/(byte) flip::r#4 flip::@2/(byte) flip::r#3 ) + (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) + (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) + (byte[256]) buffer2#1 ← phi( flip::@1/(byte[256]) buffer2#3 flip::@2/(byte[256]) buffer2#1 ) + (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) + (byte[256]) buffer1#2 ← phi( flip::@1/(byte[256]) buffer1#6 flip::@2/(byte[256]) buffer1#2 ) + (byte~) flip::$0 ← (byte[256]) buffer1#2 *idx (byte) flip::srcIdx#2 + *((byte[256]) buffer2#1 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 + (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 + (byte~) flip::$1 ← (byte) flip::dstIdx#3 + (byte) 16 + (byte) flip::dstIdx#1 ← (byte~) flip::$1 + (byte) flip::c#1 ← -- (byte) flip::c#2 + (boolean~) flip::$2 ← (byte) flip::c#1 != (byte) 0 + if((boolean~) flip::$2) goto flip::@2 + to:flip::@4 +flip::@4: from flip::@2 + (byte[256]) buffer2#6 ← phi( flip::@2/(byte[256]) buffer2#1 ) + (byte) flip::srcIdx#4 ← phi( flip::@2/(byte) flip::srcIdx#1 ) + (byte[256]) buffer1#11 ← phi( flip::@2/(byte[256]) buffer1#2 ) + (byte) flip::r#2 ← phi( flip::@2/(byte) flip::r#3 ) + (byte) flip::dstIdx#4 ← phi( flip::@2/(byte) flip::dstIdx#1 ) + (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#4 + (byte) flip::r#1 ← -- (byte) flip::r#2 + (boolean~) flip::$3 ← (byte) flip::r#1 != (byte) 0 + if((boolean~) flip::$3) goto flip::@1 + to:flip::@5 +flip::@5: from flip::@4 + (byte[256]) buffer1#7 ← phi( flip::@4/(byte[256]) buffer1#11 ) + (byte[256]) buffer2#4 ← phi( flip::@4/(byte[256]) buffer2#6 ) + to:flip::@3 +flip::@3: from flip::@3 flip::@5 + (byte[256]) buffer1#3 ← phi( flip::@3/(byte[256]) buffer1#3 flip::@5/(byte[256]) buffer1#7 ) + (byte) flip::i#2 ← phi( flip::@3/(byte) flip::i#1 flip::@5/(byte) 0 ) + (byte[256]) buffer2#2 ← phi( flip::@3/(byte[256]) buffer2#2 flip::@5/(byte[256]) buffer2#4 ) + (byte~) flip::$4 ← (byte[256]) buffer2#2 *idx (byte) flip::i#2 + *((byte[256]) buffer1#3 + (byte) flip::i#2) ← (byte~) flip::$4 + (byte) flip::i#1 ← ++ (byte) flip::i#2 + (boolean~) flip::$5 ← (byte) flip::i#1 != (byte) 0 + if((boolean~) flip::$5) goto flip::@3 + to:flip::@return +flip::@return: from flip::@3 + return + to:@RETURN +plot: from main::@10 + (byte[256]) buffer1#12 ← phi( main::@10/(byte[256]) buffer1#15 ) + (byte[1000]) SCREEN#1 ← phi( main::@10/(byte[1000]) SCREEN#2 ) + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*~) plot::$2 ← (byte*~) plot::$1 + (byte) 212 + (byte*) plot::line#0 ← (byte*~) plot::$2 + to:plot::@1 +plot::@1: from plot plot::@3 + (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) + (byte*) plot::line#4 ← phi( plot/(byte*) plot::line#0 plot::@3/(byte*) plot::line#1 ) + (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#4 ) + (byte[256]) buffer1#8 ← phi( plot/(byte[256]) buffer1#12 plot::@3/(byte[256]) buffer1#13 ) + to:plot::@2 +plot::@2: from plot::@1 plot::@2 + (byte) plot::y#3 ← phi( plot::@1/(byte) plot::y#4 plot::@2/(byte) plot::y#3 ) + (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) + (byte*) plot::line#2 ← phi( plot::@1/(byte*) plot::line#4 plot::@2/(byte*) plot::line#2 ) + (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) + (byte[256]) buffer1#4 ← phi( plot::@1/(byte[256]) buffer1#8 plot::@2/(byte[256]) buffer1#4 ) + (byte~) plot::$3 ← (byte[256]) buffer1#4 *idx (byte) plot::i#2 + *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 + (byte) plot::i#1 ← ++ (byte) plot::i#2 + (byte) plot::x#1 ← ++ (byte) plot::x#2 + (boolean~) plot::$4 ← (byte) plot::x#1 < (byte) 16 + if((boolean~) plot::$4) goto plot::@2 + to:plot::@3 +plot::@3: from plot::@2 + (byte) plot::i#4 ← phi( plot::@2/(byte) plot::i#1 ) + (byte[256]) buffer1#13 ← phi( plot::@2/(byte[256]) buffer1#4 ) + (byte) plot::y#2 ← phi( plot::@2/(byte) plot::y#3 ) + (byte*) plot::line#3 ← phi( plot::@2/(byte*) plot::line#2 ) + (byte*~) plot::$5 ← (byte*) plot::line#3 + (byte) 40 + (byte*) plot::line#1 ← (byte*~) plot::$5 + (byte) plot::y#1 ← -- (byte) plot::y#2 + (boolean~) plot::$6 ← (byte) plot::y#1 != (byte) 0 + if((boolean~) plot::$6) goto plot::@1 + to:plot::@return +plot::@return: from plot::@3 + return + to:@RETURN +@END: from @BEGIN + +Not aliassing across scopes: plot::$1 SCREEN#1 Alias (byte*) RASTER#6 = (byte*) RASTER#8 Alias (byte[1000]) SCREEN#10 = (byte[1000]) SCREEN#11 Alias (byte[256]) buffer1#22 = (byte[256]) buffer1#9 (byte[256]) buffer1#5 @@ -1607,8 +1805,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -1758,8 +1956,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -1924,8 +2122,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2073,8 +2271,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2208,8 +2406,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2340,8 +2538,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#4 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2372,7 +2570,7 @@ plot::@return: from plot::@3 @END: from @BEGIN Multiple usages for variable. Not optimizing sub-constant (byte) prepare::i#2 -Multiple usages for variable. Not optimizing sub-constant (byte[1000]) SCREEN#1 +Not aliassing across scopes: plot::$1 SCREEN#1 Alias (byte*) RASTER#1 = (byte*) RASTER#10 Alias (byte) main::c#2 = (byte) main::c#4 Alias (byte[1000]) SCREEN#1 = (byte[1000]) SCREEN#6 @@ -2474,8 +2672,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2599,8 +2797,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2628,7 +2826,7 @@ plot::@return: from plot::@3 @END: from @BEGIN Multiple usages for variable. Not optimizing sub-constant (byte) prepare::i#2 -Multiple usages for variable. Not optimizing sub-constant (byte[1000]) SCREEN#1 +Not aliassing across scopes: plot::$1 SCREEN#1 Alias (byte*) RASTER#1 = (byte*) RASTER#3 Alias (byte[1000]) SCREEN#1 = (byte[1000]) SCREEN#7 Alias (byte[256]) buffer1#10 = (byte[256]) buffer1#19 (byte[256]) buffer1#11 (byte[256]) buffer1#13 @@ -2717,8 +2915,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2832,8 +3030,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (byte[1000]) SCREEN#1 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -2943,8 +3141,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (word) 1024 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (word) 1024 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -3054,8 +3252,8 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*~) plot::$1 ← (word) 1024 + (byte) 200 - (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 12 + (byte*~) plot::$1 ← (word) 1024 + (byte*) plot::line#0 ← (byte*~) plot::$1 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) @@ -3081,7 +3279,7 @@ plot::@return: from plot::@3 to:@RETURN @END: from @BEGIN -Constant (byte*~) plot::$1 (word) 1224 +Constant (byte*~) plot::$1 (word) 1024 Succesful SSA optimization Pass2ConstantPropagation CONTROL FLOW GRAPH @BEGIN: from @@ -3160,7 +3358,7 @@ flip::@return: from flip::@3 return to:@RETURN plot: from main::@10 - (byte*) plot::line#0 ← (word) 1224 + (byte) 12 + (byte*) plot::line#0 ← (word) 1024 + (byte) 212 to:plot::@1 plot::@1: from plot plot::@3 (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) diff --git a/src/main/java/dk/camelot64/kickc/test/ref/minus.asm b/src/main/java/dk/camelot64/kickc/test/ref/minus.asm index f641d0228..84fb3ca33 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/minus.asm +++ b/src/main/java/dk/camelot64/kickc/test/ref/minus.asm @@ -4,13 +4,9 @@ B1_from_BBEGIN: sta 2 B1_from_B1: B1: - lda #2 + lda 2 clc - adc 2 - sta 3 - lda 3 - clc - adc #2 + adc #4 sta 3 lda 3 ldy 2 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/minus.cfg b/src/main/java/dk/camelot64/kickc/test/ref/minus.cfg index 5fe9d1bf2..77aeb7f43 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/minus.cfg +++ b/src/main/java/dk/camelot64/kickc/test/ref/minus.cfg @@ -2,10 +2,9 @@ to:@1 @1: from @1 @BEGIN [0] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) [ i#2 ] - [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] - [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] - [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] - [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] - [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] + [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] + [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] to:@END @END: from @1 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/minus.log b/src/main/java/dk/camelot64/kickc/test/ref/minus.log index 06545be0e..059f07381 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/minus.log +++ b/src/main/java/dk/camelot64/kickc/test/ref/minus.log @@ -134,7 +134,26 @@ CONTROL FLOW GRAPH @END: from @1 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Consolidated constant in assignment $1 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Succesful SSA optimization Pass2ConstantAdditionElimination +CONTROL FLOW GRAPH +@BEGIN: from + to:@1 +@1: from @1 @BEGIN + (byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @BEGIN/(word) 4352 ) + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) + (byte~) $0 ← (byte) i#2 + (byte~) $1 ← (byte~) $0 + (byte) 4 + *((byte[16]) p#1 + (byte) i#2) ← (byte~) $1 + (byte~) $2 ← (byte) i#2 + (byte) 1 + (byte) i#1 ← (byte~) $2 + (boolean~) $3 ← (byte) i#1 < (byte) 10 + if((boolean~) $3) goto @1 + to:@END +@END: from @1 + +Alias (byte) i#2 = (byte~) $0 Alias (byte) i#1 = (byte~) $2 Succesful SSA optimization Pass2AliasElimination CONTROL FLOW GRAPH @@ -143,8 +162,7 @@ CONTROL FLOW GRAPH @1: from @1 @BEGIN (byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @BEGIN/(word) 4352 ) (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 + (byte~) $1 ← (byte) i#2 + (byte) 4 *((byte[16]) p#1 + (byte) i#2) ← (byte~) $1 (byte) i#1 ← (byte) i#2 + (byte) 1 (boolean~) $3 ← (byte) i#1 < (byte) 10 @@ -160,8 +178,7 @@ CONTROL FLOW GRAPH @1: from @1 @BEGIN (byte[16]) p#1 ← phi( @BEGIN/(word) 4352 ) (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 + (byte~) $1 ← (byte) i#2 + (byte) 4 *((byte[16]) p#1 + (byte) i#2) ← (byte~) $1 (byte) i#1 ← (byte) i#2 + (byte) 1 (boolean~) $3 ← (byte) i#1 < (byte) 10 @@ -177,8 +194,7 @@ CONTROL FLOW GRAPH @1: from @1 @BEGIN (byte[16]) p#1 ← phi( @BEGIN/(word) 4352 ) (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 + (byte~) $1 ← (byte) i#2 + (byte) 4 *((byte[16]) p#1 + (byte) i#2) ← (byte~) $1 (byte) i#1 ← (byte) i#2 + (byte) 1 if((byte) i#1<(byte) 10) goto @1 @@ -192,8 +208,7 @@ CONTROL FLOW GRAPH to:@1 @1: from @1 @BEGIN (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 + (byte~) $1 ← (byte) i#2 + (byte) 4 *((word) 4352 + (byte) i#2) ← (byte~) $1 (byte) i#1 ← (byte) i#2 + (byte) 1 if((byte) i#1<(byte) 10) goto @1 @@ -214,8 +229,7 @@ CONTROL FLOW GRAPH - PHI LIFTED to:@1 @1: from @3 @BEGIN (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 + (byte~) $1 ← (byte) i#2 + (byte) 4 *((word) 4352 + (byte) i#2) ← (byte~) $1 (byte) i#1 ← (byte) i#2 + (byte) 1 if((byte) i#1<(byte) 10) goto @3 @@ -225,41 +239,37 @@ CONTROL FLOW GRAPH - PHI LIFTED (byte~) i#3 ← (byte) i#1 to:@1 -Propagating live ranges... Propagating live ranges... CONTROL FLOW GRAPH - LIVE RANGES @BEGIN: from to:@1 @1: from @3 @BEGIN [0] (byte) i#2 ← phi( @3/(byte~) i#3 @BEGIN/(byte) 5 ) [ i#2 ] - [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] - [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] - [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] - [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] - [5] if((byte) i#1<(byte) 10) goto @3 [ i#1 ] + [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] + [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [4] if((byte) i#1<(byte) 10) goto @3 [ i#1 ] to:@END @END: from @1 @3: from @1 - [6] (byte~) i#3 ← (byte) i#1 [ i#3 ] + [5] (byte~) i#3 ← (byte) i#1 [ i#3 ] to:@1 Created 1 initial phi equivalence classes -Coalesced [6] i#3 ← i#1 +Coalesced [5] i#3 ← i#1 Coalesced down to 1 phi equivalence classes Culled Empty Block (label) @3 Block Sequence Planned @BEGIN @1 @END Propagating live ranges... -Propagating live ranges... CONTROL FLOW GRAPH - PHI MEM COALESCED @BEGIN: from to:@1 @1: from @1 @BEGIN [0] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) [ i#2 ] - [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] - [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] - [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] - [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] - [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] + [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] + [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] to:@END @END: from @1 @@ -284,24 +294,22 @@ Initial phi equivalence classes [ i#2 i#1 ] Copy Coalesced equivalence classes [ i#2 i#1 ] -Added variable $0 to zero page equivalence class [ $0 ] -Added variable $1 to zero page equivalence class [ $0 $1 ] +Added variable $1 to zero page equivalence class [ $1 ] Complete equivalence classes [ i#2 i#1 ] -[ $0 $1 ] +[ $1 ] Allocated zp byte:2 to zp byte:2 [ i#2 i#1 ] -Allocated zp byte:3 to zp byte:3 [ $0 $1 ] +Allocated zp byte:3 to zp byte:3 [ $1 ] VARIABLE REGISTER WEIGHTS -(byte~) $0 22.0 (byte~) $1 22.0 (byte) i (byte) i#1 16.5 -(byte) i#2 11.0 +(byte) i#2 14.666666666666666 (byte[16]) p zp byte:2 [ i#2 i#1 ] -zp byte:3 [ $0 $1 ] +zp byte:3 [ $1 ] Re-allocated ZP register from zp byte:2 to zp byte:2 Re-allocated ZP register from zp byte:3 to zp byte:3 @@ -316,23 +324,18 @@ B1_from_B1: // (byte) i#2 = (byte) i#1 // register copy zp byte:2 jmp B1 B1: - // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 - lda #2 + // [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 + lda 2 clc - adc 2 + adc #4 sta 3 - // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby1_plus_coby1 - lda 3 - clc - adc #2 - sta 3 - // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + // [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 2 sta 4352,y - // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + // [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 inc 2 - // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + // [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #10 bcc B1_from_B1 @@ -352,23 +355,18 @@ B1_from_BBEGIN: B1_from_B1: // (byte) i#2 = (byte) i#1 // register copy zp byte:2 B1: - // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 - lda #2 + // [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 + lda 2 clc - adc 2 + adc #4 sta 3 - // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby1_plus_coby1 - lda 3 - clc - adc #2 - sta 3 - // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + // [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 2 sta 4352,y - // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + // [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 inc 2 - // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + // [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #10 bcc B1_from_B1 @@ -385,41 +383,35 @@ B1_from_BBEGIN: B1_from_B1: // (byte) i#2 = (byte) i#1 // register copy zp byte:2 B1: - // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 - lda #2 + // [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 + lda 2 clc - adc 2 + adc #4 sta 3 - // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby1_plus_coby1 - lda 3 - clc - adc #2 - sta 3 - // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + // [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 2 sta 4352,y - // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + // [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 inc 2 - // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + // [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #10 bcc B1_from_B1 BEND: FINAL SYMBOL TABLE -(byte~) $0 zp byte:3 22.0 (byte~) $1 zp byte:3 22.0 (label) @1 (label) @BEGIN (label) @END (byte) i (byte) i#1 zp byte:2 16.5 -(byte) i#2 zp byte:2 11.0 +(byte) i#2 zp byte:2 14.666666666666666 (byte[16]) p zp byte:2 [ i#2 i#1 ] -zp byte:3 [ $0 $1 ] +zp byte:3 [ $1 ] FINAL CODE BBEGIN: @@ -430,23 +422,18 @@ B1_from_BBEGIN: B1_from_B1: // (byte) i#2 = (byte) i#1 // register copy zp byte:2 B1: - // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 - lda #2 + // [1] (byte~) $1 ← (byte) i#2 + (byte) 4 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 + lda 2 clc - adc 2 + adc #4 sta 3 - // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby1_plus_coby1 - lda 3 - clc - adc #2 - sta 3 - // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 + // [2] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 2 sta 4352,y - // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 + // [3] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby1_plus_1 inc 2 - // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 + // [4] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #10 bcc B1_from_B1 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/minus.sym b/src/main/java/dk/camelot64/kickc/test/ref/minus.sym index 672e79f14..06669901d 100644 --- a/src/main/java/dk/camelot64/kickc/test/ref/minus.sym +++ b/src/main/java/dk/camelot64/kickc/test/ref/minus.sym @@ -1,12 +1,11 @@ -(byte~) $0 zp byte:3 22.0 (byte~) $1 zp byte:3 22.0 (label) @1 (label) @BEGIN (label) @END (byte) i (byte) i#1 zp byte:2 16.5 -(byte) i#2 zp byte:2 11.0 +(byte) i#2 zp byte:2 14.666666666666666 (byte[16]) p zp byte:2 [ i#2 i#1 ] -zp byte:3 [ $0 $1 ] +zp byte:3 [ $1 ]