001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.ssa; 014 015 import java.lang.reflect.Constructor; 016 import java.util.Arrays; 017 018 import org.jikesrvm.compilers.opt.OptOptions; 019 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 020 import org.jikesrvm.compilers.opt.dfsolver.DF_AbstractCell; 021 import org.jikesrvm.compilers.opt.dfsolver.DF_Solution; 022 import org.jikesrvm.compilers.opt.driver.CompilerPhase; 023 import org.jikesrvm.compilers.opt.ir.IR; 024 025 /** 026 * Perform index propagation (see Fink, Knobe && Sarkar, SAS 2000) 027 * 028 * <p> This analysis computes for each Array SSA variable A, 029 * the set of value numbers V(k) such that location 030 * A[k] is "available" at def A, and thus at all uses of A 031 * 032 * <p> We formulate this as a data flow problem as described in the paper. 033 * 034 * <p> This class relies on Array SSA form, global value numbering, and 035 * the dataflow equation solver framework. 036 * 037 * <p> TODO: This implementation is not terribly efficient. Speed it up. 038 */ 039 public final class IndexPropagation extends CompilerPhase { 040 041 /** 042 * Constructor for this compiler phase 043 */ 044 private static final Constructor<CompilerPhase> constructor = 045 getCompilerPhaseConstructor(IndexPropagation.class); 046 047 /** 048 * Get a constructor object for this compiler phase 049 * @return compiler phase constructor 050 */ 051 @Override 052 public Constructor<CompilerPhase> getClassConstructor() { 053 return constructor; 054 } 055 056 /** 057 * @return <code>true</code> iff SSA is constructed on the HIR 058 */ 059 @Override 060 public boolean shouldPerform(OptOptions options) { 061 return options.SSA; 062 } 063 064 /** 065 * Return the name of this compiler phase. 066 * @return "Index Propagation" 067 */ 068 @Override 069 public String getName() { 070 return "Index Propagation"; 071 } 072 073 /** 074 * Print verbose debugging messages? 075 */ 076 private static final boolean DEBUG = false; 077 078 /** 079 * Perform the analysis. 080 * <p> Pre-condition: The IR is in Array SSA form and global value numbers 081 * have been computed. 082 * 083 * @param ir the IR to optimize 084 */ 085 @Override 086 public void perform(IR ir) { 087 if (ir.desiredSSAOptions.getAbort()) return; 088 IndexPropagationSystem system = new IndexPropagationSystem(ir); 089 if (DEBUG) { 090 System.out.print("Solving..."); 091 } 092 system.solve(); 093 if (DEBUG) { 094 System.out.println("done"); 095 } 096 DF_Solution solution = system.getSolution(); 097 if (DEBUG) { 098 System.out.println("Index Propagation Solution: " + solution); 099 } 100 ir.HIRInfo.indexPropagationSolution = solution; 101 } 102 103 /** 104 * An ObjectCell is a lattice cell for the index propagation 105 * problem, used in redundant load elimination for fields. 106 * <p> An ObjectCell represents a set of value numbers, 107 * indicating that 108 * the elements indexed by these value numbers are available for 109 * a certain field type. 110 * 111 * <p> Note: this implementation does not scale, and is not terribly 112 * efficient. 113 */ 114 static final class ObjectCell extends DF_AbstractCell { 115 /** 116 * a bound on the size of a lattice cell. 117 */ 118 private static final int CAPACITY = 10; 119 /** 120 * a set of value numbers comparising this lattice cell. 121 */ 122 private int[] numbers = null; 123 /** 124 * The number of value numbers in this cell. 125 */ 126 private int size = 0; 127 /** 128 * The heap variable this lattice cell tracks information for. 129 */ 130 private final HeapVariable<?> key; 131 /** 132 * Does this lattice cell represent TOP? 133 */ 134 private boolean TOP = true; 135 136 /** 137 * Create a lattice cell corresponding to a heap variable. 138 * @param key the heap variable associated with this cell. 139 */ 140 ObjectCell(HeapVariable<?> key) { 141 this.key = key; 142 } 143 144 /** 145 * Return the key 146 */ 147 HeapVariable<?> getKey() { 148 return key; 149 } 150 151 /** 152 * Does this cell represent the TOP element in the dataflow lattice? 153 * @return true or false. 154 */ 155 boolean isTOP() { 156 return TOP; 157 } 158 159 /** 160 * Does this cell represent the BOTTOM element in the dataflow lattice? 161 * @return true or false. 162 */ 163 boolean isBOTTOM() { 164 return !TOP && (size == 0); 165 } 166 167 /** 168 * Mark this cell as representing (or not) the TOP element in the 169 * dataflow lattice. 170 * @param b should this cell contain TOP? 171 */ 172 void setTOP(boolean b) { 173 TOP = b; 174 numbers = null; 175 } 176 177 /** 178 * Set the value of this cell to BOTTOM. 179 */ 180 void setBOTTOM() { 181 clear(); 182 } 183 184 /** 185 * Does this cell contain the value number v? 186 * 187 * @param v value number in question 188 * @return true or false 189 */ 190 boolean contains(int v) { 191 192 if (isTOP()) return true; 193 if (v == GlobalValueNumberState.UNKNOWN) return false; 194 195 for (int i = 0; i < size; i++) { 196 if (numbers[i] == v) { 197 return true; 198 } 199 } 200 return false; 201 } 202 203 /** 204 * Add a value number to this cell. 205 * 206 * @param v value number 207 */ 208 void add(int v) { 209 if (isTOP()) return; 210 211 if ((size < CAPACITY) && !contains(v)) { 212 if (size == 0) { 213 numbers = new int[CAPACITY]; 214 } 215 numbers[size] = v; 216 size++; 217 } 218 } 219 220 /** 221 * Remove a value number from this cell. 222 * 223 * @param v value number 224 */ 225 void remove(int v) { 226 if (isTOP()) { 227 throw new OptimizingCompilerException("Unexpected lattice operation"); 228 } 229 int[] old = numbers; 230 int[] numbers = new int[CAPACITY]; 231 int index = 0; 232 for (int i = 0; i < size; i++) { 233 if (old[i] == v) { 234 size--; 235 } else { 236 numbers[index++] = old[i]; 237 } 238 } 239 } 240 241 /** 242 * Clear all value numbers from this cell. 243 */ 244 void clear() { 245 setTOP(false); 246 size = 0; 247 numbers = null; 248 } 249 250 /** 251 * Return a deep copy of the value numbers in this cell. 252 * @return a deep copy of the value numbers in this cell, null to 253 * represent empty set. 254 */ 255 int[] copyValueNumbers() { 256 if (isTOP()) { 257 throw new OptimizingCompilerException("Unexpected lattice operation"); 258 } 259 if (size == 0) return null; 260 261 int[] result = new int[size]; 262 for (int i = 0; i < size; i++) { 263 result[i] = numbers[i]; 264 } 265 return result; 266 } 267 268 /** 269 * Return a string representation of this cell 270 * @return a string representation of this cell 271 */ 272 @Override 273 public String toString() { 274 StringBuilder s = new StringBuilder(key.toString()); 275 276 if (isTOP()) return s.append("{TOP}").toString(); 277 if (isBOTTOM()) return s.append("{BOTTOM}").toString(); 278 279 s.append("{"); 280 for (int i = 0; i < size; i++) { 281 s.append(" ").append(numbers[i]); 282 } 283 s.append("}"); 284 return s.toString(); 285 } 286 287 /** 288 * Do two sets of value numbers differ? 289 * <p> SIDE EFFECT: sorts the sets 290 * 291 * @param set1 first set to compare 292 * @param set2 second set to compare 293 * @return true iff the two sets are different 294 */ 295 public static boolean setsDiffer(int[] set1, int[] set2) { 296 if ((set1 != null) && (set2 != null)) { 297 Arrays.sort(set1); 298 Arrays.sort(set2); 299 return !Arrays.equals(set1, set2); 300 } else { 301 return set1 == set2; 302 } 303 } 304 } 305 306 /** 307 * An ArrayCell is a lattice cell for the index propagation 308 * problem, used in redundant load elimination for one-dimensional arrays. 309 * <p> An ArrayCell represents a set of value number pairs, 310 * indicating that 311 * the elements indexed by these value numbers are available for 312 * a certain array type. 313 * 314 * <p> For example, suppose p is an int[], with value number v(p). 315 * Then the value number pair <p,5> for heap variable I[ means 316 * that p[5] is available. 317 * 318 * <p> Note: this implementation does not scale, and is not terribly 319 * efficient. 320 */ 321 static final class ArrayCell extends DF_AbstractCell { 322 /** 323 * a bound on the size of a lattice cell. 324 */ 325 private static final int CAPACITY = 10; 326 /** 327 * a set of value number pairs comparising this lattice cell. 328 */ 329 private ValueNumberPair[] numbers = null; 330 /** 331 * The number of value number pairs in this cell. 332 */ 333 private int size = 0; 334 /** 335 * The heap variable this lattice cell tracks information for. 336 */ 337 private final HeapVariable<?> key; 338 /** 339 * Does this lattice cell represent TOP? 340 */ 341 private boolean TOP = true; 342 343 /** 344 * Create a lattice cell corresponding to a heap variable. 345 * @param key the heap variable associated with this cell. 346 */ 347 ArrayCell(HeapVariable<?> key) { 348 this.key = key; 349 } 350 351 /** 352 * Return the key 353 */ 354 HeapVariable<?> getKey() { 355 return key; 356 } 357 358 /** 359 * Does this cell represent the TOP element in the dataflow lattice? 360 * @return true or false. 361 */ 362 boolean isTOP() { 363 return TOP; 364 } 365 366 /** 367 * Does this cell represent the BOTTOM element in the dataflow lattice? 368 * @return true or false. 369 */ 370 boolean isBOTTOM() { 371 return !TOP && (size == 0); 372 } 373 374 /** 375 * Mark this cell as representing (or not) the TOP element in the 376 * dataflow lattice. 377 * @param b should this cell contain TOP? 378 */ 379 void setTOP(boolean b) { 380 TOP = b; 381 numbers = null; 382 } 383 384 /** 385 * Set the value of this cell to BOTTOM. 386 */ 387 void setBOTTOM() { 388 clear(); 389 } 390 391 /** 392 * Does this cell contain the value number pair v1, v2? 393 * 394 * @param v1 first value number 395 * @param v2 second value number 396 * @return true or false 397 */ 398 boolean contains(int v1, int v2) { 399 if (isTOP()) return true; 400 if (v1 == GlobalValueNumberState.UNKNOWN) return false; 401 if (v2 == GlobalValueNumberState.UNKNOWN) return false; 402 if (size == 0) return false; 403 404 ValueNumberPair p = new ValueNumberPair(v1, v2); 405 for (int i = 0; i < size; i++) { 406 if (numbers[i].equals(p)) { 407 return true; 408 } 409 } 410 return false; 411 } 412 413 /** 414 * Add a value number pair to this cell. 415 * 416 * @param v1 first value number 417 * @param v2 second value number 418 */ 419 void add(int v1, int v2) { 420 if (isTOP()) return; 421 422 if ((size < CAPACITY) && !contains(v1, v2)) { 423 if (size == 0) { 424 numbers = new ValueNumberPair[CAPACITY]; 425 } 426 ValueNumberPair p = new ValueNumberPair(v1, v2); 427 numbers[size] = p; 428 size++; 429 } 430 } 431 432 /** 433 * Remove a value number pair from this cell. 434 * 435 * @param v1 first value number 436 * @param v2 second value number 437 */ 438 void remove(int v1, int v2) { 439 if (isTOP()) { 440 throw new OptimizingCompilerException("Unexpected lattice operation"); 441 } 442 ValueNumberPair[] old = numbers; 443 ValueNumberPair[] numbers = new ValueNumberPair[CAPACITY]; 444 int index = 0; 445 ValueNumberPair p = new ValueNumberPair(v1, v2); 446 for (int i = 0; i < size; i++) { 447 if (old[i].equals(p)) { 448 size--; 449 } else { 450 numbers[index++] = old[i]; 451 } 452 } 453 } 454 455 /** 456 * Clear all value numbers from this cell. 457 */ 458 void clear() { 459 setTOP(false); 460 size = 0; 461 numbers = null; 462 } 463 464 /** 465 * Return a deep copy of the value numbers in this cell 466 * @return a deep copy of the value numbers in this cell 467 */ 468 ValueNumberPair[] copyValueNumbers() { 469 if (isTOP()) { 470 throw new OptimizingCompilerException("Unexpected lattice operation"); 471 } 472 473 if (size == 0) return null; 474 475 ValueNumberPair[] result = new ValueNumberPair[size]; 476 for (int i = 0; i < size; i++) { 477 result[i] = new ValueNumberPair(numbers[i]); 478 } 479 return result; 480 } 481 482 /** 483 * Return a string representation of this cell 484 * @return a string representation of this cell 485 */ 486 @Override 487 public String toString() { 488 StringBuilder s = new StringBuilder(key.toString()); 489 490 if (isTOP()) return s.append("{TOP}").toString(); 491 if (isBOTTOM()) return s.append("{BOTTOM}").toString(); 492 493 s.append("{"); 494 for (int i = 0; i < size; i++) { 495 s.append(" ").append(numbers[i]); 496 } 497 s.append("}"); 498 return s.toString(); 499 } 500 501 /** 502 * Do two sets of value number pairs differ? 503 * <p> SIDE EFFECT: sorts the sets 504 * 505 * @param set1 first set to compare 506 * @param set2 second set to compare 507 * @return true iff the two sets are different 508 */ 509 public static boolean setsDiffer(ValueNumberPair[] set1, ValueNumberPair[] set2) { 510 if ((set1 != null) && (set2 != null)) { 511 Arrays.sort(set1); 512 Arrays.sort(set2); 513 return !Arrays.equals(set1, set2); 514 } else { 515 return set1 == set2; 516 } 517 } 518 } 519 }