From b7b01a89a87ba421f20f35c2c20dd09902525404 Mon Sep 17 00:00:00 2001 From: Travis Fisher Date: Sun, 7 Apr 2019 23:57:38 -0400 Subject: [PATCH] speed improvement in pass n variable reference infos --- .../kickc/model/ControlFlowBlock.java | 45 +++++++++++- .../passes/PassNVariableReferenceInfos.java | 71 ++++++++++--------- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java index 12750a889..4e68d4c1c 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java @@ -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 referencedVars = null; + /** The variables used in this block. Set by setReferencedVars(). */ + private LinkedHashSet 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 getComments() { @@ -123,15 +127,48 @@ public class ControlFlowBlock { return statements; } + private Collection 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 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 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 stmtReferencedVars = new LinkedHashSet<>(); + LinkedHashSet 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 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 getUsedVars() { + return usedVars; + } + /** * Is the block the entry of a procedure, ie. the first block of the code of the procedure. * diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java index 402bca032..5c185a4ad 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNVariableReferenceInfos.java @@ -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 referenced = getReferenced(statement); Collection 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 getUsedVars(LabelRef labelRef, Collection 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 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 getUsedVars(ControlFlowBlock block) { + LinkedHashSet 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 usedVars, Collection 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 *