1 cananian 1.1.2.1 /*
  2 cananian 1.1.2.1  * RegAlloc/Spiller.java
  3 cananian 1.1.2.1  *  rewrite instruction list to spill overflow temporaries.
  4 cananian 1.1.2.1  *   
  5 cananian 1.1.2.1  * C. Scott Ananian, cananian@princeton.edu, COS320
  6 cananian 1.1.2.1  */
  7 cananian 1.1.2.1 
  8 cananian 1.1.2.2 package harpoon.Backend.CSAHack.RegAlloc;
  9 cananian 1.1.2.1 
 10 cananian 1.1.2.3 import harpoon.Backend.StrongARM.TwoWordTemp;
 11 cananian 1.1.2.3 
 12 cananian 1.1.2.2 import harpoon.Backend.Generic.Frame;
 13 cananian 1.1.2.2 import harpoon.Backend.CSAHack.RegAlloc.Code.Access;
 14 cananian 1.1.2.2 import harpoon.IR.Assem.Instr;
 15 duncan   1.1.2.4 import harpoon.IR.Properties.CFGEdge; 
 16 cananian 1.1.2.2 import harpoon.Backend.CSAHack.Graph.NodeList;
 17 cananian 1.1.2.2 import harpoon.Temp.Temp;
 18 cananian 1.1.2.2 import harpoon.Temp.TempList;
 19 cananian 1.1.2.3 import harpoon.Temp.TempMap;
 20 cananian 1.1.2.2 
 21 cananian 1.1.2.2 import java.util.HashMap;
 22 cananian 1.1.2.2 import java.util.HashSet;
 23 cananian 1.1.2.2 import java.util.Iterator;
 24 cananian 1.1.2.2 import java.util.Map;
 25 cananian 1.1.2.2 import java.util.Set;
 26 cananian 1.1.2.1 
 27 cananian 1.1.2.1 /**
 28 cananian 1.1.2.1  * Rewrite instruction list to spill overflowing temporaries to the
 29 cananian 1.1.2.1  * local frame.
 30 cananian 1.1.2.1  * @version     1.00, 25 Nov 1996
 31 cananian 1.1.2.1  * @author      C. Scott Ananian
 32 cananian 1.1.2.1  * @see RegAlloc.RegAlloc
 33 cananian 1.1.2.1  */
 34 cananian 1.1.2.6 // XXX SPILLER SHOUD USE code.dg TO UPDATE DERIVATION WHILE IT SPILLS!
 35 cananian 1.1.2.1 class Spiller {
 36 cananian 1.1.2.2   Code code;
 37 cananian 1.1.2.2   Map  spills;
 38 cananian 1.1.2.1 
 39 cananian 1.1.2.2   Spiller(Code c, TempList spilled) {
 40 cananian 1.1.2.2     this.code = c;
 41 cananian 1.1.2.1     // make an array of temporaries that need to be spilled
 42 cananian 1.1.2.1     // and allocate each of them some space in the frame.
 43 cananian 1.1.2.2     spills = new HashMap();
 44 cananian 1.1.2.2     for (int i=0; spilled!=null; spilled=spilled.tail, i++)
 45 cananian 1.1.2.2       spills.put(spilled.head, c.allocLocal());
 46 cananian 1.1.2.1   }
 47 cananian 1.1.2.1   // rewrite an instruction list.
 48 cananian 1.1.2.2   Instr rewrite(Instr instrs) { 
 49 cananian 1.1.2.3     final Map usespill = new HashMap(), defspill=new HashMap();
 50 cananian 1.1.2.3     Set instrsToSkip = new HashSet();
 51 cananian 1.1.2.2     for (Instr il=instrs; il!=null; il=il.getNext()) {
 52 cananian 1.1.2.3       if (instrsToSkip.contains(il)) continue;
 53 cananian 1.1.2.3       // find USE and DEFs of spilltemps.
 54 cananian 1.1.2.3       Temp d[] = il.def();
 55 cananian 1.1.2.3       for (int i=0; i<d.length; i++) {
 56 cananian 1.1.2.3         if (d[i] instanceof TwoWordTemp) {
 57 cananian 1.1.2.3           // can't rename twowordtemps so just insert the pieces as themselves.
 58 cananian 1.1.2.3           Temp low = ((TwoWordTemp)d[i]).getLow();
 59 cananian 1.1.2.3           Temp high= ((TwoWordTemp)d[i]).getHigh();
 60 cananian 1.1.2.3           if (spills.containsKey(low) &&
 61 cananian 1.1.2.3               il.getAssem().indexOf("`d"+i+"l")!=-1) defspill.put(low, low);
 62 cananian 1.1.2.3           if (spills.containsKey(high) &&
 63 cananian 1.1.2.3               il.getAssem().indexOf("`d"+i+"h")!=-1) defspill.put(high, high);
 64 cananian 1.1.2.3         } else if (spills.containsKey(d[i]) && !defspill.containsKey(d[i]))
 65 cananian 1.1.2.3           defspill.put(d[i], new Temp(il.getFactory().tempFactory()));
 66 cananian 1.1.2.3       }
 67 cananian 1.1.2.3       Temp u[] = il.use();
 68 cananian 1.1.2.3       for (int i=0; i<u.length; i++) {
 69 cananian 1.1.2.3         if (u[i] instanceof TwoWordTemp) {
 70 cananian 1.1.2.3           Temp low = ((TwoWordTemp)u[i]).getLow();
 71 cananian 1.1.2.3           Temp high= ((TwoWordTemp)u[i]).getHigh();
 72 cananian 1.1.2.3           // can't rename twowordtemps so just insert the pieces as themselves.
 73 cananian 1.1.2.3           if (spills.containsKey(low) &&
 74 cananian 1.1.2.3               il.getAssem().indexOf("`s"+i+"l")!=-1)  usespill.put(low, low);
 75 cananian 1.1.2.3           if (spills.containsKey(high) &&
 76 cananian 1.1.2.3               il.getAssem().indexOf("`s"+i+"h")!=-1) usespill.put(high, high);
 77 cananian 1.1.2.3         } else if (spills.containsKey(u[i]) && !usespill.containsKey(u[i]))
 78 cananian 1.1.2.3           usespill.put(u[i], new Temp(il.getFactory().tempFactory()));
 79 cananian 1.1.2.2       }
 80 cananian 1.1.2.3       // if no uses or defs of spilltemps, continue.
 81 cananian 1.1.2.3       if (defspill.size()==0 && usespill.size()==0) continue;
 82 cananian 1.1.2.3       // okay, rename the original instr with the new limited-lifespan temps.
 83 cananian 1.1.2.5       TempMap defMap =  new TempMap() { // defmap
 84 cananian 1.1.2.3           public Temp tempMap(Temp t) {
 85 cananian 1.1.2.3               return defspill.containsKey(t) ? (Temp)defspill.get(t) : t;
 86 cananian 1.1.2.3           }
 87 cananian 1.1.2.5       }, useMap = new TempMap() { // usemap
 88 cananian 1.1.2.3           public Temp tempMap(Temp t) {
 89 cananian 1.1.2.3               return usespill.containsKey(t) ? (Temp)usespill.get(t) : t;
 90 cananian 1.1.2.3           }
 91 cananian 1.1.2.5       };
 92 cananian 1.1.2.5       Instr ni = il.rename(il.getFactory(), defMap, useMap);
 93 cananian 1.1.2.3       // replace old instr with new instr
 94 cananian 1.1.2.3       Instr.replace(il, ni);  il=ni;
 95 cananian 1.1.2.3       instrsToSkip.add(ni);
 96 cananian 1.1.2.3       // insert loads before any usespills.
 97 cananian 1.3           for (Object eO : usespill.entrySet()) {
 98 cananian 1.3               Map.Entry e = (Map.Entry) eO;
 99 cananian 1.1.2.3           Temp olduse = (Temp) e.getKey(), newuse = (Temp) e.getValue();
100 cananian 1.1.2.3           Access a = (Access) spills.get(olduse);
101 cananian 1.1.2.2           for (Iterator it2=il.predC().iterator(); it2.hasNext(); ) {
102 cananian 1.1.2.3             Instr loadi = a.makeLoad(il.getFactory(), il, newuse);
103 duncan   1.1.2.4             loadi.insertAt((CFGEdge)it2.next());
104 cananian 1.1.2.3             instrsToSkip.add(loadi);
105 cananian 1.1.2.5           }
106 cananian 1.1.2.5       }
107 cananian 1.1.2.5       // treat next instruction and this one as atomic if next instr
108 cananian 1.1.2.5       // string contains '@ dummy'
109 cananian 1.1.2.5       if (il.succC().size()==1) {
110 cananian 1.1.2.5           Instr dummy = (Instr) ((CFGEdge)il.succC().iterator().next()).to();
111 cananian 1.1.2.5           if (dummy.getAssem().indexOf("@ dummy") >= 0) {
112 cananian 1.1.2.5               ni = dummy.rename(dummy.getFactory(), defMap, useMap);
113 cananian 1.1.2.5               Instr.replace(dummy, ni); il=ni;
114 cananian 1.1.2.5               instrsToSkip.add(ni);
115 cananian 1.1.2.3           }
116 cananian 1.1.2.3       }
117 cananian 1.1.2.3       // insert stores before any defspills.
118 cananian 1.3           for (Object eO : defspill.entrySet()) {
119 cananian 1.3               Map.Entry e = (Map.Entry) eO;
120 cananian 1.1.2.3           Temp olddef = (Temp) e.getKey(), newdef = (Temp) e.getValue();
121 cananian 1.1.2.3           Access a = (Access) spills.get(olddef);
122 cananian 1.1.2.3           for (Iterator it2=il.succC().iterator(); it2.hasNext(); ) {
123 cananian 1.1.2.3             Instr storei = a.makeStore(il.getFactory(), il, newdef);
124 duncan   1.1.2.4             storei.insertAt((CFGEdge)it2.next());
125 cananian 1.1.2.3             instrsToSkip.add(storei);
126 cananian 1.1.2.2           }
127 cananian 1.1.2.2       }
128 cananian 1.1.2.3       // reset usespill and defspill for efficient re-use.
129 cananian 1.1.2.3       usespill.clear(); defspill.clear();
130 cananian 1.1.2.3       // done!
131 cananian 1.1.2.1     }
132 cananian 1.1.2.2     // fixup instrs
133 cananian 1.1.2.2     while (instrs.getPrev()!=null) instrs = instrs.getPrev();
134 cananian 1.1.2.2     return instrs;
135 cananian 1.1.2.1   }
136 cananian 1.2     }