1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-30 15:31:17 +00:00

speed improvement in pass n variable reference infos

This commit is contained in:
Travis Fisher 2019-04-07 23:57:38 -04:00
parent 7393d095b9
commit b7b01a89a8
2 changed files with 81 additions and 35 deletions

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
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.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -41,14 +42,17 @@ public class ControlFlowBlock {
/** The variables referenced in this block. Set by setReferencedVars(). */
private LinkedHashSet<VariableRef> referencedVars = null;
/** The variables used in this block. Set by setReferencedVars(). */
private LinkedHashSet<VariableRef> usedVars = null;
public ControlFlowBlock(LabelRef label, ScopeRef scope) {
this.label = label;
this.scope = scope;
this.statements = new ArrayList<>();
this.defaultSuccessor = null;
this.conditionalSuccessor = null;
this.comments = new ArrayList<>();
this.referencedVars = null;
this.usedVars = null;
}
public List<Comment> getComments() {
@ -123,15 +127,48 @@ public class ControlFlowBlock {
return statements;
}
private Collection<VariableRef> getDefinedVars(Statement stmt) {
if(stmt instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) stmt;
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
return Arrays.asList((VariableRef) lValue);
}
} else if(stmt instanceof StatementPhiBlock) {
List<VariableRef> defined = new ArrayList<>();
StatementPhiBlock phi = (StatementPhiBlock) stmt;
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
defined.add(phiVariable.getVariable());
}
return defined;
} else if(stmt instanceof StatementCall) {
List<VariableRef> defined = new ArrayList<>();
if(((StatementCall) stmt).getlValue() instanceof VariableRef) {
defined.add((VariableRef) ((StatementCall) stmt).getlValue());
}
return defined;
}
return new ArrayList<>();
}
public void setReferencedVars() {
referencedVars = new LinkedHashSet<>();
usedVars = new LinkedHashSet<>();
for(Statement statement : this.getStatements()) {
LinkedHashSet<VariableRef> stmtReferencedVars = new LinkedHashSet<>();
LinkedHashSet<VariableRef> stmtUsedVars = new LinkedHashSet<>();
ProgramValueIterator.execute(statement,
(programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof VariableRef)
referencedVars.add((VariableRef) programValue.get());
stmtReferencedVars.add((VariableRef) programValue.get());
}
, null, null);
Collection<VariableRef> stmtDefinedVars = getDefinedVars(statement);
stmtUsedVars.addAll(stmtReferencedVars);
stmtUsedVars.removeAll(stmtDefinedVars);
referencedVars.addAll(stmtReferencedVars);
usedVars.addAll(stmtUsedVars);
}
}
@ -139,6 +176,10 @@ public class ControlFlowBlock {
return referencedVars;
}
public LinkedHashSet<VariableRef> getUsedVars() {
return usedVars;
}
/**
* Is the block the entry of a procedure, ie. the first block of the code of the procedure.
*

View File

@ -37,7 +37,7 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
LabelRef blockLabel = block.getLabel();
blockReferencedVars.put(blockLabel, getReferencedVars(block));
blockUsedVars.put(blockLabel, getUsedVars(blockLabel, new ArrayList<>()));
blockUsedVars.put(blockLabel, getUsedVars(block));
for(Statement statement : block.getStatements()) {
Collection<SymbolVariableRef> referenced = getReferenced(statement);
Collection<VariableRef> defined = getDefinedVars(statement);
@ -136,38 +136,6 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
return referenced;
}
/**
* Get all variables used inside a block and its successors (including any called method)
*
* @param labelRef The block to examine
* @param visited The blocks already visited during the search. Used to stop infinite recursion
* @return All used variables
*/
private Collection<VariableRef> getUsedVars(LabelRef labelRef, Collection<LabelRef> visited) {
if(labelRef == null) {
return new ArrayList<>();
}
if(visited.contains(labelRef)) {
return new ArrayList<>();
}
visited.add(labelRef);
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
if(block == null) {
return new ArrayList<>();
}
LinkedHashSet<VariableRef> used = new LinkedHashSet<>();
for(Statement statement : block.getStatements()) {
used.addAll(getUsedVars(statement));
if(statement instanceof StatementCall) {
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
used.addAll(getUsedVars(procedure.getLabelRef(), visited));
}
}
used.addAll(getUsedVars(block.getDefaultSuccessor(), visited));
used.addAll(getUsedVars(block.getConditionalSuccessor(), visited));
return used;
}
/**
* Get all variables used or defined inside a block and its successors (including any called method)
*
@ -204,6 +172,43 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
addReferencedVars(block.getCallSuccessor(), null, referencedVars, visited);
}
/**
* Get all variables used or defined inside a block and its successors (including any called method)
*
* @param block The block to examine
* @return All used variables
*/
private Collection<VariableRef> getUsedVars(ControlFlowBlock block) {
LinkedHashSet<VariableRef> usedVars = new LinkedHashSet<>();
addUsedVars(block.getLabel(), block, usedVars, new ArrayList<>());
return usedVars;
}
/**
* Recursively get all variables used or defined inside a block and its successors (including any called method)
*
* @param labelRef The block to examine
* @param block The block to examine (optional, saves lookup)
* @param usedVars the set of referenced variables
* @param visited The blocks already visited during the search. Used to stop infinite recursion
* @return All used variables
*/
private void addUsedVars(LabelRef labelRef, ControlFlowBlock block, LinkedHashSet<VariableRef> usedVars, Collection<LabelRef> visited) {
if(labelRef == null || visited.contains(labelRef))
return;
visited.add(labelRef);
if(block == null) {
block = getProgram().getGraph().getBlock(labelRef);
if(block == null)
return;
}
usedVars.addAll(block.getUsedVars());
addUsedVars(block.getDefaultSuccessor(), null, usedVars, visited);
addUsedVars(block.getConditionalSuccessor(), null, usedVars, visited);
addUsedVars(block.getCallSuccessor(), null, usedVars, visited);
}
/**
* Get the variables defined by a statement
*