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.ir; 014 015import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_LOAD; 016import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_STORE; 017import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_COND_MOVE; 018import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_LOAD; 019import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_MOVE; 020import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_STORE; 021import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_COND_MOVE; 022import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_LOAD; 023import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_MOVE; 024import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_STORE; 025import static org.jikesrvm.compilers.opt.ir.Operators.GOTO; 026import static org.jikesrvm.compilers.opt.ir.Operators.GUARD_COND_MOVE; 027import static org.jikesrvm.compilers.opt.ir.Operators.GUARD_MOVE; 028import static org.jikesrvm.compilers.opt.ir.Operators.INT_COND_MOVE; 029import static org.jikesrvm.compilers.opt.ir.Operators.INT_LOAD; 030import static org.jikesrvm.compilers.opt.ir.Operators.INT_MOVE; 031import static org.jikesrvm.compilers.opt.ir.Operators.INT_STORE; 032import static org.jikesrvm.compilers.opt.ir.Operators.LONG_COND_MOVE; 033import static org.jikesrvm.compilers.opt.ir.Operators.LONG_LOAD; 034import static org.jikesrvm.compilers.opt.ir.Operators.LONG_MOVE; 035import static org.jikesrvm.compilers.opt.ir.Operators.LONG_STORE; 036import static org.jikesrvm.compilers.opt.ir.Operators.REF_COND_MOVE; 037import static org.jikesrvm.compilers.opt.ir.Operators.REF_LOAD; 038import static org.jikesrvm.compilers.opt.ir.Operators.REF_MOVE; 039import static org.jikesrvm.compilers.opt.ir.Operators.REF_STORE; 040import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_LOAD; 041import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_STORE; 042import static org.jikesrvm.compilers.opt.ir.Operators.UBYTE_LOAD; 043import static org.jikesrvm.compilers.opt.ir.Operators.USHORT_LOAD; 044 045import java.util.Enumeration; 046 047import org.jikesrvm.Configuration; 048import org.jikesrvm.VM; 049import org.jikesrvm.classloader.FieldReference; 050import org.jikesrvm.classloader.TypeReference; 051import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand; 052import org.jikesrvm.compilers.opt.ir.operand.BranchOperand; 053import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 054import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 055import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 056import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand; 057import org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand; 058import org.jikesrvm.compilers.opt.ir.operand.Operand; 059import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 060import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand; 061import org.vmmagic.unboxed.Address; 062import org.vmmagic.unboxed.Offset; 063 064/** 065 * This abstract class contains a bunch of useful static methods for 066 * performing operations on IR. 067 */ 068public abstract class IRTools { 069 070 /** 071 * Create an integer register operand for a given register. 072 * To be used in passthrough expressions like 073 * <pre> 074 * ... Load.create(INT_LOAD, I(r2), A(r1), IC(4)) ... 075 * </pre> 076 * 077 * @param reg the given register 078 * @return integer register operand 079 */ 080 public static RegisterOperand A(Register reg) { 081 return new RegisterOperand(reg, TypeReference.Address); 082 } 083 084 /** 085 * Create an integer register operand for a given register. 086 * To be used in passthrough expressions like 087 * <pre> 088 * ... Load.create(INT_LOAD, I(r2), A(r1), IC(4)) ... 089 * </pre> 090 * @param reg the given register 091 * @return integer register operand 092 */ 093 public static RegisterOperand I(Register reg) { 094 return new RegisterOperand(reg, TypeReference.Int); 095 } 096 097 /** 098 * Create a float register operand for a given register. 099 * To be used in passthrough expressions like 100 * <pre> 101 * ... Load.create(FLOAT_LOAD, F(r2), A(r1), IC(4)) ... 102 * </pre> 103 * 104 * @param reg the given register 105 * @return float register operand 106 */ 107 public static RegisterOperand F(Register reg) { 108 return new RegisterOperand(reg, TypeReference.Float); 109 } 110 111 /** 112 * Create a double register operand for a given register. 113 * To be used in passthrough expressions like 114 * <pre> 115 * ... Load.create(DOUBLE_LOAD, D(r2), A(r1), IC(4)) ... 116 * </pre> 117 * 118 * @param reg the given register 119 * @return double register operand 120 */ 121 public static RegisterOperand D(Register reg) { 122 return new RegisterOperand(reg, TypeReference.Double); 123 } 124 125 /** 126 * Create a long register operand for a given register. 127 * To be used in passthrough expressions like 128 * <pre> 129 * ... Binary.create(LONG_LOAD, L(r2), A(r1), IC(4)) ... 130 * </pre> 131 * 132 * @param reg the given register 133 * @return long register operand 134 */ 135 public static RegisterOperand L(Register reg) { 136 return new RegisterOperand(reg, TypeReference.Long); 137 } 138 139 /** 140 * Create a condition register operand for a given register. 141 * To be used in passthrough expressions like 142 * <pre> 143 * ... Binary.create(INT_CMP, CR(c2), I(r1), IC(4)) ... 144 * </pre> 145 * 146 * @param reg the given register 147 * @return condition register operand 148 */ 149 public static RegisterOperand CR(Register reg) { 150 return new RegisterOperand(reg, TypeReference.Int); 151 } 152 153 /** 154 * Create an address constant operand with a given value. 155 * To be used in passthrough expressions like 156 * <pre> 157 * ...<op>.create(...., AC(Address.zero()) ... 158 * </pre> 159 * 160 * @param value The address constant 161 * @return address constant operand 162 */ 163 public static AddressConstantOperand AC(Address value) { 164 return new AddressConstantOperand(value); 165 } 166 167 public static AddressConstantOperand AC(Offset value) { 168 return new AddressConstantOperand(value); 169 } 170 171 /** 172 * Create an integer constant operand with a given value. 173 * To be used in passthrough expressions like 174 * <pre> 175 * ...<op>.create(...., IC(0) ... 176 * </pre> 177 * 178 * @param value The int constant 179 * @return integer constant operand 180 */ 181 public static IntConstantOperand IC(int value) { 182 return new IntConstantOperand(value); 183 } 184 185 /** 186 * Create a long constant operand with a given value. 187 * To be used in passthrough expressions like 188 * <pre> 189 * ...<op>.create(...., LC(0L) ... 190 * </pre> 191 * 192 * @param value the long value 193 * @return long constant operand 194 */ 195 public static LongConstantOperand LC(long value) { 196 return new LongConstantOperand(value); 197 } 198 199 /** 200 * Create a long constant operand with a given value. 201 * To be used in passthrough expressions like 202 * <pre> 203 * ...<op>.create(...., FC(0L) ... 204 * </pre> 205 * 206 * @param value the float value 207 * @return float constant operand 208 */ 209 public static FloatConstantOperand FC(float value) { 210 return new FloatConstantOperand(value); 211 } 212 213 /** 214 * Create a long constant operand with a given value. 215 * To be used in passthrough expressions like 216 * <pre> 217 * ...<op>.create(...., DC(0L) ... 218 * </pre> 219 * 220 * @param value the double value 221 * @return double constant operand 222 */ 223 public static DoubleConstantOperand DC(double value) { 224 return new DoubleConstantOperand(value); 225 } 226 227 /** 228 * Create a new TrueGuardOperand. 229 * To be used in passthrough expressions like 230 * <pre> 231 * ...<op>.create(...., TG() ... 232 * </pre> 233 * 234 * @return true guard operand 235 */ 236 public static TrueGuardOperand TG() { 237 return new TrueGuardOperand(); 238 } 239 240 /** 241 * Generates appropriately sized constant operand for a given Offset. 242 * 243 * @param o an offset 244 * @return an instance of {@link IntConstantOperand} (32-bit) 245 * or {@link LongConstantOperand} (64-bit) 246 */ 247 public static Operand offsetOperand(Offset o) { 248 if (VM.BuildFor64Addr) { 249 return new LongConstantOperand(o.toLong()); 250 } else { 251 return new IntConstantOperand(o.toInt()); 252 } 253 } 254 255 /** 256 * Copy the position information from the source instruction to 257 * the destination instruction, returning the source instruction. 258 * To be used in passthrough expressions like 259 * <pre> 260 * instr.insertBack(CPOS(instr, Load.create(...))); 261 * </pre> 262 * 263 * @param src the instruction to copy position information from 264 * @param dst the instruction to copy position information to 265 * @return dest 266 */ 267 public static Instruction CPOS(Instruction src, Instruction dst) { 268 dst.copyPosition(src); 269 return dst; 270 } 271 272 /** 273 * Returns a constant operand with a default value for a given type 274 * 275 * @param type desired type 276 * @return a constant operand with the default value for type 277 */ 278 public static Operand getDefaultOperand(TypeReference type) { 279 if (type.isBooleanType()) return new IntConstantOperand(0); 280 if (type.isByteType()) return new IntConstantOperand(0); 281 if (type.isCharType()) return new IntConstantOperand(0); 282 if (type.isIntType()) return new IntConstantOperand(0); 283 if (type.isShortType()) return new IntConstantOperand(0); 284 if (type.isLongType()) return new LongConstantOperand(0); 285 if (type.isFloatType()) return new FloatConstantOperand(0f); 286 if (type.isDoubleType()) return new DoubleConstantOperand(0.0); 287 return new NullConstantOperand(); 288 } 289 290 /** 291 * Returns the correct operator for moving the given data type. 292 * 293 * @param type desired type to move 294 * @return the Operator to use for moving a value of the given type 295 */ 296 public static Operator getMoveOp(TypeReference type) { 297 if (type.isLongType()) return LONG_MOVE; 298 if (type.isFloatType()) return FLOAT_MOVE; 299 if (type.isDoubleType()) return DOUBLE_MOVE; 300 if (type == TypeReference.VALIDATION_TYPE) return GUARD_MOVE; 301 if (type.isReferenceType() || type.isWordLikeType()) return REF_MOVE; 302 return INT_MOVE; 303 } 304 305 /** 306 * Returns the correct operator for a conditional move with the given data 307 * type. 308 * 309 * @param type desired type to move 310 * @return the Operator to use for moving a value of the given type 311 */ 312 public static Operator getCondMoveOp(TypeReference type) { 313 if (type.isLongType()) return LONG_COND_MOVE; 314 if (type.isFloatType()) return FLOAT_COND_MOVE; 315 if (type.isDoubleType()) return DOUBLE_COND_MOVE; 316 if (type == TypeReference.VALIDATION_TYPE) return GUARD_COND_MOVE; 317 if (type.isReferenceType() || type.isWordLikeType()) return REF_COND_MOVE; 318 return INT_COND_MOVE; 319 } 320 321 /** 322 * Returns the correct operator for loading from the given field 323 * 324 * @param field field to load from 325 * @param isStatic is the field static 326 * @return the Operator to use when loading the given field 327 */ 328 public static Operator getLoadOp(FieldReference field, boolean isStatic) { 329 return getLoadOp(field.getFieldContentsType(), isStatic); 330 } 331 332 /** 333 * Returns the correct operator for loading a value of the given type 334 * 335 * @param type type of value to load 336 * @param isStatic is the field static 337 * @return the Operator to use when loading the given field 338 */ 339 public static Operator getLoadOp(TypeReference type, boolean isStatic) { 340 if (!Configuration.LittleEndian && isStatic) { 341 // Handle the statics table hold subword values in ints 342 if (type.isByteType()) return INT_LOAD; 343 if (type.isBooleanType()) return INT_LOAD; 344 if (type.isCharType()) return INT_LOAD; 345 if (type.isShortType()) return INT_LOAD; 346 } 347 if (type.isByteType()) return BYTE_LOAD; 348 if (type.isBooleanType()) return UBYTE_LOAD; 349 if (type.isCharType()) return USHORT_LOAD; 350 if (type.isShortType()) return SHORT_LOAD; 351 if (type.isLongType()) return LONG_LOAD; 352 if (type.isFloatType()) return FLOAT_LOAD; 353 if (type.isDoubleType()) return DOUBLE_LOAD; 354 if (type.isReferenceType()) return REF_LOAD; 355 if (type.isWordLikeType()) return REF_LOAD; 356 return INT_LOAD; 357 } 358 359 /** 360 * Returns the correct operator for storing to the given field. 361 * 362 * @param field The field we're asking about 363 * @param isStatic is the field static 364 * @return the Operator to use when storing to the given field 365 */ 366 public static Operator getStoreOp(FieldReference field, boolean isStatic) { 367 return getStoreOp(field.getFieldContentsType(), isStatic); 368 } 369 370 /** 371 * Returns the correct operator for storing a value of the given type 372 * 373 * @param type desired type to store 374 * @param isStatic is the field static 375 * @return the Operator to use when storing to the given field 376 */ 377 public static Operator getStoreOp(TypeReference type, boolean isStatic) { 378 if (!Configuration.LittleEndian && isStatic) { 379 // Handle the statics table hold subword values in ints 380 if (type.isByteType()) return INT_STORE; 381 if (type.isBooleanType()) return INT_STORE; 382 if (type.isCharType()) return INT_STORE; 383 if (type.isShortType()) return INT_STORE; 384 } 385 if (type.isByteType()) return BYTE_STORE; 386 if (type.isBooleanType()) return BYTE_STORE; 387 if (type.isCharType()) return SHORT_STORE; 388 if (type.isShortType()) return SHORT_STORE; 389 if (type.isLongType()) return LONG_STORE; 390 if (type.isFloatType()) return FLOAT_STORE; 391 if (type.isDoubleType()) return DOUBLE_STORE; 392 if (type.isReferenceType()) return REF_STORE; 393 if (type.isWordLikeType()) return REF_STORE; 394 return INT_STORE; 395 } 396 397 /** 398 * Generates an instruction to move the given operand into a register, and 399 * inserts it before the given instruction. 400 * 401 * @param pool register pool to allocate from 402 * @param s instruction to insert before 403 * @param op operand to copy to a register 404 * @return register operand that we copied into 405 */ 406 public static RegisterOperand moveIntoRegister(GenericRegisterPool pool, Instruction s, Operand op) { 407 if (op instanceof RegisterOperand) { 408 return (RegisterOperand) op; 409 } 410 TypeReference type = op.getType(); 411 Operator move_op = IRTools.getMoveOp(type); 412 return moveIntoRegister(type, move_op, pool, s, op); 413 } 414 415 /** 416 * Generates an instruction to move the given operand into a register, and 417 * inserts it before the given instruction. 418 * 419 * @param type type to move 420 * @param move_op move operator to use 421 * @param pool register pool to allocate from 422 * @param s instruction to insert before 423 * @param op operand to copy to a register 424 * @return last use register operand that we copied into 425 */ 426 public static RegisterOperand moveIntoRegister(TypeReference type, Operator move_op, GenericRegisterPool pool, 427 Instruction s, Operand op) { 428 RegisterOperand rop = pool.makeTemp(type); 429 s.insertBefore(Move.create(move_op, rop, op)); 430 rop = rop.copyD2U(); 431 return rop; 432 } 433 434 /** 435 * Moves the 'from' instruction to immediately before the 'to' instruction. 436 * 437 * @param from instruction to move 438 * @param to instruction after where you want it moved 439 */ 440 public static void moveInstruction(Instruction from, Instruction to) { 441 from.remove(); 442 to.insertBefore(from); 443 } 444 445 /** 446 * Inserts the instructions in the given basic block after the given 447 * instruction. 448 * 449 * @param after instruction after where you want it inserted 450 * @param temp basic block which contains the instructions to be inserted. 451 */ 452 public static void insertInstructionsAfter(Instruction after, BasicBlock temp) { 453 if (temp.isEmpty()) return; 454 Instruction after_after = after.getNext(); 455 after.linkWithNext(temp.firstRealInstruction()); 456 if (after_after == null) { 457 temp.lastRealInstruction().setNext(null); 458 } else { 459 temp.lastRealInstruction().linkWithNext(after_after); 460 } 461 } 462 463 /** 464 * Make an empty basic block on an edge in the control flow graph, 465 * and fix up the control flow graph and IR instructions accordingly. 466 * 467 * This routine will create the control struture 468 * <pre> 469 * in -> bb -> out. 470 * </pre> 471 * <em> Precondition </em>: There is an edge in the control flow graph 472 * from * in -> out. 473 * 474 * @param in the source of the control flow edge 475 * @param out the sink of the control flow edge 476 * @param ir the governing IR 477 * @return the new basic block bb 478 */ 479 public static BasicBlock makeBlockOnEdge(BasicBlock in, BasicBlock out, IR ir) { 480 // 1. Create the new basic block 481 BasicBlock bb = in.createSubBlock(out.firstInstruction().bcIndex, ir); 482 483 // 2. Splice the new basic block into the code order 484 BasicBlock next = in.nextBasicBlockInCodeOrder(); 485 if (next == null) { 486 ir.cfg.addLastInCodeOrder(bb); 487 } else { 488 ir.cfg.breakCodeOrder(in, next); 489 ir.cfg.linkInCodeOrder(in, bb); 490 ir.cfg.linkInCodeOrder(bb, next); 491 } 492 493 // 3. update in's branch instructions 494 boolean foundGoto = false; 495 BranchOperand target = bb.makeJumpTarget(); 496 BranchOperand outTarget = out.makeJumpTarget(); 497 for (Enumeration<Instruction> e = in.reverseRealInstrEnumerator(); e.hasMoreElements();) { 498 Instruction s = e.nextElement(); 499 if (IfCmp2.conforms(s)) { 500 if (IfCmp2.getTarget1(s).similar(outTarget)) { 501 IfCmp2.setTarget1(s, (BranchOperand) target.copy()); 502 } 503 if (IfCmp2.getTarget2(s).similar(outTarget)) { 504 IfCmp2.setTarget2(s, (BranchOperand) target.copy()); 505 } 506 } else if (IfCmp.conforms(s)) { 507 if (IfCmp.getTarget(s).similar(outTarget)) { 508 IfCmp.setTarget(s, (BranchOperand) target.copy()); 509 } 510 } else if (InlineGuard.conforms(s)) { 511 if (InlineGuard.getTarget(s).similar(outTarget)) { 512 InlineGuard.setTarget(s, (BranchOperand) target.copy()); 513 } 514 } else if (Goto.conforms(s)) { 515 foundGoto = true; 516 if (Goto.getTarget(s).similar(outTarget)) { 517 Goto.setTarget(s, (BranchOperand) target.copy()); 518 } 519 } else if (TableSwitch.conforms(s)) { 520 foundGoto = true; 521 if (TableSwitch.getDefault(s).similar(outTarget)) { 522 TableSwitch.setDefault(s, (BranchOperand) target.copy()); 523 } 524 for (int i = 0; i < TableSwitch.getNumberOfTargets(s); i++) { 525 if (TableSwitch.getTarget(s, i).similar(outTarget)) { 526 TableSwitch.setTarget(s, i, (BranchOperand) target.copy()); 527 } 528 } 529 } else if (LowTableSwitch.conforms(s)) { 530 foundGoto = true; 531 for (int i = 0; i < LowTableSwitch.getNumberOfTargets(s); i++) { 532 if (LowTableSwitch.getTarget(s, i).similar(outTarget)) { 533 LowTableSwitch.setTarget(s, i, (BranchOperand) target.copy()); 534 } 535 } 536 } else if (LookupSwitch.conforms(s)) { 537 foundGoto = true; 538 if (LookupSwitch.getDefault(s).similar(outTarget)) { 539 LookupSwitch.setDefault(s, (BranchOperand) target.copy()); 540 } 541 for (int i = 0; i < LookupSwitch.getNumberOfTargets(s); i++) { 542 if (LookupSwitch.getTarget(s, i).similar(outTarget)) { 543 LookupSwitch.setTarget(s, i, (BranchOperand) target.copy()); 544 } 545 } 546 } else { 547 // done processing all branches 548 break; 549 } 550 } 551 552 // 4. Add a goto bb->out 553 Instruction s = Goto.create(GOTO, out.makeJumpTarget()); 554 bb.appendInstruction(s); 555 // add goto in->next 556 // if out was not the fallthrough, add a GOTO to preserve this 557 // control flow 558 if (out != next) { 559 // if there's already a GOTO, there's no fall through 560 if (!foundGoto) { 561 /* 562 * TODO: come up with a better fix (?). 563 * 564 * This is a fix to a particular problem in dacapo xalan. 565 * 566 * We have a loop inside an exception handler, and the exception handler 567 * is empty. The loop termination condition simply falls through the 568 * exception handler to the next block. This works fine until LeaveSSA, 569 * when we split the final block and insert a GOTO to the exception handler 570 * block. When we reassemble the IR afterwards, kaboom. 571 * 572 * I would have though it better not to fall through empty exception handlers 573 * at all, and explicitly GOTO past them from the get go. RJG 4/2/7 574 */ 575 BasicBlock jumpTarget = next; 576 while (jumpTarget.isEmpty() && jumpTarget.isExceptionHandlerBasicBlock()) { 577 jumpTarget = jumpTarget.nextBasicBlockInCodeOrder(); 578 } 579 s = Goto.create(GOTO, jumpTarget.makeJumpTarget()); 580 in.appendInstruction(s); 581 } 582 } 583 584 // 5. Update the CFG 585 in.recomputeNormalOut(ir); 586 bb.recomputeNormalOut(ir); 587 588 return bb; 589 } 590 591 /** 592 * Is the operand u, which is a use in instruction s, also a def 593 * in instruction s? That is, is this operand defined as a DU operand 594 * in InstructionFormatList.dat. 595 * <p> 596 * TODO!!: This implementation is slow. Think about adding 597 * some IR support for this functionality; possibly add methods like 598 * enumeratePureDefs(), enumerateImpureUses(), etc ..., and restructure 599 * the caller to avoid having to call this function. Not going 600 * to put effort into this now, as the whole scratch register 601 * architecture has a questionable future. 602 * 603 * @param u the operand that's a use 604 * @param s the instruction that u is a use in 605 * @return {@code true} if the operand is both a use and a def 606 */ 607 public static boolean useDoublesAsDef(Operand u, Instruction s) { 608 for (Enumeration<Operand> d = s.getDefs(); d.hasMoreElements();) { 609 Operand def = d.nextElement(); 610 if (def != null) { 611 if (def == u) return true; 612 } 613 } 614 return false; 615 } 616 617 /** 618 * Is the operand d, which is a def in instruction s, also a use 619 * in instruction s? That is, is this operand defined as a DU operand 620 * in InstructionFormatList.dat. 621 * <p> 622 * TODO!!: This implementation is slow. Think about adding 623 * some IR support for this functionality; possibly add methods like 624 * enumeratePureDefs(), enumerateImpureUses(), etc ..., and restructure 625 * the caller to avoid having to call this function. Not going 626 * to put effort into this now, as the whole scratch register 627 * architecture has a questionable future. 628 * 629 * @param d the operand that's a def 630 * @param s the instruction that d is a def in 631 * @return {@code true} if the operand is both a use and a def 632 633 */ 634 public static boolean defDoublesAsUse(Operand d, Instruction s) { 635 for (Enumeration<Operand> u = s.getUses(); u.hasMoreElements();) { 636 Operand use = u.nextElement(); 637 if (use != null) { 638 if (use.similar(d)) return true; 639 } 640 } 641 return false; 642 } 643 644 public static boolean definedIn(Register r, Instruction s) { 645 for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements();) { 646 Operand op = e.nextElement(); 647 if (op != null && op.isRegister()) { 648 if (op.asRegister().getRegister().number == r.number) { 649 return true; 650 } 651 } 652 } 653 return false; 654 } 655 656 public static boolean usedIn(Register r, Instruction s) { 657 for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements();) { 658 Operand op = e.nextElement(); 659 if (op != null && op.isRegister()) { 660 if (op.asRegister().getRegister().number == r.number) { 661 return true; 662 } 663 } 664 } 665 return false; 666 } 667 668 /** 669 * Mark the parameter as nonGC and nonPEI and return it. 670 * To be used in passthrough expressions like 671 * <pre> 672 * instr.insertBack(notPEIGC(Load.create(...))); 673 * </pre> 674 * 675 * @param instr the given instruction 676 * @return the given instruction 677 */ 678 public static Instruction nonPEIGC(Instruction instr) { 679 instr.markAsNonPEINonGCPoint(); 680 return instr; 681 } 682 683 /** 684 * Might this instruction be a load from a field that is declared 685 * to be volatile? 686 * 687 * @param s the insruction to check 688 * @return <code>true</code> if the instruction might be a load 689 * from a volatile field or <code>false</code> if it 690 * cannot be a load from a volatile field 691 */ 692 public static boolean mayBeVolatileFieldLoad(Instruction s) { 693 return s.mayBeVolatileFieldLoad(); 694 } 695}