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:
parent
2961c84bd7
commit
6862698fb7
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user