1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Working on improving the condition simplification.

This commit is contained in:
jespergravgaard 2020-02-23 10:04:51 +01:00
parent 5ffae4d92a
commit 2961c84bd7
2 changed files with 70 additions and 55 deletions

View File

@ -4,7 +4,10 @@ import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -301,24 +304,36 @@ public class VariableReferenceInfos {
}
/**
* Get the index of the statement defining a variable
* Get the index of the statement defining a variable. Only returns if there is exactly one defining statement.
*
* @param variableRef The variable to look for
* @return Index of the defining statement
*/
public Integer getVarDefineStatement(VariableRef variableRef) {
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(variableRef);
final Collection<Integer> stmts = getVarDefineStatements(variableRef);
if(stmts.size() == 1)
return stmts.iterator().next();
else
return null;
}
/**
* Get all statements defining a variable
*
* @param varRef The variable to look for
* @return Index of all statements defining the variable (ie. assigning a value to it)
*/
public Collection<Integer> getVarDefineStatements(VariableRef varRef) {
LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
if(refs != null) {
Optional<ReferenceToSymbolVar> refDefine = refs.stream()
refs.stream()
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.DEFINE.equals(referenceToSymbolVar.getReferenceType()))
.findFirst();
if(refDefine.isPresent()) {
return ((ReferenceInStatement) refDefine.get()).getStatementIdx();
}
.forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).statementIdx));
}
return null;
return stmts;
}

View File

@ -7,7 +7,6 @@ import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;
@ -27,19 +26,16 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
@Override
public boolean step() {
final Map<LValue, StatementAssignment> assignments = getAllAssignments();
final Map<RValue, List<Statement>> usages = getAllUsages();
final List<VariableRef> simpleConditionVars = getSimpleConditions(assignments, usages);
final List<VariableRef> simpleConditionVars = getSimpleConditions(usages);
removeAssignments(getGraph(), simpleConditionVars);
deleteSymbols(getScope(), simpleConditionVars);
return (simpleConditionVars.size() > 0);
}
private List<VariableRef> getSimpleConditions(final Map<LValue, StatementAssignment> assignments, final Map<RValue, List<Statement>> usages) {
private List<VariableRef> getSimpleConditions(final Map<RValue, List<Statement>> usages) {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
final List<VariableRef> simpleConditionVars = new ArrayList<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
@ -48,49 +44,52 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
RValue conditionRValue = conditionalJump.getrValue2();
if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size() == 1) {
VariableRef conditionVar = (VariableRef) conditionRValue;
StatementAssignment conditionAssignment = assignments.get(conditionVar);
if(conditionAssignment != null && conditionAssignment.getOperator() != null) {
switch(conditionAssignment.getOperator().getOperator()) {
case "==":
case "<>":
case "!=":
case "<":
case ">":
case "<=":
case "=<":
case ">=":
case "=>":
final Collection<VariableRef> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1());
referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2()));
boolean isSimple = true;
if(referencedLoadStoreVariables.size() > 0) {
// Found referenced load/store variables
// Examine all statements between the conditionAssignment and conditionalJump for modifications
final StatementInfos statementInfos = getProgram().getStatementInfos();
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos);
for(Statement statementBetween : statementsBetween) {
for(VariableRef referencedLoadStoreVariable : referencedLoadStoreVariables) {
if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable)) {
// A referenced load/store-variable is modified in a statement between the assignment and the condition!
isSimple = false;
getLog().append("Condition not simple " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionDefineStmtIdx != null) {
final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
if(conditionDefineStmt instanceof StatementAssignment && ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStmt;
switch(conditionAssignment.getOperator().getOperator()) {
case "==":
case "<>":
case "!=":
case "<":
case ">":
case "<=":
case "=<":
case ">=":
case "=>":
final Collection<VariableRef> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1());
referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2()));
boolean isSimple = true;
if(referencedLoadStoreVariables.size() > 0) {
// Found referenced load/store variables
// Examine all statements between the conditionAssignment and conditionalJump for modifications
final StatementInfos statementInfos = getProgram().getStatementInfos();
Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos);
for(Statement statementBetween : statementsBetween) {
for(VariableRef referencedLoadStoreVariable : referencedLoadStoreVariables) {
if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable)) {
// A referenced load/store-variable is modified in a statement between the assignment and the condition!
isSimple = false;
getLog().append("Condition not simple " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
// TODO: Introduce intermediate variable copy of the load/store-variable and use that in the condition!
}
}
}
}
}
if(isSimple) {
conditionalJump.setrValue1(conditionAssignment.getrValue1());
conditionalJump.setOperator(conditionAssignment.getOperator());
conditionalJump.setrValue2(conditionAssignment.getrValue2());
simpleConditionVars.add(conditionVar);
getLog().append("Simple Condition " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
break;
}
default:
if(isSimple) {
conditionalJump.setrValue1(conditionAssignment.getrValue1());
conditionalJump.setOperator(conditionAssignment.getOperator());
conditionalJump.setrValue2(conditionAssignment.getrValue2());
simpleConditionVars.add(conditionVar);
getLog().append("Simple Condition " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
break;
}
default:
}
}
}
}
@ -103,6 +102,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
/**
* Get all referenced load/store variables in an RValue
*
* @param rValue The RValue
* @return All referenced load/store variables
*/