From 513a71ce64746985f67b50df254e779dde126a16 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 1 Jun 2020 22:17:01 +0200 Subject: [PATCH] Optimized block successor closure slightly. --- .../java/dk/camelot64/kickc/Compiler.java | 6 ++ .../AsmFragmentTemplateSynthesizer.java | 10 ++- .../ControlFlowBlockSuccessorClosure.java | 48 ++++++++++++++ .../LiveRangeVariablesEffectiveCallPaths.java | 12 ++-- .../dk/camelot64/kickc/model/Program.java | 12 ++++ .../dk/camelot64/kickc/model/Registers.java | 2 +- .../camelot64/kickc/model/StatementInfos.java | 2 +- .../kickc/model/VariableReferenceInfos.java | 57 +++++++---------- .../kickc/passes/Pass1AssertUsedVars.java | 2 + .../kickc/passes/Pass1CallVoidReturns.java | 2 + .../Pass2LoopHeadConstantIdentification.java | 1 + .../passes/PassNEliminateUnusedVars.java | 2 + .../calcs/PassNCalcBlockSuccessorClosure.java | 62 +++++++++++++++++++ .../calcs/PassNCalcLiveRangeVariables.java | 3 +- ...PassNCalcLiveRangesEffectiveCallPaths.java | 12 ++-- .../PassNCalcVariableReferenceInfos.java | 39 +----------- .../camelot64/kickc/test/TestFragments.java | 7 +++ .../dk/camelot64/kickc/test/TestPrograms.java | 4 +- 18 files changed, 193 insertions(+), 90 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/model/ControlFlowBlockSuccessorClosure.java create mode 100644 src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcBlockSuccessorClosure.java diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index c1c42e999..658298776 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -360,6 +360,7 @@ public class Compiler { optimizations.add(new PassNStatementIndices(program)); optimizations.add(() -> { program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); return false; }); optimizations.add(new Pass2UnaryNotSimplification(program)); @@ -372,6 +373,7 @@ public class Compiler { }); optimizations.add(() -> { program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); return false; }); optimizations.add(() -> { @@ -433,6 +435,7 @@ public class Compiler { loopUnrolling.add(new PassNStatementIndices(program)); loopUnrolling.add(() -> { program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); return false; }); loopUnrolling.add(() -> { @@ -481,6 +484,7 @@ public class Compiler { constantOptimizations.add(new PassNStatementIndices(program)); constantOptimizations.add(() -> { program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); return false; }); constantOptimizations.add(new Pass2NopCastInlining(program)); @@ -571,6 +575,7 @@ public class Compiler { program.clearStatementInfos(); program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); pass2AssertSSA(); // Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap @@ -585,6 +590,7 @@ public class Compiler { program.clearStatementIndices(); program.clearStatementInfos(); program.clearVariableReferenceInfos(); + program.clearControlFlowBlockSuccessorClosure(); program.clearLiveRangeVariables(); program.clearLiveRangeVariablesEffective(); new PassNStatementIndices(program).execute(); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesizer.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesizer.java index 024114df7..b45a51a78 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesizer.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesizer.java @@ -143,6 +143,7 @@ public class AsmFragmentTemplateSynthesizer { * @return The map with all best fragments from the cache file. null if the cache file is not found. */ private Map loadBestFragmentCache(Path cacheFolder, CompileLog log) { + final Date before = new Date(); if(cacheFolder == null) { return null; } @@ -173,8 +174,10 @@ public class AsmFragmentTemplateSynthesizer { } cacheLine = fragmentCacheReader.readLine(); } + final Date after = new Date(); + final long millis = after.getTime() - before.getTime(); if(log.isVerboseFragmentLog()) - log.append("Loaded cached fragments " + bestFragmentCache.size() + " from " + cacheFile.getPath()); + log.append("Loaded cached fragments " + bestFragmentCache.size() + " from " + cacheFile.getPath() + " in " + millis + "ms"); return bestFragmentCache; } catch(IOException e) { throw new RuntimeException("Error loading fragment cache file " + baseFragmentFolder, e); @@ -189,6 +192,7 @@ public class AsmFragmentTemplateSynthesizer { * @param log The compile log */ public void saveBestFragmentCache(CompileLog log) { + Date before = new Date(); if(this.cacheFolder == null) { return; } @@ -202,8 +206,10 @@ public class AsmFragmentTemplateSynthesizer { fragmentFilePrint.println(fragmentTemplate.getBody()); } fragmentFilePrint.close(); + final Date after = new Date(); + final long millis = after.getTime() - before.getTime(); if(log.isVerboseFragmentLog()) - log.append("Saved cached fragments " + this.bestFragmentCache.size() + " to " + cacheFile.getPath()); + log.append("Saved cached fragments " + this.bestFragmentCache.size() + " to " + cacheFile.getPath() + " in " + millis + "ms"); } catch(IOException e) { throw new RuntimeException("Error saving fragment cache file " + cacheFile, e); } catch(StringIndexOutOfBoundsException e) { diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowBlockSuccessorClosure.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlockSuccessorClosure.java new file mode 100644 index 000000000..ec2a6dec0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlockSuccessorClosure.java @@ -0,0 +1,48 @@ +package dk.camelot64.kickc.model; + +import dk.camelot64.kickc.model.values.LabelRef; +import dk.camelot64.kickc.model.values.VariableRef; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +/** The transitive closure of control flow graph blocks */ +public class ControlFlowBlockSuccessorClosure { + + /** For each block this is the closure of all successor blocks. */ + private Map> blockSuccessorClosure; + + public ControlFlowBlockSuccessorClosure(Map> blockSuccessorClosure) { + this.blockSuccessorClosure = blockSuccessorClosure; + } + + /** + * Get all variables used or defined inside a block and its successors (including any called method) + * + * @param labelRef The block to examine + * @return All used variables + */ + public Collection getSuccessorClosureReferencedVars(LabelRef labelRef, VariableReferenceInfos varInfos) { + ArrayList variableRefs = new ArrayList<>(); + final Collection successors = blockSuccessorClosure.get(labelRef); + successors.forEach(labelRef1 -> variableRefs.addAll(varInfos.getReferencedVars(labelRef1))); + return variableRefs; + } + + + public String getSizeInfo() { + StringBuilder sizeInfo = new StringBuilder(); + if(blockSuccessorClosure != null) { + sizeInfo.append("SIZE blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels "); + int sub = 0; + for(Collection labelRefs : blockSuccessorClosure.values()) { + sub += labelRefs.size(); + } + sizeInfo.append(" ").append(sub).append(" labels").append("\n"); + } + return sizeInfo.toString(); + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffectiveCallPaths.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffectiveCallPaths.java index 04d975593..3c4729e82 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffectiveCallPaths.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffectiveCallPaths.java @@ -33,15 +33,17 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE /** Variables (normally) alive at each statement by index. */ private Map> statementLiveVariables; - /** - * Information about which procedures reference which variables. - */ + /** Information about which procedures reference which variables. */ private VariableReferenceInfos referenceInfo; - public LiveRangeVariablesEffectiveCallPaths(Program program, Map procedureCallPaths, LiveRangeVariables liveRangeVariables, VariableReferenceInfos referenceInfo) { + /** Information about which blocks follow other blocks. */ + private ControlFlowBlockSuccessorClosure blockSuccessorClosure; + + public LiveRangeVariablesEffectiveCallPaths(Program program, Map procedureCallPaths, LiveRangeVariables liveRangeVariables, VariableReferenceInfos referenceInfo, ControlFlowBlockSuccessorClosure blockSuccessorClosure) { this.program = program; this.procedureCallPaths = procedureCallPaths; this.referenceInfo = referenceInfo; + this.blockSuccessorClosure = blockSuccessorClosure; this.statementLiveVariables = new LinkedHashMap<>(); for(ControlFlowBlock block : program.getGraph().getAllBlocks()) { for(Statement statement : block.getStatements()) { @@ -106,7 +108,7 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE if(scope instanceof Procedure) { Procedure procedure = (Procedure) scope; callPaths = procedureCallPaths.get(procedure.getRef()); - referencedInProcedure = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef()); + referencedInProcedure = blockSuccessorClosure.getSuccessorClosureReferencedVars(procedure.getRef().getLabelRef(), referenceInfo); } else { callPaths = new CallPaths(ROOT_PROCEDURE); // Interrupt is called outside procedure scope - create initial call-path. diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java index ecf0482d5..2c30b2dd8 100644 --- a/src/main/java/dk/camelot64/kickc/model/Program.java +++ b/src/main/java/dk/camelot64/kickc/model/Program.java @@ -79,6 +79,8 @@ public class Program { private CallGraph callGraph; /** Cached information about the variables referenced by blocks/statements. PASS 1-4 (CACHED ON-DEMAND) */ private VariableReferenceInfos variableReferenceInfos; + /** Cached information about the closure of all block successors. */ + private ControlFlowBlockSuccessorClosure blockSuccessorClosure; /** Information about dominators of all blocks. PASS 2U-4 (CACHED ON-DEMAND) */ private DominatorsGraph dominators; /** Cached information about symbols. Contains a symbol table cache for fast access. PASS 3-4 (CACHED ON-DEMAND) */ @@ -339,6 +341,16 @@ public class Program { this.variableReferenceInfos = null; } + public ControlFlowBlockSuccessorClosure getControlFlowBlockSuccessorClosure() { + if(blockSuccessorClosure == null) + this.blockSuccessorClosure = new PassNCalcBlockSuccessorClosure(this).calculate(); + return blockSuccessorClosure; + } + + public void clearControlFlowBlockSuccessorClosure() { + this.blockSuccessorClosure = null; + } + public DominatorsGraph getDominators() { if(dominators == null) this.dominators = new PassNCalcDominators(this).calculate(); diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java index 273d78734..a3e6bf227 100644 --- a/src/main/java/dk/camelot64/kickc/model/Registers.java +++ b/src/main/java/dk/camelot64/kickc/model/Registers.java @@ -203,7 +203,7 @@ public class Registers { @Override public int hashCode() { - return Objects.hash(zp, bytes, nonRelocatable); + return zp; } } diff --git a/src/main/java/dk/camelot64/kickc/model/StatementInfos.java b/src/main/java/dk/camelot64/kickc/model/StatementInfos.java index dbd9b42b5..3755c669c 100644 --- a/src/main/java/dk/camelot64/kickc/model/StatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/StatementInfos.java @@ -11,7 +11,7 @@ public class StatementInfos { /** The control flow graph. */ private ControlFlowGraph graph; - /** Maps statement index to block label. */ + /** Maps statement index to block. */ private Map stmtBlocks; /** Maps statement index to statement. */ diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java index 505a3b9bf..1ae58bf64 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java @@ -20,9 +20,6 @@ import java.util.stream.Collectors; */ public class VariableReferenceInfos { - /** For each block this is the closure of all successor blocks. */ - private Map> blockSuccessorClosure; - /** References to variables/constants by block label. */ private Map> blockVarReferences; @@ -124,12 +121,10 @@ public class VariableReferenceInfos { } public VariableReferenceInfos( - Map> blockSuccessorClosure, Map> symbolVarReferences, Map> blockVarReferences, Map> statementVarReferences ) { - this.blockSuccessorClosure = blockSuccessorClosure; this.symbolVarReferences = symbolVarReferences; this.blockVarReferences = blockVarReferences; this.statementVarReferences = statementVarReferences; @@ -137,14 +132,6 @@ public class VariableReferenceInfos { public String getSizeInfo() { StringBuilder sizeInfo = new StringBuilder(); - if(blockSuccessorClosure != null) { - sizeInfo.append("SIZE blockSuccessorClosure ").append(blockSuccessorClosure.size()).append(" labels "); - int sub = 0; - for(Collection labelRefs : blockSuccessorClosure.values()) { - sub += labelRefs.size(); - } - sizeInfo.append(" ").append(sub).append(" labels").append("\n"); - } { sizeInfo.append("SIZE symbolVarReferences ").append(symbolVarReferences.size()).append(" SymbolVariableRefs "); int sub = 0; @@ -182,28 +169,6 @@ public class VariableReferenceInfos { return PassNCalcVariableReferenceInfos.getReferencedVars(rValue); } - /** - * Get all variables used or defined inside a block and its successors (including any called method) - * - * @param labelRef The block to examine - * @return All used variables - */ - public Collection getReferencedVars(LabelRef labelRef) { - ArrayList variableRefs = new ArrayList<>(); - blockSuccessorClosure.get(labelRef) - .forEach(labelRef1 -> blockVarReferences - .get(labelRef1) - .stream() - .filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef) - .forEach(referenceToSymbolVar -> { - if(!variableRefs.contains(referenceToSymbolVar.getReferenced())) - variableRefs.add((VariableRef) referenceToSymbolVar.getReferenced()); - } - ) - ); - return variableRefs; - } - /** * Get the variables defined by a statement * @@ -213,7 +178,7 @@ public class VariableReferenceInfos { public Collection getDefinedVars(Statement stmt) { Collection referenceToSymbolVars = statementVarReferences.get(stmt.getIndex()); // TODO: This may cause problems since it is a sign that the maps are out of date! - if(referenceToSymbolVars==null) + if(referenceToSymbolVars == null) return new ArrayList<>(); return referenceToSymbolVars .stream() @@ -255,6 +220,26 @@ public class VariableReferenceInfos { .collect(Collectors.toList()); } + /** + * Get the variables referenced (used or defined) in a block. + * + * @param labelRef The label of the block. + * @return The referenced variables + */ + public Collection getReferencedVars(LabelRef labelRef) { + ArrayList variableRefs = new ArrayList<>(); + blockVarReferences + .get(labelRef) + .stream() + .filter(referenceToSymbolVar -> referenceToSymbolVar.getReferenced() instanceof VariableRef) + .forEach(referenceToSymbolVar -> { + if(!variableRefs.contains(referenceToSymbolVar.getReferenced())) + variableRefs.add((VariableRef) referenceToSymbolVar.getReferenced()); + } + ); + return variableRefs; + } + /** * Determines if a variable is unused * diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java index 318b8a5b6..dbfa5924f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AssertUsedVars.java @@ -32,6 +32,7 @@ public class Pass1AssertUsedVars extends Pass1Base { new PassNStatementIndices(getProgram()).execute(); getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME)); @@ -44,6 +45,7 @@ public class Pass1AssertUsedVars extends Pass1Base { } assertUsedVars(beginBlock, null, referenceInfos, defined, new LinkedHashSet<>()); getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); getProgram().clearStatementIndices(); return false; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1CallVoidReturns.java b/src/main/java/dk/camelot64/kickc/passes/Pass1CallVoidReturns.java index 804f67ac0..c24d68a44 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1CallVoidReturns.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1CallVoidReturns.java @@ -26,6 +26,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization { public boolean step() { new PassNStatementIndices(getProgram()).execute(); getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); for(ControlFlowBlock block : getGraph().getAllBlocks()) { @@ -59,6 +60,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization { } getProgram().clearStatementIndices(); getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); return false; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2LoopHeadConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopHeadConstantIdentification.java index 3840fb9df..a9b01bdc2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2LoopHeadConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2LoopHeadConstantIdentification.java @@ -37,6 +37,7 @@ public class Pass2LoopHeadConstantIdentification extends Pass2SsaOptimization { boolean modified = optimizeLoopHead(loopHeadBlock, loop, variableReferenceInfos); if(modified) { getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); getProgram().clearStatementInfos(); getProgram().clearLoopSet(); getProgram().clearDominators(); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java index 576ff30ed..9a60c6f50 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNEliminateUnusedVars.java @@ -31,6 +31,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization { public boolean step() { new PassNStatementIndices(getProgram()).execute(); getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos(); boolean modified = false; for(ControlFlowBlock block : getGraph().getAllBlocks()) { @@ -138,6 +139,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization { } getProgram().clearVariableReferenceInfos(); + getProgram().clearControlFlowBlockSuccessorClosure(); getProgram().clearStatementIndices(); return modified; } diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcBlockSuccessorClosure.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcBlockSuccessorClosure.java new file mode 100644 index 000000000..5f0432181 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcBlockSuccessorClosure.java @@ -0,0 +1,62 @@ +package dk.camelot64.kickc.passes.calcs; + +import dk.camelot64.kickc.model.ControlFlowBlock; +import dk.camelot64.kickc.model.ControlFlowBlockSuccessorClosure; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.statements.Statement; +import dk.camelot64.kickc.model.statements.StatementCallExecute; +import dk.camelot64.kickc.model.values.LabelRef; +import dk.camelot64.kickc.model.values.ProcedureRef; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; + +/** Calculates {@link dk.camelot64.kickc.model.ControlFlowBlockSuccessorClosure}. */ +public class PassNCalcBlockSuccessorClosure extends PassNCalcBase { + + public PassNCalcBlockSuccessorClosure(Program program) { + super(program); + } + + @Override + public ControlFlowBlockSuccessorClosure calculate() { + LinkedHashMap> blockSuccessors = new LinkedHashMap<>(); + for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) { + LabelRef blockLabel = block.getLabel(); + LinkedHashSet successorClosure = new LinkedHashSet<>(); + findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>()); + blockSuccessors.put(blockLabel, successorClosure); + } + return new ControlFlowBlockSuccessorClosure(blockSuccessors); + } + + /** + * Recursively get all blocks in the closure of successors & calls for a specific block + * + * @param labelRef The block to examine + * @param successorClosure the set of all blocks that are successors (including called methods). + * @param visited The blocks already visited during the search. Used to stop infinite recursion. + */ + private void findSuccessorClosure(LabelRef labelRef, LinkedHashSet successorClosure, Collection visited) { + if(labelRef == null || visited.contains(labelRef)) + return; + visited.add(labelRef); + ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef); + if(block == null) + return; + successorClosure.add(labelRef); + findSuccessorClosure(block.getDefaultSuccessor(), successorClosure, visited); + findSuccessorClosure(block.getConditionalSuccessor(), successorClosure, visited); + findSuccessorClosure(block.getCallSuccessor(), successorClosure, visited); + // Also handle stack-calls + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementCallExecute) { + final ProcedureRef calledProcRef = ((StatementCallExecute) statement).getProcedure(); + findSuccessorClosure(calledProcRef.getLabelRef(), successorClosure, visited); + } + } + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangeVariables.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangeVariables.java index b93f2d56a..c25684cb8 100644 --- a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangeVariables.java +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangeVariables.java @@ -42,10 +42,11 @@ public class PassNCalcLiveRangeVariables extends PassNCalcBase> calculateProcedureReferencedVars(Program program) { VariableReferenceInfos referenceInfo = program.getVariableReferenceInfos(); + final ControlFlowBlockSuccessorClosure blockSuccessorClosure = program.getControlFlowBlockSuccessorClosure(); Collection allProcedures = program.getScope().getAllProcedures(true); Map> procReferencedVars = new LinkedHashMap<>(); for(Procedure procedure : allProcedures) { - Collection referencedVars = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef()); + Collection referencedVars = blockSuccessorClosure.getSuccessorClosureReferencedVars(procedure.getRef().getLabelRef(), referenceInfo); procReferencedVars.put(procedure.getRef(), referencedVars); } return procReferencedVars; diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangesEffectiveCallPaths.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangesEffectiveCallPaths.java index 5ddca5828..6c03ade54 100644 --- a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangesEffectiveCallPaths.java +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcLiveRangesEffectiveCallPaths.java @@ -33,18 +33,20 @@ public class PassNCalcLiveRangesEffectiveCallPaths extends PassNCalcBase(); populateProcedureCallPaths(); - LiveRangeVariablesEffectiveCallPaths aliveEffective = new LiveRangeVariablesEffectiveCallPaths(getProgram(), procedureCallPaths, liveRangeVariables, referenceInfo); + LiveRangeVariablesEffectiveCallPaths aliveEffective = new LiveRangeVariablesEffectiveCallPaths(getProgram(), procedureCallPaths, liveRangeVariables, referenceInfo, blockSuccessorClosure); return aliveEffective; //getLog().append("Calculated effective variable live ranges"); } @@ -92,7 +94,7 @@ public class PassNCalcLiveRangesEffectiveCallPaths extends PassNCalcBase referencedInCaller = referenceInfo.getReferencedVars(callerProcedure.getRef().getLabelRef()); + Collection referencedInCaller = blockSuccessorClosure.getSuccessorClosureReferencedVars(callerProcedure.getRef().getLabelRef(), referenceInfo); // For each caller path - create a new call-path LiveRangeVariablesEffectiveCallPaths.CallPaths callerPaths = procedureCallPaths.get(callerProcedure.getRef()); if(callerPaths!=null) diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java index 1e157883c..aac4ec64b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcVariableReferenceInfos.java @@ -22,8 +22,6 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase> blockSuccessors = new LinkedHashMap<>(); - Map> symbolVarReferences = new LinkedHashMap<>(); Map> blockVarReferences = new LinkedHashMap<>(); Map> statementVarReferences = new LinkedHashMap<>(); @@ -57,12 +55,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase successorClosure = new LinkedHashSet<>(); - findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>()); - blockSuccessors.put(blockLabel, successorClosure); - } + // Gather symbols in the symbol table referencing other variables/constants Collection allVariables = getProgram().getScope().getAllVars(true); for(Variable referencingVar : allVariables) { @@ -77,7 +70,7 @@ public class PassNCalcVariableReferenceInfos extends PassNCalcBase successorClosure, Collection visited) { - if(labelRef == null || visited.contains(labelRef)) - return; - visited.add(labelRef); - ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef); - if(block == null) - return; - successorClosure.add(labelRef); - findSuccessorClosure(block.getDefaultSuccessor(), successorClosure, visited); - findSuccessorClosure(block.getConditionalSuccessor(), successorClosure, visited); - findSuccessorClosure(block.getCallSuccessor(), successorClosure, visited); - // Also handle stack-calls - for(Statement statement : block.getStatements()) { - if(statement instanceof StatementCallExecute) { - final ProcedureRef calledProcRef = ((StatementCallExecute) statement).getProcedure(); - findSuccessorClosure(calledProcRef.getLabelRef(), successorClosure, visited); - } - } - } - - /** * Get the variables defined by a statement * diff --git a/src/test/java/dk/camelot64/kickc/test/TestFragments.java b/src/test/java/dk/camelot64/kickc/test/TestFragments.java index 60761823c..3411406b4 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestFragments.java +++ b/src/test/java/dk/camelot64/kickc/test/TestFragments.java @@ -140,6 +140,13 @@ public class TestFragments { testFragments("fragments-complex", signaturesComplex); } + // @Test + // public void testPointers() throws IOException { + // List signatures = Arrays.asList("vbuz1=pbuz2_derefidx_vbuc1"); + // testFragments("fragments-complex", signatures); + // } + + @Test public void testFragmentsExist() { testFragmentExists("vbuaa=pbuc2_derefidx_vbuxx"); diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 036e4b2c7..a446d0ba1 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -4308,8 +4308,8 @@ public class TestPrograms { @BeforeClass public static void setUp() { Path asmFragmentBaseFolder = new File("src/main/fragment/").toPath(); - Path asmFragmentCacheFolder = null; - asmFragmentSynthesizer = new AsmFragmentTemplateSynthesizer(asmFragmentBaseFolder, TargetCpu.MOS6502X, asmFragmentCacheFolder, new CompileLog()); + // Path asmFragmentCacheFolder = new File("src/main/fragment/cache").toPath(); + asmFragmentSynthesizer = new AsmFragmentTemplateSynthesizer(asmFragmentBaseFolder, TargetCpu.MOS6502X, null, new CompileLog()); } @AfterClass