/**
  * Given a symbolic register, return a code that gives the physical register type to hold the
  * value of the symbolic register.
  *
  * @param r a symbolic register
  * @return one of INT_REG, DOUBLE_REG
  */
 public static int getPhysicalRegisterType(Register r) {
   if (r.isInteger() || r.isLong() || r.isAddress()) {
     return INT_REG;
   } else if (r.isFloatingPoint()) {
     return DOUBLE_REG;
   } else {
     throw new OptimizingCompilerException("getPhysicalRegisterType " + " unexpected " + r);
   }
 }
Exemple #2
0
 /**
  * @param type one of INT_VALUE, FLOAT_VALUE, or DOUBLE_VALUE
  * @return the move operator for a type of value.
  */
 private static Operator getMoveOperator(Register type) {
   if (type.isNatural()) {
     return IA32_MOV;
   } else if (type.isDouble()) {
     return SSE2_FULL ? IA32_MOVSD : IA32_FMOV;
   } else if (type.isFloat()) {
     return SSE2_FULL ? IA32_MOVSS : IA32_FMOV;
   } else {
     OptimizingCompilerException.TODO("getMoveOperator: unsupported: " + type);
     return null;
   }
 }
Exemple #3
0
 /**
  * @param type one of INT_VALUE, FLOAT_VALUE, or DOUBLE_VALUE
  * @return the size of a type of value, in bytes. NOTE: For the purpose of register allocation, an
  *     x87 FLOAT_VALUE is 64 bits!
  */
 private static byte getSizeOfType(Register type) {
   if (type.isNatural()) {
     if (VM.BuildFor64Addr && type.isInteger()) {
       return (byte) BYTES_IN_INT;
     } else {
       return (byte) WORDSIZE;
     }
   } else if (type.isFloat()) {
     if (SSE2_FULL) return (byte) BYTES_IN_FLOAT;
     return (byte) BYTES_IN_DOUBLE;
   } else if (type.isDouble()) {
     return (byte) BYTES_IN_DOUBLE;
   } else {
     OptimizingCompilerException.TODO("getSizeOfValue: unsupported: " + type);
     return (byte) -1;
   }
 }
 /**
  * Bypass MOVE instructions that def an operand: return the first def in the chain that is not the
  * result of a MOVE instruction.
  *
  * <p>Note: treat PI instructions like MOVES
  *
  * @param op the RegisterOperand
  */
 private Operand bypassMoves(Operand op) {
   if (!op.isRegister()) return op;
   Register r = op.asRegister().getRegister();
   Instruction def = r.getFirstDef();
   if (def == null) {
     return op;
   }
   if (r.isPhysical()) {
     return op;
   }
   if (Move.conforms(def)) {
     //   In a perfect world, this shouldn't happen. Copy propagation
     //   in SSA form should remove all 'normal' moves.
     //   We can't simply bypass this move, since it may lead to
     //   infinite mutual recursion.
     return op;
   } else if (def.operator == PI) {
     return bypassMoves(GuardedUnary.getVal(def));
   } else {
     return op;
   }
 }
Exemple #5
0
 @Override
 public void insertUnspillBefore(Instruction s, Register r, Register type, int location) {
   Operator move = getMoveOperator(type);
   byte size = getSizeOfType(type);
   RegisterOperand rOp;
   if (type.isFloat()) {
     rOp = F(r);
   } else if (type.isDouble()) {
     rOp = D(r);
   } else {
     if (VM.BuildFor64Addr && type.isInteger()) {
       rOp = new RegisterOperand(r, TypeReference.Int);
     } else {
       rOp = new RegisterOperand(r, PRIMITIVE_TYPE_FOR_WORD);
     }
   }
   StackLocationOperand spillLoc = new StackLocationOperand(true, -location, size);
   Instruction unspillOp = MIR_Move.create(move, rOp, spillLoc);
   if (VERBOSE_DEBUG) {
     System.out.println("INSERT_UNSPILL_BEFORE: " + "Inserting " + unspillOp + " before " + s);
   }
   s.insertBefore(unspillOp);
 }
 @Test
 public void assignCausesAssignmentOfTheIntervalsRegisterToTheGivenRegister() {
   Register r = new Register(0);
   CompoundInterval ci = new CompoundInterval(DEFAULT_BEGIN, DEFAULT_END, r);
   Register s = new Register(1);
   RegisterAllocatorState regAllocState = new RegisterAllocatorState(0);
   assertThat(ci.isAssigned(regAllocState), is(false));
   assertNull(ci.getAssignment(regAllocState));
   ci.assign(s);
   assertThat(s.mapsToRegister, is(r));
   assertThat(!s.isSpilled() && s.isTouched() && s.isAllocated(), is(true));
   assertThat(r.mapsToRegister, is(s));
   assertThat(!r.isSpilled() && r.isTouched() && r.isAllocated(), is(true));
   assertThat(ci.isAssigned(regAllocState), is(true));
   assertThat(ci.getAssignment(regAllocState), is(s));
 }
