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.isJavaConstant;
27 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
28 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
29 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
30 import static jdk.vm.ci.code.ValueUtil.isIllegal;
31
32 import java.util.Collections;
33 import java.util.EnumSet;
34 import java.util.List;
35
36 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
37 import org.graalvm.compiler.debug.Debug;
38 import org.graalvm.compiler.debug.Indent;
39 import org.graalvm.compiler.lir.ConstantValue;
40 import org.graalvm.compiler.lir.InstructionValueProcedure;
41 import org.graalvm.compiler.lir.LIRFrameState;
42 import org.graalvm.compiler.lir.LIRInstruction;
43 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
44 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
45 import org.graalvm.compiler.lir.StandardOp;
46 import org.graalvm.compiler.lir.StandardOp.MoveOp;
47 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
48 import org.graalvm.compiler.lir.Variable;
49 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
50 import org.graalvm.compiler.lir.phases.AllocationPhase;
51
52 import jdk.vm.ci.code.TargetDescription;
53 import jdk.vm.ci.meta.AllocatableValue;
54 import jdk.vm.ci.meta.Value;
66
67 @Override
68 protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
69 assignLocations();
70 }
71
72 /**
73 * Assigns the allocated location for an LIR instruction operand back into the instruction.
74 *
75 * @param op current {@link LIRInstruction}
76 * @param operand an LIR instruction operand
77 * @param mode the usage mode for {@code operand} by the instruction
78 * @return the location assigned for the operand
79 */
80 protected Value colorLirOperand(LIRInstruction op, Variable operand, OperandMode mode) {
81 int opId = op.id();
82 Interval interval = allocator.intervalFor(operand);
83 assert interval != null : "interval must exist";
84
85 if (opId != -1) {
86 if (DetailedAsserts.getValue()) {
87 AbstractBlockBase<?> block = allocator.blockForId(opId);
88 if (block.getSuccessorCount() <= 1 && opId == allocator.getLastLirInstructionId(block)) {
89 /*
90 * Check if spill moves could have been appended at the end of this block, but
91 * before the branch instruction. So the split child information for this branch
92 * would be incorrect.
93 */
94 LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
95 if (instr instanceof StandardOp.JumpOp) {
96 if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) {
97 assert false : String.format(
98 "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow) block=%s, instruction=%s, operand=%s",
99 block, instr, operand);
100 }
101 }
102 }
103 }
104
105 /*
106 * Operands are not changed when an interval is split during allocation, so search the
145 tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]);
146 mode = OperandMode.DEF;
147 }
148 }
149 }
150
151 /*
152 * Get current location of operand. The operand must be live because debug information is
153 * considered when building the intervals if the interval is not live, colorLirOperand will
154 * cause an assert on failure.
155 */
156 Value result = colorLirOperand(op, (Variable) operand, mode);
157 assert !allocator.hasCall(tempOpId) || isStackSlotValue(result) || isJavaConstant(result) || !allocator.isCallerSave(result) : "cannot have caller-save register operands at calls";
158 return result;
159 }
160
161 private void computeDebugInfo(final LIRInstruction op, LIRFrameState info) {
162 info.forEachState(op, this::debugInfoProcedure);
163 }
164
165 private void assignLocations(List<LIRInstruction> instructions) {
166 int numInst = instructions.size();
167 boolean hasDead = false;
168
169 for (int j = 0; j < numInst; j++) {
170 final LIRInstruction op = instructions.get(j);
171 if (op == null) {
172 /*
173 * this can happen when spill-moves are removed in eliminateSpillMoves
174 */
175 hasDead = true;
176 } else if (assignLocations(op)) {
177 instructions.set(j, null);
178 hasDead = true;
179 }
180 }
181
182 if (hasDead) {
183 // Remove null values from the list.
184 instructions.removeAll(Collections.singleton(null));
185 }
|
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.ValueUtil.isIllegal;
26 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
27 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
28 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
29 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
30
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.EnumSet;
34
35 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
36 import org.graalvm.compiler.debug.Debug;
37 import org.graalvm.compiler.debug.Indent;
38 import org.graalvm.compiler.lir.ConstantValue;
39 import org.graalvm.compiler.lir.InstructionValueProcedure;
40 import org.graalvm.compiler.lir.LIRFrameState;
41 import org.graalvm.compiler.lir.LIRInstruction;
42 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
43 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
44 import org.graalvm.compiler.lir.StandardOp;
45 import org.graalvm.compiler.lir.StandardOp.MoveOp;
46 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
47 import org.graalvm.compiler.lir.Variable;
48 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
49 import org.graalvm.compiler.lir.phases.AllocationPhase;
50
51 import jdk.vm.ci.code.TargetDescription;
52 import jdk.vm.ci.meta.AllocatableValue;
53 import jdk.vm.ci.meta.Value;
65
66 @Override
67 protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
68 assignLocations();
69 }
70
71 /**
72 * Assigns the allocated location for an LIR instruction operand back into the instruction.
73 *
74 * @param op current {@link LIRInstruction}
75 * @param operand an LIR instruction operand
76 * @param mode the usage mode for {@code operand} by the instruction
77 * @return the location assigned for the operand
78 */
79 protected Value colorLirOperand(LIRInstruction op, Variable operand, OperandMode mode) {
80 int opId = op.id();
81 Interval interval = allocator.intervalFor(operand);
82 assert interval != null : "interval must exist";
83
84 if (opId != -1) {
85 if (allocator.detailedAsserts) {
86 AbstractBlockBase<?> block = allocator.blockForId(opId);
87 if (block.getSuccessorCount() <= 1 && opId == allocator.getLastLirInstructionId(block)) {
88 /*
89 * Check if spill moves could have been appended at the end of this block, but
90 * before the branch instruction. So the split child information for this branch
91 * would be incorrect.
92 */
93 LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
94 if (instr instanceof StandardOp.JumpOp) {
95 if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) {
96 assert false : String.format(
97 "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow) block=%s, instruction=%s, operand=%s",
98 block, instr, operand);
99 }
100 }
101 }
102 }
103
104 /*
105 * Operands are not changed when an interval is split during allocation, so search the
144 tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]);
145 mode = OperandMode.DEF;
146 }
147 }
148 }
149
150 /*
151 * Get current location of operand. The operand must be live because debug information is
152 * considered when building the intervals if the interval is not live, colorLirOperand will
153 * cause an assert on failure.
154 */
155 Value result = colorLirOperand(op, (Variable) operand, mode);
156 assert !allocator.hasCall(tempOpId) || isStackSlotValue(result) || isJavaConstant(result) || !allocator.isCallerSave(result) : "cannot have caller-save register operands at calls";
157 return result;
158 }
159
160 private void computeDebugInfo(final LIRInstruction op, LIRFrameState info) {
161 info.forEachState(op, this::debugInfoProcedure);
162 }
163
164 private void assignLocations(ArrayList<LIRInstruction> instructions) {
165 int numInst = instructions.size();
166 boolean hasDead = false;
167
168 for (int j = 0; j < numInst; j++) {
169 final LIRInstruction op = instructions.get(j);
170 if (op == null) {
171 /*
172 * this can happen when spill-moves are removed in eliminateSpillMoves
173 */
174 hasDead = true;
175 } else if (assignLocations(op)) {
176 instructions.set(j, null);
177 hasDead = true;
178 }
179 }
180
181 if (hasDead) {
182 // Remove null values from the list.
183 instructions.removeAll(Collections.singleton(null));
184 }
|