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.regalloc;
014
015import java.util.Enumeration;
016
017import org.jikesrvm.VM;
018import org.jikesrvm.classloader.TypeReference;
019import org.jikesrvm.compilers.opt.OptOptions;
020import org.jikesrvm.compilers.opt.driver.CompilerPhase;
021import org.jikesrvm.compilers.opt.ir.BasicBlock;
022import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet;
023import org.jikesrvm.compilers.opt.ir.IR;
024import org.jikesrvm.compilers.opt.ir.Instruction;
025import org.jikesrvm.compilers.opt.ir.Register;
026import org.jikesrvm.compilers.opt.ir.operand.Operand;
027import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
028import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand;
029
030/**
031 * Insert Spill Code after register assignment.
032 */
033final class SpillCode extends CompilerPhase {
034  /**
035   * Return this instance of this phase. This phase contains no
036   * per-compilation instance fields.
037   * @param ir not used
038   * @return this
039   */
040  @Override
041  public CompilerPhase newExecution(IR ir) {
042    return this;
043  }
044
045  @Override
046  public boolean shouldPerform(OptOptions options) {
047    return true;
048  }
049
050  @Override
051  public String getName() {
052    return "Spill Code";
053  }
054
055  @Override
056  public boolean printingEnabled(OptOptions options, boolean before) {
057    return false;
058  }
059
060  /**
061   *  Rewrites floating point registers to reflect changes in stack
062   *  height induced by BURS.
063   * <p>
064   *  Side effect: update the fpStackHeight in MIRInfo.
065   *
066   *  @param ir the IR to process
067   */
068  private void rewriteFPStack(IR ir) {
069    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
070    for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements();) {
071      BasicBlock bb = b.nextElement();
072
073      // The following holds the floating point stack offset from its
074      // 'normal' position.
075      int fpStackOffset = 0;
076
077      for (Enumeration<Instruction> inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) {
078        Instruction s = inst.nextElement();
079        for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) {
080          Operand op = ops.nextElement();
081          if (op.isRegister()) {
082            RegisterOperand rop = op.asRegister();
083            Register r = rop.getRegister();
084
085            // Update MIR state for every physical FPR we see
086            if (r.isPhysical() && r.isFloatingPoint() &&
087                s.operator() != org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_DEF &&
088                s.operator() != org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_USE) {
089              int n = org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet.getFPRIndex(r);
090              if (fpStackOffset != 0) {
091                n += fpStackOffset;
092                rop.setRegister(phys.getFPR(n));
093              }
094              ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, n + 1);
095            }
096          } else if (op instanceof BURSManagedFPROperand) {
097            int regNum = ((BURSManagedFPROperand) op).regNum;
098            s.replaceOperand(op, new RegisterOperand(phys.getFPR(regNum), TypeReference.Double));
099          }
100        }
101        // account for any effect s has on the floating point stack
102        // position.
103        if (s.operator().isFpPop()) {
104          fpStackOffset--;
105        } else if (s.operator().isFpPush()) {
106          fpStackOffset++;
107        }
108        if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0);
109      }
110    }
111  }
112
113
114  /**
115   *  @param ir the IR
116   */
117  @Override
118  public void perform(IR ir) {
119    replaceSymbolicRegisters(ir);
120
121    // Generate spill code if necessary
122    if (ir.hasSysCall() || ir.MIRInfo.linearScanState.spilledSomething) {
123      GenericStackManager stackMan = ir.stackManager;
124      stackMan.insertSpillCode(ir.MIRInfo.linearScanState.active);
125    }
126
127    if (VM.BuildForIA32 && !VM.BuildForSSE2Full) {
128      rewriteFPStack(ir);
129    }
130  }
131
132  /**
133   *  Iterates over the IR and replace each symbolic register with its
134   *  allocated physical register.
135   *
136   *  @param ir the IR to process
137   */
138  private static void replaceSymbolicRegisters(IR ir) {
139    RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
140
141    for (Enumeration<Instruction> inst = ir.forwardInstrEnumerator(); inst.hasMoreElements();) {
142      Instruction s = inst.nextElement();
143      for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) {
144        Operand op = ops.nextElement();
145        if (op.isRegister()) {
146          RegisterOperand rop = op.asRegister();
147          Register r = rop.getRegister();
148          if (r.isSymbolic() && !r.isSpilled()) {
149            Register p = regAllocState.getMapping(r);
150            if (VM.VerifyAssertions) VM._assert(p != null);
151            rop.setRegister(p);
152          }
153        }
154      }
155    }
156  }
157
158}