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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user