1 cananian 1.1.2.1 // HoistingCheckOracle.java, created Sat Jan 13 14:45:14 2001 by cananian 2 cananian 1.1.2.7 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.Transactions; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.DomTree; 7 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 8 cananian 1.1.2.6 import harpoon.ClassFile.HCodeEdge; 9 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 10 cananian 1.1.2.6 import harpoon.IR.Properties.CFGrapher; 11 cananian 1.1.2.1 import harpoon.IR.Properties.UseDefer; 12 cananian 1.1.2.2 import harpoon.IR.Quads.MONITORENTER; 13 cananian 1.1.2.1 import harpoon.Temp.Temp; 14 cananian 1.1.2.1 import harpoon.Util.ArrayIterator; 15 cananian 1.5 import net.cscott.jutil.AggregateSetFactory; 16 cananian 1.5 import net.cscott.jutil.GenericMultiMap; 17 cananian 1.5 import net.cscott.jutil.MultiMap; 18 cananian 1.5 import net.cscott.jutil.SetFactory; 19 cananian 1.1.2.1 20 cananian 1.1.2.1 import java.util.Collection; 21 cananian 1.1.2.1 import java.util.Collections; 22 cananian 1.1.2.1 import java.util.Iterator; 23 cananian 1.1.2.1 import java.util.Set; 24 cananian 1.1.2.1 /** 25 cananian 1.1.2.1 * A <code>HoistingCheckOracle</code> tries to hoist and coalesce checks 26 cananian 1.1.2.3 * whenever possible. It improves on the results of a client 27 cananian 1.1.2.3 * <code>CheckOracle</code>. 28 cananian 1.1.2.1 * <p> 29 cananian 1.1.2.1 * The algorithm used is as follows: each check placed by the input 30 cananian 1.1.2.1 * oracle is moved to its immediate dominator iff that node is 31 cananian 1.1.2.1 * postdominated by the current node and that node is dominated by 32 cananian 1.1.2.1 * the definition of the variable referenced in the check. The 33 cananian 1.1.2.1 * process is repeated until no checks can be moved higher. 34 cananian 1.1.2.1 * 35 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 36 cananian 1.5 * @version $Id: HoistingCheckOracle.java,v 1.5 2004/02/08 01:54:21 cananian Exp $ 37 cananian 1.1.2.1 */ 38 cananian 1.3 // note: doesn't allow hoisting past sigmas. since input is SSA, this is 39 cananian 1.3 // fine. If you ever want to give it SSI instead, you should fix this. 40 cananian 1.1.2.3 class HoistingCheckOracle extends AnalysisCheckOracle { 41 cananian 1.1.2.1 /** Creates a <code>HoistingCheckOracle</code> for the given 42 cananian 1.1.2.1 * <code>HCode</code> which refines the checks placed by 43 cananian 1.1.2.1 * <code>CheckOracle</code> <code>co</code>. */ 44 cananian 1.1.2.6 public HoistingCheckOracle(HCode hc, CFGrapher cfgr, UseDefer udr, 45 cananian 1.1.2.6 CheckOracle co) { 46 cananian 1.1.2.6 this(hc, cfgr, udr, new DomTree(hc, cfgr, false), co); 47 cananian 1.1.2.3 } 48 cananian 1.1.2.3 // separate constructor to let us reuse an existing domtree. 49 cananian 1.1.2.6 HoistingCheckOracle(HCode hc, CFGrapher cfgr, UseDefer udr, 50 cananian 1.1.2.6 DomTree dt, CheckOracle co) { 51 cananian 1.1.2.3 /* compute the proper check locations (post-order down dt) */ 52 cananian 1.1.2.3 DomTree pdt = new DomTree(hc, true); 53 cananian 1.1.2.1 for (Iterator it=new ArrayIterator(dt.roots()); it.hasNext(); ) 54 cananian 1.1.2.6 hoister((HCodeElement)it.next(), co, cfgr, udr, dt, pdt, 55 cananian 1.1.2.1 false/*can't hoist above root*/); 56 cananian 1.1.2.1 /* done! */ 57 cananian 1.1.2.1 } 58 cananian 1.1.2.1 59 cananian 1.1.2.1 /* Returns checks which can be hoisted to immediate dominator */ 60 cananian 1.1.2.6 CheckSet hoister(HCodeElement hce, CheckOracle co, 61 cananian 1.1.2.6 CFGrapher cfgr, UseDefer udr, 62 cananian 1.1.2.1 DomTree dt, DomTree pdt, boolean canHoist) 63 cananian 1.1.2.1 { 64 cananian 1.1.2.1 /* collect checks from dominated children and from check oracle */ 65 cananian 1.1.2.3 CheckSet checks = new CheckSet(co, hce); 66 cananian 1.1.2.1 for (Iterator it=new ArrayIterator(dt.children(hce)); it.hasNext(); ) 67 cananian 1.1.2.6 checks.addAll(hoister((HCodeElement)it.next(), 68 cananian 1.1.2.6 co, cfgr, udr, dt, pdt, true)); 69 cananian 1.1.2.6 /** find common checks in successors. */ 70 cananian 1.4 HCodeEdge[] succ = (HCodeEdge[]) cfgr.succC(hce).toArray(new HCodeEdge[0]); 71 cananian 1.1.2.6 CheckSet common = null; // will contain intersection of all succ. chks 72 cananian 1.1.2.6 for (int i=0; i<succ.length; i++) { 73 cananian 1.1.2.6 CheckSet scs = (CheckSet) results.get(succ[i].to()); 74 cananian 1.1.2.6 if (scs==null) { common=null; break; /* bail out */} 75 cananian 1.1.2.6 if (common==null) common=new CheckSet(scs); 76 cananian 1.1.2.6 else { 77 cananian 1.1.2.6 scs = new CheckSet(scs); 78 cananian 1.1.2.6 scs.readVersions.addAll(scs.writeVersions); 79 cananian 1.1.2.6 common.retainAll(scs); 80 cananian 1.1.2.6 } 81 cananian 1.1.2.6 common.readVersions.addAll(common.writeVersions); 82 cananian 1.1.2.6 } 83 cananian 1.1.2.6 /** filter common checks */ 84 cananian 1.1.2.6 if (hce instanceof MONITORENTER) common=null; 85 cananian 1.1.2.8 // XXX: common=null if hoisting past possible call to Object.wait(). 86 cananian 1.1.2.6 if (common!=null) common.removeAll(udr.defC(hce)); 87 cananian 1.1.2.6 /** steal filtered common checks from successors */ 88 cananian 1.1.2.6 if (common!=null && !common.isEmpty()) { 89 cananian 1.1.2.6 System.err.println("HOISTING: "+common+" "+hce.getSourceFile()); 90 cananian 1.1.2.6 for (int i=0; i<succ.length; i++) { 91 cananian 1.1.2.6 CheckSet scs = (CheckSet) results.get(succ[i].to()); 92 cananian 1.1.2.6 scs.removeAll(common); 93 cananian 1.1.2.6 } 94 cananian 1.1.2.6 checks.addAll(common); 95 cananian 1.1.2.6 } 96 cananian 1.1.2.1 /** optimize: write versions are read versions */ 97 cananian 1.1.2.1 checks.readVersions.removeAll(checks.writeVersions); 98 cananian 1.1.2.5 /** copy set of all checks. */ 99 cananian 1.1.2.5 CheckSet nohoist = new CheckSet(checks); 100 cananian 1.1.2.1 101 cananian 1.1.2.1 /* can't hoist anything unless this==pidom(idom(this)) */ 102 cananian 1.1.2.1 canHoist = canHoist && (hce == pdt.idom(dt.idom(hce))); 103 cananian 1.1.2.2 /* never hoist above a MONITORENTER */ 104 cananian 1.1.2.2 canHoist = canHoist && !(dt.idom(hce) instanceof MONITORENTER); 105 cananian 1.1.2.5 /* okay, remove all if !canHoist */ 106 cananian 1.1.2.5 if (!canHoist) checks.clear(); 107 cananian 1.1.2.1 108 cananian 1.1.2.1 /* fetch the set of temps defined in our idom */ 109 cananian 1.1.2.1 Collection idomDef = (dt.idom(hce)==null) ? Collections.EMPTY_SET : 110 cananian 1.1.2.1 udr.defC(dt.idom(hce)); /* defs in idom of this */ 111 cananian 1.1.2.5 /* checks for a temp can't be hoisted above def */ 112 cananian 1.1.2.5 checks.removeAll(idomDef); 113 cananian 1.1.2.5 114 cananian 1.1.2.5 /** leave checks here which we can't hoist. */ 115 cananian 1.1.2.5 nohoist.removeAll(checks); 116 cananian 1.1.2.4 results.put(hce, nohoist); 117 cananian 1.1.2.1 118 cananian 1.1.2.1 /** give all of the rest of the checks to the idom */ 119 cananian 1.1.2.1 return checks; 120 cananian 1.1.2.1 } 121 cananian 1.2 }