mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-27 04:49:27 +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.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,31 +51,40 @@ 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) {
|
||||||
VariableRef conditionVar = (VariableRef) conditionRValue;
|
final int conditionRValueUsages = variableReferenceInfos.getVarUseStatements((VariableRef) conditionRValue).size();
|
||||||
StatementAssignment conditionAssignment = assignments.get(conditionVar);
|
if(conditionRValueUsages == 1) {
|
||||||
if(conditionAssignment!=null) {
|
VariableRef conditionVar = (VariableRef) conditionRValue;
|
||||||
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
|
final Integer conditionDefineStatementIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
|
||||||
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
|
if(conditionDefineStatementIdx != null) {
|
||||||
rewriteLogicAnd(block, conditional, conditionAssignment);
|
final Statement conditionDefineStatement = getGraph().getStatementByIndex(conditionDefineStatementIdx);
|
||||||
return conditionVar;
|
if(conditionDefineStatement instanceof StatementAssignment) {
|
||||||
} else if(Operators.LOGIC_OR.equals(conditionAssignment.getOperator())) {
|
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStatement;
|
||||||
// Found if() with logical || condition - rewrite to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end:
|
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
|
||||||
rewriteLogicOr(block, conditional, conditionAssignment);
|
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
|
||||||
return conditionVar;
|
rewriteLogicAnd(block, conditional, conditionAssignment);
|
||||||
} else if(Operators.LOGIC_NOT.equals(conditionAssignment.getOperator())) {
|
return conditionVar;
|
||||||
// Found if() with logical ! condition - rewrite to if(!c1) goto x else goto end, x:{ xx } end:
|
} else if(Operators.LOGIC_OR.equals(conditionAssignment.getOperator())) {
|
||||||
rewriteLogicNot(block, conditional, conditionAssignment);
|
// Found if() with logical || condition - rewrite to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end:
|
||||||
return conditionVar;
|
rewriteLogicOr(block, conditional, conditionAssignment);
|
||||||
|
return conditionVar;
|
||||||
|
} else if(Operators.LOGIC_NOT.equals(conditionAssignment.getOperator())) {
|
||||||
|
// Found if() with logical ! condition - rewrite to if(!c1) goto x else goto end, x:{ xx } end:
|
||||||
|
rewriteLogicNot(block, conditional, conditionAssignment);
|
||||||
|
return conditionVar;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,13 +97,14 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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();
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
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,71 +21,80 @@ 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()) {
|
||||||
if(assignment.getrValue1() == null
|
for(Statement statement : block.getStatements()) {
|
||||||
&& assignment.getOperator() != null
|
if(statement instanceof StatementAssignment) {
|
||||||
&& ("!".equals(assignment.getOperator().getOperator()) || "not".equals(assignment.getOperator().getOperator()))
|
StatementAssignment assignment = (StatementAssignment) statement;
|
||||||
&& assignment.getrValue2() instanceof VariableRef
|
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();
|
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);
|
||||||
switch(tempAssignment.getOperator().getOperator()) {
|
if(tempVarDefineStmt instanceof StatementAssignment) {
|
||||||
case "<":
|
StatementAssignment tempAssignment = (StatementAssignment) tempVarDefineStmt;
|
||||||
createInverse(">=", assignment, tempAssignment);
|
int tempVarUsages = variableReferenceInfos.getVarUseStatements(tempVar).size();
|
||||||
unused.add(tempVar);
|
if(tempVarUsages == 1 && tempAssignment.getOperator() != null) {
|
||||||
break;
|
switch(tempAssignment.getOperator().getOperator()) {
|
||||||
case ">":
|
case "<":
|
||||||
createInverse("<=", assignment, tempAssignment);
|
createInverse(">=", assignment, tempAssignment);
|
||||||
unused.add(tempVar);
|
unused.add(tempVar);
|
||||||
break;
|
break;
|
||||||
case "<=":
|
case ">":
|
||||||
case "=<":
|
createInverse("<=", assignment, tempAssignment);
|
||||||
createInverse(">", assignment, tempAssignment);
|
unused.add(tempVar);
|
||||||
unused.add(tempVar);
|
break;
|
||||||
break;
|
case "<=":
|
||||||
case ">=":
|
case "=<":
|
||||||
case "=>":
|
createInverse(">", assignment, tempAssignment);
|
||||||
createInverse("<", assignment, tempAssignment);
|
unused.add(tempVar);
|
||||||
unused.add(tempVar);
|
break;
|
||||||
break;
|
case ">=":
|
||||||
case "==":
|
case "=>":
|
||||||
createInverse("!=", assignment, tempAssignment);
|
createInverse("<", assignment, tempAssignment);
|
||||||
unused.add(tempVar);
|
unused.add(tempVar);
|
||||||
break;
|
break;
|
||||||
case "!=":
|
case "==":
|
||||||
case "<>":
|
createInverse("!=", assignment, tempAssignment);
|
||||||
createInverse("==", assignment, tempAssignment);
|
unused.add(tempVar);
|
||||||
unused.add(tempVar);
|
break;
|
||||||
break;
|
case "!=":
|
||||||
case "!":
|
case "<>":
|
||||||
case "not":
|
createInverse("==", assignment, tempAssignment);
|
||||||
createInverse(null, assignment, tempAssignment);
|
unused.add(tempVar);
|
||||||
unused.add(tempVar);
|
break;
|
||||||
break;
|
case "!":
|
||||||
|
case "not":
|
||||||
|
createInverse(null, assignment, tempAssignment);
|
||||||
|
unused.add(tempVar);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user