From 2961c84bd7184c7f4528576a43fc80b12f44db83 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 23 Feb 2020 10:04:51 +0100 Subject: [PATCH] Working on improving the condition simplification. --- .../kickc/model/VariableReferenceInfos.java | 33 +++++-- .../Pass2ConditionalJumpSimplification.java | 92 +++++++++---------- 2 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index d830a1ecf..8774450b0 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -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 refs = symbolVarReferences.get(variableRef); + final Collection 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 getVarDefineStatements(VariableRef varRef) { LinkedHashSet stmts = new LinkedHashSet<>(); + Collection refs = symbolVarReferences.get(varRef); if(refs != null) { - Optional 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; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java index 7b4a29f4c..cb1c030d2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java @@ -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 assignments = getAllAssignments(); final Map> usages = getAllUsages(); - final List simpleConditionVars = getSimpleConditions(assignments, usages); + final List simpleConditionVars = getSimpleConditions(usages); removeAssignments(getGraph(), simpleConditionVars); deleteSymbols(getScope(), simpleConditionVars); return (simpleConditionVars.size() > 0); } - private List getSimpleConditions(final Map assignments, final Map> usages) { - + private List getSimpleConditions(final Map> usages) { + final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos(); final List 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 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 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 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 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 */