1 cananian 1.1.2.1 // AlgebraicSimplification.java, created Sat Dec 18 17:42:19 1999 by duncan 2 cananian 1.1.2.1 // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.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.HCode; 7 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 8 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 9 cananian 1.1.2.1 import harpoon.IR.Tree.BINOP; 10 cananian 1.1.2.1 import harpoon.IR.Tree.Bop; 11 cananian 1.1.2.1 import harpoon.IR.Tree.CanonicalTreeCode; 12 cananian 1.1.2.1 import harpoon.IR.Tree.Code; 13 cananian 1.1.2.1 import harpoon.IR.Tree.CONST; 14 cananian 1.1.2.3 import harpoon.IR.Tree.DerivationGenerator; 15 cananian 1.1.2.1 import harpoon.IR.Tree.ESEQ; 16 cananian 1.1.2.1 import harpoon.IR.Tree.Exp; 17 cananian 1.1.2.1 import harpoon.IR.Tree.ExpList; 18 cananian 1.1.2.1 import harpoon.IR.Tree.SEQ; 19 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 20 cananian 1.1.2.1 import harpoon.IR.Tree.Tree; 21 cananian 1.1.2.1 import harpoon.IR.Tree.TreeFactory; 22 cananian 1.1.2.1 import harpoon.IR.Tree.TreeKind; 23 cananian 1.1.2.1 import harpoon.IR.Tree.TreeVisitor; 24 cananian 1.1.2.1 import harpoon.IR.Tree.Type; 25 cananian 1.1.2.1 import harpoon.IR.Tree.UNOP; 26 cananian 1.1.2.1 import harpoon.IR.Tree.Uop; 27 cananian 1.1.2.1 import harpoon.Util.Util; 28 cananian 1.1.2.1 29 cananian 1.1.2.1 import java.util.ArrayList; 30 cananian 1.1.2.1 import java.util.Collections; 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.Stack; 34 cananian 1.1.2.1 35 cananian 1.1.2.1 /** 36 cananian 1.1.2.1 * <code>Simplification</code> is a general-purpose simplification engine 37 cananian 1.1.2.1 * for trees. 38 cananian 1.1.2.1 * 39 cananian 1.1.2.1 * <B>Warning:</B> this performs modifications on the tree form in place. 40 cananian 1.1.2.1 * 41 cananian 1.1.2.1 * @author Duncan Bryce <duncan@lcs.mit.edu> 42 cananian 1.4 * @version $Id: Simplification.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 Simplification { 45 cananian 1.1.2.1 private static final boolean debug = false; 46 cananian 1.1.2.1 // hide constructor 47 cananian 1.1.2.1 protected Simplification() { } 48 cananian 1.1.2.1 49 cananian 1.1.2.1 /** 50 cananian 1.1.2.1 * Code factory for applying a set of simplification rules to 51 cananian 1.1.2.1 * tree form. Clones the tree before simplifying it in-place. 52 cananian 1.1.2.1 */ 53 cananian 1.1.2.1 public static HCodeFactory codeFactory(final HCodeFactory parent, 54 cananian 1.3.2.2 final List<Rule> rules) { 55 cananian 1.3.2.1 assert parent.getCodeName().equals(CanonicalTreeCode.codename); 56 cananian 1.1.2.1 return new HCodeFactory() { 57 cananian 1.1.2.1 public HCode convert(HMethod m) { 58 cananian 1.1.2.1 HCode hc = parent.convert(m); 59 cananian 1.1.2.1 if (hc!=null) { 60 cananian 1.1.2.1 harpoon.IR.Tree.Code code = (harpoon.IR.Tree.Code) hc; 61 cananian 1.1.2.2 // clone code... 62 cananian 1.1.2.9 code = (harpoon.IR.Tree.Code) code.clone(m).hcode(); 63 cananian 1.1.2.3 DerivationGenerator dg = null; 64 cananian 1.1.2.3 try { 65 cananian 1.1.2.3 dg = (DerivationGenerator) code.getTreeDerivation(); 66 cananian 1.1.2.3 } catch (ClassCastException ex) { /* i guess not */ } 67 cananian 1.1.2.2 // ...and modify cloned code in-place. 68 cananian 1.1.2.3 simplify((Stm)code.getRootElement(), dg, rules); 69 cananian 1.1.2.5 hc = code; 70 cananian 1.1.2.1 } 71 cananian 1.1.2.1 return hc; 72 cananian 1.1.2.1 } 73 cananian 1.1.2.1 public String getCodeName() { return parent.getCodeName(); } 74 cananian 1.1.2.1 public void clear(HMethod m) { parent.clear(m); } 75 cananian 1.1.2.1 }; 76 cananian 1.1.2.1 } 77 cananian 1.1.2.1 78 cananian 1.1.2.1 // Define new operator constants that can be masked together. 79 cananian 1.1.2.1 protected final static int _CMPLT = (1<<0); 80 cananian 1.1.2.1 protected final static int _CMPLE = (1<<1); 81 cananian 1.1.2.1 protected final static int _CMPEQ = (1<<2); 82 cananian 1.1.2.7 protected final static int _CMPNE = (1<<15); 83 cananian 1.1.2.1 protected final static int _CMPGE = (1<<3); 84 cananian 1.1.2.1 protected final static int _CMPGT = (1<<4); 85 cananian 1.1.2.1 protected final static int _ADD = (1<<5); 86 cananian 1.1.2.1 protected final static int _MUL = (1<<6); 87 cananian 1.1.2.1 protected final static int _DIV = (1<<7); 88 cananian 1.1.2.1 protected final static int _REM = (1<<8); 89 cananian 1.1.2.1 protected final static int _SHL = (1<<9); 90 cananian 1.1.2.1 protected final static int _SHR = (1<<10); 91 cananian 1.1.2.1 protected final static int _USHR = (1<<11); 92 cananian 1.1.2.1 protected final static int _AND = (1<<12); 93 cananian 1.1.2.1 protected final static int _OR = (1<<13); 94 cananian 1.1.2.1 protected final static int _XOR = (1<<14); 95 cananian 1.1.2.1 96 cananian 1.1.2.1 // Define new TreeKind constants that can be masked together. 97 cananian 1.1.2.1 protected final static int _ALIGN = (1<<0); 98 cananian 1.1.2.1 protected final static int _BINOP = (1<<1); 99 cananian 1.1.2.1 protected final static int _CALL = (1<<2); 100 cananian 1.1.2.1 protected final static int _CJUMP = (1<<3); 101 cananian 1.1.2.1 // _CONST represents all constants including 0 and null. 102 cananian 1.1.2.1 // _CONST0 _CONST1 _CONSTm1 and _CONSTNULL represent specific constants. 103 cananian 1.1.2.1 protected final static int _CONST = (1<<4); 104 cananian 1.1.2.1 protected final static int _DATUM = (1<<5); 105 cananian 1.1.2.1 protected final static int _ESEQ = (1<<6); 106 jwhaley 1.1.2.8 protected final static int _EXPR = (1<<7); 107 cananian 1.1.2.1 protected final static int _JUMP = (1<<8); 108 cananian 1.1.2.1 protected final static int _LABEL = (1<<9); 109 cananian 1.1.2.1 protected final static int _MEM = (1<<10); 110 cananian 1.1.2.1 protected final static int _METHOD = (1<<11); 111 cananian 1.1.2.1 protected final static int _MOVE = (1<<12); 112 cananian 1.1.2.1 protected final static int _NAME = (1<<13); 113 cananian 1.1.2.1 protected final static int _NATIVECALL = (1<<14); 114 cananian 1.1.2.1 protected final static int _RETURN = (1<<15); 115 cananian 1.1.2.1 protected final static int _SEGMENT = (1<<16); 116 cananian 1.1.2.1 protected final static int _SEQ = (1<<17); 117 cananian 1.1.2.1 protected final static int _TEMP = (1<<18); 118 cananian 1.1.2.1 protected final static int _THROW = (1<<19); 119 cananian 1.1.2.1 protected final static int _UNOP = (1<<20); 120 cananian 1.1.2.1 121 cananian 1.1.2.1 // Define more specialized types used to match rules. 122 cananian 1.1.2.1 protected final static int _CONSTNULL = (1<<21); 123 cananian 1.1.2.1 protected final static int _CONSTm1 = (1<<22); 124 cananian 1.1.2.1 protected final static int _CONST0 = (1<<23); 125 cananian 1.1.2.1 protected final static int _CONST1 = (1<<24); 126 cananian 1.1.2.1 127 cananian 1.1.2.1 /** 128 cananian 1.1.2.1 * Performs simplification on <code>root</code>, using the 129 cananian 1.1.2.1 * specified set of simplification rules. 130 cananian 1.1.2.1 * <b>Requires:</b> 131 cananian 1.1.2.1 * <OL> 132 cananian 1.1.2.1 * <LI><code>root</code> is a tree. 133 cananian 1.1.2.1 * <LI>Each element of <code>rules</code> is an implementation of the 134 cananian 1.1.2.1 * <code>Simplification.Rule</code> interface. 135 cananian 1.1.2.1 * <LI>The supplied set of rules monotonically reduces all possible 136 cananian 1.1.2.1 * <code>Tree</code> objects to some fixed point. 137 cananian 1.1.2.1 * </OL> 138 cananian 1.1.2.1 * 139 cananian 1.1.2.1 * @param root the tree to simplify 140 cananian 1.1.2.3 * @param dg a <code>DerivationGenerator</code> for the tree, 141 cananian 1.1.2.3 * or <code>null</code> to generate no type information. 142 cananian 1.1.2.1 * @param rules the set of simplification rules to apply to the elements 143 cananian 1.1.2.1 * of <code>root</code>. 144 cananian 1.1.2.1 */ 145 cananian 1.3.2.2 public static void simplify(Tree root, DerivationGenerator dg, List<Rule> rules) 146 cananian 1.1.2.3 { 147 cananian 1.1.2.1 // Shouldn't pass a null ptr. 148 cananian 1.3.2.1 assert root != null && rules != null; 149 cananian 1.1.2.1 150 cananian 1.1.2.1 // Perform the simplification. 151 cananian 1.1.2.3 while (new SimplificationVisitor(root, dg, rules).changed()) 152 cananian 1.1.2.1 /* repeat */ ; 153 cananian 1.1.2.1 } 154 cananian 1.1.2.1 155 cananian 1.1.2.1 /** 156 cananian 1.1.2.1 * A class to applies simplification rules to elements of a canonical 157 cananian 1.1.2.1 * tree form. 158 cananian 1.1.2.1 */ 159 cananian 1.1.2.1 private static class SimplificationVisitor extends TreeVisitor { 160 cananian 1.1.2.3 private final TreeFactory tf; 161 cananian 1.1.2.3 private final DerivationGenerator dg; 162 cananian 1.1.2.4 private final Rule[] rules; 163 cananian 1.1.2.1 private boolean changed = false; 164 cananian 1.1.2.1 165 cananian 1.1.2.3 public SimplificationVisitor(Tree root, DerivationGenerator dg, 166 cananian 1.3.2.2 List<Rule> rules) { 167 cananian 1.1.2.3 this.tf = root.getFactory(); 168 cananian 1.1.2.3 this.dg = dg; 169 cananian 1.3.2.2 this.rules = rules.toArray(new Rule[rules.size()]); 170 cananian 1.1.2.1 // evaluate each subtree from leaves up to root. 171 cananian 1.1.2.1 postorder(root); 172 cananian 1.1.2.1 } 173 cananian 1.1.2.1 void postorder(Tree t) { 174 cananian 1.1.2.1 // post-order traversal: visit all children first. 175 cananian 1.1.2.1 for (Tree tp = t.getFirstChild(); tp!=null; ) { 176 cananian 1.1.2.1 Tree one = tp; 177 cananian 1.1.2.1 tp=tp.getSibling();// advance *before* we (possibly) unlink tp! 178 cananian 1.1.2.1 postorder(one); 179 cananian 1.1.2.1 } 180 cananian 1.1.2.1 // now visit this. 181 cananian 1.1.2.1 t.accept(this); 182 cananian 1.1.2.1 } 183 cananian 1.1.2.1 public boolean changed() { return changed; } 184 cananian 1.1.2.1 185 cananian 1.1.2.1 public void visit(Tree t) { 186 cananian 1.1.2.1 throw new Error("No defaults here."); 187 cananian 1.1.2.1 } 188 cananian 1.1.2.1 189 cananian 1.1.2.1 public void visit(Exp e) { 190 cananian 1.1.2.10 boolean done = false; 191 cananian 1.1.2.10 RESTART: while (!done) { 192 cananian 1.1.2.4 for (int i=0; i<rules.length; i++) { 193 cananian 1.1.2.4 Rule rule = rules[i]; 194 cananian 1.1.2.1 if (rule.match(e)) { 195 cananian 1.1.2.3 Exp simpleE = rule.apply(tf, e, dg); 196 cananian 1.1.2.1 if (debug) 197 cananian 1.1.2.1 System.out.println("Replacing: " + e + " with " + 198 cananian 1.1.2.1 simpleE + " by rule " + rule); 199 cananian 1.1.2.10 e.replace(simpleE);// XXX: simpleE cannot contain e 200 cananian 1.1.2.1 e = simpleE; 201 cananian 1.1.2.1 changed = true; 202 cananian 1.1.2.1 // revisit this. 203 cananian 1.1.2.1 continue RESTART; 204 cananian 1.1.2.1 } 205 cananian 1.1.2.1 } 206 cananian 1.1.2.10 done = true; // okay, so this is just a hacked-together 'goto' 207 cananian 1.1.2.10 } 208 cananian 1.1.2.1 } 209 cananian 1.1.2.1 210 cananian 1.1.2.1 public void visit(Stm s) { 211 cananian 1.1.2.10 boolean done = false; 212 cananian 1.1.2.10 RESTART: while (!done) { 213 cananian 1.1.2.4 for (int i=0; i<rules.length; i++) { 214 cananian 1.1.2.4 Rule rule = rules[i]; 215 cananian 1.1.2.1 if (rule.match(s)) { 216 cananian 1.1.2.3 Stm simpleS = rule.apply(tf, s, dg); 217 cananian 1.1.2.1 if (debug) 218 cananian 1.1.2.1 System.out.println("Replacing: " + s + " with " + 219 cananian 1.1.2.1 simpleS + " by rule " + rule); 220 cananian 1.1.2.10 s.replace(simpleS);// XXX: simpleS cannot contain e 221 cananian 1.1.2.1 s = simpleS; 222 cananian 1.1.2.1 changed = true; 223 cananian 1.1.2.1 // revisit this. 224 cananian 1.1.2.1 continue RESTART; 225 cananian 1.1.2.1 } 226 cananian 1.1.2.1 } 227 cananian 1.1.2.10 done = true; // okay, so this is just a hacked-together 'goto' 228 cananian 1.1.2.10 } 229 cananian 1.1.2.1 } 230 cananian 1.1.2.1 } 231 cananian 1.1.2.1 232 cananian 1.1.2.1 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// 233 cananian 1.1.2.1 // // 234 cananian 1.1.2.1 // Auxiliary Classes // 235 cananian 1.1.2.1 // // 236 cananian 1.1.2.1 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// 237 cananian 1.1.2.1 238 cananian 1.1.2.1 /** 239 cananian 1.1.2.1 * A simplification rule for use with the tree simplifier. 240 cananian 1.1.2.1 */ 241 cananian 1.1.2.1 public static abstract class Rule { 242 cananian 1.1.2.1 private final String _name; 243 cananian 1.1.2.1 public Rule(String name) { this._name = name; } 244 cananian 1.1.2.1 /** Returns a human-readable name for this rule. */ 245 cananian 1.1.2.1 public String toString() { return _name; } 246 cananian 1.1.2.1 /** Returns true if <code>exp</code> matches this rule. */ 247 cananian 1.1.2.1 public boolean match(Exp exp) { return false; } 248 cananian 1.1.2.1 /** Applies this rule to <code>exp</code>, and returns the result. 249 cananian 1.1.2.1 * <code>apply()</code> should always succeed when 250 cananian 1.1.2.1 * <code>match()</code> returns <code>true</code>. Otherwise, 251 cananian 1.1.2.1 * the behavior of <code>apply</code> is undefined. 252 cananian 1.1.2.10 * The returned <code>Exp</code> cannot contain the parameter 253 cananian 1.1.2.10 * <code>exp</code>, although it can contain its children. 254 cananian 1.1.2.10 * (use exp.build(tf, exp.kids()) to workaround this limitation.) 255 cananian 1.1.2.1 */ 256 cananian 1.1.2.3 public Exp apply(TreeFactory tf, Exp exp, DerivationGenerator dg) { 257 cananian 1.1.2.3 throw new Error("unimplemented"); 258 cananian 1.1.2.3 } 259 cananian 1.1.2.1 260 cananian 1.1.2.1 /** Returns true if <code>stm</code> matches this rule. */ 261 cananian 1.1.2.1 public boolean match(Stm stm) { return false; } 262 cananian 1.1.2.1 /** Applies this rule to <code>stm</code>, and returns the result. 263 cananian 1.1.2.1 * <code>apply()</code> should always succeed when 264 cananian 1.1.2.1 * <code>match()</code> returns <code>true</code>. Otherwise, 265 cananian 1.1.2.1 * the behavior of <code>apply</code> is undefined. 266 cananian 1.1.2.10 * The returned <code>Stm</code> cannot contain the parameter 267 cananian 1.1.2.10 * <code>stm</code>, although it can contain its children. 268 cananian 1.1.2.10 * (use stm.build(tf, stm.kids()) to workaround this limitation.) 269 cananian 1.1.2.1 */ 270 cananian 1.1.2.3 public Stm apply(TreeFactory tf, Stm stm, DerivationGenerator dg) { 271 cananian 1.1.2.3 throw new Error("unimplemented"); 272 cananian 1.1.2.3 } 273 cananian 1.1.2.1 } 274 cananian 1.1.2.1 275 cananian 1.1.2.1 /** Convenience function to test whether any of the bits in 276 cananian 1.1.2.1 * <code>mask</code> are set in <code>val</code>. */ 277 cananian 1.1.2.1 protected static boolean contains(int val, int mask) { 278 cananian 1.1.2.1 return (val & mask) != 0; 279 cananian 1.1.2.1 } 280 cananian 1.1.2.1 protected static int _KIND(Tree t) { 281 cananian 1.1.2.1 switch (t.kind()) { 282 cananian 1.1.2.1 case TreeKind.ALIGN: return _ALIGN; 283 cananian 1.1.2.1 case TreeKind.BINOP: return _BINOP; 284 cananian 1.1.2.1 case TreeKind.CALL: return _CALL; 285 cananian 1.1.2.1 case TreeKind.CJUMP: return _CJUMP; 286 cananian 1.1.2.1 case TreeKind.CONST: 287 cananian 1.1.2.1 CONST c = (CONST)t; 288 cananian 1.1.2.1 return _CONST | 289 cananian 1.1.2.6 (c.isFloatingPoint() ? 0 : 290 cananian 1.1.2.11 // note that CONSTNULL is not necessarily same as CONST0 291 cananian 1.1.2.6 c.value == null ? _CONSTNULL : 292 cananian 1.1.2.6 c.value.longValue() == 0 ? _CONST0 : 293 cananian 1.1.2.6 c.value.longValue() == 1 ? _CONST1 : 294 cananian 1.1.2.6 c.value.longValue() ==-1 ? _CONSTm1: 295 cananian 1.1.2.1 0); 296 cananian 1.1.2.1 case TreeKind.DATUM: return _DATUM; 297 cananian 1.1.2.1 case TreeKind.ESEQ: return _ESEQ; 298 jwhaley 1.1.2.8 case TreeKind.EXPR: return _EXPR; 299 cananian 1.1.2.1 case TreeKind.JUMP: return _JUMP; 300 cananian 1.1.2.1 case TreeKind.LABEL: return _LABEL; 301 cananian 1.1.2.1 case TreeKind.MEM: return _MEM; 302 cananian 1.1.2.1 case TreeKind.METHOD: return _METHOD; 303 cananian 1.1.2.1 case TreeKind.MOVE: return _MOVE; 304 cananian 1.1.2.1 case TreeKind.NAME: return _NAME; 305 cananian 1.1.2.1 case TreeKind.NATIVECALL: return _NATIVECALL; 306 cananian 1.1.2.1 case TreeKind.RETURN: return _RETURN; 307 cananian 1.1.2.1 case TreeKind.SEGMENT: return _SEGMENT; 308 cananian 1.1.2.1 case TreeKind.SEQ: return _SEQ; 309 cananian 1.1.2.1 case TreeKind.TEMP: return _TEMP; 310 cananian 1.1.2.1 case TreeKind.THROW: return _THROW; 311 cananian 1.1.2.1 case TreeKind.UNOP: return _UNOP; 312 cananian 1.1.2.1 default: throw new Error("Unrecognized type: " + t.kind()); 313 cananian 1.1.2.1 } 314 cananian 1.1.2.1 } 315 cananian 1.1.2.1 316 cananian 1.1.2.1 protected static int _OP(int op) { 317 cananian 1.1.2.1 switch (op) { 318 cananian 1.1.2.1 case Bop.CMPLT: return _CMPLT; 319 cananian 1.1.2.1 case Bop.CMPLE: return _CMPLE; 320 cananian 1.1.2.1 case Bop.CMPEQ: return _CMPEQ; 321 cananian 1.1.2.7 case Bop.CMPNE: return _CMPNE; 322 cananian 1.1.2.1 case Bop.CMPGE: return _CMPGE; 323 cananian 1.1.2.1 case Bop.CMPGT: return _CMPGT; 324 cananian 1.1.2.1 case Bop.ADD: return _ADD; 325 cananian 1.1.2.1 case Bop.MUL: return _MUL; 326 cananian 1.1.2.1 case Bop.DIV: return _DIV; 327 cananian 1.1.2.1 case Bop.REM: return _REM; 328 cananian 1.1.2.1 case Bop.SHL: return _SHL; 329 cananian 1.1.2.1 case Bop.SHR: return _SHR; 330 cananian 1.1.2.1 case Bop.USHR: return _USHR; 331 cananian 1.1.2.1 case Bop.AND: return _AND; 332 cananian 1.1.2.1 case Bop.OR: return _OR; 333 cananian 1.1.2.1 case Bop.XOR: return _XOR; 334 cananian 1.1.2.1 default: throw new Error("Unrecognized op: " + op); 335 cananian 1.1.2.1 } 336 cananian 1.1.2.1 } 337 cananian 1.2 }