diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java index a58c4d37c..83cbf1c04 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java @@ -84,14 +84,19 @@ public class LiveRangeVariablesEffective { */ private Collection alive; /** - * Alias variables on the call-path. All global aliases plus any variables alias-assigned in a phi-block on the path. + * Alias variables for the innermost call. Variables alias-assigned as part of the innermost call on the path (in parameter assignment or phi block). */ - private Pass2AliasElimination.Aliases aliases; + private Pass2AliasElimination.Aliases innerAliases; + /** + * Alias variables from the entire call-path. Any variables alias-assigned as part of a call on the path (in parameter assignment or phi block). + */ + private Pass2AliasElimination.Aliases pathAliases; - public CallPath(List path, Collection alive, Pass2AliasElimination.Aliases aliases) { + public CallPath(List path, Collection alive, Pass2AliasElimination.Aliases innerAliases, Pass2AliasElimination.Aliases pathAliases) { this.path = path; this.alive = alive; - this.aliases = aliases; + this.innerAliases = innerAliases; + this.pathAliases = pathAliases; } /** @@ -111,11 +116,19 @@ public class LiveRangeVariablesEffective { } /** - * Alias variables on the call-path. All global aliases plus any variables alias-assigned in a phi-block on the path. + * Alias variables from the entire call-path. Any variables alias-assigned as part of a call on the path (in parameter assignment or phi block). * @return The aliases */ - public Pass2AliasElimination.Aliases getAliases() { - return aliases; + public Pass2AliasElimination.Aliases getPathAliases() { + return pathAliases; + } + + /** + * Alias variables for the innermost call. Variables alias-assigned as part of the innermost call on the path (in parameter assignment or phi block). + * @return The aliases + */ + public Pass2AliasElimination.Aliases getInnerAliases() { + return innerAliases; } } @@ -141,8 +154,9 @@ public class LiveRangeVariablesEffective { /** * Get all combinations of variables alive at a statement. * If the statement is inside a method the different combinations in the result arises from different calls of the method - * (recursively up til the main()-method. + * (recursively up til the main()-method.) * Each combination includes all variables alive at the exit of any surrounding call. + * Also includes variable aliases that are part of the parameter assignments to the calls on the path. *

* * @param statement The statement to examine @@ -163,6 +177,9 @@ public class LiveRangeVariablesEffective { callPaths = new CallPaths(Procedure.ROOT); referencedInProcedure = new ArrayList<>(); } + // Examine if the statement is a parameter assignment before a call + throw new RuntimeException("Examine if the statement is a parameter assignment before a call - and add the inner aliases if it is"); + return new AliveCombinations(callPaths, referencedInProcedure, aliveAtStmt); } @@ -185,25 +202,22 @@ public class LiveRangeVariablesEffective { * Variables alive at the statement inside the procedure. */ private Collection aliveAtStmt; + /** + * If the statement is an assignment to a call parameter this contains the aliases for that specific call. + */ + private Pass2AliasElimination.Aliases callAliases; - public AliveCombinations(CallPaths callPaths, Collection referencedInProcedure, Collection aliveAtStmt) { + public AliveCombinations(CallPaths callPaths, Collection referencedInProcedure, Collection aliveAtStmt, Pass2AliasElimination.Aliases callAliases) { this.callPaths = callPaths; this.referencedInProcedure = referencedInProcedure; this.aliveAtStmt = aliveAtStmt; + this.callAliases = callAliases; } public CallPaths getCallPaths() { return callPaths; } - public Collection getReferencedInProcedure() { - return referencedInProcedure; - } - - public Collection getAliveAtStmt() { - return aliveAtStmt; - } - /** * Get all variables effective alive at the statement for a specific call path. * @param callPath The call path (returned from getCallPaths) @@ -220,6 +234,16 @@ public class LiveRangeVariablesEffective { return effectiveAlive; } + public Pass2AliasElimination.Aliases getEffectiveAliasesAtStmt(CallPath callPath) { + if(callAliases==null) { + return callPath.getPathAliases(); + } else { + Pass2AliasElimination.Aliases aliases = new Pass2AliasElimination.Aliases(); + aliases.addAll(callPath.getPathAliases()); + aliases.addAll(callAliases); + return aliases; + } + } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java index 065d7d62f..726d1416a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -157,6 +157,20 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { public List getAliasSets() { return aliases; } + + public void addAll(Aliases aliases) { + for (AliasSet aliasSet : aliases.getAliasSets()) { + List vars = aliasSet.getVars(); + VariableRef first = null; + for (VariableRef var : vars) { + if(first==null) { + first = var; + } else { + add(first, var); + } + } + } + } } public static class AliasSet { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java index 12d0cf8e0..a5523c5c9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesEffectiveAnalysis.java @@ -39,54 +39,6 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { //getLog().append("Calculated effective variable live ranges"); } - /** - * Get all variables alive at a statement. - * If the statement is inside a method this also includes all variables alive at the exit of the calls. - *

- * This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph. - *

- * @param statement The statement to examine - * @return All variables alive at the statement - */ - private Collection> findAliveEffective(LiveRangeVariables liveRangeVariables, Statement statement) { - Set> combinations = new LinkedHashSet<>(); - // Get variables alive from live range analysis - Collection effectiveAlive = liveRangeVariables.getAlive(statement); - // If the statement is inside a method recurse back to all calls - // For each call add the variables alive after the call that are not referenced (used/defined) inside the method - ControlFlowBlock block = getProgram().getGraph().getBlockFromStatementIdx(statement.getIndex()); - ScopeRef scopeRef = block.getScope(); - Scope scope = getProgram().getScope().getScope(scopeRef); - if (scope instanceof Procedure) { - Procedure procedure = (Procedure) scope; - Collection callers = - getProgram().getCallGraph().getCallers(procedure.getLabel().getRef()); - Collection referencedInProcedure = referenceInfo.getReferenced(procedure.getRef().getLabelRef()); - for (CallGraph.CallBlock.Call caller : callers) { - // Each caller creates its own combinations - StatementCall callStatement = - (StatementCall) getProgram().getGraph().getStatementByIndex(caller.getCallStatementIdx()); - Collection> callerCombinations = findAliveEffective(liveRangeVariables, callStatement); - for (Collection callerCombination : callerCombinations) { - LinkedHashSet combination = new LinkedHashSet<>(); - // Add alive at call - combination.addAll(callerCombination); - // Clear out any variables referenced in the method - combination.removeAll(referencedInProcedure); - // Add alive at statement - combination.addAll(effectiveAlive); - // Add combination - combinations.add(combination); - } - } - } - if(combinations.size()==0) { - // Add the combination at the current statement if no other combinations have been created - combinations.add(effectiveAlive); - } - return combinations; - } - private void populateProcedureCallPaths() { this.procedureCallPaths = new LinkedHashMap<>(); Collection procedures = getProgram().getScope().getAllProcedures(true); @@ -125,8 +77,11 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { alive.addAll(callerPath.getAlive()); alive.removeAll(referencedInCaller); alive.addAll(liveRangeVariables.getAlive(callStatement)); - Pass2AliasElimination.Aliases aliases = getCallAliases(procedure, callBlock, callerPath); - LiveRangeVariablesEffective.CallPath callPath = new LiveRangeVariablesEffective.CallPath(path, alive, aliases); + Pass2AliasElimination.Aliases innerAliases = getCallAliases(procedure, callBlock); + Pass2AliasElimination.Aliases pathAliases = new Pass2AliasElimination.Aliases(); + pathAliases.addAll(callerPath.getPathAliases()); + pathAliases.addAll(innerAliases); + LiveRangeVariablesEffective.CallPath callPath = new LiveRangeVariablesEffective.CallPath(path, alive, innerAliases, pathAliases); callPaths.add(callPath); } } else { @@ -134,9 +89,9 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { ArrayList rootPath = new ArrayList<>(); rootPath.add(caller); ArrayList rootAlive = new ArrayList<>(); - // Initialize with global cross-scope aliases + // Initialize with global cross-scope aliases (assumed empty) Pass2AliasElimination.Aliases rootAliases = new Pass2AliasElimination.Aliases(); - LiveRangeVariablesEffective.CallPath rootCallPath = new LiveRangeVariablesEffective.CallPath(rootPath, rootAlive, rootAliases); + LiveRangeVariablesEffective.CallPath rootCallPath = new LiveRangeVariablesEffective.CallPath(rootPath, rootAlive, rootAliases, rootAliases); callPaths.add(rootCallPath); } } @@ -146,18 +101,17 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { /** * Find aliases defined when taking a specific call - meaning call parameters that have specific values when taking the specific call. - * @param procedurePhiBlock The phi-block of the called procedure + * @param procedure The called procedure * @param callBlock The block performing the call - * @param callerPath The call-path from main() to the calling procedure. (contains aliases for all preceding calls) * @return Aliases defined by the specific call. */ - private Pass2AliasElimination.Aliases getCallAliases(Procedure procedure, ControlFlowBlock callBlock, LiveRangeVariablesEffective.CallPath callerPath) { + private Pass2AliasElimination.Aliases getCallAliases(Procedure procedure, ControlFlowBlock callBlock) { ControlFlowBlock procedureBlock = getProgram().getGraph().getBlock(procedure.getLabel().getRef()); StatementPhiBlock procedurePhiBlock = null; if(procedureBlock.hasPhiBlock()) { procedurePhiBlock = procedureBlock.getPhiBlock(); } - Pass2AliasElimination.Aliases aliases = new Pass2AliasElimination.Aliases(callerPath.getAliases()); + Pass2AliasElimination.Aliases aliases = new Pass2AliasElimination.Aliases(); // Find aliases inside the phi-block of the called method if(procedurePhiBlock!=null) { for (StatementPhiBlock.PhiVariable phiVariable : procedurePhiBlock.getPhiVariables()) { @@ -167,7 +121,7 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base { } } } - // Find call parameter aliasses in the calling block before the call + // Find call parameter aliases in the calling block before the call for (Statement statement : callBlock.getStatements()) { if(statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java index cc6933ca7..5a22ccea4 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftCombinations.java @@ -221,7 +221,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base { for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) { LinkedHashMap usedRegisters = new LinkedHashMap<>(); Collection alive = aliveCombinations.getEffectiveAliveAtStmt(callPath); - Pass2AliasElimination.Aliases callPathAliases = callPath.getAliases(); + Pass2AliasElimination.Aliases callPathAliases = aliveCombinations.getEffectiveAliasesAtStmt(callPath); for (VariableRef varRef : alive) { Variable var = programScope.getVariable(varRef); Registers.Register allocation = var.getAllocation();