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.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.statements.Statement;
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.symbols.Label;
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
@ -25,12 +31,10 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
@Override
public boolean step() {
Map<LValue, StatementAssignment> assignments = getAllAssignments();
Map<RValue, List<Statement>> usages = getAllUsages();
boolean done = false;
boolean modified = false;
while(!done) {
VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition(assignments, usages);
VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition();
if(obsoleteConditionVar != null) {
Collection<VariableRef> obsoleteVars = new ArrayList<>();
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 !.
* When found rewrite it (adding blocks)
*
* @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(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditional = (StatementConditionalJump) statement;
if(conditional.getrValue1() == null && conditional.getOperator() == null) {
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;
StatementAssignment conditionAssignment = assignments.get(conditionVar);
if(conditionAssignment!=null) {
final Integer conditionDefineStatementIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
if(conditionDefineStatementIdx != null) {
final Statement conditionDefineStatement = getGraph().getStatementByIndex(conditionDefineStatementIdx);
if(conditionDefineStatement instanceof StatementAssignment) {
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStatement;
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
rewriteLogicAnd(block, conditional, conditionAssignment);
@ -79,11 +90,14 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
}
}
}
}
}
return null;
}
/**
* Rewrite logical && condition if(c1&&c2) { xx } to if(c1) if(c2) { xx }
*
* @param block The block containing the current if()
* @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.
@ -118,6 +132,7 @@ 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:
*
* @param block The block containing the current if()
* @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.
@ -174,6 +189,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
/**
* 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 conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.

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

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;
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.values.LValue;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 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
public boolean step() {
final VariableReferenceInfos usages = getProgram().getVariableReferenceInfos();
final Map<LValue, StatementAssignment> assignments = getAllAssignments();
final List<VariableRef> unusedComparisons = optimizeUnaryNots(assignments, usages);
final List<VariableRef> unusedComparisons = optimizeUnaryNots();
removeAssignments(getGraph(), unusedComparisons);
deleteSymbols(getScope(), unusedComparisons);
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 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<>();
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
&& assignment.getOperator() != null
&& ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator()))
&& assignment.getrValue2() instanceof VariableRef
) {
VariableRef tempVar = (VariableRef) assignment.getrValue2();
StatementAssignment tempAssignment = assignments.get(tempVar);
int tempVarUsages = usages.getVarUseStatements(tempVar).size();
if(tempVarUsages == 1 && tempAssignment!=null && tempAssignment.getOperator() != null) {
final Integer tempVarDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(tempVar);
if(tempVarDefineStmtIdx != 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()) {
case "<":
createInverse(">=", assignment, tempAssignment);
@ -89,6 +95,10 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
}
}
}
}
}
}
}
return unused;
}