1 cananian 1.1.2.1 // CommutativityExpander.java, created Thu Feb 17 15:42:30 2000 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1999 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.Tools.PatMat; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 /** 7 cananian 1.1.2.1 * The <code>CommutativityExpander</code> tool expands a set of 8 cananian 1.1.2.1 * <code>Spec.Rules</code> to include add'l valid patterns 9 cananian 1.1.2.1 * generated from the commutative properties of various 10 cananian 1.1.2.1 * <code>Spec.ExpBinop</code>s. 11 cananian 1.1.2.1 * 12 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 13 cananian 1.2 * @version $Id: CommutativityExpander.java,v 1.2 2002/02/25 21:08:30 cananian Exp $ 14 cananian 1.1.2.1 */ 15 cananian 1.1.2.1 public abstract class CommutativityExpander { 16 cananian 1.1.2.1 //hide constructor. 17 cananian 1.1.2.1 private CommutativityExpander() { } 18 cananian 1.1.2.5 // prefix for generated private members 19 cananian 1.1.2.5 private final static String prefix="__CommExp__"; 20 cananian 1.1.2.5 21 cananian 1.1.2.5 // two functions needed both here and in the generated code. 22 cananian 1.1.2.5 private final static String isCommFunc = 23 cananian 1.1.2.5 "private static boolean "+prefix+"isCommutative(int op) {\n"+ 24 cananian 1.1.2.5 "\tswitch(op) {\n"+ 25 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPGT:\n"+ 26 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPGE:\n"+ 27 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPLE:\n"+ 28 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPLT: return true; \n"+ 29 cananian 1.1.2.5 "\tdefault: return harpoon.IR.Tree.Bop.isCommutative(op);\n"+ 30 cananian 1.1.2.5 "\t}\n"+ 31 cananian 1.1.2.5 "}\n"; 32 cananian 1.1.2.5 private static boolean isCommutative(int op) { 33 cananian 1.1.2.5 switch(op) { 34 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPGT: 35 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPGE: 36 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPLE: 37 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPLT: return true; 38 cananian 1.1.2.5 default: return harpoon.IR.Tree.Bop.isCommutative(op); 39 cananian 1.1.2.5 } 40 cananian 1.1.2.5 } 41 cananian 1.1.2.5 private final static String swapCmpOpFunc = 42 cananian 1.1.2.5 "private static int "+prefix+"swapCmpOp(int op) {\n"+ 43 cananian 1.1.2.5 "\tswitch(op) {\n"+ 44 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPGT:return harpoon.IR.Tree.Bop.CMPLT;\n"+ 45 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPGE:return harpoon.IR.Tree.Bop.CMPLE;\n"+ 46 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPLE:return harpoon.IR.Tree.Bop.CMPGE;\n"+ 47 cananian 1.1.2.5 "\tcase harpoon.IR.Tree.Bop.CMPLT:return harpoon.IR.Tree.Bop.CMPGT;\n"+ 48 cananian 1.1.2.5 "\tdefault: return op;\n"+ 49 cananian 1.1.2.5 "\t}\n"+ 50 cananian 1.1.2.5 "}\n"; 51 cananian 1.1.2.5 private static int swapCmpOp(int op) { 52 cananian 1.1.2.5 switch(op) { 53 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPGT:return harpoon.IR.Tree.Bop.CMPLT; 54 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPGE:return harpoon.IR.Tree.Bop.CMPLE; 55 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPLE:return harpoon.IR.Tree.Bop.CMPGE; 56 cananian 1.1.2.5 case harpoon.IR.Tree.Bop.CMPLT:return harpoon.IR.Tree.Bop.CMPGT; 57 cananian 1.1.2.5 default: return op; 58 cananian 1.1.2.5 } 59 cananian 1.1.2.5 } 60 cananian 1.1.2.1 61 cananian 1.1.2.5 // this is the actual expansion function. 62 cananian 1.1.2.1 public static Spec expand(Spec s) { 63 cananian 1.1.2.5 return new Spec(s.global_stms, 64 cananian 1.1.2.5 s.class_stms +"\n"+ isCommFunc + swapCmpOpFunc +"\n", 65 cananian 1.1.2.1 s.method_prologue_stms, s.method_epilogue_stms, 66 cananian 1.1.2.1 expand(s.rules)); 67 cananian 1.1.2.1 } 68 cananian 1.1.2.1 private static Spec.RuleList expand(Spec.RuleList rl) { 69 cananian 1.1.2.1 if (rl==null) return null; 70 cananian 1.1.2.1 Spec.RuleList result = expand(rl.tail); 71 cananian 1.1.2.1 Spec.Rule[] ra = expand(rl.head); 72 cananian 1.1.2.1 for (int i=0; i<ra.length; i++) 73 cananian 1.1.2.1 result = new Spec.RuleList(ra[i], result); 74 cananian 1.1.2.1 return result; 75 cananian 1.1.2.1 } 76 cananian 1.1.2.1 private static Spec.Rule[] expand(Spec.Rule r) { 77 cananian 1.1.2.1 if (r instanceof Spec.RuleExp) 78 cananian 1.1.2.1 return expand((Spec.RuleExp) r); 79 cananian 1.1.2.1 if (r instanceof Spec.RuleStm) 80 cananian 1.1.2.1 return expand((Spec.RuleStm) r); 81 cananian 1.1.2.1 throw new Error("Unknown Spec.Rule type!"); 82 cananian 1.1.2.1 } 83 cananian 1.1.2.1 private static Spec.RuleExp[] expand(Spec.RuleExp r) { 84 cananian 1.1.2.2 ExpAndPred[] choices = expand(r.exp); 85 cananian 1.1.2.1 Spec.RuleExp[] result = new Spec.RuleExp[choices.length]; 86 cananian 1.1.2.1 for (int i=0; i<result.length; i++) 87 cananian 1.1.2.2 result[i] = new Spec.RuleExp(choices[i].exp, r.result_id, 88 cananian 1.1.2.2 addPred(r.details, choices[i].pred), 89 cananian 1.1.2.2 r.action_str); 90 cananian 1.1.2.1 return result; 91 cananian 1.1.2.1 } 92 cananian 1.1.2.1 private static Spec.RuleStm[] expand(Spec.RuleStm r) { 93 cananian 1.1.2.2 StmAndPred[] choices = expand(r.stm); 94 cananian 1.1.2.1 Spec.RuleStm[] result = new Spec.RuleStm[choices.length]; 95 cananian 1.1.2.1 for (int i=0; i<result.length; i++) 96 cananian 1.1.2.2 result[i] = new Spec.RuleStm(choices[i].stm, 97 cananian 1.1.2.2 addPred(r.details, choices[i].pred), 98 cananian 1.1.2.2 r.action_str); 99 cananian 1.1.2.1 return result; 100 cananian 1.1.2.1 } 101 cananian 1.1.2.2 private static ExpAndPred[] dispatch(Spec.Exp exp) { 102 cananian 1.1.2.1 if (exp instanceof Spec.ExpBinop) 103 cananian 1.1.2.1 return expand((Spec.ExpBinop)exp); 104 cananian 1.1.2.1 else return expand(exp); 105 cananian 1.1.2.1 } 106 cananian 1.1.2.1 // this is the real deal: 107 cananian 1.1.2.2 private static ExpAndPred[] expand(Spec.ExpBinop exp) { 108 cananian 1.1.2.1 // make normal combinations first. 109 cananian 1.1.2.2 ExpListAndPred[] combos = makeAllCombinations(exp.kids()); 110 cananian 1.1.2.1 // check whether this exp rules is commutative & worth expanding. 111 cananian 1.1.2.3 if ( // first off, one of left/right has to be non-id 112 cananian 1.1.2.3 !(exp.left instanceof Spec.ExpId&&exp.right instanceof Spec.ExpId) 113 cananian 1.1.2.3 && // also, if op is a leafop, it needs to be a commutative one. 114 cananian 1.1.2.3 (exp.opcode instanceof Spec.LeafId || 115 cananian 1.1.2.3 (exp.opcode instanceof Spec.LeafOp && 116 cananian 1.1.2.5 isCommutative(((Spec.LeafOp) exp.opcode).op)) 117 cananian 1.1.2.3 )) { 118 cananian 1.1.2.5 // check to see if an extra predicate/new leaf is needed. 119 cananian 1.1.2.5 Spec.Leaf l = exp.opcode; String extrapred=null; 120 cananian 1.1.2.5 if (exp.opcode instanceof Spec.LeafOp) { 121 cananian 1.1.2.5 l = new Spec.LeafOp(swapCmpOp(((Spec.LeafOp)exp.opcode).op)); 122 cananian 1.1.2.5 } else { 123 cananian 1.1.2.5 String id = ((Spec.LeafId) exp.opcode).id; 124 cananian 1.1.2.5 extrapred = prefix+"isCommutative("+ 125 cananian 1.1.2.5 id+"="+prefix+"swapCmpOp("+id+"))"; 126 cananian 1.1.2.5 } 127 cananian 1.1.2.1 // okay, reverse kids and make some more combos. 128 cananian 1.1.2.5 ExpAndPred[] result = new ExpAndPred[combos.length * 2]; 129 cananian 1.1.2.1 for (int i=0; i<combos.length; i++) { 130 cananian 1.1.2.5 result[2*i] = new ExpAndPred(exp.build(combos[i].explist), 131 cananian 1.1.2.5 combos[i].pred); 132 cananian 1.1.2.5 // reverse args, swap op, add pred. 133 cananian 1.1.2.5 Spec.ExpBinop binop = 134 cananian 1.1.2.5 new Spec.ExpBinop((Spec.TypeSet)exp.types.clone(), l, 135 cananian 1.1.2.5 combos[i].explist.tail.head, 136 cananian 1.1.2.5 combos[i].explist.head); 137 cananian 1.1.2.5 result[2*i+1] = 138 cananian 1.1.2.5 new ExpAndPred(binop, addPred(extrapred, combos[i].pred)); 139 cananian 1.1.2.1 } 140 cananian 1.1.2.5 return result; 141 cananian 1.1.2.1 } 142 cananian 1.1.2.1 // make exps from all the explists. 143 cananian 1.1.2.2 ExpAndPred[] result = new ExpAndPred[combos.length]; 144 cananian 1.1.2.1 for (int i=0; i<result.length; i++) 145 cananian 1.1.2.2 result[i] = new ExpAndPred(exp.build(combos[i].explist), 146 cananian 1.1.2.2 combos[i].pred); 147 cananian 1.1.2.1 return result; 148 cananian 1.1.2.1 } 149 cananian 1.1.2.2 private static ExpAndPred[] expand(Spec.Exp exp) { 150 cananian 1.1.2.1 // make explists with all combinations of children. 151 cananian 1.1.2.2 ExpListAndPred[] combos = makeAllCombinations(exp.kids()); 152 cananian 1.1.2.1 // make exps from all the explists. 153 cananian 1.1.2.2 ExpAndPred[] result = new ExpAndPred[combos.length]; 154 cananian 1.1.2.1 for (int i=0; i<result.length; i++) 155 cananian 1.1.2.2 result[i] = new ExpAndPred(exp.build(combos[i].explist), 156 cananian 1.1.2.2 combos[i].pred); 157 cananian 1.1.2.1 return result; 158 cananian 1.1.2.1 } 159 cananian 1.1.2.2 private static StmAndPred[] expand(Spec.Stm stm) { 160 cananian 1.1.2.1 // make explists with all combinations of children. 161 cananian 1.1.2.2 ExpListAndPred[] combos = makeAllCombinations(stm.kids()); 162 cananian 1.1.2.1 // make exps from all the explists. 163 cananian 1.1.2.2 StmAndPred[] result = new StmAndPred[combos.length]; 164 cananian 1.1.2.1 for (int i=0; i<result.length; i++) 165 cananian 1.1.2.2 result[i] = new StmAndPred(stm.build(combos[i].explist), 166 cananian 1.1.2.2 combos[i].pred); 167 cananian 1.1.2.1 return result; 168 cananian 1.1.2.1 } 169 cananian 1.1.2.1 private static int size(Spec.ExpList el) { 170 cananian 1.1.2.1 int i; 171 cananian 1.1.2.1 for (i=0; el!=null; el=el.tail) 172 cananian 1.1.2.1 i++; 173 cananian 1.1.2.1 return i; 174 cananian 1.1.2.1 } 175 cananian 1.1.2.2 private static ExpListAndPred[] makeAllCombinations(Spec.ExpList kids) { 176 cananian 1.1.2.1 // construct set of expanded children. 177 cananian 1.1.2.2 ExpAndPred[][] choices = new ExpAndPred[size(kids)][]; 178 cananian 1.1.2.1 for (int i=0; kids!=null; kids=kids.tail) 179 cananian 1.1.2.1 choices[i++] = dispatch(kids.head); 180 cananian 1.1.2.1 // make explists with all combinations of children. 181 cananian 1.1.2.1 return makeAllCombinations(choices); 182 cananian 1.1.2.1 } 183 cananian 1.1.2.2 private static ExpListAndPred[] makeAllCombinations(ExpAndPred[][] choices) 184 cananian 1.1.2.2 { 185 cananian 1.1.2.1 int[] state = new int[choices.length]; // all zero initially. 186 cananian 1.1.2.1 // count the # of possibilities 187 cananian 1.1.2.1 int numposs = 1; 188 cananian 1.1.2.1 for (int i=0; i<choices.length; i++) 189 cananian 1.1.2.1 numposs *= choices[i].length; 190 cananian 1.1.2.1 // iterate: 191 cananian 1.1.2.2 ExpListAndPred[] result = new ExpListAndPred[numposs]; 192 cananian 1.1.2.1 for (int i=0; i < numposs; i++) { 193 cananian 1.1.2.1 // make a Spec.ExpList 194 cananian 1.1.2.2 Spec.ExpList el=null; String pred=null; 195 cananian 1.1.2.2 for (int j=state.length-1; j>=0; j--) { 196 cananian 1.1.2.2 ExpAndPred eap = choices[j][state[j]]; 197 cananian 1.1.2.2 pred = addPred(eap.pred, pred); 198 cananian 1.1.2.2 el = new Spec.ExpList( eap.exp, el ); 199 cananian 1.1.2.2 } 200 cananian 1.1.2.1 // add to result. 201 cananian 1.1.2.2 result[i] = new ExpListAndPred(el, pred); 202 cananian 1.1.2.1 // advance state by one 203 cananian 1.1.2.1 for (int j=0; j < state.length; j++) { 204 cananian 1.1.2.1 if (++state[j] < choices[j].length) 205 cananian 1.1.2.1 break; 206 cananian 1.1.2.1 else state[j] = 0; 207 cananian 1.1.2.1 } 208 cananian 1.1.2.1 } 209 cananian 1.1.2.1 return result; 210 cananian 1.1.2.2 } 211 cananian 1.1.2.2 private static class ExpAndPred { 212 cananian 1.1.2.2 final Spec.Exp exp; 213 cananian 1.1.2.2 final String pred; 214 cananian 1.1.2.2 ExpAndPred(Spec.Exp exp, String pred) { 215 cananian 1.1.2.2 this.exp = exp; this.pred = pred; 216 cananian 1.1.2.2 } 217 cananian 1.1.2.2 } 218 cananian 1.1.2.2 private static class ExpListAndPred { 219 cananian 1.1.2.2 final Spec.ExpList explist; 220 cananian 1.1.2.2 final String pred; 221 cananian 1.1.2.2 ExpListAndPred(Spec.ExpList explist, String pred) { 222 cananian 1.1.2.2 this.explist = explist; this.pred = pred; 223 cananian 1.1.2.2 } 224 cananian 1.1.2.2 } 225 cananian 1.1.2.2 private static class StmAndPred { 226 cananian 1.1.2.2 final Spec.Stm stm; 227 cananian 1.1.2.2 final String pred; 228 cananian 1.1.2.2 StmAndPred(Spec.Stm stm, String pred) { 229 cananian 1.1.2.2 this.stm = stm; this.pred = pred; 230 cananian 1.1.2.2 } 231 cananian 1.1.2.2 } 232 cananian 1.1.2.2 private static String addPred(String p1, String p2) { 233 cananian 1.1.2.2 if (p1==null) return p2; 234 cananian 1.1.2.2 if (p2==null) return p1; 235 cananian 1.1.2.2 return "("+p1+") && ("+p2+")"; 236 cananian 1.1.2.2 } 237 cananian 1.1.2.2 private static Spec.DetailList addPred(Spec.DetailList dl, String pred) { 238 cananian 1.1.2.3 if (pred==null) 239 cananian 1.1.2.3 return dl; 240 cananian 1.1.2.2 if (dl==null) 241 cananian 1.1.2.2 return new Spec.DetailList(new Spec.DetailPredicate(pred), null); 242 cananian 1.1.2.2 if (dl.head instanceof Spec.DetailPredicate) { 243 cananian 1.1.2.2 Spec.DetailPredicate sdp = (Spec.DetailPredicate) dl.head; 244 cananian 1.1.2.2 return new Spec.DetailList(new Spec.DetailPredicate 245 cananian 1.1.2.5 (addPred(pred, sdp.predicate_string)), 246 cananian 1.1.2.5 dl.tail); 247 cananian 1.1.2.2 } 248 cananian 1.1.2.2 else return new Spec.DetailList(dl.head, addPred(dl.tail, pred)); 249 cananian 1.1.2.1 } 250 cananian 1.2 }