1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-23 08:32:39 +00:00

Eliminated redundant methods got getting assignments/usages in Pass2SsaOptimization.

This commit is contained in:
jespergravgaard 2020-02-23 19:26:53 +01:00
parent 2961c84bd7
commit 6862698fb7
4 changed files with 122 additions and 154 deletions

View File

@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -10,9 +11,14 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.values.*; import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
/** /**
* Compiler Pass rewriting conditional jumps that use && or || operators * Compiler Pass rewriting conditional jumps that use && or || operators
@ -25,12 +31,10 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
@Override @Override
public boolean step() { public boolean step() {
Map<LValue, StatementAssignment> assignments = getAllAssignments();
Map<RValue, List<Statement>> usages = getAllUsages();
boolean done = false; boolean done = false;
boolean modified = false; boolean modified = false;
while(!done) { while(!done) {
VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition(assignments, usages); VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition();
if(obsoleteConditionVar != null) { if(obsoleteConditionVar != null) {
Collection<VariableRef> obsoleteVars = new ArrayList<>(); Collection<VariableRef> obsoleteVars = new ArrayList<>();
obsoleteVars.add(obsoleteConditionVar); obsoleteVars.add(obsoleteConditionVar);
@ -47,19 +51,26 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
/** /**
* Look through the entire program looking for an if() condition that uses &&, || or !. * Look through the entire program looking for an if() condition that uses &&, || or !.
* When found rewrite it (adding blocks) * When found rewrite it (adding blocks)
*
* @return Null if no condition was found to rewrite. The now obsolete variable containing the && / || / ! to be removed. * @return Null if no condition was found to rewrite. The now obsolete variable containing the && / || / ! to be removed.
*/ */
private VariableRef findAndRewriteBooleanCondition(Map<LValue, StatementAssignment> assignments, Map<RValue, List<Statement>> usages) { private VariableRef findAndRewriteBooleanCondition() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
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) {
StatementConditionalJump conditional = (StatementConditionalJump) statement; StatementConditionalJump conditional = (StatementConditionalJump) statement;
if(conditional.getrValue1()==null && conditional.getOperator()==null) { if(conditional.getrValue1() == null && conditional.getOperator() == null) {
RValue conditionRValue = conditional.getrValue2(); RValue conditionRValue = conditional.getrValue2();
if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size() == 1) { if(conditionRValue instanceof VariableRef) {
final int conditionRValueUsages = variableReferenceInfos.getVarUseStatements((VariableRef) conditionRValue).size();
if(conditionRValueUsages == 1) {
VariableRef conditionVar = (VariableRef) conditionRValue; VariableRef conditionVar = (VariableRef) conditionRValue;
StatementAssignment conditionAssignment = assignments.get(conditionVar); final Integer conditionDefineStatementIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionAssignment!=null) { if(conditionDefineStatementIdx != null) {
final Statement conditionDefineStatement = getGraph().getStatementByIndex(conditionDefineStatementIdx);
if(conditionDefineStatement instanceof StatementAssignment) {
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStatement;
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) { if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx } // Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
rewriteLogicAnd(block, conditional, conditionAssignment); rewriteLogicAnd(block, conditional, conditionAssignment);
@ -79,18 +90,21 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
} }
} }
} }
}
}
return null; return null;
} }
/** /**
* Rewrite logical && condition if(c1&&c2) { xx } to if(c1) if(c2) { xx } * Rewrite logical && condition if(c1&&c2) { xx } to if(c1) if(c2) { xx }
*
* @param block The block containing the current if() * @param block The block containing the current if()
* @param conditional The if()-statement * @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable. * @param conditionAssignment The assignment defining the condition variable.
*/ */
private void rewriteLogicAnd(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) { private void rewriteLogicAnd(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
// Found an if with a logical && condition - rewrite to if(c1) if(c2) { xx } // Found an if with a logical && condition - rewrite to if(c1) if(c2) { xx }
getLog().append("Rewriting && if()-condition to two if()s "+conditionAssignment.toString(getProgram(), false)); getLog().append("Rewriting && if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
ScopeRef currentScopeRef = block.getScope(); ScopeRef currentScopeRef = block.getScope();
Scope currentScope = getScope().getScope(currentScopeRef); Scope currentScope = getScope().getScope(currentScopeRef);
// Add a new block containing the second part of the && condition expression // Add a new block containing the second part of the && condition expression
@ -118,12 +132,13 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
/** /**
* Rewrite logical || condition if(c1||c2) { xx } to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end: * Rewrite logical || condition if(c1||c2) { xx } to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end:
*
* @param block The block containing the current if() * @param block The block containing the current if()
* @param conditional The if()-statement * @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable. * @param conditionAssignment The assignment defining the condition variable.
*/ */
private void rewriteLogicOr(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) { private void rewriteLogicOr(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
getLog().append("Rewriting || if()-condition to two if()s "+conditionAssignment.toString(getProgram(), false)); getLog().append("Rewriting || if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
ScopeRef currentScopeRef = block.getScope(); ScopeRef currentScopeRef = block.getScope();
Scope currentScope = getScope().getScope(currentScopeRef); Scope currentScope = getScope().getScope(currentScopeRef);
// Add a new block containing the second part of the && condition expression // Add a new block containing the second part of the && condition expression
@ -174,12 +189,13 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
/** /**
* Rewrite logical ! condition if(!c1) { xx } to if(c1) goto end else goto x, x:{ xx } end: * Rewrite logical ! condition if(!c1) { xx } to if(c1) goto end else goto x, x:{ xx } end:
*
* @param block The block containing the current if() * @param block The block containing the current if()
* @param conditional The if()-statement * @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable. * @param conditionAssignment The assignment defining the condition variable.
*/ */
private void rewriteLogicNot(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) { private void rewriteLogicNot(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
getLog().append("Rewriting ! if()-condition to reversed if() "+conditionAssignment.toString(getProgram(), false)); getLog().append("Rewriting ! if()-condition to reversed if() " + conditionAssignment.toString(getProgram(), false));
// Rewrite the conditional to use only the first part of the && condition expression // Rewrite the conditional to use only the first part of the && condition expression
LabelRef defaultSuccessor = block.getDefaultSuccessor(); LabelRef defaultSuccessor = block.getDefaultSuccessor();
LabelRef conditionalSuccessor = block.getConditionalSuccessor(); LabelRef conditionalSuccessor = block.getConditionalSuccessor();

View File

@ -7,13 +7,14 @@ 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.symbols.Variable;
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;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.stream.Collectors;
/** /**
* Compiler Pass simplifying conditional jumps that are simple comparisons * Compiler Pass simplifying conditional jumps that are simple comparisons
@ -26,14 +27,13 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
@Override @Override
public boolean step() { public boolean step() {
final Map<RValue, List<Statement>> usages = getAllUsages(); final List<VariableRef> simpleConditionVars = getSimpleConditions();
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<RValue, List<Statement>> usages) { private List<VariableRef> getSimpleConditions() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos(); 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()) {
@ -42,10 +42,11 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement; StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) { if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) {
RValue conditionRValue = conditionalJump.getrValue2(); RValue conditionRValue = conditionalJump.getrValue2();
if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size() == 1) { if(conditionRValue instanceof VariableRef) {
VariableRef conditionVar = (VariableRef) conditionRValue; VariableRef conditionVar = (VariableRef) conditionRValue;
final Collection<Integer> conditionRvalueUsages = variableReferenceInfos.getVarUseStatements(conditionVar);
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar); final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionDefineStmtIdx != null) { if(conditionRvalueUsages.size() == 1 && conditionDefineStmtIdx != null) {
final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx); final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
if(conditionDefineStmt instanceof StatementAssignment && ((StatementAssignment) conditionDefineStmt).getOperator() != null) { if(conditionDefineStmt instanceof StatementAssignment && ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStmt; StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStmt;
@ -59,7 +60,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
case "=<": case "=<":
case ">=": case ">=":
case "=>": case "=>":
final Collection<VariableRef> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1()); final Collection<Variable> referencedLoadStoreVariables = getReferencedLoadStoreVariables(conditionAssignment.getrValue1());
referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2())); referencedLoadStoreVariables.addAll(getReferencedLoadStoreVariables(conditionAssignment.getrValue2()));
boolean isSimple = true; boolean isSimple = true;
if(referencedLoadStoreVariables.size() > 0) { if(referencedLoadStoreVariables.size() > 0) {
@ -68,8 +69,8 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
final StatementInfos statementInfos = getProgram().getStatementInfos(); final StatementInfos statementInfos = getProgram().getStatementInfos();
Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos); Collection<Statement> statementsBetween = getGraph().getStatementsBetween(conditionAssignment, conditionalJump, statementInfos);
for(Statement statementBetween : statementsBetween) { for(Statement statementBetween : statementsBetween) {
for(VariableRef referencedLoadStoreVariable : referencedLoadStoreVariables) { for(Variable referencedLoadStoreVariable : referencedLoadStoreVariables) {
if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable)) { if(variableReferenceInfos.getDefinedVars(statementBetween).contains(referencedLoadStoreVariable.getVariableRef())) {
// A referenced load/store-variable is modified in a statement between the assignment and the condition! // A referenced load/store-variable is modified in a statement between the assignment and the condition!
isSimple = false; isSimple = false;
getLog().append("Condition not simple " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false)); getLog().append("Condition not simple " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram(), false));
@ -106,14 +107,12 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
* @param rValue The RValue * @param rValue The RValue
* @return All referenced load/store variables * @return All referenced load/store variables
*/ */
private Collection<VariableRef> getReferencedLoadStoreVariables(RValue rValue) { private Collection<Variable> getReferencedLoadStoreVariables(RValue rValue) {
List<VariableRef> referencedLoadStoreVariables = new ArrayList<>(); return VariableReferenceInfos.getReferencedVars(rValue)
final Collection<VariableRef> vars1 = VariableReferenceInfos.getReferencedVars(rValue); .stream()
for(VariableRef variableRef : vars1) { .map(variableRef -> getScope().getVariable(variableRef))
if(getScope().getVariable(variableRef).isKindLoadStore()) .filter(Variable::isKindLoadStore)
referencedLoadStoreVariables.add(variableRef); .collect(Collectors.toList());
}
return referencedLoadStoreVariables;
} }
} }

View File

@ -127,62 +127,5 @@ public abstract class Pass2SsaOptimization extends Pass1Base implements PassStep
} }
} }
public Map<LValue, StatementAssignment> getAllAssignments() {
final HashMap<LValue, StatementAssignment> assignments = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
assignments.put(assignment.getlValue(), assignment);
return null;
}
};
visitor.visitGraph(getGraph());
return assignments;
}
public Map<RValue, List<Statement>> getAllUsages() {
final HashMap<RValue, List<Statement>> usages = new LinkedHashMap<>();
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
addUsage(assignment.getrValue1(), assignment);
addUsage(assignment.getrValue2(), assignment);
return null;
}
@Override
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
addUsage(conditionalJump.getrValue1(), conditionalJump);
addUsage(conditionalJump.getrValue2(), conditionalJump);
return null;
}
@Override
public Void visitPhiBlock(StatementPhiBlock phi) {
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
addUsage(phiRValue.getrValue(), phi);
}
}
return null;
}
private void addUsage(RValue rValue, Statement statement) {
if(rValue == null) {
return;
}
List<Statement> use = usages.get(rValue);
if(use == null) {
use = new ArrayList<>();
usages.put(rValue, use);
}
use.add(statement);
}
};
visitor.visitGraph(getGraph());
return usages;
}
} }

