src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java

Print this page




  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 }
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File