1 cananian 1.1.2.1 /* 2 cananian 1.1.2.1 * RegAlloc/RegAlloc.java 3 cananian 1.1.2.1 * register allocator 4 cananian 1.1.2.1 * 5 cananian 1.1.2.1 * ALGORITHM: iterate coloring and spilling until no more 6 cananian 1.1.2.1 * temporaries are left to be spilled. 7 cananian 1.1.2.1 * 8 cananian 1.1.2.1 * C. Scott Ananian, cananian@princeton.edu, COS320 9 cananian 1.1.2.1 */ 10 cananian 1.1.2.1 11 cananian 1.1.2.2 package harpoon.Backend.CSAHack.RegAlloc; 12 cananian 1.1.2.1 13 cananian 1.1.2.2 import harpoon.Backend.Generic.Frame; 14 cananian 1.1.2.1 15 cananian 1.1.2.4 import harpoon.Analysis.Maps.Derivation; 16 cananian 1.1.2.4 17 cananian 1.1.2.2 import harpoon.Backend.CSAHack.Graph.Node; 18 cananian 1.1.2.2 import harpoon.Backend.CSAHack.Graph.NodeList; 19 cananian 1.1.2.1 20 cananian 1.1.2.4 import harpoon.ClassFile.HCodeEdge; 21 cananian 1.1.2.4 import harpoon.ClassFile.HCodeElement; 22 cananian 1.1.2.4 23 cananian 1.1.2.2 import harpoon.IR.Assem.Instr; 24 cananian 1.1.2.2 import harpoon.IR.Assem.InstrMOVE; 25 cananian 1.1.2.4 import harpoon.IR.Properties.CFGrapher; 26 cananian 1.1.2.4 import harpoon.IR.Properties.UseDefer; 27 cananian 1.1.2.2 28 cananian 1.1.2.2 import harpoon.Temp.Temp; 29 cananian 1.1.2.2 import harpoon.Temp.TempList; 30 cananian 1.1.2.2 import harpoon.Temp.TempMap; 31 cananian 1.1.2.2 32 cananian 1.1.2.2 import harpoon.Backend.CSAHack.FlowGraph.AssemFlowGraph; 33 cananian 1.5 import net.cscott.jutil.GenericMultiMap; 34 cananian 1.5 import net.cscott.jutil.MultiMap; 35 cananian 1.5 import net.cscott.jutil.Environment; 36 cananian 1.5 import net.cscott.jutil.HashEnvironment; 37 cananian 1.1.2.2 import harpoon.Util.Util; 38 cananian 1.1.2.1 39 cananian 1.1.2.4 import java.util.ArrayList; 40 cananian 1.1.2.4 import java.util.Collection; 41 cananian 1.1.2.4 import java.util.HashSet; 42 cananian 1.1.2.4 import java.util.Iterator; 43 cananian 1.1.2.4 import java.util.Set; 44 cananian 1.1.2.1 /** 45 cananian 1.1.2.1 * Register allocation module. 46 cananian 1.1.2.1 * @version 1.00, 25 Nov 1996 47 cananian 1.1.2.1 * @author C. Scott Ananian 48 cananian 1.1.2.1 */ 49 cananian 1.1.2.2 public class RegAlloc implements TempMap { 50 cananian 1.1.2.2 Frame frame; 51 cananian 1.1.2.2 Code code; 52 cananian 1.1.2.1 Color color; 53 cananian 1.1.2.1 54 cananian 1.1.2.1 /** 55 cananian 1.1.2.1 * A list of instructions that have been successfully allocated to 56 cananian 1.1.2.1 * registers (using the mapping defined by tempMap()). 57 cananian 1.1.2.1 * Instructions to spill variables may be added during the 58 cananian 1.1.2.1 * allocation process. 59 cananian 1.1.2.1 * Unnecessary moves may similarly be deleted. 60 cananian 1.1.2.1 */ 61 cananian 1.1.2.5 Instr instrs; // this is the head of the list. 62 cananian 1.1.2.5 /** A derivation generator, or null. */ 63 cananian 1.1.2.5 DerivationGenerator dg; 64 cananian 1.1.2.1 65 cananian 1.1.2.1 boolean debug = false; // enable debugging output. 66 cananian 1.1.2.6 static boolean quiet = false; // don't show progress 67 cananian 1.1.2.1 68 cananian 1.1.2.1 69 cananian 1.1.2.1 /** 70 cananian 1.1.2.1 * Allocate the temporaries defined and used in an Assem.InstrList to 71 cananian 1.1.2.2 * machine registers defined in a Frame. 72 cananian 1.1.2.1 * The resulting InstrList is placed in the instrs field of this class. 73 cananian 1.1.2.1 * @param f a machine-specific frame and register description 74 cananian 1.1.2.1 * @param il a list of instructions to be register allocated. 75 cananian 1.1.2.1 */ 76 cananian 1.1.2.5 public RegAlloc(final Frame f, Code c, Instr root, DerivationGenerator dg) { 77 cananian 1.1.2.1 AssemFlowGraph flow; 78 cananian 1.1.2.5 UseDefer ud0 = UseDefer.DEFAULT; 79 cananian 1.1.2.1 80 cananian 1.1.2.1 frame = f; 81 cananian 1.1.2.2 code = c; 82 cananian 1.1.2.2 instrs = root; 83 cananian 1.1.2.5 this.dg = dg; 84 cananian 1.1.2.1 85 cananian 1.1.2.5 UseDefer ud = (dg==null) ? ud0 : new DerivedUseDefer(c, ud0); 86 cananian 1.1.2.4 87 cananian 1.1.2.3 // thunk the register array to a register list... 88 cananian 1.1.2.3 TempList registers=null; 89 cananian 1.1.2.3 Temp[] reg = f.getRegFileInfo().getAllRegisters(); 90 cananian 1.1.2.3 for (int i=reg.length-1; i>=0; i--) 91 cananian 1.1.2.3 registers = new TempList(reg[i], registers); 92 cananian 1.1.2.3 93 cananian 1.1.2.1 // repeat these steps until no more variables need to be spilled: 94 cananian 1.1.2.6 if (!quiet) System.err.print("{"); 95 cananian 1.1.2.1 do { 96 cananian 1.1.2.1 // create a flow graph 97 cananian 1.1.2.6 if (!quiet) System.err.print("F"); 98 cananian 1.1.2.4 flow = new AssemFlowGraph(this.instrs, ud, true); 99 cananian 1.1.2.1 // create an interference graph after analyzing the flow for liveness. 100 cananian 1.1.2.6 if (!quiet) System.err.print("L"); 101 cananian 1.1.2.1 Liveness live = new Liveness(flow); 102 cananian 1.1.2.1 // possibly dump these graphs for debugging. 103 cananian 1.1.2.1 if (debug) { 104 cananian 1.1.2.1 flow.show(System.err); 105 cananian 1.1.2.1 live.show(System.err); 106 cananian 1.1.2.1 } 107 cananian 1.1.2.1 // color the temporaries using the interference graph. 108 cananian 1.1.2.6 if (!quiet) System.err.print("C"); 109 cananian 1.1.2.2 color = new Color(flow, live, new TempMap() { 110 cananian 1.1.2.2 public Temp tempMap(Temp t) { 111 cananian 1.3.2.1 assert f.getRegFileInfo().isRegister(t); 112 cananian 1.1.2.2 return t; 113 cananian 1.1.2.2 } 114 cananian 1.1.2.2 }, registers); 115 cananian 1.1.2.6 if (!quiet) System.err.print("S"); 116 cananian 1.1.2.1 // rewrite program to spill temporaries, if necessary. 117 cananian 1.1.2.5 if (color.spills() != null) { 118 cananian 1.1.2.2 rewriteProgram(root, color.spills()); 119 cananian 1.1.2.5 // re-create derived ptr use info. 120 cananian 1.1.2.5 if (dg!=null) ud = new DerivedUseDefer(c, ud0); 121 cananian 1.1.2.5 } 122 cananian 1.1.2.1 } while (color.spills() != null); 123 cananian 1.1.2.6 if (!quiet) System.err.print("}"); 124 cananian 1.1.2.1 125 cananian 1.1.2.1 // trim redundant instructions. 126 cananian 1.1.2.1 instrs = trim(instrs); 127 cananian 1.1.2.1 } 128 cananian 1.1.2.1 129 cananian 1.1.2.1 // use the Spiller class to rewrite the program. 130 cananian 1.1.2.2 private void rewriteProgram(Instr root, TempList spilled) { 131 cananian 1.1.2.2 //throw new Error(root.getFactory().getMethod()+" needs "+color.spills()+" spilled."); 132 cananian 1.1.2.6 if (!quiet) { 133 cananian 1.1.2.6 int i=0; for (TempList tl=spilled; tl!=null; tl=tl.tail) i++; 134 cananian 1.1.2.6 System.err.print("("+i+")"); 135 cananian 1.1.2.6 } 136 cananian 1.1.2.2 Spiller spiller = new Spiller(code, spilled); 137 cananian 1.1.2.1 instrs = spiller.rewrite(instrs); 138 cananian 1.1.2.1 } 139 cananian 1.1.2.1 140 cananian 1.1.2.1 // trim coalesced moves from the instruction list. 141 cananian 1.1.2.2 private Instr trim(Instr root) { 142 cananian 1.1.2.2 for (Instr il = root; il != null; ) { 143 cananian 1.1.2.2 if ((il instanceof InstrMOVE) && 144 cananian 1.1.2.2 canBeCoalesced((InstrMOVE)il)) { 145 cananian 1.1.2.2 // delete coalesced move. (src=dst) 146 cananian 1.1.2.2 if (il == root) root = root.getNext(); 147 cananian 1.1.2.2 il = il.getNext(); 148 cananian 1.1.2.2 il.getPrev().remove(); 149 cananian 1.1.2.2 } else il = il.getNext(); 150 cananian 1.1.2.2 } 151 cananian 1.1.2.2 return root; 152 cananian 1.1.2.1 } 153 cananian 1.1.2.1 154 cananian 1.1.2.2 // check two moves for equality. 155 cananian 1.1.2.2 boolean canBeCoalesced(InstrMOVE instr) { 156 cananian 1.1.2.2 Temp[] u = (Temp[]) instr.use().clone(); 157 cananian 1.1.2.2 for (int i=0; i<u.length; i++) 158 cananian 1.1.2.2 u[i] = tempMap(u[i]); 159 cananian 1.1.2.2 Temp[] d = (Temp[]) instr.def().clone(); 160 cananian 1.1.2.2 for (int i=0; i<d.length; i++) 161 cananian 1.1.2.2 d[i] = tempMap(d[i]); 162 cananian 1.1.2.2 java.util.List ul = 163 cananian 1.1.2.2 java.util.Arrays.asList(u), dl = java.util.Arrays.asList(d); 164 cananian 1.1.2.2 return ul.containsAll(dl) && dl.containsAll(ul); 165 cananian 1.1.2.2 } 166 cananian 1.1.2.2 167 cananian 1.1.2.1 // the tempMap is the coloring defined in RegAlloc.Color 168 cananian 1.1.2.1 /** 169 cananian 1.1.2.1 * A mapping of temporaries to registers. 170 cananian 1.1.2.1 */ 171 cananian 1.1.2.2 public Temp tempMap(Temp temp) { 172 cananian 1.1.2.1 return color.tempMap(temp); 173 cananian 1.1.2.4 } 174 cananian 1.1.2.4 175 cananian 1.1.2.4 private static class DerivedUseDefer extends UseDefer { 176 cananian 1.1.2.4 UseDefer ud; 177 cananian 1.1.2.4 MultiMap extras = new GenericMultiMap(); 178 cananian 1.1.2.4 DerivedUseDefer(Code c, UseDefer ud) { 179 cananian 1.1.2.4 this.ud = ud; 180 cananian 1.1.2.4 if (c.getDerivation()==null) return; // no deriv info. 181 cananian 1.1.2.4 182 cananian 1.1.2.6 if (!quiet) System.err.print("[COMPUTING EXTRAS..."); 183 cananian 1.1.2.4 // do a depth-first search of the CFG to determine (one of the) 184 cananian 1.1.2.4 // reaching definitions for each use. 185 cananian 1.1.2.4 CFGrapher cfg = CFGrapher.DEFAULT; 186 cananian 1.1.2.4 dfs(cfg.getFirstElement(c), cfg, c.getDerivation(), 187 cananian 1.1.2.4 new HashEnvironment(), new HashSet()); 188 cananian 1.1.2.6 if (!quiet) System.err.print("done.]"); 189 cananian 1.1.2.4 } 190 cananian 1.1.2.4 /** dfs of cfg to determine (a) reaching def for each use. 191 cananian 1.1.2.4 * current reaching defs are in 'env'. */ 192 cananian 1.1.2.4 private void dfs(HCodeElement hce, CFGrapher cfg, Derivation deriv, 193 cananian 1.1.2.4 Environment env, Set seen) { 194 cananian 1.1.2.4 seen.add(hce); // keep track of touched hces. 195 cananian 1.1.2.4 // process *this* 196 cananian 1.1.2.4 // for all uses, use current reaching def to determine 'extras' 197 cananian 1.6 for (Object uO : ud.useC(hce)) { 198 cananian 1.6 Temp u = (Temp) uO; 199 cananian 1.1.2.4 HCodeElement def = (HCodeElement) env.get(u); 200 cananian 1.1.2.4 if (def==null) { 201 cananian 1.1.2.4 System.err.println("WARNING: no reaching def found for " + u + 202 cananian 1.1.2.4 " in " + hce); 203 cananian 1.1.2.4 continue; 204 cananian 1.1.2.4 } 205 cananian 1.1.2.4 for (Derivation.DList dl = deriv.derivation(def, u); 206 cananian 1.1.2.4 dl!=null; dl=dl.next) 207 cananian 1.1.2.4 extras.add(hce, dl.base); 208 cananian 1.1.2.4 } 209 cananian 1.1.2.4 // for all defs, update reaching def environment. 210 cananian 1.6 for (Object dO : ud.defC(hce)) { 211 cananian 1.6 Temp d = (Temp) dO; 212 cananian 1.1.2.4 env.put(d, hce); 213 cananian 1.1.2.4 } 214 cananian 1.1.2.4 // recurse 215 cananian 1.1.2.4 Environment.Mark mark = env.getMark(); 216 cananian 1.1.2.4 for (Iterator it=cfg.succC(hce).iterator(); it.hasNext(); ) { 217 cananian 1.1.2.4 HCodeElement succ = ((HCodeEdge) it.next()).to(); 218 cananian 1.1.2.4 if (seen.contains(succ)) continue; 219 cananian 1.1.2.4 dfs(succ, cfg, deriv, env, seen); 220 cananian 1.1.2.4 env.undoToMark(mark); 221 cananian 1.1.2.4 } 222 cananian 1.1.2.4 } 223 cananian 1.1.2.4 224 cananian 1.1.2.4 public Collection defC(HCodeElement hce) { return ud.defC(hce); } 225 cananian 1.1.2.4 // add base pointers for derived temps to use set. 226 cananian 1.1.2.4 public Collection useC(HCodeElement hce) { 227 cananian 1.1.2.4 Collection c = ud.useC(hce); 228 cananian 1.1.2.4 if (extras.containsKey(hce)) { 229 cananian 1.1.2.4 c = new ArrayList(c); 230 cananian 1.1.2.4 c.addAll(extras.getValues(hce)); 231 cananian 1.1.2.4 } 232 cananian 1.1.2.4 return c; 233 cananian 1.1.2.4 } 234 cananian 1.1.2.1 } 235 cananian 1.2 }