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.regalloc.ia32; 014 015 import java.util.ArrayList; 016 import java.util.Enumeration; 017 import org.jikesrvm.VM; 018 import org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterSet; 019 import org.jikesrvm.compilers.opt.ir.MIR_BinaryAcc; 020 import org.jikesrvm.compilers.opt.ir.MIR_CacheOp; 021 import org.jikesrvm.compilers.opt.ir.MIR_Compare; 022 import org.jikesrvm.compilers.opt.ir.MIR_CondMove; 023 import org.jikesrvm.compilers.opt.ir.MIR_DoubleShift; 024 import org.jikesrvm.compilers.opt.ir.MIR_LowTableSwitch; 025 import org.jikesrvm.compilers.opt.ir.MIR_Move; 026 import org.jikesrvm.compilers.opt.ir.MIR_Set; 027 import org.jikesrvm.compilers.opt.ir.MIR_Test; 028 import org.jikesrvm.compilers.opt.ir.MIR_Unary; 029 import org.jikesrvm.compilers.opt.ir.MIR_UnaryNoRes; 030 import org.jikesrvm.compilers.opt.ir.BasicBlock; 031 import org.jikesrvm.compilers.opt.ir.Instruction; 032 import org.jikesrvm.compilers.opt.ir.Operators; 033 import org.jikesrvm.compilers.opt.ir.Register; 034 import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 035 import org.jikesrvm.compilers.opt.ir.operand.Operand; 036 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 037 import org.jikesrvm.compilers.opt.ir.operand.ia32.BURSManagedFPROperand; 038 import org.jikesrvm.compilers.opt.regalloc.GenericRegisterRestrictions; 039 import org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement; 040 041 /** 042 * An instance of this class encapsulates restrictions on register 043 * assignment. 044 */ 045 public class RegisterRestrictions extends GenericRegisterRestrictions 046 implements Operators, PhysicalRegisterConstants { 047 048 /** 049 * Allow scratch registers in PEIs? 050 */ 051 public static final boolean SCRATCH_IN_PEI = true; 052 053 /** 054 * Default Constructor 055 */ 056 protected RegisterRestrictions(PhysicalRegisterSet phys) { 057 super(phys); 058 } 059 060 @Override 061 public void addArchRestrictions(BasicBlock bb, ArrayList<LiveIntervalElement> symbolics) { 062 // If there are any registers used in catch blocks, we want to ensure 063 // that these registers are not used or evicted from scratch registers 064 // at a relevant PEI, so that the assumptions of register homes in the 065 // catch block remain valid. For now, we do this by forcing any 066 // register used in such a PEI as not spilled. TODO: relax this 067 // restriction for better code. 068 for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) { 069 Instruction s = ie.nextElement(); 070 if (s.isPEI() && s.operator != IR_PROLOGUE) { 071 if (bb.hasApplicableExceptionalOut(s) || !SCRATCH_IN_PEI) { 072 for (Enumeration<Operand> e = s.getOperands(); e.hasMoreElements();) { 073 Operand op = e.nextElement(); 074 if (op != null && op.isRegister()) { 075 noteMustNotSpill(op.asRegister().getRegister()); 076 handle8BitRestrictions(s); 077 } 078 } 079 } 080 } 081 082 // handle special cases 083 switch (s.getOpcode()) { 084 case MIR_LOWTABLESWITCH_opcode: { 085 RegisterOperand op = MIR_LowTableSwitch.getMethodStart(s); 086 noteMustNotSpill(op.getRegister()); 087 op = MIR_LowTableSwitch.getIndex(s); 088 noteMustNotSpill(op.getRegister()); 089 } 090 break; 091 case IA32_MOVZX__B_opcode: 092 case IA32_MOVSX__B_opcode: { 093 if (MIR_Unary.getVal(s).isRegister()) { 094 RegisterOperand val = MIR_Unary.getVal(s).asRegister(); 095 restrictTo8Bits(val.getRegister()); 096 } 097 } 098 break; 099 case IA32_SET__B_opcode: { 100 if (MIR_Set.getResult(s).isRegister()) { 101 RegisterOperand op = MIR_Set.getResult(s).asRegister(); 102 restrictTo8Bits(op.getRegister()); 103 } 104 } 105 break; 106 107 default: 108 handle8BitRestrictions(s); 109 break; 110 } 111 } 112 for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements();) { 113 Instruction s = ie.nextElement(); 114 if (s.operator == IA32_FNINIT) { 115 // No floating point register survives across an FNINIT 116 for (LiveIntervalElement symb : symbolics) { 117 if (symb.getRegister().isFloatingPoint()) { 118 if (contains(symb, s.scratch)) { 119 addRestrictions(symb.getRegister(), phys.getFPRs()); 120 } 121 } 122 } 123 } else if (s.operator == IA32_FCLEAR) { 124 // Only some FPRs survive across an FCLEAR 125 for (LiveIntervalElement symb : symbolics) { 126 if (symb.getRegister().isFloatingPoint()) { 127 if (contains(symb, s.scratch)) { 128 int nSave = MIR_UnaryNoRes.getVal(s).asIntConstant().value; 129 for (int i = nSave; i < NUM_FPRS; i++) { 130 addRestriction(symb.getRegister(), phys.getFPR(i)); 131 } 132 } 133 } 134 } 135 } 136 } 137 } 138 139 /** 140 * Does instruction s contain an 8-bit memory operand? 141 */ 142 final boolean has8BitMemoryOperand(Instruction s) { 143 for (Enumeration<Operand> me = s.getMemoryOperands(); me.hasMoreElements();) { 144 MemoryOperand mop = (MemoryOperand) me.nextElement(); 145 if (mop.size == 1) { 146 return true; 147 } 148 } 149 return false; 150 } 151 152 /** 153 * Ensure that if an operand has an 8 bit memory operand that 154 * all of its register operands are in 8 bit registers. 155 * @param s the instruction to restrict 156 */ 157 final void handle8BitRestrictions(Instruction s) { 158 for (Enumeration<Operand> me = s.getMemoryOperands(); me.hasMoreElements();) { 159 MemoryOperand mop = (MemoryOperand) me.nextElement(); 160 if (mop.size == 1) { 161 for (Enumeration<Operand> e2 = s.getRootOperands(); e2.hasMoreElements();) { 162 Operand rootOp = e2.nextElement(); 163 if (rootOp.isRegister()) { 164 restrictTo8Bits(rootOp.asRegister().getRegister()); 165 } 166 } 167 } 168 } 169 } 170 171 /** 172 * Ensure that a particular register is only assigned to AL, BL, CL, or 173 * DL, since these are the only 8-bit registers we normally address. 174 */ 175 final void restrictTo8Bits(Register r) { 176 Register ESP = phys.getESP(); 177 Register EBP = phys.getEBP(); 178 Register ESI = phys.getESI(); 179 Register EDI = phys.getEDI(); 180 addRestriction(r, ESP); 181 addRestriction(r, EBP); 182 addRestriction(r, ESI); 183 addRestriction(r, EDI); 184 } 185 186 /** 187 * Given symbolic register r that appears in instruction s, does the 188 * architecture demand that r be assigned to a physical register in s? 189 */ 190 public static boolean mustBeInRegister(Register r, Instruction s) { 191 switch (s.getOpcode()) { 192 case IA32_PREFETCHNTA_opcode: { 193 RegisterOperand op = MIR_CacheOp.getAddress(s).asRegister(); 194 if (op.register == r) return true; 195 } 196 break; 197 198 case IA32_SQRTSS_opcode: 199 case IA32_SQRTSD_opcode: 200 case IA32_CVTSD2SI_opcode: 201 case IA32_CVTSD2SS_opcode: 202 case IA32_CVTSI2SD_opcode: 203 case IA32_CVTSS2SD_opcode: 204 case IA32_CVTSS2SI_opcode: 205 case IA32_CVTTSD2SI_opcode: 206 case IA32_CVTTSS2SI_opcode: 207 case IA32_CVTSI2SS_opcode: { 208 RegisterOperand op = MIR_Unary.getResult(s).asRegister(); 209 if (op.getRegister() == r) return true; 210 } 211 break; 212 213 // Instructions that require 16byte alignment (not guaranteed by our 214 // spills) must be forced to always use registers 215 case IA32_ANDPS_opcode: 216 case IA32_ANDNPS_opcode: 217 case IA32_ORPS_opcode: 218 case IA32_XORPS_opcode: 219 case IA32_ANDPD_opcode: 220 case IA32_ANDNPD_opcode: 221 case IA32_ORPD_opcode: 222 case IA32_XORPD_opcode: 223 return true; 224 225 case IA32_ADDSS_opcode: 226 case IA32_CMPEQSS_opcode: 227 case IA32_CMPLTSS_opcode: 228 case IA32_CMPLESS_opcode: 229 case IA32_CMPUNORDSS_opcode: 230 case IA32_CMPNESS_opcode: 231 case IA32_CMPNLTSS_opcode: 232 case IA32_CMPNLESS_opcode: 233 case IA32_CMPORDSS_opcode: 234 case IA32_DIVSS_opcode: 235 case IA32_MULSS_opcode: 236 case IA32_SUBSS_opcode: 237 case IA32_ADDSD_opcode: 238 case IA32_CMPEQSD_opcode: 239 case IA32_CMPLTSD_opcode: 240 case IA32_CMPLESD_opcode: 241 case IA32_CMPUNORDSD_opcode: 242 case IA32_CMPNESD_opcode: 243 case IA32_CMPNLTSD_opcode: 244 case IA32_CMPNLESD_opcode: 245 case IA32_CMPORDSD_opcode: 246 case IA32_DIVSD_opcode: 247 case IA32_MULSD_opcode: 248 case IA32_SUBSD_opcode: { 249 RegisterOperand op = MIR_BinaryAcc.getResult(s).asRegister(); 250 if (op.getRegister() == r) return true; 251 } 252 break; 253 254 case IA32_UCOMISD_opcode: 255 case IA32_UCOMISS_opcode: { 256 RegisterOperand op = MIR_Compare.getVal1(s).asRegister(); 257 if (op.getRegister() == r) return true; 258 } 259 break; 260 261 case IA32_SHRD_opcode: 262 case IA32_SHLD_opcode: { 263 RegisterOperand op = MIR_DoubleShift.getSource(s); 264 if (op.getRegister() == r) return true; 265 } 266 break; 267 case IA32_FCOMI_opcode: 268 case IA32_FCOMIP_opcode: { 269 Operand op = MIR_Compare.getVal2(s); 270 if (!(op instanceof BURSManagedFPROperand)) { 271 if (op.asRegister().getRegister() == r) return true; 272 } 273 } 274 break; 275 case IA32_IMUL2_opcode: { 276 RegisterOperand op = MIR_BinaryAcc.getResult(s).asRegister(); 277 if (op.getRegister() == r) return true; 278 } 279 break; 280 case MIR_LOWTABLESWITCH_opcode: { 281 RegisterOperand op = MIR_LowTableSwitch.getIndex(s); 282 if (op.getRegister() == r) return true; 283 } 284 break; 285 case IA32_CMOV_opcode: 286 case IA32_FCMOV_opcode: { 287 RegisterOperand op = MIR_CondMove.getResult(s).asRegister(); 288 if (op.getRegister() == r) return true; 289 } 290 break; 291 case IA32_MOVD_opcode: { 292 RegisterOperand res = MIR_Move.getResult(s).asRegister(); 293 if (!res.isFloat() && !res.isDouble()) { 294 // result is integer so source must be MM/XMM register and 295 // result must remain a register 296 if (VM.VerifyAssertions) { 297 Operand val = MIR_Move.getValue(s); 298 VM._assert(val.isRegister() && (val.isFloat() || val.isDouble())); 299 } 300 return true; 301 } 302 Operand val = MIR_Move.getValue(s); 303 if (!val.isFloat() && !val.isDouble()) { 304 // source is integer so destination must be MM/XMM register and 305 // source must remain a register 306 if (VM.VerifyAssertions) { 307 VM._assert(res.isRegister() && (res.isFloat() || res.isDouble())); 308 } 309 return true; 310 } 311 } 312 break; 313 case IA32_MOVZX__B_opcode: 314 case IA32_MOVSX__B_opcode: { 315 RegisterOperand op = MIR_Unary.getResult(s).asRegister(); 316 if (op.getRegister() == r) return true; 317 } 318 break; 319 case IA32_MOVZX__W_opcode: 320 case IA32_MOVSX__W_opcode: { 321 RegisterOperand op = MIR_Unary.getResult(s).asRegister(); 322 if (op.getRegister() == r) return true; 323 } 324 break; 325 case IA32_SET__B_opcode: { 326 if (MIR_Set.getResult(s).isRegister()) { 327 RegisterOperand op = MIR_Set.getResult(s).asRegister(); 328 if (op.asRegister().getRegister() == r) return true; 329 } 330 } 331 break; 332 case IA32_TEST_opcode: { 333 // at least 1 of the two operands must be in a register 334 if (!MIR_Test.getVal2(s).isConstant()) { 335 if (MIR_Test.getVal1(s).isRegister()) { 336 if (MIR_Test.getVal1(s).asRegister().getRegister() == r) return true; 337 } else if (MIR_Test.getVal2(s).isRegister()) { 338 if (MIR_Test.getVal2(s).asRegister().getRegister() == r) return true; 339 } 340 } 341 } 342 break; 343 case IA32_BT_opcode: { 344 // val2 of bit test must be either a constant or register 345 if (!MIR_Test.getVal2(s).isConstant()) { 346 if (MIR_Test.getVal2(s).isRegister()) { 347 if (MIR_Test.getVal2(s).asRegister().getRegister() == r) return true; 348 } 349 } 350 } 351 break; 352 353 default: 354 break; 355 } 356 return false; 357 } 358 359 /** 360 * Can physical register r hold an 8-bit value? 361 */ 362 private boolean okFor8(Register r) { 363 Register ESP = phys.getESP(); 364 Register EBP = phys.getEBP(); 365 Register ESI = phys.getESI(); 366 Register EDI = phys.getEDI(); 367 return (r != ESP && r != EBP && r != ESI && r != EDI); 368 } 369 370 @Override 371 public boolean isForbidden(Register symb, Register r, Instruction s) { 372 373 // Look at 8-bit restrictions. 374 switch (s.operator.opcode) { 375 case IA32_MOVZX__B_opcode: 376 case IA32_MOVSX__B_opcode: { 377 if (MIR_Unary.getVal(s).isRegister()) { 378 RegisterOperand val = MIR_Unary.getVal(s).asRegister(); 379 if (val.getRegister() == symb) { 380 return !okFor8(r); 381 } 382 } 383 } 384 break; 385 case IA32_SET__B_opcode: { 386 if (MIR_Set.getResult(s).isRegister()) { 387 RegisterOperand op = MIR_Set.getResult(s).asRegister(); 388 if (op.asRegister().getRegister() == symb) { 389 return !okFor8(r); 390 } 391 } 392 } 393 break; 394 } 395 396 if (has8BitMemoryOperand(s)) { 397 return !okFor8(r); 398 } 399 400 // Otherwise, it's OK. 401 return false; 402 } 403 }