1 cananian 1.1.2.1 // MemHoisting.java, created Wed Jun  6 16:52:24 2001 by cananian
  2 cananian 1.1.2.1 // 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.Tree;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  7 cananian 1.1.2.1 import harpoon.ClassFile.HCode;
  8 cananian 1.1.2.1 import harpoon.ClassFile.HCodeAndMaps;
  9 cananian 1.1.2.2 import harpoon.ClassFile.HCodeElement;
 10 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory;
 11 cananian 1.1.2.1 import harpoon.ClassFile.HMethod;
 12 cananian 1.1.2.1 import harpoon.IR.Properties.CFGrapher;
 13 cananian 1.1.2.1 import harpoon.IR.Tree.CanonicalTreeCode;
 14 cananian 1.1.2.1 import harpoon.IR.Tree.Code;
 15 cananian 1.1.2.1 import harpoon.IR.Tree.DerivationGenerator;
 16 cananian 1.1.2.1 import harpoon.IR.Tree.ESEQ;
 17 cananian 1.1.2.1 import harpoon.IR.Tree.Exp;
 18 cananian 1.1.2.1 import harpoon.IR.Tree.MEM;
 19 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE;
 20 cananian 1.1.2.1 import harpoon.IR.Tree.Stm;
 21 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP;
 22 cananian 1.1.2.1 import harpoon.IR.Tree.Tree;
 23 cananian 1.1.2.1 import harpoon.IR.Tree.TreeFactory;
 24 cananian 1.1.2.1 import harpoon.IR.Tree.TreeKind;
 25 cananian 1.1.2.1 import harpoon.Temp.Temp;
 26 cananian 1.1.2.1 import harpoon.Util.Util;
 27 cananian 1.1.2.1 
 28 cananian 1.1.2.1 import java.util.Arrays;
 29 cananian 1.1.2.1 import java.util.HashMap;
 30 cananian 1.1.2.2 import java.util.HashSet;
 31 cananian 1.1.2.1 import java.util.Iterator;
 32 cananian 1.1.2.1 import java.util.List;
 33 cananian 1.1.2.1 import java.util.Map;
 34 cananian 1.1.2.2 import java.util.Set;
 35 cananian 1.1.2.1 /**
 36 cananian 1.1.2.1  * <code>MemHoisting</code> ensures that the ordering of MEM operations
 37 cananian 1.1.2.1  * is well-defined in the tree, by creating a temporary for and hoisting
 38 cananian 1.1.2.1  * all but one MEM in any given subexpression.  Canonicalization completes
 39 cananian 1.1.2.1  * the transformation.
 40 cananian 1.1.2.1  * 
 41 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 42 cananian 1.4      * @version $Id: MemHoisting.java,v 1.4 2002/04/10 03:02:06 cananian Exp $
 43 cananian 1.1.2.1  */
 44 cananian 1.1.2.1 public abstract class MemHoisting extends Simplification {
 45 cananian 1.1.2.1     // hide constructor
 46 cananian 1.3.2.2     private MemHoisting() { }
 47 cananian 1.1.2.1     /** Code factory for applying MemHoisting to a
 48 cananian 1.1.2.1      *  canonical tree.  Clones the tree before doing
 49 cananian 1.1.2.1      *  transformation in-place. */
 50 cananian 1.1.2.1     public static HCodeFactory codeFactory(final HCodeFactory parent) {
 51 cananian 1.3.2.1         assert parent.getCodeName().equals(CanonicalTreeCode.codename);
 52 cananian 1.1.2.1         return Canonicalize.codeFactory(new HCodeFactory() {
 53 cananian 1.1.2.1             public HCode convert(HMethod m) {
 54 cananian 1.1.2.1                 HCode hc = parent.convert(m);
 55 cananian 1.1.2.1                 if (hc!=null) {
 56 cananian 1.1.2.1                     harpoon.IR.Tree.Code code = (harpoon.IR.Tree.Code) hc;
 57 cananian 1.1.2.1                     // clone code...
 58 cananian 1.1.2.1                     code = (harpoon.IR.Tree.Code) code.clone(m).hcode();
 59 cananian 1.1.2.1                     DerivationGenerator dg = null;
 60 cananian 1.1.2.1                     try {
 61 cananian 1.1.2.1                         dg = (DerivationGenerator) code.getTreeDerivation();
 62 cananian 1.1.2.1                     } catch (ClassCastException ex) { /* i guess not */ }
 63 cananian 1.1.2.1                     // ...do analysis and modify cloned code in-place.
 64 cananian 1.1.2.1                     simplify((Stm)code.getRootElement(), dg, HCE_RULES(code));
 65 cananian 1.1.2.1                     hc = code;
 66 cananian 1.1.2.1                 }
 67 cananian 1.1.2.1                 return hc;
 68 cananian 1.1.2.1             }
 69 cananian 1.1.2.1             public String getCodeName() { return parent.getCodeName(); }
 70 cananian 1.1.2.1             public void clear(HMethod m) { parent.clear(m); }
 71 cananian 1.1.2.1         });
 72 cananian 1.1.2.1     }
 73 cananian 1.1.2.1 
 74 cananian 1.3.2.2     private static int count(Tree tr, Map<Tree,Integer> m, int memcnt) {
 75 cananian 1.1.2.3         memcnt += (tr.kind()==TreeKind.MEM) ? 1 : 0;
 76 cananian 1.1.2.1         m.put(tr, new Integer(memcnt));
 77 cananian 1.1.2.3         for (Tree tp=tr.getFirstChild(); tp!=null; tp=tp.getSibling())
 78 cananian 1.1.2.3             memcnt=count(tp, m, memcnt);
 79 cananian 1.1.2.1         return memcnt;
 80 cananian 1.1.2.1     }
 81 cananian 1.3.2.2     private static void recurse(Stm stm, CFGrapher<Tree> cfgr,
 82 cananian 1.3.2.2                                 Set<Stm> done, Map<Tree,Integer> m) {
 83 cananian 1.1.2.2         // do this one.
 84 cananian 1.1.2.2         done.add(stm);
 85 cananian 1.1.2.3         count(stm, m, 0);
 86 cananian 1.1.2.2         // do successors.
 87 cananian 1.3.2.2         for (Iterator<Tree> it=cfgr.succElemC(stm).iterator(); it.hasNext();) {
 88 cananian 1.1.2.2             Stm next = (Stm) it.next();
 89 cananian 1.1.2.2             if (!done.contains(next))
 90 cananian 1.1.2.2                 recurse(next, cfgr, done, m);
 91 cananian 1.1.2.2         }
 92 cananian 1.1.2.2     }
 93 cananian 1.1.2.1 
 94 cananian 1.3.2.2     public static List<Rule> HCE_RULES(final harpoon.IR.Tree.Code code) {
 95 cananian 1.3.2.2         final CFGrapher<Tree> cfgr = code.getGrapher();
 96 cananian 1.1.2.1         // collect the number of MEMs in every subtree.
 97 cananian 1.3.2.2         final Map<Tree,Integer> memmap = new HashMap<Tree,Integer>();
 98 cananian 1.1.2.2 
 99 cananian 1.3.2.2         Set<Stm> done = new HashSet();
100 cananian 1.3.2.2         Tree[] roots = cfgr.getFirstElements(code);
101 cananian 1.1.2.2         for (int i=0; i<roots.length; i++)
102 cananian 1.1.2.2             recurse((Stm)roots[i], cfgr, done, memmap);
103 cananian 1.1.2.2         roots=null; done=null; // free memory.
104 cananian 1.1.2.1 
105 cananian 1.1.2.1         // now make rules.
106 cananian 1.1.2.1         return Arrays.asList(new Rule[] {
107 cananian 1.1.2.1             // MEM(x) -> ESEQ(MOVE(t, MEM(x)), t)
108 cananian 1.1.2.1             new Rule("hoistMem") {
109 cananian 1.1.2.1                 public boolean match(Exp e) {
110 cananian 1.1.2.1                     if (e.kind() != TreeKind.MEM) return false;
111 cananian 1.1.2.4                     // leave the first mem in a stm alone.
112 cananian 1.3.2.2                     if (memmap.get(e).intValue() < 2) return false;
113 cananian 1.1.2.4                     // assert that we're not messing with MOVE(t, MEM(x))
114 cananian 1.1.2.6                     // or MOVE(MEM(x), ...) trees [but MOVE(MEM(x), MEM(y))
115 cananian 1.1.2.6                     // is okay to touch, if we're hoisting the MEM(y) ]
116 cananian 1.1.2.5                     if (e.getParent()!=null &&
117 cananian 1.1.2.6                         e.getParent().kind() == TreeKind.MOVE) {
118 cananian 1.1.2.5                         MOVE m = (MOVE) e.getParent();
119 cananian 1.3.2.1                         assert m.getSrc().kind()==TreeKind.MEM &&
120 cananian 1.1.2.7                                     m.getDst().kind()==TreeKind.MEM &&
121 cananian 1.3.2.1                                     e == m.getSrc();
122 cananian 1.1.2.5                     }
123 cananian 1.1.2.1                     return true;
124 cananian 1.1.2.1                 }
125 cananian 1.1.2.1                 public Exp apply(TreeFactory tf,Exp e,DerivationGenerator dg) {
126 cananian 1.1.2.1                     MEM mem = (MEM) e;
127 cananian 1.1.2.1                     Temp t = new Temp(tf.tempFactory(), "memhoist");
128 cananian 1.1.2.1                     TEMP T1 = new TEMP(tf, e, mem.type(), t);
129 cananian 1.1.2.1                     TEMP T2 = new TEMP(tf, e, mem.type(), t);
130 cananian 1.1.2.2                     MEM nmem = (MEM) mem.build(tf, mem.kids());
131 cananian 1.1.2.1                     if (dg!=null) { // make types for the new TEMPs/Temp
132 cananian 1.1.2.1                         HClass hc = dg.typeMap(mem);
133 cananian 1.1.2.1                         if (hc!=null) {
134 cananian 1.1.2.1                             dg.putTypeAndTemp(T1, hc, t);
135 cananian 1.1.2.1                             dg.putTypeAndTemp(T2, hc, t);
136 cananian 1.1.2.2                             dg.putType(nmem, hc);
137 cananian 1.1.2.1                         } else {
138 cananian 1.1.2.1                             dg.putDerivation(T1, dg.derivation(mem));
139 cananian 1.1.2.1                             dg.putDerivation(T2, dg.derivation(mem));
140 cananian 1.1.2.2                             dg.putDerivation(nmem, dg.derivation(mem));
141 cananian 1.1.2.1                         }
142 cananian 1.1.2.2                         dg.remove(mem);
143 cananian 1.1.2.1                     }
144 cananian 1.1.2.7                     memmap.put(nmem, new Integer(1)); memmap.remove(mem);
145 cananian 1.1.2.1                     return new ESEQ(tf, e,
146 cananian 1.1.2.2                                     new MOVE(tf, e, T1, nmem),
147 cananian 1.1.2.1                                     T2);
148 cananian 1.1.2.1                 }
149 cananian 1.1.2.1             },
150 cananian 1.1.2.1         });
151 cananian 1.1.2.1     }
152 cananian 1.2     }