/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.regalloc;
import java.util.Enumeration;
import org.jikesrvm.VM;
import org.jikesrvm.classloader.TypeReference;
import org.jikesrvm.compilers.opt.OptOptions;
import org.jikesrvm.compilers.opt.driver.CompilerPhase;
import org.jikesrvm.compilers.opt.ir.BasicBlock;
import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet;
import org.jikesrvm.compilers.opt.ir.IR;
import org.jikesrvm.compilers.opt.ir.Instruction;
import org.jikesrvm.compilers.opt.ir.Register;
import org.jikesrvm.compilers.opt.ir.operand.Operand;
import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand;
/**
* Insert Spill Code after register assignment.
*/
final class SpillCode extends CompilerPhase {
/**
* Return this instance of this phase. This phase contains no
* per-compilation instance fields.
* @param ir not used
* @return this
*/
@Override
public CompilerPhase newExecution(IR ir) {
return this;
}
@Override
public boolean shouldPerform(OptOptions options) {
return true;
}
@Override
public String getName() {
return "Spill Code";
}
@Override
public boolean printingEnabled(OptOptions options, boolean before) {
return false;
}
/**
* Rewrites floating point registers to reflect changes in stack
* height induced by BURS.
* <p>
* Side effect: update the fpStackHeight in MIRInfo.
*
* @param ir the IR to process
*/
private void rewriteFPStack(IR ir) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements();) {
BasicBlock bb = b.nextElement();
// The following holds the floating point stack offset from its
// 'normal' position.
int fpStackOffset = 0;
for (Enumeration<Instruction> inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) {
Instruction s = inst.nextElement();
for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) {
Operand op = ops.nextElement();
if (op.isRegister()) {
RegisterOperand rop = op.asRegister();
Register r = rop.getRegister();
// Update MIR state for every physical FPR we see
if (r.isPhysical() && r.isFloatingPoint() &&
s.operator() != org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_DEF &&
s.operator() != org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_USE) {
int n = org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet.getFPRIndex(r);
if (fpStackOffset != 0) {
n += fpStackOffset;
rop.setRegister(phys.getFPR(n));
}
ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, n + 1);
}
} else if (op instanceof BURSManagedFPROperand) {
int regNum = ((BURSManagedFPROperand) op).regNum;
s.replaceOperand(op, new RegisterOperand(phys.getFPR(regNum), TypeReference.Double));
}
}
// account for any effect s has on the floating point stack
// position.
if (s.operator().isFpPop()) {
fpStackOffset--;
} else if (s.operator().isFpPush()) {
fpStackOffset++;
}
if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0);
}
}
}
/**
* @param ir the IR
*/
@Override
public void perform(IR ir) {
replaceSymbolicRegisters(ir);
// Generate spill code if necessary
if (ir.hasSysCall() || ir.MIRInfo.linearScanState.spilledSomething) {
GenericStackManager stackMan = ir.stackManager;
stackMan.insertSpillCode(ir.MIRInfo.linearScanState.active);
}
if (VM.BuildForIA32 && !VM.BuildForSSE2Full) {
rewriteFPStack(ir);
}
}
/**
* Iterates over the IR and replace each symbolic register with its
* allocated physical register.
*
* @param ir the IR to process
*/
private static void replaceSymbolicRegisters(IR ir) {
RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
for (Enumeration<Instruction> inst = ir.forwardInstrEnumerator(); inst.hasMoreElements();) {
Instruction s = inst.nextElement();
for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) {
Operand op = ops.nextElement();
if (op.isRegister()) {
RegisterOperand rop = op.asRegister();
Register r = rop.getRegister();
if (r.isSymbolic() && !r.isSpilled()) {
Register p = regAllocState.getMapping(r);
if (VM.VerifyAssertions) VM._assert(p != null);
rop.setRegister(p);
}
}
}
}
}
}