LinearScan.java revision 12651:6ef01bd40ce2
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 */
23package org.graalvm.compiler.lir.alloc.lsra;
24
25import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
26import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
27import static org.graalvm.compiler.lir.phases.LIRPhase.Options.LIROptimization;
28import static jdk.vm.ci.code.CodeUtil.isEven;
29import static jdk.vm.ci.code.ValueUtil.asRegister;
30import static jdk.vm.ci.code.ValueUtil.isIllegal;
31import static jdk.vm.ci.code.ValueUtil.isLegal;
32import static jdk.vm.ci.code.ValueUtil.isRegister;
33
34import java.util.Arrays;
35import java.util.BitSet;
36import java.util.EnumSet;
37import java.util.List;
38
39import org.graalvm.compiler.core.common.LIRKind;
40import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
41import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
42import org.graalvm.compiler.core.common.cfg.BlockMap;
43import org.graalvm.compiler.debug.Debug;
44import org.graalvm.compiler.debug.Debug.Scope;
45import org.graalvm.compiler.debug.GraalError;
46import org.graalvm.compiler.debug.Indent;
47import org.graalvm.compiler.lir.LIR;
48import org.graalvm.compiler.lir.LIRInstruction;
49import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
50import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
51import org.graalvm.compiler.lir.ValueConsumer;
52import org.graalvm.compiler.lir.Variable;
53import org.graalvm.compiler.lir.VirtualStackSlot;
54import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBinding;
55import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
56import org.graalvm.compiler.lir.gen.LIRGenerationResult;
57import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
58import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
59import org.graalvm.compiler.options.NestedBooleanOptionValue;
60import org.graalvm.compiler.options.Option;
61import org.graalvm.compiler.options.OptionType;
62import org.graalvm.compiler.options.OptionValue;
63
64import jdk.vm.ci.code.Register;
65import jdk.vm.ci.code.RegisterArray;
66import jdk.vm.ci.code.RegisterAttributes;
67import jdk.vm.ci.code.RegisterValue;
68import jdk.vm.ci.code.TargetDescription;
69import jdk.vm.ci.meta.AllocatableValue;
70import 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 */
77public 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}
929