mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Working on handling procedure parameter aliases
This commit is contained in:
parent
e4bf84c57c
commit
4fd32274af
@ -84,14 +84,19 @@ public class LiveRangeVariablesEffective {
|
|||||||
*/
|
*/
|
||||||
private Collection<VariableRef> alive;
|
private Collection<VariableRef> 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<CallGraph.CallBlock.Call> path, Collection<VariableRef> alive, Pass2AliasElimination.Aliases aliases) {
|
public CallPath(List<CallGraph.CallBlock.Call> path, Collection<VariableRef> alive, Pass2AliasElimination.Aliases innerAliases, Pass2AliasElimination.Aliases pathAliases) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.alive = alive;
|
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
|
* @return The aliases
|
||||||
*/
|
*/
|
||||||
public Pass2AliasElimination.Aliases getAliases() {
|
public Pass2AliasElimination.Aliases getPathAliases() {
|
||||||
return aliases;
|
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.
|
* 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
|
* 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.
|
* 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.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param statement The statement to examine
|
* @param statement The statement to examine
|
||||||
@ -163,6 +177,9 @@ public class LiveRangeVariablesEffective {
|
|||||||
callPaths = new CallPaths(Procedure.ROOT);
|
callPaths = new CallPaths(Procedure.ROOT);
|
||||||
referencedInProcedure = new ArrayList<>();
|
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);
|
return new AliveCombinations(callPaths, referencedInProcedure, aliveAtStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,25 +202,22 @@ public class LiveRangeVariablesEffective {
|
|||||||
* Variables alive at the statement inside the procedure.
|
* Variables alive at the statement inside the procedure.
|
||||||
*/
|
*/
|
||||||
private Collection<VariableRef> aliveAtStmt;
|
private Collection<VariableRef> 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<VariableRef> referencedInProcedure, Collection<VariableRef> aliveAtStmt) {
|
public AliveCombinations(CallPaths callPaths, Collection<VariableRef> referencedInProcedure, Collection<VariableRef> aliveAtStmt, Pass2AliasElimination.Aliases callAliases) {
|
||||||
this.callPaths = callPaths;
|
this.callPaths = callPaths;
|
||||||
this.referencedInProcedure = referencedInProcedure;
|
this.referencedInProcedure = referencedInProcedure;
|
||||||
this.aliveAtStmt = aliveAtStmt;
|
this.aliveAtStmt = aliveAtStmt;
|
||||||
|
this.callAliases = callAliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallPaths getCallPaths() {
|
public CallPaths getCallPaths() {
|
||||||
return callPaths;
|
return callPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<VariableRef> getReferencedInProcedure() {
|
|
||||||
return referencedInProcedure;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<VariableRef> getAliveAtStmt() {
|
|
||||||
return aliveAtStmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all variables effective alive at the statement for a specific call path.
|
* Get all variables effective alive at the statement for a specific call path.
|
||||||
* @param callPath The call path (returned from getCallPaths)
|
* @param callPath The call path (returned from getCallPaths)
|
||||||
@ -220,6 +234,16 @@ public class LiveRangeVariablesEffective {
|
|||||||
return effectiveAlive;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,6 +157,20 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
|||||||
public List<AliasSet> getAliasSets() {
|
public List<AliasSet> getAliasSets() {
|
||||||
return aliases;
|
return aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAll(Aliases aliases) {
|
||||||
|
for (AliasSet aliasSet : aliases.getAliasSets()) {
|
||||||
|
List<VariableRef> vars = aliasSet.getVars();
|
||||||
|
VariableRef first = null;
|
||||||
|
for (VariableRef var : vars) {
|
||||||
|
if(first==null) {
|
||||||
|
first = var;
|
||||||
|
} else {
|
||||||
|
add(first, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AliasSet {
|
public static class AliasSet {
|
||||||
|
@ -39,54 +39,6 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
|||||||
//getLog().append("Calculated effective variable live ranges");
|
//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.
|
|
||||||
* <p>
|
|
||||||
* This method requires a number of other analysis to be present and updated in the (global) program - especailly the Call Graph.
|
|
||||||
* </p>
|
|
||||||
* @param statement The statement to examine
|
|
||||||
* @return All variables alive at the statement
|
|
||||||
*/
|
|
||||||
private Collection<Collection<VariableRef>> findAliveEffective(LiveRangeVariables liveRangeVariables, Statement statement) {
|
|
||||||
Set<Collection<VariableRef>> combinations = new LinkedHashSet<>();
|
|
||||||
// Get variables alive from live range analysis
|
|
||||||
Collection<VariableRef> 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<CallGraph.CallBlock.Call> callers =
|
|
||||||
getProgram().getCallGraph().getCallers(procedure.getLabel().getRef());
|
|
||||||
Collection<VariableRef> 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<Collection<VariableRef>> callerCombinations = findAliveEffective(liveRangeVariables, callStatement);
|
|
||||||
for (Collection<VariableRef> callerCombination : callerCombinations) {
|
|
||||||
LinkedHashSet<VariableRef> 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() {
|
private void populateProcedureCallPaths() {
|
||||||
this.procedureCallPaths = new LinkedHashMap<>();
|
this.procedureCallPaths = new LinkedHashMap<>();
|
||||||
Collection<Procedure> procedures = getProgram().getScope().getAllProcedures(true);
|
Collection<Procedure> procedures = getProgram().getScope().getAllProcedures(true);
|
||||||
@ -125,8 +77,11 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
|||||||
alive.addAll(callerPath.getAlive());
|
alive.addAll(callerPath.getAlive());
|
||||||
alive.removeAll(referencedInCaller);
|
alive.removeAll(referencedInCaller);
|
||||||
alive.addAll(liveRangeVariables.getAlive(callStatement));
|
alive.addAll(liveRangeVariables.getAlive(callStatement));
|
||||||
Pass2AliasElimination.Aliases aliases = getCallAliases(procedure, callBlock, callerPath);
|
Pass2AliasElimination.Aliases innerAliases = getCallAliases(procedure, callBlock);
|
||||||
LiveRangeVariablesEffective.CallPath callPath = new LiveRangeVariablesEffective.CallPath(path, alive, aliases);
|
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);
|
callPaths.add(callPath);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -134,9 +89,9 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
|||||||
ArrayList<CallGraph.CallBlock.Call> rootPath = new ArrayList<>();
|
ArrayList<CallGraph.CallBlock.Call> rootPath = new ArrayList<>();
|
||||||
rootPath.add(caller);
|
rootPath.add(caller);
|
||||||
ArrayList<VariableRef> rootAlive = new ArrayList<>();
|
ArrayList<VariableRef> rootAlive = new ArrayList<>();
|
||||||
// Initialize with global cross-scope aliases
|
// Initialize with global cross-scope aliases (assumed empty)
|
||||||
Pass2AliasElimination.Aliases rootAliases = new Pass2AliasElimination.Aliases();
|
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);
|
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.
|
* 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 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.
|
* @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());
|
ControlFlowBlock procedureBlock = getProgram().getGraph().getBlock(procedure.getLabel().getRef());
|
||||||
StatementPhiBlock procedurePhiBlock = null;
|
StatementPhiBlock procedurePhiBlock = null;
|
||||||
if(procedureBlock.hasPhiBlock()) {
|
if(procedureBlock.hasPhiBlock()) {
|
||||||
procedurePhiBlock = procedureBlock.getPhiBlock();
|
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
|
// Find aliases inside the phi-block of the called method
|
||||||
if(procedurePhiBlock!=null) {
|
if(procedurePhiBlock!=null) {
|
||||||
for (StatementPhiBlock.PhiVariable phiVariable : procedurePhiBlock.getPhiVariables()) {
|
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()) {
|
for (Statement statement : callBlock.getStatements()) {
|
||||||
if(statement instanceof StatementAssignment) {
|
if(statement instanceof StatementAssignment) {
|
||||||
StatementAssignment assignment = (StatementAssignment) statement;
|
StatementAssignment assignment = (StatementAssignment) statement;
|
||||||
|
@ -221,7 +221,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
|
|||||||
for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
|
for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
|
||||||
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>();
|
LinkedHashMap<Registers.Register, LiveRangeEquivalenceClass> usedRegisters = new LinkedHashMap<>();
|
||||||
Collection<VariableRef> alive = aliveCombinations.getEffectiveAliveAtStmt(callPath);
|
Collection<VariableRef> alive = aliveCombinations.getEffectiveAliveAtStmt(callPath);
|
||||||
Pass2AliasElimination.Aliases callPathAliases = callPath.getAliases();
|
Pass2AliasElimination.Aliases callPathAliases = aliveCombinations.getEffectiveAliasesAtStmt(callPath);
|
||||||
for (VariableRef varRef : alive) {
|
for (VariableRef varRef : alive) {
|
||||||
Variable var = programScope.getVariable(varRef);
|
Variable var = programScope.getVariable(varRef);
|
||||||
Registers.Register allocation = var.getAllocation();
|
Registers.Register allocation = var.getAllocation();
|
||||||
|
Loading…
Reference in New Issue
Block a user