1 package Analysis.Locality;
5 import IR.MethodDescriptor;
8 public class GenerateConversions {
9 LocalityAnalysis locality;
12 /** Warning: This class modifies the code in place. */
14 public GenerateConversions(LocalityAnalysis la, State state) {
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
33 /* At the end of an atomic block, we need to convert any global
34 * references that will be used again into OID's. */
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>>();
45 Set<FlatNode> toprocess=fm.getNodeSet();
47 while(!toprocess.isEmpty()) {
48 FlatNode fn=toprocess.iterator().next();
50 boolean isatomic=atomictab.get(fn).intValue()>0;
52 Hashtable<TempDescriptor, Integer> nodetemptab=temptab.get(fn);
54 List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
55 List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
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>());
63 HashSet<TempNodePair> tempset=new HashSet<TempNodePair>();
65 for(int i=0; i<fn.numPrev(); i++) {
66 FlatNode fnprev=fn.getPrev(i);
67 if (!nodetotnpair.containsKey(fnprev))
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) {
79 if (reads.contains(tnp.getTemp())&&tnp.getNode()!=null) {
80 //Value actually is read...
81 nodetoconvs.get(tnp.getNode()).add(tnp.getTemp());
84 if (writes.contains(tnp.getTemp())) //value overwritten
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());
92 nodetoconvs2.get(fn).add(tnp.getTemp()); //have to hide cached copies from gc -- add unused converted temps
100 /* If this is in an atomic block, record temps that
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*/
108 if (fn.kind()!=FKind.FlatGlobalConvNode||
109 ((FlatGlobalConvNode)fn).getLocality()==lb) {
110 /*If globalconvnode, make sure we have the right
112 for(Iterator<TempDescriptor> writeit=writes.iterator(); writeit.hasNext(); ) {
113 TempDescriptor wrtmp=writeit.next();
114 if (state.SINGLETM) {
115 if (wrtmp.getType().isPtr()&&
116 (nodetemptab.get(wrtmp)!=LocalityAnalysis.SCRATCH)) {
117 TempNodePair tnp=new TempNodePair(wrtmp);
120 } else if (nodetemptab.get(wrtmp)==LocalityAnalysis.GLOBAL) {
121 TempNodePair tnp=new TempNodePair(wrtmp);
127 if (!nodetotnpair.containsKey(fn)||!nodetotnpair.get(fn).equals(tempset)) {
128 //changes to set, so enqueue next nodes
129 nodetotnpair.put(fn, tempset); //update set
130 for(int i=0; i<fn.numNext(); i++) {
131 toprocess.add(fn.getNext(i));
135 //Place Convert to Oid nodes
136 toprocess=fm.getNodeSet();
137 for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext(); ) {
138 FlatNode fn=it.next();
139 if (atomictab.get(fn).intValue()==0&&fn.numPrev()>0&&
140 atomictab.get(fn.getPrev(0)).intValue()>0) {
142 assert(fn.kind()==FKind.FlatAtomicExitNode);
143 //insert calls here...
144 Set<TempDescriptor> tempset=nodetoconvs2.get(fn);
145 for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext(); ) {
146 TempDescriptor tmpd=tempit.next();
147 FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tmpd, lb, false, nodetoconvs.get(fn).contains(tmpd));
149 //This loop makes sure that we have accurate atomic information for the new node
150 for(Iterator<LocalityBinding> lbit=locality.getMethodBindings(lb.getMethod()).iterator(); lbit.hasNext(); ) {
151 LocalityBinding fixlb=lbit.next();
152 locality.getAtomic(fixlb).put(fgcn, locality.getAtomic(fixlb).get(fn.getPrev(0)));
153 locality.getNodeTempInfo(fixlb).put(fgcn, (Hashtable<TempDescriptor, Integer>)locality.getNodeTempInfo(fixlb).get(fn).clone());
156 fgcn.setAtomicEnter(((FlatAtomicExitNode)fn).getAtomicEnter());
158 FlatNode[] prevarray=new FlatNode[fn.numPrev()];
159 for(int i=0; i<fn.numPrev(); i++) {
160 FlatNode fnprev=fn.getPrev(i);
163 for(int i=0; i<prevarray.length; i++) {
164 for(int j=0; j<prevarray[i].numNext(); j++) {
165 if (prevarray[i].getNext(j)==fn) {
166 //found index, change node
167 prevarray[i].setNext(j, fgcn);
178 /* At the beginning of an atomic block, we need to convert any
179 * OID's that will be used in the atomic block to pointers */
181 private void converttoPtr(LocalityBinding lb) {
182 Hashtable<FlatNode, Set<TempDescriptor>> nodetotranstemps=new Hashtable<FlatNode, Set<TempDescriptor>>();
183 Hashtable<FlatNode, Integer> atomictab=locality.getAtomic(lb);
184 Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=locality.getNodeTempInfo(lb);
185 MethodDescriptor md=lb.getMethod();
186 FlatMethod fm=state.getMethodFlat(md);
187 Set<FlatNode> toprocess=fm.getNodeSet();
189 while(!toprocess.isEmpty()) {
190 FlatNode fn=toprocess.iterator().next();
191 toprocess.remove(fn);
193 if (atomictab.get(fn).intValue()>0) {
194 //build set of transaction temps use by next nodes
195 HashSet<TempDescriptor> transtemps=new HashSet<TempDescriptor>();
196 for(int i=0; i<fn.numNext(); i++) {
197 FlatNode fnnext=fn.getNext(i);
198 if (nodetotranstemps.containsKey(fnnext))
199 transtemps.addAll(nodetotranstemps.get(fnnext));
201 //subtract out the ones we write to
202 transtemps.removeAll(Arrays.asList(fn.writesTemps()));
203 //add in the globals we read from
204 Hashtable<TempDescriptor, Integer> pretemptab=locality.getNodePreTempInfo(lb, fn);
205 if (state.SINGLETM) {
206 TempDescriptor [] readtemps=fn.readsTemps();
207 for(int i=0; i<readtemps.length; i++) {
208 TempDescriptor tmp=readtemps[i];
209 if (tmp.getType().isPtr()&&
210 pretemptab.get(tmp).intValue()!=LocalityAnalysis.SCRATCH) {
215 TempDescriptor [] readtemps=fn.readsTemps();
216 for(int i=0; i<readtemps.length; i++) {
217 TempDescriptor tmp=readtemps[i];
218 if (pretemptab.get(tmp).intValue()==LocalityAnalysis.GLOBAL) {
223 if (!nodetotranstemps.containsKey(fn)||!nodetotranstemps.get(fn).equals(transtemps)) {
224 nodetotranstemps.put(fn, transtemps);
225 for(int i=0; i<fn.numPrev(); i++)
226 toprocess.add(fn.getPrev(i));
230 toprocess=fm.getNodeSet();
231 for(Iterator<FlatNode> it=toprocess.iterator(); it.hasNext(); ) {
232 FlatNode fn=it.next();
233 if (atomictab.get(fn).intValue()>0&&
234 atomictab.get(fn.getPrev(0)).intValue()==0) {
236 assert(fn.kind()==FKind.FlatAtomicEnterNode);
238 //insert calls here...
239 Set<TempDescriptor> tempset=nodetotranstemps.get(fn);
240 for(Iterator<TempDescriptor> tempit=tempset.iterator(); tempit.hasNext(); ) {
241 FlatGlobalConvNode fgcn=new FlatGlobalConvNode(tempit.next(), lb, true);
242 fgcn.setAtomicEnter((FlatAtomicEnterNode)fn);
243 //This loop makes sure that we have accurate atomic information for the new node
244 for(Iterator<LocalityBinding> lbit=locality.getMethodBindings(lb.getMethod()).iterator(); lbit.hasNext(); ) {
245 LocalityBinding fixlb=lbit.next();
246 locality.getAtomic(fixlb).put(fgcn, locality.getAtomic(fixlb).get(fn));
247 locality.getNodeTempInfo(fixlb).put(fgcn, (Hashtable<TempDescriptor, Integer>)locality.getNodeTempInfo(fixlb).get(fn).clone());
249 fgcn.addNext(fn.getNext(0));