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.lir2mir; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 017 import org.jikesrvm.compilers.opt.ir.ALoad; 018 import org.jikesrvm.compilers.opt.ir.AStore; 019 import org.jikesrvm.compilers.opt.ir.Binary; 020 import org.jikesrvm.compilers.opt.ir.Load; 021 import org.jikesrvm.compilers.opt.ir.Instruction; 022 import org.jikesrvm.compilers.opt.ir.Store; 023 import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand; 024 import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand; 025 import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand; 026 import org.jikesrvm.compilers.opt.ir.operand.LocationOperand; 027 import org.jikesrvm.compilers.opt.ir.operand.MemoryOperand; 028 import org.jikesrvm.compilers.opt.ir.operand.Operand; 029 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 030 import org.vmmagic.unboxed.Offset; 031 032 /** 033 * Contains common BURS helper functions for platforms with memory operands. 034 */ 035 public abstract class BURS_MemOp_Helpers extends BURS_Common_Helpers { 036 // word size for memory operands 037 protected static final byte B = 0x01; // byte (8 bits) 038 protected static final byte W = 0x02; // word (16 bits) 039 protected static final byte DW = 0x04; // doubleword (32 bits) 040 protected static final byte QW = 0x08; // quadword (64 bits) 041 protected static final byte PARAGRAPH = 0x10; // paragraph (128 bits) 042 043 protected static final byte B_S = 0x00; // byte (8*2^0 bits) 044 protected static final byte W_S = 0x01; // word (8*2^116 bits) 045 protected static final byte DW_S = 0x02; // doubleword (8*2^2 bits) 046 protected static final byte QW_S = 0x03; // quadword (8*2^3 bits) 047 048 protected BURS_MemOp_Helpers(BURS burs) { 049 super(burs); 050 } 051 052 // Cost functions better suited to grammars with multiple non-termials 053 protected final int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { 054 return ADDRESS_EQUAL(store, load, trueCost, INFINITE); 055 } 056 057 protected final int ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { 058 if (Store.getAddress(store).similar(Load.getAddress(load)) && 059 Store.getOffset(store).similar(Load.getOffset(load))) { 060 return trueCost; 061 } else { 062 return falseCost; 063 } 064 } 065 066 protected final int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost) { 067 return ARRAY_ADDRESS_EQUAL(store, load, trueCost, INFINITE); 068 } 069 070 protected final int ARRAY_ADDRESS_EQUAL(Instruction store, Instruction load, int trueCost, int falseCost) { 071 if (AStore.getArray(store).similar(ALoad.getArray(load)) && AStore.getIndex(store).similar(ALoad.getIndex(load))) { 072 return trueCost; 073 } else { 074 return falseCost; 075 } 076 } 077 078 // support to remember an address being computed in a subtree 079 private static final class AddrStackElement { 080 RegisterOperand base; 081 RegisterOperand index; 082 byte scale; 083 Offset displacement; 084 AddrStackElement next; 085 086 AddrStackElement(RegisterOperand b, RegisterOperand i, byte s, Offset d, AddrStackElement n) { 087 base = b; 088 index = i; 089 scale = s; 090 displacement = d; 091 next = n; 092 } 093 } 094 095 private AddrStackElement AddrStack; 096 097 protected final void pushAddress(RegisterOperand base, RegisterOperand index, byte scale, Offset disp) { 098 AddrStack = new AddrStackElement(base, index, scale, disp, AddrStack); 099 } 100 101 protected final void augmentAddress(Operand op) { 102 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to augment"); 103 if (op.isRegister()) { 104 RegisterOperand rop = op.asRegister(); 105 if (AddrStack.base == null) { 106 AddrStack.base = rop; 107 } else if (AddrStack.index == null) { 108 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 109 AddrStack.index = rop; 110 } else { 111 throw new OptimizingCompilerException("three base registers in address"); 112 } 113 } else { 114 int disp = ((IntConstantOperand) op).value; 115 AddrStack.displacement = AddrStack.displacement.plus(disp); 116 } 117 } 118 119 protected final void combineAddresses() { 120 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to combine"); 121 AddrStackElement tmp = AddrStack; 122 AddrStack = AddrStack.next; 123 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "only 1 address to combine"); 124 if (tmp.base != null) { 125 if (AddrStack.base == null) { 126 AddrStack.base = tmp.base; 127 } else if (AddrStack.index == null) { 128 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 129 AddrStack.index = tmp.base; 130 } else { 131 throw new OptimizingCompilerException("three base registers in address"); 132 } 133 } 134 if (tmp.index != null) { 135 if (AddrStack.index == null) { 136 if (VM.VerifyAssertions) VM._assert(AddrStack.scale == (byte) 0); 137 AddrStack.index = tmp.index; 138 AddrStack.scale = tmp.scale; 139 } else if (AddrStack.base == null && tmp.scale == (byte) 0) { 140 AddrStack.base = tmp.base; 141 } else { 142 throw new OptimizingCompilerException("two scaled registers in address"); 143 } 144 } 145 AddrStack.displacement = AddrStack.displacement.plus(tmp.displacement.toInt()); 146 } 147 148 protected final MemoryOperand consumeAddress(byte size, LocationOperand loc, Operand guard) { 149 if (VM.VerifyAssertions) VM._assert(AddrStack != null, "No address to consume"); 150 MemoryOperand mo = 151 new MemoryOperand(AddrStack.base, 152 AddrStack.index, 153 AddrStack.scale, 154 AddrStack.displacement, 155 size, 156 loc, 157 guard); 158 AddrStack = AddrStack.next; 159 return mo; 160 } 161 162 // support to remember a memory operand computed in a subtree 163 private static final class MOStackElement { 164 MemoryOperand mo; 165 MOStackElement next; 166 167 MOStackElement(MemoryOperand m, MOStackElement n) { 168 mo = m; 169 next = n; 170 } 171 } 172 173 private MOStackElement MOStack; 174 175 protected final void pushMO(MemoryOperand mo) { 176 MOStack = new MOStackElement(mo, MOStack); 177 } 178 179 protected final MemoryOperand consumeMO() { 180 if (VM.VerifyAssertions) VM._assert(MOStack != null, "No memory operand to consume"); 181 MemoryOperand mo = MOStack.mo; 182 MOStack = MOStack.next; 183 return mo; 184 } 185 186 /** 187 * Construct a memory operand for the effective address of the 188 * load instruction 189 */ 190 protected final MemoryOperand MO_L(Instruction s, byte size) { 191 return MO_L(s, size, 0); 192 } 193 194 /** 195 * Construct a displaced memory operand for the effective address of the 196 * load instruction 197 */ 198 protected final MemoryOperand MO_L(Instruction s, byte size, int disp) { 199 if (VM.VerifyAssertions) VM._assert(Load.conforms(s)); 200 return MO(Load.getAddress(s), 201 Load.getOffset(s), 202 size, 203 Offset.fromIntSignExtend(disp), 204 Load.getLocation(s), 205 Load.getGuard(s)); 206 } 207 208 /** 209 * Construct a memory operand for the effective address of the 210 * store instruction 211 */ 212 protected final MemoryOperand MO_S(Instruction s, byte size) { 213 return MO_S(s, size, 0); 214 } 215 216 /** 217 * Construct a displaced memory operand for the effective address of the 218 * store instruction 219 */ 220 protected final MemoryOperand MO_S(Instruction s, byte size, int disp) { 221 if (VM.VerifyAssertions) VM._assert(Store.conforms(s)); 222 return MO(Store.getAddress(s), 223 Store.getOffset(s), 224 size, 225 Offset.fromIntSignExtend(disp), 226 Store.getLocation(s), 227 Store.getGuard(s)); 228 } 229 230 protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, 231 Operand guard) { 232 if (base instanceof IntConstantOperand) { 233 if (offset instanceof IntConstantOperand) { 234 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset)), size, loc, guard); 235 } else { 236 return MO_BD(offset, Offset.fromIntSignExtend(IV(base)), size, loc, guard); 237 } 238 } else { 239 if (offset instanceof IntConstantOperand) { 240 return MO_BD(base, Offset.fromIntSignExtend(IV(offset)), size, loc, guard); 241 } else { 242 return MO_BI(base, offset, size, loc, guard); 243 } 244 } 245 } 246 247 protected final MemoryOperand MO(Operand base, Operand offset, byte size, LocationOperand loc, 248 Operand guard, int disp) { 249 if (base instanceof IntConstantOperand) { 250 if (offset instanceof IntConstantOperand) { 251 return MO_D(Offset.fromIntSignExtend(IV(base) + IV(offset) + disp), size, loc, guard); 252 } else { 253 return MO_BD(offset, Offset.fromIntSignExtend(IV(base)+disp), size, loc, guard); 254 } 255 } else { 256 if (offset instanceof IntConstantOperand) { 257 return MO_BD(base, Offset.fromIntSignExtend(IV(offset)+disp), size, loc, guard); 258 } else { 259 return MO_BID(base, offset, Offset.fromIntSignExtend(disp), size, loc, guard); 260 } 261 } 262 } 263 264 protected final MemoryOperand MO(Operand base, Operand offset, byte size, Offset disp, 265 LocationOperand loc, Operand guard) { 266 if (base instanceof IntConstantOperand) { 267 if (offset instanceof IntConstantOperand) { 268 return MO_D(disp.plus(IV(base) + IV(offset)), size, loc, guard); 269 } else { 270 return MO_BD(offset, disp.plus(IV(base)), size, loc, guard); 271 } 272 } else { 273 if (offset instanceof IntConstantOperand) { 274 return MO_BD(base, disp.plus(IV(offset)), size, loc, guard); 275 } else { 276 return MO_BID(base, offset, disp, size, loc, guard); 277 } 278 } 279 } 280 281 282 protected final MemoryOperand MO_B(Operand base, byte size, LocationOperand loc, Operand guard) { 283 return MemoryOperand.B(R(base), size, loc, guard); 284 } 285 286 protected final MemoryOperand MO_BI(Operand base, Operand index, byte size, LocationOperand loc, 287 Operand guard) { 288 return MemoryOperand.BI(R(base), R(index), size, loc, guard); 289 } 290 291 protected final MemoryOperand MO_BD(Operand base, Offset disp, byte size, LocationOperand loc, 292 Operand guard) { 293 return MemoryOperand.BD(R(base), disp, size, loc, guard); 294 } 295 296 protected final MemoryOperand MO_BID(Operand base, Operand index, Offset disp, byte size, 297 LocationOperand loc, Operand guard) { 298 return MemoryOperand.BID(R(base), R(index), disp, size, loc, guard); 299 } 300 301 protected final MemoryOperand MO_BIS(Operand base, Operand index, byte scale, byte size, 302 LocationOperand loc, Operand guard) { 303 return MemoryOperand.BIS(R(base), R(index), scale, size, loc, guard); 304 } 305 306 protected final MemoryOperand MO_D(Offset disp, byte size, LocationOperand loc, Operand guard) { 307 return MemoryOperand.D(disp.toWord().toAddress(), size, loc, guard); 308 } 309 310 /** 311 * Construct a memory operand for the effective address of the 312 * array load instruction 313 */ 314 protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size) { 315 return MO_AL(s, scale, size, 0); 316 } 317 318 /** 319 * Construct a memory operand for the effective address of the 320 * array load instruction 321 */ 322 protected final MemoryOperand MO_AL(Instruction s, byte scale, byte size, int disp) { 323 if (VM.VerifyAssertions) VM._assert(ALoad.conforms(s)); 324 return MO_ARRAY(ALoad.getArray(s), 325 ALoad.getIndex(s), 326 scale, 327 size, 328 Offset.fromIntSignExtend(disp), 329 ALoad.getLocation(s), 330 ALoad.getGuard(s)); 331 } 332 333 /** 334 * Construct a memory operand for the effective address of the 335 * array store instruction 336 */ 337 protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size) { 338 return MO_AS(s, scale, size, 0); 339 } 340 341 342 // Construct a memory operand for the effective address of the array store instruction 343 protected final MemoryOperand MO_AS(Instruction s, byte scale, byte size, int disp) { 344 if (VM.VerifyAssertions) VM._assert(AStore.conforms(s)); 345 return MO_ARRAY(AStore.getArray(s), 346 AStore.getIndex(s), 347 scale, 348 size, 349 Offset.fromIntSignExtend(disp), 350 AStore.getLocation(s), 351 AStore.getGuard(s)); 352 } 353 354 /** 355 * Construct memory operand for an array access 356 */ 357 private MemoryOperand MO_ARRAY(Operand base, Operand index, byte scale, byte size, Offset disp, 358 LocationOperand loc, Operand guard) { 359 if (base instanceof IntConstantOperand) { 360 if (index instanceof IntConstantOperand) { 361 return MO_D(disp.plus(IV(base) + (IV(index) << scale)), size, loc, guard); 362 } else { 363 return new MemoryOperand(null, R(index), scale, disp.plus(IV(base)), size, loc, guard); 364 } 365 } else { 366 if (index instanceof IntConstantOperand) { 367 return MO_BD(base, disp.plus(IV(index) << scale), size, loc, guard); 368 } else { 369 return new MemoryOperand(R(base), R(index), scale, disp, size, loc, guard); 370 } 371 } 372 } 373 374 /** 375 * Construct memory operand for a MATERIALIZE_FP_CONSTANT 376 */ 377 protected final MemoryOperand MO_MC(Instruction s) { 378 Operand base = Binary.getVal1(s); // JTOC 379 Operand val = Binary.getVal2(s); // float or double value 380 if (val instanceof FloatConstantOperand) { 381 FloatConstantOperand fc = (FloatConstantOperand) val; 382 Offset offset = fc.offset; 383 LocationOperand loc = new LocationOperand(offset); 384 if (base instanceof IntConstantOperand) { 385 return MO_D(offset.plus(IV(base)), DW, loc, TG()); 386 } else { 387 return MO_BD(base, offset, DW, loc, TG()); 388 } 389 } else { 390 DoubleConstantOperand dc = (DoubleConstantOperand) val; 391 Offset offset = dc.offset; 392 LocationOperand loc = new LocationOperand(offset); 393 if (base instanceof IntConstantOperand) { 394 return MO_D(offset.plus(IV(base)), QW, loc, TG()); 395 } else { 396 return MO_BD(Binary.getVal1(s), dc.offset, QW, loc, TG()); 397 } 398 } 399 } 400 }