mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Refactored phi to use blocks instead of individual statements
This commit is contained in:
parent
122cef4e30
commit
300bb644b9
@ -138,7 +138,7 @@ public class AsmFragment {
|
||||
LabelRef destination = conditionalJump.getDestination();
|
||||
ControlFlowBlock destinationBlock = graph.getBlock(destination);
|
||||
String destinationLabel = destination.getFullName();
|
||||
if (destinationBlock.hasPhiStatements()) {
|
||||
if (destinationBlock.hasPhiBlock()) {
|
||||
destinationLabel = (destinationBlock.getLabel().getLocalName() + "_from_" + block.getLabel().getLocalName()).replace('@', 'B').replace(':','_');
|
||||
}
|
||||
Symbol destSymbol = symbols.getSymbol(destination);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -78,10 +79,6 @@ public class ControlFlowBlock {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public void addPhiStatement(VariableVersion newVersion) {
|
||||
statements.add(0, new StatementPhi(newVersion.getRef()));
|
||||
}
|
||||
|
||||
public String getAsTypedString(ControlFlowGraph graph, ProgramScope scope) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append(label.getFullName() + ":" );
|
||||
@ -134,15 +131,6 @@ public class ControlFlowBlock {
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public boolean hasPhiStatements() {
|
||||
if(statements.size()>0) {
|
||||
if(statements.get(0) instanceof StatementPhi) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -168,4 +156,32 @@ public class ControlFlowBlock {
|
||||
result = 31 * result + (callSuccessor != null ? callSuccessor.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the phi block for the block. If the phi block has not yet been created it is created.
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
public StatementPhiBlock getPhiBlock() {
|
||||
StatementPhiBlock phiBlock = null;
|
||||
if(statements.size()>0 && statements.get(0) instanceof StatementPhiBlock) {
|
||||
phiBlock = (StatementPhiBlock) statements.get(0);
|
||||
}
|
||||
if(phiBlock==null) {
|
||||
phiBlock = new StatementPhiBlock();
|
||||
statements.add(0, phiBlock);
|
||||
}
|
||||
return phiBlock;
|
||||
}
|
||||
|
||||
public boolean hasPhiBlock() {
|
||||
if(statements.size()>0) {
|
||||
if(statements.get(0) instanceof StatementPhiBlock) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -29,10 +29,10 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return visitJump((StatementJump) statement);
|
||||
} else if(statement instanceof StatementLabel) {
|
||||
return visitJumpTarget((StatementLabel) statement);
|
||||
} else if(statement instanceof StatementPhi) {
|
||||
return visitPhi((StatementPhi) statement);
|
||||
} else if(statement instanceof StatementCall) {
|
||||
return visitCall((StatementCall) statement);
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
return visitPhiBlock((StatementPhiBlock) statement);
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
return visitReturn((StatementReturn) statement);
|
||||
} else if(statement instanceof StatementProcedureBegin) {
|
||||
@ -72,7 +72,7 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitPhi(StatementPhi phi) {
|
||||
public T visitPhiBlock(StatementPhiBlock phi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -114,13 +114,14 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatementPhi visitPhi(StatementPhi phi) {
|
||||
VariableRef lValue = phi.getlValue();
|
||||
StatementPhi copyPhi = new StatementPhi(lValue);
|
||||
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
|
||||
RValue rValue = origPreviousVersion.getrValue();
|
||||
LabelRef block = origPreviousVersion.getBlock();
|
||||
copyPhi.addPreviousVersion(block, rValue);
|
||||
public StatementPhiBlock visitPhiBlock(StatementPhiBlock phi) {
|
||||
StatementPhiBlock copyPhi = new StatementPhiBlock();
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
VariableRef variable = phiVariable.getVariable();
|
||||
StatementPhiBlock.PhiVariable copyVar = copyPhi.addPhiVariable(variable);
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
copyVar.setrValue(phiRValue.getPredecessor(), phiRValue.getrValue());
|
||||
}
|
||||
}
|
||||
return copyPhi;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = StatementAssignment.class, name = "assign"),
|
||||
@JsonSubTypes.Type(value = StatementPhi.class, name = "phi"),
|
||||
@JsonSubTypes.Type(value = StatementPhiBlock.class, name = "phiblock"),
|
||||
@JsonSubTypes.Type(value = StatementConditionalJump.class, name = "cond"),
|
||||
@JsonSubTypes.Type(value = StatementJump.class, name = "jump"),
|
||||
@JsonSubTypes.Type(value = StatementLabel.class, name = "label"),
|
||||
|
@ -1,155 +0,0 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Single Static Assignment Form Phi Statement.
|
||||
* Selects appropriate value of a variable based on the actual control flow.
|
||||
* <br>
|
||||
* <i> X<sub>i</sub> := phi(X<sub>j</sub>, X<sub>k</sub>, ...) </i>
|
||||
*/
|
||||
public class StatementPhi implements StatementLValue {
|
||||
|
||||
/** The versioned variable being assigned a value by the statement. */
|
||||
private VariableRef lValue;
|
||||
|
||||
/** The previous version of the rValue from predecessor control blocks. */
|
||||
private List<PreviousSymbol> previousVersions;
|
||||
|
||||
public StatementPhi(VariableRef lValue) {
|
||||
this.lValue = lValue;
|
||||
this.previousVersions = new ArrayList<>();
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
StatementPhi(
|
||||
@JsonProperty("lValue") VariableRef lValue,
|
||||
@JsonProperty("previousVersions") List<PreviousSymbol> previousVersions) {
|
||||
this.lValue = lValue;
|
||||
this.previousVersions = previousVersions;
|
||||
}
|
||||
|
||||
public PreviousSymbol getPreviousVersion(int i) {
|
||||
return previousVersions.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* A previous version of the rValue that the phi function might take its value from.
|
||||
* Which value is chosen depends on which block transition was made.
|
||||
*/
|
||||
public static class PreviousSymbol {
|
||||
private LabelRef block;
|
||||
private RValue rValue;
|
||||
|
||||
@JsonCreator
|
||||
public PreviousSymbol(
|
||||
@JsonProperty("block") LabelRef block,
|
||||
@JsonProperty("rValue") RValue rValue) {
|
||||
this.block = block;
|
||||
this.rValue = rValue;
|
||||
}
|
||||
|
||||
public LabelRef getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public RValue getrValue() {
|
||||
return rValue;
|
||||
}
|
||||
|
||||
public void setrValue(RValue RValue) {
|
||||
this.rValue = RValue;
|
||||
}
|
||||
|
||||
public void setBlock(LabelRef block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PreviousSymbol that = (PreviousSymbol) o;
|
||||
|
||||
if (!block.equals(that.block)) return false;
|
||||
return rValue.equals(that.rValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = block.hashCode();
|
||||
result = 31 * result + rValue.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public VariableRef getlValue() {
|
||||
return lValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setlValue(LValue lValue) {
|
||||
if(!(lValue instanceof VariableRef)) {
|
||||
throw new RuntimeException("Error modifying phi-statement lValue "+this.lValue+". Attempt to set to non-versioned variable "+lValue);
|
||||
}
|
||||
this.lValue = (VariableRef) lValue;
|
||||
}
|
||||
|
||||
public void addPreviousVersion(LabelRef block, RValue rValue) {
|
||||
previousVersions.add(new PreviousSymbol(block, rValue));
|
||||
}
|
||||
|
||||
public List<PreviousSymbol> getPreviousVersions() {
|
||||
return previousVersions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsTypedString(ProgramScope scope) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(lValue.getAsTypedString(scope) + " ← " + "phi(");
|
||||
for (PreviousSymbol previousSymbol : previousVersions) {
|
||||
out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getrValue().getAsTypedString(scope));
|
||||
}
|
||||
out.append(" )");
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(lValue + " ← " + "phi(");
|
||||
for (PreviousSymbol previousSymbol : previousVersions) {
|
||||
out.append(" "+previousSymbol.getBlock().getFullName()+"/"+previousSymbol.getrValue());
|
||||
}
|
||||
out.append(" )");
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
StatementPhi that = (StatementPhi) o;
|
||||
|
||||
if (!lValue.equals(that.lValue)) return false;
|
||||
return previousVersions.equals(that.previousVersions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = lValue.hashCode();
|
||||
result = 31 * result + previousVersions.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
313
src/dk/camelot64/kickc/icl/StatementPhiBlock.java
Normal file
313
src/dk/camelot64/kickc/icl/StatementPhiBlock.java
Normal file
@ -0,0 +1,313 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The Phi Block initializing the necessary SSA-variables of a predecessor.
|
||||
* The phi predecessor initializes a number of variables with different values depending on which predecessor control flow enters from.
|
||||
*/
|
||||
public class StatementPhiBlock implements Statement {
|
||||
|
||||
/**
|
||||
* Maps each phi-varible of the predecessor to a map from a predecessor predecessor to the rvalue of the variable.
|
||||
*/
|
||||
private List<PhiVariable> phiVariables;
|
||||
|
||||
@JsonCreator
|
||||
public StatementPhiBlock(
|
||||
@JsonProperty("phiVariables") List<PhiVariable> phiVariables) {
|
||||
this.phiVariables = phiVariables;
|
||||
}
|
||||
|
||||
public StatementPhiBlock() {
|
||||
this.phiVariables = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ordered predecessor blocks where control can enter the predecessor.
|
||||
*
|
||||
* @return the predecessor blocks
|
||||
*/
|
||||
//public List<LabelRef> getPredecessors() {
|
||||
// return predecessors;
|
||||
//}
|
||||
|
||||
|
||||
/**
|
||||
* Get the variables defined by the phi predecessor.
|
||||
*
|
||||
* @return The variables defined
|
||||
*/
|
||||
@JsonIgnore
|
||||
public List<VariableRef> getVariables() {
|
||||
ArrayList<VariableRef> vars = new ArrayList<>();
|
||||
for (PhiVariable phiVariable : phiVariables) {
|
||||
vars.add(phiVariable.getVariable());
|
||||
}
|
||||
return vars;
|
||||
|
||||
}
|
||||
|
||||
public PhiVariable getPhiVariable(VariableRef variable) {
|
||||
for (PhiVariable phiVariable : phiVariables) {
|
||||
if (phiVariable.getVariable().equals(variable)) {
|
||||
return phiVariable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public RValue getrValue(LabelRef predecessor, VariableRef variable) {
|
||||
return getPhiVariable(variable).getrValue(predecessor);
|
||||
}
|
||||
|
||||
public PhiRValue getPhirValue(LabelRef predecessor, VariableRef variable) {
|
||||
return getPhiVariable(variable).getPhirValue(predecessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsTypedString(ProgramScope scope) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
List<PhiVariable> variables = new ArrayList<>(phiVariables);
|
||||
Collections.reverse(variables);
|
||||
for (PhiVariable phiVariable : variables) {
|
||||
s.append(phiVariable.getVariable().getAsTypedString(scope));
|
||||
s.append(" ← phi(");
|
||||
for (PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
s.append(" ");
|
||||
s.append(phiRValue.getPredecessor().getAsString());
|
||||
s.append("/");
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
s.append(rValue==null?"null":rValue.getAsTypedString(scope));
|
||||
}
|
||||
s.append(" )\n ");
|
||||
}
|
||||
if(s.length()>0) {
|
||||
return s.toString().substring(0, s.length() - 3);
|
||||
} else {
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
List<PhiVariable> variables = new ArrayList<>(phiVariables);
|
||||
Collections.reverse(variables);
|
||||
for (PhiVariable phiVariable : variables) {
|
||||
s.append(phiVariable.getVariable().getAsString());
|
||||
s.append(" ← phi(");
|
||||
for (PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
s.append(" ");
|
||||
s.append(phiRValue.getPredecessor().getAsString());
|
||||
s.append("/");
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
s.append(rValue==null?"null":rValue.getAsString());
|
||||
}
|
||||
s.append(" )\n ");
|
||||
}
|
||||
if(s.length()>0) {
|
||||
return s.toString().substring(0, s.length() - 3);
|
||||
} else {
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public PhiVariable addPhiVariable(VariableRef variable) {
|
||||
PhiVariable phiVariable = new PhiVariable(variable);
|
||||
this.phiVariables.add(phiVariable);
|
||||
return phiVariable;
|
||||
}
|
||||
|
||||
public List<PhiVariable> getPhiVariables() {
|
||||
return phiVariables;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
StatementPhiBlock phiBlock = (StatementPhiBlock) o;
|
||||
|
||||
return phiVariables != null ? phiVariables.equals(phiBlock.phiVariables) : phiBlock.phiVariables == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return phiVariables != null ? phiVariables.hashCode() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A variable being defined as part of a phi predecessor.
|
||||
*/
|
||||
public static class PhiVariable {
|
||||
|
||||
/**
|
||||
* The variable being defined.
|
||||
*/
|
||||
private VariableRef variable;
|
||||
|
||||
/**
|
||||
* The Rvalues assigned to the variable when entering from different blocks.
|
||||
*/
|
||||
private List<PhiRValue> values;
|
||||
|
||||
public PhiVariable(VariableRef variable) {
|
||||
this.variable = variable;
|
||||
this.values = new ArrayList<>();
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public PhiVariable(
|
||||
@JsonProperty("variable") VariableRef variable,
|
||||
@JsonProperty("values") List<PhiRValue> values) {
|
||||
this.variable = variable;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public PhiVariable() {
|
||||
}
|
||||
|
||||
public VariableRef getVariable() {
|
||||
return variable;
|
||||
}
|
||||
|
||||
public void setVariable(VariableRef variable) {
|
||||
this.variable = variable;
|
||||
}
|
||||
|
||||
public void setValues(List<PhiRValue> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public List<PhiRValue> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
public RValue getrValue(LabelRef predecessor) {
|
||||
for (PhiRValue phiRValue : values) {
|
||||
if (phiRValue.getPredecessor().equals(predecessor)) {
|
||||
return phiRValue.getrValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the phi rvalue of the phi variable for a specific predecessor block.
|
||||
* Creates the phi-rValue if it does not already exist.
|
||||
*
|
||||
* @param predecessor The predecessor block
|
||||
* @return The rValue assigned to the phi variable when entering from the passed block.
|
||||
*/
|
||||
public PhiRValue getPhirValue(LabelRef predecessor) {
|
||||
for (PhiRValue phiRValue : values) {
|
||||
if (phiRValue.getPredecessor().equals(predecessor)) {
|
||||
return phiRValue;
|
||||
}
|
||||
}
|
||||
// Not found - create and return
|
||||
PhiRValue phirValue = new PhiRValue(predecessor);
|
||||
this.values.add(phirValue);
|
||||
return phirValue;
|
||||
}
|
||||
|
||||
public void setrValue(LabelRef predecessor, RValue rValue) {
|
||||
getPhirValue(predecessor).setrValue(rValue);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isEmpty() {
|
||||
return this.values.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PhiVariable that = (PhiVariable) o;
|
||||
|
||||
if (!variable.equals(that.variable)) return false;
|
||||
return values.equals(that.values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = variable.hashCode();
|
||||
result = 31 * result + values.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value assigned to a phi variable when entering the predecessor from a specific predecessor block.
|
||||
*/
|
||||
public static class PhiRValue {
|
||||
|
||||
/**
|
||||
* The predecessor predecessor
|
||||
*/
|
||||
private LabelRef predecessor;
|
||||
|
||||
/**
|
||||
* The value to assign to the phi-variable when entering from the predecessor block
|
||||
*/
|
||||
private RValue rValue;
|
||||
|
||||
public PhiRValue(LabelRef predecessor) {
|
||||
this.predecessor = predecessor;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public PhiRValue(
|
||||
@JsonProperty("predecessor") LabelRef predecessor,
|
||||
@JsonProperty("rValue") RValue rValue) {
|
||||
this.predecessor = predecessor;
|
||||
this.rValue = rValue;
|
||||
}
|
||||
|
||||
public LabelRef getPredecessor() {
|
||||
return predecessor;
|
||||
}
|
||||
|
||||
public RValue getrValue() {
|
||||
return rValue;
|
||||
}
|
||||
|
||||
public void setrValue(RValue rValue) {
|
||||
this.rValue = rValue;
|
||||
}
|
||||
|
||||
public void setPredecessor(LabelRef predecessor) {
|
||||
this.predecessor = predecessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
PhiRValue phiRValue = (PhiRValue) o;
|
||||
|
||||
if (!predecessor.equals(phiRValue.predecessor)) return false;
|
||||
return rValue != null ? rValue.equals(phiRValue.rValue) : phiRValue.rValue == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = predecessor.hashCode();
|
||||
result = 31 * result + (rValue != null ? rValue.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -30,6 +30,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
|
||||
do {
|
||||
log.append("Completing Phi functions...");
|
||||
done = completePhiFunctions();
|
||||
//log.append(this.controlFlowGraph.getAsTypedString(symbols));
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
@ -124,7 +125,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
|
||||
}
|
||||
// Add new Phi functions to block
|
||||
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
|
||||
block.addPhiStatement(blockNewPhis.get(symbol));
|
||||
block.getPhiBlock().addPhiVariable(blockNewPhis.get(symbol).getRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,34 +175,37 @@ public class Pass1GenerateSingleStaticAssignmentForm {
|
||||
Map<LabelRef, Map<VariableUnversioned, VariableVersion>> symbolMap = buildSymbolMap();
|
||||
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementPhi) {
|
||||
StatementPhi phi = (StatementPhi) statement;
|
||||
if (phi.getPreviousVersions().isEmpty()) {
|
||||
VariableRef phiLValVarRef = phi.getlValue();
|
||||
VariableVersion versioned = (VariableVersion) symbols.getVariable(phiLValVarRef);
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) {
|
||||
LabelRef predecessorLabel = predecessor.getLabel();
|
||||
Map<VariableUnversioned, VariableVersion> predecessorMap = symbolMap.get(predecessorLabel);
|
||||
VariableVersion previousSymbol = null;
|
||||
if (predecessorMap != null) {
|
||||
previousSymbol = predecessorMap.get(unversioned);
|
||||
}
|
||||
if (previousSymbol == null) {
|
||||
// No previous symbol found in predecessor block. Look in new phi functions.
|
||||
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessorLabel);
|
||||
if (predecessorNewPhis == null) {
|
||||
predecessorNewPhis = new LinkedHashMap<>();
|
||||
newPhis.put(predecessorLabel, predecessorNewPhis);
|
||||
|
||||
if (statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
if(phiVariable.isEmpty()) {
|
||||
VariableRef phiLValVarRef = phiVariable.getVariable();
|
||||
VariableVersion versioned = (VariableVersion) symbols.getVariable(phiLValVarRef);
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) {
|
||||
LabelRef predecessorLabel = predecessor.getLabel();
|
||||
Map<VariableUnversioned, VariableVersion> predecessorMap = symbolMap.get(predecessorLabel);
|
||||
VariableVersion previousSymbol = null;
|
||||
if (predecessorMap != null) {
|
||||
previousSymbol = predecessorMap.get(unversioned);
|
||||
}
|
||||
previousSymbol = predecessorNewPhis.get(unversioned);
|
||||
if (previousSymbol == null) {
|
||||
// No previous symbol found in predecessor block. Add a new phi function to the predecessor.
|
||||
previousSymbol = unversioned.createVersion();
|
||||
predecessorNewPhis.put(unversioned, previousSymbol);
|
||||
// No previous symbol found in predecessor block. Look in new phi functions.
|
||||
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessorLabel);
|
||||
if (predecessorNewPhis == null) {
|
||||
predecessorNewPhis = new LinkedHashMap<>();
|
||||
newPhis.put(predecessorLabel, predecessorNewPhis);
|
||||
}
|
||||
previousSymbol = predecessorNewPhis.get(unversioned);
|
||||
if (previousSymbol == null) {
|
||||
// No previous symbol found in predecessor block. Add a new phi function to the predecessor.
|
||||
previousSymbol = unversioned.createVersion();
|
||||
predecessorNewPhis.put(unversioned, previousSymbol);
|
||||
}
|
||||
}
|
||||
phiVariable.setrValue(predecessorLabel, previousSymbol.getRef());
|
||||
}
|
||||
phi.addPreviousVersion(predecessorLabel, previousSymbol.getRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,7 +216,8 @@ public class Pass1GenerateSingleStaticAssignmentForm {
|
||||
Map<VariableUnversioned, VariableVersion> blockNewPhis = newPhis.get(block.getLabel());
|
||||
if (blockNewPhis != null) {
|
||||
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
|
||||
block.addPhiStatement(blockNewPhis.get(symbol));
|
||||
StatementPhiBlock phiBlock = block.getPhiBlock();
|
||||
phiBlock.addPhiVariable(blockNewPhis.get(symbol).getRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,23 +234,32 @@ public class Pass1GenerateSingleStaticAssignmentForm {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementLValue) {
|
||||
StatementLValue assignment = (StatementLValue) statement;
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable lValueVar = symbols.getVariable((VariableRef) lValue);
|
||||
if (lValueVar instanceof VariableVersion) {
|
||||
VariableVersion versioned = (VariableVersion) lValueVar;
|
||||
LabelRef label = block.getLabel();
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
|
||||
if (blockMap == null) {
|
||||
blockMap = new LinkedHashMap<>();
|
||||
symbolMap.put(label, blockMap);
|
||||
}
|
||||
blockMap.put(unversioned, versioned);
|
||||
} }
|
||||
addSymbolToMap(symbolMap, block, assignment.getlValue());
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
addSymbolToMap(symbolMap, block, phiVariable.getVariable());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return symbolMap;
|
||||
}
|
||||
|
||||
private void addSymbolToMap(Map<LabelRef, Map<VariableUnversioned, VariableVersion>> symbolMap, ControlFlowBlock block, LValue lValue) {
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable lValueVar = symbols.getVariable((VariableRef) lValue);
|
||||
if (lValueVar instanceof VariableVersion) {
|
||||
VariableVersion versioned = (VariableVersion) lValueVar;
|
||||
LabelRef label = block.getLabel();
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
|
||||
if (blockMap == null) {
|
||||
blockMap = new LinkedHashMap<>();
|
||||
symbolMap.put(label, blockMap);
|
||||
}
|
||||
blockMap.put(unversioned, versioned);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
import javafx.scene.input.InputMethodTextRun;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -54,14 +55,21 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} else if (statement instanceof StatementPhi) {
|
||||
StatementPhi phi = (StatementPhi) statement;
|
||||
AliasSet aliasSet = aliases.findAliasSet(phi.getlValue());
|
||||
if (aliasSet != null) {
|
||||
if (phi.getPreviousVersions().size() == 1 && aliasSet.contains(phi.getPreviousVersion(0).getrValue())) {
|
||||
iterator.remove();
|
||||
} else if (statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
||||
Iterator<StatementPhiBlock.PhiVariable> variableIterator = phiBlock.getPhiVariables().iterator();
|
||||
while (variableIterator.hasNext()) {
|
||||
StatementPhiBlock.PhiVariable phiVariable = variableIterator.next();
|
||||
AliasSet aliasSet = aliases.findAliasSet(phiVariable.getVariable());
|
||||
if (aliasSet != null) {
|
||||
if (phiVariable.getValues().size() == 1 && aliasSet.contains(phiVariable.getValues().get(0).getrValue())) {
|
||||
variableIterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(phiBlock.getPhiVariables().size()==0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -222,32 +230,28 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
// Remove all candidates that are used after assignment in phi blocks
|
||||
private void cleanupCandidates(Aliases candidates) {
|
||||
for (final AliasSet aliasSet : candidates.aliases) {
|
||||
final Boolean[] lMatch = {false};
|
||||
ControlFlowGraphBaseVisitor<Void> candidateEliminator = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
@Override
|
||||
public Void visitBlock(ControlFlowBlock block) {
|
||||
lMatch[0] = false;
|
||||
return super.visitBlock(block);
|
||||
}
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
if(lMatch[0]) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
RValue phiRValue = previousSymbol.getrValue();
|
||||
if (aliasSet.contains(phiRValue)) {
|
||||
log.append("Alias candidate removed " + phiRValue.getAsTypedString(getSymbols()));
|
||||
aliasSet.remove(phiRValue);
|
||||
break;
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
if(block.hasPhiBlock()) {
|
||||
StatementPhiBlock phi = block.getPhiBlock();
|
||||
boolean lMatch = false;
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if(lMatch) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
if (aliasSet.contains(rValue)) {
|
||||
log.append("Alias candidate removed " + rValue.getAsTypedString(getSymbols()));
|
||||
aliasSet.remove(rValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aliasSet.contains(phiVariable.getVariable())) {
|
||||
lMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aliasSet.contains(phi.getlValue())) {
|
||||
lMatch[0] = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
candidateEliminator.visitGraph(getGraph());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,13 +277,15 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
if (phi.getPreviousVersions().size() == 1) {
|
||||
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
|
||||
if (previousSymbol.getrValue() instanceof VariableRef) {
|
||||
VariableRef variable = phi.getlValue();
|
||||
VariableRef alias = (VariableRef) previousSymbol.getrValue();
|
||||
aliases.add(variable, alias);
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if(phiVariable.getValues().size()==1) {
|
||||
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
|
||||
if (phiRValue.getrValue() instanceof VariableRef) {
|
||||
VariableRef variable = phiVariable.getVariable();
|
||||
VariableRef alias = (VariableRef) phiRValue.getrValue();
|
||||
aliases.add(variable, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -60,11 +60,13 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
assertBlock(previousSymbol.getBlock());
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
assertBlock(phiRValue.getPredecessor());
|
||||
}
|
||||
}
|
||||
return super.visitPhi(phi);
|
||||
return super.visitPhiBlock(phi);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,12 +153,14 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
addSymbol(phi.getlValue());
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
addSymbol(previousSymbol.getrValue());
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
addSymbol(phiVariable.getVariable());
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
addSymbol(phiRValue.getrValue());
|
||||
}
|
||||
}
|
||||
return super.visitPhi(phi);
|
||||
return super.visitPhiBlock(phi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,17 +68,21 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
if (phi.getPreviousVersions().size() == 1) {
|
||||
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
|
||||
if (previousSymbol.getrValue() instanceof Constant) {
|
||||
VariableRef variable = phi.getlValue();
|
||||
Constant constant = (Constant) previousSymbol.getrValue();
|
||||
constants.put(variable, constant);
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if(phiVariable.getValues().size()==1) {
|
||||
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
|
||||
if (phiRValue.getrValue() instanceof Constant) {
|
||||
VariableRef variable = phiVariable.getVariable();
|
||||
Constant constant = (Constant) phiRValue.getrValue();
|
||||
constants.put(variable, constant);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
visitor.visitGraph(getGraph());
|
||||
return constants;
|
||||
|
@ -42,20 +42,22 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
|
||||
// In all phi functions of a successor blocks make a copy of the phi assignment for each predecessor
|
||||
ControlFlowGraphBaseVisitor<Void> phiFixVisitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
if(previousSymbol.getBlock().equals(removeBlock.getLabel())) {
|
||||
// Found a phi function referencing the remove block - add copies for each predecessor
|
||||
RValue previousRValue = previousSymbol.getrValue();
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
if(previousSymbol!=null) {
|
||||
previousSymbol.setBlock(predecessor.getLabel());
|
||||
previousSymbol = null;
|
||||
} else {
|
||||
phi.addPreviousVersion(predecessor.getLabel(), previousRValue);
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(phiRValue.getPredecessor().equals(removeBlock.getLabel())) {
|
||||
// Found a phi function referencing the remove block - add copies for each predecessor
|
||||
RValue previousRValue = phiRValue.getrValue();
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
if(phiRValue!=null) {
|
||||
phiRValue.setPredecessor(predecessor.getLabel());
|
||||
phiRValue = null;
|
||||
} else {
|
||||
phiVariable.setrValue(predecessor.getLabel(), previousRValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -36,27 +36,31 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
|
||||
private Map<VariableRef, RValue> findRedundantPhis() {
|
||||
final Map<VariableRef, RValue> aliases = new LinkedHashMap<>();
|
||||
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
boolean found = true;
|
||||
RValue phiRValue = null;
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
if(phiRValue==null) {
|
||||
phiRValue = previousSymbol.getrValue();
|
||||
} else {
|
||||
if(!phiRValue.equals(previousSymbol.getrValue())) {
|
||||
found = false;
|
||||
break;
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
boolean found = true;
|
||||
RValue rValue = null;
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(rValue==null) {
|
||||
rValue = phiRValue.getrValue();
|
||||
} else {
|
||||
if(!rValue.equals(phiRValue.getrValue())) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(found) {
|
||||
VariableRef variable = phi.getlValue();
|
||||
if(phiRValue==null) {phiRValue = VOID;}
|
||||
aliases.put(variable, phiRValue);
|
||||
if(found) {
|
||||
VariableRef variable = phiVariable.getVariable();
|
||||
if(rValue==null) {rValue = VOID;}
|
||||
aliases.put(variable, rValue);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
visitor.visitGraph(getGraph());
|
||||
return aliases;
|
||||
|
@ -20,13 +20,16 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
|
||||
final Boolean[] optimized = {Boolean.FALSE};
|
||||
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
|
||||
StatementPhi.PreviousSymbol previousSymbol = iterator.next();
|
||||
if (previousSymbol.getrValue().equals(phi.getlValue())) {
|
||||
iterator.remove();
|
||||
optimized[0] = Boolean.TRUE;
|
||||
log.append("Self Phi Eliminated "+phi.getlValue().getAsTypedString(getSymbols()));
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
Iterator<StatementPhiBlock.PhiRValue> iterator = phiVariable.getValues().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
StatementPhiBlock.PhiRValue phiRValue = iterator.next();
|
||||
if (phiRValue.getrValue().equals(phiVariable.getVariable())) {
|
||||
iterator.remove();
|
||||
optimized[0] = Boolean.TRUE;
|
||||
log.append("Self Phi Eliminated "+phiVariable.getVariable().getAsTypedString(getSymbols()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -145,26 +145,31 @@ public abstract class Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
if (getAlias(aliases, phi.getlValue()) != null) {
|
||||
RValue alias = getAlias(aliases, phi.getlValue());
|
||||
if (alias instanceof LValue) {
|
||||
phi.setlValue((VariableRef) alias);
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if (getAlias(aliases, phiVariable.getVariable()) != null) {
|
||||
RValue alias = getAlias(aliases, phiVariable.getVariable());
|
||||
if (alias instanceof LValue) {
|
||||
phiVariable.setVariable((VariableRef) alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
|
||||
StatementPhi.PreviousSymbol previousSymbol = iterator.next();
|
||||
if (getAlias(aliases, previousSymbol.getrValue()) != null) {
|
||||
RValue alias = getAlias(aliases, previousSymbol.getrValue());
|
||||
if (VOID.equals(alias)) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
previousSymbol.setrValue(alias);
|
||||
List<StatementPhiBlock.PhiRValue> phirValues = phiVariable.getValues();
|
||||
Iterator<StatementPhiBlock.PhiRValue> it = phirValues.iterator();
|
||||
while (it.hasNext()) {
|
||||
StatementPhiBlock.PhiRValue phirValue = it.next();
|
||||
if (getAlias(aliases, phirValue.getrValue()) != null) {
|
||||
RValue alias = getAlias(aliases, phirValue.getrValue());
|
||||
if (VOID.equals(alias)) {
|
||||
it.remove();
|
||||
} else {
|
||||
phirValue.setrValue(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
visitor.visitGraph(graph);
|
||||
}
|
||||
@ -184,16 +189,6 @@ public abstract class Pass2SsaOptimization {
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all usages of a label in statements with another label.
|
||||
*
|
||||
* @param replacements Variables that have alias values.
|
||||
*/
|
||||
public void replaceLabels(final Map<LabelRef, LabelRef> replacements) {
|
||||
ControlFlowGraphBaseVisitor<Void> visitor = getLabelReplaceVisitor(replacements);
|
||||
visitor.visitGraph(graph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all usages of a label in statements with another label.
|
||||
*
|
||||
@ -208,33 +203,34 @@ public abstract class Pass2SsaOptimization {
|
||||
private ControlFlowGraphBaseVisitor<Void> getLabelReplaceVisitor(final Map<LabelRef, LabelRef> replacements) {
|
||||
return new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
||||
@Override
|
||||
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||
if (getReplacement(replacements, conditionalJump.getDestination()) != null) {
|
||||
conditionalJump.setDestination(getReplacement(replacements, conditionalJump.getDestination()));
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||
if (getReplacement(replacements, conditionalJump.getDestination()) != null) {
|
||||
conditionalJump.setDestination(getReplacement(replacements, conditionalJump.getDestination()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitJump(StatementJump jump) {
|
||||
if (getReplacement(replacements, jump.getDestination()) != null) {
|
||||
jump.setDestination(getReplacement(replacements, jump.getDestination()));
|
||||
}
|
||||
return null;
|
||||
@Override
|
||||
public Void visitJump(StatementJump jump) {
|
||||
if (getReplacement(replacements, jump.getDestination()) != null) {
|
||||
jump.setDestination(getReplacement(replacements, jump.getDestination()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
LabelRef replacement = getReplacement(replacements, previousSymbol.getBlock());
|
||||
if (replacement != null) {
|
||||
previousSymbol.setBlock(replacement);
|
||||
@Override
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if (getReplacement(replacements, phiRValue.getPredecessor()) != null) {
|
||||
phiRValue.setPredecessor(getReplacement(replacements, phiRValue.getPredecessor()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,9 +263,16 @@ public abstract class Pass2SsaOptimization {
|
||||
if (variables.contains(assignment.getlValue())) {
|
||||
iterator.remove();
|
||||
}
|
||||
} else if (statement instanceof StatementPhi) {
|
||||
StatementPhi phi = (StatementPhi) statement;
|
||||
if (variables.contains(phi.getlValue())) {
|
||||
} else if (statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock phiBlock = (StatementPhiBlock) statement;
|
||||
Iterator<StatementPhiBlock.PhiVariable> variableIterator = phiBlock.getPhiVariables().iterator();
|
||||
while (variableIterator.hasNext()) {
|
||||
StatementPhiBlock.PhiVariable phiVariable = variableIterator.next();
|
||||
if(variables.contains(phiVariable.getVariable())) {
|
||||
variableIterator.remove();
|
||||
}
|
||||
}
|
||||
if(phiBlock.getPhiVariables().size()==0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
@ -326,9 +329,11 @@ public abstract class Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhi(StatementPhi phi) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
addUsage(previousSymbol.getrValue(), phi);
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
addUsage(phiRValue.getrValue(), phi);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -393,12 +398,15 @@ public abstract class Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitPhi(StatementPhi phi) {
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
|
||||
addUsage(previousSymbol.getrValue());
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
addUsage(phiRValue.getrValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
usageVisitor.visitGraph(getGraph());
|
||||
return usages;
|
||||
|
@ -31,7 +31,7 @@ public class Pass3CodeGeneration {
|
||||
// Generate exit
|
||||
ControlFlowBlock defaultSuccessor = graph.getDefaultSuccessor(block);
|
||||
if (defaultSuccessor != null) {
|
||||
if (defaultSuccessor.hasPhiStatements()) {
|
||||
if (defaultSuccessor.hasPhiBlock()) {
|
||||
genBlockPhiTransition(asm, block, defaultSuccessor);
|
||||
}
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getFullName().replace('@', 'B').replace(':','_'));
|
||||
@ -44,7 +44,7 @@ public class Pass3CodeGeneration {
|
||||
Iterator<Statement> statementsIt = block.getStatements().iterator();
|
||||
while (statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if (!(statement instanceof StatementPhi)) {
|
||||
if (!(statement instanceof StatementPhiBlock)) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
LValue lValue = assignment.getlValue();
|
||||
@ -58,7 +58,7 @@ public class Pass3CodeGeneration {
|
||||
StatementAssignment assignmentAlu = assignment;
|
||||
statement = statementsIt.next();
|
||||
if (!(statement instanceof StatementAssignment)) {
|
||||
throw new RuntimeException("Error! ALU statement must be followed immidiately by assignment using the ALU. " + statement);
|
||||
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);
|
||||
@ -79,7 +79,7 @@ public class Pass3CodeGeneration {
|
||||
} else if (statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
ControlFlowBlock callSuccessor = graph.getCallSuccessor(block);
|
||||
if (callSuccessor != null && callSuccessor.hasPhiStatements()) {
|
||||
if (callSuccessor != null && callSuccessor.hasPhiBlock()) {
|
||||
genBlockPhiTransition(asm, block, callSuccessor);
|
||||
}
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName());
|
||||
@ -93,7 +93,7 @@ public class Pass3CodeGeneration {
|
||||
}
|
||||
|
||||
private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) {
|
||||
if (block.hasPhiStatements()) {
|
||||
if (block.hasPhiBlock()) {
|
||||
List<ControlFlowBlock> predecessors = new ArrayList<>(graph.getPredecessors(block));
|
||||
Collections.sort(predecessors, new Comparator<ControlFlowBlock>() {
|
||||
@Override
|
||||
@ -111,24 +111,24 @@ public class Pass3CodeGeneration {
|
||||
}
|
||||
|
||||
private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) {
|
||||
asm.addLabel((toBlock.getLabel().getFullName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B').replace(':','_'));
|
||||
for (Statement statement : toBlock.getStatements()) {
|
||||
if (!(statement instanceof StatementPhi)) {
|
||||
// No more phi statements to handle
|
||||
break;
|
||||
}
|
||||
StatementPhi phi = (StatementPhi) statement;
|
||||
List<StatementPhi.PreviousSymbol> previousVersions = new ArrayList<>(phi.getPreviousVersions());
|
||||
Collections.sort(previousVersions, new Comparator<StatementPhi.PreviousSymbol>() {
|
||||
@Override
|
||||
public int compare(StatementPhi.PreviousSymbol o1, StatementPhi.PreviousSymbol o2) {
|
||||
return o1.getBlock().getFullName().compareTo(o2.getBlock().getFullName());
|
||||
}
|
||||
});
|
||||
for (StatementPhi.PreviousSymbol previousSymbol : previousVersions) {
|
||||
if (previousSymbol.getBlock().equals(fromBlock.getLabel())) {
|
||||
genAsmMove(asm, phi.getlValue(), previousSymbol.getrValue());
|
||||
break;
|
||||
asm.addLabel((toBlock.getLabel().getFullName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B').replace(':', '_'));
|
||||
if (toBlock.hasPhiBlock()) {
|
||||
StatementPhiBlock phiBlock = toBlock.getPhiBlock();
|
||||
List<StatementPhiBlock.PhiVariable> phiVariables = new ArrayList<>(phiBlock.getPhiVariables());
|
||||
Collections.reverse(phiVariables);
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : phiVariables) {
|
||||
List<StatementPhiBlock.PhiRValue> phiRValues = phiVariable.getValues();
|
||||
Collections.sort(phiRValues, new Comparator<StatementPhiBlock.PhiRValue>() {
|
||||
@Override
|
||||
public int compare(StatementPhiBlock.PhiRValue o1, StatementPhiBlock.PhiRValue o2) {
|
||||
return o1.getPredecessor().getFullName().compareTo(o2.getPredecessor().getFullName());
|
||||
}
|
||||
});
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiRValues) {
|
||||
if (phiRValue.getPredecessor().equals(fromBlock.getLabel())) {
|
||||
genAsmMove(asm, phiVariable.getVariable(), phiRValue.getrValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,16 @@ public class TestCompilationOutput extends TestCase {
|
||||
tester.testFile("bresenham");
|
||||
}
|
||||
|
||||
public void testMinus() throws IOException, URISyntaxException {
|
||||
TestCompilationOutput tester = new TestCompilationOutput();
|
||||
tester.testFile("minus");
|
||||
}
|
||||
|
||||
public void testLoopMin() throws IOException, URISyntaxException {
|
||||
TestCompilationOutput tester = new TestCompilationOutput();
|
||||
tester.testFile("loopmin");
|
||||
}
|
||||
|
||||
public void testSumMin() throws IOException, URISyntaxException {
|
||||
TestCompilationOutput tester = new TestCompilationOutput();
|
||||
tester.testFile("summin");
|
||||
|
File diff suppressed because one or more lines are too long
8
src/dk/camelot64/kickc/test/loopmin.kc
Normal file
8
src/dk/camelot64/kickc/test/loopmin.kc
Normal file
@ -0,0 +1,8 @@
|
||||
byte i=10;
|
||||
byte s=0;
|
||||
do {
|
||||
if(i>5) {
|
||||
s=s+i;
|
||||
}
|
||||
i--;
|
||||
} while (i>0)
|
@ -14,13 +14,13 @@ B1_from_BBEGIN:
|
||||
B1_from_B3:
|
||||
lda 18
|
||||
sta 14
|
||||
lda 15
|
||||
lda 17
|
||||
sta 13
|
||||
lda 2
|
||||
sta 12
|
||||
lda 16
|
||||
lda 15
|
||||
sta 10
|
||||
lda 16+1
|
||||
lda 15+1
|
||||
sta 10+1
|
||||
B1:
|
||||
ldy #0
|
||||
@ -47,12 +47,12 @@ B1:
|
||||
B3_from_B1:
|
||||
lda 14
|
||||
sta 18
|
||||
lda 3
|
||||
sta 16
|
||||
lda 3+1
|
||||
sta 16+1
|
||||
lda 5
|
||||
sta 17
|
||||
lda 3
|
||||
sta 15
|
||||
lda 3+1
|
||||
sta 15+1
|
||||
B3:
|
||||
lda 2
|
||||
cmp #40
|
||||
@ -77,10 +77,10 @@ B2:
|
||||
B3_from_B2:
|
||||
lda 6
|
||||
sta 18
|
||||
lda 7
|
||||
sta 16
|
||||
lda 7+1
|
||||
sta 16+1
|
||||
lda 9
|
||||
sta 17
|
||||
lda 7
|
||||
sta 15
|
||||
lda 7+1
|
||||
sta 15+1
|
||||
jmp B3
|
||||
|
@ -17,9 +17,9 @@
|
||||
(byte) e#2 ← (byte) e#1 - (byte) 39
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte) y#5 ← 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
|
||||
|
@ -249,8 +249,8 @@ CONTROL FLOW GRAPH SSA
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 @5/(byte) yd#5 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 @5/(byte) STAR#5 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 @5/(byte) x#6 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 @5/(byte) xd#4 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 @5/(byte) e#6 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 @5/(byte*) cursor#6 )
|
||||
@ -269,16 +269,16 @@ CONTROL FLOW GRAPH SSA
|
||||
(byte) e#7 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#7 ← phi( @1/(byte*) cursor#1 )
|
||||
(byte) STAR#4 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
(byte) x#5 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#6 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#5 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#5 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -286,14 +286,14 @@ CONTROL FLOW GRAPH SSA
|
||||
if((boolean~) $14) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) yd#5 ← phi( )
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) x#6 ← phi( )
|
||||
(byte) x1#5 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte) xd#4 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@ -342,8 +342,8 @@ CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 @5/(byte) yd#5 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 @5/(byte) STAR#5 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 @5/(byte) x#6 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 @5/(byte) xd#4 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 @5/(byte) e#6 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 @5/(byte*) cursor#6 )
|
||||
@ -362,16 +362,16 @@ CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
(byte) e#7 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#7 ← phi( @1/(byte*) cursor#1 )
|
||||
(byte) STAR#4 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
(byte) x#5 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#6 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#5 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#5 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -379,14 +379,14 @@ CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
if((boolean~) $14) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) yd#5 ← phi( )
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) x#6 ← phi( )
|
||||
(byte) x1#5 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte) xd#4 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@ -437,8 +437,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 @5/(byte) yd#5 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 @5/(byte) STAR#5 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 @5/(byte) x#6 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 @5/(byte) xd#4 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 @5/(byte) e#6 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 @5/(byte*) cursor#6 )
|
||||
@ -457,16 +457,16 @@ CONTROL FLOW GRAPH
|
||||
(byte) e#7 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#7 ← phi( @1/(byte*) cursor#1 )
|
||||
(byte) STAR#4 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
(byte) x#5 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#6 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#5 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#5 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -474,14 +474,14 @@ CONTROL FLOW GRAPH
|
||||
if((boolean~) $14) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) yd#5 ← phi( )
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) x#6 ← phi( )
|
||||
(byte) x1#5 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte) xd#4 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
@ -529,8 +529,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 @5/(byte) yd#5 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 @5/(byte) STAR#5 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 @5/(byte) x#6 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#4 @5/(byte) x1#5 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 @5/(byte) xd#4 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 @5/(byte) e#6 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 @5/(byte*) cursor#6 )
|
||||
@ -549,16 +549,16 @@ CONTROL FLOW GRAPH
|
||||
(byte) e#7 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#7 ← phi( @1/(byte*) cursor#1 )
|
||||
(byte) STAR#4 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
(byte) x#5 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#3 ← phi( @1/(byte) x1#4 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#6 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#5 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#4 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#7 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#7 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#4 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#5 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -566,14 +566,14 @@ CONTROL FLOW GRAPH
|
||||
if((boolean~) $14) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) yd#5 ← phi( )
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) x#6 ← phi( )
|
||||
(byte) x1#5 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte) xd#4 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
@ -588,11 +588,11 @@ Alias (byte) e#1 = (byte~) $8 (byte) e#7
|
||||
Alias (byte) y#1 = (byte~) $10
|
||||
Alias (byte*) cursor#2 = (byte*~) $11
|
||||
Alias (byte) e#2 = (byte~) $12
|
||||
Alias (byte) y#3 = (byte) y#6
|
||||
Alias (byte) xd#1 = (byte) xd#5
|
||||
Alias (byte) yd#1 = (byte) yd#4
|
||||
Alias (byte) STAR#1 = (byte) STAR#4
|
||||
Alias (byte) x1#3 = (byte) x1#4
|
||||
Alias (byte) STAR#1 = (byte) STAR#4
|
||||
Alias (byte) yd#1 = (byte) yd#4
|
||||
Alias (byte) xd#1 = (byte) xd#5
|
||||
Alias (byte) y#3 = (byte) y#6
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -624,8 +624,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 @5/(byte) yd#5 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 @5/(byte) STAR#5 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 @5/(byte) x1#5 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 @5/(byte) x#6 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 @5/(byte) x1#5 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 @5/(byte) xd#4 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 @5/(byte) e#6 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 @5/(byte*) cursor#6 )
|
||||
@ -638,11 +638,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#3 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -650,25 +650,25 @@ CONTROL FLOW GRAPH
|
||||
if((boolean~) $14) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) yd#5 ← phi( )
|
||||
(byte) STAR#5 ← phi( )
|
||||
(byte) x#6 ← phi( )
|
||||
(byte) x1#5 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte) xd#4 ← phi( )
|
||||
(byte) e#6 ← phi( )
|
||||
(byte*) cursor#6 ← phi( )
|
||||
(byte) y#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Redundant Phi (byte) STAR#5 VOID
|
||||
Redundant Phi (byte) yd#5 VOID
|
||||
Redundant Phi (byte) x#6 VOID
|
||||
Redundant Phi (byte) x1#5 VOID
|
||||
Redundant Phi (byte) y#4 VOID
|
||||
Redundant Phi (byte*) cursor#6 VOID
|
||||
Redundant Phi (byte) e#6 VOID
|
||||
Redundant Phi (byte) xd#4 VOID
|
||||
Redundant Phi (byte) x1#5 VOID
|
||||
Redundant Phi (byte) x#6 VOID
|
||||
Redundant Phi (byte) STAR#5 VOID
|
||||
Redundant Phi (byte) yd#5 VOID
|
||||
Succesful SSA optimization Pass2RedundantPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -700,8 +700,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 )
|
||||
@ -714,11 +714,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#3 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -761,8 +761,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1 @5
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 )
|
||||
@ -775,11 +775,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @4/(byte) y#3 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @4/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @4/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @4/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @4/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @4/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @4/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @4/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -821,8 +821,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 )
|
||||
@ -833,11 +833,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#3 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @1/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @1/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @1/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @1/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @1/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @1/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @1/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -875,8 +875,8 @@ CONTROL FLOW GRAPH
|
||||
@2: from @1
|
||||
(byte) yd#3 ← phi( @1/(byte) yd#1 )
|
||||
(byte) STAR#3 ← phi( @1/(byte) STAR#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) x#4 ← phi( @1/(byte) x#1 )
|
||||
(byte) x1#2 ← phi( @1/(byte) x1#3 )
|
||||
(byte) xd#2 ← phi( @1/(byte) xd#1 )
|
||||
(byte) e#4 ← phi( @1/(byte) e#1 )
|
||||
(byte*) cursor#4 ← phi( @1/(byte*) cursor#1 )
|
||||
@ -887,11 +887,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#3 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @1/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @1/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#2 @1/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#3 @1/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#3 @1/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#4 @1/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @1/(byte) x1#3 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -900,14 +900,14 @@ CONTROL FLOW GRAPH
|
||||
@END: from @3
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) x1#1
|
||||
Alias (byte) yd#1 = (byte) yd#3
|
||||
Alias (byte) STAR#1 = (byte) STAR#3
|
||||
Alias (byte) y#2 = (byte) y#3
|
||||
Alias (byte*) cursor#1 = (byte*) cursor#4
|
||||
Alias (byte) e#1 = (byte) e#4
|
||||
Alias (byte) xd#1 = (byte) xd#2
|
||||
Alias (byte) x1#2 = (byte) x1#3
|
||||
Alias (byte) x#1 = (byte) x#4
|
||||
Alias (byte) xd#1 = (byte) xd#2
|
||||
Alias (byte) e#1 = (byte) e#4
|
||||
Alias (byte*) cursor#1 = (byte*) cursor#4
|
||||
Alias (byte) y#2 = (byte) y#3
|
||||
Alias (byte) STAR#1 = (byte) STAR#3
|
||||
Alias (byte) yd#1 = (byte) yd#3
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -938,11 +938,11 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#1 @1/(byte) STAR#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#1 @1/(byte) yd#1 )
|
||||
(byte) xd#3 ← phi( @2/(byte) xd#1 @1/(byte) xd#1 )
|
||||
(byte) yd#2 ← phi( @2/(byte) yd#1 @1/(byte) yd#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) STAR#2 ← phi( @2/(byte) STAR#1 @1/(byte) STAR#1 )
|
||||
(byte) x#3 ← phi( @2/(byte) x#1 @1/(byte) x#1 )
|
||||
(byte) x1#1 ← phi( @2/(byte) x1#2 @1/(byte) x1#2 )
|
||||
(byte~) $13 ← (byte) x1#1 + (byte) 1
|
||||
@ -950,11 +950,11 @@ CONTROL FLOW GRAPH
|
||||
to:@END
|
||||
@END: from @3
|
||||
|
||||
Redundant Phi (byte) x1#1 (byte) x1#2
|
||||
Redundant Phi (byte) x#3 (byte) x#1
|
||||
Redundant Phi (byte) STAR#2 (byte) STAR#1
|
||||
Redundant Phi (byte) yd#2 (byte) yd#1
|
||||
Redundant Phi (byte) xd#3 (byte) xd#1
|
||||
Redundant Phi (byte) x#3 (byte) x#1
|
||||
Redundant Phi (byte) x1#1 (byte) x1#2
|
||||
Succesful SSA optimization Pass2RedundantPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -985,17 +985,17 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte~) $13 ← (byte) x1#2 + (byte) 1
|
||||
if((byte) x#1<(byte~) $13) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
|
||||
Self Phi Eliminated (byte) x1#2
|
||||
Self Phi Eliminated (byte) xd#1
|
||||
Self Phi Eliminated (byte) yd#1
|
||||
Self Phi Eliminated (byte) STAR#1
|
||||
Self Phi Eliminated (byte) yd#1
|
||||
Self Phi Eliminated (byte) xd#1
|
||||
Self Phi Eliminated (byte) x1#2
|
||||
Succesful SSA optimization Pass2SelfPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -1026,8 +1026,8 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte~) $13 ← (byte) x1#2 + (byte) 1
|
||||
if((byte) x#1<(byte~) $13) goto @1
|
||||
to:@END
|
||||
@ -1035,10 +1035,10 @@ CONTROL FLOW GRAPH
|
||||
|
||||
Constant (byte) e#0 (byte) 12
|
||||
Constant (byte~) $3 (byte) 0
|
||||
Constant (byte) x1#2 (byte) 39
|
||||
Constant (byte) xd#1 (byte) 39
|
||||
Constant (byte) yd#1 (byte) 24
|
||||
Constant (byte) STAR#1 (byte) 81
|
||||
Constant (byte) yd#1 (byte) 24
|
||||
Constant (byte) xd#1 (byte) 39
|
||||
Constant (byte) x1#2 (byte) 39
|
||||
Succesful SSA optimization Pass2ConstantPropagation
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
@ -1063,8 +1063,8 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte~) $13 ← (byte) 39 + (byte) 1
|
||||
if((byte) x#1<(byte~) $13) goto @1
|
||||
to:@END
|
||||
@ -1097,8 +1097,8 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
if((byte) x#1<(byte) 40) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
@ -1128,8 +1128,8 @@ CONTROL FLOW GRAPH
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) y#5 ← phi( @2/(byte) y#1 @1/(byte) y#2 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
(byte) e#5 ← phi( @2/(byte) e#2 @1/(byte) e#1 )
|
||||
(byte*) cursor#5 ← phi( @2/(byte*) cursor#2 @1/(byte*) cursor#1 )
|
||||
if((byte) x#1<(byte) 40) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
@ -1161,15 +1161,15 @@ B1_from_B3:
|
||||
lda 18
|
||||
sta 14
|
||||
// (byte) e#3 = (byte) e#5 // zpby1=zpby2
|
||||
lda 15
|
||||
lda 17
|
||||
sta 13
|
||||
// (byte) x#2 = (byte) x#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 12
|
||||
// (byte*) cursor#3 = (byte*) cursor#5 // zpptrby1=zpptrby2
|
||||
lda 16
|
||||
lda 15
|
||||
sta 10
|
||||
lda 16+1
|
||||
lda 15+1
|
||||
sta 10+1
|
||||
jmp B1
|
||||
B1:
|
||||
@ -1203,14 +1203,14 @@ B3_from_B1:
|
||||
// (byte) y#5 = (byte) y#2 // zpby1=zpby2
|
||||
lda 14
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 16
|
||||
lda 3+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#1 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 15
|
||||
lda 3+1
|
||||
sta 15+1
|
||||
jmp B3
|
||||
B3:
|
||||
// if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1
|
||||
@ -1242,14 +1242,14 @@ B3_from_B2:
|
||||
// (byte) y#5 = (byte) y#1 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 16
|
||||
lda 7+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#2 // zpby1=zpby2
|
||||
lda 9
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 15
|
||||
lda 7+1
|
||||
sta 15+1
|
||||
jmp B3
|
||||
|
||||
Removing instruction jmp B1
|
||||
@ -1279,15 +1279,15 @@ B1_from_B3:
|
||||
lda 18
|
||||
sta 14
|
||||
// (byte) e#3 = (byte) e#5 // zpby1=zpby2
|
||||
lda 15
|
||||
lda 17
|
||||
sta 13
|
||||
// (byte) x#2 = (byte) x#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 12
|
||||
// (byte*) cursor#3 = (byte*) cursor#5 // zpptrby1=zpptrby2
|
||||
lda 16
|
||||
lda 15
|
||||
sta 10
|
||||
lda 16+1
|
||||
lda 15+1
|
||||
sta 10+1
|
||||
B1:
|
||||
// *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1
|
||||
@ -1320,14 +1320,14 @@ B3_from_B1:
|
||||
// (byte) y#5 = (byte) y#2 // zpby1=zpby2
|
||||
lda 14
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 16
|
||||
lda 3+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#1 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 15
|
||||
lda 3+1
|
||||
sta 15+1
|
||||
B3:
|
||||
// if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1
|
||||
lda 2
|
||||
@ -1357,14 +1357,14 @@ B3_from_B2:
|
||||
// (byte) y#5 = (byte) y#1 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 16
|
||||
lda 7+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#2 // zpby1=zpby2
|
||||
lda 9
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 15
|
||||
lda 7+1
|
||||
sta 15+1
|
||||
jmp B3
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
@ -1379,12 +1379,12 @@ FINAL SYMBOL TABLE
|
||||
(byte*) cursor#1 zp ptr byte:3
|
||||
(byte*) cursor#2 zp ptr byte:7
|
||||
(byte*) cursor#3 zp ptr byte:10
|
||||
(byte*) cursor#5 zp ptr byte:16
|
||||
(byte*) cursor#5 zp ptr byte:15
|
||||
(byte) e
|
||||
(byte) e#1 zp byte:5
|
||||
(byte) e#2 zp byte:9
|
||||
(byte) e#3 zp byte:13
|
||||
(byte) e#5 zp byte:15
|
||||
(byte) e#5 zp byte:17
|
||||
(byte) x
|
||||
(byte) x#1 zp byte:2
|
||||
(byte) x#2 zp byte:12
|
||||
@ -1422,15 +1422,15 @@ B1_from_B3:
|
||||
lda 18
|
||||
sta 14
|
||||
// (byte) e#3 = (byte) e#5 // zpby1=zpby2
|
||||
lda 15
|
||||
lda 17
|
||||
sta 13
|
||||
// (byte) x#2 = (byte) x#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 12
|
||||
// (byte*) cursor#3 = (byte*) cursor#5 // zpptrby1=zpptrby2
|
||||
lda 16
|
||||
lda 15
|
||||
sta 10
|
||||
lda 16+1
|
||||
lda 15+1
|
||||
sta 10+1
|
||||
B1:
|
||||
// *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1
|
||||
@ -1463,14 +1463,14 @@ B3_from_B1:
|
||||
// (byte) y#5 = (byte) y#2 // zpby1=zpby2
|
||||
lda 14
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 16
|
||||
lda 3+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#1 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#1 // zpptrby1=zpptrby2
|
||||
lda 3
|
||||
sta 15
|
||||
lda 3+1
|
||||
sta 15+1
|
||||
B3:
|
||||
// if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1
|
||||
lda 2
|
||||
@ -1500,13 +1500,13 @@ B3_from_B2:
|
||||
// (byte) y#5 = (byte) y#1 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 18
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 16
|
||||
lda 7+1
|
||||
sta 16+1
|
||||
// (byte) e#5 = (byte) e#2 // zpby1=zpby2
|
||||
lda 9
|
||||
sta 17
|
||||
// (byte*) cursor#5 = (byte*) cursor#2 // zpptrby1=zpptrby2
|
||||
lda 7
|
||||
sta 15
|
||||
lda 7+1
|
||||
sta 15+1
|
||||
jmp B3
|
||||
|
||||
|
@ -9,12 +9,12 @@
|
||||
(byte*) cursor#1 zp ptr byte:3
|
||||
(byte*) cursor#2 zp ptr byte:7
|
||||
(byte*) cursor#3 zp ptr byte:10
|
||||
(byte*) cursor#5 zp ptr byte:16
|
||||
(byte*) cursor#5 zp ptr byte:15
|
||||
(byte) e
|
||||
(byte) e#1 zp byte:5
|
||||
(byte) e#2 zp byte:9
|
||||
(byte) e#3 zp byte:13
|
||||
(byte) e#5 zp byte:15
|
||||
(byte) e#5 zp byte:17
|
||||
(byte) x
|
||||
(byte) x#1 zp byte:2
|
||||
(byte) x#2 zp byte:12
|
||||
|
@ -34,11 +34,11 @@ plot:
|
||||
plot__B1_from_plot:
|
||||
lda #16
|
||||
sta 100
|
||||
ldx #0
|
||||
lda #<1236
|
||||
sta 101
|
||||
lda #>1236
|
||||
sta 101+1
|
||||
ldx #0
|
||||
plot__B1_from_B3:
|
||||
plot__B1:
|
||||
plot__B2_from_B1:
|
||||
@ -68,8 +68,8 @@ flip:
|
||||
flip__B1_from_flip:
|
||||
lda #16
|
||||
sta 104
|
||||
ldx #0
|
||||
ldy #15
|
||||
ldx #0
|
||||
flip__B1_from_B4:
|
||||
flip__B1:
|
||||
flip__B2_from_B1:
|
||||
|
@ -5,7 +5,7 @@ main: from @BEGIN
|
||||
call prepare param-assignment
|
||||
to:main::@2
|
||||
main::@2: from main main::@11 main::@6
|
||||
(byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@11/(byte) 25 )
|
||||
(byte) main::c#2 ← phi( main/(byte) 25 main::@11/(byte) 25 main::@6/(byte) main::c#1 )
|
||||
to:main::@3
|
||||
main::@3: from main::@2 main::@3
|
||||
(byte~) main::$1 ← * (word) 53266
|
||||
@ -46,8 +46,8 @@ flip: from main::@7
|
||||
to:flip::@1
|
||||
flip::@1: from flip flip::@4
|
||||
(byte) flip::r#2 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 )
|
||||
(byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 )
|
||||
(byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 )
|
||||
(byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 )
|
||||
to:flip::@2
|
||||
flip::@2: from flip::@1 flip::@2
|
||||
(byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 )
|
||||
@ -79,8 +79,8 @@ plot: from main::@10
|
||||
to:plot::@1
|
||||
plot::@1: from plot plot::@3
|
||||
(byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 )
|
||||
(byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 )
|
||||
(byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@3/(byte*) plot::line#1 )
|
||||
(byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 )
|
||||
to:plot::@2
|
||||
plot::@2: from plot::@1 plot::@2
|
||||
(byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 )
|
||||
|
File diff suppressed because it is too large
Load Diff
37
src/dk/camelot64/kickc/test/ref/loopmin.asm
Normal file
37
src/dk/camelot64/kickc/test/ref/loopmin.asm
Normal file
@ -0,0 +1,37 @@
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
lda #0
|
||||
sta 5
|
||||
lda #10
|
||||
sta 4
|
||||
jmp B1
|
||||
B1_from_B3:
|
||||
lda 6
|
||||
sta 5
|
||||
lda 3
|
||||
sta 4
|
||||
B1:
|
||||
lda 4
|
||||
cmp #5
|
||||
beq !+
|
||||
bcs B2
|
||||
!:
|
||||
B3_from_B1:
|
||||
lda 5
|
||||
sta 6
|
||||
B3:
|
||||
lda 4
|
||||
sta 3
|
||||
dec 3
|
||||
lda 3
|
||||
bne B1_from_B3
|
||||
BEND:
|
||||
B2:
|
||||
lda 5
|
||||
clc
|
||||
adc 4
|
||||
sta 2
|
||||
B3_from_B2:
|
||||
lda 2
|
||||
sta 6
|
||||
jmp B3
|
16
src/dk/camelot64/kickc/test/ref/loopmin.cfg
Normal file
16
src/dk/camelot64/kickc/test/ref/loopmin.cfg
Normal file
@ -0,0 +1,16 @@
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#2 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
if((byte) i#2>(byte) 5) goto @2
|
||||
to:@3
|
||||
@2: from @1
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#2
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) s#5 ← phi( @1/(byte) s#2 @2/(byte) s#1 )
|
||||
(byte) i#1 ← -- (byte) i#2
|
||||
if((byte) i#1>(byte) 0) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
558
src/dk/camelot64/kickc/test/ref/loopmin.log
Normal file
558
src/dk/camelot64/kickc/test/ref/loopmin.log
Normal file
@ -0,0 +1,558 @@
|
||||
byte i=10;
|
||||
byte s=0;
|
||||
do {
|
||||
if(i>5) {
|
||||
s=s+i;
|
||||
}
|
||||
i--;
|
||||
} while (i>0)
|
||||
Adding pre/post-modifier (byte) i ← -- (byte) i
|
||||
PROGRAM
|
||||
(byte) i ← (byte) 10
|
||||
(byte) s ← (byte) 0
|
||||
@1:
|
||||
(boolean~) $0 ← (byte) i > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
goto @3
|
||||
@2:
|
||||
(byte~) $1 ← (byte) s + (byte) i
|
||||
(byte) s ← (byte~) $1
|
||||
@3:
|
||||
(byte) i ← -- (byte) i
|
||||
(boolean~) $2 ← (byte) i > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
|
||||
SYMBOLS
|
||||
(boolean~) $0
|
||||
(byte~) $1
|
||||
(boolean~) $2
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(byte) i
|
||||
(byte) s
|
||||
|
||||
INITIAL CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
(byte) i ← (byte) 10
|
||||
(byte) s ← (byte) 0
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(boolean~) $0 ← (byte) i > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte~) $1 ← (byte) s + (byte) i
|
||||
(byte) s ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) i ← -- (byte) i
|
||||
(boolean~) $2 ← (byte) i > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@END: from @6
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
|
||||
@BEGIN: from
|
||||
(byte) i ← (byte) 10
|
||||
(byte) s ← (byte) 0
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(boolean~) $0 ← (byte) i > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte~) $1 ← (byte) s + (byte) i
|
||||
(byte) s ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) i ← -- (byte) i
|
||||
(boolean~) $2 ← (byte) i > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@END: from @6
|
||||
|
||||
Completing Phi functions...
|
||||
Completing Phi functions...
|
||||
Completing Phi functions...
|
||||
Completing Phi functions...
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@BEGIN: from
|
||||
(byte) i#0 ← (byte) 10
|
||||
(byte) s#0 ← (byte) 0
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) s#0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 @5/(byte) i#5 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 @5/(byte) s#4 )
|
||||
(byte~) $1 ← (byte) s#2 + (byte) i#3
|
||||
(byte) s#1 ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
(byte) s#6 ← phi( @1/(byte) s#3 )
|
||||
(byte) i#6 ← phi( @1/(byte) i#2 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#6 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#6 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
(byte) i#5 ← phi( )
|
||||
(byte) s#4 ← phi( )
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@END: from @6
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
@BEGIN: from
|
||||
(byte) i#0 ← (byte) 10
|
||||
(byte) s#0 ← (byte) 0
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) s#0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 @5/(byte) i#5 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 @5/(byte) s#4 )
|
||||
(byte~) $1 ← (byte) s#2 + (byte) i#3
|
||||
(byte) s#1 ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
(byte) s#6 ← phi( @1/(byte) s#3 )
|
||||
(byte) i#6 ← phi( @1/(byte) i#2 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#6 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#6 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@6
|
||||
@5: from
|
||||
(byte) i#5 ← phi( )
|
||||
(byte) s#4 ← phi( )
|
||||
to:@2
|
||||
@6: from @3
|
||||
to:@END
|
||||
@END: from @6
|
||||
|
||||
Culled Empty Block (label) @6
|
||||
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
(byte) i#0 ← (byte) 10
|
||||
(byte) s#0 ← (byte) 0
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) s#0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 @5/(byte) i#5 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 @5/(byte) s#4 )
|
||||
(byte~) $1 ← (byte) s#2 + (byte) i#3
|
||||
(byte) s#1 ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
(byte) s#6 ← phi( @1/(byte) s#3 )
|
||||
(byte) i#6 ← phi( @1/(byte) i#2 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#6 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#6 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) i#5 ← phi( )
|
||||
(byte) s#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Constant (byte) i#0 (byte) 10
|
||||
Constant (byte) s#0 (byte) 0
|
||||
Succesful SSA optimization Pass2ConstantPropagation
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 @5/(byte) i#5 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 @5/(byte) s#4 )
|
||||
(byte~) $1 ← (byte) s#2 + (byte) i#3
|
||||
(byte) s#1 ← (byte~) $1
|
||||
to:@3
|
||||
@4: from @1
|
||||
(byte) s#6 ← phi( @1/(byte) s#3 )
|
||||
(byte) i#6 ← phi( @1/(byte) i#2 )
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#6 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#6 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) i#5 ← phi( )
|
||||
(byte) s#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Alias (byte) s#1 = (byte~) $1
|
||||
Alias (byte) i#2 = (byte) i#6
|
||||
Alias (byte) s#3 = (byte) s#6
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 @5/(byte) i#5 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 @5/(byte) s#4 )
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#3
|
||||
to:@3
|
||||
@4: from @1
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#3 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#2 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
(byte) i#5 ← phi( )
|
||||
(byte) s#4 ← phi( )
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Redundant Phi (byte) s#4 VOID
|
||||
Redundant Phi (byte) i#5 VOID
|
||||
Succesful SSA optimization Pass2RedundantPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
(boolean~) $0 ← (byte) i#2 > (byte) 5
|
||||
if((boolean~) $0) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 )
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#3
|
||||
to:@3
|
||||
@4: from @1
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#3 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#2 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
(boolean~) $2 ← (byte) i#1 > (byte) 0
|
||||
if((boolean~) $2) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Simple Condition (boolean~) $0 if((byte) i#2>(byte) 5) goto @2
|
||||
Simple Condition (boolean~) $2 if((byte) i#1>(byte) 0) goto @1
|
||||
Succesful SSA optimization Pass2ConditionalJumpSimplification
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
if((byte) i#2>(byte) 5) goto @2
|
||||
to:@4
|
||||
@2: from @1 @5
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 )
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#3
|
||||
to:@3
|
||||
@4: from @1
|
||||
to:@3
|
||||
@3: from @2 @4
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @4/(byte) s#3 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @4/(byte) i#2 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
if((byte) i#1>(byte) 0) goto @1
|
||||
to:@END
|
||||
@5: from
|
||||
to:@2
|
||||
@END: from @3
|
||||
|
||||
Culled Empty Block (label) @4
|
||||
Culled Empty Block (label) @5
|
||||
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#3 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
if((byte) i#2>(byte) 5) goto @2
|
||||
to:@3
|
||||
@2: from @1
|
||||
(byte) i#3 ← phi( @1/(byte) i#2 )
|
||||
(byte) s#2 ← phi( @1/(byte) s#3 )
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#3
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @1/(byte) s#3 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#3 @1/(byte) i#2 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
if((byte) i#1>(byte) 0) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
|
||||
Alias (byte) s#2 = (byte) s#3
|
||||
Alias (byte) i#2 = (byte) i#3
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#2 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
if((byte) i#2>(byte) 5) goto @2
|
||||
to:@3
|
||||
@2: from @1
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#2
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @1/(byte) s#2 )
|
||||
(byte) i#4 ← phi( @2/(byte) i#2 @1/(byte) i#2 )
|
||||
(byte) i#1 ← -- (byte) i#4
|
||||
if((byte) i#1>(byte) 0) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
|
||||
Redundant Phi (byte) i#4 (byte) i#2
|
||||
Succesful SSA optimization Pass2RedundantPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@1: from @3 @BEGIN
|
||||
(byte) s#2 ← phi( @3/(byte) s#5 @BEGIN/(byte) 0 )
|
||||
(byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 )
|
||||
if((byte) i#2>(byte) 5) goto @2
|
||||
to:@3
|
||||
@2: from @1
|
||||
(byte) s#1 ← (byte) s#2 + (byte) i#2
|
||||
to:@3
|
||||
@3: from @1 @2
|
||||
(byte) s#5 ← phi( @2/(byte) s#1 @1/(byte) s#2 )
|
||||
(byte) i#1 ← -- (byte) i#2
|
||||
if((byte) i#1>(byte) 0) goto @1
|
||||
to:@END
|
||||
@END: from @3
|
||||
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) s#2 = (byte) 0 // zpby1=coby1
|
||||
lda #0
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) 10 // zpby1=coby1
|
||||
lda #10
|
||||
sta 4
|
||||
jmp B1
|
||||
B1_from_B3:
|
||||
// (byte) s#2 = (byte) s#5 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 3
|
||||
sta 4
|
||||
jmp B1
|
||||
B1:
|
||||
// if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #5
|
||||
beq !+
|
||||
bcs B2
|
||||
!:
|
||||
B3_from_B1:
|
||||
// (byte) s#5 = (byte) s#2 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 6
|
||||
jmp B3
|
||||
B3:
|
||||
// (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2
|
||||
lda 4
|
||||
sta 3
|
||||
dec 3
|
||||
// if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1
|
||||
lda 3
|
||||
bne B1_from_B3
|
||||
jmp BEND
|
||||
BEND:
|
||||
B2:
|
||||
// (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3
|
||||
lda 5
|
||||
clc
|
||||
adc 4
|
||||
sta 2
|
||||
B3_from_B2:
|
||||
// (byte) s#5 = (byte) s#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 6
|
||||
jmp B3
|
||||
|
||||
Removing instruction jmp B1
|
||||
Removing instruction jmp B3
|
||||
Removing instruction jmp BEND
|
||||
Succesful ASM optimization Pass4NextJumpElimination
|
||||
ASSEMBLER
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) s#2 = (byte) 0 // zpby1=coby1
|
||||
lda #0
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) 10 // zpby1=coby1
|
||||
lda #10
|
||||
sta 4
|
||||
jmp B1
|
||||
B1_from_B3:
|
||||
// (byte) s#2 = (byte) s#5 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 3
|
||||
sta 4
|
||||
B1:
|
||||
// if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #5
|
||||
beq !+
|
||||
bcs B2
|
||||
!:
|
||||
B3_from_B1:
|
||||
// (byte) s#5 = (byte) s#2 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 6
|
||||
B3:
|
||||
// (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2
|
||||
lda 4
|
||||
sta 3
|
||||
dec 3
|
||||
// if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1
|
||||
lda 3
|
||||
bne B1_from_B3
|
||||
BEND:
|
||||
B2:
|
||||
// (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3
|
||||
lda 5
|
||||
clc
|
||||
adc 4
|
||||
sta 2
|
||||
B3_from_B2:
|
||||
// (byte) s#5 = (byte) s#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 6
|
||||
jmp B3
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @BEGIN
|
||||
(label) @END
|
||||
(byte) i
|
||||
(byte) i#1 zp byte:3
|
||||
(byte) i#2 zp byte:4
|
||||
(byte) s
|
||||
(byte) s#1 zp byte:2
|
||||
(byte) s#2 zp byte:5
|
||||
(byte) s#5 zp byte:6
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) s#2 = (byte) 0 // zpby1=coby1
|
||||
lda #0
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) 10 // zpby1=coby1
|
||||
lda #10
|
||||
sta 4
|
||||
jmp B1
|
||||
B1_from_B3:
|
||||
// (byte) s#2 = (byte) s#5 // zpby1=zpby2
|
||||
lda 6
|
||||
sta 5
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 3
|
||||
sta 4
|
||||
B1:
|
||||
// if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #5
|
||||
beq !+
|
||||
bcs B2
|
||||
!:
|
||||
B3_from_B1:
|
||||
// (byte) s#5 = (byte) s#2 // zpby1=zpby2
|
||||
lda 5
|
||||
sta 6
|
||||
B3:
|
||||
// (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2
|
||||
lda 4
|
||||
sta 3
|
||||
dec 3
|
||||
// if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1
|
||||
lda 3
|
||||
bne B1_from_B3
|
||||
BEND:
|
||||
B2:
|
||||
// (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3
|
||||
lda 5
|
||||
clc
|
||||
adc 4
|
||||
sta 2
|
||||
B3_from_B2:
|
||||
// (byte) s#5 = (byte) s#1 // zpby1=zpby2
|
||||
lda 2
|
||||
sta 6
|
||||
jmp B3
|
||||
|
12
src/dk/camelot64/kickc/test/ref/loopmin.sym
Normal file
12
src/dk/camelot64/kickc/test/ref/loopmin.sym
Normal file
@ -0,0 +1,12 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @BEGIN
|
||||
(label) @END
|
||||
(byte) i
|
||||
(byte) i#1 zp byte:3
|
||||
(byte) i#2 zp byte:4
|
||||
(byte) s
|
||||
(byte) s#1 zp byte:2
|
||||
(byte) s#2 zp byte:5
|
||||
(byte) s#5 zp byte:6
|
28
src/dk/camelot64/kickc/test/ref/minus.asm
Normal file
28
src/dk/camelot64/kickc/test/ref/minus.asm
Normal file
@ -0,0 +1,28 @@
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
lda #5
|
||||
sta 5
|
||||
jmp B1
|
||||
B1_from_B1:
|
||||
lda 4
|
||||
sta 5
|
||||
B1:
|
||||
lda #2
|
||||
clc
|
||||
adc 5
|
||||
sta 2
|
||||
lda 2
|
||||
clc
|
||||
adc #2
|
||||
sta 3
|
||||
lda 3
|
||||
ldy 5
|
||||
sta 4352,y
|
||||
lda 5
|
||||
clc
|
||||
adc #1
|
||||
sta 4
|
||||
lda 4
|
||||
cmp #10
|
||||
bcc B1_from_B1
|
||||
BEND:
|
11
src/dk/camelot64/kickc/test/ref/minus.cfg
Normal file
11
src/dk/camelot64/kickc/test/ref/minus.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
@BEGIN: from
|
||||
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
|
||||
*((word) 4352 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@END
|
||||
@END: from @1
|
344
src/dk/camelot64/kickc/test/ref/minus.log
Normal file
344
src/dk/camelot64/kickc/test/ref/minus.log
Normal file
@ -0,0 +1,344 @@
|
||||
byte[16] p = $1100;
|
||||
byte i = 5;
|
||||
do {
|
||||
p[i] = 2+i+2;
|
||||
i = i+1;
|
||||
} while(i<10)
|
||||
|
||||
PROGRAM
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
@1:
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
|
||||
SYMBOLS
|
||||
(byte~) $0
|
||||
(byte~) $1
|
||||
(byte~) $2
|
||||
(boolean~) $3
|
||||
(label) @1
|
||||
(byte) i
|
||||
(byte[16]) p
|
||||
|
||||
INITIAL CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
to:@1
|
||||
@1: from @1 @BEGIN
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@2
|
||||
@2: from @1
|
||||
to:@END
|
||||
@END: from @2
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
|
||||
@BEGIN: from
|
||||
(byte[16]) p ← (word) 4352
|
||||
(byte) i ← (byte) 5
|
||||
to:@1
|
||||
@1: from @1 @BEGIN
|
||||
(byte~) $0 ← (byte) 2 + (byte) i
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p + (byte) i) ← (byte~) $1
|
||||
(byte~) $2 ← (byte) i + (byte) 1
|
||||
(byte) i ← (byte~) $2
|
||||
(boolean~) $3 ← (byte) i < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@2
|
||||
@2: from @1
|
||||
to:@END
|
||||
@END: from @2
|
||||
|
||||
Completing Phi functions...
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@BEGIN: from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: from @1 @BEGIN
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @BEGIN/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((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:@2
|
||||
@2: from @1
|
||||
to:@END
|
||||
@END: from @2
|
||||
|
||||
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||
@BEGIN: from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: from @1 @BEGIN
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @BEGIN/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((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:@2
|
||||
@2: from @1
|
||||
to:@END
|
||||
@END: from @2
|
||||
|
||||
Culled Empty Block (label) @2
|
||||
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
(byte[16]) p#0 ← (word) 4352
|
||||
(byte) i#0 ← (byte) 5
|
||||
to:@1
|
||||
@1: from @1 @BEGIN
|
||||
(byte[16]) p#1 ← phi( @1/(byte[16]) p#1 @BEGIN/(byte[16]) p#0 )
|
||||
(byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) i#0 )
|
||||
(byte~) $0 ← (byte) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((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
|
||||
|
||||
Constant (byte[16]) p#0 (word) 4352
|
||||
Constant (byte) i#0 (byte) 5
|
||||
Succesful SSA optimization Pass2ConstantPropagation
|
||||
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) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((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
|
||||
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Alias (byte) i#1 = (byte~) $2
|
||||
Succesful SSA optimization Pass2AliasElimination
|
||||
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) 2 + (byte) i#2
|
||||
(byte~) $1 ← (byte~) $0 + (byte) 2
|
||||
*((byte[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@END
|
||||
@END: from @1
|
||||
|
||||
Self Phi Eliminated (byte[16]) p#1
|
||||
Succesful SSA optimization Pass2SelfPhiElimination
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@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[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
(boolean~) $3 ← (byte) i#1 < (byte) 10
|
||||
if((boolean~) $3) goto @1
|
||||
to:@END
|
||||
@END: from @1
|
||||
|
||||
Simple Condition (boolean~) $3 if((byte) i#1<(byte) 10) goto @1
|
||||
Succesful SSA optimization Pass2ConditionalJumpSimplification
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
to:@1
|
||||
@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[16]) p#1 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) goto @1
|
||||
to:@END
|
||||
@END: from @1
|
||||
|
||||
Constant (byte[16]) p#1 (word) 4352
|
||||
Succesful SSA optimization Pass2ConstantPropagation
|
||||
CONTROL FLOW GRAPH
|
||||
@BEGIN: from
|
||||
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
|
||||
*((word) 4352 + (byte) i#2) ← (byte~) $1
|
||||
(byte) i#1 ← (byte) i#2 + (byte) 1
|
||||
if((byte) i#1<(byte) 10) 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
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
Multiple usages for variable. Not optimizing sub-constant (byte) i#2
|
||||
INITIAL ASM
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) i#2 = (byte) 5 // zpby1=coby1
|
||||
lda #5
|
||||
sta 5
|
||||
jmp B1
|
||||
B1_from_B1:
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 4
|
||||
sta 5
|
||||
jmp B1
|
||||
B1:
|
||||
// (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2
|
||||
lda #2
|
||||
clc
|
||||
adc 5
|
||||
sta 2
|
||||
// (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1
|
||||
lda 2
|
||||
clc
|
||||
adc #2
|
||||
sta 3
|
||||
// *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2
|
||||
lda 3
|
||||
ldy 5
|
||||
sta 4352,y
|
||||
// (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1
|
||||
lda 5
|
||||
clc
|
||||
adc #1
|
||||
sta 4
|
||||
// if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #10
|
||||
bcc B1_from_B1
|
||||
jmp BEND
|
||||
BEND:
|
||||
|
||||
Removing instruction jmp B1
|
||||
Removing instruction jmp BEND
|
||||
Succesful ASM optimization Pass4NextJumpElimination
|
||||
ASSEMBLER
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) i#2 = (byte) 5 // zpby1=coby1
|
||||
lda #5
|
||||
sta 5
|
||||
jmp B1
|
||||
B1_from_B1:
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 4
|
||||
sta 5
|
||||
B1:
|
||||
// (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2
|
||||
lda #2
|
||||
clc
|
||||
adc 5
|
||||
sta 2
|
||||
// (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1
|
||||
lda 2
|
||||
clc
|
||||
adc #2
|
||||
sta 3
|
||||
// *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2
|
||||
lda 3
|
||||
ldy 5
|
||||
sta 4352,y
|
||||
// (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1
|
||||
lda 5
|
||||
clc
|
||||
adc #1
|
||||
sta 4
|
||||
// if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #10
|
||||
bcc B1_from_B1
|
||||
BEND:
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(byte~) $0 zp byte:2
|
||||
(byte~) $1 zp byte:3
|
||||
(label) @1
|
||||
(label) @BEGIN
|
||||
(label) @END
|
||||
(byte) i
|
||||
(byte) i#1 zp byte:4
|
||||
(byte) i#2 zp byte:5
|
||||
(byte[16]) p
|
||||
|
||||
FINAL CODE
|
||||
BBEGIN:
|
||||
B1_from_BBEGIN:
|
||||
// (byte) i#2 = (byte) 5 // zpby1=coby1
|
||||
lda #5
|
||||
sta 5
|
||||
jmp B1
|
||||
B1_from_B1:
|
||||
// (byte) i#2 = (byte) i#1 // zpby1=zpby2
|
||||
lda 4
|
||||
sta 5
|
||||
B1:
|
||||
// (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2
|
||||
lda #2
|
||||
clc
|
||||
adc 5
|
||||
sta 2
|
||||
// (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1
|
||||
lda 2
|
||||
clc
|
||||
adc #2
|
||||
sta 3
|
||||
// *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2
|
||||
lda 3
|
||||
ldy 5
|
||||
sta 4352,y
|
||||
// (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1
|
||||
lda 5
|
||||
clc
|
||||
adc #1
|
||||
sta 4
|
||||
// if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1
|
||||
lda 4
|
||||
cmp #10
|
||||
bcc B1_from_B1
|
||||
BEND:
|
||||
|
9
src/dk/camelot64/kickc/test/ref/minus.sym
Normal file
9
src/dk/camelot64/kickc/test/ref/minus.sym
Normal file
@ -0,0 +1,9 @@
|
||||
(byte~) $0 zp byte:2
|
||||
(byte~) $1 zp byte:3
|
||||
(label) @1
|
||||
(label) @BEGIN
|
||||
(label) @END
|
||||
(byte) i
|
||||
(byte) i#1 zp byte:4
|
||||
(byte) i#2 zp byte:5
|
||||
(byte[16]) p
|
Loading…
Reference in New Issue
Block a user