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}