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 static org.jikesrvm.compilers.opt.driver.OptConstants.SSA_SYNTH_BCI; 016 import static org.jikesrvm.compilers.opt.ir.Operators.FENCE; 017 import static org.jikesrvm.compilers.opt.ir.Operators.PHI; 018 import static org.jikesrvm.compilers.opt.ir.Operators.READ_CEILING; 019 import static org.jikesrvm.compilers.opt.ir.Operators.UNINT_BEGIN_opcode; 020 import static org.jikesrvm.compilers.opt.ir.Operators.UNINT_END_opcode; 021 import static org.jikesrvm.compilers.opt.ir.Operators.WRITE_FLOOR; 022 023 import java.lang.reflect.Constructor; 024 import java.util.Enumeration; 025 import java.util.HashMap; 026 import java.util.HashSet; 027 import java.util.Iterator; 028 import java.util.Set; 029 import java.util.Stack; 030 031 import org.jikesrvm.VM; 032 import org.jikesrvm.classloader.TypeReference; 033 import org.jikesrvm.compilers.opt.ClassLoaderProxy; 034 import org.jikesrvm.compilers.opt.DefUse; 035 import org.jikesrvm.compilers.opt.OptOptions; 036 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 037 import org.jikesrvm.compilers.opt.controlflow.DominanceFrontier; 038 import org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode; 039 import org.jikesrvm.compilers.opt.driver.CompilerPhase; 040 import org.jikesrvm.compilers.opt.ir.Athrow; 041 import org.jikesrvm.compilers.opt.ir.Attempt; 042 import org.jikesrvm.compilers.opt.ir.BBend; 043 import org.jikesrvm.compilers.opt.ir.BasicBlock; 044 import org.jikesrvm.compilers.opt.ir.CacheOp; 045 import org.jikesrvm.compilers.opt.ir.Call; 046 import org.jikesrvm.compilers.opt.ir.IR; 047 import org.jikesrvm.compilers.opt.ir.Instruction; 048 import org.jikesrvm.compilers.opt.ir.Label; 049 import org.jikesrvm.compilers.opt.ir.MonitorOp; 050 import org.jikesrvm.compilers.opt.ir.Phi; 051 import org.jikesrvm.compilers.opt.ir.Prepare; 052 import org.jikesrvm.compilers.opt.ir.Register; 053 import org.jikesrvm.compilers.opt.ir.ResultCarrier; 054 import org.jikesrvm.compilers.opt.ir.Return; 055 import org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand; 056 import org.jikesrvm.compilers.opt.ir.operand.HeapOperand; 057 import org.jikesrvm.compilers.opt.ir.operand.Operand; 058 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 059 import org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand; 060 import org.jikesrvm.compilers.opt.liveness.LiveAnalysis; 061 import org.jikesrvm.compilers.opt.liveness.LiveSet; 062 import org.jikesrvm.compilers.opt.util.TreeNode; 063 import org.jikesrvm.util.BitVector; 064 import org.jikesrvm.util.Pair; 065 066 /** 067 * This compiler phase constructs SSA form. 068 * 069 * <p> This module constructs SSA according to the SSA properties defined 070 * in </code> IR.desiredSSAOptions </code>. See <code> SSAOptions 071 * </code> for more details on supported options for SSA construction. 072 * 073 * <p>The SSA construction algorithm is the classic dominance frontier 074 * based algorithm from Cytron et al.'s 1991 TOPLAS paper. 075 * 076 * <p> See our SAS 2000 paper 077 * <a href="http://www.research.ibm.com/jalapeno/publication.html#sas00"> 078 * Unified Analysis of Arrays and Object References in Strongly Typed 079 * Languages </a> for an overview of Array SSA form. More implementation 080 * details are documented in {@link SSA <code> SSA.java</code>}. 081 * 082 * @see SSA 083 * @see SSAOptions 084 * @see org.jikesrvm.compilers.opt.controlflow.LTDominators 085 */ 086 public class EnterSSA extends CompilerPhase { 087 /** 088 * flag to optionally print verbose debugging messages 089 */ 090 static final boolean DEBUG = false; 091 092 /** 093 * The governing IR 094 */ 095 private IR ir; 096 097 /** 098 * Cached results of liveness analysis 099 */ 100 private LiveAnalysis live; 101 102 /** 103 * A set of registers determined to span basic blocks 104 */ 105 private HashSet<Register> nonLocalRegisters; 106 107 /** 108 * The set of scalar phi functions inserted 109 */ 110 private final HashSet<Instruction> scalarPhis = new HashSet<Instruction>(); 111 112 /** 113 * For each basic block, the number of predecessors that have been 114 * processed. 115 */ 116 private int[] numPredProcessed; 117 118 /** 119 * Should this phase be performed under a guiding set of compiler 120 * options? 121 * 122 * @param options the controlling compiler options 123 * @return true iff SSA is enabled under the options 124 */ 125 @Override 126 public final boolean shouldPerform(OptOptions options) { 127 return options.SSA; 128 } 129 130 /** 131 * Constructor for this compiler phase 132 */ 133 private static final Constructor<CompilerPhase> constructor = getCompilerPhaseConstructor(EnterSSA.class); 134 135 /** 136 * Get a constructor object for this compiler phase 137 * @return compiler phase constructor 138 */ 139 @Override 140 public Constructor<CompilerPhase> getClassConstructor() { 141 return constructor; 142 } 143 144 /** 145 * Return a string identifying this compiler phase. 146 * @return "Enter SSA" 147 */ 148 @Override 149 public final String getName() { 150 return "Enter SSA"; 151 } 152 153 /** 154 * Should the IR be printed either before or after performing this phase? 155 * 156 * @param options controlling compiler options 157 * @param before true iff querying before the phase 158 * @return true or false 159 */ 160 @Override 161 public final boolean printingEnabled(OptOptions options, boolean before) { 162 return false; 163 } 164 165 /** 166 * Construct SSA form to satisfy the desired options in ir.desiredSSAOptions. 167 * This module is lazy; if the actual SSA options satisfy the desired options, 168 * then do nothing. 169 */ 170 @Override 171 public final void perform(IR ir) { 172 173 // Exit if we don't have to recompute SSA. 174 if (ir.desiredSSAOptions.getAbort()) return; 175 if (ir.actualSSAOptions != null) { 176 if (ir.actualSSAOptions.satisfies(ir.desiredSSAOptions)) { 177 return; 178 } 179 } 180 this.ir = ir; 181 boolean scalarsOnly = ir.desiredSSAOptions.getScalarsOnly(); 182 boolean backwards = ir.desiredSSAOptions.getBackwards(); 183 Set<Object> heapTypes = ir.desiredSSAOptions.getHeapTypes(); 184 boolean insertUsePhis = ir.desiredSSAOptions.getInsertUsePhis(); 185 boolean insertPEIDeps = ir.desiredSSAOptions.getInsertPEIDeps(); 186 boolean excludeGuards = ir.desiredSSAOptions.getExcludeGuards(); 187 188 // make sure the dominator computation completed successfully 189 if (!ir.HIRInfo.dominatorsAreComputed) { 190 throw new OptimizingCompilerException("Need dominators for SSA"); 191 } 192 // reset SSA dictionary information 193 ir.HIRInfo.dictionary = new SSADictionary(null, true, false, ir); 194 // initialize as needed for SSA options 195 prepare(); 196 // work around problem with PEI-generated values and handlers 197 if (true /* ir.options.UNFACTOR_FOR_SSA */) { 198 patchPEIgeneratedValues(); 199 } 200 if (ir.options.PRINT_SSA) { 201 SSA.printInstructions(ir); 202 } 203 computeSSA(ir, scalarsOnly, backwards, heapTypes, insertUsePhis, insertPEIDeps, excludeGuards); 204 // reset the SSAOptions 205 ir.actualSSAOptions = new SSAOptions(); 206 ir.actualSSAOptions.setScalarsOnly(scalarsOnly); 207 ir.actualSSAOptions.setBackwards(backwards); 208 ir.actualSSAOptions.setHeapTypes(heapTypes); 209 ir.actualSSAOptions.setInsertUsePhis(insertUsePhis); 210 ir.actualSSAOptions.setInsertPEIDeps(insertPEIDeps); 211 ir.actualSSAOptions.setExcludeGuards(excludeGuards); 212 ir.actualSSAOptions.setScalarValid(true); 213 ir.actualSSAOptions.setHeapValid(!scalarsOnly); 214 } 215 216 /** 217 * Perform some calculations to prepare for SSA construction. 218 * <ul> 219 * <li> If using pruned SSA, compute liveness. 220 * <li> If using semi-pruned SSA, compute non-local registers 221 * </ul> 222 */ 223 private void prepare() { 224 live = new LiveAnalysis(false, // don't create GC maps 225 true, // skip (final) local propagation step 226 // of live analysis 227 false, // don't store live at handlers 228 ir.desiredSSAOptions.getExcludeGuards()); 229 // don't skip guards 230 live.perform(ir); 231 } 232 233 /** 234 * Pass through the IR and calculate which registers are not 235 * local to a basic block. Store the result in the <code> nonLocalRegisters 236 * </code> field. 237 */ 238 @SuppressWarnings("unused") 239 private void computeNonLocals() { 240 nonLocalRegisters = new HashSet<Register>(20); 241 Enumeration<BasicBlock> blocks = ir.getBasicBlocks(); 242 while (blocks.hasMoreElements()) { 243 HashSet<Register> killed = new HashSet<Register>(5); 244 BasicBlock block = blocks.nextElement(); 245 Enumeration<Instruction> instrs = block.forwardRealInstrEnumerator(); 246 while (instrs.hasMoreElements()) { 247 Instruction instr = instrs.nextElement(); 248 Enumeration<Operand> uses = instr.getUses(); 249 while (uses.hasMoreElements()) { 250 Operand op = uses.nextElement(); 251 if (op instanceof RegisterOperand) { 252 if (!killed.contains(op.asRegister().getRegister())) { 253 nonLocalRegisters.add(op.asRegister().getRegister()); 254 } 255 } 256 } 257 Enumeration<Operand> defs = instr.getDefs(); 258 while (defs.hasMoreElements()) { 259 Operand op = defs.nextElement(); 260 if (op instanceof RegisterOperand) { 261 killed.add(op.asRegister().getRegister()); 262 } 263 } 264 } 265 } 266 } 267 268 /** 269 * Work around some problems with PEI-generated values and 270 * handlers. Namely, if a PEI has a return value, rename the 271 * result register before and after the PEI in order to reflect the fact 272 * that the PEI may not actually assign the result register. 273 */ 274 private void patchPEIgeneratedValues() { 275 // this only applies if there are exception handlers 276 if (!ir.hasReachableExceptionHandlers()) return; 277 278 HashSet<Pair<BasicBlock, RegisterOperand>> needed = new HashSet<Pair<BasicBlock,RegisterOperand>>(4); 279 Enumeration<BasicBlock> blocks = ir.getBasicBlocks(); 280 while (blocks.hasMoreElements()) { 281 BasicBlock block = blocks.nextElement(); 282 if (block.getExceptionalOut().hasMoreElements()) { 283 Instruction pei = block.lastRealInstruction(); 284 if (pei != null && pei.isPEI() && ResultCarrier.conforms(pei)) { 285 boolean copyNeeded = false; 286 RegisterOperand v = ResultCarrier.getResult(pei); 287 // void calls and the like... :( 288 if (v != null) { 289 Register orig = v.getRegister(); 290 { 291 Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei); 292 while (out.hasMoreElements()) { 293 BasicBlock exp = out.nextElement(); 294 LiveSet explive = live.getLiveInfo(exp).getIn(); 295 if (explive.contains(orig)) { 296 copyNeeded = true; 297 break; 298 } 299 } 300 } 301 if (copyNeeded) { 302 Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei); 303 while (out.hasMoreElements()) { 304 BasicBlock exp = out.nextElement(); 305 needed.add(new Pair<BasicBlock, RegisterOperand>(exp, v)); 306 } 307 } 308 } 309 } 310 } 311 } 312 // having determine where copies should be inserted, now insert them. 313 if (!needed.isEmpty()) { 314 for (Pair<BasicBlock, RegisterOperand> copy : needed) { 315 BasicBlock inBlock = copy.first; 316 RegisterOperand registerOp = copy.second; 317 TypeReference type = registerOp.getType(); 318 Register register = registerOp.getRegister(); 319 Register temp = ir.regpool.getReg(register); 320 inBlock.prependInstruction(SSA.makeMoveInstruction(ir, register, temp, type)); 321 Enumeration<BasicBlock> outBlocks = inBlock.getIn(); 322 while (outBlocks.hasMoreElements()) { 323 BasicBlock outBlock = outBlocks.nextElement(); 324 Instruction x = SSA.makeMoveInstruction(ir, temp, register, type); 325 SSA.addAtEnd(ir, outBlock, x, true); 326 } 327 } 328 // Recompute liveness information. You might be tempted to incrementally 329 // update it, but it's tricky, so resist.....do the obvious, but easy thing! 330 prepare(); 331 } 332 } 333 334 /** 335 * Calculate SSA form for an IR. This routine holds the guts of the 336 * transformation. 337 * 338 * @param ir the governing IR 339 * @param scalarsOnly should we compute SSA only for scalar variables? 340 * @param backwards If this is true, then every statement that 341 * can leave the procedure is considered to <em> use </em> every heap 342 * variable. This option is useful for backwards analyses such as dead 343 * store elimination. 344 * @param heapTypes If this variable is non-null, then heap array SSA 345 * form will restrict itself to this set of types. If this is null, build 346 * heap array SSA for all types. 347 * @param insertUsePhis Should we insert uphi functions for heap array 348 * SSA? ie., should we create a new name for each heap array at every use 349 * of the heap array? This option is useful for some analyses, such as 350 * our redundant load elimination algorithm. 351 * @param insertPEIDeps Should we model exceptions with an explicit 352 * heap variable for exception state? This option is useful for global 353 * code placement algorithms. 354 * @param excludeGuards Should we exclude guard registers from SSA? 355 */ 356 private void computeSSA(IR ir, boolean scalarsOnly, boolean backwards, Set<Object> heapTypes, 357 boolean insertUsePhis, boolean insertPEIDeps, boolean excludeGuards) { 358 // if reads Kill. model this with uphis. 359 if (ir.options.READS_KILL) insertUsePhis = true; 360 361 // reset Array SSA information 362 if (!scalarsOnly) { 363 ir.HIRInfo.dictionary = new SSADictionary(heapTypes, insertUsePhis, insertPEIDeps, ir); 364 } else { 365 ir.HIRInfo.dictionary = new SSADictionary(null, insertUsePhis, insertPEIDeps, ir); 366 } 367 if (DEBUG) System.out.println("Computing register lists..."); 368 369 // 1. re-compute the flow-insensitive isSSA flag for each register 370 DefUse.computeDU(ir); 371 DefUse.recomputeSSA(ir); 372 373 // 2. set up a mapping from symbolic register number to the 374 // register. !!TODO: factor this out and make it more 375 // useful. 376 Register[] symbolicRegisters = getSymbolicRegisters(); 377 378 // 3. walk through the IR, and set up BitVectors representing the defs 379 // for each symbolic register (more efficient than using register 380 // lists) 381 if (DEBUG) System.out.println("Find defs for each register..."); 382 BitVector[] defSets = getDefSets(); 383 384 // 4. Insert phi functions for scalars 385 if (DEBUG) System.out.println("Insert phi functions..."); 386 insertPhiFunctions(ir, defSets, symbolicRegisters, excludeGuards); 387 388 // 5. Insert heap variables into the Array SSA form 389 if (!scalarsOnly) { 390 insertHeapVariables(ir, backwards); 391 } 392 if (DEBUG) System.out.println("Before renaming..."); 393 if (DEBUG) SSA.printInstructions(ir); 394 if (DEBUG) System.out.println("Renaming..."); 395 renameSymbolicRegisters(symbolicRegisters); 396 397 if (!scalarsOnly) { 398 renameHeapVariables(ir); 399 } 400 if (DEBUG) System.out.println("SSA done."); 401 if (ir.options.PRINT_SSA) SSA.printInstructions(ir); 402 } 403 404 /** 405 * Insert heap variables needed for Array SSA form. 406 * 407 * @param ir the governing IR 408 * @param backwards if this is true, every statement that can leave the 409 * procedure <em> uses </em> every heap variable. 410 * This option is useful for backwards analyses 411 */ 412 private void insertHeapVariables(IR ir, boolean backwards) { 413 // insert dphi functions where needed 414 registerHeapVariables(ir); 415 416 // insert heap defs and uses for CALL instructions 417 registerCalls(ir); 418 419 // register heap uses for instructions that can leave the procedure 420 if (backwards) { 421 registerExits(ir); 422 } 423 424 // insert phi funcions where needed 425 insertHeapPhiFunctions(ir); 426 } 427 428 /** 429 * Register every instruction that can leave this method with the 430 * implicit heap array SSA look aside structure. 431 * 432 * @param ir the governing IR 433 */ 434 private void registerExits(IR ir) { 435 SSADictionary dictionary = ir.HIRInfo.dictionary; 436 for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) { 437 BasicBlock b = bbe.nextElement(); 438 for (Enumeration<Instruction> e = b.forwardInstrEnumerator(); e.hasMoreElements();) { 439 Instruction s = e.nextElement(); 440 // we already handled calls in a previous pass. 441 if (Call.conforms(s)) { 442 continue; 443 } 444 if (Return.conforms(s) || Athrow.conforms(s) || s.isPEI()) { 445 dictionary.registerExit(s, b); 446 } 447 } 448 } 449 } 450 451 /** 452 * Register every CALL instruction in this method with the 453 * implicit heap array SSA look aside structure. 454 * Namely, mark that this instruction defs and uses <em> every </em> 455 * type of heap variable in the IR's SSA dictionary. 456 * 457 * @param ir the governing IR 458 */ 459 private void registerCalls(IR ir) { 460 SSADictionary dictionary = ir.HIRInfo.dictionary; 461 for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) { 462 BasicBlock b = bbe.nextElement(); 463 for (Enumeration<Instruction> e = b.forwardInstrEnumerator(); e.hasMoreElements();) { 464 Instruction s = e.nextElement(); 465 boolean isSynch = (s.operator() == READ_CEILING) || (s.operator() == WRITE_FLOOR) || (s.operator() == FENCE); 466 if (isSynch || 467 Call.conforms(s) || 468 MonitorOp.conforms(s) || 469 Prepare.conforms(s) || 470 Attempt.conforms(s) || 471 CacheOp.conforms(s) || 472 s.isDynamicLinkingPoint()) { 473 dictionary.registerUnknown(s, b); 474 } 475 } 476 } 477 } 478 479 /** 480 * Register every instruction in this method with the 481 * implicit heap array SSA lookaside structure. 482 * 483 * @param ir the governing IR 484 */ 485 private void registerHeapVariables(IR ir) { 486 SSADictionary dictionary = ir.HIRInfo.dictionary; 487 for (Enumeration<BasicBlock> bbe = ir.getBasicBlocks(); bbe.hasMoreElements();) { 488 BasicBlock b = bbe.nextElement(); 489 for (Enumeration<Instruction> e = b.forwardInstrEnumerator(); e.hasMoreElements();) { 490 Instruction s = e.nextElement(); 491 if (s.isImplicitLoad() || 492 s.isImplicitStore() || 493 s.isAllocation() || 494 Phi.conforms(s) || 495 s.isPEI() || 496 Label.conforms(s) || 497 BBend.conforms(s) || 498 s.operator.opcode == UNINT_BEGIN_opcode || 499 s.operator.opcode == UNINT_END_opcode) { 500 dictionary.registerInstruction(s, b); 501 } 502 } 503 } 504 } 505 506 /** 507 * Insert phi functions for heap array SSA heap variables. 508 * 509 * @param ir the governing IR 510 */ 511 private void insertHeapPhiFunctions(IR ir) { 512 Iterator<HeapVariable<Object>> e = ir.HIRInfo.dictionary.getHeapVariables(); 513 while (e.hasNext()) { 514 HeapVariable<Object> H = e.next(); 515 516 if (DEBUG) System.out.println("Inserting phis for Heap " + H); 517 if (DEBUG) System.out.println("Start iterated frontier..."); 518 519 BitVector defH = H.getDefBlocks(); 520 if (DEBUG) System.out.println(H + " DEFINED IN " + defH); 521 522 BitVector needsPhi = DominanceFrontier. 523 getIteratedDominanceFrontier(ir, defH); 524 if (DEBUG) System.out.println(H + " NEEDS PHI " + needsPhi); 525 526 if (DEBUG) System.out.println("Done."); 527 for (int b = 0; b < needsPhi.length(); b++) { 528 if (needsPhi.get(b)) { 529 BasicBlock bb = ir.getBasicBlock(b); 530 ir.HIRInfo.dictionary.createHeapPhiInstruction(bb, H); 531 } 532 } 533 } 534 } 535 536 /** 537 * Calculate the set of blocks that contain defs for each 538 * symbolic register in an IR. <em> Note: </em> This routine skips 539 * registers marked already having a single static 540 * definition, physical registers, and guard registeres. 541 * 542 * @return an array of BitVectors, where element <em>i</em> represents the 543 * basic blocks that contain defs for symbolic register <em>i</em> 544 */ 545 private BitVector[] getDefSets() { 546 int nBlocks = ir.getMaxBasicBlockNumber(); 547 BitVector[] result = new BitVector[ir.getNumberOfSymbolicRegisters()]; 548 549 for (int i = 0; i < result.length; i++) { 550 result[i] = new BitVector(nBlocks + 1); 551 } 552 553 // loop over each basic block 554 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { 555 BasicBlock bb = e.nextElement(); 556 int bbNumber = bb.getNumber(); 557 // visit each instruction in the basic block 558 for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) { 559 Instruction s = ie.nextElement(); 560 // record each def in the instruction 561 // skip SSA defs 562 for (int j = 0; j < s.getNumberOfDefs(); j++) { 563 Operand operand = s.getOperand(j); 564 if (operand == null) continue; 565 if (!operand.isRegister()) continue; 566 if (operand.asRegister().getRegister().isSSA()) continue; 567 if (operand.asRegister().getRegister().isPhysical()) continue; 568 569 int reg = operand.asRegister().getRegister().getNumber(); 570 result[reg].set(bbNumber); 571 } 572 } 573 } 574 return result; 575 } 576 577 /** 578 * Insert the necessary phi functions into an IR. 579 * <p> Algorithm: 580 * <p>For register r, let S be the set of all blocks that 581 * contain defs of r. Let D be the iterated dominance frontier 582 * of S. Each block in D needs a phi-function for r. 583 * 584 * <p> Special Java case: if node N dominates all defs of r, then N 585 * does not need a phi-function for r 586 * 587 * @param ir the governing IR 588 * @param defs defs[i] represents the basic blocks that define 589 * symbolic register i. 590 * @param symbolics symbolics[i] is symbolic register number i 591 */ 592 private void insertPhiFunctions(IR ir, BitVector[] defs, Register[] symbolics, boolean excludeGuards) { 593 for (int r = 0; r < defs.length; r++) { 594 if (symbolics[r] == null) continue; 595 if (symbolics[r].isSSA()) continue; 596 if (symbolics[r].isPhysical()) continue; 597 if (excludeGuards && symbolics[r].isValidation()) continue; 598 if (DEBUG) System.out.println("Inserting phis for register " + r); 599 if (DEBUG) System.out.println("Start iterated frontier..."); 600 BitVector needsPhi = DominanceFrontier.getIteratedDominanceFrontier(ir, defs[r]); 601 removePhisThatDominateAllDefs(needsPhi, ir, defs[r]); 602 if (DEBUG) System.out.println("Done."); 603 604 for (int b = 0; b < needsPhi.length(); b++) { 605 if (needsPhi.get(b)) { 606 BasicBlock bb = ir.getBasicBlock(b); 607 if (live.getLiveInfo(bb).getIn().contains(symbolics[r])) { 608 insertPhi(bb, symbolics[r]); 609 } 610 } 611 } 612 } 613 } 614 615 /** 616 * If node N dominates all defs of a register r, then N does 617 * not need a phi function for r; this function removes such 618 * nodes N from a Bit Set. 619 * 620 * @param needsPhi representation of set of nodes that 621 * need phi functions for a register r 622 * @param ir the governing IR 623 * @param defs set of nodes that define register r 624 */ 625 private void removePhisThatDominateAllDefs(BitVector needsPhi, IR ir, BitVector defs) { 626 for (int i = 0; i < needsPhi.length(); i++) { 627 if (!needsPhi.get(i)) { 628 continue; 629 } 630 if (ir.HIRInfo.dominatorTree.dominates(i, defs)) { 631 needsPhi.clear(i); 632 } 633 } 634 } 635 636 /** 637 * Insert a phi function for a symbolic register at the head 638 * of a basic block. 639 * 640 * @param bb the basic block 641 * @param r the symbolic register that needs a phi function 642 */ 643 private void insertPhi(BasicBlock bb, Register r) { 644 Instruction s = makePhiInstruction(r, bb); 645 bb.firstInstruction().insertAfter(s); 646 scalarPhis.add(s); 647 } 648 649 /** 650 * Create a phi-function instruction 651 * 652 * @param r the symbolic register 653 * @param bb the basic block holding the new phi function 654 * @return the instruction r = PHI null,null,..,null 655 */ 656 private Instruction makePhiInstruction(Register r, BasicBlock bb) { 657 int n = bb.getNumberOfIn(); 658 Enumeration<BasicBlock> in = bb.getIn(); 659 TypeReference type = null; 660 Instruction s = Phi.create(PHI, new RegisterOperand(r, type), n); 661 for (int i = 0; i < n; i++) { 662 RegisterOperand junk = new RegisterOperand(r, type); 663 Phi.setValue(s, i, junk); 664 BasicBlock pred = in.nextElement(); 665 Phi.setPred(s, i, new BasicBlockOperand(pred)); 666 } 667 s.position = ir.gc.inlineSequence; 668 s.bcIndex = SSA_SYNTH_BCI; 669 return s; 670 } 671 672 /** 673 * Set up a mapping from symbolic register number to the register. 674 * <p> TODO: put this functionality elsewhere. 675 * 676 * @return a mapping 677 */ 678 private Register[] getSymbolicRegisters() { 679 Register[] map = new Register[ir.getNumberOfSymbolicRegisters()]; 680 for (Register reg = ir.regpool.getFirstSymbolicRegister(); reg != null; reg = reg.getNext()) { 681 int number = reg.getNumber(); 682 map[number] = reg; 683 } 684 return map; 685 } 686 687 /** 688 * Rename the symbolic registers so that each register has only one 689 * definition. 690 * 691 * <p><em> Note </em>: call this after phi functions have been inserted. 692 * <p> <b> Algorithm:</b> from Cytron et. al 91 693 * <pre> 694 * call search(entry) 695 * 696 * search(X): 697 * for each statement A in X do 698 * if A is not-phi 699 * for each r in RHS(A) do 700 * if !r.isSSA, replace r with TOP(S(r)) 701 * done 702 * fi 703 * for each r in LHS(A) do 704 * if !r.isSSA 705 * r2 = new temp register 706 * push r2 onto S(r) 707 * replace r in A by r2 708 * fi 709 * done 710 * done (end of first loop) 711 * for each Y in succ(X) do 712 * j <- whichPred(Y,X) 713 * for each phi-function F in Y do 714 * replace the j-th operand (r) in RHS(F) with TOP(S(r)) 715 * done 716 * done (end of second loop) 717 * for each Y in Children(X) do 718 * call search(Y) 719 * done (end of third loop) 720 * for each assignment A in X do 721 * for each r in LHS(A) do 722 * pop(S(r)) 723 * done 724 * done (end of fourth loop) 725 * end 726 * <pre> 727 * 728 * @param symbolicRegisters mapping from integer to symbolic registers 729 */ 730 private void renameSymbolicRegisters(Register[] symbolicRegisters) { 731 int n = ir.getNumberOfSymbolicRegisters(); 732 @SuppressWarnings("unchecked") // the old covariant array-type problem 733 Stack<RegisterOperand>[] S = new Stack[n + 1]; 734 for (int i = 0; i < S.length; i++) { 735 S[i] = new Stack<RegisterOperand>(); 736 // populate the Stacks with initial names for 737 // each parameter, and push "null" for other symbolic registers 738 if (i >= symbolicRegisters.length) continue; 739 //Register r = symbolicRegisters[i]; 740 // If a register's name is "null", that means the 741 // register has not yet been defined. 742 S[i].push(null); 743 } 744 BasicBlock entry = ir.cfg.entry(); 745 DefUse.clearDU(ir); 746 numPredProcessed = new int[ir.getMaxBasicBlockNumber()]; 747 search(entry, S); 748 DefUse.recomputeSSA(ir); 749 rectifyPhiTypes(); 750 } 751 752 /** 753 * This routine is the guts of the SSA construction phase for scalars. See 754 * renameSymbolicRegisters for more details. 755 * 756 * @param X basic block to search dominator tree from 757 * @param S stack of names for each register 758 */ 759 private void search(BasicBlock X, Stack<RegisterOperand>[] S) { 760 if (DEBUG) System.out.println("SEARCH " + X); 761 for (Enumeration<Instruction> ie = X.forwardInstrEnumerator(); ie.hasMoreElements();) { 762 Instruction A = ie.nextElement(); 763 if (A.operator() != PHI) { 764 // replace each use 765 for (int u = A.getNumberOfDefs(); u < A.getNumberOfOperands(); u++) { 766 Operand op = A.getOperand(u); 767 if (op instanceof RegisterOperand) { 768 RegisterOperand rop = (RegisterOperand) op; 769 Register r1 = rop.getRegister(); 770 if (r1.isSSA()) continue; 771 if (r1.isPhysical()) continue; 772 RegisterOperand r2 = S[r1.getNumber()].peek(); 773 if (DEBUG) System.out.println("REPLACE NORMAL USE " + r1 + " with " + r2); 774 if (r2 != null) { 775 rop.setRegister(r2.getRegister()); 776 DefUse.recordUse(rop); 777 } 778 } 779 } 780 } 781 // replace each def 782 for (int d = 0; d < A.getNumberOfDefs(); d++) { 783 Operand op = A.getOperand(d); 784 if (op instanceof RegisterOperand) { 785 RegisterOperand rop = (RegisterOperand) op; 786 Register r1 = rop.getRegister(); 787 if (r1.isSSA()) continue; 788 if (r1.isPhysical()) continue; 789 Register r2 = ir.regpool.getReg(r1); 790 if (DEBUG) System.out.println("PUSH " + r2 + " FOR " + r1 + " BECAUSE " + A); 791 S[r1.getNumber()].push(new RegisterOperand(r2, rop.getType())); 792 rop.setRegister(r2); 793 r2.scratchObject = r1; 794 } 795 } 796 } // end of first loop 797 798 if (DEBUG) System.out.println("SEARCH (second loop) " + X); 799 for (Enumeration<BasicBlock> y = X.getOut(); y.hasMoreElements();) { 800 BasicBlock Y = y.nextElement(); 801 if (DEBUG) System.out.println(" Successor: " + Y); 802 int j = numPredProcessed[Y.getNumber()]++; 803 if (Y.isExit()) continue; 804 Instruction s = Y.firstRealInstruction(); 805 if (s == null) continue; 806 // replace use USE in each PHI instruction 807 if (DEBUG) System.out.println(" Predecessor: " + j); 808 while (s.operator() == PHI) { 809 Operand val = Phi.getValue(s, j); 810 if (val.isRegister()) { 811 Register r1 = ((RegisterOperand) Phi.getValue(s, j)).getRegister(); 812 // ignore registers already marked SSA by a previous pass 813 if (!r1.isSSA()) { 814 RegisterOperand r2 = S[r1.getNumber()].peek(); 815 if (r2 == null) { 816 // in this case, the register is never defined along 817 // this particular control flow path into the basic 818 // block. 819 Phi.setValue(s, j, new UnreachableOperand()); 820 } else { 821 RegisterOperand rop = r2.copyRO(); 822 Phi.setValue(s, j, rop); 823 DefUse.recordUse(rop); 824 } 825 Phi.setPred(s, j, new BasicBlockOperand(X)); 826 } 827 } 828 s = s.nextInstructionInCodeOrder(); 829 } 830 } // end of second loop 831 832 if (DEBUG) System.out.println("SEARCH (third loop) " + X); 833 for (Enumeration<TreeNode> c = ir.HIRInfo.dominatorTree.getChildren(X); c.hasMoreElements();) { 834 DominatorTreeNode v = (DominatorTreeNode) c.nextElement(); 835 search(v.getBlock(), S); 836 } // end of third loop 837 838 if (DEBUG) System.out.println("SEARCH (fourth loop) " + X); 839 for (Enumeration<Instruction> a = X.forwardInstrEnumerator(); a.hasMoreElements();) { 840 Instruction A = a.nextElement(); 841 // loop over each def 842 for (int d = 0; d < A.getNumberOfDefs(); d++) { 843 Operand newOp = A.getOperand(d); 844 if (newOp == null) continue; 845 if (!newOp.isRegister()) continue; 846 Register newReg = newOp.asRegister().getRegister(); 847 if (newReg.isSSA()) continue; 848 if (newReg.isPhysical()) continue; 849 Register r1 = (Register) newReg.scratchObject; 850 S[r1.getNumber()].pop(); 851 if (DEBUG) System.out.println("POP " + r1); 852 } 853 } // end of fourth loop 854 if (DEBUG) System.out.println("FINISHED SEARCH " + X); 855 } 856 857 /** 858 * Rename the implicit heap variables in the SSA form so that 859 * each heap variable has only one definition. 860 * 861 * <p> Algorithm: Cytron et. al 91 (see renameSymbolicRegisters) 862 * 863 * @param ir the governing IR 864 */ 865 private void renameHeapVariables(IR ir) { 866 int n = ir.HIRInfo.dictionary.getNumberOfHeapVariables(); 867 if (n == 0) { 868 return; 869 } 870 // we maintain a stack of names for each type of heap variable 871 // stacks implements a mapping from type to Stack. 872 // Example: to get the stack of names for HEAP<int> variables, 873 // use stacks.get(ClassLoaderProxy.IntType); 874 HashMap<Object, Stack<HeapOperand<Object>>> stacks = new HashMap<Object, Stack<HeapOperand<Object>>>(n); 875 // populate the stacks variable with the initial heap variable 876 // names, currently stored in the SSADictionary 877 for (Iterator<HeapVariable<Object>> e = ir.HIRInfo.dictionary.getHeapVariables(); e.hasNext();) { 878 HeapVariable<Object> H = e.next(); 879 Stack<HeapOperand<Object>> S = new Stack<HeapOperand<Object>>(); 880 S.push(new HeapOperand<Object>(H)); 881 Object heapType = H.getHeapType(); 882 stacks.put(heapType, S); 883 } 884 BasicBlock entry = ir.cfg.entry(); 885 numPredProcessed = new int[ir.getMaxBasicBlockNumber()]; 886 search2(entry, stacks); 887 // registerRenamedHeapPhis(ir); 888 } 889 890 /** 891 * This routine is the guts of the SSA construction phase for heap array 892 * SSA. The renaming algorithm is analagous to the algorithm for 893 * scalars See <code> renameSymbolicRegisters </code> for more details. 894 * 895 * @param X the current basic block being traversed 896 * @param stacks a structure holding the current names for each heap 897 * variable 898 * used and defined by each instruction. 899 */ 900 private void search2(BasicBlock X, HashMap<Object, Stack<HeapOperand<Object>>> stacks) { 901 if (DEBUG) System.out.println("SEARCH2 " + X); 902 SSADictionary dictionary = ir.HIRInfo.dictionary; 903 for (Enumeration<Instruction> ie = dictionary.getAllInstructions(X); ie.hasMoreElements();) { 904 Instruction A = ie.nextElement(); 905 if (!dictionary.usesHeapVariable(A) && !dictionary.defsHeapVariable(A)) continue; 906 if (A.operator() != PHI) { 907 // replace the Heap variables USED by this instruction 908 HeapOperand<Object>[] uses = dictionary.getHeapUses(A); 909 if (uses != null) { 910 @SuppressWarnings("unchecked") // Generic array problem 911 HeapOperand<Object>[] newUses = new HeapOperand[uses.length]; 912 for (int i = 0; i < uses.length; i++) { 913 Stack<HeapOperand<Object>> S = stacks.get(uses[i].getHeapType()); 914 newUses[i] = S.peek().copy(); 915 if (DEBUG) { 916 System.out.println("NORMAL USE PEEK " + newUses[i]); 917 } 918 } 919 dictionary.replaceUses(A, newUses); 920 } 921 } 922 // replace any Heap variable DEF 923 if (A.operator() != PHI) { 924 HeapOperand<Object>[] defs = dictionary.getHeapDefs(A); 925 if (defs != null) { 926 for (HeapOperand<Object> operand : dictionary.replaceDefs(A, X)) { 927 Stack<HeapOperand<Object>> S = stacks.get(operand.getHeapType()); 928 S.push(operand); 929 if (DEBUG) System.out.println("PUSH " + operand + " FOR " + operand.getHeapType()); 930 } 931 } 932 } else { 933 HeapOperand<Object>[] r = dictionary.replaceDefs(A, X); 934 Stack<HeapOperand<Object>> S = stacks.get(r[0].getHeapType()); 935 S.push(r[0]); 936 if (DEBUG) System.out.println("PUSH " + r[0] + " FOR " + r[0].getHeapType()); 937 } 938 } // end of first loop 939 940 for (Enumeration<BasicBlock> y = X.getOut(); y.hasMoreElements();) { 941 BasicBlock Y = y.nextElement(); 942 if (Y.isExit()) continue; 943 int j = numPredProcessed[Y.getNumber()]++; 944 // replace each USE in each HEAP-PHI function for Y 945 for (Iterator<Instruction> hp = dictionary.getHeapPhiInstructions(Y); hp.hasNext();) { 946 Instruction s = hp.next(); 947 @SuppressWarnings("unchecked") // Down-cast to a generic type 948 HeapOperand<Object> H1 = (HeapOperand) Phi.getResult(s); 949 Stack<HeapOperand<Object>> S = stacks.get(H1.getHeapType()); 950 HeapOperand<Object> H2 = S.peek(); 951 Phi.setValue(s, j, new HeapOperand<Object>(H2.getHeapVariable())); 952 Phi.setPred(s, j, new BasicBlockOperand(X)); 953 } 954 } // end of second loop 955 956 for (Enumeration<TreeNode> c = ir.HIRInfo.dominatorTree.getChildren(X); c.hasMoreElements();) { 957 DominatorTreeNode v = (DominatorTreeNode) c.nextElement(); 958 search2(v.getBlock(), stacks); 959 } // end of third loop 960 961 for (Enumeration<Instruction> a = dictionary.getAllInstructions(X); a.hasMoreElements();) { 962 Instruction A = a.nextElement(); 963 if (!dictionary.usesHeapVariable(A) && !dictionary.defsHeapVariable(A)) continue; 964 // retrieve the Heap Variables defined by A 965 if (A.operator != PHI) { 966 HeapOperand<Object>[] defs = dictionary.getHeapDefs(A); 967 if (defs != null) { 968 for (HeapOperand<Object> def : defs) { 969 Stack<HeapOperand<Object>> S = stacks.get(def.getHeapType()); 970 S.pop(); 971 if (DEBUG) System.out.println("POP " + def.getHeapType()); 972 } 973 } 974 } else { 975 @SuppressWarnings("unchecked") // Down-cast to a generic type 976 HeapOperand<Object> H = (HeapOperand) Phi.getResult(A); 977 Stack<HeapOperand<Object>> S = stacks.get(H.getHeapType()); 978 S.pop(); 979 if (DEBUG) System.out.println("POP " + H.getHeapType()); 980 } 981 } // end of fourth loop 982 if (DEBUG) System.out.println("END SEARCH2 " + X); 983 } 984 985 /** 986 * After performing renaming on heap phi functions, this 987 * routines notifies the SSA dictionary of the new names. 988 * <p> 989 * FIXME - this was commented out: delete it ?? RJG 990 * 991 * @param ir the governing IR 992 */ 993 @SuppressWarnings({"unused", "unchecked"}) 994 // HeapOperand requires casts to a generic type 995 private void registerRenamedHeapPhis(IR ir) { 996 SSADictionary ssa = ir.HIRInfo.dictionary; 997 for (Enumeration<BasicBlock> e1 = ir.getBasicBlocks(); e1.hasMoreElements();) { 998 BasicBlock bb = e1.nextElement(); 999 for (Enumeration<Instruction> e2 = ssa.getAllInstructions(bb); e2.hasMoreElements();) { 1000 Instruction s = e2.nextElement(); 1001 if (Phi.conforms(s)) { 1002 if (ssa.defsHeapVariable(s)) { 1003 int n = Phi.getNumberOfValues(s); 1004 HeapOperand<Object>[] uses = new HeapOperand[n]; 1005 for (int i = 0; i < n; i++) { 1006 uses[i] = (HeapOperand) Phi.getValue(s, i); 1007 } 1008 ssa.replaceUses(s, uses); 1009 } 1010 } 1011 } 1012 } 1013 } 1014 1015 /** 1016 * Store a copy of the Heap variables each instruction defs. 1017 * 1018 * @param ir governing IR 1019 * @param store place to store copies 1020 */ 1021 @SuppressWarnings("unused") 1022 private void copyHeapDefs(IR ir, HashMap<Instruction, HeapOperand<?>[]> store) { 1023 SSADictionary dictionary = ir.HIRInfo.dictionary; 1024 for (Enumeration<BasicBlock> be = ir.forwardBlockEnumerator(); be.hasMoreElements();) { 1025 BasicBlock bb = be.nextElement(); 1026 for (Enumeration<Instruction> e = dictionary.getAllInstructions(bb); e.hasMoreElements();) { 1027 Instruction s = e.nextElement(); 1028 store.put(s, ir.HIRInfo.dictionary.getHeapDefs(s)); 1029 } 1030 } 1031 } 1032 1033 /* 1034 * Compute type information for operands in each phi instruction. 1035 * 1036 * PRECONDITION: Def-use chains computed. 1037 * SIDE EFFECT: empties the scalarPhis set 1038 * SIDE EFFECT: bashes the Instruction scratch field. 1039 */ 1040 private static final int NO_NULL_TYPE = 0; 1041 private static final int FOUND_NULL_TYPE = 1; 1042 1043 private void rectifyPhiTypes() { 1044 if (DEBUG) System.out.println("Rectify phi types."); 1045 removeAllUnreachablePhis(scalarPhis); 1046 while (!scalarPhis.isEmpty()) { 1047 boolean didSomething = false; 1048 for (Iterator<Instruction> i = scalarPhis.iterator(); i.hasNext();) { 1049 Instruction phi = i.next(); 1050 phi.scratch = NO_NULL_TYPE; 1051 if (DEBUG) System.out.println("PHI: " + phi); 1052 TypeReference meet = meetPhiType(phi); 1053 if (DEBUG) System.out.println("MEET: " + meet); 1054 if (meet != null) { 1055 didSomething = true; 1056 if (phi.scratch == NO_NULL_TYPE) i.remove(); 1057 RegisterOperand result = (RegisterOperand) Phi.getResult(phi); 1058 result.setType(meet); 1059 for (Enumeration<RegisterOperand> e = DefUse.uses(result.getRegister()); e.hasMoreElements();) { 1060 RegisterOperand rop = e.nextElement(); 1061 if (rop.getType() != meet) { 1062 rop.clearPreciseType(); 1063 rop.setType(meet); 1064 } 1065 } 1066 } 1067 } 1068 if (!didSomething) { 1069 // iteration has bottomed out. 1070 return; 1071 } 1072 } 1073 } 1074 1075 /** 1076 * Remove all phis that are unreachable 1077 */ 1078 private void removeAllUnreachablePhis(HashSet<Instruction> scalarPhis) { 1079 boolean iterateAgain = false; 1080 do { 1081 iterateAgain = false; 1082 outer: 1083 for (Iterator<Instruction> i = scalarPhis.iterator(); i.hasNext();) { 1084 Instruction phi = i.next(); 1085 for (int j = 0; j < Phi.getNumberOfValues(phi); j++) { 1086 Operand op = Phi.getValue(phi, j); 1087 if (!(op instanceof UnreachableOperand)) { 1088 continue outer; 1089 } 1090 } 1091 RegisterOperand result = Phi.getResult(phi).asRegister(); 1092 i.remove(); 1093 for (Enumeration<RegisterOperand> e = DefUse.uses(result.getRegister()); e.hasMoreElements();) { 1094 RegisterOperand use = e.nextElement(); 1095 Instruction s = use.instruction; 1096 if (Phi.conforms(s)) { 1097 for (int k = 0; k < Phi.getNumberOfValues(phi); k++) { 1098 Operand op = Phi.getValue(phi, k); 1099 if (op != null && op.similar(result)) { 1100 Phi.setValue(phi, k, new UnreachableOperand()); 1101 iterateAgain = true; 1102 } 1103 } 1104 } 1105 } 1106 } 1107 } while (iterateAgain); 1108 } 1109 1110 /** 1111 * Remove all unreachable operands from scalar phi functions<p> 1112 * 1113 * NOT CURRENTLY USED 1114 */ 1115 @SuppressWarnings("unused") 1116 private void removeUnreachableOperands(HashSet<Instruction> scalarPhis) { 1117 for (Instruction phi : scalarPhis) { 1118 boolean didSomething = true; 1119 while (didSomething) { 1120 didSomething = false; 1121 for (int j = 0; j < Phi.getNumberOfValues(phi); j++) { 1122 Operand v = Phi.getValue(phi, j); 1123 if (v instanceof UnreachableOperand) { 1124 // rewrite the phi instruction to remove the unreachable 1125 // operand 1126 didSomething = true; 1127 Instruction tmpPhi = phi.copyWithoutLinks(); 1128 Phi.mutate(phi, PHI, Phi.getResult(tmpPhi), Phi.getNumberOfValues(phi) - 1); 1129 int m = 0; 1130 for (int k = 0; k < Phi.getNumberOfValues(phi); k++) { 1131 if (k == j) continue; 1132 Phi.setValue(phi, m, Phi.getValue(tmpPhi, k)); 1133 Phi.setPred(phi, m, Phi.getPred(tmpPhi, k)); 1134 m++; 1135 } 1136 } 1137 } 1138 } 1139 } 1140 } 1141 1142 /** 1143 * Return the meet of the types on the rhs of a phi instruction 1144 * <p> 1145 * SIDE EFFECT: bashes the Instruction scratch field. 1146 * 1147 * @param s phi instruction 1148 */ 1149 private static TypeReference meetPhiType(Instruction s) { 1150 1151 TypeReference result = null; 1152 for (int i = 0; i < Phi.getNumberOfValues(s); i++) { 1153 Operand val = Phi.getValue(s, i); 1154 if (val instanceof UnreachableOperand) continue; 1155 TypeReference t = val.getType(); 1156 if (t == null) { 1157 s.scratch = FOUND_NULL_TYPE; 1158 } else if (result == null) { 1159 result = t; 1160 } else { 1161 TypeReference meet = ClassLoaderProxy.findCommonSuperclass(result, t); 1162 if (meet == null) { 1163 // TODO: This horrific kludge should go away once we get rid of Address.toInt() 1164 if ((result.isIntLikeType() && (t.isReferenceType() || t.isWordLikeType())) || 1165 ((result.isReferenceType() || result.isWordLikeType()) && t.isIntLikeType())) { 1166 meet = TypeReference.Int; 1167 } else if (result.isReferenceType() && t.isWordLikeType()) { 1168 meet = t; 1169 } else if (result.isWordLikeType() && t.isReferenceType()) { 1170 meet = result; 1171 } 1172 } 1173 if (VM.VerifyAssertions && meet == null) { 1174 VM._assert(VM.NOT_REACHED, result + " and " + t + " meet to null"); 1175 } 1176 result = meet; 1177 } 1178 } 1179 return result; 1180 } 1181 1182 /** 1183 * Find a parameter type. 1184 * 1185 * <p> Given a register that holds a parameter, look at the register's 1186 * use chain to find the type of the parameter 1187 */ 1188 @SuppressWarnings("unused") 1189 private TypeReference findParameterType(Register p) { 1190 RegisterOperand firstUse = p.useList; 1191 if (firstUse == null) { 1192 return null; // parameter has no uses 1193 } 1194 return firstUse.getType(); 1195 } 1196 } 1197 1198 1199