1 cananian 1.1.2.1 // AlignmentAnalysis.java, created Thu Mar 14 01:19:55 2002 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.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Analysis.DomTree; 8 cananian 1.1.2.1 import harpoon.Analysis.ReachingDefs; 9 cananian 1.1.2.1 import harpoon.Analysis.ReachingDefsAltImpl; 10 cananian 1.1.2.1 import harpoon.Analysis.Maps.Derivation.DList; 11 cananian 1.1.2.1 import harpoon.Backend.Generic.Runtime.TreeBuilder; 12 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 13 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 14 cananian 1.1.2.1 import harpoon.ClassFile.HCode.PrintCallback; 15 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 16 cananian 1.1.2.1 import harpoon.IR.Properties.CFGrapher; 17 cananian 1.1.2.1 import harpoon.IR.Properties.UseDefer; 18 cananian 1.1.2.1 import harpoon.IR.Tree.BINOP; 19 cananian 1.1.2.1 import harpoon.IR.Tree.Bop; 20 cananian 1.1.2.1 import harpoon.IR.Tree.CALL; 21 cananian 1.1.2.1 import harpoon.IR.Tree.CONST; 22 cananian 1.1.2.1 import harpoon.IR.Tree.Code; 23 cananian 1.1.2.1 import harpoon.IR.Tree.ESEQ; 24 cananian 1.1.2.1 import harpoon.IR.Tree.Exp; 25 cananian 1.1.2.1 import harpoon.IR.Tree.ExpList; 26 cananian 1.1.2.1 import harpoon.IR.Tree.INVOCATION; 27 cananian 1.1.2.1 import harpoon.IR.Tree.MEM; 28 cananian 1.1.2.1 import harpoon.IR.Tree.METHOD; 29 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE; 30 cananian 1.1.2.1 import harpoon.IR.Tree.NAME; 31 cananian 1.1.2.1 import harpoon.IR.Tree.Print; 32 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 33 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP; 34 cananian 1.1.2.1 import harpoon.IR.Tree.Tree; 35 cananian 1.1.2.1 import harpoon.IR.Tree.TreeDerivation; 36 cananian 1.1.2.1 import harpoon.IR.Tree.TreeKind; 37 cananian 1.1.2.1 import harpoon.IR.Tree.TreeVisitor; 38 cananian 1.1.2.1 import harpoon.IR.Tree.Type; 39 cananian 1.1.2.1 import harpoon.IR.Tree.UNOP; 40 cananian 1.1.2.1 import harpoon.IR.Tree.Uop; 41 cananian 1.1.2.1 import harpoon.Temp.Label; 42 cananian 1.1.2.1 import harpoon.Temp.Temp; 43 cananian 1.1.2.1 44 cananian 1.1.2.1 import java.util.Arrays; 45 cananian 1.1.2.1 import java.util.Collection; 46 cananian 1.1.2.1 import java.util.Collections; 47 cananian 1.1.2.1 import java.util.HashMap; 48 cananian 1.1.2.1 import java.util.HashSet; 49 cananian 1.1.2.1 import java.util.Iterator; 50 cananian 1.1.2.1 import java.util.List; 51 cananian 1.1.2.1 import java.util.Map; 52 cananian 1.1.2.1 import java.util.Set; 53 cananian 1.3 54 cananian 1.3 import net.cscott.jutil.GenericMultiMap; 55 cananian 1.3 import net.cscott.jutil.MultiMap; 56 cananian 1.3 import net.cscott.jutil.Default; 57 cananian 1.3 import net.cscott.jutil.Environment; 58 cananian 1.3 import net.cscott.jutil.HashEnvironment; 59 cananian 1.3 import net.cscott.jutil.Util; 60 cananian 1.3 import net.cscott.jutil.WorkSet; 61 cananian 1.1.2.1 /** 62 cananian 1.1.2.1 * <code>AlignmentAnalysis</code> computes the alignment 63 cananian 1.1.2.1 * (some offset modulo some number from some base) of every 64 cananian 1.1.2.1 * typed pointer in a Tree. It is a dataflow analysis. 65 cananian 1.1.2.1 * 66 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 67 cananian 1.4 * @version $Id: AlignmentAnalysis.java,v 1.4 2004/02/08 03:20:34 cananian Exp $ 68 cananian 1.1.2.1 */ 69 cananian 1.1.2.1 public class AlignmentAnalysis { 70 cananian 1.1.2.1 71 cananian 1.1.2.1 final ReachingDefs<Tree> rd; 72 cananian 1.1.2.1 final TreeDerivation td; 73 cananian 1.1.2.1 /** Creates a <code>AlignmentAnalysis</code>. */ 74 cananian 1.1.2.1 public AlignmentAnalysis(Code c, CFGrapher<Tree> cfg, UseDefer<Tree> udr, 75 cananian 1.1.2.1 TreeDerivation td) { 76 cananian 1.1.2.1 this.rd = new ReachingDefsAltImpl<Tree>(c, cfg, udr); 77 cananian 1.1.2.1 this.td = td; 78 cananian 1.1.2.1 new StmVisitor(c, cfg, udr); 79 cananian 1.1.2.1 } 80 cananian 1.1.2.1 /* dataflow result accessor functions */ 81 cananian 1.1.2.1 public Value valueOf(Exp e, Stm root) { 82 cananian 1.1.2.1 return new ValueVisitor(e, root).value; 83 cananian 1.1.2.1 } 84 cananian 1.1.2.1 /* temp x stm-to-value mapping */ 85 cananian 1.1.2.1 private Map<Map.Entry<Temp,Stm>,Value> valueMap = 86 cananian 1.1.2.1 new HashMap<Map.Entry<Temp,Stm>,Value>(); 87 cananian 1.1.2.1 public Value valueUseAt(Temp t, Stm s) { 88 cananian 1.1.2.1 Value v = Value.NOINFO; 89 cananian 1.1.2.1 Set<Tree> rdset=rd.reachingDefs(s, t); 90 cananian 1.1.2.1 for (Iterator<Tree> it=rdset.iterator(); it.hasNext(); ) 91 cananian 1.1.2.1 v = v.unify(valueDefAt(t, (Stm)it.next())); 92 cananian 1.1.2.1 return v.fillKGroup(rdset, t); 93 cananian 1.1.2.1 } 94 cananian 1.1.2.1 public Value valueDefAt(Temp t, Stm s) { 95 cananian 1.1.2.1 Value v = valueMap.get(Default.entry(t,s)); 96 cananian 1.1.2.1 return (v==null) ? Value.NOINFO : v; 97 cananian 1.1.2.1 } 98 cananian 1.1.2.1 /** visitor class to do dataflow through statements */ 99 cananian 1.1.2.1 private class StmVisitor extends TreeVisitor { 100 cananian 1.1.2.1 MultiMap<Map.Entry<Temp,Stm>,Stm> uses = 101 cananian 1.1.2.1 new GenericMultiMap<Map.Entry<Temp,Stm>,Stm>(); 102 cananian 1.1.2.1 WorkSet<Stm> ws = new WorkSet<Stm>(); 103 cananian 1.1.2.1 StmVisitor(Code c, CFGrapher<Tree> cfg, UseDefer<Tree> udr) { 104 cananian 1.1.2.1 /* create uses map & add all elements to worklist. */ 105 cananian 1.1.2.1 for (Iterator<Tree> it=cfg.getElements(c).iterator(); 106 cananian 1.1.2.1 it.hasNext(); ) { 107 cananian 1.1.2.1 Stm s = (Stm) it.next(); 108 cananian 1.4 for (Temp u : udr.useC(s)) { 109 cananian 1.1.2.1 for (Iterator<Tree> it3=rd.reachingDefs(s, u).iterator(); 110 cananian 1.1.2.1 it3.hasNext(); ) { 111 cananian 1.1.2.1 Stm d = (Stm) it3.next(); 112 cananian 1.1.2.1 uses.add(Default.entry(u,d), s); 113 cananian 1.1.2.1 } 114 cananian 1.1.2.1 } 115 cananian 1.1.2.1 // add all statements s to worklist. 116 cananian 1.1.2.1 ws.addLast(s); 117 cananian 1.1.2.1 } 118 cananian 1.1.2.1 /* for each element on the worklist... */ 119 cananian 1.1.2.1 while (!ws.isEmpty()) { 120 cananian 1.1.2.1 Stm s = ws.removeFirst(); 121 cananian 1.1.2.1 s.accept(this); 122 cananian 1.1.2.1 } 123 cananian 1.1.2.1 } 124 cananian 1.1.2.1 public void update(Temp t, Stm def, Value v) { 125 cananian 1.1.2.1 assert t!=null && def!=null && v!=null; 126 cananian 1.1.2.1 Map.Entry<Temp,Stm> pair = Default.entry(t, def); 127 cananian 1.1.2.1 Value old = valueMap.put(pair, v); 128 cananian 1.1.2.1 if (old==null || !old.equals(v)) 129 cananian 1.1.2.1 //put uses of t on the workset. 130 cananian 1.1.2.1 for (Iterator<Stm> it = uses.getValues(pair).iterator(); 131 cananian 1.1.2.1 it.hasNext(); ) 132 cananian 1.1.2.1 ws.addLast(it.next()); 133 cananian 1.1.2.1 } 134 cananian 1.1.2.1 public void visit(Tree e) { assert false; } 135 cananian 1.1.2.1 public void visit(Stm s) { /* no defs */ } 136 cananian 1.1.2.1 public void visit(INVOCATION s) { 137 cananian 1.1.2.1 TEMP t = s.getRetval(); 138 cananian 1.1.2.1 if (t!=null) 139 cananian 1.1.2.1 update(t.temp, s, 140 cananian 1.1.2.1 new BaseAndOffset(new TempDefPoint(t, s), 0)); 141 cananian 1.1.2.1 } 142 cananian 1.1.2.1 public void visit(CALL s) { 143 cananian 1.1.2.1 visit((INVOCATION)s); 144 cananian 1.1.2.1 TEMP t = s.getRetex(); 145 cananian 1.1.2.1 update(t.temp, s, 146 cananian 1.1.2.1 new BaseAndOffset(new TempDefPoint(t, s), 0)); 147 cananian 1.1.2.1 } 148 cananian 1.1.2.1 public void visit(METHOD s) { 149 cananian 1.1.2.1 for (int i=0; i<s.getParamsLength(); i++) { 150 cananian 1.1.2.1 TEMP t = s.getParams(i); 151 cananian 1.1.2.1 update(t.temp, s, 152 cananian 1.1.2.1 new BaseAndOffset(new TempDefPoint(t, s), 0)); 153 cananian 1.1.2.1 } 154 cananian 1.1.2.1 } 155 cananian 1.1.2.1 public void visit(MOVE s) { 156 cananian 1.1.2.1 if (s.getDst().kind()==TreeKind.TEMP) { 157 cananian 1.1.2.1 TEMP t = (TEMP) s.getDst(); 158 cananian 1.1.2.1 Value v = valueOf(s.getSrc(), s); 159 cananian 1.1.2.1 if (s.getDst().type()==Type.POINTER && 160 cananian 1.1.2.1 v.isBaseKnown() && 161 cananian 1.1.2.1 !((BaseAndOffset)v).def.isWellTyped()) 162 cananian 1.1.2.1 update(t.temp, s, 163 cananian 1.1.2.1 new BaseAndOffset(new TempDefPoint(t, s),0)); 164 cananian 1.1.2.1 else { 165 cananian 1.1.2.1 // if kgroup is unset, fill it now. 166 cananian 1.1.2.1 update(t.temp, s, v.fillKGroup(s, t.temp)); 167 cananian 1.1.2.1 } 168 cananian 1.1.2.1 } 169 cananian 1.1.2.1 } 170 cananian 1.1.2.1 } 171 cananian 1.1.2.1 /** visitor class to compute Values of expression trees. */ 172 cananian 1.1.2.1 private class ValueVisitor extends TreeVisitor { 173 cananian 1.1.2.1 final Stm root; 174 cananian 1.1.2.1 Value value; 175 cananian 1.1.2.1 ValueVisitor(Exp e, Stm root) { 176 cananian 1.1.2.1 this.root=root; 177 cananian 1.1.2.1 this.value= (e.type()==Type.INT || e.type()==Type.LONG) 178 cananian 1.1.2.1 ? Value.SOMEINT : Value.BOTTOM; 179 cananian 1.1.2.1 e.accept(this); 180 cananian 1.1.2.1 } 181 cananian 1.1.2.1 public void visit(Tree e) { assert false; } 182 cananian 1.1.2.1 public void visit(CONST c) { 183 cananian 1.1.2.1 if (c.type()==Type.INT || c.type()==Type.LONG) 184 cananian 1.1.2.1 this.value = new Constant(c.value().longValue()); 185 cananian 1.1.2.1 } 186 cananian 1.1.2.1 public void visit(ESEQ e) { 187 cananian 1.1.2.1 this.value=valueOf(e.getExp(), root); 188 cananian 1.1.2.1 } 189 cananian 1.1.2.1 public void visit(MEM e) { /* bottom */ } 190 cananian 1.1.2.1 public void visit(NAME e) { 191 cananian 1.1.2.1 this.value = new BaseAndOffset(new NameDefPoint(e), 0); 192 cananian 1.1.2.1 } 193 cananian 1.1.2.1 public void visit(BINOP e) { 194 cananian 1.1.2.1 if (e.op==Bop.ADD) { 195 cananian 1.1.2.1 Value left = valueOf(e.getLeft(), root); 196 cananian 1.1.2.1 Value right= valueOf(e.getRight(), root); 197 cananian 1.1.2.1 this.value = left.add(right); 198 cananian 1.1.2.1 } else if (e.op==Bop.MUL) { 199 cananian 1.1.2.1 Value left = valueOf(e.getLeft(), root); 200 cananian 1.1.2.1 Value right= valueOf(e.getRight(), root); 201 cananian 1.1.2.1 this.value = left.mul(right); 202 cananian 1.1.2.1 } else if (e.op==Bop.SHL) { 203 cananian 1.1.2.1 Value left = valueOf(e.getLeft(), root); 204 cananian 1.1.2.1 Value right= valueOf(e.getRight(), root); 205 cananian 1.1.2.1 Value mult = (right instanceof Constant) ? 206 cananian 1.1.2.1 new Constant(1<<((Constant)right).number) : 207 cananian 1.1.2.1 Value.SOMEINT; 208 cananian 1.1.2.1 this.value = left.mul(mult); 209 cananian 1.1.2.1 } 210 cananian 1.1.2.1 } 211 cananian 1.1.2.1 public void visit(UNOP e) { 212 cananian 1.1.2.1 if (e.op==Uop.NEG) { 213 cananian 1.1.2.1 Value op = valueOf(e.getOperand(), root); 214 cananian 1.1.2.1 this.value = op.negate(); 215 cananian 1.1.2.1 } 216 cananian 1.1.2.1 } 217 cananian 1.1.2.1 public void visit(TEMP t) { 218 cananian 1.1.2.1 this.value = valueUseAt(t.temp, root); 219 cananian 1.1.2.1 } 220 cananian 1.1.2.1 } 221 cananian 1.1.2.1 /* the value lattice: top/bottom, constants, and base pointers 222 cananian 1.1.2.1 * with known and unknown offsets, modulo a constant. */ 223 cananian 1.1.2.1 // op rules: most specific is 'this'. base ptrs more spec than consts. 224 cananian 1.1.2.1 public static abstract class Value { // bottom/noinfo. 225 cananian 1.1.2.1 abstract protected int specificity(); 226 cananian 1.1.2.2 public boolean isBaseKnown() { return false; } 227 cananian 1.1.2.2 public boolean isOffsetKnown() { return false; } 228 cananian 1.1.2.1 Value fillKGroup(Set defs, Temp t) { return this; } 229 cananian 1.1.2.1 final Value fillKGroup(Stm def, Temp t) { 230 cananian 1.1.2.1 return fillKGroup(Collections.singleton(def), t); 231 cananian 1.1.2.1 } 232 cananian 1.1.2.1 Value unify(Value v) { 233 cananian 1.1.2.1 assert this!=NOINFO; 234 cananian 1.1.2.1 if (v==NOINFO) return this; 235 cananian 1.1.2.1 return BOTTOM; 236 cananian 1.1.2.1 } 237 cananian 1.1.2.1 final Value add(Value v) { 238 cananian 1.1.2.1 return (this.specificity()>v.specificity()) ? 239 cananian 1.1.2.1 this._add(v) : v._add(this); 240 cananian 1.1.2.1 } 241 cananian 1.1.2.1 protected abstract Value _add(Value v); 242 cananian 1.1.2.1 final Value mul(Value v) { 243 cananian 1.1.2.1 return (this.specificity()>v.specificity()) ? 244 cananian 1.1.2.1 this._mul(v) : v._mul(this); 245 cananian 1.1.2.1 } 246 cananian 1.1.2.1 protected abstract Value _mul(Value v); 247 cananian 1.1.2.1 abstract Value negate(); 248 cananian 1.1.2.1 static final Value BOTTOM = new Value() { 249 cananian 1.1.2.1 protected int specificity() { return 0; } 250 cananian 1.1.2.1 protected Value _add(Value v) { return BOTTOM; } 251 cananian 1.1.2.1 protected Value _mul(Value v) { return BOTTOM; } 252 cananian 1.1.2.1 Value negate() { return BOTTOM; } 253 cananian 1.1.2.1 public String toString() { return "BOTTOM"; } 254 cananian 1.1.2.1 }; 255 cananian 1.1.2.1 static final Value SOMEINT = new IntegerValue(); 256 cananian 1.1.2.1 static final Value NOINFO = new Value() { 257 cananian 1.1.2.1 protected int specificity() { return 5; } 258 cananian 1.1.2.1 Value unify(Value v) { return v; } 259 cananian 1.1.2.1 protected Value _add(Value v) { return NOINFO; } 260 cananian 1.1.2.1 protected Value _mul(Value v) { return NOINFO; } 261 cananian 1.1.2.1 Value negate() { return NOINFO; } 262 cananian 1.1.2.1 public String toString() { return "NO INFO"; } 263 cananian 1.1.2.1 }; 264 cananian 1.1.2.1 } 265 cananian 1.1.2.1 public static class IntegerValue extends Value { 266 cananian 1.1.2.1 protected int specificity() { return 1; } 267 cananian 1.1.2.1 IntegerValue() { 268 cananian 1.1.2.1 assert this instanceof ConstantModuloN || 269 cananian 1.1.2.1 Value.SOMEINT==null; 270 cananian 1.1.2.1 } 271 cananian 1.1.2.1 Value unify(Value v) { 272 cananian 1.1.2.1 if (!(v instanceof IntegerValue)) return super.unify(v); 273 cananian 1.1.2.1 // IntegerValue is common superclass of this and v. 274 cananian 1.1.2.1 return Value.SOMEINT; 275 cananian 1.1.2.1 } 276 cananian 1.1.2.1 protected Value _add(Value v) { 277 cananian 1.1.2.1 // must handle v=BOTTOM, v=SOMEINT 278 cananian 1.1.2.1 if (v instanceof IntegerValue) return Value.SOMEINT; 279 cananian 1.1.2.1 return Value.BOTTOM; 280 cananian 1.1.2.1 } 281 cananian 1.1.2.1 protected Value _mul(Value v) { 282 cananian 1.1.2.1 // must handle v=BOTTOM, v=SOMEINT 283 cananian 1.1.2.1 if (v instanceof IntegerValue) return Value.SOMEINT; 284 cananian 1.1.2.1 return Value.BOTTOM; 285 cananian 1.1.2.1 } 286 cananian 1.1.2.1 Value negate() { return this; } 287 cananian 1.1.2.1 public String toString() { return "X"; } 288 cananian 1.1.2.1 } 289 cananian 1.1.2.1 public static class ConstantModuloN extends IntegerValue { 290 cananian 1.1.2.1 protected int specificity() { return 2; } 291 cananian 1.1.2.2 public final long number; public final long modulus; 292 cananian 1.1.2.2 public final KGroup kgroup; 293 cananian 1.1.2.1 ConstantModuloN(long number, long modulus, KGroup kgroup) { 294 cananian 1.1.2.1 this.number=number; this.modulus=modulus; this.kgroup=kgroup; 295 cananian 1.1.2.1 assert modulus>1; 296 cananian 1.1.2.1 assert kgroup!=null || (number>=0 && number<modulus); 297 cananian 1.1.2.1 } 298 cananian 1.1.2.1 protected ConstantModuloN(long number) { 299 cananian 1.1.2.1 assert this instanceof Constant; 300 cananian 1.1.2.1 this.number=number; this.modulus=0; this.kgroup=null; 301 cananian 1.1.2.1 } 302 cananian 1.1.2.2 public boolean isOffsetKnown() { return true; } 303 cananian 1.1.2.1 Value fillKGroup(Set defs, Temp t) { 304 cananian 1.1.2.1 if (kgroup!=null || this instanceof Constant) 305 cananian 1.1.2.1 return this; 306 cananian 1.1.2.1 return new ConstantModuloN(mymod(number, modulus),modulus, 307 cananian 1.1.2.1 new KGroup(defs, t)); 308 cananian 1.1.2.1 } 309 cananian 1.1.2.1 Value unify(Value v) { 310 cananian 1.1.2.1 if (!(v instanceof ConstantModuloN)) return super.unify(v); 311 cananian 1.1.2.1 // preserve k-group equality if this==v 312 cananian 1.1.2.1 if (this.equals(v)) return this; 313 cananian 1.1.2.1 // ConstantModuloN is common superclass of this and v. 314 cananian 1.1.2.1 ConstantModuloN large, small; 315 cananian 1.1.2.1 if (this.modulus > ((ConstantModuloN)v).modulus) { 316 cananian 1.1.2.1 large=this; small=(ConstantModuloN)v; 317 cananian 1.1.2.1 } else { 318 cananian 1.1.2.1 small=this; large=(ConstantModuloN)v; 319 cananian 1.1.2.1 } 320 cananian 1.1.2.1 assert large.modulus>0; 321 cananian 1.1.2.1 long off=0, mod=1; 322 cananian 1.1.2.1 if ((small.modulus==0 || small.modulus==large.modulus) && 323 cananian 1.1.2.1 mymod(small.number, large.modulus) == 324 cananian 1.1.2.1 mymod(large.number, large.modulus)) {//(a mod b) join c 325 cananian 1.1.2.1 off=large.number; mod=large.modulus; 326 cananian 1.1.2.1 } else if (small.modulus > 0) { // (a mod b) join (c mod d) 327 cananian 1.1.2.1 mod=Util.gcd(large.modulus, small.modulus); 328 cananian 1.1.2.1 if (large.number!=small.number) 329 cananian 1.1.2.1 mod=Util.gcd(mod, Math.abs(large.number-small.number)); 330 cananian 1.1.2.1 off=small.number; 331 cananian 1.1.2.1 } // others? 332 cananian 1.1.2.1 if (mod>1) 333 cananian 1.1.2.1 return new ConstantModuloN(mymod(off,mod), mod, null); 334 cananian 1.1.2.1 // can't unify the constants. 335 cananian 1.1.2.1 return Value.SOMEINT; 336 cananian 1.1.2.1 } 337 cananian 1.1.2.1 protected Value _add(Value v) { 338 cananian 1.1.2.1 // must handle v=BOTTOM, SOMEINT, CONSTANTMODULON, CONSTANT 339 cananian 1.1.2.1 // and this=CONSTANTMODULON, CONSTANT 340 cananian 1.1.2.1 if (v==Value.BOTTOM) return v; 341 cananian 1.1.2.1 if (v==Value.SOMEINT) return Value.SOMEINT; 342 cananian 1.1.2.1 ConstantModuloN large, small; 343 cananian 1.1.2.1 if (this.modulus > ((ConstantModuloN)v).modulus) { 344 cananian 1.1.2.1 large=this; small=(ConstantModuloN)v; 345 cananian 1.1.2.1 } else { 346 cananian 1.1.2.1 small=this; large=(ConstantModuloN)v; 347 cananian 1.1.2.1 } 348 cananian 1.1.2.1 if (small.modulus>0) {// (a mod b)+(c mod d) 349 cananian 1.1.2.1 if (large.kgroup==small.kgroup && large.kgroup!=null) 350 cananian 1.1.2.1 // (a+k*b)+(c+k*d) = (a+c)+k*(b+d) 351 cananian 1.1.2.1 return new ConstantModuloN 352 cananian 1.1.2.1 (large.number+small.number, 353 cananian 1.1.2.1 large.modulus+small.modulus, large.kgroup); 354 cananian 1.1.2.1 // (a mod b)+(c mod d)=(a+c) mod gcd(b, d) 355 cananian 1.1.2.1 long mod = Util.gcd(small.modulus, large.modulus); 356 cananian 1.1.2.1 if (mod>1) 357 cananian 1.1.2.1 return new ConstantModuloN 358 cananian 1.1.2.1 (mymod(large.number+small.number,mod), mod, null); 359 cananian 1.1.2.1 } else if (large.modulus>0) { // (a mod b)+c 360 cananian 1.1.2.1 long off=large.number+small.number; 361 cananian 1.1.2.1 if (large.kgroup==null) off=mymod(off, large.modulus); 362 cananian 1.1.2.1 return new ConstantModuloN(off, large.modulus, 363 cananian 1.1.2.1 large.kgroup); 364 cananian 1.1.2.1 } else return new Constant(large.number+small.number); 365 cananian 1.1.2.1 return Value.SOMEINT; 366 cananian 1.1.2.1 } 367 cananian 1.1.2.1 protected Value _mul(Value v) { 368 cananian 1.1.2.1 // handles v=BOTTOM, v=SOMEINT, v=CONSTANTMODULON 369 cananian 1.1.2.1 if (v==Value.BOTTOM) return v; 370 cananian 1.1.2.1 if (v==Value.SOMEINT) { 371 cananian 1.1.2.1 // SOMEINT*(0 mod b) = 0 mod b 372 cananian 1.1.2.1 // SOMEINT*(a mod b) = 0 mod gcd(a,b) 373 cananian 1.1.2.1 if (this.number==0) 374 cananian 1.1.2.1 return new ConstantModuloN(0, this.modulus, null); 375 cananian 1.1.2.1 long mod = Util.gcd(this.number, this.modulus); 376 cananian 1.1.2.1 if (mod>1) 377 cananian 1.1.2.1 return new ConstantModuloN(0, mod, null); 378 cananian 1.1.2.1 return Value.SOMEINT; 379 cananian 1.1.2.1 } 380 cananian 1.1.2.1 ConstantModuloN cmn = (ConstantModuloN) v; 381 cananian 1.1.2.1 // (a mod b) * (c mod d) = (ac) mod gdb(b, d) 382 cananian 1.1.2.1 assert cmn.modulus>1 && this.modulus>1; 383 cananian 1.1.2.1 long mod = Util.gcd(this.modulus, cmn.modulus); 384 cananian 1.1.2.1 if (mod>1) 385 cananian 1.1.2.1 return new ConstantModuloN 386 cananian 1.1.2.1 (mymod(this.number*cmn.number,mod), mod, null); 387 cananian 1.1.2.1 else return Value.SOMEINT; 388 cananian 1.1.2.1 } 389 cananian 1.1.2.1 Value negate() { 390 cananian 1.1.2.1 return new ConstantModuloN(mymod(modulus-number,modulus), 391 cananian 1.1.2.1 modulus, null/*k'=-k*/); 392 cananian 1.1.2.1 } 393 cananian 1.1.2.1 public boolean equals(Object o) { 394 cananian 1.1.2.1 if (!(o instanceof ConstantModuloN)) return false; 395 cananian 1.1.2.1 ConstantModuloN cmn = (ConstantModuloN) o; 396 cananian 1.1.2.1 return (this.kgroup==null ? cmn.kgroup==null : 397 cananian 1.1.2.1 (cmn.kgroup!=null && 398 cananian 1.1.2.1 this.kgroup.equals(cmn.kgroup))) && 399 cananian 1.1.2.1 this.number == cmn.number && 400 cananian 1.1.2.1 this.modulus == cmn.modulus; 401 cananian 1.1.2.1 } 402 cananian 1.1.2.1 public int hashCode() { return (int)number + 7*(int)modulus; } 403 cananian 1.1.2.1 public String toString() { 404 cananian 1.1.2.1 return number+((modulus==0)?"":(" mod "+modulus+" k:"+kgroup)); 405 cananian 1.1.2.1 } 406 cananian 1.1.2.1 } 407 cananian 1.1.2.1 public static class Constant extends ConstantModuloN { 408 cananian 1.1.2.1 protected int specificity() { return 3; } 409 cananian 1.1.2.1 Constant(long number) { super(number); } 410 cananian 1.1.2.1 Value unify(Value v) { 411 cananian 1.1.2.1 if (!(v instanceof Constant)) return super.unify(v); 412 cananian 1.1.2.1 // Constant is common superclass of this and v. 413 cananian 1.1.2.1 Constant c = (Constant) v; 414 cananian 1.1.2.1 if (this.number==c.number) 415 cananian 1.1.2.1 return new Constant(this.number); 416 cananian 1.1.2.1 long small=Math.min(this.number, c.number); 417 cananian 1.1.2.1 long large=Math.max(this.number, c.number); 418 cananian 1.1.2.1 long mod=(large-small); 419 cananian 1.1.2.1 assert mymod(small, mod)==mymod(large, mod); 420 cananian 1.1.2.1 if (mod>1) 421 cananian 1.1.2.1 return new ConstantModuloN(mymod(small, mod), mod, null); 422 cananian 1.1.2.1 return Value.SOMEINT; 423 cananian 1.1.2.1 } 424 cananian 1.1.2.1 protected Value _mul(Value v) { 425 cananian 1.1.2.1 // must handle BOTTOM, SOMEINT, CONSTANTMODULON, CONSTANT 426 cananian 1.1.2.1 if (v==Value.BOTTOM) return v; 427 cananian 1.1.2.1 if (v==Value.SOMEINT) { 428 cananian 1.1.2.1 // SOMEINT * c = 0 mod c 429 cananian 1.1.2.1 if (this.number>1) 430 cananian 1.1.2.1 return new ConstantModuloN(0, this.number, null); 431 cananian 1.1.2.1 if (this.number<-1) 432 cananian 1.1.2.1 return new ConstantModuloN(0, -this.number, null) 433 cananian 1.1.2.1 .negate(); 434 cananian 1.1.2.1 return Value.SOMEINT; 435 cananian 1.1.2.1 } 436 cananian 1.1.2.1 ConstantModuloN cmn = (ConstantModuloN) v; 437 cananian 1.1.2.1 if (cmn.modulus>1) { 438 cananian 1.1.2.1 long mult = Math.abs(this.number); 439 cananian 1.1.2.1 Value r = new ConstantModuloN(cmn.number*mult, 440 cananian 1.1.2.1 cmn.modulus*mult, 441 cananian 1.1.2.1 cmn.kgroup); 442 cananian 1.1.2.1 return (this.number>=0) ? r : r.negate(); 443 cananian 1.1.2.1 } 444 cananian 1.1.2.1 assert cmn.modulus==0 && this.modulus==0; 445 cananian 1.1.2.1 return new Constant(cmn.number * this.number); 446 cananian 1.1.2.1 } 447 cananian 1.1.2.1 Value negate() { return new Constant(-this.number); } 448 cananian 1.1.2.1 } 449 cananian 1.1.2.1 public static class BaseAndOffset extends Value { 450 cananian 1.1.2.1 protected int specificity() { return 4; } 451 cananian 1.1.2.2 public final DefPoint def; 452 cananian 1.1.2.2 public final IntegerValue offset; 453 cananian 1.1.2.1 BaseAndOffset(DefPoint def, IntegerValue offset) { 454 cananian 1.1.2.1 this.def = def; this.offset = offset; 455 cananian 1.1.2.1 } 456 cananian 1.1.2.1 // special case: 457 cananian 1.1.2.1 BaseAndOffset(DefPoint def, long offset) { 458 cananian 1.1.2.1 this(def, new Constant(offset)); 459 cananian 1.1.2.1 } 460 cananian 1.1.2.2 public boolean isBaseKnown() { return true; } 461 cananian 1.1.2.2 public boolean isOffsetKnown() { return offset.isOffsetKnown(); } 462 cananian 1.1.2.1 Value fillKGroup(Set defs, Temp t) { 463 cananian 1.1.2.1 return new BaseAndOffset(def, (IntegerValue) 464 cananian 1.1.2.1 offset.fillKGroup(defs, t)); 465 cananian 1.1.2.1 } 466 cananian 1.1.2.1 Value unify(Value v) { 467 cananian 1.1.2.1 if (!(v instanceof BaseAndOffset)) return super.unify(v); 468 cananian 1.1.2.1 // BaseAndOffset is common superclass of this and v 469 cananian 1.1.2.1 BaseAndOffset ko = (BaseAndOffset) v; 470 cananian 1.1.2.1 if (this.def.equals(ko.def)) { 471 cananian 1.1.2.1 Value cc = this.offset.unify(ko.offset); 472 cananian 1.1.2.1 if (cc instanceof IntegerValue) 473 cananian 1.1.2.1 return new BaseAndOffset(def, (IntegerValue) cc); 474 cananian 1.1.2.1 } 475 cananian 1.1.2.1 return Value.BOTTOM; 476 cananian 1.1.2.1 } 477 cananian 1.1.2.1 protected Value _add(Value v) { 478 cananian 1.1.2.1 // must handle BOTTOM, SOMEINT, CMN, C, BAO 479 cananian 1.1.2.1 if (!(v instanceof IntegerValue)) return Value.BOTTOM; 480 cananian 1.1.2.1 Value cc = this.offset.add(v); 481 cananian 1.1.2.1 assert cc instanceof IntegerValue; 482 cananian 1.1.2.1 return new BaseAndOffset(def, (IntegerValue) cc); 483 cananian 1.1.2.1 } 484 cananian 1.1.2.1 protected Value _mul(Value v) { 485 cananian 1.1.2.1 // must handle BOTTOM, SOMEINT, CMN, C, BAO. 486 cananian 1.1.2.1 return Value.BOTTOM; 487 cananian 1.1.2.1 } 488 cananian 1.1.2.1 Value negate() { return Value.BOTTOM; } 489 cananian 1.1.2.1 public boolean equals(Object o) { 490 cananian 1.1.2.1 if (!(o instanceof BaseAndOffset)) return false; 491 cananian 1.1.2.1 BaseAndOffset bao = (BaseAndOffset) o; 492 cananian 1.1.2.1 return this.def.equals(bao.def) && 493 cananian 1.1.2.1 this.offset.equals(bao.offset); 494 cananian 1.1.2.1 } 495 cananian 1.1.2.1 public int hashCode() { 496 cananian 1.1.2.1 return def.hashCode()+7*offset.hashCode(); 497 cananian 1.1.2.1 } 498 cananian 1.1.2.1 public String toString() { return def+"+"+offset; } 499 cananian 1.1.2.1 } 500 cananian 1.1.2.1 // utility function 501 cananian 1.1.2.1 /** returns the positive value of a mod b, even when a is negative. */ 502 cananian 1.1.2.1 private static long mymod(long a, long b) { 503 cananian 1.1.2.1 assert b>0; 504 cananian 1.1.2.1 long r = a % b; 505 cananian 1.1.2.1 return (r<0) ? (b+r) : r; 506 cananian 1.1.2.1 } 507 cananian 1.1.2.1 /*------------------------------------------------------------- */ 508 cananian 1.1.2.1 /* both pointers in temps and pointer constants can be def points */ 509 cananian 1.1.2.1 public abstract class DefPoint { 510 cananian 1.1.2.2 public abstract HClass type(); 511 cananian 1.1.2.2 public final boolean isWellTyped() { 512 cananian 1.1.2.1 HClass hc=type(); 513 cananian 1.1.2.1 return hc!=null && !hc.isPrimitive(); 514 cananian 1.1.2.1 } 515 cananian 1.1.2.1 } 516 cananian 1.1.2.1 public class TempDefPoint extends DefPoint { 517 cananian 1.1.2.2 public final TEMP base; public final Stm def; 518 cananian 1.1.2.1 TempDefPoint(TEMP base, Stm def) { this.base=base; this.def=def; } 519 cananian 1.1.2.2 public HClass type() { return td.typeMap(base); } 520 cananian 1.1.2.1 public boolean equals(Object o) { 521 cananian 1.1.2.1 return o instanceof TempDefPoint && 522 cananian 1.1.2.1 base.temp.equals(((TempDefPoint)o).base.temp) && 523 cananian 1.1.2.1 def.equals(((TempDefPoint)o).def); 524 cananian 1.1.2.1 } 525 cananian 1.1.2.1 public int hashCode() { 526 cananian 1.1.2.1 return base.temp.hashCode() ^ def.hashCode(); 527 cananian 1.1.2.1 } 528 cananian 1.1.2.1 public String toString() { return base.temp.toString(); } 529 cananian 1.1.2.1 } 530 cananian 1.1.2.1 public class NameDefPoint extends DefPoint { 531 cananian 1.1.2.2 public final NAME name; 532 cananian 1.1.2.1 NameDefPoint(NAME name) { this.name = name; } 533 cananian 1.1.2.1 public boolean equals(Object o) { 534 cananian 1.1.2.1 return o instanceof NameDefPoint && 535 cananian 1.1.2.1 name.label.equals(((NameDefPoint)o).name.label); 536 cananian 1.1.2.1 } 537 cananian 1.1.2.2 public HClass type() { return td.typeMap(name); } 538 cananian 1.1.2.1 public int hashCode() { return name.label.hashCode(); } 539 cananian 1.1.2.1 public String toString() { return name.label.toString(); } 540 cananian 1.1.2.1 } 541 cananian 1.1.2.1 542 cananian 1.1.2.1 /** a k-group is a "phi-function" definition point. */ 543 cananian 1.1.2.1 public static class KGroup { 544 cananian 1.1.2.1 final Set defs; final Temp t; 545 cananian 1.1.2.1 KGroup(Set defs, Temp t) { this.defs=defs; this.t=t; } 546 cananian 1.1.2.1 public String toString() { return "<"+t+","+defs+">"; } 547 cananian 1.1.2.1 public boolean equals(Object o) { 548 cananian 1.1.2.1 if (!(o instanceof KGroup)) return false; 549 cananian 1.1.2.1 KGroup kg = (KGroup) o; 550 cananian 1.1.2.1 return this.t.equals(kg.t) && this.defs.equals(kg.defs); 551 cananian 1.1.2.1 } 552 cananian 1.1.2.1 public int hashCode() { return t.hashCode() + 11*defs.hashCode(); } 553 cananian 1.1.2.1 } 554 cananian 1.2 }