Exemple #7
0
  @Override
  public boolean needScratch(Register r, Instruction s) {
    // We never need a scratch register for a floating point value in an
    // FMOV instruction.
    if (r.isFloatingPoint() && s.operator() == IA32_FMOV) return false;

    // never need a scratch register for a YIELDPOINT_OSR
    if (s.operator() == YIELDPOINT_OSR) return false;

    // Some MOVEs never need scratch registers
    if (isScratchFreeMove(s)) return false;

    // If s already has a memory operand, it is illegal to introduce
    // another.
    if (s.hasMemoryOperand()) return true;

    // If r appears more than once in the instruction, we can't
    // use a memory operand for all occurrences, so we will need a scratch
    int count = 0;
    for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements(); ) {
      Operand op = ops.nextElement();
      if (op.isRegister()) {
        RegisterOperand rop = op.asRegister();
        if (rop.getRegister() == r) {
          count++;
        }
      }
    }
    if (count > 1) return true;

    // Check the architecture restrictions.
    if (RegisterRestrictions.mustBeInRegister(r, s)) return true;

    // Otherwise, everything is OK.
    return false;
  }
Exemple #8
0
  @Override
  public void computeNonVolatileArea() {
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();

    if (ir.compiledMethod.isSaveVolatile()) {
      // Record that we use every nonvolatile GPR
      int numGprNv = PhysicalRegisterSet.getNumberOfNonvolatileGPRs();
      ir.compiledMethod.setNumberOfNonvolatileGPRs((short) numGprNv);

      // set the frame size
      frameSize += numGprNv * WORDSIZE;
      frameSize = align(frameSize, STACKFRAME_ALIGNMENT);

      // TODO!!
      ir.compiledMethod.setNumberOfNonvolatileFPRs((short) 0);

      // Record that we need a stack frame.
      setFrameRequired();

      int fpuStateSaveAreaBegin = spillPointer;
      // Calculate FPU state save area for restoreFloatingPointState(..)
      // and saveFloatingPointState(..)
      if (SSE2_FULL) {
        for (int i = 0; i < 8; i++) {
          fsaveLocation = allocateNewSpillLocation(DOUBLE_REG);
        }
      } else {
        // Grab 108 bytes (same as 27 4-byte spills) in the stack
        // frame, as a place to store the floating-point state with FSAVE
        for (int i = 0; i < 27; i++) {
          fsaveLocation = allocateNewSpillLocation(INT_REG);
        }
      }

      int fpuStateSaveAreaEnd = spillPointer;
      int fpuStateSize = fpuStateSaveAreaEnd - fpuStateSaveAreaBegin;
      if (VM.VerifyAssertions) {
        VM._assert(fpuStateSize == OPT_SAVE_VOLATILE_SPACE_FOR_FPU_STATE);
      }

      int volatileGPRSaveAreaBegin = spillPointer;
      // Map each volatile register to a spill location.
      int i = 0;
      for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements(); i++) {
        e.nextElement();
        // Note that as a side effect, the following call bumps up the
        // frame size.
        saveVolatileGPRLocation[i] = allocateNewSpillLocation(INT_REG);
      }
      int volatileGPRSaveAreaEnd = spillPointer;
      int volatileGPRSaveAreaSize = volatileGPRSaveAreaEnd - volatileGPRSaveAreaBegin;
      if (VM.VerifyAssertions) {
        VM._assert(volatileGPRSaveAreaSize == OPT_SAVE_VOLATILE_SPACE_FOR_VOLATILE_GPRS);
        VM._assert((volatileGPRSaveAreaSize + fpuStateSize) == OPT_SAVE_VOLATILE_TOTAL_SIZE);
      }

      // Map each non-volatile register to a spill location.
      i = 0;
      for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements(); i++) {
        e.nextElement();
        // Note that as a side effect, the following call bumps up the
        // frame size.
        nonVolatileGPRLocation[i] = allocateNewSpillLocation(INT_REG);
      }

      // Set the offset to find non-volatiles.
      int gprOffset = getNonvolatileGPROffset(0);
      ir.compiledMethod.setUnsignedNonVolatileOffset(gprOffset);

    } else {
      // Count the number of nonvolatiles used.
      int numGprNv = 0;
      int i = 0;
      for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements(); ) {
        Register r = e.nextElement();
        if (r.isTouched()) {
          // Note that as a side effect, the following call bumps up the
          // frame size.
          nonVolatileGPRLocation[i++] = allocateNewSpillLocation(INT_REG);
          numGprNv++;
        }
      }
      // Update the OptCompiledMethod object.
      ir.compiledMethod.setNumberOfNonvolatileGPRs((short) numGprNv);
      if (numGprNv > 0) {
        int gprOffset = getNonvolatileGPROffset(0);
        ir.compiledMethod.setUnsignedNonVolatileOffset(gprOffset);
        // record that we need a stack frame
        setFrameRequired();
      } else {
        ir.compiledMethod.setUnsignedNonVolatileOffset(0);
      }

      ir.compiledMethod.setNumberOfNonvolatileFPRs((short) 0);
    }
  }
 /**
  * Add a node to the value graph for every symbolic register.
  *
  * <p><b>PRECONDITION:</b> register lists are computed and valid
  *
  * @param ir the governing IR
  */
 private void addRegisterNodes(IR ir) {
   for (Register reg = ir.regpool.getFirstSymbolicRegister(); reg != null; reg = reg.getNext()) {
     findOrCreateVertex(reg);
   }
 }
  public PhysicalRegisterSet() {

    // 1. Create all the physical registers in the pool.
    for (int i = 0; i < reg.length; i++) {
      Register r = new Register(i);
      r.setPhysical();
      reg[i] = r;
    }

    // 2. Set the 'integer' attribute on each GPR
    for (int i = FIRST_INT; i < FIRST_DOUBLE; i++) {
      reg[i].setInteger();
    }

    // 3. Set the 'double' attribute on each FPR
    for (int i = FIRST_DOUBLE; i < FIRST_SPECIAL; i++) {
      reg[i].setDouble();
    }

    // 4. set up the volatile GPRs
    for (Enumeration<Register> e = enumerateVolatileGPRs(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      r.setVolatile();
    }

    // 5. set up the non-volatile GPRs
    for (Enumeration<Register> e = enumerateNonvolatileGPRs(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      r.setNonVolatile();
    }

    // 6. set properties on some special registers
    reg[AF].setSpansBasicBlock();
    reg[CF].setSpansBasicBlock();
    reg[OF].setSpansBasicBlock();
    reg[PF].setSpansBasicBlock();
    reg[SF].setSpansBasicBlock();
    reg[ZF].setSpansBasicBlock();
    reg[C0].setSpansBasicBlock();
    reg[C1].setSpansBasicBlock();
    reg[C2].setSpansBasicBlock();
    reg[C3].setSpansBasicBlock();
    reg[THREAD_REGISTER.value()].setSpansBasicBlock();

    // For SSE2
    reg[ST0].setDouble();
    reg[ST1].setDouble();

    // 7. set up the volatile FPRs
    for (Enumeration<Register> e = enumerateVolatileFPRs(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      r.setVolatile();
    }

    // 8. set up the non-volatile FPRs
    for (Enumeration<Register> e = enumerateNonvolatileFPRs(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      r.setNonVolatile();
    }

    // 9. Cache the volatile registers for efficiency
    volatileSet = new BitSet(this);
    for (Enumeration<Register> e = enumerateVolatiles(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      volatileSet.add(r);
    }

    // 10. Cache the FPRs for efficiency
    fpSet = new BitSet(this);
    for (Enumeration<Register> e = enumerateFPRs(); e.hasMoreElements(); ) {
      Register r = e.nextElement();
      fpSet.add(r);
    }

    // Note no registers are excluded from live analysis (as is done for PPC)

  }