1 pnkfelix 1.1.2.1 // RegAllocOpts.java, created Thu Oct 19 19:14:47 2000 by pnkfelix
  2 cananian 1.1.2.6 // Copyright (C) 2000 Felix S. Klock II <pnkfelix@mit.edu>
  3 pnkfelix 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1 package harpoon.Analysis.Instr;
  5 pnkfelix 1.1.2.1 
  6 pnkfelix 1.1.2.1 import harpoon.ClassFile.HClass;
  7 pnkfelix 1.1.2.1 import harpoon.ClassFile.HMethod;
  8 pnkfelix 1.1.2.1 import harpoon.ClassFile.HCodeFactory;
  9 pnkfelix 1.1.2.1 import harpoon.Backend.Generic.Code;
 10 pnkfelix 1.1.2.1 
 11 pnkfelix 1.1.2.1 import java.io.BufferedInputStream;
 12 pnkfelix 1.1.2.1 import java.io.BufferedReader;
 13 pnkfelix 1.1.2.1 import java.io.File;
 14 pnkfelix 1.1.2.1 import java.io.FileInputStream;
 15 pnkfelix 1.1.2.1 import java.io.FileOutputStream;
 16 pnkfelix 1.1.2.1 import java.io.FileReader;
 17 pnkfelix 1.1.2.1 import java.io.InputStream;
 18 pnkfelix 1.1.2.1 import java.io.InputStreamReader;
 19 pnkfelix 1.1.2.1 import java.io.IOException;
 20 pnkfelix 1.1.2.1 import java.io.LineNumberReader;
 21 pnkfelix 1.1.2.1 
 22 pnkfelix 1.1.2.1 import java.util.HashSet;
 23 pnkfelix 1.1.2.3 import java.util.Iterator;
 24 pnkfelix 1.1.2.3 import java.util.ArrayList;
 25 pnkfelix 1.1.2.1 import java.util.StringTokenizer;
 26 pnkfelix 1.1.2.1 
 27 pnkfelix 1.1.2.1 /**
 28 pnkfelix 1.1.2.1  * <code>RegAllocOpts</code> encapsulates a set of modifications to
 29 pnkfelix 1.1.2.1  * how register allocation will be performed on a particular set of
 30 pnkfelix 1.1.2.1  * methods.  The choice of modifications are read in from a seperate
 31 pnkfelix 1.1.2.1  * file, and then code factories produced by this will use the options
 32 pnkfelix 1.1.2.1  * given the file to change how register allocation is done in certain
 33 pnkfelix 1.1.2.1  * cases. 
 34 pnkfelix 1.1.2.1  * <p>
 35 pnkfelix 1.1.2.1  * Currently, the file supports the following options:
 36 pnkfelix 1.1.2.1  * <br> "FORCE_LOCAL <em>method name</em> ..." forces the register allocator to
 37 pnkfelix 1.1.2.1  * use a local allocation strategy on <em>method name</em> rather than
 38 pnkfelix 1.1.2.1  * whatever default strategy is in place. 
 39 pnkfelix 1.1.2.4  * <br> "DISABLE_REACHING_DEFS <em>method name</em> ..." forces the
 40 pnkfelix 1.1.2.4  * register allocator to use a local allocation strategy on <em>method
 41 pnkfelix 1.1.2.4  * name</em> rather than whatever default strategy is in place, and
 42 pnkfelix 1.1.2.4  * <b>in addition</b> disables ReachingDefs analysis in local register
 43 pnkfelix 1.1.2.4  * allocation.  This is a sick hack added just to compile certain spec
 44 pnkfelix 1.1.2.4  * classes before his deadline.
 45 pnkfelix 1.1.2.1  * <br> "FORCE_GLOBAL <em>method name</em> ..." forces the register
 46 pnkfelix 1.1.2.1  * allocator to use a global allocation strategy on <em>method
 47 pnkfelix 1.1.2.1  * name</em>, rather than whatever default stategy is in place. 
 48 pnkfelix 1.1.2.1  * <br> "FORCE_COALESCE <em>method name</em> ..." forces global
 49 pnkfelix 1.1.2.1  * allocation with non-conservative move coalescing to take place,
 50 pnkfelix 1.1.2.1  * even when it might result in additional memory traffic.
 51 pnkfelix 1.1.2.4  * <br> "DISABLE_COALESCE <em>method name</em> ..." turns off 
 52 pnkfelix 1.1.2.4  * move coalescing on global allocation.  
 53 pnkfelix 1.1.2.5  * <br> "FORCE_APPEL <em>method name</em> ..." forces the register
 54 pnkfelix 1.1.2.5  * allocator to use Appel-style register allocation on <em>method
 55 pnkfelix 1.1.2.5  * name</em>, rather than whatever default strategy is in place.
 56 pnkfelix 1.1.2.8  * <br> "FORCE_FELIX <em>method name</em> ..." forces the register
 57 pnkfelix 1.1.2.8  * allocator to use Appel-style register allocation on <em>method
 58 pnkfelix 1.1.2.8  * name</em> (with modifications for architectural indepedence),
 59 pnkfelix 1.1.2.8  * rather than whatever default strategy is in place.
 60 pnkfelix 1.1.2.1  * <br> "# <em>comment</em>" is a comment line (not strictly an
 61 pnkfelix 1.1.2.1  * option, since this line is ignored by this, but too useful to omit) 
 62 pnkfelix 1.1.2.1  * <p>
 63 pnkfelix 1.1.2.7  * The method names given in the file should be disjoint; the behavior
 64 pnkfelix 1.1.2.7  * of allocation is undefined when a <em>method</em> is listed under
 65 pnkfelix 1.1.2.7  * multiple options.
 66 pnkfelix 1.1.2.7  * <p> 
 67 pnkfelix 1.1.2.7  * A set of methods with a common prefix can be passed as the <em>method name</em> argument
 68 pnkfelix 1.1.2.7  * to a single option by appending the wildcard character '*' to the prefix.
 69 pnkfelix 1.1.2.1  * <p>
 70 pnkfelix 1.1.2.1  * After these options have been loaded, this class can be used to
 71 pnkfelix 1.1.2.1  * produce wrapper <code>RegAlloc.Factory</code>s around other
 72 pnkfelix 1.1.2.1  * <code>RegAlloc.Factory</code>s
 73 pnkfelix 1.1.2.1  * 
 74 cananian 1.1.2.6  * @author  Felix S. Klock II <pnkfelix@mit.edu>
 75 cananian 1.3      * @version $Id: RegAllocOpts.java,v 1.3 2004/02/08 03:19:37 cananian Exp $ */
 76 pnkfelix 1.1.2.1 public class RegAllocOpts {
 77 pnkfelix 1.1.2.2     public static final boolean INFO = false;
 78 pnkfelix 1.1.2.4     Filter disableReachingDefs;
 79 pnkfelix 1.1.2.3     Filter forceLocal;
 80 pnkfelix 1.1.2.3     Filter forceGlobal;
 81 pnkfelix 1.1.2.5     Filter forceAppel;
 82 pnkfelix 1.1.2.8     Filter forceFelix;
 83 pnkfelix 1.1.2.3     Filter forceCoalesce;
 84 pnkfelix 1.1.2.4     Filter disableCoalesce;
 85 pnkfelix 1.1.2.1 
 86 pnkfelix 1.1.2.1     /** Creates a <code>RegAllocOpts</code>. */
 87 pnkfelix 1.1.2.1     public RegAllocOpts(String filename) {
 88 pnkfelix 1.1.2.4         disableReachingDefs = new Filter();
 89 pnkfelix 1.1.2.3         forceLocal = new Filter();
 90 pnkfelix 1.1.2.3         forceGlobal = new Filter();
 91 pnkfelix 1.1.2.3         forceCoalesce = new Filter();
 92 pnkfelix 1.1.2.5         forceAppel = new Filter();
 93 pnkfelix 1.1.2.8         forceFelix = new Filter();
 94 pnkfelix 1.1.2.4         disableCoalesce = new Filter();
 95 pnkfelix 1.1.2.1 
 96 pnkfelix 1.1.2.1         if (filename != null) {
 97 pnkfelix 1.1.2.1             try {
 98 pnkfelix 1.1.2.5                 if (INFO) System.out.println("reading options from "+filename);
 99 pnkfelix 1.1.2.1                 readOptions(filename);
100 pnkfelix 1.1.2.1             } catch (IOException e) {
101 pnkfelix 1.1.2.1                 System.out.println(e.getMessage());
102 pnkfelix 1.1.2.1                 System.out.println
103 pnkfelix 1.1.2.1                     ("Error reading regalloc options file; no options being used");
104 pnkfelix 1.1.2.1                 forceLocal.clear(); forceGlobal.clear(); forceCoalesce.clear();
105 pnkfelix 1.1.2.4                 disableCoalesce.clear();
106 pnkfelix 1.1.2.1             }
107 pnkfelix 1.1.2.1         }
108 pnkfelix 1.1.2.1     }
109 pnkfelix 1.1.2.1 
110 pnkfelix 1.1.2.1     public RegAlloc.Factory factory(final RegAlloc.Factory hc) {
111 pnkfelix 1.1.2.1         return new RegAlloc.Factory() {
112 pnkfelix 1.1.2.1             public RegAlloc makeRegAlloc(Code c) {
113 pnkfelix 1.1.2.1                 String name = nameFor(c).trim();
114 pnkfelix 1.1.2.1                 
115 pnkfelix 1.1.2.4                 if (disableReachingDefs.contains(name)) {
116 pnkfelix 1.1.2.4                     if (INFO) System.out.println(" * USING DRd FOR "+name);
117 pnkfelix 1.1.2.4                     return LocalCffRegAlloc.RD_DISABLED_FACTORY.makeRegAlloc(c);
118 pnkfelix 1.1.2.4                 } else if (forceLocal.contains(name)) {
119 pnkfelix 1.1.2.2                     if (INFO) System.out.println(" * USING FL FOR "+name);
120 pnkfelix 1.1.2.1                     return RegAlloc.LOCAL.makeRegAlloc(c);
121 pnkfelix 1.1.2.1                 } else if (forceGlobal.contains(name)) {
122 pnkfelix 1.1.2.2                     if (INFO) System.out.println(" * USING FG FOR "+name);
123 pnkfelix 1.1.2.1                     return RegAlloc.GLOBAL.makeRegAlloc(c);
124 pnkfelix 1.1.2.1                 } else if (forceCoalesce.contains(name)) {
125 pnkfelix 1.1.2.2                     if (INFO) System.out.println(" * USING FC FOR "+name);
126 pnkfelix 1.1.2.1                     return GraphColoringRegAlloc.AGGRESSIVE_FACTORY.makeRegAlloc(c);
127 pnkfelix 1.1.2.5                 } else if (forceAppel.contains(name)) {
128 pnkfelix 1.1.2.5                     if (INFO) System.out.println(" * USING Appel FOR "+name);
129 pnkfelix 1.1.2.5                     return AppelRegAlloc.FACTORY.makeRegAlloc(c);
130 pnkfelix 1.1.2.8                 } else if (forceFelix.contains(name)) {
131 pnkfelix 1.1.2.8                     if (INFO) System.out.println(" * USING Felix FOR "+name);
132 pnkfelix 1.1.2.8                     return AppelRegAllocFsk.FACTORY.makeRegAlloc(c);
133 pnkfelix 1.1.2.4                 } else if (disableCoalesce.contains(name)) {
134 pnkfelix 1.1.2.4                     if (INFO) System.out.println(" * USING DC FOR "+name);
135 pnkfelix 1.1.2.5                     return GraphColoringRegAlloc.BRAINDEAD_FACTORY.makeRegAlloc(c);
136 pnkfelix 1.1.2.1                 } else {
137 pnkfelix 1.1.2.2                     if (INFO) System.out.println(" * USING NM FOR "+name);
138 pnkfelix 1.1.2.1                     return hc.makeRegAlloc(c);
139 pnkfelix 1.1.2.1                 }
140 pnkfelix 1.1.2.1             }
141 pnkfelix 1.1.2.1         };
142 pnkfelix 1.1.2.1     }
143 pnkfelix 1.1.2.1 
144 pnkfelix 1.1.2.1     private static String nameFor(Code c) {
145 pnkfelix 1.1.2.1         HMethod hm = c.getMethod();
146 pnkfelix 1.1.2.1         return hm.getDeclaringClass().getName() +"."+ hm.getName();
147 pnkfelix 1.1.2.1     }
148 pnkfelix 1.1.2.1 
149 pnkfelix 1.1.2.1     private void readOptions(String filename) throws IOException {
150 pnkfelix 1.1.2.1         LineNumberReader r = new LineNumberReader(new FileReader(filename));
151 pnkfelix 1.1.2.1         String line;
152 pnkfelix 1.1.2.1         while (null != (line=r.readLine())) {
153 pnkfelix 1.1.2.1             line = line.trim(); // remove white space from both sides.
154 pnkfelix 1.1.2.1             
155 pnkfelix 1.1.2.1             // allow comments and blank lines.
156 pnkfelix 1.1.2.1             if (line.startsWith("#") || line.length()==0) continue;
157 pnkfelix 1.1.2.1             
158 pnkfelix 1.1.2.1             StringTokenizer st = new StringTokenizer(line);
159 pnkfelix 1.1.2.1             String s = st.nextToken();
160 pnkfelix 1.1.2.3             Filter addToSet = null;
161 pnkfelix 1.1.2.4             if (s.toUpperCase().equals("DISABLE_REACHING_DEFS")) {
162 pnkfelix 1.1.2.4                 addToSet = disableReachingDefs;
163 pnkfelix 1.1.2.4             } else if (s.toUpperCase().equals("FORCE_LOCAL")) {
164 pnkfelix 1.1.2.1                 addToSet = forceLocal;
165 pnkfelix 1.1.2.1             } else if (s.toUpperCase().equals("FORCE_GLOBAL")) {
166 pnkfelix 1.1.2.1                 addToSet = forceGlobal;
167 pnkfelix 1.1.2.1             } else if (s.toUpperCase().equals("FORCE_COALESCE")) {
168 pnkfelix 1.1.2.1                 addToSet = forceCoalesce;
169 pnkfelix 1.1.2.5             } else if (s.toUpperCase().equals("FORCE_APPEL")) {
170 pnkfelix 1.1.2.5                 addToSet = forceAppel;
171 pnkfelix 1.1.2.8             } else if (s.toUpperCase().equals("FORCE_FELIX")) {
172 pnkfelix 1.1.2.8                 addToSet = forceFelix;
173 pnkfelix 1.1.2.4             } else if (s.toUpperCase().equals("DISABLE_COALESCE")) {
174 pnkfelix 1.1.2.4                 addToSet = disableCoalesce;
175 pnkfelix 1.1.2.1             } else {
176 pnkfelix 1.1.2.8                 System.err.println("unknown RegAlloc option: "+s+
177 pnkfelix 1.1.2.1                                    " line: "+r.getLineNumber());
178 pnkfelix 1.1.2.1                 continue;
179 pnkfelix 1.1.2.1             }
180 pnkfelix 1.1.2.1 
181 pnkfelix 1.1.2.1             while (st.hasMoreTokens()) {
182 pnkfelix 1.1.2.1                 String tkn = st.nextToken();
183 pnkfelix 1.1.2.1                 addToSet.add(tkn);
184 pnkfelix 1.1.2.1                 // System.out.println("adding "+tkn+" to "+s);
185 pnkfelix 1.1.2.1             }
186 pnkfelix 1.1.2.1         }
187 pnkfelix 1.1.2.1 
188 pnkfelix 1.1.2.1         r.close();
189 pnkfelix 1.1.2.1         
190 pnkfelix 1.1.2.3     }
191 pnkfelix 1.1.2.3 
192 pnkfelix 1.1.2.3     /** Filter is a set of strings. */
193 pnkfelix 1.1.2.3     class Filter {
194 pnkfelix 1.1.2.5         // AF(c) = { s | s in c.names OR exists p in c.prefixMatches
195 pnkfelix 1.1.2.3         //               such that s begins-with p }
196 pnkfelix 1.1.2.3         HashSet names = new HashSet(5); 
197 pnkfelix 1.1.2.3         ArrayList prefixMatches = new ArrayList(5);
198 pnkfelix 1.1.2.3 
199 pnkfelix 1.1.2.3         public boolean contains(String name) {
200 pnkfelix 1.1.2.3             if (names.contains(name)) 
201 pnkfelix 1.1.2.3                 return true;
202 pnkfelix 1.1.2.3             
203 cananian 1.3                 for(Object sO : prefixMatches){
204 cananian 1.3                     String s = (String) sO;
205 pnkfelix 1.1.2.5                 if (name.startsWith(s)) 
206 pnkfelix 1.1.2.3                     return true;
207 pnkfelix 1.1.2.3             }
208 pnkfelix 1.1.2.3 
209 pnkfelix 1.1.2.3             return false;
210 pnkfelix 1.1.2.3         }
211 pnkfelix 1.1.2.3         
212 pnkfelix 1.1.2.3         public void add(String str) {
213 pnkfelix 1.1.2.3             if (!str.endsWith("*")) {
214 pnkfelix 1.1.2.3                 addName(str);
215 pnkfelix 1.1.2.3             } else {
216 pnkfelix 1.1.2.3                 addPrefix(str.substring(0,str.length()-1));
217 pnkfelix 1.1.2.3             }
218 pnkfelix 1.1.2.3         }
219 pnkfelix 1.1.2.3         public void addName(String str) { names.add(str); }
220 pnkfelix 1.1.2.3         public void addPrefix(String prefix) { prefixMatches.add(prefix); }
221 pnkfelix 1.1.2.3 
222 pnkfelix 1.1.2.3         public void clear() { names.clear(); prefixMatches.clear(); }
223 pnkfelix 1.1.2.1     }
224 pnkfelix 1.1.2.1     
225 cananian 1.2     }