View File

@ -1,14 +1,15 @@
package dk.camelot64.kickc.passes; package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*; import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Compiler Pass simplifying unary not variables if they reference a comparison that can be inverted * Compiler Pass simplifying unary not variables if they reference a comparison that can be inverted
@ -20,38 +21,43 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
} }
/** /**
* Eliminate unary nots if they are the only usage of a reversable comparison * Eliminate unary nots if they are the only usage of a reversible comparison
*/ */
@Override @Override
public boolean step() { public boolean step() {
final VariableReferenceInfos usages = getProgram().getVariableReferenceInfos(); final List<VariableRef> unusedComparisons = optimizeUnaryNots();
final Map<LValue, StatementAssignment> assignments = getAllAssignments();
final List<VariableRef> unusedComparisons = optimizeUnaryNots(assignments, usages);
removeAssignments(getGraph(), unusedComparisons); removeAssignments(getGraph(), unusedComparisons);
deleteSymbols(getScope(), unusedComparisons); deleteSymbols(getScope(), unusedComparisons);
return (unusedComparisons.size() > 0); return (unusedComparisons.size() > 0);
} }
/** /**
* Examine all unary nots. If they are the only usage of a reversable unary not replace the unary not with the reversed comparison - and eliminate the riginal variable. * Examine all unary nots. If they are the only usage of a reversible unary not replace the unary not with the reversed comparison - and eliminate the original variable.
* *
* @param assignments Assignments to examine * @param assignments Assignments to examine
* @param usages All variable usages * @param usages All variable usages
* @return Unused comparisons (because they have been replaced with reversed comparisions) * @return Unused comparisons (because they have been replaced with reversed comparisons)
*/ */
private List<VariableRef> optimizeUnaryNots(final Map<LValue, StatementAssignment> assignments, VariableReferenceInfos usages) { private List<VariableRef> optimizeUnaryNots() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
final List<VariableRef> unused = new ArrayList<>(); final List<VariableRef> unused = new ArrayList<>();
for(StatementAssignment assignment : assignments.values()) { for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getrValue1() == null if(assignment.getrValue1() == null
&& assignment.getOperator() != null && assignment.getOperator() != null
&& ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator())) && ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator()))
&& assignment.getrValue2() instanceof VariableRef && assignment.getrValue2() instanceof VariableRef
) { ) {
VariableRef tempVar = (VariableRef) assignment.getrValue2(); VariableRef tempVar = (VariableRef) assignment.getrValue2();
StatementAssignment tempAssignment = assignments.get(tempVar); final Integer tempVarDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(tempVar);
int tempVarUsages = usages.getVarUseStatements(tempVar).size(); if(tempVarDefineStmtIdx != null) {
if(tempVarUsages == 1 && tempAssignment!=null && tempAssignment.getOperator() != null) { final Statement tempVarDefineStmt = getGraph().getStatementByIndex(tempVarDefineStmtIdx);
if(tempVarDefineStmt instanceof StatementAssignment) {
StatementAssignment tempAssignment = (StatementAssignment) tempVarDefineStmt;
int tempVarUsages = variableReferenceInfos.getVarUseStatements(tempVar).size();
if(tempVarUsages == 1 && tempAssignment.getOperator() != null) {
switch(tempAssignment.getOperator().getOperator()) { switch(tempAssignment.getOperator().getOperator()) {
case "<": case "<":
createInverse(">=", assignment, tempAssignment); createInverse(">=", assignment, tempAssignment);
@ -89,6 +95,10 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
} }
} }
} }
}
}
}
}
return unused; return unused;
} }