mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-01 00:51:12 +00:00
Made statement loops simpler.
This commit is contained in:
parent
c78b8c59b1
commit
55bec51f09
@ -74,10 +74,8 @@ public class ControlFlowGraph implements Graph {
|
||||
* Clear all statement indices,
|
||||
*/
|
||||
public void clearStatementIndices() {
|
||||
for(var block : getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
statement.setIndex(null);
|
||||
}
|
||||
for (Statement statement : getAllStatements()) {
|
||||
statement.setIndex(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,11 +62,9 @@ public interface Graph {
|
||||
* @return The statement
|
||||
*/
|
||||
default Statement getStatementByIndex(int statementIdx) {
|
||||
for(Graph.Block block : getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement.getIndex() != null && statementIdx == statement.getIndex()) {
|
||||
return statement;
|
||||
}
|
||||
for (Statement statement : getAllStatements()) {
|
||||
if (statement.getIndex() != null && statementIdx == statement.getIndex()) {
|
||||
return statement;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -45,10 +45,8 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
|
||||
this.referenceInfo = referenceInfo;
|
||||
this.blockSuccessorClosure = blockSuccessorClosure;
|
||||
this.statementLiveVariables = new LinkedHashMap<>();
|
||||
for(Graph.Block block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex()));
|
||||
}
|
||||
for (Statement statement : program.getGraph().getAllStatements()) {
|
||||
statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,16 +24,14 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if(lValue instanceof LvalueIntermediate) {
|
||||
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
|
||||
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getProgramScope());
|
||||
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
|
||||
throw new CompileError("LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if(lValue instanceof LvalueIntermediate) {
|
||||
VariableRef intermediateVar = ((LvalueIntermediate) lValue).getVariable();
|
||||
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(intermediateVar, getGraph(), getProgramScope());
|
||||
final VarAssignments.VarAssignment varAssignment = varAssignments.get(0);
|
||||
throw new CompileError("LValue is illegal. " + statement + " - definition of lValue " + varAssignment, varAssignment.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,16 @@ public class Pass1AssertNoModifyVars extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
StatementLValue statementLValue = (StatementLValue) statement;
|
||||
if(!statementLValue.isInitialAssignment() && statementLValue.getlValue() instanceof VariableRef) {
|
||||
Variable assignedVar = getProgramScope().getVariable((VariableRef) statementLValue.getlValue());
|
||||
if(assignedVar.isNoModify())
|
||||
throw new CompileError("const variable may not be modified! " + assignedVar.toString(), statement);
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if (statement instanceof StatementLValue) {
|
||||
StatementLValue statementLValue = (StatementLValue) statement;
|
||||
if (!statementLValue.isInitialAssignment()
|
||||
&& statementLValue.getlValue() instanceof VariableRef) {
|
||||
Variable assignedVar = getProgramScope().getVariable(
|
||||
(VariableRef) statementLValue.getlValue());
|
||||
if (assignedVar.isNoModify()) {
|
||||
throw new CompileError(
|
||||
"const variable may not be modified! " + assignedVar.toString(), statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,29 +26,31 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
|
||||
getProgram().clearControlFlowBlockSuccessorClosure();
|
||||
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
|
||||
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCall) {
|
||||
final ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();
|
||||
final Procedure procedure = getProgramScope().getProcedure(procedureRef);
|
||||
if(SymbolType.VOID.equals(procedure.getReturnType())) {
|
||||
// Found a call to a VOID returning procedure
|
||||
final LValue lValue = ((StatementCall) statement).getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef tmpVar = (VariableRef) lValue;
|
||||
final Collection<Integer> usages = referenceInfos.getVarUseStatements(tmpVar);
|
||||
if(usages.size() > 0) {
|
||||
final Integer usageIdx = usages.iterator().next();
|
||||
final Statement usage = getProgram().getStatementInfos().getStatement(usageIdx);
|
||||
throw new CompileError("Function " + procedure.getLocalName() + " does not return a value! ", usage);
|
||||
} else {
|
||||
// Delete the temporary variable
|
||||
final Variable var = getProgramScope().getVar(tmpVar);
|
||||
var.getScope().remove(var);
|
||||
// And remove the lValue
|
||||
((StatementCall) statement).setlValue(null);
|
||||
if(getLog().isVerbosePass1CreateSsa())
|
||||
getLog().append("Removing LValue from call to function returning void");
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if (statement instanceof StatementCall) {
|
||||
final ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();
|
||||
final Procedure procedure = getProgramScope().getProcedure(procedureRef);
|
||||
if (SymbolType.VOID.equals(procedure.getReturnType())) {
|
||||
// Found a call to a VOID returning procedure
|
||||
final LValue lValue = ((StatementCall) statement).getlValue();
|
||||
if (lValue instanceof VariableRef) {
|
||||
VariableRef tmpVar = (VariableRef) lValue;
|
||||
final Collection<Integer> usages = referenceInfos.getVarUseStatements(tmpVar);
|
||||
if (usages.size() > 0) {
|
||||
final Integer usageIdx = usages.iterator().next();
|
||||
final Statement usage = getProgram().getStatementInfos()
|
||||
.getStatement(usageIdx);
|
||||
throw new CompileError(
|
||||
"Function " + procedure.getLocalName() + " does not return a value! ",
|
||||
usage);
|
||||
} else {
|
||||
// Delete the temporary variable
|
||||
final Variable var = getProgramScope().getVar(tmpVar);
|
||||
var.getScope().remove(var);
|
||||
// And remove the lValue
|
||||
((StatementCall) statement).setlValue(null);
|
||||
if (getLog().isVerbosePass1CreateSsa()) {
|
||||
getLog().append("Removing LValue from call to function returning void");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +75,8 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
|
||||
}
|
||||
}
|
||||
// Remove the statements
|
||||
for(var allBlock : getGraph().getAllBlocks()) {
|
||||
allBlock.getStatements().removeIf(removeStmt::contains);
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
block.getStatements().removeIf(removeStmt::contains);
|
||||
}
|
||||
// Replace all variable refs with constant refs
|
||||
ProgramValueIterator.execute(getProgram(), new AliasReplacer(aliases));
|
||||
|
@ -46,14 +46,11 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
|
||||
*/
|
||||
public static Set<ProcedureRef> getAllCalledProcedures(Graph graph) {
|
||||
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
|
||||
for(Graph.Block block : graph.getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCalling) {
|
||||
StatementCalling call = (StatementCalling) statement;
|
||||
for(var statement : graph.getAllStatements()) {
|
||||
if(statement instanceof StatementCalling call) {
|
||||
ProcedureRef procedureRef = call.getProcedure();
|
||||
calledProcedures.add(procedureRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
return calledProcedures;
|
||||
}
|
||||
|
@ -49,20 +49,21 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
* Version all non-versioned non-intermediary being assigned a value.
|
||||
*/
|
||||
private void versionAllAssignments() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
StatementLValue statementLValue = (StatementLValue) statement;
|
||||
LValue lValue = statementLValue.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
versionAssignment((VariableRef) lValue, new ProgramValue.ProgramValueLValue(statementLValue), statementLValue.getSource());
|
||||
} else if(lValue instanceof ValueList) {
|
||||
List<RValue> lValueList = ((ValueList) lValue).getList();
|
||||
for(int i = 0; i < lValueList.size(); i++) {
|
||||
LValue lVal = (LValue) lValueList.get(i);
|
||||
if(lVal instanceof VariableRef) {
|
||||
versionAssignment((VariableRef) lVal, new ProgramValue.ProgramValueListElement((ValueList) lValue, i), statementLValue.getSource());
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if (statement instanceof StatementLValue statementLValue) {
|
||||
LValue lValue = statementLValue.getlValue();
|
||||
if (lValue instanceof VariableRef) {
|
||||
versionAssignment((VariableRef) lValue,
|
||||
new ProgramValue.ProgramValueLValue(statementLValue),
|
||||
statementLValue.getSource());
|
||||
} else if (lValue instanceof ValueList) {
|
||||
List<RValue> lValueList = ((ValueList) lValue).getList();
|
||||
for (int i = 0; i < lValueList.size(); i++) {
|
||||
LValue lVal = (LValue) lValueList.get(i);
|
||||
if (lVal instanceof VariableRef) {
|
||||
versionAssignment((VariableRef) lVal,
|
||||
new ProgramValue.ProgramValueListElement((ValueList) lValue, i),
|
||||
statementLValue.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,8 +108,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
programValue.set(version.getRef());
|
||||
}
|
||||
// Update map of versions encountered in the block
|
||||
if(currentStmt instanceof StatementLValue && programValue instanceof ProgramValue.ProgramValueLValue) {
|
||||
StatementLValue statementLValue = (StatementLValue) currentStmt;
|
||||
if(currentStmt instanceof StatementLValue statementLValue && programValue instanceof ProgramValue.ProgramValueLValue) {
|
||||
LValue lValue = statementLValue.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
updateBlockVersions((VariableRef) lValue, blockVersions);
|
||||
|
@ -27,21 +27,20 @@ public class Pass1UnrollConditionVariableSsa extends Pass2SsaOptimization {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
final StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
|
||||
if(conditionalJump.isDeclaredUnroll()) {
|
||||
Collection<VariableRef> referencedVars = new LinkedHashSet<>();
|
||||
findAllReferencedVars(referencedVars, conditionalJump.getrValue1());
|
||||
findAllReferencedVars(referencedVars, conditionalJump.getrValue2());
|
||||
for(VariableRef referencedVar : referencedVars) {
|
||||
final Variable variable = getProgramScope().getVariable(referencedVar);
|
||||
if(variable.isKindLoadStore()) {
|
||||
// Convert the variable to versioned if it is load/store
|
||||
getLog().append("Converting unrolled condition variable to single-static-assignment "+variable);
|
||||
variable.setKind(Variable.Kind.PHI_MASTER);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if (statement instanceof final StatementConditionalJump conditionalJump) {
|
||||
if (conditionalJump.isDeclaredUnroll()) {
|
||||
Collection<VariableRef> referencedVars = new LinkedHashSet<>();
|
||||
findAllReferencedVars(referencedVars, conditionalJump.getrValue1());
|
||||
findAllReferencedVars(referencedVars, conditionalJump.getrValue2());
|
||||
for (VariableRef referencedVar : referencedVars) {
|
||||
final Variable variable = getProgramScope().getVariable(referencedVar);
|
||||
if (variable.isKindLoadStore()) {
|
||||
// Convert the variable to versioned if it is load/store
|
||||
getLog().append(
|
||||
"Converting unrolled condition variable to single-static-assignment "
|
||||
+ variable);
|
||||
variable.setKind(Variable.Kind.PHI_MASTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Initializers;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
@ -12,8 +9,10 @@ import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import dk.camelot64.kickc.model.values.CastValue;
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.ValueList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -29,38 +28,34 @@ public class Pass1UnwindStructPrepare extends Pass2SsaOptimization {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getOperator()==null) {
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getProgram().getScope(), assignment.getlValue());
|
||||
RValue rValue = assignment.getrValue2();
|
||||
if(!(rValue instanceof ConstantValue) && lValueType instanceof SymbolTypeStruct) {
|
||||
// TODO: Constantify all R-Values?
|
||||
Initializers.ValueTypeSpec lValueTypeSpec = new Initializers.ValueTypeSpec(lValueType);
|
||||
RValue rValueConstantified = Initializers.constantify(rValue, lValueTypeSpec, getProgram(), assignment.getSource());
|
||||
if(!rValue.equals(rValueConstantified)) {
|
||||
assignment.setrValue2(rValueConstantified);
|
||||
getLog().append("Constantified RValue "+assignment.toString(getProgram(), false));
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(assignment.getOperator()==null) {
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getProgram().getScope(), assignment.getlValue());
|
||||
RValue rValue = assignment.getrValue2();
|
||||
if(!(rValue instanceof ConstantValue) && lValueType instanceof SymbolTypeStruct) {
|
||||
// TODO: Constantify all R-Values?
|
||||
Initializers.ValueTypeSpec lValueTypeSpec = new Initializers.ValueTypeSpec(lValueType);
|
||||
RValue rValueConstantified = Initializers.constantify(rValue, lValueTypeSpec, getProgram(), assignment.getSource());
|
||||
if(!rValue.equals(rValueConstantified)) {
|
||||
assignment.setrValue2(rValueConstantified);
|
||||
getLog().append("Constantified RValue "+assignment.toString(getProgram(), false));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if(statement instanceof StatementCall) {
|
||||
final StatementCall call = (StatementCall) statement;
|
||||
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
|
||||
final List<Variable> paramDefs = procedure.getParameters();
|
||||
final List<RValue> paramVals = call.getParameters();
|
||||
for(int i=0;i<paramDefs.size();i++) {
|
||||
final Variable paramDef = paramDefs.get(i);
|
||||
final RValue paramVal = paramVals.get(i);
|
||||
if(paramDef.getType() instanceof SymbolTypeStruct && paramVal instanceof ValueList) {
|
||||
// Add a cast to the parameter value list
|
||||
paramVals.set(i, new CastValue(paramDef.getType(), paramVal));
|
||||
getLog().append("Added struct type cast to parameter value list "+call.toString(getProgram(), false));
|
||||
}
|
||||
}
|
||||
if(statement instanceof final StatementCall call) {
|
||||
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
|
||||
final List<Variable> paramDefs = procedure.getParameters();
|
||||
final List<RValue> paramVals = call.getParameters();
|
||||
for(int i=0;i<paramDefs.size();i++) {
|
||||
final Variable paramDef = paramDefs.get(i);
|
||||
final RValue paramVal = paramVals.get(i);
|
||||
if(paramDef.getType() instanceof SymbolTypeStruct && paramVal instanceof ValueList) {
|
||||
// Add a cast to the parameter value list
|
||||
paramVals.set(i, new CastValue(paramDef.getType(), paramVal));
|
||||
getLog().append("Added struct type cast to parameter value list "+call.toString(getProgram(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,17 +24,15 @@ public class Pass2AssertSingleAssignment extends Pass2SsaAssertion {
|
||||
|
||||
Map<VariableRef, Statement> assignments = new LinkedHashMap<>();
|
||||
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
checkAssignment(assignments, (VariableRef) lValue, statement);
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
checkAssignment(assignments, phiVariable.getVariable(), statement);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if (statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if (lValue instanceof VariableRef) {
|
||||
checkAssignment(assignments, (VariableRef) lValue, statement);
|
||||
}
|
||||
} else if (statement instanceof StatementPhiBlock) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
checkAssignment(assignments, phiVariable.getVariable(), statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,39 +35,37 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization {
|
||||
*/
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
|
||||
Operator operator = conditionalJump.getOperator();
|
||||
if(operator!=null && conditionalJump.getrValue2() instanceof ConstantValue) {
|
||||
SymbolType valueType = SymbolTypeInference.inferType(getProgramScope(), conditionalJump.getrValue1());
|
||||
ConstantValue constantValue = (ConstantValue) conditionalJump.getrValue2();
|
||||
ConstantLiteral constantLiteral = null;
|
||||
try {
|
||||
constantLiteral = constantValue.calculateLiteral(getProgramScope());
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// Ignore
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
|
||||
Operator operator = conditionalJump.getOperator();
|
||||
if(operator!=null && conditionalJump.getrValue2() instanceof ConstantValue) {
|
||||
SymbolType valueType = SymbolTypeInference.inferType(getProgramScope(), conditionalJump.getrValue1());
|
||||
ConstantValue constantValue = (ConstantValue) conditionalJump.getrValue2();
|
||||
ConstantLiteral constantLiteral = null;
|
||||
try {
|
||||
constantLiteral = constantValue.calculateLiteral(getProgramScope());
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// Ignore
|
||||
}
|
||||
if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
|
||||
// Found > C - rewrite to >= C+1 if possible
|
||||
Long longValue = (Long) constantLiteral.getValue();
|
||||
if(longValue > 0x00L && longValue < 0xffL) {
|
||||
// Rewrite is possible - do it
|
||||
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
|
||||
conditionalJump.setOperator(Operators.GE);
|
||||
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
|
||||
}
|
||||
if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
|
||||
// Found > C - rewrite to >= C+1 if possible
|
||||
Long longValue = (Long) constantLiteral.getValue();
|
||||
if(longValue > 0x00L && longValue < 0xffL) {
|
||||
// Rewrite is possible - do it
|
||||
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
|
||||
conditionalJump.setOperator(Operators.GE);
|
||||
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
|
||||
}
|
||||
}
|
||||
if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
|
||||
// Found <= C - rewrite to < C+1 if possible
|
||||
Long longValue = (Long) constantLiteral.getValue();
|
||||
if(longValue > 0x00L && longValue < 0xffL) {
|
||||
// Rewrite is possible - do it
|
||||
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
|
||||
conditionalJump.setOperator(Operators.LT);
|
||||
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
|
||||
}
|
||||
}
|
||||
if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
|
||||
// Found <= C - rewrite to < C+1 if possible
|
||||
Long longValue = (Long) constantLiteral.getValue();
|
||||
if(longValue > 0x00L && longValue < 0xffL) {
|
||||
// Rewrite is possible - do it
|
||||
getLog().append("Rewriting conditional comparison " + statement.toString(getProgram(), false));
|
||||
conditionalJump.setOperator(Operators.LT);
|
||||
conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,33 +66,29 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
|
||||
private List<SimpleCondition> getSimpleConditionTodos() {
|
||||
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
|
||||
List<SimpleCondition> todos = new ArrayList<>();
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
|
||||
if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) {
|
||||
RValue conditionRValue = conditionalJump.getrValue2();
|
||||
if(conditionRValue instanceof VariableRef) {
|
||||
VariableRef conditionVar = (VariableRef) conditionRValue;
|
||||
final Collection<Integer> conditionRvalueUsages = variableReferenceInfos.getVarUseStatements(conditionVar);
|
||||
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
|
||||
if(conditionRvalueUsages.size() == 1 && 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 "=>":
|
||||
todos.add(new SimpleCondition(conditionalJump, conditionAssignment, conditionVar));
|
||||
default:
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementConditionalJump conditionalJump) {
|
||||
if(conditionalJump.getrValue1() == null && conditionalJump.getOperator() == null) {
|
||||
RValue conditionRValue = conditionalJump.getrValue2();
|
||||
if(conditionRValue instanceof VariableRef conditionVar) {
|
||||
final Collection<Integer> conditionRvalueUsages = variableReferenceInfos.getVarUseStatements(conditionVar);
|
||||
final Integer conditionDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
|
||||
if(conditionRvalueUsages.size() == 1 && conditionDefineStmtIdx != null) {
|
||||
final Statement conditionDefineStmt = getGraph().getStatementByIndex(conditionDefineStmtIdx);
|
||||
if(conditionDefineStmt instanceof StatementAssignment conditionAssignment
|
||||
&& ((StatementAssignment) conditionDefineStmt).getOperator() != null) {
|
||||
switch(conditionAssignment.getOperator().getOperator()) {
|
||||
case "==":
|
||||
case "<>":
|
||||
case "!=":
|
||||
case "<":
|
||||
case ">":
|
||||
case "<=":
|
||||
case "=<":
|
||||
case ">=":
|
||||
case "=>":
|
||||
todos.add(new SimpleCondition(conditionalJump, conditionAssignment, conditionVar));
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,20 +55,18 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
});
|
||||
|
||||
// Examine all assignments - performing constant consolidation for +/-
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
Operator operator = assignment.getOperator();
|
||||
if(operator != null) {
|
||||
switch(operator.getOperator()) {
|
||||
case "+":
|
||||
optimized[0] |= optimizePlus(assignment);
|
||||
break;
|
||||
case "*idx":
|
||||
optimized[0] |= optimizeArrayDeref(assignment);
|
||||
break;
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
Operator operator = assignment.getOperator();
|
||||
if(operator != null) {
|
||||
switch(operator.getOperator()) {
|
||||
case "+":
|
||||
optimized[0] |= optimizePlus(assignment);
|
||||
break;
|
||||
case "*idx":
|
||||
optimized[0] |= optimizeArrayDeref(assignment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
// NULL pointer assigment is OK
|
||||
;
|
||||
else if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) {
|
||||
ConstantLiteral constantLiteral = null;
|
||||
ConstantLiteral<?> constantLiteral = null;
|
||||
try {
|
||||
constantLiteral = constVal.calculateLiteral(getProgramScope());
|
||||
} catch(ConstantNotLiteral e) {
|
||||
@ -92,16 +92,16 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
private static class ConstantVariableValue {
|
||||
|
||||
/** The variable that has been determined to be constant. */
|
||||
private VariableRef variableRef;
|
||||
private final VariableRef variableRef;
|
||||
|
||||
/** The constant value of the variable. */
|
||||
private ConstantValue constantValue;
|
||||
private final ConstantValue constantValue;
|
||||
|
||||
/**
|
||||
* The statement that assigns the variable its value (the assignment will be removed at the end).
|
||||
* Either a {@link StatementAssignment} or a {@link StatementPhiBlock}.
|
||||
*/
|
||||
private Statement assignment;
|
||||
private final Statement assignment;
|
||||
|
||||
public ConstantVariableValue(VariableRef variableRef, ConstantValue constantValue, Statement assignment) {
|
||||
this.variableRef = variableRef;
|
||||
@ -131,39 +131,34 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
final Map<VariableRef, ConstantVariableValue> constants = new LinkedHashMap<>();
|
||||
|
||||
// Look for constants among versions, intermediates & declared constants
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef varRef = (VariableRef) lValue;
|
||||
Variable var = getProgramScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
if(var.getRegister() != null && var.getRegister().isMem())
|
||||
// Skip variables allocated into memory
|
||||
continue;
|
||||
ConstantValue constant = getConstant(assignment.getrValue2());
|
||||
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
|
||||
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef varRef) {
|
||||
Variable var = getProgramScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
if(var.getRegister() != null && var.getRegister().isMem())
|
||||
// Skip variables allocated into memory
|
||||
continue;
|
||||
ConstantValue constant = getConstant(assignment.getrValue2());
|
||||
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
|
||||
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock phi = (StatementPhiBlock) statement;
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if(phiVariable.getValues().size() == 1) {
|
||||
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
|
||||
if(getConstant(phiRValue.getrValue()) != null) {
|
||||
VariableRef varRef = phiVariable.getVariable();
|
||||
Variable var = getProgramScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
ConstantValue constant = getConstant(phiRValue.getrValue());
|
||||
constants.put(varRef, new ConstantVariableValue(varRef, constant, phi));
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock phi) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
if(phiVariable.getValues().size() == 1) {
|
||||
StatementPhiBlock.PhiRValue phiRValue = phiVariable.getValues().get(0);
|
||||
if(getConstant(phiRValue.getrValue()) != null) {
|
||||
VariableRef varRef = phiVariable.getVariable();
|
||||
Variable var = getProgramScope().getVariable(varRef);
|
||||
if(var.isVolatile() || var.isKindLoadStore())
|
||||
// Do not examine volatiles and non-versioned variables
|
||||
continue;
|
||||
ConstantValue constant = getConstant(phiRValue.getrValue());
|
||||
constants.put(varRef, new ConstantVariableValue(varRef, constant, phi));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,8 +181,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
continue;
|
||||
StatementAssignment assignment = (StatementAssignment) varAssignment.statementLValue;
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef varRef = (VariableRef) lValue;
|
||||
if(lValue instanceof VariableRef varRef) {
|
||||
ConstantValue constant = getConstant(assignment.getrValue2());
|
||||
if(assignment.getrValue1() == null && assignment.getOperator() == null && constant != null) {
|
||||
constants.put(varRef, new ConstantVariableValue(varRef, constant, assignment));
|
||||
@ -209,11 +203,9 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
public static ConstantValue getConstant(RValue rValue) {
|
||||
if(rValue instanceof ConstantValue) {
|
||||
return (ConstantValue) rValue;
|
||||
} else if(rValue instanceof Variable && ((Variable) rValue).isKindConstant()) {
|
||||
Variable constantVar = (Variable) rValue;
|
||||
} else if(rValue instanceof Variable constantVar && ((Variable) rValue).isKindConstant()) {
|
||||
return constantVar.getConstantRef();
|
||||
} else if(rValue instanceof CastValue) {
|
||||
CastValue castValue = (CastValue) rValue;
|
||||
} else if(rValue instanceof CastValue castValue) {
|
||||
ConstantValue castConstant = getConstant(castValue.getValue());
|
||||
if(castConstant != null) {
|
||||
return new ConstantCastValue(castValue.getToType(), castConstant);
|
||||
@ -236,47 +228,43 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
return new ConstantBinary(c1, operator, c2);
|
||||
}
|
||||
|
||||
switch(operator.getOperator()) {
|
||||
case "-":
|
||||
case "*":
|
||||
case "/":
|
||||
case "%":
|
||||
case "&":
|
||||
case "|":
|
||||
case "&&":
|
||||
case "||":
|
||||
case "^":
|
||||
case "<<":
|
||||
case ">>":
|
||||
case "==":
|
||||
case "!=":
|
||||
case ">":
|
||||
case "<":
|
||||
case ">=":
|
||||
case "<=":
|
||||
return new ConstantBinary(c1, operator, c2);
|
||||
case "w=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(256L)), Operators.PLUS, c2);
|
||||
case "dw=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(65536L)), Operators.PLUS, c2);
|
||||
case "byte0=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffffff00L)), Operators.BOOL_OR, c2);
|
||||
case "byte1=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff00ffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x100L)));
|
||||
case "byte2=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xff00ffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
|
||||
case "byte3=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x00ffffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x1000000L)));
|
||||
case "word0=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff0000L)), Operators.BOOL_OR, c2);
|
||||
case "word1=":
|
||||
return new ConstantBinary(new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x0000ffffL)), Operators.BOOL_OR, new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
|
||||
case "*idx":
|
||||
return switch (operator.getOperator()) {
|
||||
case "-", "*", "/", "%", "&", "|", "&&", "||", "^", "<<", ">>", "==", "!=", ">", "<", ">=", "<=" ->
|
||||
new ConstantBinary(c1, operator, c2);
|
||||
case "w=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(256L)), Operators.PLUS,
|
||||
c2);
|
||||
case "dw=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.MULTIPLY, new ConstantInteger(65536L)),
|
||||
Operators.PLUS, c2);
|
||||
case "byte0=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffffff00L)),
|
||||
Operators.BOOL_OR, c2);
|
||||
case "byte1=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff00ffL)),
|
||||
Operators.BOOL_OR,
|
||||
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x100L)));
|
||||
case "byte2=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xff00ffffL)),
|
||||
Operators.BOOL_OR,
|
||||
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
|
||||
case "byte3=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x00ffffffL)),
|
||||
Operators.BOOL_OR,
|
||||
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x1000000L)));
|
||||
case "word0=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0xffff0000L)),
|
||||
Operators.BOOL_OR, c2);
|
||||
case "word1=" -> new ConstantBinary(
|
||||
new ConstantBinary(c1, Operators.BOOL_AND, new ConstantInteger(0x0000ffffL)),
|
||||
Operators.BOOL_OR,
|
||||
new ConstantBinary(c2, Operators.MULTIPLY, new ConstantInteger(0x10000L)));
|
||||
case "*idx" ->
|
||||
// Pointer dereference - not constant
|
||||
return null;
|
||||
default:
|
||||
throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
|
||||
}
|
||||
null;
|
||||
default ->
|
||||
throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -301,13 +289,10 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
// Examine all statements
|
||||
for(var block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && procedureRef.equals(assignment.getrValue2())) {
|
||||
return true;
|
||||
}
|
||||
for(var statement : program.getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && procedureRef.equals(assignment.getrValue2())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
@ -33,20 +30,17 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
boolean modified = false;
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) {
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getProgramScope(), assignment.getlValue());
|
||||
ConstantValue constant = getConstantAssignmentValue(assignment, lValueType);
|
||||
if(constant != null) {
|
||||
getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
|
||||
assignment.setrValue2(constant);
|
||||
assignment.setOperator(null);
|
||||
assignment.setrValue1(null);
|
||||
modified = true;
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) {
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getProgramScope(), assignment.getlValue());
|
||||
ConstantValue constant = getConstantAssignmentValue(assignment);
|
||||
if(constant != null) {
|
||||
getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
|
||||
assignment.setrValue2(constant);
|
||||
assignment.setOperator(null);
|
||||
assignment.setrValue1(null);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,10 +52,9 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
|
||||
* Examine the right side of an assignment and if it is constant then return the constant value.
|
||||
*
|
||||
* @param assignment The assignment to examine
|
||||
* @param lValueType The type of the lvalue
|
||||
* @return The constant value if the right side is constant
|
||||
*/
|
||||
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment, SymbolType lValueType) {
|
||||
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment) {
|
||||
|
||||
if(assignment.getrValue1() == null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
|
||||
if(assignment.getOperator() == null) {
|
||||
|
@ -1,15 +1,11 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
@ -27,42 +23,39 @@ public class Pass2IdenticalPhiElimination extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
Map<VariableRef, RValue> phiIdentical = new LinkedHashMap<>();
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock statementPhi = (StatementPhiBlock) statement;
|
||||
ListIterator<StatementPhiBlock.PhiVariable> phiVariableIt = statementPhi.getPhiVariables().listIterator();
|
||||
while(phiVariableIt.hasNext()) {
|
||||
StatementPhiBlock.PhiVariable phiVariable = phiVariableIt.next();
|
||||
RValue rValue = null;
|
||||
boolean identical = true;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(phiRValue.getrValue() instanceof SymbolVariableRef) {
|
||||
Variable symbolVar = (Variable) getProgramScope().getSymbol((SymbolVariableRef) phiRValue.getrValue());
|
||||
if(symbolVar.getRegister() != null) { //TODO: Handle register/memory/storage strategy differently!
|
||||
// Do not collapse PHI's for variables with declared registers (this prevents procedure parameters from being turned into constants)
|
||||
identical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(phiRValue.getrValue().equals(phiVariable.getVariable())) {
|
||||
// Self PHI - skip that
|
||||
continue;
|
||||
}
|
||||
if(rValue == null) {
|
||||
rValue = phiRValue.getrValue();
|
||||
} else {
|
||||
if(!rValue.equals(phiRValue.getrValue())) {
|
||||
identical = false;
|
||||
break;
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementPhiBlock statementPhi) {
|
||||
ListIterator<StatementPhiBlock.PhiVariable> phiVariableIt = statementPhi.getPhiVariables().listIterator();
|
||||
while(phiVariableIt.hasNext()) {
|
||||
StatementPhiBlock.PhiVariable phiVariable = phiVariableIt.next();
|
||||
RValue rValue = null;
|
||||
boolean identical = true;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(phiRValue.getrValue() instanceof SymbolVariableRef) {
|
||||
Variable symbolVar = (Variable) getProgramScope().getSymbol((SymbolVariableRef) phiRValue.getrValue());
|
||||
if(symbolVar.getRegister() != null) { //TODO: Handle register/memory/storage strategy differently!
|
||||
// Do not collapse PHI's for variables with declared registers (this prevents procedure parameters from being turned into constants)
|
||||
identical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(identical && rValue!=null) {
|
||||
// Found a phi-value with all rValues being identical
|
||||
phiIdentical.put(phiVariable.getVariable(), rValue);
|
||||
phiVariableIt.remove();
|
||||
if(phiRValue.getrValue().equals(phiVariable.getVariable())) {
|
||||
// Self PHI - skip that
|
||||
continue;
|
||||
}
|
||||
if(rValue == null) {
|
||||
rValue = phiRValue.getrValue();
|
||||
} else {
|
||||
if(!rValue.equals(phiRValue.getrValue())) {
|
||||
identical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(identical && rValue!=null) {
|
||||
// Found a phi-value with all rValues being identical
|
||||
phiIdentical.put(phiVariable.getVariable(), rValue);
|
||||
phiVariableIt.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.OperatorCast;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.CastValue;
|
||||
@ -19,17 +16,14 @@ public class Pass2InlineCast extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
boolean optimized = false;
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) {
|
||||
SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType();
|
||||
assignment.setrValue2(new CastValue(toType, assignment.getrValue2()));
|
||||
assignment.setOperator(null);
|
||||
getLog().append("Inlining cast "+assignment.toString(getProgram(), false));
|
||||
optimized = true;
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) {
|
||||
SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType();
|
||||
assignment.setrValue2(new CastValue(toType, assignment.getrValue2()));
|
||||
assignment.setOperator(null);
|
||||
getLog().append("Inlining cast "+assignment.toString(getProgram(), false));
|
||||
optimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||
|
||||
/**
|
||||
* Check that the unrolling of a loop was sucessfully completed.
|
||||
* Check that the unrolling of a loop was successfully completed.
|
||||
* This is done by checking that no conditional jumps exist marked as wasUnrolled.
|
||||
* Since unrolling requires the loop iteration count to be constant the conditionals must always be resolved to true or false and thus deleted or changed to jumps.
|
||||
*/
|
||||
@ -20,12 +17,10 @@ public class Pass2LoopUnrollAssertComplete extends Pass2SsaOptimization {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
if(((StatementConditionalJump) statement).isWasUnrolled()) {
|
||||
throw new CompileError("Loop cannot be unrolled. Condition not resolvable to a constant true/false. ", statement);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementConditionalJump) {
|
||||
if(((StatementConditionalJump) statement).isWasUnrolled()) {
|
||||
throw new CompileError("Loop cannot be unrolled. Condition not resolvable to a constant true/false. ", statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
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;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -35,63 +32,53 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
|
||||
/**
|
||||
* 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 comparisons)
|
||||
*/
|
||||
private List<VariableRef> optimizeUnaryNots() {
|
||||
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
|
||||
final List<VariableRef> unused = new ArrayList<>();
|
||||
for(var 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();
|
||||
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);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case ">":
|
||||
createInverse("<=", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case "<=":
|
||||
case "=<":
|
||||
createInverse(">", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case ">=":
|
||||
case "=>":
|
||||
createInverse("<", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case "==":
|
||||
createInverse("!=", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case "!=":
|
||||
case "<>":
|
||||
createInverse("==", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
case "!":
|
||||
case "not":
|
||||
createInverse(null, assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
break;
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
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();
|
||||
final Integer tempVarDefineStmtIdx = variableReferenceInfos.getVarDefineStatement(tempVar);
|
||||
if(tempVarDefineStmtIdx != null) {
|
||||
final Statement tempVarDefineStmt = getGraph().getStatementByIndex(tempVarDefineStmtIdx);
|
||||
if(tempVarDefineStmt instanceof StatementAssignment tempAssignment) {
|
||||
int tempVarUsages = variableReferenceInfos.getVarUseStatements(tempVar).size();
|
||||
if(tempVarUsages == 1 && tempAssignment.getOperator() != null) {
|
||||
switch (tempAssignment.getOperator().getOperator()) {
|
||||
case "<" -> {
|
||||
createInverse(">=", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case ">" -> {
|
||||
createInverse("<=", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case "<=", "=<" -> {
|
||||
createInverse(">", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case ">=", "=>" -> {
|
||||
createInverse("<", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case "==" -> {
|
||||
createInverse("!=", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case "!=", "<>" -> {
|
||||
createInverse("==", assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
case "!", "not" -> {
|
||||
createInverse(null, assignment, tempAssignment);
|
||||
unused.add(tempVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAsm;
|
||||
import dk.camelot64.kickc.model.statements.StatementKickAsm;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
@ -14,7 +11,6 @@ import dk.camelot64.kickc.model.values.ConstantRef;
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -34,44 +30,39 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
for(var block : getProgram().getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementKickAsm) {
|
||||
RValue bytes = ((StatementKickAsm) statement).getBytes();
|
||||
if(bytes != null && !(bytes instanceof ConstantValue)) {
|
||||
throw new CompileError("KickAssembler bytes is not constant " + bytes.toString(), statement);
|
||||
}
|
||||
RValue cycles = ((StatementKickAsm) statement).getCycles();
|
||||
if(cycles != null && !(cycles instanceof ConstantValue)) {
|
||||
throw new CompileError("KickAssembler cycles is not constant " + cycles.toString(), statement);
|
||||
}
|
||||
} else if(statement instanceof StatementAsm) {
|
||||
StatementAsm statementAsm = (StatementAsm) statement;
|
||||
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
|
||||
for(String label : referenced.keySet()) {
|
||||
SymbolRef symbolRef = referenced.get(label);
|
||||
Symbol symbol = getScope().getSymbol(symbolRef);
|
||||
if(symbol instanceof Procedure)
|
||||
// Referencing procedures are fine!
|
||||
continue;
|
||||
else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant())
|
||||
// Referencing constants are fine!
|
||||
continue;
|
||||
else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore())
|
||||
// Referencing load/store is fine!
|
||||
continue;
|
||||
else
|
||||
throw new CompileError("Inline ASM reference is not constant " + label, statement);
|
||||
}
|
||||
} else if(statement instanceof StatementKickAsm) {
|
||||
StatementKickAsm statementAsm = (StatementKickAsm) statement;
|
||||
List<SymbolRef> uses = statementAsm.getUses();
|
||||
for(SymbolRef use : uses) {
|
||||
if(!(use instanceof ConstantRef)) {
|
||||
throw new CompileError("Inline KickAsm reference is not constant " + use, statement);
|
||||
}
|
||||
for(var statement : getProgram().getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementKickAsm statementKickAsm) {
|
||||
RValue bytes = statementKickAsm.getBytes();
|
||||
if(bytes != null && !(bytes instanceof ConstantValue)) {
|
||||
throw new CompileError("KickAssembler bytes is not constant " + bytes.toString(), statement);
|
||||
}
|
||||
RValue cycles = statementKickAsm.getCycles();
|
||||
if(cycles != null && !(cycles instanceof ConstantValue)) {
|
||||
throw new CompileError("KickAssembler cycles is not constant " + cycles.toString(), statement);
|
||||
}
|
||||
List<SymbolRef> uses = statementKickAsm.getUses();
|
||||
for(SymbolRef use : uses) {
|
||||
if(!(use instanceof ConstantRef)) {
|
||||
throw new CompileError("Inline KickAsm reference is not constant " + use, statement);
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementAsm statementAsm) {
|
||||
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
|
||||
for(String label : referenced.keySet()) {
|
||||
SymbolRef symbolRef = referenced.get(label);
|
||||
Symbol symbol = getScope().getSymbol(symbolRef);
|
||||
if(symbol instanceof Procedure)
|
||||
// Referencing procedures are fine!
|
||||
continue;
|
||||
else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant())
|
||||
// Referencing constants are fine!
|
||||
continue;
|
||||
else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore())
|
||||
// Referencing load/store is fine!
|
||||
continue;
|
||||
else
|
||||
throw new CompileError("Inline ASM reference is not constant " + label, statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
|
||||
/**
|
||||
@ -19,21 +16,17 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
for(Graph.Block block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.MULTIPLY.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.DIVIDE.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.MODULO.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(Operators.MULTIPLY.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime multiplication not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.DIVIDE.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime division not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
if(Operators.MODULO.equals(assignment.getOperator())) {
|
||||
throw new CompileError("Runtime modulo not supported. "+statement.toString(getProgram(), false), statement.getSource());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
@ -23,22 +21,20 @@ public class Pass3AssertNoNumbers extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
checkValue(((StatementAssignment) statement).getlValue(), statement);
|
||||
checkValue(((StatementAssignment) statement).getrValue1(), statement);
|
||||
checkValue(((StatementAssignment) statement).getrValue2(), statement);
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
|
||||
checkValue(value.getrValue(), statement);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof final StatementAssignment assignment) {
|
||||
checkValue(assignment.getlValue(), statement);
|
||||
checkValue(assignment.getrValue1(), statement);
|
||||
checkValue(assignment.getrValue2(), statement);
|
||||
} else if(statement instanceof final StatementPhiBlock phiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
|
||||
checkValue(value.getrValue(), statement);
|
||||
}
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
checkValue(((StatementConditionalJump) statement).getrValue1(), statement);
|
||||
checkValue(((StatementConditionalJump) statement).getrValue2(), statement);
|
||||
}
|
||||
} else if(statement instanceof final StatementConditionalJump conditionalJump) {
|
||||
checkValue(conditionalJump.getrValue1(), statement);
|
||||
checkValue(conditionalJump.getrValue2(), statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,15 +55,13 @@ public class Pass4MemoryCoalesceAssignment extends Pass2Base {
|
||||
public CoalesceVarScores(Program program) {
|
||||
this.scores = new LinkedHashMap<>();
|
||||
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
|
||||
for(var block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
|
||||
Collection<VariableRef> usedVars = variableReferenceInfos.getUsedVars(statement);
|
||||
if(definedVars != null && definedVars.size() > 0) {
|
||||
for(VariableRef definedVar : definedVars) {
|
||||
for(VariableRef usedVar : usedVars) {
|
||||
incScore(definedVar, usedVar);
|
||||
}
|
||||
for(var statement : program.getGraph().getAllStatements()) {
|
||||
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
|
||||
Collection<VariableRef> usedVars = variableReferenceInfos.getUsedVars(statement);
|
||||
if (definedVars != null && definedVars.size() > 0) {
|
||||
for (VariableRef definedVar : definedVars) {
|
||||
for (VariableRef usedVar : usedVars) {
|
||||
incScore(definedVar, usedVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,11 +170,9 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
|
||||
* @return true if the register allocation contains an overlapping allocation. false otherwise.
|
||||
*/
|
||||
public static boolean isAllocationOverlapping(Program program) {
|
||||
for(var block : program.getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(isStatementAllocationOverlapping(program, statement)) {
|
||||
return true;
|
||||
}
|
||||
for(var statement : program.getGraph().getAllStatements()) {
|
||||
if(isStatementAllocationOverlapping(program, statement)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -1,20 +1,20 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallPointer;
|
||||
import dk.camelot64.kickc.model.types.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
||||
import dk.camelot64.kickc.model.values.ConstantSymbolPointer;
|
||||
import dk.camelot64.kickc.model.values.PointerDereferenceSimple;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -22,7 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
|
||||
private boolean pass1;
|
||||
private final boolean pass1;
|
||||
|
||||
public PassNAddTypeConversionAssignment(Program program, boolean pass1) {
|
||||
super(program);
|
||||
@ -33,8 +33,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
AtomicBoolean modified = new AtomicBoolean(false);
|
||||
ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programExpression instanceof ProgramExpressionBinary) {
|
||||
ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
|
||||
if(programExpression instanceof ProgramExpressionBinary binary) {
|
||||
RValue left = binary.getLeft();
|
||||
RValue right = binary.getRight();
|
||||
SymbolType leftType;
|
||||
@ -71,22 +70,20 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
||||
});
|
||||
|
||||
// Add dereference to call to pointer to function
|
||||
for(var block : getProgram().getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCallPointer) {
|
||||
RValue procedure = ((StatementCallPointer) statement).getProcedure();
|
||||
SymbolType procType = SymbolTypeInference.inferType(getProgramScope(), procedure);
|
||||
if(procType instanceof SymbolTypePointer && ((SymbolTypePointer) procType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
// Allow calling pointer to procedure directly
|
||||
// Add an automatic dereference to a pointer to procedure
|
||||
if(!pass1 || getLog().isVerbosePass1CreateSsa())
|
||||
getLog().append("Adding dereference to call function pointer " + procedure.toString() + " in " + statement.toString(getProgram(), false));
|
||||
((StatementCallPointer) statement).setProcedure(new PointerDereferenceSimple(procedure));
|
||||
}
|
||||
for(var statement : getProgram().getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementCallPointer) {
|
||||
final StatementCallPointer callPointer = (StatementCallPointer) statement;
|
||||
RValue procedure = callPointer.getProcedure();
|
||||
SymbolType procType = SymbolTypeInference.inferType(getProgramScope(), procedure);
|
||||
if(procType instanceof SymbolTypePointer && ((SymbolTypePointer) procType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
// Allow calling pointer to procedure directly
|
||||
// Add an automatic dereference to a pointer to procedure
|
||||
if(!pass1 || getLog().isVerbosePass1CreateSsa())
|
||||
getLog().append("Adding dereference to call function pointer " + procedure.toString() + " in " + statement.toString(getProgram(), false));
|
||||
callPointer.setProcedure(new PointerDereferenceSimple(procedure));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modified.get();
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,10 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -24,20 +20,16 @@ public class PassNArrayElementAddressOfRewriting extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
AtomicBoolean modified = new AtomicBoolean(false);
|
||||
// Examine all statements
|
||||
for(var block : getProgram().getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
|
||||
RValue rValue = assignment.getrValue2();
|
||||
if(rValue instanceof PointerDereferenceIndexed) {
|
||||
PointerDereferenceIndexed dereferenceIndexed = (PointerDereferenceIndexed) rValue;
|
||||
assignment.setrValue1(dereferenceIndexed.getPointer());
|
||||
assignment.setOperator(Operators.PLUS);
|
||||
assignment.setrValue2(dereferenceIndexed.getIndex());
|
||||
getLog().append("Rewriting array member address-of to pointer addition "+assignment.toString(getProgram(), false));
|
||||
modified.set(true);
|
||||
}
|
||||
for(var statement : getProgram().getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(Operators.ADDRESS_OF.equals(assignment.getOperator()) ) {
|
||||
RValue rValue = assignment.getrValue2();
|
||||
if(rValue instanceof PointerDereferenceIndexed dereferenceIndexed) {
|
||||
assignment.setrValue1(dereferenceIndexed.getPointer());
|
||||
assignment.setOperator(Operators.PLUS);
|
||||
assignment.setrValue2(dereferenceIndexed.getIndex());
|
||||
getLog().append("Rewriting array member address-of to pointer addition "+assignment.toString(getProgram(), false));
|
||||
modified.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,11 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Graph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementLValue;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@ -25,19 +21,16 @@ public class PassNAssertConstantModification extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
Set<VariableRef> assigned = new HashSet<>();
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementLValue) {
|
||||
LValue lValue = ((StatementLValue) statement).getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef variableRef = (VariableRef) lValue;
|
||||
Variable variable = getProgramScope().getVariable(variableRef);
|
||||
if(variable.isKindConstant() || variable.isNoModify()) {
|
||||
if(assigned.contains(variableRef)) {
|
||||
throw new CompileError("const variable may not be modified "+variable.toString(getProgram()), statement.getSource());
|
||||
} else {
|
||||
assigned.add(variableRef);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof final StatementLValue statementLValue) {
|
||||
LValue lValue = statementLValue.getlValue();
|
||||
if(lValue instanceof VariableRef variableRef) {
|
||||
Variable variable = getProgramScope().getVariable(variableRef);
|
||||
if(variable.isKindConstant() || variable.isNoModify()) {
|
||||
if(assigned.contains(variableRef)) {
|
||||
throw new CompileError("const variable may not be modified "+variable.toString(getProgram()), statement.getSource());
|
||||
} else {
|
||||
assigned.add(variableRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,13 +24,11 @@ public class PassNAssertTypeMatch extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
checkAssignment((StatementAssignment) statement);
|
||||
}
|
||||
// TODO: Implement checking for calls / ...
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof final StatementAssignment assignment) {
|
||||
checkAssignment(assignment);
|
||||
}
|
||||
// TODO: Implement checking for calls / ...
|
||||
}
|
||||
for(Variable var : getScope().getAllVars(true)) {
|
||||
if(var.getInitValue()!=null) {
|
||||
|
@ -1,17 +1,25 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.values.ConstantArrayList;
|
||||
import dk.camelot64.kickc.model.values.ConstantBinary;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
import dk.camelot64.kickc.model.values.ConstantRef;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
import dk.camelot64.kickc.model.values.ConstantUnary;
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@ -27,22 +35,18 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
public boolean step() {
|
||||
AtomicBoolean modified = new AtomicBoolean(false);
|
||||
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
if(Operators.SIZEOF.equals(assignment.getOperator())) {
|
||||
if(assignment.getrValue2() instanceof SymbolVariableRef) {
|
||||
SymbolVariableRef symbolRef = (SymbolVariableRef) assignment.getrValue2();
|
||||
Variable symbolVar = (Variable) getProgramScope().getSymbol(symbolRef);
|
||||
SymbolType symbolType = symbolVar.getType();
|
||||
if(!(symbolVar.isArray())) {
|
||||
getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false));
|
||||
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), symbolType);
|
||||
assignment.setrValue2(sizeOfConstantVar);
|
||||
assignment.setOperator(null);
|
||||
modified.set(true);
|
||||
}
|
||||
for(var statement : getGraph().getAllStatements()) {
|
||||
if(statement instanceof StatementAssignment assignment) {
|
||||
if(Operators.SIZEOF.equals(assignment.getOperator())) {
|
||||
if(assignment.getrValue2() instanceof SymbolVariableRef symbolRef) {
|
||||
Variable symbolVar = (Variable) getProgramScope().getSymbol(symbolRef);
|
||||
SymbolType symbolType = symbolVar.getType();
|
||||
if(!(symbolVar.isArray())) {
|
||||
getLog().append("Resolving sizeof() " + assignment.toString(getProgram(), false));
|
||||
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), symbolType);
|
||||
assignment.setrValue2(sizeOfConstantVar);
|
||||
assignment.setOperator(null);
|
||||
modified.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,8 +54,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programValue.get() instanceof ConstantUnary) {
|
||||
ConstantUnary unary = (ConstantUnary) programValue.get();
|
||||
if(programValue.get() instanceof ConstantUnary unary) {
|
||||
if(unary.getOperator().equals(Operators.SIZEOF)) {
|
||||
ConstantValue operand = unary.getOperand();
|
||||
resolveConstantSizeOf(modified, programValue, unary, operand);
|
||||
@ -67,8 +70,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
if(operand instanceof ConstantRef) {
|
||||
Variable constant = getProgramScope().getConstant((ConstantRef) operand);
|
||||
SymbolType symbolType = constant.getType();
|
||||
if(constant.isArray() && symbolType instanceof SymbolTypePointer) {
|
||||
SymbolTypePointer arrayType = (SymbolTypePointer) symbolType;
|
||||
if(constant.isArray() && symbolType instanceof SymbolTypePointer arrayType) {
|
||||
ConstantValue arraySize = constant.getArraySize();
|
||||
if(arraySize!=null) {
|
||||
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
|
||||
@ -83,14 +85,13 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
modified.set(true);
|
||||
} else {
|
||||
// Try to calculate the literal to check if it is a string
|
||||
ConstantLiteral stringLiteral = null;
|
||||
ConstantLiteral<?> stringLiteral = null;
|
||||
try {
|
||||
stringLiteral = constant.getInitValue().calculateLiteral(getProgram().getScope());
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// Ignore
|
||||
}
|
||||
if(stringLiteral instanceof ConstantString) {
|
||||
ConstantString constString = (ConstantString) stringLiteral;
|
||||
if(stringLiteral instanceof ConstantString constString) {
|
||||
int length = constString.getStringLength();
|
||||
getLog().append("Resolving string sizeof() " + unary.toString(getProgram()));
|
||||
ConstantRef sizeOfChar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), SymbolType.BYTE);
|
||||
@ -107,7 +108,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
modified.set(true);
|
||||
} else {
|
||||
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
|
||||
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
|
||||
ConstantLiteral<?> literal = operand.calculateLiteral(getProgram().getScope());
|
||||
SymbolType constType = literal.getType(getProgram().getScope());
|
||||
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), constType);
|
||||
programValue.set(sizeOfConstantVar);
|
||||
@ -115,7 +116,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
|
||||
}
|
||||
} else {
|
||||
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
|
||||
ConstantLiteral literal = operand.calculateLiteral(getProgram().getScope());
|
||||
ConstantLiteral<?> literal = operand.calculateLiteral(getProgram().getScope());
|
||||
SymbolType constType = literal.getType(getProgram().getScope());
|
||||
ConstantRef sizeOfConstantVar = SizeOfConstants.getSizeOfConstantVar(getProgramScope(), constType);
|
||||
programValue.set(sizeOfConstantVar);
|
||||
|
@ -22,10 +22,8 @@ public class PassNStatementIndices extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
int currentIdx = 0;
|
||||
for(var block : getProgram().getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
statement.setIndex(currentIdx++);
|
||||
}
|
||||
for(var statement : getProgram().getGraph().getAllStatements()) {
|
||||
statement.setIndex(currentIdx++);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -22,19 +22,17 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(var block : getGraph().getAllBlocks()) {
|
||||
for(Statement statement : block.getStatements()) {
|
||||
try {
|
||||
if(statement instanceof StatementLValue) {
|
||||
updateInferedTypeLValue(getProgram(), (StatementLValue) statement);
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
updateInferedTypePhiVariable(getProgram(), phiVariable);
|
||||
}
|
||||
for(var statement : getProgram().getGraph().getAllStatements()) {
|
||||
try {
|
||||
if(statement instanceof final StatementLValue statementLValue) {
|
||||
updateInferedTypeLValue(getProgram(), statementLValue);
|
||||
} else if(statement instanceof final StatementPhiBlock statementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : statementPhiBlock.getPhiVariables()) {
|
||||
updateInferedTypePhiVariable(getProgram(), phiVariable);
|
||||
}
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), statement.getSource());
|
||||
}
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), statement.getSource());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -82,84 +82,96 @@ public class PassNCalcLiveRangeVariables extends PassNCalcBase<LiveRangeVariable
|
||||
VariableReferenceInfos referenceInfo = getProgram().getVariableReferenceInfos();
|
||||
boolean modified = false;
|
||||
LiveRangeVariables.LiveRangeVariablesByStatement liveRangeVariablesByStatement = liveRanges.getLiveRangeVariablesByStatement();
|
||||
for(var block : getProgram().getGraph().getAllBlocks()) {
|
||||
for(Statement nextStmt : block.getStatements()) {
|
||||
List<VariableRef> aliveNextStmt = liveRangeVariablesByStatement.getAlive(nextStmt.getIndex());
|
||||
Collection<VariableRef> definedNextStmt = referenceInfo.getDefinedVars(nextStmt);
|
||||
initLiveRange(liveRanges, definedNextStmt);
|
||||
Collection<PreviousStatement> previousStmts = getPreviousStatements(nextStmt);
|
||||
for(PreviousStatement previousStmt : previousStmts) {
|
||||
if(PreviousStatement.Type.NORMAL.equals(previousStmt.getType())) {
|
||||
// Add all vars alive in the next statement
|
||||
for(VariableRef aliveVar : aliveNextStmt) {
|
||||
if(!definedNextStmt.contains(aliveVar)) {
|
||||
boolean addAlive = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
|
||||
modified |= addAlive;
|
||||
if(addAlive && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append("Propagated alive var " + aliveVar + " to " + previousStmt.getStatement());
|
||||
}
|
||||
for (Statement nextStmt : getProgram().getGraph().getAllStatements()) {
|
||||
List<VariableRef> aliveNextStmt = liveRangeVariablesByStatement.getAlive(
|
||||
nextStmt.getIndex());
|
||||
Collection<VariableRef> definedNextStmt = referenceInfo.getDefinedVars(nextStmt);
|
||||
initLiveRange(liveRanges, definedNextStmt);
|
||||
Collection<PreviousStatement> previousStmts = getPreviousStatements(nextStmt);
|
||||
for (PreviousStatement previousStmt : previousStmts) {
|
||||
if (PreviousStatement.Type.NORMAL.equals(previousStmt.getType())) {
|
||||
// Add all vars alive in the next statement
|
||||
for (VariableRef aliveVar : aliveNextStmt) {
|
||||
if (!definedNextStmt.contains(aliveVar)) {
|
||||
boolean addAlive = liveRanges.addAlive(aliveVar,
|
||||
previousStmt.getStatementIdx());
|
||||
modified |= addAlive;
|
||||
if (addAlive && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append("Propagated alive var " + aliveVar + " to "
|
||||
+ previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
// Add all used variables to the previous statement (taking into account phi from blocks)
|
||||
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
|
||||
} else if(PreviousStatement.Type.LAST_IN_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all vars that are referenced in the method
|
||||
StatementCalling call = (StatementCalling) nextStmt;
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
Collection<VariableRef> procUsed = procedureReferencedVars.get(procedure);
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for(VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are not used inside the method
|
||||
if(procUsed.contains(aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if(added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append("Propagated alive var used in method into method " + aliveVar + " to " + previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(PreviousStatement.Type.SKIP_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all vars from next statement that the method does not use
|
||||
StatementCalling call = (StatementCalling) nextStmt;
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
if(procedure!=null) {
|
||||
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure);
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for(VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are not used inside the method
|
||||
if(!procReferenced.contains(aliveVar) && !definedNextStmt.contains(aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if(added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append("Propagated alive var unused in method by skipping call " + aliveVar + " to " + previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(PreviousStatement.Type.BEFORE_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all alive variables to previous that are used inside the method
|
||||
Graph.Block procBlock = getProgram().getStatementInfos().getBlock(nextStmt);
|
||||
Procedure procedure = (Procedure) getProgram().getScope().getSymbol(procBlock.getLabel());
|
||||
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure.getRef());
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for(VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are used inside the method
|
||||
if(procReferenced.contains(aliveVar)) {
|
||||
if(!definedNextStmt.contains(aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if(added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append("Propagated alive used in method out of method " + aliveVar + " to " + previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Do nothing
|
||||
// getLog().append("Not propagating "+aliveVar.toString(getProgram()) +" in BEFORE_METHOD case from "+nextStmt.toString(getProgram(), false)+ " to "+previousStmt.getStatement().toString(getProgram(), false));
|
||||
}
|
||||
}
|
||||
// Add all used variables to the previous statement (taking into account phi from blocks)
|
||||
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
|
||||
}
|
||||
// Add all used variables to the previous statement (taking into account phi from blocks)
|
||||
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
|
||||
} else if (PreviousStatement.Type.LAST_IN_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all vars that are referenced in the method
|
||||
StatementCalling call = (StatementCalling) nextStmt;
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
Collection<VariableRef> procUsed = procedureReferencedVars.get(procedure);
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for (VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are not used inside the method
|
||||
if (procUsed.contains(aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar, previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if (added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append(
|
||||
"Propagated alive var used in method into method " + aliveVar + " to "
|
||||
+ previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (PreviousStatement.Type.SKIP_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all vars from next statement that the method does not use
|
||||
StatementCalling call = (StatementCalling) nextStmt;
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
if (procedure != null) {
|
||||
Collection<VariableRef> procReferenced = procedureReferencedVars.get(procedure);
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for (VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are not used inside the method
|
||||
if (!procReferenced.contains(aliveVar) && !definedNextStmt.contains(
|
||||
aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar,
|
||||
previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if (added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append(
|
||||
"Propagated alive var unused in method by skipping call " + aliveVar
|
||||
+ " to " + previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (PreviousStatement.Type.BEFORE_METHOD.equals(previousStmt.getType())) {
|
||||
// Add all alive variables to previous that are used inside the method
|
||||
Graph.Block procBlock = getProgram().getStatementInfos().getBlock(nextStmt);
|
||||
Procedure procedure = (Procedure) getProgram().getScope()
|
||||
.getSymbol(procBlock.getLabel());
|
||||
Collection<VariableRef> procReferenced = procedureReferencedVars.get(
|
||||
procedure.getRef());
|
||||
// The call statement has no used or defined by itself so only work with the alive vars
|
||||
for (VariableRef aliveVar : aliveNextStmt) {
|
||||
// Add all variables to previous that are used inside the method
|
||||
if (procReferenced.contains(aliveVar)) {
|
||||
if (!definedNextStmt.contains(aliveVar)) {
|
||||
boolean added = liveRanges.addAlive(aliveVar,
|
||||
previousStmt.getStatementIdx());
|
||||
modified |= added;
|
||||
if (added && getLog().isVerboseLiveRanges()) {
|
||||
getLog().append(
|
||||
"Propagated alive used in method out of method " + aliveVar + " to "
|
||||
+ previousStmt.getStatement());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Do nothing
|
||||
// getLog().append("Not propagating "+aliveVar.toString(getProgram()) +" in BEFORE_METHOD case from "+nextStmt.toString(getProgram(), false)+ " to "+previousStmt.getStatement().toString(getProgram(), false));
|
||||
}
|
||||
}
|
||||
// Add all used variables to the previous statement (taking into account phi from blocks)
|
||||
modified |= initUsedVars(liveRanges, nextStmt, previousStmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user