lots of changes for dsm now that william's stuff is checked in
[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                 
42         Hashtable<FlatNode, Set<TempNodePair>> nodetotnpair=new Hashtable<FlatNode, Set<TempNodePair>>();       
43         Hashtable<FlatNode, Set<TempDescriptor>> nodetoconvs=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             Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
52             
53             List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
54             List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
55
56             if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode
57                 &&!nodetoconvs.containsKey(fn))
58                 nodetoconvs.put(fn, new HashSet<TempDescriptor>());
59
60
61             HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
62             for(int i=0;i<fn.numPrev();i++) {
63                 FlatNode fnprev=fn.getPrev(i);
64                 if (!nodetotnpair.containsKey(fnprev))
65                     continue;
66                 Set<TempNodePair> prevset=nodetotnpair.get(fnprev);
67                 for(Iterator<TempNodePair> it=prevset.iterator();it.hasNext();) {
68                     TempNodePair tnp=it.next();
69                     if (reads.contains(tnp.getTemp())&&tnp.getNode()!=null) {
70                         //Value actually is read...
71                         nodetoconvs.get(tnp.getNode()).add(tnp.getTemp());
72                     }
73                     if (writes.contains(tnp.getTemp())) //value overwritten
74                         continue;
75                     if (!isatomic&&fn.kind()==FKind.FlatAtomicExitNode) {
76                         //Create new node and tag it with this exit
77                         if (tnp.getNode()==null) {
78                             TempNodePair tnp2=new TempNodePair(tnp.getTemp());
79                             tnp2.setNode(fn);
80                             tempset.add(tnp2);
81                         }
82                     } else
83                         tempset.add(tnp);
84                 }
85             }
86             if (isatomic) {
87                 //if this is in an atomic block, record temps that are written to
88
89                 /* NOTE: If this compiler is changed to maintain
90                  * OID/Ptr's in variables, then we need to use all
91                  * global temps that could be read and not just the
92                  * ones converted by globalconvnode*/
93
94                 if (fn.kind()!=FKind.FlatGlobalConvNode||
95                     ((FlatGlobalConvNode)fn).getLocality()==lb)
96                     //If globalconvnode, make sure we have the right locality
97                     for(Iterator<TempDescriptor> writeit=writes.iterator();writeit.hasNext();) {
98                         TempDescriptor wrtmp=writeit.next();
99                         if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
100                             TempNodePair tnp=new TempNodePair(wrtmp);
101                             tempset.add(tnp);
102                         }
103                     }
104             }
105             if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
106                 //changes to set, so enqueue next nodes
107                 nodetotnpair.put(fn, tempset); //update set
108                 for(int i=0;i<fn.numNext();i++) {
109                     toprocess.add(fn.getNext(i));
110                 }
111             }
112         }
113         //Place Convert to Oid nodes
114         toprocess=fm.getNodeSet();
115         for(Iterator<FlatNode> it=toprocess.iterator();it.hasNext();) {
116             FlatNode fn=it.next();
117             if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
118                 atomictab.get(fn.getPrev(0)).intValue()>0) {
119                 //sanity check
120                 assert(fn.kind()==FKind.FlatAtomicExitNode);
121
122                 //insert calls here...
123                 Set<TempDescriptor> tempset=nodetoconvs.get(fn);
124                 for(Iterator<TempDescriptor> tempit=tempset.iterator();tempit.hasNext();) {
125                     FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, false);
126                     atomictab.put(fgcn, atomictab.get(fn));
127                     temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>) temptab.get(fn).clone());
128                     for(int i=0;i<fn.numPrev();i++) {
129                         FlatNode fnprev=fn.getPrev(i);
130                         for(int j=0;j<fnprev.numNext();j++) {
131                             if (fnprev.getNext(j)==fn) {
132                                 //found index, change node
133                                 fnprev.setNext(j, fgcn);
134                                 break;
135                             }
136                         }
137                     }
138                     fgcn.addNext(fn);
139                 }
140             }
141         }
142     }
143     
144     /* At the beginning of an atomic block, we need to convert any
145      * OID's that will be used in the atomic block to pointers */
146
147     private void converttoPtr(LocalityBinding lb) {
148         Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
149         Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
150         Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
151         MethodDescriptor md=lb.getMethod();
152         FlatMethod fm=state.getMethodFlat(md);
153         Set<FlatNode> toprocess=fm.getNodeSet();
154
155         while(!toprocess.isEmpty()) {
156             FlatNode fn=toprocess.iterator().next();
157             toprocess.remove(fn);
158             
159             if (atomictab.get(fn).intValue()>0) {
160                 //build set of transaction temps use by next nodes
161                 HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
162                 for(int i=0;i<fn.numNext();i++) {
163                     FlatNode fnnext=fn.getNext(i);
164                     if (nodetotranstemps.containsKey(fnnext))
165                         transtemps.addAll(nodetotranstemps.get(fnnext));
166                 }
167                 //subtract out the ones we write to
168                 transtemps.removeAll(Arrays.asList(fn.writesTemps()));
169                 //add in the globals we read from
170                 TempDescriptor []readtemps=fn.readsTemps();
171                 for(int i=0;i<readtemps.length;i++) {
172                     TempDescriptor tmp=readtemps[i];
173                     if (temptab.get(fn).get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
174                         transtemps.add(tmp);
175                     }
176                 }
177                 if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
178                     nodetotranstemps.put(fn, transtemps);
179                     for(int i=0;i<fn.numPrev();i++)
180                         toprocess.add(fn.getPrev(i));
181                 }
182             }
183         }
184         toprocess=fm.getNodeSet();
185         for(Iterator<FlatNode> it=toprocess.iterator();it.hasNext();) {
186             FlatNode fn=it.next();
187             if (atomictab.get(fn).intValue()>0&&
188                 atomictab.get(fn.getPrev(0)).intValue()==0) {
189                 //sanity check
190                 assert(fn.kind()==FKind.FlatAtomicEnterNode);
191
192                 //insert calls here...
193                 Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
194                 for(Iterator<TempDescriptor> tempit=tempset.iterator();tempit.hasNext();) {
195                     FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
196                     atomictab.put(fgcn, atomictab.get(fn));
197                     temptab.put(fgcn, (Hashtable<TempDescriptor, Integer>) temptab.get(fn).clone());
198                     fgcn.addNext(fn.getNext(0));
199                     fn.setNext(0, fgcn);
200                 }       
201             }
202         }
203     }
204 }