4e9d3d673a05beb4688668bfa0519ee48c129d9a
[IRC.git] / Robust / src / Analysis / Locality / GenerateConversions.java
1 package Analysis.Locality;
2 import IR.State;
3 import IR.Flat.*;
4 import java.util.*;
5 import IR.MethodDescriptor;
6
7
8 public class GenerateConversions {
9   LocalityAnalysis locality;
10   State state;
11
12   /** Warning: This class modifies the code in place.  */
13
14   public GenerateConversions(LocalityAnalysis la, State state) {
15     locality=la;
16     this.state=state;
17     doConversion();
18   }
19
20   private void doConversion() {
21     Set<LocalityBinding> bindings=locality.getLocalityBindings();
22     Iterator<LocalityBinding> bindit=bindings.iterator();
23     while(bindit.hasNext()) {
24       LocalityBinding lb=bindit.next();
25       //Don't need to do conversion if it is already atomic
26       if (lb.isAtomic())
27         continue;
28       converttoPtr(lb);
29       converttoOid(lb);
30     }
31   }
32
33   /* At the end of an atomic block, we need to convert any global
34    * references that will be used again into OID's. */
35
36   private void converttoOid(LocalityBinding lb) {
37     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
38     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
39     MethodDescriptor md=lb.getMethod();
40     FlatMethod fm=state.getMethodFlat(md);
41     Hashtable<FlatNode, Set<TempNodePair>> nodetotnpair=new Hashtable<FlatNode, Set<TempNodePair>>();
42     Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs=new Hashtable<FlatNode, Set<TempDescriptor>>();
43     Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs2=new Hashtable<FlatNode, Set<TempDescriptor>>();
44
45     Set<FlatNode> toprocess=fm.getNodeSet();
46
47     while(!toprocess.isEmpty()) {
48       FlatNode fn=toprocess.iterator().next();
49       toprocess.remove(fn);
50       boolean isatomic=atomictab.get(fn).intValue()>0;
51
52       Hashtable<TempDescriptor, Integer> nodetemptab=state.DSM?temptab.get(fn):null;
53
54       List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
55       List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
56
57       if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
58           &&!nodetoconvs.containsKey(fn)) {
59         nodetoconvs.put(fn, new HashSet<TempDescriptor>());
60         nodetoconvs2.put(fn, new HashSet<TempDescriptor>());
61       }
62
63       HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
64
65       for(int i=0; i<fn.numPrev(); i++) {
66         FlatNode fnprev=fn.getPrev(i);
67         if (!nodetotnpair.containsKey(fnprev))
68           continue;
69
70         Set<TempNodePair> prevset=nodetotnpair.get(fnprev);
71         for(Iterator<TempNodePair> it=prevset.iterator(); it.hasNext();) {
72           TempNodePair tnp=it.next();
73           if (fn.kind()==FKind.FlatGlobalConvNode&&
74               ((FlatGlobalConvNode)fn).getLocality()!=lb) {
75             //ignore this node
76             tempset.add(tnp);
77             continue;
78           }
79           if (reads.contains(tnp.getTemp())&&tnp.getNode()!=null) {
80             //Value actually is read...
81             nodetoconvs.get(tnp.getNode()).add(tnp.getTemp());
82           }
83
84           if (writes.contains(tnp.getTemp()))           //value overwritten
85             continue;
86           if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode) {
87             //Create new node and tag it with this exit
88             if (tnp.getNode()==null) {
89               TempNodePair tnp2=new TempNodePair(tnp.getTemp());
90               tnp2.setNode(fn);
91               tempset.add(tnp2);
92               nodetoconvs2.get(fn).add(tnp.getTemp());  //have to hide cached copies from gc
93             } else
94               tempset.add(tnp);
95           } else
96             tempset.add(tnp);
97         }
98       }
99       if (isatomic) {
100         /* If this is in an atomic block, record temps that
101          * are written to.*/
102
103         /* NOTE: If this compiler is changed to maintain
104          * OID/Ptr's in variables, then we need to use all
105          * global temps that could be read and not just the
106          * ones converted by globalconvnode*/
107
108         if (fn.kind()!=FKind.FlatGlobalConvNode||
109             ((FlatGlobalConvNode)fn).getLocality()==lb) {
110           /*If globalconvnode, make sure we have the right
111            * locality. */
112           for(Iterator<TempDescriptor> writeit=writes.iterator(); writeit.hasNext();) {
113             TempDescriptor wrtmp=writeit.next();
114             if (state.SINGLETM) {
115               if (wrtmp.getType().isPtr()) {
116                 TempNodePair tnp=new TempNodePair(wrtmp);
117                 tempset.add(tnp);
118               }
119             } else if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
120               TempNodePair tnp=new TempNodePair(wrtmp);
121               tempset.add(tnp);
122             }
123           }
124         }
125       }
126       if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
127         //changes to set, so enqueue next nodes
128         nodetotnpair.put(fn, tempset);         //update set
129         for(int i=0; i<fn.numNext(); i++) {
130           toprocess.add(fn.getNext(i));
131         }
132       }
133     }
134     //Place Convert to Oid nodes
135     toprocess=fm.getNodeSet();
136     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
137       FlatNode fn=it.next();
138       if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
139           atomictab.get(fn.getPrev(0)).intValue()>0) {
140         //sanity check
141         assert(fn.kind()==FKind.FlatAtomicExitNode);
142         //insert calls here...
143         Set<TempDescriptor> tempset=nodetoconvs2.get(fn);
144         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
145           TempDescriptor tmpd=tempit.next();
146           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tmpd, lb, false, nodetoconvs.get(fn).contains(tmpd));
147           atomictab.put(fgcn, atomictab.get(fn));
148           if (state.DSM)
149             temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
150
151           FlatNode[] prevarray=new FlatNode[fn.numPrev()];
152           for(int i=0; i<fn.numPrev(); i++) {
153             FlatNode fnprev=fn.getPrev(i);
154             prevarray[i]=fnprev;
155           }
156           for(int i=0; i<prevarray.length; i++) {
157             for(int j=0; j<prevarray[i].numNext(); j++) {
158               if (prevarray[i].getNext(j)==fn) {
159                 //found index, change node
160                 prevarray[i].setNext(j, fgcn);
161                 break;
162               }
163             }
164           }
165           fgcn.addNext(fn);
166         }
167       }
168     }
169   }
170
171   /* At the beginning of an atomic block, we need to convert any
172    * OID's that will be used in the atomic block to pointers */
173
174   private void converttoPtr(LocalityBinding lb) {
175     Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
176     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
177     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
178     MethodDescriptor md=lb.getMethod();
179     FlatMethod fm=state.getMethodFlat(md);
180     Set<FlatNode> toprocess=fm.getNodeSet();
181
182     while(!toprocess.isEmpty()) {
183       FlatNode fn=toprocess.iterator().next();
184       toprocess.remove(fn);
185
186       if (atomictab.get(fn).intValue()>0) {
187         //build set of transaction temps use by next nodes
188         HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
189         for(int i=0; i<fn.numNext(); i++) {
190           FlatNode fnnext=fn.getNext(i);
191           if (nodetotranstemps.containsKey(fnnext))
192             transtemps.addAll(nodetotranstemps.get(fnnext));
193         }
194         //subtract out the ones we write to
195         transtemps.removeAll(Arrays.asList(fn.writesTemps()));
196         //add in the globals we read from
197         if (state.SINGLETM) {
198           TempDescriptor [] readtemps=fn.readsTemps();
199           for(int i=0; i<readtemps.length; i++) {
200             TempDescriptor tmp=readtemps[i];
201             if (tmp.getType().isPtr()) {
202               transtemps.add(tmp);
203             }
204           }
205         } else {
206           Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
207           TempDescriptor [] readtemps=fn.readsTemps();
208           for(int i=0; i<readtemps.length; i++) {
209             TempDescriptor tmp=readtemps[i];
210             if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
211               transtemps.add(tmp);
212             }
213           }
214         }
215         if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
216           nodetotranstemps.put(fn, transtemps);
217           for(int i=0; i<fn.numPrev(); i++)
218             toprocess.add(fn.getPrev(i));
219         }
220       }
221     }
222     toprocess=fm.getNodeSet();
223     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
224       FlatNode fn=it.next();
225       if (atomictab.get(fn).intValue()>0&&
226           atomictab.get(fn.getPrev(0)).intValue()==0) {
227         //sanity check
228         assert(fn.kind()==FKind.FlatAtomicEnterNode);
229
230         //insert calls here...
231         Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
232         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
233           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
234           atomictab.put(fgcn, atomictab.get(fn));
235           if (state.DSM) {
236             temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
237           }
238           fgcn.addNext(fn.getNext(0));
239           fn.setNext(0, fgcn);
240         }
241       }
242     }
243   }
244 }