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 */ 013 package org.jikesrvm.compilers.opt.ir.ia32; 014 015 import java.util.Enumeration; 016 017 import org.jikesrvm.VM; 018 import org.jikesrvm.classloader.TypeReference; 019 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 020 import org.jikesrvm.compilers.opt.ir.Empty; 021 import org.jikesrvm.compilers.opt.ir.MIR_CondBranch; 022 import org.jikesrvm.compilers.opt.ir.MIR_CondBranch2; 023 import org.jikesrvm.compilers.opt.ir.MIR_Move; 024 import org.jikesrvm.compilers.opt.ir.BasicBlock; 025 import org.jikesrvm.compilers.opt.ir.IR; 026 import org.jikesrvm.compilers.opt.ir.Instruction; 027 import org.jikesrvm.compilers.opt.ir.MachineSpecificIR; 028 import org.jikesrvm.compilers.opt.ir.Operator; 029 import static org.jikesrvm.compilers.opt.ir.Operators.ADVISE_ESP; 030 import static org.jikesrvm.compilers.opt.ir.Operators.DUMMY_DEF; 031 import static org.jikesrvm.compilers.opt.ir.Operators.DUMMY_USE; 032 import static org.jikesrvm.compilers.opt.ir.Operators.GET_CURRENT_PROCESSOR_opcode; 033 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FCLEAR; 034 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FMOV; 035 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FMOV_ENDING_LIVE_RANGE; 036 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_FNINIT; 037 import static org.jikesrvm.compilers.opt.ir.Operators.IA32_JCC; 038 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_2ADDR_opcode; 039 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ADD_opcode; 040 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_AND_opcode; 041 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_MOVE_opcode; 042 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_NEG_opcode; 043 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_OR_opcode; 044 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHL_opcode; 045 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SHR_opcode; 046 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_SUB_opcode; 047 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_USHR_opcode; 048 import static org.jikesrvm.compilers.opt.ir.Operators.LONG_XOR_opcode; 049 import static org.jikesrvm.compilers.opt.ir.Operators.NOP; 050 import static org.jikesrvm.compilers.opt.ir.Operators.PREFETCH_opcode; 051 import org.jikesrvm.compilers.opt.ir.Register; 052 import org.jikesrvm.compilers.opt.ir.operand.Operand; 053 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 054 import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand; 055 import org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand; 056 import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement; 057 058 /** 059 * Wrappers around IA32-specific IR common to both 32 & 64 bit 060 */ 061 public abstract class MachineSpecificIRIA extends MachineSpecificIR { 062 063 /** 064 * Wrappers around IA32-specific IR (32-bit specific) 065 */ 066 public static final class IA32 extends MachineSpecificIRIA { 067 public static final IA32 singleton = new IA32(); 068 069 /* common to all ISAs */ 070 @Override 071 public boolean mayEscapeThread(Instruction instruction) { 072 switch (instruction.getOpcode()) { 073 case PREFETCH_opcode: 074 return false; 075 case GET_CURRENT_PROCESSOR_opcode: 076 return true; 077 default: 078 throw new OptimizingCompilerException("SimpleEscape: Unexpected " + instruction); 079 } 080 } 081 082 @Override 083 public boolean mayEscapeMethod(Instruction instruction) { 084 return mayEscapeThread(instruction); // at this stage we're no more specific 085 } 086 } 087 088 /** 089 * Wrappers around EMT64-specific IR (64-bit specific) 090 */ 091 public static final class EM64T extends MachineSpecificIRIA { 092 public static final EM64T singleton = new EM64T(); 093 094 /* common to all ISAs */ 095 @Override 096 public boolean mayEscapeThread(Instruction instruction) { 097 switch (instruction.getOpcode()) { 098 case PREFETCH_opcode: 099 return false; 100 case GET_CURRENT_PROCESSOR_opcode: 101 case LONG_OR_opcode: 102 case LONG_AND_opcode: 103 case LONG_XOR_opcode: 104 case LONG_SUB_opcode: 105 case LONG_SHL_opcode: 106 case LONG_ADD_opcode: 107 case LONG_SHR_opcode: 108 case LONG_USHR_opcode: 109 case LONG_NEG_opcode: 110 case LONG_MOVE_opcode: 111 case LONG_2ADDR_opcode: 112 return true; 113 default: 114 throw new OptimizingCompilerException("SimpleEscapge: Unexpected " + instruction); 115 } 116 } 117 118 @Override 119 public boolean mayEscapeMethod(Instruction instruction) { 120 return mayEscapeThread(instruction); // at this stage we're no more specific 121 } 122 } 123 124 /* 125 * Generic (32/64 neutral) IA support 126 */ 127 128 /* common to all ISAs */ 129 130 @Override 131 public boolean isConditionOperand(Operand operand) { 132 return operand instanceof IA32ConditionOperand; 133 } 134 135 @Override 136 public void mutateMIRCondBranch(Instruction cb) { 137 MIR_CondBranch.mutate(cb, 138 IA32_JCC, 139 MIR_CondBranch2.getCond1(cb), 140 MIR_CondBranch2.getTarget1(cb), 141 MIR_CondBranch2.getBranchProfile1(cb)); 142 } 143 144 @Override 145 public boolean isHandledByRegisterUnknown(char opcode) { 146 return (opcode == PREFETCH_opcode); 147 } 148 149 /* unique to IA */ 150 @Override 151 public boolean isAdviseESP(Operator operator) { 152 return operator == ADVISE_ESP; 153 } 154 155 @Override 156 public boolean isFClear(Operator operator) { 157 return operator == IA32_FCLEAR; 158 } 159 160 @Override 161 public boolean isFNInit(Operator operator) { 162 return operator == IA32_FNINIT; 163 } 164 165 @Override 166 public boolean isBURSManagedFPROperand(Operand operand) { 167 return operand instanceof BURSManagedFPROperand; 168 } 169 170 @Override 171 public int getBURSManagedFPRValue(Operand operand) { 172 return ((BURSManagedFPROperand) operand).regNum; 173 } 174 175 /** 176 * Mutate FMOVs that end live ranges 177 * 178 * @param live The live interval for a basic block/reg pair 179 * @param register The register for this live interval 180 * @param dfnbegin The (adjusted) begin for this interval 181 * @param dfnend The (adjusted) end for this interval 182 */ 183 @Override 184 public boolean mutateFMOVs(LiveIntervalElement live, Register register, int dfnbegin, int dfnend) { 185 Instruction end = live.getEnd(); 186 if (end != null && end.operator == IA32_FMOV) { 187 if (dfnend == dfnbegin) { 188 // if end, an FMOV, both begins and ends the live range, 189 // then end is dead. Change it to a NOP and return null. 190 Empty.mutate(end, NOP); 191 return false; 192 } else { 193 if (!end.isPEI()) { 194 if (VM.VerifyAssertions) { 195 Operand value = MIR_Move.getValue(end); 196 VM._assert(value.isRegister()); 197 VM._assert(MIR_Move.getValue(end).asRegister().getRegister() == register); 198 } 199 end.operator = IA32_FMOV_ENDING_LIVE_RANGE; 200 } 201 } 202 } 203 return true; 204 } 205 206 /** 207 * Rewrite floating point registers to reflect changes in stack 208 * height induced by BURS. 209 * 210 * Side effect: update the fpStackHeight in MIRInfo 211 */ 212 @Override 213 public void rewriteFPStack(IR ir) { 214 PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 215 for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements();) { 216 BasicBlock bb = b.nextElement(); 217 218 // The following holds the floating point stack offset from its 219 // 'normal' position. 220 int fpStackOffset = 0; 221 222 for (Enumeration<Instruction> inst = bb.forwardInstrEnumerator(); inst.hasMoreElements();) { 223 Instruction s = inst.nextElement(); 224 for (Enumeration<Operand> ops = s.getOperands(); ops.hasMoreElements();) { 225 Operand op = ops.nextElement(); 226 if (op.isRegister()) { 227 RegisterOperand rop = op.asRegister(); 228 Register r = rop.getRegister(); 229 230 // Update MIR state for every physical FPR we see 231 if (r.isPhysical() && r.isFloatingPoint() && s.operator() != DUMMY_DEF && s.operator() != DUMMY_USE) { 232 int n = PhysicalRegisterSet.getFPRIndex(r); 233 if (fpStackOffset != 0) { 234 n += fpStackOffset; 235 rop.setRegister(phys.getFPR(n)); 236 } 237 ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, n + 1); 238 } 239 } else if (op instanceof BURSManagedFPROperand) { 240 int regNum = ((BURSManagedFPROperand) op).regNum; 241 s.replaceOperand(op, new RegisterOperand(phys.getFPR(regNum), TypeReference.Double)); 242 } 243 } 244 // account for any effect s has on the floating point stack 245 // position. 246 if (s.operator().isFpPop()) { 247 fpStackOffset--; 248 } else if (s.operator().isFpPush()) { 249 fpStackOffset++; 250 } 251 if (VM.VerifyAssertions) VM._assert(fpStackOffset >= 0); 252 } 253 } 254 } 255 }