mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-09 04:25:12 +00:00
Implemented conditional simplification optimization
This commit is contained in:
@@ -26,7 +26,11 @@ public class AsmFragment {
|
|||||||
this.bindings = new HashMap<>();
|
this.bindings = new HashMap<>();
|
||||||
this.symbols = symbols;
|
this.symbols = symbols;
|
||||||
StringBuilder signature = new StringBuilder();
|
StringBuilder signature = new StringBuilder();
|
||||||
signature.append(bind(conditionalJump.getCondition()));
|
if(conditionalJump.getRValue1()!=null) {
|
||||||
|
signature.append(bind(conditionalJump.getRValue1()));
|
||||||
|
signature.append(conditionalJump.getOperator().getOperator());
|
||||||
|
}
|
||||||
|
signature.append(bind(conditionalJump.getRValue2()));
|
||||||
signature.append("?");
|
signature.append("?");
|
||||||
signature.append(bind(conditionalJump.getDestination()));
|
signature.append(bind(conditionalJump.getDestination()));
|
||||||
setSignature(signature.toString());
|
setSignature(signature.toString());
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiler Pass simplifying conditional jumps that are simple comparisons
|
||||||
|
*/
|
||||||
|
public class Pass2ConditionalJumpSimplification extends Pass2Optimization {
|
||||||
|
|
||||||
|
private Map<Variable, List<Statement>> allUsages;
|
||||||
|
|
||||||
|
public Pass2ConditionalJumpSimplification(ControlFlowGraph graph, SymbolTable symbolTable) {
|
||||||
|
super(graph, symbolTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eliminate alias assignments replacing them with the aliased variable.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean optimize() {
|
||||||
|
final Map<LValue, StatementAssignment> assignments = getAllAssignments();
|
||||||
|
final Map<RValue, List<Statement>> usages = getAllUsages();
|
||||||
|
final List<Variable> simpleConditionVars = getSimpleConditions(assignments, usages);
|
||||||
|
removeAssignments(simpleConditionVars);
|
||||||
|
deleteSymbols(simpleConditionVars);
|
||||||
|
return (simpleConditionVars.size()>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Variable> getSimpleConditions(final Map<LValue, StatementAssignment> assignments, final Map<RValue, List<Statement>> usages) {
|
||||||
|
|
||||||
|
final List<Variable> simpleConditionVars = new ArrayList<>();
|
||||||
|
|
||||||
|
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||||
|
if(conditionalJump.getRValue1()==null && conditionalJump.getOperator()==null) {
|
||||||
|
RValue conditionRValue = conditionalJump.getRValue2();
|
||||||
|
if(conditionRValue instanceof Variable && usages.get(conditionRValue).size()==1) {
|
||||||
|
Variable conditionVar = (Variable) conditionRValue;
|
||||||
|
StatementAssignment conditionAssignment = assignments.get(conditionVar);
|
||||||
|
if(conditionAssignment.getOperator()!=null) {
|
||||||
|
switch (conditionAssignment.getOperator().getOperator()) {
|
||||||
|
case "==":
|
||||||
|
case "<>":
|
||||||
|
case "!=":
|
||||||
|
case "<":
|
||||||
|
case ">":
|
||||||
|
case "<=":
|
||||||
|
case "=<":
|
||||||
|
case ">=":
|
||||||
|
case "=>":
|
||||||
|
conditionalJump.setRValue1(conditionAssignment.getRValue1());
|
||||||
|
conditionalJump.setOperator(conditionAssignment.getOperator());
|
||||||
|
conditionalJump.setRValue2(conditionAssignment.getRValue2());
|
||||||
|
simpleConditionVars.add(conditionVar);
|
||||||
|
System.out.println("Simple Condition " + conditionVar + " " + conditionalJump);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
visitor.visitGraph(getGraph());
|
||||||
|
return simpleConditionVars;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,8 +1,6 @@
|
|||||||
package dk.camelot64.kickc.icl;
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimization performed during Compiler Pass 2.
|
* Optimization performed during Compiler Pass 2.
|
||||||
@@ -66,8 +64,11 @@ public abstract class Pass2Optimization {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||||
if(getAlias(aliases, conditionalJump.getCondition())!=null) {
|
if(getAlias(aliases, conditionalJump.getRValue1())!=null) {
|
||||||
conditionalJump.setCondition(getAlias(aliases, conditionalJump.getCondition()));
|
conditionalJump.setRValue1(getAlias(aliases, conditionalJump.getRValue1()));
|
||||||
|
}
|
||||||
|
if(getAlias(aliases, conditionalJump.getRValue2())!=null) {
|
||||||
|
conditionalJump.setRValue2(getAlias(aliases, conditionalJump.getRValue2()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -196,5 +197,59 @@ public abstract class Pass2Optimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<LValue, StatementAssignment> getAllAssignments() {
|
||||||
|
final HashMap<LValue, StatementAssignment> assignments = new HashMap<>();
|
||||||
|
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitAssignment(StatementAssignment assignment) {
|
||||||
|
assignments.put(assignment.getLValue(), assignment);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
visitor.visitGraph(getGraph());
|
||||||
|
return assignments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<RValue, List<Statement>> getAllUsages() {
|
||||||
|
final HashMap<RValue, List<Statement>> usages = new HashMap<>();
|
||||||
|
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void visitAssignment(StatementAssignment assignment) {
|
||||||
|
addUsage(assignment.getRValue1(), assignment);
|
||||||
|
addUsage(assignment.getRValue2(), assignment);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||||
|
addUsage(conditionalJump.getRValue1(), conditionalJump);
|
||||||
|
addUsage(conditionalJump.getRValue2(), conditionalJump);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitPhi(StatementPhi phi) {
|
||||||
|
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||||
|
addUsage(previousSymbol.getRValue(), phi);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addUsage(RValue rValue, Statement statement) {
|
||||||
|
if (rValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Statement> use = usages.get(rValue);
|
||||||
|
if (use == null) {
|
||||||
|
use = new ArrayList<>();
|
||||||
|
usages.put(rValue, use);
|
||||||
|
}
|
||||||
|
use.add(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
visitor.visitGraph(getGraph());
|
||||||
|
|
||||||
|
return usages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,5 +25,4 @@ public class Pass3RegisterAllocation {
|
|||||||
symbols.setAllocation(allocation);
|
symbols.setAllocation(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,35 +5,75 @@ package dk.camelot64.kickc.icl;
|
|||||||
* Intermediate form used for compiler optimization.
|
* Intermediate form used for compiler optimization.
|
||||||
* <br>
|
* <br>
|
||||||
* <i> if ( Y<sub>j</sub> ) goto XX </i>
|
* <i> if ( Y<sub>j</sub> ) goto XX </i>
|
||||||
|
* <br>
|
||||||
|
* The condition may be a single boolean variable, or a comparison between two variables (==, <>, <, >, <=, >= )
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class StatementConditionalJump implements Statement {
|
public class StatementConditionalJump implements Statement {
|
||||||
|
|
||||||
private RValue condition;
|
private RValue rValue1;
|
||||||
|
private Operator operator;
|
||||||
|
private RValue rValue2;
|
||||||
private Label destination;
|
private Label destination;
|
||||||
|
|
||||||
public StatementConditionalJump(RValue condition, Label destination) {
|
public StatementConditionalJump(RValue condition, Label destination) {
|
||||||
this.condition = condition;
|
this.rValue1 = null;
|
||||||
|
this.operator = null;
|
||||||
|
this.rValue2 = condition;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RValue getCondition() {
|
public StatementConditionalJump(RValue rValue1, Operator operator, RValue rValue2, Label destination) {
|
||||||
return condition;
|
this.rValue1 = rValue1;
|
||||||
|
this.operator = operator;
|
||||||
|
this.rValue2 = rValue2;
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RValue getRValue1() {
|
||||||
|
return rValue1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RValue getRValue2() {
|
||||||
|
return rValue2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Label getDestination() {
|
public Label getDestination() {
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setRValue1(RValue rValue1) {
|
||||||
public String toString() {
|
this.rValue1 = rValue1;
|
||||||
return "if("+condition+") goto "+destination.getName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCondition(RValue condition) {
|
public void setOperator(Operator operator) {
|
||||||
this.condition = condition;
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRValue2(RValue rValue2) {
|
||||||
|
this.rValue2 = rValue2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestination(Label destination) {
|
public void setDestination(Label destination) {
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
out.append("if(");
|
||||||
|
if(rValue1!=null) {
|
||||||
|
out.append(rValue1);
|
||||||
|
out.append(operator.getOperator());
|
||||||
|
}
|
||||||
|
out.append(rValue2);
|
||||||
|
out.append(") goto ");
|
||||||
|
out.append(destination.getName());
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
src/dk/camelot64/kickc/icl/asm/zpby1<=coby1?la1.asm
Normal file
4
src/dk/camelot64/kickc/icl/asm/zpby1<=coby1?la1.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lda {zpby1}
|
||||||
|
cmp #{coby1}
|
||||||
|
bcc {la1}
|
||||||
|
beq {la1}
|
@@ -42,6 +42,7 @@ public class Main {
|
|||||||
optimizations.add(new Pass2AliasElimination(controlFlowGraph, symbolTable));
|
optimizations.add(new Pass2AliasElimination(controlFlowGraph, symbolTable));
|
||||||
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, symbolTable));
|
optimizations.add(new Pass2RedundantPhiElimination(controlFlowGraph, symbolTable));
|
||||||
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, symbolTable));
|
optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, symbolTable));
|
||||||
|
optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, symbolTable));
|
||||||
|
|
||||||
boolean optimized = true;
|
boolean optimized = true;
|
||||||
while (optimized) {
|
while (optimized) {
|
||||||
|
@@ -2,7 +2,7 @@ byte n1 = 0;
|
|||||||
byte n2 = 1;
|
byte n2 = 1;
|
||||||
byte i = 0;
|
byte i = 0;
|
||||||
byte fib = 0;
|
byte fib = 0;
|
||||||
while(i<=10) {
|
while(i<=11) {
|
||||||
fib = n1 + n2;
|
fib = n1 + n2;
|
||||||
n1 = n2;
|
n1 = n2;
|
||||||
n2 = fib;
|
n2 = fib;
|
||||||
|
Reference in New Issue
Block a user