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   *    ...&lt;op&gt;.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   *    ...&lt;op&gt;.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   *    ...&lt;op&gt;.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   *    ...&lt;op&gt;.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   *    ...&lt;op&gt;.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   *    ...&lt;op&gt;.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 -&gt; bb -&gt; out.
470   * </pre>
471   * <em> Precondition </em>: There is an edge in the control flow graph
472   * from * in -&gt; 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}