SSAMoveResolver.java revision 12651:6ef01bd40ce2
1114402Sru/*
2151497Sru * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
3114402Sru * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4114402Sru *
5114402Sru * This code is free software; you can redistribute it and/or modify it
6114402Sru * under the terms of the GNU General Public License version 2 only, as
7114402Sru * published by the Free Software Foundation.
8114402Sru *
9114402Sru * This code is distributed in the hope that it will be useful, but WITHOUT
10114402Sru * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11114402Sru * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12114402Sru * version 2 for more details (a copy is included in the LICENSE file that
13114402Sru * accompanied this code).
14114402Sru *
15114402Sru * You should have received a copy of the GNU General Public License version
16114402Sru * 2 along with this work; if not, write to the Free Software Foundation,
17114402Sru * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18114402Sru *
19114402Sru * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20151497Sru * or visit www.oracle.com if you need additional information or have any
21114402Sru * questions.
22114402Sru */
23114402Srupackage org.graalvm.compiler.lir.alloc.lsra.ssa;
24114402Sru
25114402Sruimport static org.graalvm.compiler.lir.LIRValueUtil.asVirtualStackSlot;
26114402Sruimport static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
27114402Sruimport static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
28114402Sruimport static jdk.vm.ci.code.ValueUtil.asStackSlot;
29114402Sruimport static jdk.vm.ci.code.ValueUtil.isStackSlot;
30114402Sru
31114402Sruimport java.util.Arrays;
32114402Sru
33114402Sruimport org.graalvm.compiler.debug.GraalError;
34114402Sruimport org.graalvm.compiler.lir.LIRInstruction;
35114402Sruimport org.graalvm.compiler.lir.VirtualStackSlot;
36114402Sruimport org.graalvm.compiler.lir.alloc.lsra.Interval;
37114402Sruimport org.graalvm.compiler.lir.alloc.lsra.LinearScan;
38114402Sruimport org.graalvm.compiler.lir.alloc.lsra.MoveResolver;
39114402Sruimport org.graalvm.compiler.lir.framemap.FrameMap;
40114402Sruimport org.graalvm.compiler.lir.framemap.FrameMapBuilderTool;
41114402Sru
42114402Sruimport jdk.vm.ci.code.StackSlot;
43114402Sruimport jdk.vm.ci.meta.AllocatableValue;
44114402Sruimport jdk.vm.ci.meta.Value;
45114402Sru
46114402Srupublic final class SSAMoveResolver extends MoveResolver {
47114402Sru
48114402Sru    private static final int STACK_SLOT_IN_CALLER_FRAME_IDX = -1;
49114402Sru    private int[] stackBlocked;
50114402Sru    private final int firstVirtualStackIndex;
51114402Sru
52114402Sru    public SSAMoveResolver(LinearScan allocator) {
53114402Sru        super(allocator);
54114402Sru        FrameMapBuilderTool frameMapBuilderTool = (FrameMapBuilderTool) allocator.getFrameMapBuilder();
55114402Sru        FrameMap frameMap = frameMapBuilderTool.getFrameMap();
56114402Sru        this.stackBlocked = new int[frameMapBuilderTool.getNumberOfStackSlots()];
57114402Sru        this.firstVirtualStackIndex = !frameMap.frameNeedsAllocating() ? 0 : frameMap.currentFrameSize() + 1;
58114402Sru    }
59114402Sru
60114402Sru    @Override
61114402Sru    public boolean checkEmpty() {
62114402Sru        for (int i = 0; i < stackBlocked.length; i++) {
63114402Sru            assert stackBlocked[i] == 0 : "stack map must be empty before and after processing";
64114402Sru        }
65114402Sru        return super.checkEmpty();
66114402Sru    }
67114402Sru
68114402Sru    @Override
69114402Sru    protected void checkMultipleReads() {
70114402Sru        // multiple reads are allowed in SSA LSRA
71114402Sru    }
72114402Sru
73114402Sru    @Override
74114402Sru    protected void verifyStackSlotMapping() {
75114402Sru        // relax disjoint stack maps invariant
76114402Sru    }
77114402Sru
78114402Sru    @Override
79114402Sru    protected boolean areMultipleReadsAllowed() {
80114402Sru        return true;
81114402Sru    }
82114402Sru
83114402Sru    @Override
84114402Sru    protected boolean mightBeBlocked(Value location) {
85114402Sru        if (super.mightBeBlocked(location)) {
86114402Sru            return true;
87114402Sru        }
88114402Sru        if (isStackSlotValue(location)) {
89114402Sru            return true;
90114402Sru        }
91114402Sru        return false;
92114402Sru    }
93114402Sru
94114402Sru    private int getStackArrayIndex(Value stackSlotValue) {
95114402Sru        if (isStackSlot(stackSlotValue)) {
96114402Sru            return getStackArrayIndex(asStackSlot(stackSlotValue));
97114402Sru        }
98114402Sru        if (isVirtualStackSlot(stackSlotValue)) {
99114402Sru            return getStackArrayIndex(asVirtualStackSlot(stackSlotValue));
100114402Sru        }
101114402Sru        throw GraalError.shouldNotReachHere("value is not a stack slot: " + stackSlotValue);
102114402Sru    }
103114402Sru
104114402Sru    private int getStackArrayIndex(StackSlot stackSlot) {
105114402Sru        int stackIdx;
106114402Sru        if (stackSlot.isInCallerFrame()) {
107114402Sru            // incoming stack arguments can be ignored
108114402Sru            stackIdx = STACK_SLOT_IN_CALLER_FRAME_IDX;
109114402Sru        } else {
110114402Sru            assert stackSlot.getRawAddFrameSize() : "Unexpected stack slot: " + stackSlot;
111114402Sru            int offset = -stackSlot.getRawOffset();
112114402Sru            assert 0 <= offset && offset < firstVirtualStackIndex : String.format("Wrong stack slot offset: %d (first virtual stack slot index: %d", offset, firstVirtualStackIndex);
113114402Sru            stackIdx = offset;
114114402Sru        }
115114402Sru        return stackIdx;
116114402Sru    }
117114402Sru
118114402Sru    private int getStackArrayIndex(VirtualStackSlot virtualStackSlot) {
119114402Sru        return firstVirtualStackIndex + virtualStackSlot.getId();
120114402Sru    }
121114402Sru
122114402Sru    @Override
123114402Sru    protected void setValueBlocked(Value location, int direction) {
124114402Sru        assert direction == 1 || direction == -1 : "out of bounds";
125114402Sru        if (isStackSlotValue(location)) {
126114402Sru            int stackIdx = getStackArrayIndex(location);
127114402Sru            if (stackIdx == STACK_SLOT_IN_CALLER_FRAME_IDX) {
128114402Sru                // incoming stack arguments can be ignored
129114402Sru                return;
130114402Sru            }
131114402Sru            if (stackIdx >= stackBlocked.length) {
132114402Sru                stackBlocked = Arrays.copyOf(stackBlocked, stackIdx + 1);
133114402Sru            }
134114402Sru            stackBlocked[stackIdx] += direction;
135114402Sru        } else {
136114402Sru            super.setValueBlocked(location, direction);
137114402Sru        }
138114402Sru    }
139114402Sru
140114402Sru    @Override
141114402Sru    protected int valueBlocked(Value location) {
142114402Sru        if (isStackSlotValue(location)) {
143114402Sru            int stackIdx = getStackArrayIndex(location);
144114402Sru            if (stackIdx == STACK_SLOT_IN_CALLER_FRAME_IDX) {
145114402Sru                // incoming stack arguments are always blocked (aka they can not be written)
146114402Sru                return 1;
147114402Sru            }
148114402Sru            if (stackIdx >= stackBlocked.length) {
149114402Sru                return 0;
150114402Sru            }
151114402Sru            return stackBlocked[stackIdx];
152114402Sru        }
153114402Sru        return super.valueBlocked(location);
154114402Sru    }
155114402Sru
156114402Sru    @Override
157114402Sru    protected LIRInstruction createMove(AllocatableValue fromOpr, AllocatableValue toOpr, AllocatableValue fromLocation, AllocatableValue toLocation) {
158114402Sru        if (isStackSlotValue(toLocation) && isStackSlotValue(fromLocation)) {
159114402Sru            return getAllocator().getSpillMoveFactory().createStackMove(toOpr, fromOpr);
160114402Sru        }
161114402Sru        return super.createMove(fromOpr, toOpr, fromLocation, toLocation);
162114402Sru    }
163114402Sru
164114402Sru    @Override
165114402Sru    protected void breakCycle(int spillCandidate) {
166114402Sru        if (spillCandidate != -1) {
167114402Sru            super.breakCycle(spillCandidate);
168114402Sru            return;
169114402Sru        }
170114402Sru        assert mappingFromSize() > 1;
171114402Sru        // Arbitrarily select the first entry for spilling.
172114402Sru        int stackSpillCandidate = 0;
173114402Sru        Interval fromInterval = getMappingFrom(stackSpillCandidate);
174114402Sru        // allocate new stack slot
175114402Sru        VirtualStackSlot spillSlot = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval.kind());
176114402Sru        spillInterval(stackSpillCandidate, fromInterval, spillSlot);
177114402Sru    }
178114402Sru}
179114402Sru