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 */ 013package org.jikesrvm.compilers.opt.ssa; 014 015import java.lang.reflect.Constructor; 016import java.util.Arrays; 017 018import org.jikesrvm.compilers.opt.OptOptions; 019import org.jikesrvm.compilers.opt.OptimizingCompilerException; 020import org.jikesrvm.compilers.opt.dfsolver.DF_AbstractCell; 021import org.jikesrvm.compilers.opt.dfsolver.DF_Solution; 022import org.jikesrvm.compilers.opt.driver.CompilerPhase; 023import 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 */ 039public 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 HeapVariable<?> getKey() { 145 return key; 146 } 147 148 /** 149 * Does this cell represent the TOP element in the dataflow lattice? 150 * @return true or false. 151 */ 152 boolean isTOP() { 153 return TOP; 154 } 155 156 /** 157 * Does this cell represent the BOTTOM element in the dataflow lattice? 158 * @return true or false. 159 */ 160 boolean isBOTTOM() { 161 return !TOP && (size == 0); 162 } 163 164 /** 165 * Mark this cell as representing (or not) the TOP element in the 166 * dataflow lattice. 167 * @param b should this cell contain TOP? 168 */ 169 void setTOP(boolean b) { 170 TOP = b; 171 numbers = null; 172 } 173 174 /** 175 * Set the value of this cell to BOTTOM. 176 */ 177 void setBOTTOM() { 178 clear(); 179 } 180 181 /** 182 * Does this cell contain the value number v? 183 * 184 * @param v value number in question 185 * @return true or false 186 */ 187 boolean contains(int v) { 188 189 if (isTOP()) return true; 190 if (v == GlobalValueNumberState.UNKNOWN) return false; 191 192 for (int i = 0; i < size; i++) { 193 if (numbers[i] == v) { 194 return true; 195 } 196 } 197 return false; 198 } 199 200 /** 201 * Add a value number to this cell. 202 * 203 * @param v value number 204 */ 205 void add(int v) { 206 if (isTOP()) return; 207 208 if ((size < CAPACITY) && !contains(v)) { 209 if (size == 0) { 210 numbers = new int[CAPACITY]; 211 } 212 numbers[size] = v; 213 size++; 214 } 215 } 216 217 /** 218 * Remove a value number from this cell. 219 * 220 * @param v value number 221 */ 222 void remove(int v) { 223 if (isTOP()) { 224 throw new OptimizingCompilerException("Unexpected lattice operation"); 225 } 226 int[] old = numbers; 227 int[] numbers = new int[CAPACITY]; 228 int index = 0; 229 for (int i = 0; i < size; i++) { 230 if (old[i] == v) { 231 size--; 232 } else { 233 numbers[index++] = old[i]; 234 } 235 } 236 } 237 238 /** 239 * Clear all value numbers from this cell. 240 */ 241 void clear() { 242 setTOP(false); 243 size = 0; 244 numbers = null; 245 } 246 247 /** 248 * Return a deep copy of the value numbers in this cell. 249 * @return a deep copy of the value numbers in this cell, null to 250 * represent empty set. 251 */ 252 int[] copyValueNumbers() { 253 if (isTOP()) { 254 throw new OptimizingCompilerException("Unexpected lattice operation"); 255 } 256 if (size == 0) return null; 257 258 int[] result = new int[size]; 259 for (int i = 0; i < size; i++) { 260 result[i] = numbers[i]; 261 } 262 return result; 263 } 264 265 /** 266 * Return a string representation of this cell 267 * @return a string representation of this cell 268 */ 269 @Override 270 public String toString() { 271 StringBuilder s = new StringBuilder(key.toString()); 272 273 if (isTOP()) return s.append("{TOP}").toString(); 274 if (isBOTTOM()) return s.append("{BOTTOM}").toString(); 275 276 s.append("{"); 277 for (int i = 0; i < size; i++) { 278 s.append(" ").append(numbers[i]); 279 } 280 s.append("}"); 281 return s.toString(); 282 } 283 284 /** 285 * Do two sets of value numbers differ? 286 * <p> SIDE EFFECT: sorts the sets 287 * 288 * @param set1 first set to compare 289 * @param set2 second set to compare 290 * @return true iff the two sets are different 291 */ 292 public static boolean setsDiffer(int[] set1, int[] set2) { 293 if ((set1 != null) && (set2 != null)) { 294 Arrays.sort(set1); 295 Arrays.sort(set2); 296 return !Arrays.equals(set1, set2); 297 } else { 298 return set1 == set2; 299 } 300 } 301 } 302 303 /** 304 * An ArrayCell is a lattice cell for the index propagation 305 * problem, used in redundant load elimination for one-dimensional arrays. 306 * <p> An ArrayCell represents a set of value number pairs, 307 * indicating that 308 * the elements indexed by these value numbers are available for 309 * a certain array type. 310 * 311 * <p> For example, suppose {@code p} is an {@code int[]}, with value number 312 * {@code v(p)}. 313 * Then the value number pair {@code <p,5>} for heap variable {@code I[} means 314 * that {@code p[5]} is available. 315 * 316 * <p> Note: this implementation does not scale, and is not terribly 317 * efficient. 318 */ 319 static final class ArrayCell extends DF_AbstractCell { 320 /** 321 * a bound on the size of a lattice cell. 322 */ 323 private static final int CAPACITY = 10; 324 /** 325 * a set of value number pairs comparising this lattice cell. 326 */ 327 private ValueNumberPair[] numbers = null; 328 /** 329 * The number of value number pairs in this cell. 330 */ 331 private int size = 0; 332 /** 333 * The heap variable this lattice cell tracks information for. 334 */ 335 private final HeapVariable<?> key; 336 /** 337 * Does this lattice cell represent TOP? 338 */ 339 private boolean TOP = true; 340 341 /** 342 * Create a lattice cell corresponding to a heap variable. 343 * @param key the heap variable associated with this cell. 344 */ 345 ArrayCell(HeapVariable<?> key) { 346 this.key = key; 347 } 348 349 HeapVariable<?> getKey() { 350 return key; 351 } 352 353 /** 354 * Does this cell represent the TOP element in the dataflow lattice? 355 * @return true or false. 356 */ 357 boolean isTOP() { 358 return TOP; 359 } 360 361 /** 362 * Does this cell represent the BOTTOM element in the dataflow lattice? 363 * @return true or false. 364 */ 365 boolean isBOTTOM() { 366 return !TOP && (size == 0); 367 } 368 369 /** 370 * Mark this cell as representing (or not) the TOP element in the 371 * dataflow lattice. 372 * @param b should this cell contain TOP? 373 */ 374 void setTOP(boolean b) { 375 TOP = b; 376 numbers = null; 377 } 378 379 /** 380 * Set the value of this cell to BOTTOM. 381 */ 382 void setBOTTOM() { 383 clear(); 384 } 385 386 /** 387 * Does this cell contain the value number pair v1, v2? 388 * 389 * @param v1 first value number 390 * @param v2 second value number 391 * @return true or false 392 */ 393 boolean contains(int v1, int v2) { 394 if (isTOP()) return true; 395 if (v1 == GlobalValueNumberState.UNKNOWN) return false; 396 if (v2 == GlobalValueNumberState.UNKNOWN) return false; 397 if (size == 0) return false; 398 399 ValueNumberPair p = new ValueNumberPair(v1, v2); 400 for (int i = 0; i < size; i++) { 401 if (numbers[i].equals(p)) { 402 return true; 403 } 404 } 405 return false; 406 } 407 408 /** 409 * Add a value number pair to this cell. 410 * 411 * @param v1 first value number 412 * @param v2 second value number 413 */ 414 void add(int v1, int v2) { 415 if (isTOP()) return; 416 417 if ((size < CAPACITY) && !contains(v1, v2)) { 418 if (size == 0) { 419 numbers = new ValueNumberPair[CAPACITY]; 420 } 421 ValueNumberPair p = new ValueNumberPair(v1, v2); 422 numbers[size] = p; 423 size++; 424 } 425 } 426 427 /** 428 * Remove a value number pair from this cell. 429 * 430 * @param v1 first value number 431 * @param v2 second value number 432 */ 433 void remove(int v1, int v2) { 434 if (isTOP()) { 435 throw new OptimizingCompilerException("Unexpected lattice operation"); 436 } 437 ValueNumberPair[] old = numbers; 438 ValueNumberPair[] numbers = new ValueNumberPair[CAPACITY]; 439 int index = 0; 440 ValueNumberPair p = new ValueNumberPair(v1, v2); 441 for (int i = 0; i < size; i++) { 442 if (old[i].equals(p)) { 443 size--; 444 } else { 445 numbers[index++] = old[i]; 446 } 447 } 448 } 449 450 /** 451 * Clear all value numbers from this cell. 452 */ 453 void clear() { 454 setTOP(false); 455 size = 0; 456 numbers = null; 457 } 458 459 /** 460 * Return a deep copy of the value numbers in this cell 461 * @return a deep copy of the value numbers in this cell 462 */ 463 ValueNumberPair[] copyValueNumbers() { 464 if (isTOP()) { 465 throw new OptimizingCompilerException("Unexpected lattice operation"); 466 } 467 468 if (size == 0) return null; 469 470 ValueNumberPair[] result = new ValueNumberPair[size]; 471 for (int i = 0; i < size; i++) { 472 result[i] = new ValueNumberPair(numbers[i]); 473 } 474 return result; 475 } 476 477 /** 478 * Return a string representation of this cell 479 * @return a string representation of this cell 480 */ 481 @Override 482 public String toString() { 483 StringBuilder s = new StringBuilder(key.toString()); 484 485 if (isTOP()) return s.append("{TOP}").toString(); 486 if (isBOTTOM()) return s.append("{BOTTOM}").toString(); 487 488 s.append("{"); 489 for (int i = 0; i < size; i++) { 490 s.append(" ").append(numbers[i]); 491 } 492 s.append("}"); 493 return s.toString(); 494 } 495 496 /** 497 * Do two sets of value number pairs differ? 498 * <p> SIDE EFFECT: sorts the sets 499 * 500 * @param set1 first set to compare 501 * @param set2 second set to compare 502 * @return true iff the two sets are different 503 */ 504 public static boolean setsDiffer(ValueNumberPair[] set1, ValueNumberPair[] set2) { 505 if ((set1 != null) && (set2 != null)) { 506 Arrays.sort(set1); 507 Arrays.sort(set2); 508 return !Arrays.equals(set1, set2); 509 } else { 510 return set1 == set2; 511 } 512 } 513 } 514}