12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir.alloc.lsra; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.isIllegal; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 29 import java.util.ArrayList; 30 31 import org.graalvm.compiler.core.common.LIRKind; 32 import org.graalvm.compiler.debug.Debug; 33 import org.graalvm.compiler.debug.DebugCounter; 34 import org.graalvm.compiler.debug.GraalError; 35 import org.graalvm.compiler.debug.Indent; 36 import org.graalvm.compiler.lir.LIRInsertionBuffer; 37 import org.graalvm.compiler.lir.LIRInstruction; 38 import org.graalvm.compiler.lir.LIRValueUtil; 39 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 40 import org.graalvm.util.Equivalence; 41 import org.graalvm.util.EconomicSet; 42 43 import jdk.vm.ci.meta.AllocatableValue; 44 import jdk.vm.ci.meta.Constant; 45 import jdk.vm.ci.meta.Value; 46 47 /** 48 */ 49 public class MoveResolver { 50 51 private static final DebugCounter cycleBreakingSlotsAllocated = Debug.counter("LSRA[cycleBreakingSlotsAllocated]"); 52 53 private final LinearScan allocator; 54 55 private int insertIdx; 56 private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted 57 58 private final ArrayList<Interval> mappingFrom; 59 private final ArrayList<Constant> mappingFromOpr; 60 private final ArrayList<Interval> mappingTo; 61 private boolean multipleReadsAllowed; 62 private final int[] registerBlocked; 63 64 private final LIRGenerationResult res; 65 66 protected void setValueBlocked(Value location, int direction) { 67 assert direction == 1 || direction == -1 : "out of bounds"; 68 if (isRegister(location)) { 69 registerBlocked[asRegister(location).number] += direction; 70 } else { 71 throw GraalError.shouldNotReachHere("unhandled value " + location); 190 assert !usedRegs.contains(interval.location()) || 191 checkIntervalLocation(mappingFrom.get(i), interval, mappingFromOpr.get(i)) : "stack slots used in mappingFrom must be disjoint to mappingTo"; 192 } 193 } 194 195 private static boolean checkIntervalLocation(Interval from, Interval to, Constant fromOpr) { 196 if (from == null) { 197 return fromOpr != null; 198 } else { 199 return to.location().equals(from.location()); 200 } 201 } 202 203 // mark assignedReg and assignedRegHi of the interval as blocked 204 private void blockRegisters(Interval interval) { 205 Value location = interval.location(); 206 if (mightBeBlocked(location)) { 207 assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; 208 int direction = 1; 209 setValueBlocked(location, direction); 210 Debug.log("block %s", location); 211 } 212 } 213 214 // mark assignedReg and assignedRegHi of the interval as unblocked 215 private void unblockRegisters(Interval interval) { 216 Value location = interval.location(); 217 if (mightBeBlocked(location)) { 218 assert valueBlocked(location) > 0 : "location already marked as unused: " + location; 219 setValueBlocked(location, -1); 220 Debug.log("unblock %s", location); 221 } 222 } 223 224 /** 225 * Checks if the {@linkplain Interval#location() location} of {@code to} is not blocked or is 226 * only blocked by {@code from}. 227 */ 228 private boolean safeToProcessMove(Interval from, Interval to) { 229 Value fromReg = from != null ? from.location() : null; 230 231 Value location = to.location(); 232 if (mightBeBlocked(location)) { 233 if ((valueBlocked(location) > 1 || (valueBlocked(location) == 1 && !isMoveToSelf(fromReg, location)))) { 234 return false; 235 } 236 } 237 238 return true; 239 } 240 259 insertionBuffer.init(list); 260 } 261 262 private void appendInsertionBuffer() { 263 if (insertionBuffer.initialized()) { 264 insertionBuffer.finish(); 265 } 266 assert !insertionBuffer.initialized() : "must be uninitialized now"; 267 268 insertIdx = -1; 269 } 270 271 private LIRInstruction insertMove(Interval fromInterval, Interval toInterval) { 272 assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 273 assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : "move between different types"; 274 assert insertIdx != -1 : "must setup insert position first"; 275 276 LIRInstruction move = createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location()); 277 insertionBuffer.append(insertIdx, move); 278 279 if (Debug.isLogEnabled()) { 280 Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); 281 } 282 return move; 283 } 284 285 /** 286 * @param fromOpr {@link Interval#operand operand} of the {@code from} interval 287 * @param toOpr {@link Interval#operand operand} of the {@code to} interval 288 * @param fromLocation {@link Interval#location() location} of the {@code to} interval 289 * @param toLocation {@link Interval#location() location} of the {@code to} interval 290 */ 291 protected LIRInstruction createMove(AllocatableValue fromOpr, AllocatableValue toOpr, AllocatableValue fromLocation, AllocatableValue toLocation) { 292 return getAllocator().getSpillMoveFactory().createMove(toOpr, fromOpr); 293 } 294 295 private LIRInstruction insertMove(Constant fromOpr, Interval toInterval) { 296 assert insertIdx != -1 : "must setup insert position first"; 297 298 AllocatableValue toOpr = toInterval.operand; 299 LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr); 300 insertionBuffer.append(insertIdx, move); 301 302 if (Debug.isLogEnabled()) { 303 Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); 304 } 305 return move; 306 } 307 308 @SuppressWarnings("try") 309 private void resolveMappings() { 310 try (Indent indent = Debug.logAndIndent("resolveMapping")) { 311 assert verifyBeforeResolve(); 312 if (Debug.isLogEnabled()) { 313 printMapping(); 314 } 315 316 // Block all registers that are used as input operands of a move. 317 // When a register is blocked, no move to this register is emitted. 318 // This is necessary for detecting cycles in moves. 319 int i; 320 for (i = mappingFrom.size() - 1; i >= 0; i--) { 321 Interval fromInterval = mappingFrom.get(i); 322 if (fromInterval != null) { 323 blockRegisters(fromInterval); 324 } 325 } 326 327 ArrayList<AllocatableValue> busySpillSlots = null; 328 while (mappingFrom.size() > 0) { 329 boolean processedInterval = false; 330 331 int spillCandidate = -1; 332 for (i = mappingFrom.size() - 1; i >= 0; i--) { 372 multipleReadsAllowed = false; 373 374 // check that all intervals have been processed 375 assert checkEmpty(); 376 } 377 378 protected void breakCycle(int spillCandidate) { 379 // no move could be processed because there is a cycle in the move list 380 // (e.g. r1 . r2, r2 . r1), so one interval must be spilled to memory 381 assert spillCandidate != -1 : "no interval in register for spilling found"; 382 383 // create a new spill interval and assign a stack slot to it 384 Interval fromInterval = mappingFrom.get(spillCandidate); 385 // do not allocate a new spill slot for temporary interval, but 386 // use spill slot assigned to fromInterval. Otherwise moves from 387 // one stack slot to another can happen (not allowed by LIRAssembler 388 AllocatableValue spillSlot = fromInterval.spillSlot(); 389 if (spillSlot == null) { 390 spillSlot = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval.kind()); 391 fromInterval.setSpillSlot(spillSlot); 392 cycleBreakingSlotsAllocated.increment(); 393 } 394 spillInterval(spillCandidate, fromInterval, spillSlot); 395 } 396 397 protected void spillInterval(int spillCandidate, Interval fromInterval, AllocatableValue spillSlot) { 398 assert mappingFrom.get(spillCandidate).equals(fromInterval); 399 Interval spillInterval = getAllocator().createDerivedInterval(fromInterval); 400 spillInterval.setKind(fromInterval.kind()); 401 402 // add a dummy range because real position is difficult to calculate 403 // Note: this range is a special case when the integrity of the allocation is 404 // checked 405 spillInterval.addRange(1, 2); 406 407 spillInterval.assignLocation(spillSlot); 408 409 if (Debug.isLogEnabled()) { 410 Debug.log("created new Interval for spilling: %s", spillInterval); 411 } 412 blockRegisters(spillInterval); 413 414 // insert a move from register to stack and update the mapping 415 LIRInstruction move = insertMove(fromInterval, spillInterval); 416 mappingFrom.set(spillCandidate, spillInterval); 417 unblockRegisters(fromInterval); 418 move.setComment(res, "MoveResolver break cycle"); 419 } 420 421 @SuppressWarnings("try") 422 private void printMapping() { 423 try (Indent indent = Debug.logAndIndent("Mapping")) { 424 for (int i = mappingFrom.size() - 1; i >= 0; i--) { 425 Interval fromInterval = mappingFrom.get(i); 426 Interval toInterval = mappingTo.get(i); 427 String from; 428 Value to = toInterval.location(); 429 if (fromInterval == null) { 430 from = mappingFromOpr.get(i).toString(); 431 } else { 432 from = fromInterval.location().toString(); 433 } 434 Debug.log("move %s <- %s", from, to); 435 } 436 } 437 } 438 439 void setInsertPosition(ArrayList<LIRInstruction> insertList, int insertIdx) { 440 assert this.insertIdx == -1 : "use moveInsertPosition instead of setInsertPosition when data already set"; 441 442 createInsertionBuffer(insertList); 443 this.insertIdx = insertIdx; 444 } 445 446 void moveInsertPosition(ArrayList<LIRInstruction> newInsertList, int newInsertIdx) { 447 if (insertionBuffer.lirList() != null && (insertionBuffer.lirList() != newInsertList || this.insertIdx != newInsertIdx)) { 448 // insert position changed . resolve current mappings 449 resolveMappings(); 450 } 451 452 if (insertionBuffer.lirList() != newInsertList) { 453 // block changed . append insertionBuffer because it is 454 // bound to a specific block and create a new insertionBuffer 455 appendInsertionBuffer(); 456 createInsertionBuffer(newInsertList); 457 } 458 459 this.insertIdx = newInsertIdx; 460 } 461 462 public void addMapping(Interval fromInterval, Interval toInterval) { 463 464 if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { 465 if (Debug.isLogEnabled()) { 466 Debug.log("no store to rematerializable interval %s needed", toInterval); 467 } 468 return; 469 } 470 if (isIllegal(fromInterval.location()) && fromInterval.canMaterialize()) { 471 // Instead of a reload, re-materialize the value 472 Constant rematValue = fromInterval.getMaterializedValue(); 473 addMapping(rematValue, toInterval); 474 return; 475 } 476 if (Debug.isLogEnabled()) { 477 Debug.log("add move mapping from %s to %s", fromInterval, toInterval); 478 } 479 480 assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 481 assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s", fromInterval.kind(), 482 toInterval.kind(), fromInterval, toInterval); 483 mappingFrom.add(fromInterval); 484 mappingFromOpr.add(null); 485 mappingTo.add(toInterval); 486 } 487 488 public void addMapping(Constant fromOpr, Interval toInterval) { 489 if (Debug.isLogEnabled()) { 490 Debug.log("add move mapping from %s to %s", fromOpr, toInterval); 491 } 492 493 mappingFrom.add(null); 494 mappingFromOpr.add(fromOpr); 495 mappingTo.add(toInterval); 496 } 497 498 void resolveAndAppendMoves() { 499 if (hasMappings()) { 500 resolveMappings(); 501 } 502 appendInsertionBuffer(); 503 } 504 } | 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir.alloc.lsra; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.isIllegal; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 29 import java.util.ArrayList; 30 31 import org.graalvm.compiler.core.common.LIRKind; 32 import org.graalvm.compiler.debug.CounterKey; 33 import org.graalvm.compiler.debug.DebugContext; 34 import org.graalvm.compiler.debug.GraalError; 35 import org.graalvm.compiler.debug.Indent; 36 import org.graalvm.compiler.lir.LIRInsertionBuffer; 37 import org.graalvm.compiler.lir.LIRInstruction; 38 import org.graalvm.compiler.lir.LIRValueUtil; 39 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 40 import org.graalvm.util.Equivalence; 41 import org.graalvm.util.EconomicSet; 42 import jdk.vm.ci.meta.AllocatableValue; 43 import jdk.vm.ci.meta.Constant; 44 import jdk.vm.ci.meta.Value; 45 46 /** 47 */ 48 public class MoveResolver { 49 50 private static final CounterKey cycleBreakingSlotsAllocated = DebugContext.counter("LSRA[cycleBreakingSlotsAllocated]"); 51 52 private final LinearScan allocator; 53 54 private int insertIdx; 55 private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted 56 57 private final ArrayList<Interval> mappingFrom; 58 private final ArrayList<Constant> mappingFromOpr; 59 private final ArrayList<Interval> mappingTo; 60 private boolean multipleReadsAllowed; 61 private final int[] registerBlocked; 62 63 private final LIRGenerationResult res; 64 65 protected void setValueBlocked(Value location, int direction) { 66 assert direction == 1 || direction == -1 : "out of bounds"; 67 if (isRegister(location)) { 68 registerBlocked[asRegister(location).number] += direction; 69 } else { 70 throw GraalError.shouldNotReachHere("unhandled value " + location); 189 assert !usedRegs.contains(interval.location()) || 190 checkIntervalLocation(mappingFrom.get(i), interval, mappingFromOpr.get(i)) : "stack slots used in mappingFrom must be disjoint to mappingTo"; 191 } 192 } 193 194 private static boolean checkIntervalLocation(Interval from, Interval to, Constant fromOpr) { 195 if (from == null) { 196 return fromOpr != null; 197 } else { 198 return to.location().equals(from.location()); 199 } 200 } 201 202 // mark assignedReg and assignedRegHi of the interval as blocked 203 private void blockRegisters(Interval interval) { 204 Value location = interval.location(); 205 if (mightBeBlocked(location)) { 206 assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; 207 int direction = 1; 208 setValueBlocked(location, direction); 209 allocator.getDebug().log("block %s", location); 210 } 211 } 212 213 // mark assignedReg and assignedRegHi of the interval as unblocked 214 private void unblockRegisters(Interval interval) { 215 Value location = interval.location(); 216 if (mightBeBlocked(location)) { 217 assert valueBlocked(location) > 0 : "location already marked as unused: " + location; 218 setValueBlocked(location, -1); 219 allocator.getDebug().log("unblock %s", location); 220 } 221 } 222 223 /** 224 * Checks if the {@linkplain Interval#location() location} of {@code to} is not blocked or is 225 * only blocked by {@code from}. 226 */ 227 private boolean safeToProcessMove(Interval from, Interval to) { 228 Value fromReg = from != null ? from.location() : null; 229 230 Value location = to.location(); 231 if (mightBeBlocked(location)) { 232 if ((valueBlocked(location) > 1 || (valueBlocked(location) == 1 && !isMoveToSelf(fromReg, location)))) { 233 return false; 234 } 235 } 236 237 return true; 238 } 239 258 insertionBuffer.init(list); 259 } 260 261 private void appendInsertionBuffer() { 262 if (insertionBuffer.initialized()) { 263 insertionBuffer.finish(); 264 } 265 assert !insertionBuffer.initialized() : "must be uninitialized now"; 266 267 insertIdx = -1; 268 } 269 270 private LIRInstruction insertMove(Interval fromInterval, Interval toInterval) { 271 assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 272 assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : "move between different types"; 273 assert insertIdx != -1 : "must setup insert position first"; 274 275 LIRInstruction move = createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location()); 276 insertionBuffer.append(insertIdx, move); 277 278 DebugContext debug = allocator.getDebug(); 279 if (debug.isLogEnabled()) { 280 debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); 281 } 282 return move; 283 } 284 285 /** 286 * @param fromOpr {@link Interval#operand operand} of the {@code from} interval 287 * @param toOpr {@link Interval#operand operand} of the {@code to} interval 288 * @param fromLocation {@link Interval#location() location} of the {@code to} interval 289 * @param toLocation {@link Interval#location() location} of the {@code to} interval 290 */ 291 protected LIRInstruction createMove(AllocatableValue fromOpr, AllocatableValue toOpr, AllocatableValue fromLocation, AllocatableValue toLocation) { 292 return getAllocator().getSpillMoveFactory().createMove(toOpr, fromOpr); 293 } 294 295 private LIRInstruction insertMove(Constant fromOpr, Interval toInterval) { 296 assert insertIdx != -1 : "must setup insert position first"; 297 298 AllocatableValue toOpr = toInterval.operand; 299 LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr); 300 insertionBuffer.append(insertIdx, move); 301 302 DebugContext debug = allocator.getDebug(); 303 if (debug.isLogEnabled()) { 304 debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); 305 } 306 return move; 307 } 308 309 @SuppressWarnings("try") 310 private void resolveMappings() { 311 DebugContext debug = allocator.getDebug(); 312 try (Indent indent = debug.logAndIndent("resolveMapping")) { 313 assert verifyBeforeResolve(); 314 if (debug.isLogEnabled()) { 315 printMapping(); 316 } 317 318 // Block all registers that are used as input operands of a move. 319 // When a register is blocked, no move to this register is emitted. 320 // This is necessary for detecting cycles in moves. 321 int i; 322 for (i = mappingFrom.size() - 1; i >= 0; i--) { 323 Interval fromInterval = mappingFrom.get(i); 324 if (fromInterval != null) { 325 blockRegisters(fromInterval); 326 } 327 } 328 329 ArrayList<AllocatableValue> busySpillSlots = null; 330 while (mappingFrom.size() > 0) { 331 boolean processedInterval = false; 332 333 int spillCandidate = -1; 334 for (i = mappingFrom.size() - 1; i >= 0; i--) { 374 multipleReadsAllowed = false; 375 376 // check that all intervals have been processed 377 assert checkEmpty(); 378 } 379 380 protected void breakCycle(int spillCandidate) { 381 // no move could be processed because there is a cycle in the move list 382 // (e.g. r1 . r2, r2 . r1), so one interval must be spilled to memory 383 assert spillCandidate != -1 : "no interval in register for spilling found"; 384 385 // create a new spill interval and assign a stack slot to it 386 Interval fromInterval = mappingFrom.get(spillCandidate); 387 // do not allocate a new spill slot for temporary interval, but 388 // use spill slot assigned to fromInterval. Otherwise moves from 389 // one stack slot to another can happen (not allowed by LIRAssembler 390 AllocatableValue spillSlot = fromInterval.spillSlot(); 391 if (spillSlot == null) { 392 spillSlot = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval.kind()); 393 fromInterval.setSpillSlot(spillSlot); 394 cycleBreakingSlotsAllocated.increment(allocator.getDebug()); 395 } 396 spillInterval(spillCandidate, fromInterval, spillSlot); 397 } 398 399 protected void spillInterval(int spillCandidate, Interval fromInterval, AllocatableValue spillSlot) { 400 assert mappingFrom.get(spillCandidate).equals(fromInterval); 401 Interval spillInterval = getAllocator().createDerivedInterval(fromInterval); 402 spillInterval.setKind(fromInterval.kind()); 403 404 // add a dummy range because real position is difficult to calculate 405 // Note: this range is a special case when the integrity of the allocation is 406 // checked 407 spillInterval.addRange(1, 2); 408 409 spillInterval.assignLocation(spillSlot); 410 411 DebugContext debug = allocator.getDebug(); 412 if (debug.isLogEnabled()) { 413 debug.log("created new Interval for spilling: %s", spillInterval); 414 } 415 blockRegisters(spillInterval); 416 417 // insert a move from register to stack and update the mapping 418 LIRInstruction move = insertMove(fromInterval, spillInterval); 419 mappingFrom.set(spillCandidate, spillInterval); 420 unblockRegisters(fromInterval); 421 move.setComment(res, "MoveResolver break cycle"); 422 } 423 424 @SuppressWarnings("try") 425 private void printMapping() { 426 DebugContext debug = allocator.getDebug(); 427 try (Indent indent = debug.logAndIndent("Mapping")) { 428 for (int i = mappingFrom.size() - 1; i >= 0; i--) { 429 Interval fromInterval = mappingFrom.get(i); 430 Interval toInterval = mappingTo.get(i); 431 String from; 432 Value to = toInterval.location(); 433 if (fromInterval == null) { 434 from = mappingFromOpr.get(i).toString(); 435 } else { 436 from = fromInterval.location().toString(); 437 } 438 debug.log("move %s <- %s", from, to); 439 } 440 } 441 } 442 443 void setInsertPosition(ArrayList<LIRInstruction> insertList, int insertIdx) { 444 assert this.insertIdx == -1 : "use moveInsertPosition instead of setInsertPosition when data already set"; 445 446 createInsertionBuffer(insertList); 447 this.insertIdx = insertIdx; 448 } 449 450 void moveInsertPosition(ArrayList<LIRInstruction> newInsertList, int newInsertIdx) { 451 if (insertionBuffer.lirList() != null && (insertionBuffer.lirList() != newInsertList || this.insertIdx != newInsertIdx)) { 452 // insert position changed . resolve current mappings 453 resolveMappings(); 454 } 455 456 if (insertionBuffer.lirList() != newInsertList) { 457 // block changed . append insertionBuffer because it is 458 // bound to a specific block and create a new insertionBuffer 459 appendInsertionBuffer(); 460 createInsertionBuffer(newInsertList); 461 } 462 463 this.insertIdx = newInsertIdx; 464 } 465 466 public void addMapping(Interval fromInterval, Interval toInterval) { 467 DebugContext debug = allocator.getDebug(); 468 if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { 469 if (debug.isLogEnabled()) { 470 debug.log("no store to rematerializable interval %s needed", toInterval); 471 } 472 return; 473 } 474 if (isIllegal(fromInterval.location()) && fromInterval.canMaterialize()) { 475 // Instead of a reload, re-materialize the value 476 Constant rematValue = fromInterval.getMaterializedValue(); 477 addMapping(rematValue, toInterval); 478 return; 479 } 480 if (debug.isLogEnabled()) { 481 debug.log("add move mapping from %s to %s", fromInterval, toInterval); 482 } 483 484 assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 485 assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s", fromInterval.kind(), 486 toInterval.kind(), fromInterval, toInterval); 487 mappingFrom.add(fromInterval); 488 mappingFromOpr.add(null); 489 mappingTo.add(toInterval); 490 } 491 492 public void addMapping(Constant fromOpr, Interval toInterval) { 493 DebugContext debug = allocator.getDebug(); 494 if (debug.isLogEnabled()) { 495 debug.log("add move mapping from %s to %s", fromOpr, toInterval); 496 } 497 498 mappingFrom.add(null); 499 mappingFromOpr.add(fromOpr); 500 mappingTo.add(toInterval); 501 } 502 503 void resolveAndAppendMoves() { 504 if (hasMappings()) { 505 resolveMappings(); 506 } 507 appendInsertionBuffer(); 508 } 509 } |