1 // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 5 package com.android.tools.r8.ir.regalloc; 6 7 import com.android.tools.r8.dex.Constants; 8 import com.android.tools.r8.graph.DebugLocalInfo; 9 import com.android.tools.r8.ir.code.Add; 10 import com.android.tools.r8.ir.code.And; 11 import com.android.tools.r8.ir.code.BasicBlock; 12 import com.android.tools.r8.ir.code.DebugLocalsChange; 13 import com.android.tools.r8.ir.code.IRCode; 14 import com.android.tools.r8.ir.code.Instruction; 15 import com.android.tools.r8.ir.code.InstructionListIterator; 16 import com.android.tools.r8.ir.code.Invoke; 17 import com.android.tools.r8.ir.code.Move; 18 import com.android.tools.r8.ir.code.MoveType; 19 import com.android.tools.r8.ir.code.NumericType; 20 import com.android.tools.r8.ir.code.Or; 21 import com.android.tools.r8.ir.code.Phi; 22 import com.android.tools.r8.ir.code.Sub; 23 import com.android.tools.r8.ir.code.Value; 24 import com.android.tools.r8.ir.code.Xor; 25 import com.android.tools.r8.logging.Log; 26 import com.android.tools.r8.utils.CfgPrinter; 27 import com.android.tools.r8.utils.InternalOptions; 28 import com.android.tools.r8.utils.ListUtils; 29 import com.android.tools.r8.utils.StringUtils; 30 import com.google.common.collect.HashMultiset; 31 import com.google.common.collect.ImmutableMap; 32 import com.google.common.collect.Multiset; 33 import com.google.common.collect.Multiset.Entry; 34 import com.google.common.collect.Multisets; 35 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; 36 import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; 37 import it.unimi.dsi.fastutil.ints.IntArraySet; 38 import it.unimi.dsi.fastutil.ints.IntIterator; 39 import it.unimi.dsi.fastutil.ints.IntSet; 40 import java.util.ArrayList; 41 import java.util.Comparator; 42 import java.util.HashMap; 43 import java.util.HashSet; 44 import java.util.IdentityHashMap; 45 import java.util.Iterator; 46 import java.util.LinkedList; 47 import java.util.List; 48 import java.util.ListIterator; 49 import java.util.Map; 50 import java.util.PriorityQueue; 51 import java.util.Queue; 52 import java.util.Set; 53 import java.util.TreeSet; 54 55 /** 56 * Linear scan register allocator. 57 * 58 * <p>The implementation is inspired by: 59 * 60 * <ul> 61 * <li>"Linear Scan Register Allocation in the Context of SSA Form and Register Constraints" 62 * (ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF)</li> 63 * <li>"Linear Scan Register Allocation on SSA Form" 64 * (http://www.christianwimmer.at/Publications/Wimmer10a/Wimmer10a.pdf)</li> 65 * <li>"Linear Scan Register Allocation for the Java HotSpot Client Compiler" 66 * (http://www.christianwimmer.at/Publications/Wimmer04a/Wimmer04a.pdf)</li> 67 * </ul> 68 */ 69 public class LinearScanRegisterAllocator implements RegisterAllocator { 70 public static final int NO_REGISTER = Integer.MIN_VALUE; 71 public static final int REGISTER_CANDIDATE_NOT_FOUND = -1; 72 public static final int MIN_CONSTANT_FREE_FOR_POSITIONS = 5; 73 74 private enum ArgumentReuseMode { 75 ALLOW_ARGUMENT_REUSE, 76 DISALLOW_ARGUMENT_REUSE 77 } 78 79 private static class LocalRange implements Comparable<LocalRange> { 80 final DebugLocalInfo local; 81 final int register; 82 final int start; 83 final int end; 84 LocalRange(Value value, int register, int start, int end)85 LocalRange(Value value, int register, int start, int end) { 86 assert value.getLocalInfo() != null; 87 this.local = value.getLocalInfo(); 88 this.register = register; 89 this.start = start; 90 this.end = end; 91 } 92 93 @Override compareTo(LocalRange o)94 public int compareTo(LocalRange o) { 95 return (start != o.start) 96 ? Integer.compare(start, o.start) 97 : Integer.compare(end, o.end); 98 } 99 100 @Override toString()101 public String toString() { 102 return local + " @ r" + register + ": " + new LiveRange(start, end); 103 } 104 } 105 106 // When numbering instructions we number instructions only with even numbers. This allows us to 107 // use odd instruction numbers for the insertion of moves during spilling. 108 public static final int INSTRUCTION_NUMBER_DELTA = 2; 109 // The max register number that will fit in any dex instruction encoding. 110 private static final int MAX_SMALL_REGISTER = Constants.U4BIT_MAX; 111 // We put one sentinel in front of the argument chain and one after the argument chain. 112 private static final int NUMBER_OF_SENTINEL_REGISTERS = 2; 113 114 // The code for which to allocate registers. 115 private final IRCode code; 116 // Number of registers used for arguments. 117 private final int numberOfArgumentRegisters; 118 // Compiler options. 119 private final InternalOptions options; 120 121 // Mapping from basic blocks to the set of values live at entry to that basic block. 122 private Map<BasicBlock, Set<Value>> liveAtEntrySets = new IdentityHashMap<>(); 123 // The sentinel value starting the chain of linked argument values. 124 private Value preArgumentSentinelValue = null; 125 126 // The set of registers that are free for allocation. 127 private TreeSet<Integer> freeRegisters = new TreeSet<>(); 128 // The max register number used. 129 private int maxRegisterNumber = 0; 130 // The next available register number not yet included in the set of used registers. 131 private int nextUnusedRegisterNumber = 0; 132 133 // List of all top-level live intervals for all SSA values. 134 private List<LiveIntervals> liveIntervals = new ArrayList<>(); 135 // List of active intervals. 136 private List<LiveIntervals> active = new LinkedList<>(); 137 // List of intervals where the current instruction falls into one of their live range holes. 138 private List<LiveIntervals> inactive = new LinkedList<>(); 139 // List of intervals that no register has been allocated to sorted by first live range. 140 private PriorityQueue<LiveIntervals> unhandled = 141 new PriorityQueue<>(Comparator.comparingInt(LiveIntervals::getStart)); 142 143 // The first register used for parallel moves. After register allocation the parallel move 144 // temporary registers are [firstParallelMoveTemporary, maxRegisterNumber]. 145 private int firstParallelMoveTemporary = NO_REGISTER; 146 // Mapping from register number to the number of unused register numbers below that register 147 // number. Used for compacting the register numbers if some spill registers are not used 148 // because their values can be rematerialized. 149 private int[] unusedRegisters = null; 150 151 // Whether or not the code has a move exception instruction. Used to pin the move exception 152 // register. 153 private boolean hasDedicatedMoveExceptionRegister = false; 154 LinearScanRegisterAllocator(IRCode code, InternalOptions options)155 public LinearScanRegisterAllocator(IRCode code, InternalOptions options) { 156 this.code = code; 157 this.options = options; 158 int argumentRegisters = 0; 159 for (Instruction instruction : code.blocks.getFirst().getInstructions()) { 160 if (instruction.isArgument()) { 161 argumentRegisters += instruction.outValue().requiredRegisters(); 162 } 163 } 164 numberOfArgumentRegisters = argumentRegisters; 165 } 166 167 /** 168 * Perform register allocation for the IRCode. 169 */ allocateRegisters(boolean debug)170 public void allocateRegisters(boolean debug) { 171 // There are no linked values prior to register allocation. 172 assert noLinkedValues(); 173 assert code.isConsistentSSA(); 174 computeNeedsRegister(); 175 insertArgumentMoves(); 176 BasicBlock[] blocks = computeLivenessInformation(); 177 // First attempt to allocate register allowing argument reuse. This will fail if spilling 178 // is required or if we end up using more than 16 registers. 179 boolean noSpilling = 180 performAllocationWithoutMoveInsertion(ArgumentReuseMode.ALLOW_ARGUMENT_REUSE); 181 if (!noSpilling || (highestUsedRegister() > MAX_SMALL_REGISTER)) { 182 // Redo allocation disallowing argument reuse. This always succeeds. 183 clearRegisterAssignments(); 184 performAllocation(ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE); 185 } else { 186 // Insert spill and phi moves after allocating with argument reuse. If the moves causes 187 // the method to use more than 16 registers we redo allocation disallowing argument 188 // reuse. This very rarely happens in practice (12 methods on GMSCore v4 hits that case). 189 insertMoves(); 190 if (highestUsedRegister() > MAX_SMALL_REGISTER) { 191 // Redo allocation disallowing argument reuse. This always succeeds. 192 clearRegisterAssignments(); 193 removeSpillAndPhiMoves(); 194 performAllocation(ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE); 195 } 196 } 197 198 clearUserInfo(); 199 assert code.isConsistentGraph(); 200 if (Log.ENABLED) { 201 Log.debug(this.getClass(), toString()); 202 } 203 computeUnusedRegisters(); 204 if (debug) { 205 computeDebugInfo(blocks); 206 } 207 clearState(); 208 } 209 nextInRange(int start, int end, List<Integer> points)210 private static Integer nextInRange(int start, int end, List<Integer> points) { 211 while (!points.isEmpty() && points.get(0) < start) { 212 points.remove(0); 213 } 214 if (points.isEmpty()) { 215 return null; 216 } 217 Integer next = points.get(0); 218 assert start <= next; 219 if (next < end) { 220 points.remove(0); 221 return next; 222 } 223 return null; 224 } 225 computeDebugInfo(BasicBlock[] blocks)226 private void computeDebugInfo(BasicBlock[] blocks) { 227 // Collect live-ranges for all SSA values with local information. 228 List<LocalRange> ranges = new ArrayList<>(); 229 for (LiveIntervals interval : liveIntervals) { 230 Value value = interval.getValue(); 231 if (value.getLocalInfo() == null) { 232 continue; 233 } 234 List<Integer> starts = ListUtils.map(value.getDebugLocalStarts(), Instruction::getNumber); 235 List<Integer> ends = ListUtils.map(value.getDebugLocalEnds(), Instruction::getNumber); 236 List<LiveRange> liveRanges = new ArrayList<>(); 237 liveRanges.addAll(interval.getRanges()); 238 for (LiveIntervals child : interval.getSplitChildren()) { 239 assert child.getValue() == value; 240 assert child.getSplitChildren() == null || child.getSplitChildren().isEmpty(); 241 liveRanges.addAll(child.getRanges()); 242 } 243 liveRanges.sort((r1, r2) -> Integer.compare(r1.start, r2.start)); 244 starts.sort(Integer::compare); 245 ends.sort(Integer::compare); 246 247 for (LiveRange liveRange : liveRanges) { 248 int start = liveRange.start; 249 int end = liveRange.end; 250 Integer nextEnd; 251 while ((nextEnd = nextInRange(start, end, ends)) != null) { 252 // If an argument value has been split, we have disallowed argument reuse and therefore, 253 // the argument value is also in the argument register throughout the method. For debug 254 // information, we always use the argument register whenever a local corresponds to an 255 // argument value. That avoids ending and restarting locals whenever we move arguments 256 // to lower register. 257 int register = getRegisterForValue(value, value.isArgument() ? 0 : start); 258 ranges.add(new LocalRange(value, register, start, nextEnd)); 259 Integer nextStart = nextInRange(nextEnd, end, starts); 260 if (nextStart == null) { 261 start = -1; 262 break; 263 } 264 start = nextStart; 265 } 266 if (start >= 0) { 267 ranges.add(new LocalRange(value, getRegisterForValue(value, start), start, end)); 268 } 269 } 270 } 271 if (ranges.isEmpty()) { 272 return; 273 } 274 ranges.sort(LocalRange::compareTo); 275 276 // For each debug position compute the set of live locals. 277 boolean localsChanged = false; 278 Int2ReferenceMap<DebugLocalInfo> currentLocals = new Int2ReferenceOpenHashMap<>(); 279 280 LinkedList<LocalRange> openRanges = new LinkedList<>(); 281 Iterator<LocalRange> rangeIterator = ranges.iterator(); 282 LocalRange nextStartingRange = rangeIterator.next(); 283 284 // Open initial (argument) ranges. 285 while (nextStartingRange != null && nextStartingRange.start == 0) { 286 currentLocals.put(nextStartingRange.register, nextStartingRange.local); 287 openRanges.add(nextStartingRange); 288 nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null; 289 } 290 291 for (BasicBlock block : blocks) { 292 boolean blockEntry = true; 293 ListIterator<Instruction> instructionIterator = block.listIterator(); 294 while (instructionIterator.hasNext()) { 295 Instruction instruction = instructionIterator.next(); 296 int index = instruction.getNumber(); 297 ListIterator<LocalRange> it = openRanges.listIterator(0); 298 Int2ReferenceMap<DebugLocalInfo> ending = new Int2ReferenceOpenHashMap<>(); 299 Int2ReferenceMap<DebugLocalInfo> starting = new Int2ReferenceOpenHashMap<>(); 300 while (it.hasNext()) { 301 LocalRange openRange = it.next(); 302 if (openRange.end <= index) { 303 it.remove(); 304 assert currentLocals.get(openRange.register) == openRange.local; 305 currentLocals.remove(openRange.register); 306 localsChanged = true; 307 ending.put(openRange.register, openRange.local); 308 } 309 } 310 while (nextStartingRange != null && nextStartingRange.start <= index) { 311 // If the full range is between the two debug positions ignore it. 312 if (nextStartingRange.end > index) { 313 openRanges.add(nextStartingRange); 314 assert !currentLocals.containsKey(nextStartingRange.register); 315 currentLocals.put(nextStartingRange.register, nextStartingRange.local); 316 starting.put(nextStartingRange.register, nextStartingRange.local); 317 localsChanged = true; 318 } 319 nextStartingRange = rangeIterator.hasNext() ? rangeIterator.next() : null; 320 } 321 if (blockEntry) { 322 blockEntry = false; 323 block.setLocalsAtEntry(new Int2ReferenceOpenHashMap<>(currentLocals)); 324 } else if (localsChanged && shouldEmitChangesAtInstruction(instruction)) { 325 DebugLocalsChange change = createLocalsChange(ending, starting); 326 if (change != null) { 327 if (instruction.isDebugPosition() || instruction.isJumpInstruction()) { 328 instructionIterator.previous(); 329 instructionIterator.add(new DebugLocalsChange(ending, starting)); 330 instructionIterator.next(); 331 } else { 332 instructionIterator.add(new DebugLocalsChange(ending, starting)); 333 } 334 } 335 } 336 localsChanged = false; 337 } 338 } 339 } 340 createLocalsChange( Int2ReferenceMap<DebugLocalInfo> ending, Int2ReferenceMap<DebugLocalInfo> starting)341 private DebugLocalsChange createLocalsChange( 342 Int2ReferenceMap<DebugLocalInfo> ending, Int2ReferenceMap<DebugLocalInfo> starting) { 343 if (ending.isEmpty() || starting.isEmpty()) { 344 return new DebugLocalsChange(ending, starting); 345 } 346 IntSet unneeded = new IntArraySet(Math.min(ending.size(), starting.size())); 347 for (Int2ReferenceMap.Entry<DebugLocalInfo> entry : ending.int2ReferenceEntrySet()) { 348 if (starting.get(entry.getIntKey()) == entry.getValue()) { 349 unneeded.add(entry.getIntKey()); 350 } 351 } 352 if (unneeded.size() == ending.size() && unneeded.size() == starting.size()) { 353 return null; 354 } 355 IntIterator iterator = unneeded.iterator(); 356 while (iterator.hasNext()) { 357 int key = iterator.nextInt(); 358 ending.remove(key); 359 starting.remove(key); 360 } 361 return new DebugLocalsChange(ending, starting); 362 } 363 shouldEmitChangesAtInstruction(Instruction instruction)364 private boolean shouldEmitChangesAtInstruction(Instruction instruction) { 365 BasicBlock block = instruction.getBlock(); 366 // We emit local changes on all non-exit instructions or, since we have only a singe return 367 // block, any exits directly targeting that. 368 return instruction != block.exit() 369 || (instruction.isGoto() && instruction.asGoto().getTarget() == code.getNormalExitBlock()); 370 } 371 verifyLocalsEqual( ImmutableMap<Integer, DebugLocalInfo> a, Map<Integer, DebugLocalInfo> b)372 private boolean verifyLocalsEqual( 373 ImmutableMap<Integer, DebugLocalInfo> a, Map<Integer, DebugLocalInfo> b) { 374 int size = 0; 375 for (Map.Entry<Integer, DebugLocalInfo> entry : b.entrySet()) { 376 if (entry.getValue() != null) { 377 assert a.get(entry.getKey()) == entry.getValue(); 378 ++size; 379 } 380 } 381 return a.size() == size; 382 } 383 clearState()384 private void clearState() { 385 liveAtEntrySets = null; 386 liveIntervals = null; 387 active = null; 388 inactive = null; 389 unhandled = null; 390 freeRegisters = null; 391 } 392 393 // Compute a table that for each register numbers contains the number of previous register 394 // numbers that were unused. This table is then used to slide down the actual registers 395 // used to fill the gaps. computeUnusedRegisters()396 private void computeUnusedRegisters() { 397 if (registersUsed() == 0) { 398 return; 399 } 400 // Compute the set of registers that is used based on all live intervals. 401 Set<Integer> usedRegisters = new HashSet<>(); 402 for (LiveIntervals intervals : liveIntervals) { 403 addRegisterIfUsed(usedRegisters, intervals); 404 for (LiveIntervals childIntervals : intervals.getSplitChildren()) { 405 addRegisterIfUsed(usedRegisters, childIntervals); 406 } 407 } 408 // Additionally, we have used temporary registers for parallel move scheduling, those 409 // are used as well. 410 for (int i = firstParallelMoveTemporary; i < maxRegisterNumber + 1; i++) { 411 usedRegisters.add(realRegisterNumberFromAllocated(i)); 412 } 413 // Compute the table based on the set of used registers. 414 int unused = 0; 415 int[] computed = new int[registersUsed()]; 416 for (int i = 0; i < registersUsed(); i++) { 417 if (!usedRegisters.contains(i)) { 418 unused++; 419 } 420 computed[i] = unused; 421 } 422 unusedRegisters = computed; 423 } 424 addRegisterIfUsed(Set<Integer> used, LiveIntervals intervals)425 private void addRegisterIfUsed(Set<Integer> used, LiveIntervals intervals) { 426 boolean unused = intervals.isSpilledAndRematerializable(this); 427 if (!unused) { 428 used.add(realRegisterNumberFromAllocated(intervals.getRegister())); 429 if (intervals.getType() == MoveType.WIDE) { 430 used.add(realRegisterNumberFromAllocated(intervals.getRegister() + 1)); 431 } 432 } 433 } 434 435 @Override argumentValueUsesHighRegister(Value value, int instructionNumber)436 public boolean argumentValueUsesHighRegister(Value value, int instructionNumber) { 437 return isHighRegister( 438 getRegisterForValue(value, instructionNumber) + value.requiredRegisters() - 1); 439 } 440 highestUsedRegister()441 public int highestUsedRegister() { 442 return registersUsed() - 1; 443 } 444 445 @Override registersUsed()446 public int registersUsed() { 447 int numberOfRegister = maxRegisterNumber + 1 - NUMBER_OF_SENTINEL_REGISTERS; 448 if (unusedRegisters != null) { 449 return numberOfRegister - unusedRegisters[unusedRegisters.length - 1]; 450 } 451 return numberOfRegister; 452 } 453 454 @Override getRegisterForValue(Value value, int instructionNumber)455 public int getRegisterForValue(Value value, int instructionNumber) { 456 if (value.isFixedRegisterValue()) { 457 return realRegisterNumberFromAllocated(value.asFixedRegisterValue().getRegister()); 458 } 459 LiveIntervals intervals = value.getLiveIntervals(); 460 if (intervals.hasSplits()) { 461 intervals = intervals.getSplitCovering(instructionNumber); 462 } 463 return getRegisterForIntervals(intervals); 464 } 465 466 @Override getArgumentOrAllocateRegisterForValue(Value value, int instructionNumber)467 public int getArgumentOrAllocateRegisterForValue(Value value, int instructionNumber) { 468 if (value.isArgument()) { 469 return getRegisterForIntervals(value.getLiveIntervals()); 470 } 471 return getRegisterForValue(value, instructionNumber); 472 } 473 computeLivenessInformation()474 private BasicBlock[] computeLivenessInformation() { 475 BasicBlock[] blocks = code.numberInstructions(); 476 computeLiveAtEntrySets(); 477 computeLiveRanges(); 478 return blocks; 479 } 480 performAllocationWithoutMoveInsertion(ArgumentReuseMode mode)481 private boolean performAllocationWithoutMoveInsertion(ArgumentReuseMode mode) { 482 pinArgumentRegisters(); 483 return performLinearScan(mode); 484 } 485 performAllocation(ArgumentReuseMode mode)486 private boolean performAllocation(ArgumentReuseMode mode) { 487 boolean result = performAllocationWithoutMoveInsertion(mode); 488 insertMoves(); 489 if (mode == ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE) { 490 // Now that we know the max register number we can compute whether it is safe to use 491 // argument registers in place. If it is, we redo move insertion to get rid of the moves 492 // caused by splitting of the argument registers. 493 if (unsplitArguments()) { 494 removeSpillAndPhiMoves(); 495 insertMoves(); 496 } 497 } 498 return result; 499 } 500 501 // When argument register reuse is disallowed, we split argument values to make sure that 502 // we can get the argument into low enough registers at uses that require low numbers. After 503 // register allocation we can check if it is safe to just use the argument register itself 504 // for all uses and thereby avoid moving argument values around. unsplitArguments()505 private boolean unsplitArguments() { 506 boolean argumentRegisterUnsplit = false; 507 Value current = preArgumentSentinelValue; 508 while (current != null) { 509 LiveIntervals intervals = current.getLiveIntervals(); 510 assert intervals.getRegisterLimit() == Constants.U16BIT_MAX; 511 boolean canUseArgumentRegister = true; 512 for (LiveIntervals child : intervals.getSplitChildren()) { 513 if (child.getRegisterLimit() < highestUsedRegister()) { 514 canUseArgumentRegister = false; 515 break; 516 } 517 } 518 if (canUseArgumentRegister) { 519 argumentRegisterUnsplit = true; 520 for (LiveIntervals child : intervals.getSplitChildren()) { 521 child.clearRegisterAssignment(); 522 child.setRegister(intervals.getRegister()); 523 child.setSpilled(false); 524 } 525 } 526 current = current.getNextConsecutive(); 527 } 528 return argumentRegisterUnsplit; 529 } 530 removeSpillAndPhiMoves()531 private void removeSpillAndPhiMoves() { 532 for (BasicBlock block : code.blocks) { 533 InstructionListIterator it = block.listIterator(); 534 while (it.hasNext()) { 535 Instruction instruction = it.next(); 536 Value outValue = instruction.outValue(); 537 if (outValue != null && outValue.isFixedRegisterValue()) { 538 // Only move and const number instructions are inserted for spill and phi moves. The 539 // const number instructions are for values that can be rematerialized instead of 540 // spilled. 541 assert instruction.isMove() || instruction.isConstNumber(); 542 assert !instruction.isDebugInstruction(); 543 it.remove(); 544 } 545 } 546 } 547 } 548 clearRegisterAssignments()549 private void clearRegisterAssignments() { 550 freeRegisters.clear(); 551 maxRegisterNumber = 0; 552 nextUnusedRegisterNumber = 0; 553 active.clear(); 554 inactive.clear(); 555 unhandled.clear(); 556 for (LiveIntervals intervals : liveIntervals) { 557 intervals.clearRegisterAssignment(); 558 } 559 } 560 561 /** 562 * Get the register allocated to a given set of live intervals. 563 */ getRegisterForIntervals(LiveIntervals intervals)564 private int getRegisterForIntervals(LiveIntervals intervals) { 565 int intervalsRegister = intervals.getRegister(); 566 return realRegisterNumberFromAllocated(intervalsRegister); 567 } 568 unadjustedRealRegisterFromAllocated(int allocated)569 int unadjustedRealRegisterFromAllocated(int allocated) { 570 assert allocated != NO_REGISTER; 571 assert allocated >= 0; 572 int register; 573 if (allocated < numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS) { 574 // For the |numberOfArguments| first registers map to the correct argument register. 575 // Due to the sentinel register in front of the arguments, the register number returned is 576 // the argument number starting from one. 577 register = maxRegisterNumber - (numberOfArgumentRegisters - allocated) 578 - NUMBER_OF_SENTINEL_REGISTERS; 579 } else { 580 // For everything else use the lower numbers. 581 register = allocated - numberOfArgumentRegisters - NUMBER_OF_SENTINEL_REGISTERS; 582 } 583 return register; 584 } 585 realRegisterNumberFromAllocated(int allocated)586 int realRegisterNumberFromAllocated(int allocated) { 587 int register = unadjustedRealRegisterFromAllocated(allocated); 588 // Adjust for spill registers that turn out to be unused because the value can be 589 // rematerialized instead of spilled. 590 if (unusedRegisters != null) { 591 return register - unusedRegisters[register]; 592 } 593 return register; 594 } 595 isHighRegister(int register)596 private boolean isHighRegister(int register) { 597 return register > Constants.U4BIT_MAX; 598 } 599 performLinearScan(ArgumentReuseMode mode)600 private boolean performLinearScan(ArgumentReuseMode mode) { 601 unhandled.addAll(liveIntervals); 602 LiveIntervals argumentInterval = preArgumentSentinelValue.getLiveIntervals(); 603 while (argumentInterval != null) { 604 assert argumentInterval.getRegister() != NO_REGISTER; 605 unhandled.remove(argumentInterval); 606 if (mode == ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) { 607 // All the argument intervals are active in the beginning and have preallocated registers. 608 active.add(argumentInterval); 609 } else { 610 // Treat the argument interval as spilled which will require a load to a different 611 // register for all register-constrained usages. 612 if (argumentInterval.getUses().size() > 1) { 613 LiveIntervalsUse use = argumentInterval.firstUseWithConstraint(); 614 if (use != null) { 615 LiveIntervals split; 616 if (argumentInterval.numberOfUsesWithConstraint() == 1) { 617 // If there is only one register-constrained use, split before 618 // that one use. 619 split = argumentInterval.splitBefore(use.getPosition()); 620 } else { 621 // If there are multiple register-constrained users, split right after the definition 622 // to make it more likely that arguments get in usable registers from the start. 623 split = argumentInterval 624 .splitBefore(argumentInterval.getValue().definition.getNumber() + 1); 625 } 626 unhandled.add(split); 627 } 628 } 629 } 630 argumentInterval = argumentInterval.getNextConsecutive(); 631 } 632 633 // We have to be careful when it comes to the register allocated for a move exception 634 // instruction. For move exception instructions there is no place to put spill or 635 // restore moves. The move exception instruction has to be the first instruction in a 636 // catch handler. 637 // 638 // When we allow argument reuse we do not allow any splitting, therefore we cannot get into 639 // trouble with move exception registers. When argument reuse is disallowed we block a fixed 640 // register to be used only by move exception instructions. 641 if (mode != ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) { 642 // Force all move exception ranges to start out with the exception in a fixed register. Split 643 // their live ranges which will force another register if used. 644 int moveExceptionRegister = NO_REGISTER; 645 List<LiveIntervals> moveExceptionIntervals = new ArrayList<>(); 646 boolean overlappingMoveExceptionIntervals = false; 647 for (BasicBlock block : code.blocks) { 648 for (Instruction instruction : block.getInstructions()) { 649 if (instruction.isMoveException()) { 650 hasDedicatedMoveExceptionRegister = true; 651 Value exceptionValue = instruction.outValue(); 652 LiveIntervals intervals = exceptionValue.getLiveIntervals(); 653 unhandled.remove(intervals); 654 if (moveExceptionRegister == NO_REGISTER) { 655 moveExceptionRegister = getFreeConsecutiveRegisters(1); 656 } 657 intervals.setRegister(moveExceptionRegister); 658 if (!overlappingMoveExceptionIntervals) { 659 for (LiveIntervals other : moveExceptionIntervals) { 660 overlappingMoveExceptionIntervals |= other.overlaps(intervals); 661 } 662 } 663 moveExceptionIntervals.add(intervals); 664 } 665 } 666 } 667 if (overlappingMoveExceptionIntervals) { 668 for (LiveIntervals intervals : moveExceptionIntervals) { 669 if (intervals.getUses().size() > 1) { 670 LiveIntervalsUse firstUse = intervals.getUses().pollFirst(); 671 LiveIntervalsUse secondUse = intervals.getUses().pollFirst(); 672 intervals.getUses().add(firstUse); 673 intervals.getUses().add(secondUse); 674 LiveIntervals split = intervals.splitBefore(secondUse.getPosition()); 675 unhandled.add(split); 676 } 677 } 678 } 679 } 680 681 // Go through each unhandled live interval and find a register for it. 682 while (!unhandled.isEmpty()) { 683 LiveIntervals unhandledInterval = unhandled.poll(); 684 // If this interval value is the src of an argument move. Fix the registers for the 685 // consecutive arguments now and add hints to the move sources. This looks forward 686 // and propagate hints backwards to avoid many moves in connection with ranged invokes. 687 allocateArgumentIntervalsWithSrc(unhandledInterval); 688 if (unhandledInterval.getRegister() != NO_REGISTER) { 689 // The value itself could be in the chain that has now gotten registers allocated. 690 continue; 691 } 692 693 int start = unhandledInterval.getStart(); 694 // Check for active intervals that expired or became inactive. 695 Iterator<LiveIntervals> activeIterator = active.iterator(); 696 while (activeIterator.hasNext()) { 697 LiveIntervals activeIntervals = activeIterator.next(); 698 if (start >= activeIntervals.getEnd()) { 699 activeIterator.remove(); 700 freeRegistersForIntervals(activeIntervals); 701 } else if (!activeIntervals.overlapsPosition(start)) { 702 activeIterator.remove(); 703 assert activeIntervals.getRegister() != NO_REGISTER; 704 inactive.add(activeIntervals); 705 freeRegistersForIntervals(activeIntervals); 706 } 707 } 708 709 // Check for inactive intervals that expired or became reactivated. 710 Iterator<LiveIntervals> inactiveIterator = inactive.iterator(); 711 while (inactiveIterator.hasNext()) { 712 LiveIntervals inactiveIntervals = inactiveIterator.next(); 713 if (start >= inactiveIntervals.getEnd()) { 714 inactiveIterator.remove(); 715 } else if (inactiveIntervals.overlapsPosition(start)) { 716 inactiveIterator.remove(); 717 assert inactiveIntervals.getRegister() != NO_REGISTER; 718 active.add(inactiveIntervals); 719 takeRegistersForIntervals(inactiveIntervals); 720 } 721 } 722 723 // Perform the actual allocation. 724 if (unhandledInterval.isLinked() && !unhandledInterval.isArgumentInterval()) { 725 allocateLinkedIntervals(unhandledInterval); 726 } else { 727 if (!allocateSingleInterval(unhandledInterval, mode)) { 728 return false; 729 } 730 } 731 } 732 return true; 733 } 734 735 /** 736 * Perform look-ahead and allocate registers for linked argument chains that have the argument 737 * interval as an argument move source. 738 * 739 * <p>The end result of calling this method is that the argument intervals have registers 740 * allocated and have been moved from unhandled to inactive. The move sources have their hints 741 * updated. The rest of the register allocation state is unchanged. 742 */ allocateArgumentIntervalsWithSrc(LiveIntervals srcInterval)743 private void allocateArgumentIntervalsWithSrc(LiveIntervals srcInterval) { 744 Value value = srcInterval.getValue(); 745 for (Instruction instruction : value.uniqueUsers()) { 746 // If there is a move user that is an argument move, we allocate the consecutive 747 // registers for the argument intervals and propagate the selected registers back as 748 // hints to the sources. 749 if (instruction.isMove() && instruction.asMove().dest().isLinked()) { 750 Move move = instruction.asMove(); 751 Value dest = move.dest(); 752 LiveIntervals destIntervals = dest.getLiveIntervals(); 753 if (destIntervals.getRegister() == NO_REGISTER) { 754 // Save the current register allocation state so we can restore it at the end. 755 TreeSet<Integer> savedFreeRegisters = new TreeSet<>(freeRegisters); 756 int savedUnusedRegisterNumber = nextUnusedRegisterNumber; 757 List<LiveIntervals> savedActive = new LinkedList<>(active); 758 List<LiveIntervals> savedInactive = new LinkedList<>(inactive); 759 760 // Add all the active intervals to the inactive set. When allocating linked intervals we 761 // check all inactive intervals and exclude the registers for overlapping inactive 762 // intervals. 763 for (LiveIntervals active : active) { 764 // TODO(ager): We could allow the use of all the currently active registers for the 765 // ranged invoke (by adding the registers for all the active intervals to freeRegisters 766 // here). That could lead to lower register pressure. However, it would also often mean 767 // that we cannot allocate the right argument register to the current unhandled 768 // interval. Size measurements on GMSCore indicate that blocking the current active 769 // registers works the best for code size. 770 if (active.isArgumentInterval()) { 771 // Allow the ranged invoke to use argument registers if free. This improves register 772 // allocation for brigde methods that forwards all of their arguments after check-cast 773 // checks on their types. 774 freeRegistersForIntervals(active); 775 } 776 inactive.add(active); 777 } 778 779 // Allocate the argument intervals. 780 unhandled.remove(destIntervals); 781 allocateLinkedIntervals(destIntervals); 782 // Restore the register allocation state. 783 freeRegisters = savedFreeRegisters; 784 for (int i = savedUnusedRegisterNumber; i < nextUnusedRegisterNumber; i++) { 785 freeRegisters.add(i); 786 } 787 active = savedActive; 788 inactive = savedInactive; 789 // Move all the argument intervals to the inactive set. 790 LiveIntervals current = destIntervals.getStartOfConsecutive(); 791 while (current != null) { 792 assert !inactive.contains(current); 793 assert !active.contains(current); 794 assert !unhandled.contains(current); 795 inactive.add(current); 796 current = current.getNextConsecutive(); 797 } 798 } 799 } 800 } 801 } 802 allocateLinkedIntervals(LiveIntervals unhandledInterval)803 private void allocateLinkedIntervals(LiveIntervals unhandledInterval) { 804 // Exclude the registers that overlap the start of one of the live ranges we are 805 // going to assign registers to now. 806 LiveIntervals current = unhandledInterval.getStartOfConsecutive(); 807 Set<Integer> excludedRegisters = new HashSet<>(); 808 while (current != null) { 809 for (LiveIntervals inactiveIntervals : inactive) { 810 if (inactiveIntervals.overlaps(current)) { 811 excludeRegistersForInterval(inactiveIntervals, excludedRegisters); 812 } 813 } 814 current = current.getNextConsecutive(); 815 } 816 // Select registers. 817 current = unhandledInterval.getStartOfConsecutive(); 818 int numberOfRegister = current.numberOfConsecutiveRegisters(); 819 int firstRegister = getFreeConsecutiveRegisters(numberOfRegister); 820 for (int i = 0; i < numberOfRegister; i++) { 821 assert current != null; 822 current.setRegister(firstRegister + i); 823 if (current.getType() == MoveType.WIDE) { 824 assert i < numberOfRegister; 825 i++; 826 } 827 // Propagate hints to the move sources. 828 Value value = current.getValue(); 829 if (!value.isPhi() && value.definition.isMove()) { 830 Move move = value.definition.asMove(); 831 LiveIntervals intervals = move.src().getLiveIntervals(); 832 intervals.setHint(current); 833 } 834 if (current != unhandledInterval) { 835 // Only the start of unhandledInterval has been reached at this point. All other live 836 // intervals in the chain have been assigned registers but their start has not yet been 837 // reached. Therefore, they belong in the inactive set. 838 unhandled.remove(current); 839 assert current.getRegister() != NO_REGISTER; 840 inactive.add(current); 841 freeRegistersForIntervals(current); 842 } 843 current = current.getNextConsecutive(); 844 } 845 assert current == null; 846 assert unhandledInterval.getRegister() != NO_REGISTER; 847 active.add(unhandledInterval); 848 // Include the registers for inactive ranges that we had to exclude for this allocation. 849 freeRegisters.addAll(excludedRegisters); 850 } 851 852 // Update the information about used registers when |register| has been selected for use. 853 private void updateRegisterState(int register, boolean needsRegisterPair) { 854 int maxRegister = register + (needsRegisterPair ? 1 : 0); 855 if (maxRegister >= nextUnusedRegisterNumber) { 856 nextUnusedRegisterNumber = maxRegister + 1; 857 } 858 maxRegisterNumber = Math.max(maxRegisterNumber, maxRegister); 859 } 860 getSpillRegister(LiveIntervals intervals)861 private int getSpillRegister(LiveIntervals intervals) { 862 if (intervals.isArgumentInterval()) { 863 return intervals.getSplitParent().getRegister(); 864 } 865 int registerNumber = nextUnusedRegisterNumber++; 866 maxRegisterNumber = registerNumber; 867 if (intervals.getType() == MoveType.WIDE) { 868 nextUnusedRegisterNumber++; 869 maxRegisterNumber++; 870 } 871 return registerNumber; 872 } 873 toInstructionPosition(int position)874 private int toInstructionPosition(int position) { 875 return position % 2 == 0 ? position : position + 1; 876 } 877 toGapPosition(int position)878 private int toGapPosition(int position) { 879 return position % 2 == 1 ? position : position - 1; 880 } 881 882 // The dalvik jit had a bug where the long operations add, sub, or, xor and and would write 883 // the first part of the result long before reading the second part of the input longs. 884 // 885 // Therefore, on dalvik, we cannot generate code with overlapping long registers such as: 886 // 887 // add-long v3, v0, v2 888 // 889 // Dalvik would add v0 and v2 and write that to v3. It would then read v1 and v3 and produce 890 // the wrong result. needsOverlappingLongRegisterWorkaround(LiveIntervals intervals)891 private boolean needsOverlappingLongRegisterWorkaround(LiveIntervals intervals) { 892 if (intervals.requiredRegisters() == 1) { 893 // Not the live range for a wide value. 894 return false; 895 } 896 if (intervals.getValue().isPhi()) { 897 // If this writes a new register pair it will be via a move and not a long operation. 898 return false; 899 } 900 if (intervals.getSplitParent() != intervals) { 901 // This is a split of the parent interval and therefore if this leads to a write of a 902 // register pair it will be via a move and not a long operation. 903 return false; 904 } 905 Instruction definition = intervals.getValue().definition; 906 if (definition.isArithmeticBinop() && 907 definition.asArithmeticBinop().getNumericType() == NumericType.LONG) { 908 return definition instanceof Add || definition instanceof Sub; 909 } 910 if (definition.isLogicalBinop() && 911 definition.asLogicalBinop().getNumericType() == NumericType.LONG) { 912 return definition instanceof Or || definition instanceof Xor || definition instanceof And; 913 } 914 return false; 915 } 916 hasOverlappingLongRegisters(LiveIntervals unhandledInterval, int register)917 private boolean hasOverlappingLongRegisters(LiveIntervals unhandledInterval, int register) { 918 assert needsOverlappingLongRegisterWorkaround(unhandledInterval); 919 Value left = unhandledInterval.getValue().definition.asBinop().leftValue(); 920 Value right = unhandledInterval.getValue().definition.asBinop().rightValue(); 921 int leftReg = 922 left.getLiveIntervals().getSplitCovering(unhandledInterval.getStart()).getRegister(); 923 int rightReg = 924 right.getLiveIntervals().getSplitCovering(unhandledInterval.getStart()).getRegister(); 925 assert leftReg != NO_REGISTER && rightReg != NO_REGISTER; 926 // The dalvik bug is actually only for overlap with the second operand, For now we 927 // make sure that there is no overlap with either operand. 928 if ((leftReg + 1) == register || (rightReg + 1) == register) { 929 return true; 930 } 931 return false; 932 } 933 allocateSingleInterval(LiveIntervals unhandledInterval, ArgumentReuseMode mode)934 private boolean allocateSingleInterval(LiveIntervals unhandledInterval, ArgumentReuseMode mode) { 935 int registerConstraint = unhandledInterval.getRegisterLimit(); 936 assert registerConstraint <= Constants.U16BIT_MAX; 937 938 assert unhandledInterval.requiredRegisters() <= 2; 939 boolean needsRegisterPair = unhandledInterval.requiredRegisters() == 2; 940 941 // Just use the argument register if an argument split has no register constraint. That will 942 // avoid move generation for the argument. 943 if (registerConstraint == Constants.U16BIT_MAX && unhandledInterval.isArgumentInterval()) { 944 int argumentRegister = unhandledInterval.getSplitParent().getRegister(); 945 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, argumentRegister); 946 return true; 947 } 948 949 if (registerConstraint < Constants.U16BIT_MAX) { 950 // We always have argument sentinels that will not actually occupy registers. Therefore, we 951 // allow the use of NUMBER_OF_SENTINEL_REGISTERS more than the limit. 952 registerConstraint += NUMBER_OF_SENTINEL_REGISTERS; 953 if (mode == ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE) { 954 // We know that none of the argument registers will be reused. Therefore, we allow the 955 // use of number of arguments more registers. (We will never use number of arguments + 956 // number of sentinel registers of them.) 957 registerConstraint += numberOfArgumentRegisters; 958 } 959 } 960 961 // Set all free positions for possible registers to max integer. 962 RegisterPositions freePositions = new RegisterPositions(registerConstraint + 1); 963 964 if (mode == ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) { 965 // The sentinel registers cannot be used and we block them. 966 freePositions.set(0, 0, false); 967 if (options.debug && !code.method.accessFlags.isStatic()) { 968 // If we are generating debug information, we pin the this value register since the 969 // debugger expects to always be able to find it in the input register. 970 assert numberOfArgumentRegisters > 0; 971 assert preArgumentSentinelValue.getNextConsecutive().requiredRegisters() == 1; 972 freePositions.set(1, 0, false); 973 } 974 int lastSentinelRegister = numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS - 1; 975 if (lastSentinelRegister <= registerConstraint) { 976 freePositions.set(lastSentinelRegister, 0, false); 977 } 978 } else { 979 // Argument reuse is not allowed and we block all the argument registers so that 980 // arguments are never free. 981 for (int i = 0; i < numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS; i++) { 982 if (i <= registerConstraint) { 983 freePositions.set(i, 0, false); 984 } 985 } 986 } 987 988 // If there is a move exception instruction we block register 0 as the move exception 989 // register. If we cannot find a free valid register for the move exception value we have no 990 // place to put a spill move (because the move exception instruction has to be the 991 // first instruction in the handler block). 992 if (hasDedicatedMoveExceptionRegister) { 993 int moveExceptionRegister = numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS; 994 if (moveExceptionRegister <= registerConstraint) { 995 freePositions.set(moveExceptionRegister, 0, false); 996 } 997 } 998 999 // All the active intervals are not free at this point. 1000 for (LiveIntervals intervals : active) { 1001 int activeRegister = intervals.getRegister(); 1002 if (activeRegister <= registerConstraint) { 1003 for (int i = 0; i < intervals.requiredRegisters(); i++) { 1004 if (activeRegister + i <= registerConstraint) { 1005 freePositions.set(activeRegister + i, 0, intervals.isConstantNumberInterval()); 1006 } 1007 } 1008 } 1009 } 1010 1011 // The register for inactive intervals that overlap with this interval are free until 1012 // the next overlap. 1013 for (LiveIntervals intervals : inactive) { 1014 int inactiveRegister = intervals.getRegister(); 1015 if (inactiveRegister <= registerConstraint && unhandledInterval.overlaps(intervals)) { 1016 int nextOverlap = unhandledInterval.nextOverlap(intervals); 1017 for (int i = 0; i < intervals.requiredRegisters(); i++) { 1018 int register = inactiveRegister + i; 1019 if (register <= registerConstraint) { 1020 int unhandledStart = toInstructionPosition(unhandledInterval.getStart()); 1021 if (nextOverlap == unhandledStart) { 1022 // Don't use the register for an inactive interval that is only free until the next 1023 // instruction. We can get into this situation when unhandledInterval starts at a 1024 // gap position. 1025 freePositions.set(register, 0, freePositions.holdsConstant(register)); 1026 } else { 1027 if (nextOverlap < freePositions.get(register)) { 1028 freePositions.set(register, nextOverlap, intervals.isConstantNumberInterval()); 1029 } 1030 } 1031 } 1032 } 1033 } 1034 } 1035 1036 // Attempt to use register hints. 1037 if (useRegisterHint(unhandledInterval, registerConstraint, freePositions, needsRegisterPair)) { 1038 return true; 1039 } 1040 1041 // Get the register (pair) that is free the longest. That is the register with the largest 1042 // free position. 1043 int candidate = getLargestValidCandidate( 1044 unhandledInterval, registerConstraint, needsRegisterPair, freePositions, false); 1045 assert candidate != REGISTER_CANDIDATE_NOT_FOUND; 1046 int largestFreePosition = freePositions.get(candidate); 1047 if (needsRegisterPair) { 1048 largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1)); 1049 } 1050 1051 // Determine what to do based on how long the selected candidate is free. 1052 if (largestFreePosition == 0) { 1053 // Not free. We need to spill. 1054 if (mode == ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) { 1055 // No spilling is allowed when we allow argument reuse. Bailout and start over with 1056 // argument reuse disallowed. 1057 return false; 1058 } 1059 // If the first use for these intervals is unconstrained, just spill this interval instead 1060 // of finding another candidate to spill via allocateBlockedRegister. 1061 if (!unhandledInterval.getUses().first().hasConstraint()) { 1062 int nextConstrainedPosition = unhandledInterval.firstUseWithConstraint().getPosition(); 1063 int register; 1064 // Arguments are always in the argument registers, so for arguments just use that register 1065 // for the unconstrained prefix. For everything else, get a spill register. 1066 if (unhandledInterval.isArgumentInterval()) { 1067 register = unhandledInterval.getSplitParent().getRegister(); 1068 } else { 1069 register = getSpillRegister(unhandledInterval); 1070 } 1071 LiveIntervals split = unhandledInterval.splitBefore(nextConstrainedPosition); 1072 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, register); 1073 unhandled.add(split); 1074 } else { 1075 allocateBlockedRegister(unhandledInterval); 1076 } 1077 } else if (largestFreePosition >= unhandledInterval.getEnd()) { 1078 // Free for the entire interval. Allocate the register. 1079 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, candidate); 1080 } else { 1081 if (mode == ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) { 1082 // No splitting is allowed when we allow argument reuse. Bailout and start over with 1083 // argument reuse disallowed. 1084 return false; 1085 } 1086 // The candidate is free for the beginning of an interval. We split the interval 1087 // and use the register for as long as we can. 1088 LiveIntervals split = unhandledInterval.splitBefore(largestFreePosition); 1089 assert split != unhandledInterval; 1090 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, candidate); 1091 unhandled.add(split); 1092 } 1093 return true; 1094 } 1095 1096 // Attempt to use the register hint for the unhandled interval in order to avoid generating 1097 // moves. useRegisterHint(LiveIntervals unhandledInterval, int registerConstraint, RegisterPositions freePositions, boolean needsRegisterPair)1098 private boolean useRegisterHint(LiveIntervals unhandledInterval, int registerConstraint, 1099 RegisterPositions freePositions, boolean needsRegisterPair) { 1100 // If the unhandled interval has a hint we give it that register if it is available without 1101 // spilling. For phis we also use the hint before looking at the operand registers. The 1102 // phi could have a hint from an argument moves which it seems more important to honor in 1103 // practice. 1104 LiveIntervals hint = unhandledInterval.getHint(); 1105 if (hint != null) { 1106 int register = hint.getRegister(); 1107 if (tryHint(unhandledInterval, registerConstraint, freePositions, needsRegisterPair, 1108 register)) { 1109 return true; 1110 } 1111 } 1112 1113 // If there is no hint or it cannot be applied we search for a good register for phis using 1114 // the registers assigned to the operand intervals. We determine all the registers used 1115 // for operands and try them one by one based on frequency. 1116 Value value = unhandledInterval.getValue(); 1117 if (value.isPhi()) { 1118 Phi phi = value.asPhi(); 1119 Multiset<Integer> map = HashMultiset.create(); 1120 List<Value> operands = phi.getOperands(); 1121 for (int i = 0; i < operands.size(); i++) { 1122 LiveIntervals intervals = operands.get(i).getLiveIntervals(); 1123 if (intervals.hasSplits()) { 1124 BasicBlock pred = phi.getBlock().getPredecessors().get(i); 1125 intervals = intervals.getSplitCovering(pred.exit().getNumber()); 1126 } 1127 int operandRegister = intervals.getRegister(); 1128 if (operandRegister != NO_REGISTER) { 1129 map.add(operandRegister); 1130 } 1131 } 1132 for (Entry<Integer> entry : Multisets.copyHighestCountFirst(map).entrySet()) { 1133 int register = entry.getElement(); 1134 if (tryHint(unhandledInterval, registerConstraint, freePositions, needsRegisterPair, 1135 register)) { 1136 return true; 1137 } 1138 } 1139 } 1140 1141 return false; 1142 } 1143 1144 // Attempt to allocate the hint register to the unhandled intervals. tryHint(LiveIntervals unhandledInterval, int registerConstraint, RegisterPositions freePositions, boolean needsRegisterPair, int register)1145 private boolean tryHint(LiveIntervals unhandledInterval, int registerConstraint, 1146 RegisterPositions freePositions, boolean needsRegisterPair, int register) { 1147 if (register + (needsRegisterPair ? 1 : 0) <= registerConstraint) { 1148 int freePosition = freePositions.get(register); 1149 if (needsRegisterPair) { 1150 freePosition = Math.min(freePosition, freePositions.get(register + 1)); 1151 } 1152 if (freePosition >= unhandledInterval.getEnd()) { 1153 // Check for overlapping long registers issue. 1154 if (needsOverlappingLongRegisterWorkaround(unhandledInterval) && 1155 hasOverlappingLongRegisters(unhandledInterval, register)) { 1156 return false; 1157 } 1158 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, register); 1159 return true; 1160 } 1161 } 1162 return false; 1163 } 1164 assignRegister(LiveIntervals intervals, int register)1165 private void assignRegister(LiveIntervals intervals, int register) { 1166 intervals.setRegister(register); 1167 updateRegisterHints(intervals); 1168 } 1169 updateRegisterHints(LiveIntervals intervals)1170 private void updateRegisterHints(LiveIntervals intervals) { 1171 Value value = intervals.getValue(); 1172 // If the value flows into a phi, set the hint for all the operand splits that flow into the 1173 // phi and do not have hints yet. 1174 for (Phi phi : value.uniquePhiUsers()) { 1175 LiveIntervals phiIntervals = phi.getLiveIntervals(); 1176 if (phiIntervals.getHint() == null) { 1177 for (int i = 0; i < phi.getOperands().size(); i++) { 1178 Value operand = phi.getOperand(i); 1179 LiveIntervals operandIntervals = operand.getLiveIntervals(); 1180 BasicBlock pred = phi.getBlock().getPredecessors().get(i); 1181 operandIntervals = operandIntervals.getSplitCovering(pred.exit().getNumber()); 1182 if (operandIntervals.getHint() == null) { 1183 operandIntervals.setHint(intervals); 1184 } 1185 } 1186 } 1187 } 1188 // If the value is a phi and we are at the start of the interval, we set the register as 1189 // the hint for all of the operand splits flowing into the phi. We set the hint no matter 1190 // if there is already a hint. We know the register for the phi and want as many operands 1191 // as possible to be allocated the same register to avoid phi moves. 1192 if (value.isPhi() && intervals.getSplitParent() == intervals) { 1193 Phi phi = value.asPhi(); 1194 BasicBlock block = phi.getBlock(); 1195 for (int i = 0; i < phi.getOperands().size(); i++) { 1196 Value operand = phi.getOperand(i); 1197 BasicBlock pred = block.getPredecessors().get(i); 1198 LiveIntervals operandIntervals = 1199 operand.getLiveIntervals().getSplitCovering(pred.exit().getNumber()); 1200 operandIntervals.setHint(intervals); 1201 } 1202 } 1203 } 1204 assignRegisterToUnhandledInterval( LiveIntervals unhandledInterval, boolean needsRegisterPair, int register)1205 private void assignRegisterToUnhandledInterval( 1206 LiveIntervals unhandledInterval, boolean needsRegisterPair, int register) { 1207 assignRegister(unhandledInterval, register); 1208 takeRegistersForIntervals(unhandledInterval); 1209 updateRegisterState(register, needsRegisterPair); 1210 active.add(unhandledInterval); 1211 } 1212 getLargestCandidate(int registerConstraint, RegisterPositions freePositions, boolean needsRegisterPair, boolean restrictToConstant)1213 private int getLargestCandidate(int registerConstraint, RegisterPositions freePositions, 1214 boolean needsRegisterPair, boolean restrictToConstant) { 1215 int candidate = REGISTER_CANDIDATE_NOT_FOUND; 1216 int largest = -1; 1217 1218 for (int i = 0; i <= registerConstraint; i++) { 1219 if (restrictToConstant && !freePositions.holdsConstant(i)) { 1220 continue; 1221 } 1222 int freePosition = freePositions.get(i); 1223 if (needsRegisterPair) { 1224 if (i >= registerConstraint) { 1225 break; 1226 } 1227 freePosition = Math.min(freePosition, freePositions.get(i + 1)); 1228 } 1229 if (freePosition > largest) { 1230 candidate = i; 1231 largest = freePosition; 1232 if (largest == Integer.MAX_VALUE) { 1233 break; 1234 } 1235 } 1236 } 1237 1238 return candidate; 1239 } 1240 getLargestValidCandidate(LiveIntervals unhandledInterval, int registerConstraint, boolean needsRegisterPair, RegisterPositions freePositions, boolean restrictToConstant)1241 private int getLargestValidCandidate(LiveIntervals unhandledInterval, int registerConstraint, 1242 boolean needsRegisterPair, RegisterPositions freePositions, boolean restrictToConstant) { 1243 int candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, 1244 restrictToConstant); 1245 if (candidate == REGISTER_CANDIDATE_NOT_FOUND) { 1246 return candidate; 1247 } 1248 if (needsOverlappingLongRegisterWorkaround(unhandledInterval)) { 1249 while (hasOverlappingLongRegisters(unhandledInterval, candidate)) { 1250 // Make the overlapping register unavailable for allocation and try again. 1251 freePositions.set(candidate, 0, freePositions.holdsConstant(candidate)); 1252 candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, 1253 restrictToConstant); 1254 } 1255 } 1256 return candidate; 1257 } 1258 allocateBlockedRegister(LiveIntervals unhandledInterval)1259 private void allocateBlockedRegister(LiveIntervals unhandledInterval) { 1260 int registerConstraint = unhandledInterval.getRegisterLimit(); 1261 if (registerConstraint < Constants.U16BIT_MAX) { 1262 // We always have argument sentinels that will not actually occupy registers. Therefore, we 1263 // allow the use of NUMBER_OF_SENTINEL_REGISTERS more than the limit. Additionally, we never 1264 // reuse argument registers and therefore allow the use of numberOfArgumentRegisters as well. 1265 registerConstraint += numberOfArgumentRegisters; 1266 registerConstraint += NUMBER_OF_SENTINEL_REGISTERS; 1267 } 1268 1269 // Initialize all candidate registers to Integer.MAX_VALUE. 1270 RegisterPositions usePositions = new RegisterPositions(registerConstraint + 1); 1271 RegisterPositions blockedPositions = new RegisterPositions(registerConstraint + 1); 1272 1273 // Compute next use location for all currently active registers. 1274 for (LiveIntervals intervals : active) { 1275 int activeRegister = intervals.getRegister(); 1276 if (activeRegister <= registerConstraint) { 1277 for (int i = 0; i < intervals.requiredRegisters(); i++) { 1278 if (activeRegister + i <= registerConstraint) { 1279 int unhandledStart = unhandledInterval.getStart(); 1280 usePositions.set(activeRegister + i, intervals.firstUseAfter(unhandledStart), 1281 intervals.isConstantNumberInterval()); 1282 } 1283 } 1284 } 1285 } 1286 1287 // Compute next use location for all inactive registers that overlaps the unhandled interval. 1288 for (LiveIntervals intervals : inactive) { 1289 int inactiveRegister = intervals.getRegister(); 1290 if (inactiveRegister <= registerConstraint && intervals.overlaps(unhandledInterval)) { 1291 for (int i = 0; i < intervals.requiredRegisters(); i++) { 1292 if (inactiveRegister + i <= registerConstraint) { 1293 int firstUse = intervals.firstUseAfter(unhandledInterval.getStart()); 1294 if (firstUse < usePositions.get(inactiveRegister + i)) { 1295 usePositions.set(inactiveRegister + i, firstUse, 1296 intervals.isConstantNumberInterval()); 1297 } 1298 } 1299 } 1300 } 1301 } 1302 1303 // Disallow the reuse of argument registers by always treating them as being used 1304 // at instruction number 0. 1305 for (int i = 0; i < numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS; i++) { 1306 usePositions.set(i, 0, false); 1307 } 1308 1309 // Disallow reuse of the move exception register if we have reserved one. 1310 if (hasDedicatedMoveExceptionRegister) { 1311 usePositions.set(numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS, 0, false); 1312 } 1313 1314 // Treat active linked argument intervals as pinned. They cannot be given another register 1315 // at their uses. 1316 blockLinkedRegisters(active, unhandledInterval, registerConstraint, usePositions, 1317 blockedPositions); 1318 1319 // Treat inactive linked argument intervals as pinned. They cannot be given another register 1320 // at their uses. 1321 blockLinkedRegisters(inactive, unhandledInterval, registerConstraint, usePositions, 1322 blockedPositions); 1323 1324 // Get the register (pair) that has the highest use position. 1325 boolean needsRegisterPair = unhandledInterval.requiredRegisters() == 2; 1326 1327 int candidate = getLargestValidCandidate(unhandledInterval, registerConstraint, 1328 needsRegisterPair, usePositions, true); 1329 if (candidate != Integer.MAX_VALUE) { 1330 int nonConstCandidate = getLargestValidCandidate(unhandledInterval, registerConstraint, 1331 needsRegisterPair, usePositions, false); 1332 if (nonConstCandidate == Integer.MAX_VALUE || candidate == REGISTER_CANDIDATE_NOT_FOUND) { 1333 candidate = nonConstCandidate; 1334 } else { 1335 int largestConstUsePosition = getLargestPosition(usePositions, candidate, needsRegisterPair); 1336 if (largestConstUsePosition - MIN_CONSTANT_FREE_FOR_POSITIONS < unhandledInterval 1337 .getStart()) { 1338 // The candidate that can be rematerialized has a live range too short to use it. 1339 candidate = nonConstCandidate; 1340 } 1341 } 1342 } 1343 1344 int largestUsePosition = getLargestPosition(usePositions, candidate, needsRegisterPair); 1345 int blockedPosition = getBlockedPosition(blockedPositions, candidate, needsRegisterPair); 1346 1347 if (largestUsePosition < unhandledInterval.getFirstUse()) { 1348 // All active and inactive intervals are used before current. Therefore, it is best to spill 1349 // current itself. 1350 int splitPosition = unhandledInterval.getFirstUse(); 1351 LiveIntervals split = unhandledInterval.splitBefore(splitPosition); 1352 assert split != unhandledInterval; 1353 int registerNumber = getSpillRegister(unhandledInterval); 1354 assignRegisterToUnhandledInterval(unhandledInterval, needsRegisterPair, registerNumber); 1355 unhandledInterval.setSpilled(true); 1356 unhandled.add(split); 1357 } else if (blockedPosition > unhandledInterval.getEnd()) { 1358 // Spilling can make a register available for the entire interval. 1359 assignRegisterAndSpill(unhandledInterval, needsRegisterPair, candidate); 1360 } else { 1361 // Spilling only makes a register available for the first part of current. 1362 LiveIntervals splitChild = unhandledInterval.splitBefore(blockedPosition); 1363 unhandled.add(splitChild); 1364 assignRegisterAndSpill(unhandledInterval, needsRegisterPair, candidate); 1365 } 1366 } 1367 getLargestPosition(RegisterPositions usePositions, int register, boolean needsRegisterPair)1368 private int getLargestPosition(RegisterPositions usePositions, int register, 1369 boolean needsRegisterPair) { 1370 int largestUsePosition = usePositions.get(register); 1371 1372 if (needsRegisterPair) { 1373 largestUsePosition = Math.min(largestUsePosition, usePositions.get(register + 1)); 1374 } 1375 1376 return largestUsePosition; 1377 } 1378 getBlockedPosition(RegisterPositions blockedPositions, int register, boolean needsRegisterPair)1379 private int getBlockedPosition(RegisterPositions blockedPositions, int register, 1380 boolean needsRegisterPair) { 1381 int blockedPosition = blockedPositions.get(register); 1382 1383 if (needsRegisterPair) { 1384 blockedPosition = Math.min(blockedPosition, blockedPositions.get(register + 1)); 1385 } 1386 1387 return blockedPosition; 1388 } 1389 assignRegisterAndSpill( LiveIntervals unhandledInterval, boolean needsRegisterPair, int candidate)1390 private void assignRegisterAndSpill( 1391 LiveIntervals unhandledInterval, 1392 boolean needsRegisterPair, 1393 int candidate) { 1394 assignRegister(unhandledInterval, candidate); 1395 updateRegisterState(candidate, needsRegisterPair); 1396 // Split and spill intersecting active intervals for this register. 1397 spillOverlappingActiveIntervals(unhandledInterval, needsRegisterPair, candidate); 1398 takeRegistersForIntervals(unhandledInterval); 1399 active.add(unhandledInterval); 1400 // Split all overlapping inactive intervals for this register. They need to have a new 1401 // register assigned at the next use. 1402 splitOverlappingInactiveIntervals(unhandledInterval, needsRegisterPair, candidate); 1403 } 1404 splitOverlappingInactiveIntervals( LiveIntervals unhandledInterval, boolean needsRegisterPair, int candidate)1405 private void splitOverlappingInactiveIntervals( 1406 LiveIntervals unhandledInterval, 1407 boolean needsRegisterPair, 1408 int candidate) { 1409 Iterator<LiveIntervals> inactiveIterator = inactive.iterator(); 1410 while (inactiveIterator.hasNext()) { 1411 LiveIntervals intervals = inactiveIterator.next(); 1412 if ((intervals.usesRegister(candidate) || 1413 (needsRegisterPair && intervals.usesRegister(candidate + 1))) && 1414 intervals.overlaps(unhandledInterval)) { 1415 // If these assertions trigger we have changed the way blocked parts of intervals 1416 // are handled. If we ever get intervals with fixed registers in here, we need 1417 // to split them before the first use in the same way that we do when spilling 1418 // overlapping active intervals. 1419 assert !intervals.isLinked() || intervals.isArgumentInterval(); 1420 if (intervals.getStart() > unhandledInterval.getStart()) { 1421 // The inactive live intervals hasn't started yet. Clear the temporary register 1422 // assignment and move back to unhandled for register reassignment. 1423 intervals.clearRegisterAssignment(); 1424 inactiveIterator.remove(); 1425 unhandled.add(intervals); 1426 } else { 1427 // The inactive live intervals is in a live range hole. Split the interval and 1428 // put the ranges after the hole into the unhandled set for register reassignment. 1429 LiveIntervals split = intervals.splitBefore(unhandledInterval.getStart()); 1430 unhandled.add(split); 1431 } 1432 } 1433 } 1434 } 1435 spillOverlappingActiveIntervals( LiveIntervals unhandledInterval, boolean needsRegisterPair, int candidate)1436 private void spillOverlappingActiveIntervals( 1437 LiveIntervals unhandledInterval, 1438 boolean needsRegisterPair, 1439 int candidate) { 1440 List<LiveIntervals> newActive = new ArrayList<>(); 1441 Iterator<LiveIntervals> activeIterator = active.iterator(); 1442 while (activeIterator.hasNext()) { 1443 LiveIntervals intervals = activeIterator.next(); 1444 if (intervals.usesRegister(candidate) || 1445 (needsRegisterPair && intervals.usesRegister(candidate + 1))) { 1446 activeIterator.remove(); 1447 freeRegistersForIntervals(intervals); 1448 LiveIntervals splitChild = intervals.splitBefore(unhandledInterval.getStart()); 1449 int registerNumber = getSpillRegister(intervals); 1450 assignRegister(splitChild, registerNumber); 1451 splitChild.setSpilled(true); 1452 takeRegistersForIntervals(splitChild); 1453 assert splitChild.getRegister() != NO_REGISTER; 1454 assert intervals.getRegister() != NO_REGISTER; 1455 newActive.add(splitChild); 1456 // If the constant is split before its first actual use, mark the constant as being 1457 // spilled. That will allows us to remove it afterwards if it is rematerializable. 1458 if (intervals.getValue().isConstant() 1459 && intervals.getStart() == intervals.getValue().definition.getNumber() 1460 && intervals.getUses().size() == 1) { 1461 intervals.setSpilled(true); 1462 } 1463 if (splitChild.getUses().size() > 0) { 1464 if (splitChild.isLinked() && !splitChild.isArgumentInterval()) { 1465 // Spilling a value with a pinned register. We need to move back at the next use. 1466 LiveIntervals splitOfSplit = splitChild.splitBefore(splitChild.getFirstUse()); 1467 splitOfSplit.setRegister(intervals.getRegister()); 1468 inactive.add(splitOfSplit); 1469 } else if (intervals.getValue().isConstant()) { 1470 splitRangesForSpilledConstant(splitChild, registerNumber); 1471 } else if (intervals.isArgumentInterval()) { 1472 splitRangesForSpilledArgument(splitChild); 1473 } else { 1474 splitRangesForSpilledInterval(splitChild, registerNumber); 1475 } 1476 } 1477 } 1478 } 1479 active.addAll(newActive); 1480 } 1481 splitRangesForSpilledArgument(LiveIntervals spilled)1482 private void splitRangesForSpilledArgument(LiveIntervals spilled) { 1483 assert spilled.isSpilled(); 1484 assert spilled.isArgumentInterval(); 1485 // Argument intervals are spilled to the original argument register. We don't know what 1486 // that is yet, and therefore we split before the next use to make sure we get a usable 1487 // register at the next use. 1488 if (!spilled.getUses().isEmpty()) { 1489 LiveIntervals split = spilled.splitBefore(spilled.getUses().first().getPosition()); 1490 unhandled.add(split); 1491 } 1492 } 1493 splitRangesForSpilledInterval(LiveIntervals spilled, int registerNumber)1494 private void splitRangesForSpilledInterval(LiveIntervals spilled, int registerNumber) { 1495 // Spilling a non-pinned, non-rematerializable value. We use the value in the spill 1496 // register for as long as possible to avoid further moves. 1497 assert spilled.isSpilled(); 1498 assert !spilled.getValue().isConstant(); 1499 assert !spilled.isLinked() || spilled.isArgumentInterval(); 1500 if (spilled.isArgumentInterval()) { 1501 registerNumber = Constants.U16BIT_MAX; 1502 } 1503 LiveIntervalsUse firstUseWithLowerLimit = null; 1504 boolean hasUsesBeforeFirstUseWithLowerLimit = false; 1505 for (LiveIntervalsUse use : spilled.getUses()) { 1506 if (registerNumber > use.getLimit()) { 1507 firstUseWithLowerLimit = use; 1508 break; 1509 } else { 1510 hasUsesBeforeFirstUseWithLowerLimit = true; 1511 } 1512 } 1513 if (hasUsesBeforeFirstUseWithLowerLimit) { 1514 spilled.setSpilled(false); 1515 } 1516 if (firstUseWithLowerLimit != null) { 1517 LiveIntervals splitOfSplit = spilled.splitBefore(firstUseWithLowerLimit.getPosition()); 1518 unhandled.add(splitOfSplit); 1519 } 1520 } 1521 splitRangesForSpilledConstant(LiveIntervals spilled, int spillRegister)1522 private void splitRangesForSpilledConstant(LiveIntervals spilled, int spillRegister) { 1523 // When spilling a constant we should not keep it alive in the spill register, instead 1524 // we should use rematerialization. We aggressively spill the constant in all gaps 1525 // between uses that span more than a certain number of instructions. If we needed to 1526 // spill we are running low on registers and this constant should get out of the way 1527 // as much as possible. 1528 assert spilled.isSpilled(); 1529 assert spilled.getValue().isConstant(); 1530 assert !spilled.isLinked() || spilled.isArgumentInterval(); 1531 // Do not split range if constant is reused by one of the eleven following instruction. 1532 int maxGapSize = 11 * INSTRUCTION_NUMBER_DELTA; 1533 if (!spilled.getUses().isEmpty()) { 1534 // Split at first use after the spill position and add to unhandled to get a register 1535 // assigned for rematerialization. 1536 LiveIntervals split = spilled.splitBefore(spilled.getFirstUse()); 1537 unhandled.add(split); 1538 // Now repeatedly split for each use that is more than maxGapSize away from the previous use. 1539 boolean changed = true; 1540 while (changed) { 1541 changed = false; 1542 int previousUse = split.getStart(); 1543 for (LiveIntervalsUse use : split.getUses()) { 1544 if (use.getPosition() - previousUse > maxGapSize) { 1545 // Found a use that is more than gap size away from the previous use. Split after 1546 // the previous use. 1547 split = split.splitBefore(previousUse + INSTRUCTION_NUMBER_DELTA); 1548 // If the next use is not at the start of the new split, we split again at the next use 1549 // and spill the gap. 1550 if (toGapPosition(use.getPosition()) > split.getStart()) { 1551 assignRegister(split, spillRegister); 1552 split.setSpilled(true); 1553 inactive.add(split); 1554 split = split.splitBefore(use.getPosition()); 1555 } 1556 // |split| now starts at the next use - add it to unhandled to get a register 1557 // assigned for rematerialization. 1558 unhandled.add(split); 1559 // Break out of the loop to start iterating the new split uses. 1560 changed = true; 1561 break; 1562 } 1563 previousUse = use.getPosition(); 1564 } 1565 } 1566 } 1567 } 1568 blockLinkedRegisters( List<LiveIntervals> intervalsList, LiveIntervals interval, int registerConstraint, RegisterPositions usePositions, RegisterPositions blockedPositions)1569 private void blockLinkedRegisters( 1570 List<LiveIntervals> intervalsList, LiveIntervals interval, int registerConstraint, 1571 RegisterPositions usePositions, RegisterPositions blockedPositions) { 1572 for (LiveIntervals other : intervalsList) { 1573 if (other.isLinked()) { 1574 int register = other.getRegister(); 1575 if (register <= registerConstraint && other.overlaps(interval)) { 1576 for (int i = 0; i < other.requiredRegisters(); i++) { 1577 if (register + i <= registerConstraint) { 1578 int firstUse = other.firstUseAfter(interval.getStart()); 1579 if (firstUse < blockedPositions.get(register + i)) { 1580 blockedPositions.set(register + i, firstUse, other.isConstantNumberInterval()); 1581 // If we start blocking registers other than linked arguments, we might need to 1582 // explicitly update the use positions as well as blocked positions. 1583 assert usePositions.get(register + i) <= blockedPositions.get(register + i); 1584 } 1585 } 1586 } 1587 } 1588 } 1589 } 1590 } 1591 insertMoves()1592 private void insertMoves() { 1593 SpillMoveSet spillMoves = 1594 new SpillMoveSet(this, code, numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS); 1595 for (LiveIntervals intervals : liveIntervals) { 1596 if (intervals.hasSplits()) { 1597 LiveIntervals current = intervals; 1598 PriorityQueue<LiveIntervals> sortedChildren = 1599 new PriorityQueue<>((o1, o2) -> Integer.compare(o1.getStart(), o2.getStart())); 1600 sortedChildren.addAll(current.getSplitChildren()); 1601 for (LiveIntervals split = sortedChildren.poll(); 1602 split != null; 1603 split = sortedChildren.poll()) { 1604 int position = split.getStart(); 1605 spillMoves.addSpillOrRestoreMove(toGapPosition(position), split, current); 1606 current = split; 1607 } 1608 } 1609 } 1610 1611 resolveControlFlow(spillMoves); 1612 firstParallelMoveTemporary = maxRegisterNumber + 1; 1613 maxRegisterNumber += spillMoves.scheduleAndInsertMoves(maxRegisterNumber + 1); 1614 } 1615 1616 // Resolve control flow by inserting phi moves and by inserting moves when the live intervals 1617 // change for a value across block boundaries. resolveControlFlow(SpillMoveSet spillMoves)1618 private void resolveControlFlow(SpillMoveSet spillMoves) { 1619 // For a control-flow graph like the following where a value v is split at an instruction in 1620 // block C a spill move is inserted in block C to transfer the value from register r0 to 1621 // register r1. However, that move is not executed when taking the control-flow edge from 1622 // B to D and therefore resolution will insert a move from r0 to r1 on that edge. 1623 // 1624 // r0 r1 1625 // v: |----------------|--------| 1626 // 1627 // A ----> B ----> C ----> D 1628 // | ^ 1629 // +---------------+ 1630 for (BasicBlock block : code.blocks) { 1631 for (BasicBlock successor : block.getSuccessors()) { 1632 // If we are processing an exception edge, we need to use the throwing instruction 1633 // as the instruction we are coming from. 1634 int fromInstruction = block.exit().getNumber(); 1635 boolean isCatch = block.hasCatchSuccessor(successor); 1636 if (isCatch) { 1637 for (Instruction instruction : block.getInstructions()) { 1638 if (instruction.instructionTypeCanThrow()) { 1639 fromInstruction = instruction.getNumber(); 1640 break; 1641 } 1642 } 1643 } 1644 int toInstruction = successor.entry().getNumber(); 1645 1646 // Insert spill/restore moves when a value changes across a block boundary. 1647 Set<Value> liveAtEntry = liveAtEntrySets.get(successor); 1648 for (Value value : liveAtEntry) { 1649 LiveIntervals parentInterval = value.getLiveIntervals(); 1650 LiveIntervals fromIntervals = parentInterval.getSplitCovering(fromInstruction); 1651 LiveIntervals toIntervals = parentInterval.getSplitCovering(toInstruction); 1652 if (fromIntervals != toIntervals) { 1653 if (block.exit().isGoto() && !isCatch) { 1654 spillMoves.addOutResolutionMove(fromInstruction - 1, toIntervals, fromIntervals); 1655 } else if (successor.entry().isMoveException()) { 1656 spillMoves.addInResolutionMove(toInstruction + 1, toIntervals, fromIntervals); 1657 } else { 1658 spillMoves.addInResolutionMove(toInstruction - 1, toIntervals, fromIntervals); 1659 } 1660 } 1661 } 1662 1663 // Insert phi moves. 1664 int predIndex = successor.getPredecessors().indexOf(block); 1665 for (Phi phi : successor.getPhis()) { 1666 LiveIntervals toIntervals = phi.getLiveIntervals().getSplitCovering(toInstruction); 1667 Value operand = phi.getOperand(predIndex); 1668 LiveIntervals fromIntervals = operand.getLiveIntervals(); 1669 if (operand.isPhi() && operand != phi && successor.getPhis().contains(operand)) { 1670 // If the input to this phi is another phi in this block we want the value after 1671 // merging which is the value for that phi at the from instruction. 1672 fromIntervals = fromIntervals.getSplitCovering(fromInstruction); 1673 } else { 1674 fromIntervals = fromIntervals.getSplitCovering(fromInstruction); 1675 } 1676 if (fromIntervals != toIntervals && !toIntervals.isArgumentInterval()) { 1677 assert block.getSuccessors().size() == 1; 1678 spillMoves.addPhiMove(fromInstruction - 1, toIntervals, fromIntervals); 1679 } 1680 } 1681 } 1682 } 1683 } 1684 1685 /** 1686 * Compute the set of live values at the entry to each block using a backwards data-flow 1687 * analysis. 1688 */ computeLiveAtEntrySets()1689 private void computeLiveAtEntrySets() { 1690 Queue<BasicBlock> worklist = new LinkedList<>(); 1691 // Since this is a backwards data-flow analysis we process the blocks in reverse 1692 // topological order to reduce the number of iterations. 1693 BasicBlock[] sorted = code.topologicallySortedBlocks(); 1694 for (int i = sorted.length - 1; i >= 0; i--) { 1695 worklist.add(sorted[i]); 1696 } 1697 while (!worklist.isEmpty()) { 1698 BasicBlock block = worklist.poll(); 1699 Set<Value> live = new HashSet<>(); 1700 for (BasicBlock succ : block.getSuccessors()) { 1701 Set<Value> succLiveAtEntry = liveAtEntrySets.get(succ); 1702 if (succLiveAtEntry != null) { 1703 live.addAll(succLiveAtEntry); 1704 } 1705 int predIndex = succ.getPredecessors().indexOf(block); 1706 for (Phi phi : succ.getPhis()) { 1707 live.add(phi.getOperand(predIndex)); 1708 } 1709 } 1710 ListIterator<Instruction> iterator = 1711 block.getInstructions().listIterator(block.getInstructions().size()); 1712 while (iterator.hasPrevious()) { 1713 Instruction instruction = iterator.previous(); 1714 if (instruction.outValue() != null) { 1715 live.remove(instruction.outValue()); 1716 } 1717 for (Value use : instruction.inValues()) { 1718 if (use.needsRegister()) { 1719 live.add(use); 1720 } 1721 } 1722 if (options.debug) { 1723 for (Value use : instruction.getDebugValues()) { 1724 assert use.needsRegister(); 1725 live.add(use); 1726 } 1727 Value use = instruction.getPreviousLocalValue(); 1728 if (use != null) { 1729 assert use.needsRegister(); 1730 live.add(use); 1731 } 1732 } 1733 } 1734 for (Phi phi : block.getPhis()) { 1735 live.remove(phi); 1736 } 1737 Set<Value> previousLiveAtEntry = liveAtEntrySets.put(block, live); 1738 // If the live at entry set changed for this block at the predecessors to the worklist if 1739 // they are not already there. 1740 if (previousLiveAtEntry == null || !previousLiveAtEntry.equals(live)) { 1741 for (BasicBlock pred : block.getPredecessors()) { 1742 if (!worklist.contains(pred)) { 1743 worklist.add(pred); 1744 } 1745 } 1746 } 1747 } 1748 assert liveAtEntrySets.get(sorted[0]).size() == 0; 1749 } 1750 addLiveRange(Value v, BasicBlock b, int end)1751 private void addLiveRange(Value v, BasicBlock b, int end) { 1752 int firstInstructionInBlock = b.entry().getNumber(); 1753 int instructionsSize = b.getInstructions().size() * INSTRUCTION_NUMBER_DELTA; 1754 int lastInstructionInBlock = 1755 firstInstructionInBlock + instructionsSize - INSTRUCTION_NUMBER_DELTA; 1756 int instructionNumber; 1757 if (v.isPhi()) { 1758 instructionNumber = firstInstructionInBlock; 1759 } else { 1760 Instruction instruction = v.definition; 1761 instructionNumber = instruction.getNumber(); 1762 } 1763 if (v.getLiveIntervals() == null) { 1764 Value current = v.getStartOfConsecutive(); 1765 LiveIntervals intervals = new LiveIntervals(current); 1766 while (true) { 1767 liveIntervals.add(intervals); 1768 Value next = current.getNextConsecutive(); 1769 if (next == null) { 1770 break; 1771 } 1772 LiveIntervals nextIntervals = new LiveIntervals(next); 1773 intervals.link(nextIntervals); 1774 current = next; 1775 intervals = nextIntervals; 1776 } 1777 } 1778 LiveIntervals intervals = v.getLiveIntervals(); 1779 if (firstInstructionInBlock <= instructionNumber && 1780 instructionNumber <= lastInstructionInBlock) { 1781 if (v.isPhi()) { 1782 // Phis need to interfere with spill restore moves inserted before the instruction because 1783 // the phi value is defined on the inflowing edge. 1784 instructionNumber--; 1785 } 1786 intervals.addRange(new LiveRange(instructionNumber, end)); 1787 if (!v.isPhi()) { 1788 int constraint = v.definition.maxOutValueRegister(); 1789 intervals.addUse(new LiveIntervalsUse(instructionNumber, constraint)); 1790 } 1791 } else { 1792 intervals.addRange(new LiveRange(firstInstructionInBlock - 1, end)); 1793 } 1794 } 1795 1796 /** 1797 * Compute live ranges based on liveAtEntry sets for all basic blocks. 1798 */ computeLiveRanges()1799 private void computeLiveRanges() { 1800 for (BasicBlock block : code.topologicallySortedBlocks()) { 1801 Set<Value> live = new HashSet<>(); 1802 List<BasicBlock> successors = block.getSuccessors(); 1803 Set<Value> phiOperands = new HashSet<>(); 1804 for (BasicBlock successor : successors) { 1805 live.addAll(liveAtEntrySets.get(successor)); 1806 for (Phi phi : successor.getPhis()) { 1807 live.remove(phi); 1808 phiOperands.add(phi.getOperand(successor.getPredecessors().indexOf(block))); 1809 } 1810 } 1811 live.addAll(phiOperands); 1812 List<Instruction> instructions = block.getInstructions(); 1813 for (Value value : live) { 1814 int end = block.entry().getNumber() + instructions.size() * INSTRUCTION_NUMBER_DELTA; 1815 // Make sure that phi operands do not overlap the phi live range. The phi operand is 1816 // not live until the next instruction, but only until the gap before the next instruction 1817 // where the phi value takes over. 1818 if (phiOperands.contains(value)) { 1819 end--; 1820 } 1821 addLiveRange(value, block, end); 1822 } 1823 ListIterator<Instruction> iterator = 1824 block.getInstructions().listIterator(block.getInstructions().size()); 1825 while (iterator.hasPrevious()) { 1826 Instruction instruction = iterator.previous(); 1827 Value definition = instruction.outValue(); 1828 if (definition != null) { 1829 // For instructions that define values which have no use create a live range covering 1830 // the instruction. This will typically be instructions that can have side effects even 1831 // if their output is not used. 1832 if (definition.numberOfAllUsers() == 0) { 1833 addLiveRange(definition, block, instruction.getNumber() + INSTRUCTION_NUMBER_DELTA); 1834 } 1835 live.remove(definition); 1836 } 1837 for (Value use : instruction.inValues()) { 1838 if (!live.contains(use) && use.needsRegister()) { 1839 live.add(use); 1840 addLiveRange(use, block, instruction.getNumber()); 1841 } 1842 if (use.needsRegister()) { 1843 LiveIntervals useIntervals = use.getLiveIntervals(); 1844 useIntervals.addUse( 1845 new LiveIntervalsUse(instruction.getNumber(), instruction.maxInValueRegister())); 1846 } 1847 } 1848 if (options.debug) { 1849 int number = instruction.getNumber(); 1850 for (Value use : instruction.getDebugValues()) { 1851 assert use.needsRegister(); 1852 if (!live.contains(use)) { 1853 live.add(use); 1854 addLiveRange(use, block, number); 1855 } 1856 } 1857 Value use = instruction.getPreviousLocalValue(); 1858 if (use != null) { 1859 assert use.needsRegister(); 1860 if (!live.contains(use)) { 1861 live.add(use); 1862 addLiveRange(use, block, number); 1863 } 1864 } 1865 } 1866 } 1867 } 1868 } 1869 clearUserInfo()1870 private void clearUserInfo() { 1871 code.blocks.forEach(BasicBlock::clearUserInfo); 1872 } 1873 createValue(MoveType type)1874 private Value createValue(MoveType type) { 1875 Value value = code.createValue(type, null); 1876 value.setNeedsRegister(true); 1877 return value; 1878 } 1879 replaceArgument(Invoke invoke, int index, Value newArgument)1880 private void replaceArgument(Invoke invoke, int index, Value newArgument) { 1881 Value argument = invoke.arguments().get(index); 1882 invoke.arguments().set(index, newArgument); 1883 argument.removeUser(invoke); 1884 newArgument.addUser(invoke); 1885 } 1886 generateArgumentMoves(Invoke invoke, InstructionListIterator insertAt)1887 private void generateArgumentMoves(Invoke invoke, InstructionListIterator insertAt) { 1888 // If the invoke instruction require more than 5 registers we link the inputs because they 1889 // need to be in consecutive registers. 1890 if (invoke.requiredArgumentRegisters() > 5 && !argumentsAreAlreadyLinked(invoke)) { 1891 List<Value> arguments = invoke.arguments(); 1892 Value previous = null; 1893 for (int i = 0; i < arguments.size(); i++) { 1894 Value argument = arguments.get(i); 1895 Value newArgument = argument; 1896 // In debug mode, we have debug instructions that are also moves. Do not generate another 1897 // move if there already is a move instruction that we can use. We generate moves if: 1898 // 1899 // 1. the argument is not defined by a move, 1900 // 1901 // 2. the argument is already linked or would cause a cycle if linked, or 1902 // 1903 // 3. the argument has a register constraint (the argument moves are there to make the 1904 // input value to a ranged invoke unconstrained.) 1905 if (argument.definition == null || 1906 !argument.definition.isMove() || 1907 argument.isLinked() || 1908 argument == previous || 1909 argument.hasRegisterConstraint()) { 1910 newArgument = createValue(argument.outType()); 1911 Move move = new Move(newArgument, argument); 1912 move.setBlock(invoke.getBlock()); 1913 replaceArgument(invoke, i, newArgument); 1914 insertAt.add(move); 1915 } 1916 if (previous != null) { 1917 previous.linkTo(newArgument); 1918 } 1919 previous = newArgument; 1920 } 1921 } 1922 } 1923 argumentsAreAlreadyLinked(Invoke invoke)1924 private boolean argumentsAreAlreadyLinked(Invoke invoke) { 1925 Iterator<Value> it = invoke.arguments().iterator(); 1926 Value current = it.next(); 1927 while (it.hasNext()) { 1928 Value next = it.next(); 1929 if (!current.isLinked() || current.getNextConsecutive() != next) { 1930 return false; 1931 } 1932 current = next; 1933 } 1934 return true; 1935 } 1936 createSentinelRegisterValue()1937 private Value createSentinelRegisterValue() { 1938 return createValue(MoveType.OBJECT); 1939 } 1940 createSentinelLiveInterval(Value sentinelValue)1941 private LiveIntervals createSentinelLiveInterval(Value sentinelValue) { 1942 LiveIntervals sentinelInterval = new LiveIntervals(sentinelValue); 1943 sentinelInterval.addRange(LiveRange.INFINITE); 1944 liveIntervals.add(sentinelInterval); 1945 return sentinelInterval; 1946 } 1947 linkArgumentValues()1948 private void linkArgumentValues() { 1949 Value current = preArgumentSentinelValue = createSentinelRegisterValue(); 1950 for (Value argument : code.collectArguments()) { 1951 current.linkTo(argument); 1952 current = argument; 1953 } 1954 Value endSentinel = createSentinelRegisterValue(); 1955 current.linkTo(endSentinel); 1956 } 1957 setupArgumentLiveIntervals()1958 private void setupArgumentLiveIntervals() { 1959 Value current = preArgumentSentinelValue; 1960 LiveIntervals currentIntervals = createSentinelLiveInterval(current); 1961 current = current.getNextConsecutive(); 1962 int index = 0; 1963 while (current.getNextConsecutive() != null) { 1964 // Add a live range to this value from the beginning of the block up to the argument 1965 // instruction to avoid dead arguments without a range. This may create an actually empty 1966 // range like [0,0[ but that works, too. 1967 LiveIntervals argumentInterval = new LiveIntervals(current); 1968 argumentInterval.addRange(new LiveRange(0, index * INSTRUCTION_NUMBER_DELTA)); 1969 index++; 1970 liveIntervals.add(argumentInterval); 1971 currentIntervals.link(argumentInterval); 1972 currentIntervals = argumentInterval; 1973 current = current.getNextConsecutive(); 1974 } 1975 currentIntervals.link(createSentinelLiveInterval(current)); 1976 } 1977 insertArgumentMoves()1978 private void insertArgumentMoves() { 1979 // Record the constraint that incoming arguments are in consecutive registers. 1980 // We also insert sentinel registers before and after the arguments at this 1981 // point. 1982 linkArgumentValues(); 1983 setupArgumentLiveIntervals(); 1984 for (BasicBlock block : code.blocks) { 1985 InstructionListIterator it = block.listIterator(); 1986 while (it.hasNext()) { 1987 Instruction instruction = it.next(); 1988 if (instruction.isInvoke()) { 1989 // Rewind so moves are inserted before the invoke. 1990 it.previous(); 1991 // Generate the argument moves. 1992 generateArgumentMoves(instruction.asInvoke(), it); 1993 // Move past the move again. 1994 it.next(); 1995 } 1996 } 1997 } 1998 } 1999 computeNeedsRegister()2000 private void computeNeedsRegister() { 2001 for (BasicBlock block : code.topologicallySortedBlocks()) { 2002 for (Instruction instruction : block.getInstructions()) { 2003 if (instruction.outValue() != null) { 2004 instruction.outValue().computeNeedsRegister(); 2005 } 2006 } 2007 } 2008 } 2009 pinArgumentRegisters()2010 private void pinArgumentRegisters() { 2011 // Special handling for arguments. Pin their register. 2012 int register = 0; 2013 Value current = preArgumentSentinelValue; 2014 while (current != null) { 2015 LiveIntervals argumentLiveInterval = current.getLiveIntervals(); 2016 // Pin the argument register. We use getFreeConsecutiveRegisters to make sure that we update 2017 // the max register number. 2018 register = getFreeConsecutiveRegisters(argumentLiveInterval.requiredRegisters()); 2019 assignRegister(argumentLiveInterval, register); 2020 current = current.getNextConsecutive(); 2021 } 2022 assert register == numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS - 1; 2023 } 2024 getFreeConsecutiveRegisters(int numberOfRegister)2025 private int getFreeConsecutiveRegisters(int numberOfRegister) { 2026 List<Integer> unused = new ArrayList<>(); 2027 int first = getNextFreeRegister(); 2028 int current = first; 2029 while ((current - first + 1) != numberOfRegister) { 2030 for (int i = 0; i < numberOfRegister - 1; i++) { 2031 int next = getNextFreeRegister(); 2032 if (next != current + 1) { 2033 for (int j = first; j <= current; j++) { 2034 unused.add(j); 2035 } 2036 first = next; 2037 current = first; 2038 break; 2039 } 2040 current++; 2041 } 2042 } 2043 freeRegisters.addAll(unused); 2044 maxRegisterNumber = Math.max(maxRegisterNumber, first + numberOfRegister - 1); 2045 return first; 2046 } 2047 getNextFreeRegister()2048 private int getNextFreeRegister() { 2049 if (freeRegisters.size() > 0) { 2050 return freeRegisters.pollFirst(); 2051 } 2052 return nextUnusedRegisterNumber++; 2053 } 2054 excludeRegistersForInterval(LiveIntervals intervals, Set<Integer> excluded)2055 private void excludeRegistersForInterval(LiveIntervals intervals, Set<Integer> excluded) { 2056 int register = intervals.getRegister(); 2057 for (int i = 0; i < intervals.requiredRegisters(); i++) { 2058 if (freeRegisters.remove(register + i)) { 2059 excluded.add(register + i); 2060 } 2061 } 2062 } 2063 freeRegistersForIntervals(LiveIntervals intervals)2064 private void freeRegistersForIntervals(LiveIntervals intervals) { 2065 int register = intervals.getRegister(); 2066 freeRegisters.add(register); 2067 if (intervals.getType() == MoveType.WIDE) { 2068 freeRegisters.add(register + 1); 2069 } 2070 } 2071 takeRegistersForIntervals(LiveIntervals intervals)2072 private void takeRegistersForIntervals(LiveIntervals intervals) { 2073 int register = intervals.getRegister(); 2074 freeRegisters.remove(register); 2075 if (intervals.getType() == MoveType.WIDE) { 2076 freeRegisters.remove(register + 1); 2077 } 2078 } 2079 noLinkedValues()2080 private boolean noLinkedValues() { 2081 for (BasicBlock block : code.blocks) { 2082 for (Phi phi : block.getPhis()) { 2083 assert phi.getNextConsecutive() == null; 2084 } 2085 for (Instruction instruction : block.getInstructions()) { 2086 for (Value value : instruction.inValues()) { 2087 assert value.getNextConsecutive() == null; 2088 } 2089 assert instruction.outValue() == null || 2090 instruction.outValue().getNextConsecutive() == null; 2091 } 2092 } 2093 return true; 2094 } 2095 print(CfgPrinter printer, String title)2096 public void print(CfgPrinter printer, String title) { 2097 printer.begin("intervals"); 2098 printer.print("name \"").append(title).append("\"").ln(); 2099 PriorityQueue<LiveIntervals> sortedIntervals = 2100 new PriorityQueue<>((o1, o2) -> Integer.compare(o1.getStart(), o2.getStart())); 2101 sortedIntervals.addAll(liveIntervals); 2102 for (LiveIntervals interval = sortedIntervals.poll(); 2103 interval != null; 2104 interval = sortedIntervals.poll()) { 2105 Value value = interval.getValue(); 2106 if (interval.getRanges().get(0).isInfinite()) { 2107 // Skip argument sentinels. 2108 continue; 2109 } 2110 interval.print(printer, value.getNumber(), value.getNumber()); 2111 } 2112 printer.end("intervals"); 2113 } 2114 2115 @Override toString()2116 public String toString() { 2117 StringBuilder builder = new StringBuilder("Live ranges:\n"); 2118 for (LiveIntervals intervals : liveIntervals) { 2119 Value value = intervals.getValue(); 2120 builder.append(value); 2121 builder.append(" "); 2122 builder.append(intervals); 2123 } 2124 builder.append("\nLive range ascii art: \n"); 2125 for (LiveIntervals intervals : liveIntervals) { 2126 Value value = intervals.getValue(); 2127 if (intervals.getRegister() == NO_REGISTER) { 2128 StringUtils.appendRightPadded(builder, value + " (no reg): ", 20); 2129 } else { 2130 StringUtils.appendRightPadded(builder, value + " r" + intervals.getRegister() + ": ", 20); 2131 } 2132 builder.append("|"); 2133 builder.append(intervals.toAscciArtString()); 2134 builder.append("\n"); 2135 } 2136 return builder.toString(); 2137 } 2138 } 2139