1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Optimized live range equivalence classe set lookup from variable to spped up uplift.

This commit is contained in:
jespergravgaard 2017-11-10 00:01:49 +01:00
parent 58500b39e0
commit a3c18cf756
5 changed files with 67 additions and 31 deletions

View File

@ -8,8 +8,8 @@ import java.util.List;
**/
public class LiveRangeEquivalenceClass {
/** The containing program. */
private Program program;
/** The containing set. */
private LiveRangeEquivalenceClassSet set;
/** The variables of the equivalence class. */
private List<VariableRef> variables;
@ -20,8 +20,8 @@ public class LiveRangeEquivalenceClass {
/** A register allocated to hold all variables of the equivalence class. (null if no register is currently allocated) */
private Registers.Register register;
public LiveRangeEquivalenceClass(Program program) {
this.program = program;
public LiveRangeEquivalenceClass(LiveRangeEquivalenceClassSet set) {
this.set = set;
this.variables = new ArrayList<>();
this.liveRange = new LiveRange();
this.register = null;
@ -44,13 +44,18 @@ public class LiveRangeEquivalenceClass {
if(variables.contains(variable)) {
return;
}
LiveRangeVariables liveRanges = program.getLiveRangeVariables();
LiveRangeVariables liveRanges = set.getProgram().getLiveRangeVariables();
LiveRange varLiveRange = liveRanges.getLiveRange(variable);
if (liveRange.overlaps(varLiveRange)) {
throw new RuntimeException("Compilation error! Variable live range overlaps live range equivalence class live range. " + variable);
}
liveRange.add(varLiveRange);
variables.add(variable);
set.setVarClass(variable, this);
}
public List<VariableRef> getVariables() {
return variables;
}
/**
@ -68,17 +73,18 @@ public class LiveRangeEquivalenceClass {
}
public void addAll(LiveRangeEquivalenceClass other) {
variables.addAll(other.variables);
liveRange.add(other.liveRange);
variables.addAll(other.variables);
for (VariableRef variable : other.variables) {
set.setVarClass(variable, this);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LiveRangeEquivalenceClass that = (LiveRangeEquivalenceClass) o;
return variables.equals(that.variables);
}
@ -107,7 +113,4 @@ public class LiveRangeEquivalenceClass {
return s.toString();
}
public List<VariableRef> getVariables() {
return variables;
}
}

View File

@ -1,18 +1,43 @@
package dk.camelot64.kickc.model;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** A set of live range equivalence classes. */
/**
* A set of live range equivalence classes.
*/
public class LiveRangeEquivalenceClassSet {
/**
* The containing program.
*/
private Program program;
/**
* The equivalence classes of the set.
*/
private List<LiveRangeEquivalenceClass> equivalenceClasses;
/**
* Maps variables to their containing class.
*/
Map<VariableRef, LiveRangeEquivalenceClass> varClass;
public LiveRangeEquivalenceClassSet(Program program) {
this.program = program;
this.equivalenceClasses = new ArrayList<>();
this.varClass = new LinkedHashMap<>();
}
/**
* Get the containing program
*
* @return The program
*/
Program getProgram() {
return program;
}
/**
@ -28,12 +53,33 @@ public class LiveRangeEquivalenceClassSet {
return equivalenceClass;
}
// Not found - create it
equivalenceClass = new LiveRangeEquivalenceClass(program);
equivalenceClass = new LiveRangeEquivalenceClass(this);
equivalenceClasses.add(equivalenceClass);
equivalenceClass.addVariable(variable);
return equivalenceClass;
}
/**
* Consolidates two live range equivalence calsses into one.
* All variables and live ranges from the other class is added to the first one - and the other one is deleted.
* @param equivalenceClass The first live range equivalence class.
* @param otherEquivalenceClass The other live range equivalence class, that is added to the first and deleted.
*/
public void consolidate(LiveRangeEquivalenceClass equivalenceClass, LiveRangeEquivalenceClass otherEquivalenceClass) {
equivalenceClass.addAll(otherEquivalenceClass);
equivalenceClasses.remove(otherEquivalenceClass);
}
/**
* Informs the set that class of a variable has ben set - called by add/remove methods inside LiveRangeEquivalenceClass
*
* @param variable The variable
* @param equivalenceClass The class
*/
void setVarClass(VariableRef variable, LiveRangeEquivalenceClass equivalenceClass) {
varClass.put(variable, equivalenceClass);
}
/**
* Get the phi equivalence class for a specific variable.
*
@ -41,12 +87,7 @@ public class LiveRangeEquivalenceClassSet {
* @return The existing phi equivalence class. null if no equivalence class contains the variable.
*/
public LiveRangeEquivalenceClass getEquivalenceClass(VariableRef variable) {
for (LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
if (equivalenceClass.contains(variable)) {
return equivalenceClass;
}
}
return null;
return varClass.get(variable);
}
public List<LiveRangeEquivalenceClass> getEquivalenceClasses() {
@ -57,10 +98,6 @@ public class LiveRangeEquivalenceClassSet {
return equivalenceClasses.size();
}
public void remove(LiveRangeEquivalenceClass equivalenceClass) {
equivalenceClasses.remove(equivalenceClass);
}
/**
* Store the register allocation of the live range equivalence classes into the variables in the symbol table (program scope).
*/

View File

@ -76,8 +76,7 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
replace.put((VariableRef) assignment.getlValue(), assignVar);
getLog().append("Coalesced (already) " + assignment);
} else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) {
lValEquivalenceClass.addAll(assignVarEquivalenceClass);
phiEquivalenceClassSet.remove(assignVarEquivalenceClass);
phiEquivalenceClassSet.consolidate(lValEquivalenceClass, assignVarEquivalenceClass);
remove.add((VariableRef) assignment.getlValue());
replace.put((VariableRef) assignment.getlValue(), assignVar);
getLog().append("Coalesced " + assignment);
@ -112,8 +111,7 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
VariableRef phiRVar = (VariableRef) phiRValue.getrValue();
LiveRangeEquivalenceClass rValEquivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(phiRVar);
if(!rValEquivalenceClass.equals(equivalenceClass)) {
equivalenceClass.addAll(rValEquivalenceClass);
phiEquivalenceClasses.remove(rValEquivalenceClass);
phiEquivalenceClasses.consolidate(equivalenceClass, rValEquivalenceClass);
}
}
}

View File

@ -124,8 +124,7 @@ public class Pass4RegisterUpliftStatic extends Pass2Base {
VariableRef variableRef2 = scope.getVariable(varFullName2).getRef();
LiveRangeEquivalenceClass equivalenceClass2 = equivalenceClassSet.getEquivalenceClass(variableRef2);
if(!equivalenceClass1.equals(equivalenceClass2)) {
equivalenceClass1.addAll(equivalenceClass2);
equivalenceClassSet.remove(equivalenceClass2);
equivalenceClassSet.consolidate(equivalenceClass1, equivalenceClass2);
}
}

View File

@ -34,8 +34,7 @@ public class Pass4ZeroPageCoalesce extends Pass2Base {
if (!myEquivalenceClass.equals(otherEquivalenceClass)) {
if(canCoalesce(myEquivalenceClass, otherEquivalenceClass)) {
getLog().append("Coalescing zero page register [ "+myEquivalenceClass+" ] with [ "+otherEquivalenceClass+" ]" );
myEquivalenceClass.addAll(otherEquivalenceClass);
liveRangeEquivalenceClassSet.remove(otherEquivalenceClass);
liveRangeEquivalenceClassSet.consolidate(myEquivalenceClass, otherEquivalenceClass);
// Reset the program register allocation
getProgram().getLiveRangeEquivalenceClassSet().storeRegisterAllocation();
return true;