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