mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Working on improving the condition simplification.
This commit is contained in:
parent
5ffae4d92a
commit
2961c84bd7
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user