• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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