1 cananian 1.1.2.5 // TreeFolding.java, created Mon Apr 5 17:52:42 1999 by duncan 2 cananian 1.1.2.4 // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.edu> 3 cananian 1.1.2.4 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 duncan 1.1.2.1 package harpoon.Analysis.Tree; 5 duncan 1.1.2.1 6 duncan 1.1.2.3 import harpoon.Analysis.DataFlow.TreeSolver; 7 pnkfelix 1.1.2.8 import harpoon.Analysis.BasicBlock; 8 salcianu 1.4 import harpoon.Analysis.BasicBlockInterf; 9 duncan 1.1.2.3 import harpoon.Analysis.DataFlow.ForwardDataFlowBasicBlockVisitor; 10 duncan 1.1.2.3 import harpoon.Analysis.DataFlow.ReversePostOrderIterator; 11 duncan 1.1.2.3 import harpoon.Analysis.EdgesIterator; 12 duncan 1.1.2.3 import harpoon.ClassFile.HCodeElement; 13 cananian 1.1.2.11 import harpoon.IR.Properties.CFGrapher; 14 cananian 1.1.2.18 import harpoon.IR.Properties.UseDefer; 15 duncan 1.1.2.3 import harpoon.IR.Tree.CanonicalTreeCode; 16 duncan 1.1.2.3 import harpoon.IR.Tree.Code; 17 duncan 1.1.2.1 import harpoon.IR.Tree.Exp; 18 duncan 1.1.2.1 import harpoon.IR.Tree.ExpList; 19 duncan 1.1.2.1 import harpoon.IR.Tree.MEM; 20 duncan 1.1.2.1 import harpoon.IR.Tree.MOVE; 21 duncan 1.1.2.1 import harpoon.IR.Tree.SEQ; 22 duncan 1.1.2.1 import harpoon.IR.Tree.Stm; 23 duncan 1.1.2.1 import harpoon.IR.Tree.TEMP; 24 duncan 1.1.2.1 import harpoon.IR.Tree.Tree; 25 duncan 1.1.2.3 import harpoon.IR.Tree.TreeKind; 26 duncan 1.1.2.1 import harpoon.Temp.Temp; 27 cananian 1.6 import net.cscott.jutil.BitString; 28 duncan 1.1.2.1 import harpoon.Util.Tuple; 29 duncan 1.1.2.1 import harpoon.Util.Util; 30 duncan 1.1.2.1 31 duncan 1.1.2.3 import java.util.HashMap; 32 duncan 1.1.2.3 import java.util.HashSet; 33 duncan 1.1.2.3 import java.util.Iterator; 34 duncan 1.1.2.3 import java.util.Map; 35 duncan 1.1.2.3 import java.util.Set; 36 duncan 1.1.2.3 37 duncan 1.1.2.3 /** 38 duncan 1.1.2.3 * The <code>TreeFolding</code> class performs tree folding on a 39 duncan 1.1.2.3 * tree code in canonical form. Tree folding is used to remove 40 duncan 1.1.2.3 * superfluous temp definitions in the tree form. For example, 41 duncan 1.1.2.3 * in the tree expression: 42 duncan 1.1.2.3 * 43 duncan 1.1.2.3 * <PRE> 44 duncan 1.1.2.3 * SEQ( 45 duncan 1.1.2.3 * MOVE(t1, 5) 46 duncan 1.1.2.3 * CJUMP(t1, L-true, L-false) 47 duncan 1.1.2.3 * ) 48 duncan 1.1.2.3 * </PRE> 49 duncan 1.1.2.3 * 50 duncan 1.1.2.3 * the superfluous temp t1 would be removed, and its use would be replaced 51 duncan 1.1.2.3 * with the expression to which t1 was assigned: 52 duncan 1.1.2.3 * 53 duncan 1.1.2.3 * <PRE> 54 duncan 1.1.2.3 * CJUMP(5, L-true, L-false) 55 duncan 1.1.2.3 * </PRE> 56 duncan 1.1.2.3 * 57 duncan 1.1.2.3 * 58 duncan 1.1.2.3 * The algorithm for tree folding is as follows: 59 duncan 1.1.2.3 * 60 duncan 1.1.2.3 * <PRE> 61 duncan 1.1.2.3 * foreach TEMP t do 62 duncan 1.1.2.3 * if ((t has one DEF) AND 63 duncan 1.1.2.3 * (DEF(t) has one USE) AND 64 duncan 1.1.2.3 * (RHS(DEF(t)) is available)) 65 duncan 1.1.2.3 * remove DEF(t) 66 duncan 1.1.2.3 * replace t with RHS(DEF(t)) 67 duncan 1.1.2.3 * </PRE> 68 duncan 1.1.2.3 * 69 duncan 1.1.2.3 * <b>Issues:</b><p> 70 duncan 1.1.2.3 * 71 duncan 1.1.2.3 * At this time, memory writes kill all expressions. However, this is not 72 duncan 1.1.2.3 * really necessary. Furthermore, the algorithm is not especially efficient 73 duncan 1.1.2.3 * either in time or in space. 74 duncan 1.1.2.3 * 75 duncan 1.1.2.3 * @author Duncan Bryce <duncan@lcs.mit.edu> 76 cananian 1.7 * @version $Id: TreeFolding.java,v 1.7 2004/02/08 03:20:35 cananian Exp $ 77 duncan 1.1.2.3 * 78 duncan 1.1.2.3 */ 79 duncan 1.1.2.3 public class TreeFolding extends ForwardDataFlowBasicBlockVisitor { 80 duncan 1.1.2.3 private boolean initialized = false; 81 duncan 1.1.2.3 82 cananian 1.3.2.2 private final int maxTreeID; 83 cananian 1.3.2.2 private final Code code; 84 cananian 1.3.2.2 private final Map bb2tfi; 85 cananian 1.3.2.2 private final Map DUChains, UDChains; 86 cananian 1.3.2.2 private final Map tempsToPrsvs; 87 cananian 1.3.2.2 private final Stm root; 88 cananian 1.3.2.2 private final BasicBlock.Factory bbfactory; 89 duncan 1.1.2.3 90 cananian 1.1.2.11 private CFGrapher grapher; 91 cananian 1.1.2.18 private UseDefer usedefer; 92 cananian 1.1.2.11 93 duncan 1.1.2.3 /** Constructs a new <code>TreeFolding</code> object for the 94 duncan 1.1.2.3 * <code>code</code>. 95 duncan 1.1.2.3 * 96 duncan 1.1.2.3 * <BR> <B>requires:</B> <OL> 97 duncan 1.1.2.3 * <LI> <code>code</code> is a tree codeview in canonical form 98 duncan 1.1.2.3 * (<code>code.isCanonical()</code> should return 99 duncan 1.1.2.3 * <code>true</code>). 100 duncan 1.1.2.3 * <BR> <B>modifies:</B> nothing. 101 duncan 1.1.2.3 * <BR> <B>effects:</B> constructs a new 102 duncan 1.1.2.3 * <code>BasicBlockVisitor</code> and initializes its 103 duncan 1.1.2.3 * internal datasets for analysis of the 104 duncan 1.1.2.3 * <code>BasicBlock</code>s in <code>code</code>. 105 duncan 1.1.2.3 * However, the <code>visit()</code> and <code>merge()</code> 106 duncan 1.1.2.3 * methods should not be called directly. Rather, the folded 107 duncan 1.1.2.3 * tree code should be extracted by calling the calling the 108 duncan 1.1.2.3 * <code>fold()</code> method. 109 duncan 1.1.2.3 */ 110 duncan 1.1.2.3 public TreeFolding(harpoon.IR.Tree.Code code) { 111 duncan 1.1.2.3 Map tempsToDefs = new HashMap(); 112 duncan 1.1.2.3 113 cananian 1.3.2.1 assert code.isCanonical(); 114 duncan 1.1.2.3 115 duncan 1.1.2.3 this.code = code; 116 duncan 1.1.2.3 this.root = (Stm)this.code.getRootElement(); 117 cananian 1.1.2.11 this.grapher = code.getGrapher(); 118 cananian 1.1.2.18 this.usedefer = code.getUseDefer(); 119 duncan 1.1.2.3 this.maxTreeID = TreeSolver.getMaxID(RS(this.root)); 120 duncan 1.1.2.3 this.bb2tfi = new HashMap(); 121 duncan 1.1.2.3 this.DUChains = new HashMap(); 122 duncan 1.1.2.3 this.UDChains = new HashMap(); 123 duncan 1.1.2.3 this.tempsToPrsvs = new HashMap(); 124 cananian 1.1.2.19 this.bbfactory = new BasicBlock.Factory(code, grapher); 125 cananian 1.1.2.16 BasicBlock rootbb = bbfactory.getRoot(); 126 duncan 1.1.2.1 127 duncan 1.1.2.3 initTempsToPrsvs(tempsToPrsvs); 128 duncan 1.1.2.3 initTempsToDefs (tempsToDefs); 129 duncan 1.1.2.3 130 duncan 1.1.2.3 for (Iterator i = new ReversePostOrderIterator(rootbb);i.hasNext();) { 131 duncan 1.1.2.3 BasicBlock bb = (BasicBlock)i.next(); 132 duncan 1.1.2.3 bb2tfi.put(bb, new TreeFoldingInfo(bb)); 133 duncan 1.1.2.1 } 134 duncan 1.1.2.1 135 duncan 1.1.2.3 TreeSolver.forward_rpo_solver(rootbb, this); 136 cananian 1.1.2.16 computeUseDef(bbfactory, tempsToDefs); 137 duncan 1.1.2.1 138 duncan 1.1.2.3 initialized = true; 139 duncan 1.1.2.3 } 140 duncan 1.1.2.1 141 duncan 1.1.2.3 /** 142 duncan 1.1.2.3 * Performs the tree-folding optimization on this class's tree code. 143 duncan 1.1.2.3 * 144 duncan 1.1.2.3 * <BR> <B>Requires:</B> 145 duncan 1.1.2.3 * <BR> <B>Modifies:</B> this class's tree code 146 duncan 1.1.2.3 * <BR> <B>Effects:</B> Performs the tree-folding optimization on 147 duncan 1.1.2.3 * this class's tree code, and returns the resulting 148 cananian 1.1.2.9 * tree code. Preserves the <code>CFGraphable</code> 149 duncan 1.1.2.3 * interface correctly by calling the code's 150 duncan 1.1.2.3 * <code>recomputeEdges()</code> method. 151 duncan 1.1.2.3 */ 152 duncan 1.1.2.3 public harpoon.IR.Tree.Code fold() { 153 duncan 1.1.2.3 Map IDsToTrees; 154 duncan 1.1.2.3 initIDsToTrees(IDsToTrees = new HashMap()); 155 cananian 1.1.2.16 fold(bbfactory.getRoot(), IDsToTrees, this.DUChains, this.UDChains); 156 duncan 1.1.2.3 return this.code; 157 duncan 1.1.2.1 } 158 duncan 1.1.2.1 159 duncan 1.1.2.1 160 duncan 1.1.2.3 /** Visit (Transfer) function. 161 duncan 1.1.2.3 * <pre> OUT(bb) = GEN(bb) union (IN(bb) intersect PRSV(bb)) </pre> 162 duncan 1.1.2.3 * <pre> OUT_mem(bb) = IN_mem(bb) union KILL_mem(bb) </pre>. 163 duncan 1.1.2.3 * 164 duncan 1.1.2.3 * <B>Note:</B> this method should never be called directly, and will 165 duncan 1.1.2.3 * cause an assertion failure if it is called from outside of the 166 duncan 1.1.2.3 * <code>TreeFolding</code> class. 167 duncan 1.1.2.3 */ 168 duncan 1.1.2.3 public void visit(BasicBlock bb) { 169 cananian 1.3.2.1 assert bb!=null; 170 cananian 1.3.2.1 assert !initialized; 171 duncan 1.1.2.3 172 duncan 1.1.2.3 //if (DEBUG) db("Visiting: " + bb); 173 duncan 1.1.2.3 TreeFoldingInfo info = (TreeFoldingInfo)bb2tfi.get(bb); 174 duncan 1.1.2.3 175 cananian 1.3.2.1 assert info!=null; 176 duncan 1.1.2.3 info.outSet[0].clearUpTo(maxTreeID); 177 duncan 1.1.2.3 info.outSet[0].or (info.prsvSet[0]); 178 duncan 1.1.2.3 info.outSet[0].and(info.inSet[0]); 179 duncan 1.1.2.3 info.outSet[0].or (info.genSet[0]); 180 duncan 1.1.2.3 info.outSet[1].clearUpTo(maxTreeID); 181 duncan 1.1.2.3 info.outSet[1].or(info.prsvSet[1]); 182 duncan 1.1.2.3 info.outSet[1].or(info.inSet[1]); 183 duncan 1.1.2.3 info.outSet[1].and(info.genSet[1]); 184 duncan 1.1.2.3 } 185 duncan 1.1.2.3 186 duncan 1.1.2.3 /** 187 duncan 1.1.2.3 * Merges operation on the from and to basic block. Returns true if 188 duncan 1.1.2.3 * the to basic block changes. 189 duncan 1.1.2.3 * 190 duncan 1.1.2.3 * <BR> <B>NOTE:</B> "changes" above refers to our knowledge about 191 duncan 1.1.2.3 * the basic block changing, not the contents of the basic block 192 duncan 1.1.2.3 * itself, which shouldn't be modified during Analysis. Thus, an 193 duncan 1.1.2.3 * appropriate "change" would be a variable being added to the 194 duncan 1.1.2.3 * IN-set of 'to' during Forward Dataflow Analysis 195 duncan 1.1.2.3 */ 196 salcianu 1.4 public boolean merge(BasicBlockInterf from, BasicBlockInterf to) { 197 duncan 1.1.2.3 BitString fOUT, fOUT_mem, tIN, tIN_mem; 198 duncan 1.1.2.3 TreeFoldingInfo fInfo, tInfo; 199 duncan 1.1.2.3 boolean result; 200 duncan 1.1.2.1 201 cananian 1.3.2.1 assert !initialized; 202 duncan 1.1.2.1 203 duncan 1.1.2.3 //if (DEBUG) db("Merging: " + from + ", " + to); 204 duncan 1.1.2.1 205 duncan 1.1.2.3 fInfo = (TreeFoldingInfo)bb2tfi.get(from); 206 duncan 1.1.2.3 tInfo = (TreeFoldingInfo)bb2tfi.get(to); 207 duncan 1.1.2.3 208 duncan 1.1.2.3 fOUT = fInfo.outSet[0]; 209 duncan 1.1.2.3 tIN = tInfo.inSet[0]; 210 duncan 1.1.2.3 result = tIN.or_upTo(fOUT, maxTreeID); 211 duncan 1.1.2.3 212 duncan 1.1.2.3 fOUT_mem = fInfo.outSet[1]; 213 duncan 1.1.2.3 tIN_mem = tInfo.inSet[1]; 214 duncan 1.1.2.3 result = result || tIN_mem.or_upTo(fOUT_mem, maxTreeID); 215 duncan 1.1.2.1 216 duncan 1.1.2.3 return result; 217 duncan 1.1.2.3 218 duncan 1.1.2.3 } 219 duncan 1.1.2.3 220 duncan 1.1.2.3 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* 221 duncan 1.1.2.3 * * 222 duncan 1.1.2.3 * Initialization routines * 223 duncan 1.1.2.3 * * 224 duncan 1.1.2.3 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 225 duncan 1.1.2.3 226 duncan 1.1.2.3 // Maps tree IDs to Tree objects 227 duncan 1.1.2.3 private void initIDsToTrees(Map IDsToTrees) { 228 cananian 1.1.2.11 for (Iterator i = new EdgesIterator(RS(root),grapher); i.hasNext();) { 229 duncan 1.1.2.3 Stm stm = (Stm)i.next(); 230 duncan 1.1.2.3 int ID = stm.getID(); 231 duncan 1.1.2.3 IDsToTrees.put(new Integer(ID), stm); 232 duncan 1.1.2.1 } 233 duncan 1.1.2.3 } 234 duncan 1.1.2.1 235 duncan 1.1.2.3 // Maps Temps to BitStrings representing the Tree IDs of the Trees 236 duncan 1.1.2.3 // they preserve 237 duncan 1.1.2.3 private void initTempsToPrsvs(Map tempsToPrsvs) { 238 cananian 1.1.2.7 for (Iterator i = ((Code.TreeFactory)root.getFactory()).getParent().getElementsI(); 239 duncan 1.1.2.3 i.hasNext();) { 240 cananian 1.1.2.18 Tree u = (Tree)i.next(); 241 cananian 1.1.2.18 Temp[] tmps = (u instanceof Stm)?usedefer.def(u):usedefer.use(u); 242 duncan 1.1.2.3 for (int n=0; n<tmps.length; n++) { 243 duncan 1.1.2.3 BitString bs = (BitString)tempsToPrsvs.get(tmps[n]); 244 duncan 1.1.2.3 if (bs==null) { 245 duncan 1.1.2.3 tempsToPrsvs.put(tmps[n], bs=new BitString(maxTreeID+1)); 246 duncan 1.1.2.3 bs.setAll(); 247 duncan 1.1.2.1 } 248 cananian 1.1.2.18 bs.clear(u.getID()); 249 duncan 1.1.2.3 } 250 duncan 1.1.2.3 } 251 duncan 1.1.2.3 } 252 duncan 1.1.2.3 253 duncan 1.1.2.3 // Maps Temps to the Tree IDs of the statements where they are defined 254 duncan 1.1.2.3 private void initTempsToDefs(Map tempsToDefs) { 255 cananian 1.1.2.11 for (Iterator i = new EdgesIterator(RS(root),grapher); i.hasNext();) { 256 duncan 1.1.2.3 Stm stm = (Stm)i.next(); 257 duncan 1.1.2.3 if (!((stm.kind()==TreeKind.CALL) || 258 duncan 1.1.2.3 (stm.kind()==TreeKind.NATIVECALL))) { 259 cananian 1.3.2.1 Temp[] defs = usedefer.def(stm); assert defs.length<=1; 260 duncan 1.1.2.3 if (defs.length==1) { 261 duncan 1.1.2.3 MAP_TO_SET(defs[0], new Integer(stm.getID()), tempsToDefs); 262 duncan 1.1.2.1 } 263 duncan 1.1.2.1 } 264 duncan 1.1.2.1 } 265 duncan 1.1.2.3 } 266 duncan 1.1.2.1 267 duncan 1.1.2.3 // Computes UD and DU chains based on the computed IN and OUT sets 268 duncan 1.1.2.3 // FIX: this method could probably be cleaned up substantially 269 duncan 1.1.2.3 // 270 cananian 1.1.2.16 private void computeUseDef(BasicBlock.Factory bbf, Map tempsToDefs) { 271 cananian 1.1.2.16 for (Iterator i = bbf.blocksIterator(); i.hasNext();) { 272 duncan 1.1.2.3 BasicBlock bb = (BasicBlock)i.next(); 273 duncan 1.1.2.3 TreeFoldingInfo bbInfo = (TreeFoldingInfo)bb2tfi.get(bb); 274 duncan 1.1.2.3 BitString bbIn = (BitString)((bbInfo.inSet[0]).clone()); 275 pnkfelix 1.1.2.13 for (Iterator j = bb.statements().listIterator(); j.hasNext();) { 276 duncan 1.1.2.3 Stm stm = (Stm)j.next(); 277 duncan 1.1.2.3 Integer useID = new Integer(stm.getID()); 278 cananian 1.1.2.18 Temp[] uses = usedefer.use(stm); 279 duncan 1.1.2.3 for (int n=0; n<uses.length; n++) { 280 duncan 1.1.2.3 Temp use = uses[n]; 281 duncan 1.1.2.3 Set defIDs = (Set)tempsToDefs.get(use); 282 cananian 1.3.2.1 //assert tempsToDefs.containsKey(use); 283 duncan 1.1.2.3 if (tempsToDefs.containsKey(use)) { 284 cananian 1.7 for (Object defIDO : defIDs) { 285 cananian 1.7 Integer defID = (Integer) defIDO; 286 duncan 1.1.2.3 if (bbIn.get(defID.intValue())) { 287 duncan 1.1.2.3 Tuple defT=new Tuple(new Object[]{defID,use}); 288 duncan 1.1.2.3 Tuple useT=new Tuple(new Object[]{useID,use}); 289 duncan 1.1.2.3 MAP_TO_SET(useT, defT, UDChains); 290 duncan 1.1.2.3 MAP_TO_SET(defT, useT, DUChains); 291 duncan 1.1.2.1 } 292 duncan 1.1.2.3 } 293 duncan 1.1.2.1 } 294 duncan 1.1.2.3 } 295 duncan 1.1.2.3 // Update IN set 296 cananian 1.1.2.18 Temp[] defs = usedefer.def(stm); 297 cananian 1.3.2.1 assert defs.length<=1 || 298 duncan 1.1.2.3 stm.kind()==TreeKind.CALL || 299 cananian 1.3.2.1 stm.kind()==TreeKind.NATIVECALL; 300 duncan 1.1.2.3 if (defs.length==1) { 301 duncan 1.1.2.3 bbIn.and((BitString)tempsToPrsvs.get(defs[0])); 302 duncan 1.1.2.3 bbIn.set(stm.getID()); 303 duncan 1.1.2.1 } 304 duncan 1.1.2.1 } 305 duncan 1.1.2.1 } 306 duncan 1.1.2.3 } 307 duncan 1.1.2.3 308 duncan 1.1.2.3 // Performs the folding operation, using the suppiled DU and UD chains. 309 duncan 1.1.2.3 // FIX: this method could probably be cleaned up substantially 310 duncan 1.1.2.3 private void fold(BasicBlock root, Map IDsToTrees, 311 duncan 1.1.2.3 Map DUChains, Map UDChains) { 312 duncan 1.1.2.3 Map tm = new HashMap(); 313 duncan 1.1.2.3 BasicBlock bb; 314 duncan 1.1.2.3 TreeFoldingInfo tfi; 315 duncan 1.1.2.3 BitString dataIn, memIn; 316 duncan 1.1.2.3 for (Iterator i = new ReversePostOrderIterator(root); i.hasNext();) { 317 duncan 1.1.2.3 bb = (BasicBlock)i.next(); 318 duncan 1.1.2.3 tfi = (TreeFoldingInfo)bb2tfi.get(bb); 319 duncan 1.1.2.3 dataIn = (BitString)tfi.inSet[0].clone(); 320 duncan 1.1.2.3 memIn = (BitString)tfi.inSet[1].clone(); 321 duncan 1.1.2.1 322 pnkfelix 1.1.2.13 for (Iterator bbi = bb.statements().listIterator(); bbi.hasNext();) { 323 duncan 1.1.2.3 Stm stm = (Stm)bbi.next(); 324 cananian 1.1.2.18 Temp[] uses = usedefer.use(stm); 325 duncan 1.1.2.3 for (int j=0; j<uses.length; j++) { 326 duncan 1.1.2.3 Tuple useT = 327 duncan 1.1.2.3 new Tuple(new Object[] 328 duncan 1.1.2.3 { new Integer(stm.getID()), uses[j] }); 329 duncan 1.1.2.3 Set D = (Set)UDChains.get(useT); 330 duncan 1.1.2.3 // Is there only one DEF for this USE? 331 duncan 1.1.2.3 if (D!=null && D.size()==1) { 332 duncan 1.1.2.3 Tuple defT = (Tuple)(D.iterator().next()); 333 duncan 1.1.2.3 Set U = (Set)DUChains.get(defT); 334 duncan 1.1.2.3 // is there only one USE for this DEF? 335 duncan 1.1.2.3 if (U.size()==1) { 336 cananian 1.3.2.1 //assert U contains use; 337 cananian 1.3.2.1 assert IDsToTrees.containsKey(defT.proj(0)); 338 duncan 1.1.2.3 339 duncan 1.1.2.3 // Is memory valid here? 340 duncan 1.1.2.3 if (!memIn.get 341 duncan 1.1.2.3 (((Integer)defT.proj(0)).intValue())) { 342 duncan 1.1.2.3 // Is the expression we want available? 343 duncan 1.1.2.3 if (dataIn.get 344 duncan 1.1.2.3 (((Integer)defT.proj(0)).intValue())) { 345 duncan 1.1.2.3 Stm DStm = 346 duncan 1.1.2.3 (Stm)(IDsToTrees.get(defT.proj(0))); 347 duncan 1.1.2.3 DStm = (Stm)GET_TREE(tm, DStm); 348 duncan 1.1.2.12 code.remove(DStm); 349 duncan 1.1.2.3 Stm foldedStm = 350 duncan 1.1.2.3 stm.build 351 cananian 1.1.2.11 (replace(((MOVE)DStm).getSrc(), 352 duncan 1.1.2.3 GET_TREE(tm, stm).kids(), 353 duncan 1.1.2.3 uses[j])); 354 cananian 1.1.2.17 GET_TREE(tm, stm).replace(foldedStm); 355 duncan 1.1.2.3 MAP_TREE(tm, GET_TREE(tm, stm), foldedStm); 356 duncan 1.1.2.3 } 357 duncan 1.1.2.3 } 358 duncan 1.1.2.3 } 359 duncan 1.1.2.3 } 360 duncan 1.1.2.1 } 361 duncan 1.1.2.3 if (mayWriteMem(stm)) 362 duncan 1.1.2.3 memIn.setAll(); 363 duncan 1.1.2.3 else if (stm.kind()==TreeKind.MOVE) { 364 duncan 1.1.2.3 dataIn.and 365 cananian 1.1.2.18 ((BitString)tempsToPrsvs.get(usedefer.def(stm)[0])); 366 duncan 1.1.2.3 dataIn.set(stm.getID()); 367 duncan 1.1.2.3 memIn.clear(stm.getID()); 368 duncan 1.1.2.1 } 369 duncan 1.1.2.1 } 370 duncan 1.1.2.1 } 371 duncan 1.1.2.1 } 372 duncan 1.1.2.1 373 duncan 1.1.2.3 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++* 374 duncan 1.1.2.3 * * 375 duncan 1.1.2.3 * Utility functions * 376 duncan 1.1.2.3 * * 377 duncan 1.1.2.3 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 378 duncan 1.1.2.3 379 duncan 1.1.2.3 private void MAP_TREE(Map table, Tree key, Tree value) { 380 duncan 1.1.2.3 table.put(key, value); 381 duncan 1.1.2.3 } 382 duncan 1.1.2.3 383 duncan 1.1.2.3 private Tree GET_TREE(Map table, Tree key) { 384 duncan 1.1.2.3 while (table.containsKey(key)) key = (Tree)table.get(key); 385 duncan 1.1.2.3 return key; 386 duncan 1.1.2.3 } 387 duncan 1.1.2.1 388 duncan 1.1.2.3 private void MAP_TO_SET(Object key, Object value, Map map) { 389 duncan 1.1.2.3 Set set; 390 duncan 1.1.2.3 if (!map.containsKey(key)) { 391 duncan 1.1.2.3 set = new HashSet(); 392 duncan 1.1.2.3 map.put(key, set); 393 duncan 1.1.2.1 } 394 duncan 1.1.2.3 else { 395 duncan 1.1.2.3 set = (Set)map.get(key); 396 duncan 1.1.2.1 } 397 duncan 1.1.2.3 set.add(value); 398 duncan 1.1.2.3 } 399 duncan 1.1.2.1 400 duncan 1.1.2.3 401 duncan 1.1.2.3 private Stm RS(Stm s) { 402 cananian 1.1.2.11 try { while (true) s = ((SEQ)s).getLeft(); } 403 duncan 1.1.2.3 catch (ClassCastException e) { return s; } 404 duncan 1.1.2.3 } 405 duncan 1.1.2.1 406 duncan 1.1.2.3 private ExpList replace(Exp src, ExpList use, Temp tUse) { 407 duncan 1.1.2.3 if (use==null||use.head==null) return null; 408 duncan 1.1.2.3 else { 409 duncan 1.1.2.3 if (use.head.kind()==TreeKind.TEMP) { 410 duncan 1.1.2.3 TEMP temp = (TEMP)use.head; 411 duncan 1.1.2.3 // Only replaces one instance of the temp 412 duncan 1.1.2.3 if (temp.temp==tUse) return new ExpList(src, use.tail); 413 duncan 1.1.2.3 else return new ExpList(temp, replace(src, use.tail, tUse)); 414 duncan 1.1.2.3 } 415 duncan 1.1.2.3 else return new ExpList 416 duncan 1.1.2.3 (use.head.build(replace(src, use.head.kids(), tUse)), 417 duncan 1.1.2.3 replace(src, use.tail, tUse)); 418 duncan 1.1.2.1 } 419 duncan 1.1.2.1 } 420 duncan 1.1.2.3 421 duncan 1.1.2.3 // TreeFoldingInfo is a record type grouping together four sets: 422 duncan 1.1.2.3 class TreeFoldingInfo { 423 duncan 1.1.2.3 final BitString[] genSet = new BitString[2]; 424 duncan 1.1.2.3 final BitString[] prsvSet = new BitString[2]; 425 duncan 1.1.2.3 final BitString[] inSet = new BitString[2]; 426 duncan 1.1.2.3 final BitString[] outSet = new BitString[2]; 427 duncan 1.1.2.1 428 duncan 1.1.2.3 TreeFoldingInfo(BasicBlock bb) { 429 duncan 1.1.2.3 this.genSet[0] = new BitString(maxTreeID+1); 430 duncan 1.1.2.3 this.genSet[1] = new BitString(maxTreeID+1); 431 duncan 1.1.2.3 this.inSet[0] = new BitString(maxTreeID+1); 432 duncan 1.1.2.3 this.inSet[1] = new BitString(maxTreeID+1); 433 duncan 1.1.2.3 this.outSet[0] = new BitString(maxTreeID+1); 434 duncan 1.1.2.3 this.outSet[1] = new BitString(maxTreeID+1); 435 duncan 1.1.2.3 this.prsvSet[0] = new BitString(maxTreeID+1); 436 duncan 1.1.2.3 this.prsvSet[1] = new BitString(maxTreeID+1); 437 duncan 1.1.2.3 438 duncan 1.1.2.3 computeGenPrsvSets(bb); 439 duncan 1.1.2.1 } 440 duncan 1.1.2.1 441 duncan 1.1.2.3 // Initializes the GEN and PRSV sets of this TreeFoldingInfo 442 duncan 1.1.2.3 // This method should be called just once after the object is 443 duncan 1.1.2.3 // created. 444 duncan 1.1.2.3 private void computeGenPrsvSets(BasicBlock bb) { 445 duncan 1.1.2.3 prsvSet[0].setAll(); 446 duncan 1.1.2.3 prsvSet[1].setAll(); 447 duncan 1.1.2.3 genSet[1].setAll(); 448 pnkfelix 1.1.2.13 for (Iterator i = bb.statements().listIterator(); i.hasNext();) { 449 duncan 1.1.2.3 Stm stm = (Stm)i.next(); 450 duncan 1.1.2.3 if (mayWriteMem(stm)) { 451 duncan 1.1.2.3 prsvSet[1].setAll(); 452 duncan 1.1.2.1 } 453 duncan 1.1.2.3 else { 454 duncan 1.1.2.3 if (stm.kind()==TreeKind.MOVE) { 455 duncan 1.1.2.3 prsvSet[0].and 456 cananian 1.1.2.18 ((BitString)tempsToPrsvs.get(usedefer.def(stm)[0])); 457 duncan 1.1.2.3 genSet[0].set(stm.getID()); 458 duncan 1.1.2.3 genSet[1].clear(stm.getID()); 459 duncan 1.1.2.3 } 460 duncan 1.1.2.1 } 461 duncan 1.1.2.1 } 462 duncan 1.1.2.1 } 463 duncan 1.1.2.3 464 duncan 1.1.2.3 public String toString() { 465 duncan 1.1.2.3 StringBuffer s = new StringBuffer(); 466 duncan 1.1.2.3 s.append( "tGen set: "+genSet[0].toString()); 467 duncan 1.1.2.3 s.append("\n\tPrsv set: "+prsvSet[0].toString()); 468 duncan 1.1.2.3 s.append("\n\tIn set: "+inSet[0].toString()); 469 duncan 1.1.2.3 s.append("\n\tOut set: "+outSet[0].toString()+"\n"); 470 duncan 1.1.2.3 return s.toString(); 471 duncan 1.1.2.1 } 472 duncan 1.1.2.1 } 473 duncan 1.1.2.1 474 duncan 1.1.2.3 475 duncan 1.1.2.1 476 duncan 1.1.2.3 // Returns true if the parameter is a statement that might perform 477 duncan 1.1.2.3 // a memory write. 478 duncan 1.1.2.3 private static boolean mayWriteMem(Stm s) { 479 duncan 1.1.2.3 int s_kind = s.kind(); 480 duncan 1.1.2.3 return 481 duncan 1.1.2.3 (s_kind==TreeKind.CALL) || 482 duncan 1.1.2.3 (s_kind==TreeKind.NATIVECALL) || 483 duncan 1.1.2.3 ((s_kind==TreeKind.MOVE) && 484 cananian 1.1.2.11 ((((MOVE)s).getDst()).kind()==TreeKind.MEM)); 485 duncan 1.1.2.1 } 486 duncan 1.1.2.1 } 487 duncan 1.1.2.1 488 duncan 1.1.2.3 489 cananian 1.2