This commit was manufactured by cvs2svn to create tag 'buildscript'.
[IRC.git] /
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=temptab.get(fn);
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 (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
115               TempNodePair tnp=new TempNodePair(wrtmp);
116               tempset.add(tnp);
117             }
118           }
119         }
120       }
121       if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
122         //changes to set, so enqueue next nodes
123         nodetotnpair.put(fn, tempset);         //update set
124         for(int i=0; i<fn.numNext(); i++) {
125           toprocess.add(fn.getNext(i));
126         }
127       }
128     }
129     //Place Convert to Oid nodes
130     toprocess=fm.getNodeSet();
131     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
132       FlatNode fn=it.next();
133       if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
134           atomictab.get(fn.getPrev(0)).intValue()>0) {
135         //sanity check
136         assert(fn.kind()==FKind.FlatAtomicExitNode);
137         //insert calls here...
138         Set<TempDescriptor> tempset=nodetoconvs2.get(fn);
139         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
140           TempDescriptor tmpd=tempit.next();
141           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tmpd, lb, false, nodetoconvs.get(fn).contains(tmpd));
142           atomictab.put(fgcn, atomictab.get(fn));
143           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
144
145           for(int i=0; i<fn.numPrev(); i++) {
146             FlatNode fnprev=fn.getPrev(i);
147             for(int j=0; j<fnprev.numNext(); j++) {
148               if (fnprev.getNext(j)==fn) {
149                 //found index, change node
150                 fnprev.setNext(j, fgcn);
151                 break;
152               }
153             }
154           }
155           fgcn.addNext(fn);
156         }
157       }
158     }
159   }
160
161   /* At the beginning of an atomic block, we need to convert any
162    * OID's that will be used in the atomic block to pointers */
163
164   private void converttoPtr(LocalityBinding lb) {
165     Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
166     Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
167     Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
168     MethodDescriptor md=lb.getMethod();
169     FlatMethod fm=state.getMethodFlat(md);
170     Set<FlatNode> toprocess=fm.getNodeSet();
171
172     while(!toprocess.isEmpty()) {
173       FlatNode fn=toprocess.iterator().next();
174       toprocess.remove(fn);
175
176       if (atomictab.get(fn).intValue()>0) {
177         //build set of transaction temps use by next nodes
178         HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
179         for(int i=0; i<fn.numNext(); i++) {
180           FlatNode fnnext=fn.getNext(i);
181           if (nodetotranstemps.containsKey(fnnext))
182             transtemps.addAll(nodetotranstemps.get(fnnext));
183         }
184         //subtract out the ones we write to
185         transtemps.removeAll(Arrays.asList(fn.writesTemps()));
186         //add in the globals we read from
187         Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
188         TempDescriptor [] readtemps=fn.readsTemps();
189         for(int i=0; i<readtemps.length; i++) {
190           TempDescriptor tmp=readtemps[i];
191           if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
192             transtemps.add(tmp);
193           }
194         }
195         if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
196           nodetotranstemps.put(fn, transtemps);
197           for(int i=0; i<fn.numPrev(); i++)
198             toprocess.add(fn.getPrev(i));
199         }
200       }
201     }
202     toprocess=fm.getNodeSet();
203     for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext();) {
204       FlatNode fn=it.next();
205       if (atomictab.get(fn).intValue()>0&&
206           atomictab.get(fn.getPrev(0)).intValue()==0) {
207         //sanity check
208         assert(fn.kind()==FKind.FlatAtomicEnterNode);
209
210         //insert calls here...
211         Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
212         for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext();) {
213           FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
214           atomictab.put(fgcn, atomictab.get(fn));
215           temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>)temptab.get(fn).clone());
216           fgcn.addNext(fn.getNext(0));
217           fn.setNext(0, fgcn);
218         }
219       }
220     }
221   }
222 }