/*
* 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.ia32;
import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_DEF;
import static org.jikesrvm.compilers.opt.ir.ia32.ArchOperators.DUMMY_USE;
import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL;
import java.util.Enumeration;
import org.jikesrvm.VM;
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.ExceptionHandlerBasicBlock;
import org.jikesrvm.compilers.opt.ir.IR;
import org.jikesrvm.compilers.opt.ir.IRTools;
import org.jikesrvm.compilers.opt.ir.Instruction;
import org.jikesrvm.compilers.opt.ir.Register;
import org.jikesrvm.compilers.opt.ir.ia32.MIR_Nullary;
import org.jikesrvm.compilers.opt.ir.ia32.MIR_UnaryNoRes;
import org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet;
/**
* At the beginning of each basic block, the register allocator expects
* all floating-point stack locations to be available, and named
* FPi, 0 < i < 7
*
* <p>However, BURS may consume FP stack locations by inserting instructions
* that push or pop the floating-point stack. This phase inserts dummy
* definitions and uses to indicate when symbolic FP registers are not
* available for register allocation since BURS has consumed a stack slot.
*
* For example,
* <pre>
* FLD t1
* ...
* FSTP M, t1
* </pre>
*
* will be modified by this phase to indicate that FP6 is not available
* for allocation in the interval:
*
* <pre>
* DUMMY_DEF FP6
* FLD t1
* .....
* FSTP M, t1
* DUMMY_USE FP6
* </pre>
*
* <p> Additionally, by convention, we will always clear the
* floating-point stack when delivering an exception. To model this, we
* insert dummy defs and uses for each floating-point register at the
* beginning of each catch block.
*/
public final class ExpandFPRStackConvention extends CompilerPhase {
/**
* The number of FPRs available for allocation.
* Normally 7: we reserve one for final MIR expansion.
*/
private static final int NUM_ALLOCATABLE_FPR = 7;
/**
* 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 printingEnabled(OptOptions options, boolean before) {
return options.PRINT_CALLING_CONVENTIONS && !before;
}
@Override
public String getName() {
return "Expand Calling Convention";
}
/**
* Insert the needed dummy defs and uses.
*/
@Override
public void perform(IR ir) {
if (SSE2_FULL) {
return;
}
PhysicalRegisterSet phys = (PhysicalRegisterSet)ir.regpool.getPhysicalRegisterSet();
for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements();) {
BasicBlock bb = b.nextElement();
if (bb instanceof ExceptionHandlerBasicBlock) {
// clear all floating-point state at the entry to a catch block
for (int i = 0; i < NUM_ALLOCATABLE_FPR; i++) {
Register fpr = phys.getFPR(i);
bb.prependInstruction(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
bb.prependInstruction(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
}
}
// 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();
if (s.operator().isFpPop()) {
// A pop instruction 'ends' a dummy live range.
Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
s.insertAfter(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
fpStackOffset--;
} else if (s.operator().isFpPush()) {
fpStackOffset++;
Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
s.insertBefore(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
}
if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0);
if (VM.VerifyAssertions) {
VM._assert(fpStackOffset < NUM_ALLOCATABLE_FPR);
}
}
}
}
}