From a3c18cf75673f5f031fd35a71e6413b54b3ca7c1 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Fri, 10 Nov 2017 00:01:49 +0100 Subject: [PATCH] Optimized live range equivalence classe set lookup from variable to spped up uplift. --- .../model/LiveRangeEquivalenceClass.java | 25 ++++---- .../model/LiveRangeEquivalenceClassSet.java | 61 +++++++++++++++---- .../kickc/passes/Pass3PhiMemCoalesce.java | 6 +- .../passes/Pass4RegisterUpliftStatic.java | 3 +- .../kickc/passes/Pass4ZeroPageCoalesce.java | 3 +- 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java index d7b9b2a45..a33a370b2 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java @@ -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 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 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 getVariables() { - return variables; - } } diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java index d09e55631..f60bd6493 100644 --- a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java +++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java @@ -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 equivalenceClasses; + /** + * Maps variables to their containing class. + */ + Map 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 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). */ diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java index 4dd6fa31f..24d5e84be 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java @@ -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); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java index f9a1de7bb..143be94ea 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftStatic.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4ZeroPageCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass4ZeroPageCoalesce.java index b71409e32..eae6cac3e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4ZeroPageCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4ZeroPageCoalesce.java @@ -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;