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