diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_coby1.asm new file mode 100644 index 000000000..159b74b48 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_coby1.asm @@ -0,0 +1,3 @@ +lda {zpby1} +clc +adc #{coby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_zpby2.asm new file mode 100644 index 000000000..bce1722ee --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=zpby1_plus_zpby2.asm @@ -0,0 +1,3 @@ +lda {zpby1} +clc +adc {zpby2} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=aby.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=aby.asm new file mode 100644 index 000000000..a4bf27e7e --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=aby.asm @@ -0,0 +1 @@ +sta {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=aby_plus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=aby_plus_coby1.asm new file mode 100644 index 000000000..ff2537921 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=aby_plus_coby1.asm @@ -0,0 +1,3 @@ +clc +adc #{coby1} +sta {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java index 777104295..773920456 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java @@ -32,7 +32,7 @@ public class ControlFlowGraphBaseVisitor { } else if(statement instanceof StatementPhi) { return visitPhi((StatementPhi) statement); } else if(statement instanceof StatementCall) { - return visitCallLValue((StatementCall) statement); + return visitCall((StatementCall) statement); } else if(statement instanceof StatementReturn) { return visitReturn((StatementReturn) statement); } else if(statement instanceof StatementProcedureBegin) { @@ -76,7 +76,7 @@ public class ControlFlowGraphBaseVisitor { return null; } - public T visitCallLValue(StatementCall callLValue) { + public T visitCall(StatementCall callLValue) { return null; } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java index 3aba9fa14..0ee885fc0 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java @@ -156,7 +156,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor parameters = callLValue.getParameters(); diff --git a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java index 5bb258765..9074331c1 100644 --- a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java +++ b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallParameters.java @@ -19,7 +19,7 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { } @Override - public StatementCall visitCallLValue(StatementCall origCall) { + public StatementCall visitCall(StatementCall origCall) { // Procedure strategy implemented is currently variable-based transfer of parameters/return values // Generate parameter passing assignments Procedure procedure = origCall.getProcedure(); diff --git a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java index 494fd0c3f..b00149f6d 100644 --- a/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java +++ b/src/dk/camelot64/kickc/icl/Pass1ProcedureCallsReturnValue.java @@ -17,7 +17,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor } @Override - public StatementCall visitCallLValue(StatementCall origCall) { + public StatementCall visitCall(StatementCall origCall) { // Procedure strategy implemented is currently variable-based transfer of parameters/return values // Generate return value assignment Procedure procedure = origCall.getProcedure(); diff --git a/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java b/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java index b8cf16d29..0576b1223 100644 --- a/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java +++ b/src/dk/camelot64/kickc/icl/Pass2ConstantAdditionElimination.java @@ -1,5 +1,8 @@ package dk.camelot64.kickc.icl; +import java.util.HashMap; +import java.util.Map; + /** * Compiler Pass eliminating several additions of constants by consolidating them to a single (compile time) constant c1+v+c2 => (c1+c2)+v * @@ -12,6 +15,8 @@ package dk.camelot64.kickc.icl; */ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { + private Map usages; + public Pass2ConstantAdditionElimination(ControlFlowGraph graph, Scope scope) { super(graph, scope); } @@ -24,6 +29,9 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { @Override public boolean optimize() { boolean optimized = false; + + this.usages = countVarUsages(); + // Examine all assigments - performing constant consolidation for (ControlFlowBlock block : getGraph().getAllBlocks()) { for (Statement statement : block.getStatements()) { @@ -116,6 +124,10 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { * @return The consolidated constant. Null if no sub-constants were found. */ private ConstantInteger consolidateSubConstants(Variable variable) { + if(usages.get(variable)>1) { + System.out.println("Multiple usages for variable. Not optimizing sub-constant "+variable); + return null; + } StatementAssignment assignment = getGraph().getAssignment(variable); if (assignment != null && assignment.getOperator() != null && "+".equals(assignment.getOperator().getOperator())) { if (assignment.getRValue1() instanceof ConstantInteger) { diff --git a/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java b/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java index fcd4ac67e..8c841f385 100644 --- a/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java +++ b/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java @@ -110,7 +110,7 @@ public abstract class Pass2SsaOptimization { } @Override - public Void visitCallLValue(StatementCall call) { + public Void visitCall(StatementCall call) { if(call.getParameters()!=null) { List newParams = new ArrayList<>(); for (RValue parameter : call.getParameters()) { @@ -309,4 +309,57 @@ public abstract class Pass2SsaOptimization { return usages; } + + protected Map countVarUsages() { + final HashMap usages = new HashMap<>(); + ControlFlowGraphBaseVisitor usageVisitor = new ControlFlowGraphBaseVisitor() { + private void addUsage(RValue rVal) { + if(rVal instanceof Variable) { + Variable var = (Variable) rVal; + Integer usage = usages.get(var); + if (usage == null) { + usage = 0; + } + usage = usage + 1; + usages.put(var, usage); + } else if(rVal instanceof PointerDereference) { + throw new RuntimeException("Unexpected pointer dereference!"); + } + } + + + @Override + public Object visitAssignment(StatementAssignment assignment) { + addUsage(assignment.getRValue1()); + addUsage(assignment.getRValue2()); + return null; + } + + @Override + public Object visitReturn(StatementReturn aReturn) { + addUsage(aReturn.getValue()); + return null; + } + + @Override + public Object visitCall(StatementCall call) { + if(call.getParameters()!=null) { + for (RValue param : call.getParameters()) { + addUsage(param); + } + } + return null; + } + + @Override + public Object visitPhi(StatementPhi phi) { + for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { + addUsage(previousSymbol.getRValue()); + } + return null; + } + }; + usageVisitor.visitGraph(getGraph()); + return usages; + } } diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index 81f4f5afb..2ccf13596 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -53,13 +53,16 @@ public class Pass3RegisterAllocation { //allocation.allocate(symbols.getVariable("$0"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("$2"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterALUByte()); - allocation.allocate(symbols.getVariable("$4"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(symbols.getVariable("$6"), new RegisterAllocation.RegisterALUByte()); - allocation.allocate(symbols.getVariable("$7"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("$1"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("$3"), new RegisterAllocation.RegisterALUByte()); + //allocation.allocate(symbols.getVariable("$4"), new RegisterAllocation.RegisterAByte()); + //allocation.allocate(symbols.getVariable("$6"), new RegisterAllocation.RegisterALUByte()); + //allocation.allocate(symbols.getVariable("$7"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("inc::a#2"), new RegisterAllocation.RegisterAByte()); //allocation.allocate(symbols.getVariable("bv#0"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("sum::b#0"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("inc::b#1"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("a#0"), new RegisterAllocation.RegisterAByte()); symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index 5f7da3dbf..5c9942634 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -64,7 +64,7 @@ public class Main { List optimizations = new ArrayList<>(); optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope)); optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope)); - //optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope)); + optimizations.add(new Pass2ConstantAdditionElimination(controlFlowGraph, programScope)); optimizations.add(new Pass2AliasElimination(controlFlowGraph, programScope)); optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, programScope)); optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, programScope)); diff --git a/src/dk/camelot64/kickc/test/callsum.kc b/src/dk/camelot64/kickc/test/callsum.kc index 5263ec3f9..058b48051 100644 --- a/src/dk/camelot64/kickc/test/callsum.kc +++ b/src/dk/camelot64/kickc/test/callsum.kc @@ -1,6 +1,6 @@ byte a = 12; byte s = sum(5,a); -a = a+s; +a = a+s+4; a = sum(s, a); byte sum(byte b1, byte b2) {