1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-15 13:27:36 +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.model.values.*;
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos; 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; 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 * @param variableRef The variable to look for
* @return Index of the defining statement * @return Index of the defining statement
*/ */
public Integer getVarDefineStatement(VariableRef variableRef) { 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<>(); LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
if(refs != null) { if(refs != null) {
Optional<ReferenceToSymbolVar> refDefine = refs.stream() refs.stream()
.filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement) .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
.filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.DEFINE.equals(referenceToSymbolVar.getReferenceType())) .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.DEFINE.equals(referenceToSymbolVar.getReferenceType()))
.findFirst(); .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).statementIdx));
if(refDefine.isPresent()) {
return ((ReferenceInStatement) refDefine.get()).getStatementIdx();
}
} }
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.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementConditionalJump; import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementInfos; 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.RValue;
import dk.camelot64.kickc.model.values.VariableRef; import dk.camelot64.kickc.model.values.VariableRef;
@@ -27,19 +26,16 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
@Override @Override
public boolean step() { public boolean step() {
final Map<LValue, StatementAssignment> assignments = getAllAssignments();
final Map<RValue, List<Statement>> usages = getAllUsages(); final Map<RValue, List<Statement>> usages = getAllUsages();
final List<VariableRef> simpleConditionVars = getSimpleConditions(assignments, usages); final List<VariableRef> simpleConditionVars = getSimpleConditions(usages);
removeAssignments(getGraph(), simpleConditionVars); removeAssignments(getGraph(), simpleConditionVars);
deleteSymbols(getScope(), simpleConditionVars); deleteSymbols(getScope(), simpleConditionVars);
return (simpleConditionVars.size() > 0); 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<>(); final List<VariableRef> simpleConditionVars = new ArrayList<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) { for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) { for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) { if(statement instanceof StatementConditionalJump) {
@@ -48,49 +44,52 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
RValue conditionRValue = conditionalJump.getrValue2(); RValue conditionRValue = conditionalJump.getrValue2();
if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size() == 1) { if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size() == 1) {
VariableRef conditionVar = (VariableRef) conditionRValue; VariableRef conditionVar = (VariableRef) conditionRValue;
StatementAssignment conditionAssignment = assignments.get(conditionVar); final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionAssignment != null && conditionAssignment.getOperator() != null) { if(conditionDefineStmtIdx != null) {
switch(conditionAssignment.getOperator().getOperator()) { final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
case "==": if(conditionDefineStmt instanceof StatementAssignment && ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
case "<>": StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStmt;
case "!=": switch(conditionAssignment.getOperator().getOperator()) {
case "<": case "==":
case ">": case "<>":
case "<=": case "!=":
case "=<": case "<":
case ">=": case ">":
case "=>": case "<=":
final Collection<VariableRef> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1()); case "=<":
referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2())); case ">=":
boolean isSimple = true; case "=>":
if(referencedLoadStoreVariables.size() > 0) { final Collection<VariableRef> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1());
// Found referenced load/store variables referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2()));
// Examine all statements between the conditionAssignment and conditionalJump for modifications boolean isSimple = true;
final StatementInfos statementInfos = getProgram().getStatementInfos(); if(referencedLoadStoreVariables.size() > 0) {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos(); // Found referenced load/store variables
Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos); // Examine all statements between the conditionAssignment and conditionalJump for modifications
for(Statement statementBetween : statementsBetween) { final StatementInfos statementInfos = getProgram().getStatementInfos();
for(VariableRef referencedLoadStoreVariable : referencedLoadStoreVariables) { Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos);
if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable)) { for(Statement statementBetween : statementsBetween) {
// A referenced load/store-variable is modified in a statement between the assignment and the condition! for(VariableRef referencedLoadStoreVariable : referencedLoadStoreVariables) {
isSimple = false; if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable)) {
getLog().append("Condition not simple " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false)); // 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) {
if(isSimple) { conditionalJump.setrValue1(conditionAssignment.getrValue1());
conditionalJump.setrValue1(conditionAssignment.getrValue1()); conditionalJump.setOperator(conditionAssignment.getOperator());
conditionalJump.setOperator(conditionAssignment.getOperator()); conditionalJump.setrValue2(conditionAssignment.getrValue2());
conditionalJump.setrValue2(conditionAssignment.getrValue2()); simpleConditionVars.add(conditionVar);
simpleConditionVars.add(conditionVar); getLog().append("Simple Condition " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
getLog().append("Simple Condition " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false)); break;
break; }
} default:
default: }
} }
} }
} }
@@ -103,6 +102,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
/** /**
* Get all referenced load/store variables in an RValue * Get all referenced load/store variables in an RValue
*
* @param rValue The RValue * @param rValue The RValue
* @return All referenced load/store variables * @return All referenced load/store variables
*/ */