1 /*
   2  * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.lir.alloc.lsra;
  24 
  25 import static jdk.vm.ci.code.CodeUtil.isEven;
  26 import static jdk.vm.ci.code.ValueUtil.asRegister;
  27 import static jdk.vm.ci.code.ValueUtil.isIllegal;
  28 import static jdk.vm.ci.code.ValueUtil.isLegal;
  29 import static jdk.vm.ci.code.ValueUtil.isRegister;
  30 import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
  31 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
  32 import static org.graalvm.compiler.lir.phases.LIRPhase.Options.LIROptimization;
  33 
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.BitSet;
  37 import java.util.EnumSet;
  38 
  39 import org.graalvm.compiler.core.common.LIRKind;
  40 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
  41 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  42 import org.graalvm.compiler.core.common.cfg.BlockMap;
  43 import org.graalvm.compiler.debug.DebugContext;
  44 import org.graalvm.compiler.debug.GraalError;
  45 import org.graalvm.compiler.debug.Indent;
  46 import org.graalvm.compiler.lir.LIR;
  47 import org.graalvm.compiler.lir.LIRInstruction;
  48 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
  49 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
  50 import org.graalvm.compiler.lir.ValueConsumer;
  51 import org.graalvm.compiler.lir.Variable;
  52 import org.graalvm.compiler.lir.VirtualStackSlot;
  53 import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBinding;
  54 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
  55 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
  56 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
  57 import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
  58 import org.graalvm.compiler.options.NestedBooleanOptionKey;
  59 import org.graalvm.compiler.options.Option;
  60 import org.graalvm.compiler.options.OptionKey;
  61 import org.graalvm.compiler.options.OptionType;
  62 import org.graalvm.compiler.options.OptionValues;
  63 import org.graalvm.util.Pair;
  64 
  65 import jdk.vm.ci.code.Register;
  66 import jdk.vm.ci.code.RegisterArray;
  67 import jdk.vm.ci.code.RegisterAttributes;
  68 import jdk.vm.ci.code.RegisterValue;
  69 import jdk.vm.ci.code.TargetDescription;
  70 import jdk.vm.ci.meta.AllocatableValue;
  71 import jdk.vm.ci.meta.Value;
  72 
  73 /**
  74  * An implementation of the linear scan register allocator algorithm described in
  75  * <a href="http://doi.acm.org/10.1145/1064979.1064998" > "Optimized Interval Splitting in a Linear
  76  * Scan Register Allocator"</a> by Christian Wimmer and Hanspeter Moessenboeck.
  77  */
  78 public class LinearScan {
  79 
  80     public static class Options {
  81         // @formatter:off
  82         @Option(help = "Enable spill position optimization", type = OptionType.Debug)
  83         public static final OptionKey<Boolean> LIROptLSRAOptimizeSpillPosition = new NestedBooleanOptionKey(LIROptimization, true);
  84         // @formatter:on
  85     }
  86 
  87     public static class BlockData {
  88 
  89         /**
  90          * Bit map specifying which operands are live upon entry to this block. These are values
  91          * used in this block or any of its successors where such value are not defined in this
  92          * block. The bit index of an operand is its {@linkplain LinearScan#operandNumber(Value)
  93          * operand number}.
  94          */
  95         public BitSet liveIn;
  96 
  97         /**
  98          * Bit map specifying which operands are live upon exit from this block. These are values
  99          * used in a successor block that are either defined in this block or were live upon entry
 100          * to this block. The bit index of an operand is its
 101          * {@linkplain LinearScan#operandNumber(Value) operand number}.
 102          */
 103         public BitSet liveOut;
 104 
 105         /**
 106          * Bit map specifying which operands are used (before being defined) in this block. That is,
 107          * these are the values that are live upon entry to the block. The bit index of an operand
 108          * is its {@linkplain LinearScan#operandNumber(Value) operand number}.
 109          */
 110         public BitSet liveGen;
 111 
 112         /**
 113          * Bit map specifying which operands are defined/overwritten in this block. The bit index of
 114          * an operand is its {@linkplain LinearScan#operandNumber(Value) operand number}.
 115          */
 116         public BitSet liveKill;
 117     }
 118 
 119     public static final int DOMINATOR_SPILL_MOVE_ID = -2;
 120     private static final int SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT = 1;
 121 
 122     private final LIR ir;
 123     private final FrameMapBuilder frameMapBuilder;
 124     private final RegisterAttributes[] registerAttributes;
 125     private final RegisterArray registers;
 126     private final RegisterAllocationConfig regAllocConfig;
 127     private final MoveFactory moveFactory;
 128 
 129     private final BlockMap<BlockData> blockData;
 130     protected final DebugContext debug;
 131 
 132     /**
 133      * List of blocks in linear-scan order. This is only correct as long as the CFG does not change.
 134      */
 135     private final AbstractBlockBase<?>[] sortedBlocks;
 136 
 137     /**
 138      * @see #intervals()
 139      */
 140     private Interval[] intervals;
 141 
 142     /**
 143      * The number of valid entries in {@link #intervals}.
 144      */
 145     private int intervalsSize;
 146 
 147     /**
 148      * The index of the first entry in {@link #intervals} for a
 149      * {@linkplain #createDerivedInterval(Interval) derived interval}.
 150      */
 151     private int firstDerivedIntervalIndex = -1;
 152 
 153     /**
 154      * Intervals sorted by {@link Interval#from()}.
 155      */
 156     private Interval[] sortedIntervals;
 157 
 158     /**
 159      * Map from an instruction {@linkplain LIRInstruction#id id} to the instruction. Entries should
 160      * be retrieved with {@link #instructionForId(int)} as the id is not simply an index into this
 161      * array.
 162      */
 163     private LIRInstruction[] opIdToInstructionMap;
 164 
 165     /**
 166      * Map from an instruction {@linkplain LIRInstruction#id id} to the
 167      * {@linkplain AbstractBlockBase block} containing the instruction. Entries should be retrieved
 168      * with {@link #blockForId(int)} as the id is not simply an index into this array.
 169      */
 170     private AbstractBlockBase<?>[] opIdToBlockMap;
 171 
 172     /**
 173      * The {@linkplain #operandNumber(Value) number} of the first variable operand allocated.
 174      */
 175     private final int firstVariableNumber;
 176     /**
 177      * Number of variables.
 178      */
 179     private int numVariables;
 180     private final boolean neverSpillConstants;
 181 
 182     /**
 183      * Sentinel interval to denote the end of an interval list.
 184      */
 185     protected final Interval intervalEndMarker;
 186     public final Range rangeEndMarker;
 187     public final boolean detailedAsserts;
 188     private final LIRGenerationResult res;
 189 
 190     protected LinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, AbstractBlockBase<?>[] sortedBlocks,
 191                     boolean neverSpillConstants) {
 192         this.ir = res.getLIR();
 193         this.res = res;
 194         this.debug = ir.getDebug();
 195         this.moveFactory = spillMoveFactory;
 196         this.frameMapBuilder = res.getFrameMapBuilder();
 197         this.sortedBlocks = sortedBlocks;
 198         this.registerAttributes = regAllocConfig.getRegisterConfig().getAttributesMap();
 199         this.regAllocConfig = regAllocConfig;
 200 
 201         this.registers = target.arch.getRegisters();
 202         this.firstVariableNumber = getRegisters().size();
 203         this.numVariables = ir.numVariables();
 204         this.blockData = new BlockMap<>(ir.getControlFlowGraph());
 205         this.neverSpillConstants = neverSpillConstants;
 206         this.rangeEndMarker = new Range(Integer.MAX_VALUE, Integer.MAX_VALUE, null);
 207         this.intervalEndMarker = new Interval(Value.ILLEGAL, Interval.END_MARKER_OPERAND_NUMBER, null, rangeEndMarker);
 208         this.intervalEndMarker.next = intervalEndMarker;
 209         this.detailedAsserts = DetailedAsserts.getValue(ir.getOptions());
 210     }
 211 
 212     public LIRGenerationResult getLIRGenerationResult() {
 213         return res;
 214     }
 215 
 216     public Interval intervalEndMarker() {
 217         return intervalEndMarker;
 218     }
 219 
 220     public OptionValues getOptions() {
 221         return ir.getOptions();
 222     }
 223 
 224     public DebugContext getDebug() {
 225         return debug;
 226     }
 227 
 228     public int getFirstLirInstructionId(AbstractBlockBase<?> block) {
 229         int result = ir.getLIRforBlock(block).get(0).id();
 230         assert result >= 0;
 231         return result;
 232     }
 233 
 234     public int getLastLirInstructionId(AbstractBlockBase<?> block) {
 235         ArrayList<LIRInstruction> instructions = ir.getLIRforBlock(block);
 236         int result = instructions.get(instructions.size() - 1).id();
 237         assert result >= 0;
 238         return result;
 239     }
 240 
 241     public MoveFactory getSpillMoveFactory() {
 242         return moveFactory;
 243     }
 244 
 245     protected MoveResolver createMoveResolver() {
 246         MoveResolver moveResolver = new MoveResolver(this);
 247         assert moveResolver.checkEmpty();
 248         return moveResolver;
 249     }
 250 
 251     public static boolean isVariableOrRegister(Value value) {
 252         return isVariable(value) || isRegister(value);
 253     }
 254 
 255     /**
 256      * Converts an operand (variable or register) to an index in a flat address space covering all
 257      * the {@linkplain Variable variables} and {@linkplain RegisterValue registers} being processed
 258      * by this allocator.
 259      */
 260     int operandNumber(Value operand) {
 261         if (isRegister(operand)) {
 262             int number = asRegister(operand).number;
 263             assert number < firstVariableNumber;
 264             return number;
 265         }
 266         assert isVariable(operand) : operand;
 267         return firstVariableNumber + ((Variable) operand).index;
 268     }
 269 
 270     /**
 271      * Gets the number of operands. This value will increase by 1 for new variable.
 272      */
 273     int operandSize() {
 274         return firstVariableNumber + numVariables;
 275     }
 276 
 277     /**
 278      * Gets the highest operand number for a register operand. This value will never change.
 279      */
 280     int maxRegisterNumber() {
 281         return firstVariableNumber - 1;
 282     }
 283 
 284     public BlockData getBlockData(AbstractBlockBase<?> block) {
 285         return blockData.get(block);
 286     }
 287 
 288     void initBlockData(AbstractBlockBase<?> block) {
 289         blockData.put(block, new BlockData());
 290     }
 291 
 292     static final IntervalPredicate IS_PRECOLORED_INTERVAL = new IntervalPredicate() {
 293 
 294         @Override
 295         public boolean apply(Interval i) {
 296             return isRegister(i.operand);
 297         }
 298     };
 299 
 300     static final IntervalPredicate IS_VARIABLE_INTERVAL = new IntervalPredicate() {
 301 
 302         @Override
 303         public boolean apply(Interval i) {
 304             return isVariable(i.operand);
 305         }
 306     };
 307 
 308     static final IntervalPredicate IS_STACK_INTERVAL = new IntervalPredicate() {
 309 
 310         @Override
 311         public boolean apply(Interval i) {
 312             return !isRegister(i.operand);
 313         }
 314     };
 315 
 316     /**
 317      * Gets an object describing the attributes of a given register according to this register
 318      * configuration.
 319      */
 320     public RegisterAttributes attributes(Register reg) {
 321         return registerAttributes[reg.number];
 322     }
 323 
 324     void assignSpillSlot(Interval interval) {
 325         /*
 326          * Assign the canonical spill slot of the parent (if a part of the interval is already
 327          * spilled) or allocate a new spill slot.
 328          */
 329         if (interval.canMaterialize()) {
 330             interval.assignLocation(Value.ILLEGAL);
 331         } else if (interval.spillSlot() != null) {
 332             interval.assignLocation(interval.spillSlot());
 333         } else {
 334             VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(interval.kind());
 335             interval.setSpillSlot(slot);
 336             interval.assignLocation(slot);
 337         }
 338     }
 339 
 340     /**
 341      * Map from {@linkplain #operandNumber(Value) operand numbers} to intervals.
 342      */
 343     public Interval[] intervals() {
 344         return intervals;
 345     }
 346 
 347     void initIntervals() {
 348         intervalsSize = operandSize();
 349         intervals = new Interval[intervalsSize + (intervalsSize >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT)];
 350     }
 351 
 352     /**
 353      * Creates a new interval.
 354      *
 355      * @param operand the operand for the interval
 356      * @return the created interval
 357      */
 358     Interval createInterval(AllocatableValue operand) {
 359         assert isLegal(operand);
 360         int operandNumber = operandNumber(operand);
 361         Interval interval = new Interval(operand, operandNumber, intervalEndMarker, rangeEndMarker);
 362         assert operandNumber < intervalsSize;
 363         assert intervals[operandNumber] == null;
 364         intervals[operandNumber] = interval;
 365         return interval;
 366     }
 367 
 368     /**
 369      * Creates an interval as a result of splitting or spilling another interval.
 370      *
 371      * @param source an interval being split of spilled
 372      * @return a new interval derived from {@code source}
 373      */
 374     Interval createDerivedInterval(Interval source) {
 375         if (firstDerivedIntervalIndex == -1) {
 376             firstDerivedIntervalIndex = intervalsSize;
 377         }
 378         if (intervalsSize == intervals.length) {
 379             intervals = Arrays.copyOf(intervals, intervals.length + (intervals.length >> SPLIT_INTERVALS_CAPACITY_RIGHT_SHIFT) + 1);
 380         }
 381         intervalsSize++;
 382         assert intervalsSize <= intervals.length;
 383         /*
 384          * Note that these variables are not managed and must therefore never be inserted into the
 385          * LIR
 386          */
 387         Variable variable = new Variable(source.kind(), numVariables++);
 388 
 389         Interval interval = createInterval(variable);
 390         assert intervals[intervalsSize - 1] == interval;
 391         return interval;
 392     }
 393 
 394     // access to block list (sorted in linear scan order)
 395     public int blockCount() {
 396         return sortedBlocks.length;
 397     }
 398 
 399     public AbstractBlockBase<?> blockAt(int index) {
 400         return sortedBlocks[index];
 401     }
 402 
 403     /**
 404      * Gets the size of the {@link BlockData#liveIn} and {@link BlockData#liveOut} sets for a basic
 405      * block. These sets do not include any operands allocated as a result of creating
 406      * {@linkplain #createDerivedInterval(Interval) derived intervals}.
 407      */
 408     public int liveSetSize() {
 409         return firstDerivedIntervalIndex == -1 ? operandSize() : firstDerivedIntervalIndex;
 410     }
 411 
 412     int numLoops() {
 413         return ir.getControlFlowGraph().getLoops().size();
 414     }
 415 
 416     Interval intervalFor(int operandNumber) {
 417         return intervals[operandNumber];
 418     }
 419 
 420     public Interval intervalFor(Value operand) {
 421         int operandNumber = operandNumber(operand);
 422         assert operandNumber < intervalsSize;
 423         return intervals[operandNumber];
 424     }
 425 
 426     public Interval getOrCreateInterval(AllocatableValue operand) {
 427         Interval ret = intervalFor(operand);
 428         if (ret == null) {
 429             return createInterval(operand);
 430         } else {
 431             return ret;
 432         }
 433     }
 434 
 435     void initOpIdMaps(int numInstructions) {
 436         opIdToInstructionMap = new LIRInstruction[numInstructions];
 437         opIdToBlockMap = new AbstractBlockBase<?>[numInstructions];
 438     }
 439 
 440     void putOpIdMaps(int index, LIRInstruction op, AbstractBlockBase<?> block) {
 441         opIdToInstructionMap[index] = op;
 442         opIdToBlockMap[index] = block;
 443     }
 444 
 445     /**
 446      * Gets the highest instruction id allocated by this object.
 447      */
 448     int maxOpId() {
 449         assert opIdToInstructionMap.length > 0 : "no operations";
 450         return (opIdToInstructionMap.length - 1) << 1;
 451     }
 452 
 453     /**
 454      * Converts an {@linkplain LIRInstruction#id instruction id} to an instruction index. All LIR
 455      * instructions in a method have an index one greater than their linear-scan order predecessor
 456      * with the first instruction having an index of 0.
 457      */
 458     private static int opIdToIndex(int opId) {
 459         return opId >> 1;
 460     }
 461 
 462     /**
 463      * Retrieves the {@link LIRInstruction} based on its {@linkplain LIRInstruction#id id}.
 464      *
 465      * @param opId an instruction {@linkplain LIRInstruction#id id}
 466      * @return the instruction whose {@linkplain LIRInstruction#id} {@code == id}
 467      */
 468     public LIRInstruction instructionForId(int opId) {
 469         assert isEven(opId) : "opId not even";
 470         LIRInstruction instr = opIdToInstructionMap[opIdToIndex(opId)];
 471         assert instr.id() == opId;
 472         return instr;
 473     }
 474 
 475     /**
 476      * Gets the block containing a given instruction.
 477      *
 478      * @param opId an instruction {@linkplain LIRInstruction#id id}
 479      * @return the block containing the instruction denoted by {@code opId}
 480      */
 481     public AbstractBlockBase<?> blockForId(int opId) {
 482         assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range";
 483         return opIdToBlockMap[opIdToIndex(opId)];
 484     }
 485 
 486     boolean isBlockBegin(int opId) {
 487         return opId == 0 || blockForId(opId) != blockForId(opId - 1);
 488     }
 489 
 490     boolean coversBlockBegin(int opId1, int opId2) {
 491         return blockForId(opId1) != blockForId(opId2);
 492     }
 493 
 494     /**
 495      * Determines if an {@link LIRInstruction} destroys all caller saved registers.
 496      *
 497      * @param opId an instruction {@linkplain LIRInstruction#id id}
 498      * @return {@code true} if the instruction denoted by {@code id} destroys all caller saved
 499      *         registers.
 500      */
 501     boolean hasCall(int opId) {
 502         assert isEven(opId) : "opId not even";
 503         return instructionForId(opId).destroysCallerSavedRegisters();
 504     }
 505 
 506     abstract static class IntervalPredicate {
 507 
 508         abstract boolean apply(Interval i);
 509     }
 510 
 511     public boolean isProcessed(Value operand) {
 512         return !isRegister(operand) || attributes(asRegister(operand)).isAllocatable();
 513     }
 514 
 515     // * Phase 5: actual register allocation
 516 
 517     private static boolean isSorted(Interval[] intervals) {
 518         int from = -1;
 519         for (Interval interval : intervals) {
 520             assert interval != null;
 521             assert from <= interval.from();
 522             from = interval.from();
 523         }
 524         return true;
 525     }
 526 
 527     static Interval addToList(Interval first, Interval prev, Interval interval) {
 528         Interval newFirst = first;
 529         if (prev != null) {
 530             prev.next = interval;
 531         } else {
 532             newFirst = interval;
 533         }
 534         return newFirst;
 535     }
 536 
 537     Pair<Interval, Interval> createUnhandledLists(IntervalPredicate isList1, IntervalPredicate isList2) {
 538         assert isSorted(sortedIntervals) : "interval list is not sorted";
 539 
 540         Interval list1 = intervalEndMarker;
 541         Interval list2 = intervalEndMarker;
 542 
 543         Interval list1Prev = null;
 544         Interval list2Prev = null;
 545         Interval v;
 546 
 547         int n = sortedIntervals.length;
 548         for (int i = 0; i < n; i++) {
 549             v = sortedIntervals[i];
 550             if (v == null) {
 551                 continue;
 552             }
 553 
 554             if (isList1.apply(v)) {
 555                 list1 = addToList(list1, list1Prev, v);
 556                 list1Prev = v;
 557             } else if (isList2 == null || isList2.apply(v)) {
 558                 list2 = addToList(list2, list2Prev, v);
 559                 list2Prev = v;
 560             }
 561         }
 562 
 563         if (list1Prev != null) {
 564             list1Prev.next = intervalEndMarker;
 565         }
 566         if (list2Prev != null) {
 567             list2Prev.next = intervalEndMarker;
 568         }
 569 
 570         assert list1Prev == null || list1Prev.next.isEndMarker() : "linear list ends not with sentinel";
 571         assert list2Prev == null || list2Prev.next.isEndMarker() : "linear list ends not with sentinel";
 572 
 573         return Pair.create(list1, list2);
 574     }
 575 
 576     protected void sortIntervalsBeforeAllocation() {
 577         int sortedLen = 0;
 578         for (Interval interval : intervals) {
 579             if (interval != null) {
 580                 sortedLen++;
 581             }
 582         }
 583 
 584         Interval[] sortedList = new Interval[sortedLen];
 585         int sortedIdx = 0;
 586         int sortedFromMax = -1;
 587 
 588         // special sorting algorithm: the original interval-list is almost sorted,
 589         // only some intervals are swapped. So this is much faster than a complete QuickSort
 590         for (Interval interval : intervals) {
 591             if (interval != null) {
 592                 int from = interval.from();
 593 
 594                 if (sortedFromMax <= from) {
 595                     sortedList[sortedIdx++] = interval;
 596                     sortedFromMax = interval.from();
 597                 } else {
 598                     // the assumption that the intervals are already sorted failed,
 599                     // so this interval must be sorted in manually
 600                     int j;
 601                     for (j = sortedIdx - 1; j >= 0 && from < sortedList[j].from(); j--) {
 602                         sortedList[j + 1] = sortedList[j];
 603                     }
 604                     sortedList[j + 1] = interval;
 605                     sortedIdx++;
 606                 }
 607             }
 608         }
 609         sortedIntervals = sortedList;
 610     }
 611 
 612     void sortIntervalsAfterAllocation() {
 613         if (firstDerivedIntervalIndex == -1) {
 614             // no intervals have been added during allocation, so sorted list is already up to date
 615             return;
 616         }
 617 
 618         Interval[] oldList = sortedIntervals;
 619         Interval[] newList = Arrays.copyOfRange(intervals, firstDerivedIntervalIndex, intervalsSize);
 620         int oldLen = oldList.length;
 621         int newLen = newList.length;
 622 
 623         // conventional sort-algorithm for new intervals
 624         Arrays.sort(newList, (Interval a, Interval b) -> a.from() - b.from());
 625 
 626         // merge old and new list (both already sorted) into one combined list
 627         Interval[] combinedList = new Interval[oldLen + newLen];
 628         int oldIdx = 0;
 629         int newIdx = 0;
 630 
 631         while (oldIdx + newIdx < combinedList.length) {
 632             if (newIdx >= newLen || (oldIdx < oldLen && oldList[oldIdx].from() <= newList[newIdx].from())) {
 633                 combinedList[oldIdx + newIdx] = oldList[oldIdx];
 634                 oldIdx++;
 635             } else {
 636                 combinedList[oldIdx + newIdx] = newList[newIdx];
 637                 newIdx++;
 638             }
 639         }
 640 
 641         sortedIntervals = combinedList;
 642     }
 643 
 644     // wrapper for Interval.splitChildAtOpId that performs a bailout in product mode
 645     // instead of returning null
 646     public Interval splitChildAtOpId(Interval interval, int opId, LIRInstruction.OperandMode mode) {
 647         Interval result = interval.getSplitChildAtOpId(opId, mode, this);
 648 
 649         if (result != null) {
 650             if (debug.isLogEnabled()) {
 651                 debug.log("Split child at pos %d of interval %s is %s", opId, interval, result);
 652             }
 653             return result;
 654         }
 655         throw new GraalError("LinearScan: interval is null");
 656     }
 657 
 658     static AllocatableValue canonicalSpillOpr(Interval interval) {
 659         assert interval.spillSlot() != null : "canonical spill slot not set";
 660         return interval.spillSlot();
 661     }
 662 
 663     boolean isMaterialized(AllocatableValue operand, int opId, OperandMode mode) {
 664         Interval interval = intervalFor(operand);
 665         assert interval != null : "interval must exist";
 666 
 667         if (opId != -1) {
 668             /*
 669              * Operands are not changed when an interval is split during allocation, so search the
 670              * right interval here.
 671              */
 672             interval = splitChildAtOpId(interval, opId, mode);
 673         }
 674 
 675         return isIllegal(interval.location()) && interval.canMaterialize();
 676     }
 677 
 678     boolean isCallerSave(Value operand) {
 679         return attributes(asRegister(operand)).isCallerSave();
 680     }
 681 
 682     @SuppressWarnings("try")
 683     protected void allocate(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
 684         /*
 685          * This is the point to enable debug logging for the whole register allocation.
 686          */
 687         try (Indent indent = debug.logAndIndent("LinearScan allocate")) {
 688 
 689             createLifetimeAnalysisPhase().apply(target, lirGenRes, context);
 690 
 691             try (DebugContext.Scope s = debug.scope("AfterLifetimeAnalysis", (Object) intervals)) {
 692                 sortIntervalsBeforeAllocation();
 693 
 694                 createRegisterAllocationPhase().apply(target, lirGenRes, context);
 695 
 696                 if (LinearScan.Options.LIROptLSRAOptimizeSpillPosition.getValue(getOptions())) {
 697                     createOptimizeSpillPositionPhase().apply(target, lirGenRes, context);
 698                 }
 699                 createResolveDataFlowPhase().apply(target, lirGenRes, context);
 700 
 701                 sortIntervalsAfterAllocation();
 702 
 703                 if (detailedAsserts) {
 704                     verify();
 705                 }
 706                 beforeSpillMoveElimination();
 707                 createSpillMoveEliminationPhase().apply(target, lirGenRes, context);
 708                 createAssignLocationsPhase().apply(target, lirGenRes, context);
 709 
 710                 if (detailedAsserts) {
 711                     verifyIntervals();
 712                 }
 713             } catch (Throwable e) {
 714                 throw debug.handle(e);
 715             }
 716         }
 717     }
 718 
 719     protected void beforeSpillMoveElimination() {
 720     }
 721 
 722     protected LinearScanLifetimeAnalysisPhase createLifetimeAnalysisPhase() {
 723         return new LinearScanLifetimeAnalysisPhase(this);
 724     }
 725 
 726     protected LinearScanRegisterAllocationPhase createRegisterAllocationPhase() {
 727         return new LinearScanRegisterAllocationPhase(this);
 728     }
 729 
 730     protected LinearScanOptimizeSpillPositionPhase createOptimizeSpillPositionPhase() {
 731         return new LinearScanOptimizeSpillPositionPhase(this);
 732     }
 733 
 734     protected LinearScanResolveDataFlowPhase createResolveDataFlowPhase() {
 735         return new LinearScanResolveDataFlowPhase(this);
 736     }
 737 
 738     protected LinearScanEliminateSpillMovePhase createSpillMoveEliminationPhase() {
 739         return new LinearScanEliminateSpillMovePhase(this);
 740     }
 741 
 742     protected LinearScanAssignLocationsPhase createAssignLocationsPhase() {
 743         return new LinearScanAssignLocationsPhase(this);
 744     }
 745 
 746     @SuppressWarnings("try")
 747     public void printIntervals(String label) {
 748         if (debug.isLogEnabled()) {
 749             try (Indent indent = debug.logAndIndent("intervals %s", label)) {
 750                 for (Interval interval : intervals) {
 751                     if (interval != null) {
 752                         debug.log("%s", interval.logString(this));
 753                     }
 754                 }
 755 
 756                 try (Indent indent2 = debug.logAndIndent("Basic Blocks")) {
 757                     for (int i = 0; i < blockCount(); i++) {
 758                         AbstractBlockBase<?> block = blockAt(i);
 759                         debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop());
 760                     }
 761                 }
 762             }
 763         }
 764         debug.dump(DebugContext.VERBOSE_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label);
 765     }
 766 
 767     boolean verify() {
 768         // (check that all intervals have a correct register and that no registers are overwritten)
 769         verifyIntervals();
 770 
 771         verifyRegisters();
 772 
 773         debug.log("no errors found");
 774 
 775         return true;
 776     }
 777 
 778     @SuppressWarnings("try")
 779     private void verifyRegisters() {
 780         // Enable this logging to get output for the verification process.
 781         try (Indent indent = debug.logAndIndent("verifying register allocation")) {
 782             RegisterVerifier verifier = new RegisterVerifier(this);
 783             verifier.verify(blockAt(0));
 784         }
 785     }
 786 
 787     @SuppressWarnings("try")
 788     protected void verifyIntervals() {
 789         try (Indent indent = debug.logAndIndent("verifying intervals")) {
 790             int len = intervalsSize;
 791 
 792             for (int i = 0; i < len; i++) {
 793                 Interval i1 = intervals[i];
 794                 if (i1 == null) {
 795                     continue;
 796                 }
 797 
 798                 i1.checkSplitChildren();
 799 
 800                 if (i1.operandNumber != i) {
 801                     debug.log("Interval %d is on position %d in list", i1.operandNumber, i);
 802                     debug.log(i1.logString(this));
 803                     throw new GraalError("");
 804                 }
 805 
 806                 if (isVariable(i1.operand) && i1.kind().equals(LIRKind.Illegal)) {
 807                     debug.log("Interval %d has no type assigned", i1.operandNumber);
 808                     debug.log(i1.logString(this));
 809                     throw new GraalError("");
 810                 }
 811 
 812                 if (i1.location() == null) {
 813                     debug.log("Interval %d has no register assigned", i1.operandNumber);
 814                     debug.log(i1.logString(this));
 815                     throw new GraalError("");
 816                 }
 817 
 818                 if (i1.first().isEndMarker()) {
 819                     debug.log("Interval %d has no Range", i1.operandNumber);
 820                     debug.log(i1.logString(this));
 821                     throw new GraalError("");
 822                 }
 823 
 824                 for (Range r = i1.first(); !r.isEndMarker(); r = r.next) {
 825                     if (r.from >= r.to) {
 826                         debug.log("Interval %d has zero length range", i1.operandNumber);
 827                         debug.log(i1.logString(this));
 828                         throw new GraalError("");
 829                     }
 830                 }
 831 
 832                 for (int j = i + 1; j < len; j++) {
 833                     Interval i2 = intervals[j];
 834                     if (i2 == null) {
 835                         continue;
 836                     }
 837 
 838                     // special intervals that are created in MoveResolver
 839                     // . ignore them because the range information has no meaning there
 840                     if (i1.from() == 1 && i1.to() == 2) {
 841                         continue;
 842                     }
 843                     if (i2.from() == 1 && i2.to() == 2) {
 844                         continue;
 845                     }
 846                     Value l1 = i1.location();
 847                     Value l2 = i2.location();
 848                     if (i1.intersects(i2) && !isIllegal(l1) && (l1.equals(l2))) {
 849                         throw GraalError.shouldNotReachHere(String.format("Intervals %d and %d overlap and have the same register assigned\n%s\n%s", i1.operandNumber, i2.operandNumber,
 850                                         i1.logString(this), i2.logString(this)));
 851                     }
 852                 }
 853             }
 854         }
 855     }
 856 
 857     class CheckConsumer implements ValueConsumer {
 858 
 859         boolean ok;
 860         Interval curInterval;
 861 
 862         @Override
 863         public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
 864             if (isRegister(operand)) {
 865                 if (intervalFor(operand) == curInterval) {
 866                     ok = true;
 867                 }
 868             }
 869         }
 870     }
 871 
 872     @SuppressWarnings("try")
 873     void verifyNoOopsInFixedIntervals() {
 874         try (Indent indent = debug.logAndIndent("verifying that no oops are in fixed intervals *")) {
 875             CheckConsumer checkConsumer = new CheckConsumer();
 876 
 877             Interval fixedIntervals;
 878             Interval otherIntervals;
 879             fixedIntervals = createUnhandledLists(IS_PRECOLORED_INTERVAL, null).getLeft();
 880             // to ensure a walking until the last instruction id, add a dummy interval
 881             // with a high operation id
 882             otherIntervals = new Interval(Value.ILLEGAL, -1, intervalEndMarker, rangeEndMarker);
 883             otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
 884             IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals);
 885 
 886             for (AbstractBlockBase<?> block : sortedBlocks) {
 887                 ArrayList<LIRInstruction> instructions = ir.getLIRforBlock(block);
 888 
 889                 for (int j = 0; j < instructions.size(); j++) {
 890                     LIRInstruction op = instructions.get(j);
 891 
 892                     if (op.hasState()) {
 893                         iw.walkBefore(op.id());
 894                         boolean checkLive = true;
 895 
 896                         /*
 897                          * Make sure none of the fixed registers is live across an oopmap since we
 898                          * can't handle that correctly.
 899                          */
 900                         if (checkLive) {
 901                             for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); !interval.isEndMarker(); interval = interval.next) {
 902                                 if (interval.currentTo() > op.id() + 1) {
 903                                     /*
 904                                      * This interval is live out of this op so make sure that this
 905                                      * interval represents some value that's referenced by this op
 906                                      * either as an input or output.
 907                                      */
 908                                     checkConsumer.curInterval = interval;
 909                                     checkConsumer.ok = false;
 910 
 911                                     op.visitEachInput(checkConsumer);
 912                                     op.visitEachAlive(checkConsumer);
 913                                     op.visitEachTemp(checkConsumer);
 914                                     op.visitEachOutput(checkConsumer);
 915 
 916                                     assert checkConsumer.ok : "fixed intervals should never be live across an oopmap point";
 917                                 }
 918                             }
 919                         }
 920                     }
 921                 }
 922             }
 923         }
 924     }
 925 
 926     public LIR getLIR() {
 927         return ir;
 928     }
 929 
 930     public FrameMapBuilder getFrameMapBuilder() {
 931         return frameMapBuilder;
 932     }
 933 
 934     public AbstractBlockBase<?>[] sortedBlocks() {
 935         return sortedBlocks;
 936     }
 937 
 938     public RegisterArray getRegisters() {
 939         return registers;
 940     }
 941 
 942     public RegisterAllocationConfig getRegisterAllocationConfig() {
 943         return regAllocConfig;
 944     }
 945 
 946     public boolean callKillsRegisters() {
 947         return regAllocConfig.getRegisterConfig().areAllAllocatableRegistersCallerSaved();
 948     }
 949 
 950     boolean neverSpillConstants() {
 951         return neverSpillConstants;
 952     }
 953 
 954 }