comparison graal/com.oracle.max.graal.compiler/src/com/sun/c1x/alloc/LinearScan.java @ 2872:0341b6424579

Project renaming.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:42:25 +0200
parents graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java@7f14e6b48a9c
children
comparison
equal deleted inserted replaced
2871:d704eb526603 2872:0341b6424579
1 /*
2 * Copyright (c) 2009, 2011, 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 com.sun.c1x.alloc;
24
25 import static com.sun.cri.ci.CiUtil.*;
26 import static java.lang.reflect.Modifier.*;
27
28 import java.util.*;
29
30 import com.oracle.graal.graph.*;
31 import com.sun.c1x.*;
32 import com.sun.c1x.alloc.Interval.*;
33 import com.sun.c1x.debug.*;
34 import com.sun.c1x.gen.*;
35 import com.sun.c1x.graph.*;
36 import com.sun.c1x.ir.*;
37 import com.sun.c1x.lir.*;
38 import com.sun.c1x.lir.LIRInstruction.*;
39 import com.sun.c1x.observer.*;
40 import com.sun.c1x.util.*;
41 import com.sun.c1x.value.*;
42 import com.sun.c1x.value.FrameState.*;
43 import com.sun.cri.ci.*;
44 import com.sun.cri.ri.*;
45
46 /**
47 * An implementation of the linear scan register allocator algorithm described
48 * in <a href="http://doi.acm.org/10.1145/1064979.1064998">"Optimized Interval Splitting in a Linear Scan Register Allocator"</a>
49 * by Christian Wimmer and Hanspeter Moessenboeck.
50 *
51 * @author Christian Wimmer (original HotSpot implementation)
52 * @author Thomas Wuerthinger
53 * @author Doug Simon
54 */
55 public final class LinearScan {
56
57 final C1XCompilation compilation;
58 final IR ir;
59 final LIRGenerator gen;
60 final FrameMap frameMap;
61 final RiRegisterAttributes[] registerAttributes;
62 final CiRegister[] registers;
63
64 private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32;
65
66 /**
67 * List of blocks in linear-scan order. This is only correct as long as the CFG does not change.
68 */
69 final LIRBlock[] sortedBlocks;
70
71 final OperandPool operands;
72
73 /**
74 * Number of stack slots used for intervals allocated to memory.
75 */
76 int maxSpills;
77
78 /**
79 * Unused spill slot for a single-word value because of alignment of a double-word value.
80 */
81 CiStackSlot unusedSpillSlot;
82
83 /**
84 * Map from {@linkplain #operandNumber(CiValue) operand numbers} to intervals.
85 */
86 Interval[] intervals;
87
88 /**
89 * The number of valid entries in {@link #intervals}.
90 */
91 int intervalsSize;
92
93 /**
94 * The index of the first entry in {@link #intervals} for a {@linkplain #createDerivedInterval(Interval) derived interval}.
95 */
96 int firstDerivedIntervalIndex = -1;
97
98 /**
99 * Intervals sorted by {@link Interval#from()}.
100 */
101 Interval[] sortedIntervals;
102
103 /**
104 * Map from an instruction {@linkplain LIRInstruction#id id} to the instruction.
105 * Entries should be retrieved with {@link #instructionForId(int)} as the id is
106 * not simply an index into this array.
107 */
108 LIRInstruction[] opIdToInstructionMap;
109
110 /**
111 * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain
112 * LIRBlock block} containing the instruction. Entries should be retrieved with
113 * {@link #blockForId(int)} as the id is not simply an index into this array.
114 */
115 LIRBlock[] opIdToBlockMap;
116
117 /**
118 * Bit set for each variable that is contained in each loop.
119 */
120 BitMap2D intervalInLoop;
121
122 public LinearScan(C1XCompilation compilation, IR ir, LIRGenerator gen, FrameMap frameMap) {
123 this.compilation = compilation;
124 this.ir = ir;
125 this.gen = gen;
126 this.frameMap = frameMap;
127 this.maxSpills = frameMap.initialSpillSlot();
128 this.unusedSpillSlot = null;
129 this.sortedBlocks = ir.linearScanOrder().toArray(new LIRBlock[ir.linearScanOrder().size()]);
130 CiRegister[] allocatableRegisters = compilation.registerConfig.getAllocatableRegisters();
131 this.registers = new CiRegister[CiRegister.maxRegisterNumber(allocatableRegisters) + 1];
132 for (CiRegister reg : allocatableRegisters) {
133 registers[reg.number] = reg;
134 }
135 this.registerAttributes = compilation.registerConfig.getAttributesMap();
136 this.operands = gen.operands;
137 }
138
139 /**
140 * Converts an operand (variable or register) to an index in a flat address space covering all the
141 * {@linkplain CiVariable variables} and {@linkplain CiRegisterValue registers} being processed by this
142 * allocator.
143 */
144 int operandNumber(CiValue operand) {
145 return operands.operandNumber(operand);
146 }
147
148 static final IntervalPredicate IS_PRECOLORED_INTERVAL = new IntervalPredicate() {
149 @Override
150 public boolean apply(Interval i) {
151 return i.operand.isRegister();
152 }
153 };
154
155 static final IntervalPredicate IS_VARIABLE_INTERVAL = new IntervalPredicate() {
156 @Override
157 public boolean apply(Interval i) {
158 return i.operand.isVariable();
159 }
160 };
161
162 static final IntervalPredicate IS_OOP_INTERVAL = new IntervalPredicate() {
163 @Override
164 public boolean apply(Interval i) {
165 return !i.operand.isRegister() && i.kind() == CiKind.Object;
166 }
167 };
168
169 /**
170 * Gets an object describing the attributes of a given register according to this register configuration.
171 */
172 RiRegisterAttributes attributes(CiRegister reg) {
173 return registerAttributes[reg.number];
174 }
175
176 /**
177 * Allocates the next available spill slot for a value of a given kind.
178 */
179 CiStackSlot allocateSpillSlot(CiKind kind) {
180 CiStackSlot spillSlot;
181 if (numberOfSpillSlots(kind) == 2) {
182 if (isOdd(maxSpills)) {
183 // alignment of double-slot values
184 // the hole because of the alignment is filled with the next single-slot value
185 assert unusedSpillSlot == null : "wasting a spill slot";
186 unusedSpillSlot = CiStackSlot.get(kind, maxSpills);
187 maxSpills++;
188 }
189 spillSlot = CiStackSlot.get(kind, maxSpills);
190 maxSpills += 2;
191 } else if (unusedSpillSlot != null) {
192 // re-use hole that was the result of a previous double-word alignment
193 spillSlot = unusedSpillSlot;
194 unusedSpillSlot = null;
195 } else {
196 spillSlot = CiStackSlot.get(kind, maxSpills);
197 maxSpills++;
198 }
199
200 return spillSlot;
201 }
202
203 void assignSpillSlot(Interval interval) {
204 // assign the canonical spill slot of the parent (if a part of the interval
205 // is already spilled) or allocate a new spill slot
206 if (interval.spillSlot() != null) {
207 interval.assignLocation(interval.spillSlot());
208 } else {
209 CiStackSlot slot = allocateSpillSlot(interval.kind());
210 interval.setSpillSlot(slot);
211 interval.assignLocation(slot);
212 }
213 }
214
215 /**
216 * Creates a new interval.
217 *
218 * @param operand the operand for the interval
219 * @return the created interval
220 */
221 Interval createInterval(CiValue operand) {
222 assert isProcessed(operand);
223 assert operand.isLegal();
224 int operandNumber = operandNumber(operand);
225 Interval interval = new Interval(operand, operandNumber);
226 assert operandNumber < intervalsSize;
227 assert intervals[operandNumber] == null;
228 intervals[operandNumber] = interval;
229 return interval;
230 }
231
232 /**
233 * Creates an interval as a result of splitting or spilling another interval.
234 *
235 * @param source an interval being split of spilled
236 * @return a new interval derived from {@code source}
237 */
238 Interval createDerivedInterval(Interval source) {
239 if (firstDerivedIntervalIndex == -1) {
240 firstDerivedIntervalIndex = intervalsSize;
241 }
242 if (intervalsSize == intervals.length) {
243 intervals = Arrays.copyOf(intervals, intervals.length * 2);
244 }
245 intervalsSize++;
246 Interval interval = createInterval(operands.newVariable(source.kind()));
247 assert intervals[intervalsSize - 1] == interval;
248 return interval;
249 }
250
251 // copy the variable flags if an interval is split
252 void copyRegisterFlags(Interval from, Interval to) {
253 if (operands.mustBeByteRegister(from.operand)) {
254 operands.setMustBeByteRegister((CiVariable) to.operand);
255 }
256
257 // Note: do not copy the mustStartInMemory flag because it is not necessary for child
258 // intervals (only the very beginning of the interval must be in memory)
259 }
260
261 // access to block list (sorted in linear scan order)
262 int blockCount() {
263 assert sortedBlocks.length == ir.linearScanOrder().size() : "invalid cached block list";
264 return sortedBlocks.length;
265 }
266
267 LIRBlock blockAt(int index) {
268 assert sortedBlocks[index] == ir.linearScanOrder().get(index) : "invalid cached block list";
269 return sortedBlocks[index];
270 }
271
272 /**
273 * Gets the size of the {@link LIRBlock#liveIn} and {@link LIRBlock#liveOut} sets for a basic block. These sets do
274 * not include any operands allocated as a result of creating {@linkplain #createDerivedInterval(Interval) derived
275 * intervals}.
276 */
277 int liveSetSize() {
278 return firstDerivedIntervalIndex == -1 ? operands.size() : firstDerivedIntervalIndex;
279 }
280
281 int numLoops() {
282 return ir.numLoops();
283 }
284
285 boolean isIntervalInLoop(int interval, int loop) {
286 return intervalInLoop.at(interval, loop);
287 }
288
289 Interval intervalFor(CiValue operand) {
290 int operandNumber = operandNumber(operand);
291 assert operandNumber < intervalsSize;
292 return intervals[operandNumber];
293 }
294
295 /**
296 * Gets the highest instruction id allocated by this object.
297 */
298 int maxOpId() {
299 assert opIdToInstructionMap.length > 0 : "no operations";
300 return (opIdToInstructionMap.length - 1) << 1;
301 }
302
303 /**
304 * Converts an {@linkplain LIRInstruction#id instruction id} to an instruction index.
305 * All LIR instructions in a method have an index one greater than their linear-scan order predecesor
306 * with the first instruction having an index of 0.
307 */
308 static int opIdToIndex(int opId) {
309 return opId >> 1;
310 }
311
312 /**
313 * Retrieves the {@link LIRInstruction} based on its {@linkplain LIRInstruction#id id}.
314 *
315 * @param opId an instruction {@linkplain LIRInstruction#id id}
316 * @return the instruction whose {@linkplain LIRInstruction#id} {@code == id}
317 */
318 LIRInstruction instructionForId(int opId) {
319 assert isEven(opId) : "opId not even";
320 LIRInstruction instr = opIdToInstructionMap[opIdToIndex(opId)];
321 assert instr.id == opId;
322 return instr;
323 }
324
325 /**
326 * Gets the block containing a given instruction.
327 *
328 * @param opId an instruction {@linkplain LIRInstruction#id id}
329 * @return the block containing the instruction denoted by {@code opId}
330 */
331 LIRBlock blockForId(int opId) {
332 assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range";
333 return opIdToBlockMap[opIdToIndex(opId)];
334 }
335
336 boolean isBlockBegin(int opId) {
337 return opId == 0 || blockForId(opId) != blockForId(opId - 1);
338 }
339
340 boolean coversBlockBegin(int opId1, int opId2) {
341 return blockForId(opId1) != blockForId(opId2);
342 }
343
344 /**
345 * Determines if an {@link LIRInstruction} destroys all caller saved registers.
346 *
347 * @param opId an instruction {@linkplain LIRInstruction#id id}
348 * @return {@code true} if the instruction denoted by {@code id} destroys all caller saved registers.
349 */
350 boolean hasCall(int opId) {
351 assert isEven(opId) : "opId not even";
352 return instructionForId(opId).hasCall;
353 }
354
355 /**
356 * Eliminates moves from register to stack if the stack slot is known to be correct.
357 */
358 void changeSpillDefinitionPos(Interval interval, int defPos) {
359 assert interval.isSplitParent() : "can only be called for split parents";
360
361 switch (interval.spillState()) {
362 case NoDefinitionFound:
363 assert interval.spillDefinitionPos() == -1 : "must no be set before";
364 interval.setSpillDefinitionPos(defPos);
365 interval.setSpillState(SpillState.NoSpillStore);
366 break;
367
368 case NoSpillStore:
369 assert defPos <= interval.spillDefinitionPos() : "positions are processed in reverse order when intervals are created";
370 if (defPos < interval.spillDefinitionPos() - 2 || instructionForId(interval.spillDefinitionPos()).code == LIROpcode.Xir) {
371 // second definition found, so no spill optimization possible for this interval
372 interval.setSpillState(SpillState.NoOptimization);
373 } else {
374 // two consecutive definitions (because of two-operand LIR form)
375 assert blockForId(defPos) == blockForId(interval.spillDefinitionPos()) : "block must be equal";
376 }
377 break;
378
379 case NoOptimization:
380 // nothing to do
381 break;
382
383 default:
384 throw new CiBailout("other states not allowed at this time");
385 }
386 }
387
388 // called during register allocation
389 void changeSpillState(Interval interval, int spillPos) {
390 switch (interval.spillState()) {
391 case NoSpillStore: {
392 int defLoopDepth = blockForId(interval.spillDefinitionPos()).loopDepth();
393 int spillLoopDepth = blockForId(spillPos).loopDepth();
394
395 if (defLoopDepth < spillLoopDepth) {
396 // the loop depth of the spilling position is higher then the loop depth
397 // at the definition of the interval . move write to memory out of loop
398 // by storing at definitin of the interval
399 interval.setSpillState(SpillState.StoreAtDefinition);
400 } else {
401 // the interval is currently spilled only once, so for now there is no
402 // reason to store the interval at the definition
403 interval.setSpillState(SpillState.OneSpillStore);
404 }
405 break;
406 }
407
408 case OneSpillStore: {
409 // the interval is spilled more then once, so it is better to store it to
410 // memory at the definition
411 interval.setSpillState(SpillState.StoreAtDefinition);
412 break;
413 }
414
415 case StoreAtDefinition:
416 case StartInMemory:
417 case NoOptimization:
418 case NoDefinitionFound:
419 // nothing to do
420 break;
421
422 default:
423 throw new CiBailout("other states not allowed at this time");
424 }
425 }
426
427 abstract static class IntervalPredicate {
428 abstract boolean apply(Interval i);
429 }
430
431 private static final IntervalPredicate mustStoreAtDefinition = new IntervalPredicate() {
432 @Override
433 public boolean apply(Interval i) {
434 return i.isSplitParent() && i.spillState() == SpillState.StoreAtDefinition;
435 }
436 };
437
438 // called once before assignment of register numbers
439 void eliminateSpillMoves() {
440 if (C1XOptions.TraceLinearScanLevel >= 3) {
441 TTY.println(" Eliminating unnecessary spill moves");
442 }
443
444 // collect all intervals that must be stored after their definition.
445 // the list is sorted by Interval.spillDefinitionPos
446 Interval interval;
447 interval = createUnhandledLists(mustStoreAtDefinition, null).first;
448 if (C1XOptions.DetailedAsserts) {
449 checkIntervals(interval);
450 }
451
452 LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
453 int numBlocks = blockCount();
454 for (int i = 0; i < numBlocks; i++) {
455 LIRBlock block = blockAt(i);
456 List<LIRInstruction> instructions = block.lir().instructionsList();
457 int numInst = instructions.size();
458 boolean hasNew = false;
459
460 // iterate all instructions of the block. skip the first because it is always a label
461 for (int j = 1; j < numInst; j++) {
462 LIRInstruction op = instructions.get(j);
463 int opId = op.id;
464
465 if (opId == -1) {
466 CiValue resultOperand = op.result();
467 // remove move from register to stack if the stack slot is guaranteed to be correct.
468 // only moves that have been inserted by LinearScan can be removed.
469 assert op.code == LIROpcode.Move : "only moves can have a opId of -1";
470 assert resultOperand.isVariable() : "LinearScan inserts only moves to variables";
471
472 LIROp1 op1 = (LIROp1) op;
473 Interval curInterval = intervalFor(resultOperand);
474
475 if (!curInterval.location().isRegister() && curInterval.alwaysInMemory()) {
476 // move target is a stack slot that is always correct, so eliminate instruction
477 if (C1XOptions.TraceLinearScanLevel >= 4) {
478 TTY.println("eliminating move from interval %d to %d", operandNumber(op1.operand()), operandNumber(op1.result()));
479 }
480 instructions.set(j, null); // null-instructions are deleted by assignRegNum
481 }
482
483 } else {
484 // insert move from register to stack just after the beginning of the interval
485 assert interval == Interval.EndMarker || interval.spillDefinitionPos() >= opId : "invalid order";
486 assert interval == Interval.EndMarker || (interval.isSplitParent() && interval.spillState() == SpillState.StoreAtDefinition) : "invalid interval";
487
488 while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) {
489 if (!hasNew) {
490 // prepare insertion buffer (appended when all instructions of the block are processed)
491 insertionBuffer.init(block.lir());
492 hasNew = true;
493 }
494
495 CiValue fromLocation = interval.location();
496 CiValue toLocation = canonicalSpillOpr(interval);
497
498 assert fromLocation.isRegister() : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState();
499 assert toLocation.isStackSlot() : "to operand must be a stack slot";
500
501 insertionBuffer.move(j, fromLocation, toLocation, null);
502
503 if (C1XOptions.TraceLinearScanLevel >= 4) {
504 CiStackSlot slot = interval.spillSlot();
505 TTY.println("inserting move after definition of interval %d to stack slot %d%s at opId %d",
506 interval.operandNumber, slot.index(), slot.inCallerFrame() ? " in caller frame" : "", opId);
507 }
508
509 interval = interval.next;
510 }
511 }
512 } // end of instruction iteration
513
514 if (hasNew) {
515 block.lir().append(insertionBuffer);
516 }
517 } // end of block iteration
518
519 assert interval == Interval.EndMarker : "missed an interval";
520 }
521
522 private void checkIntervals(Interval interval) {
523 Interval prev = null;
524 Interval temp = interval;
525 while (temp != Interval.EndMarker) {
526 assert temp.spillDefinitionPos() > 0 : "invalid spill definition pos";
527 if (prev != null) {
528 assert temp.from() >= prev.from() : "intervals not sorted";
529 assert temp.spillDefinitionPos() >= prev.spillDefinitionPos() : "when intervals are sorted by from : then they must also be sorted by spillDefinitionPos";
530 }
531
532 assert temp.spillSlot() != null : "interval has no spill slot assigned";
533 assert temp.spillDefinitionPos() >= temp.from() : "invalid order";
534 assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized";
535
536 if (C1XOptions.TraceLinearScanLevel >= 4) {
537 TTY.println("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos());
538 }
539
540 prev = temp;
541 temp = temp.next;
542 }
543 }
544
545 /**
546 * Numbers all instructions in all blocks. The numbering follows the {@linkplain ComputeLinearScanOrder linear scan order}.
547 */
548 void numberInstructions() {
549 // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node.
550 int numBlocks = blockCount();
551 int numInstructions = 0;
552 for (int i = 0; i < numBlocks; i++) {
553 numInstructions += blockAt(i).lir().instructionsList().size();
554 }
555
556 // initialize with correct length
557 opIdToInstructionMap = new LIRInstruction[numInstructions];
558 opIdToBlockMap = new LIRBlock[numInstructions];
559
560 int opId = 0;
561 int index = 0;
562
563 for (int i = 0; i < numBlocks; i++) {
564 LIRBlock block = blockAt(i);
565 block.setFirstLirInstructionId(opId);
566 List<LIRInstruction> instructions = block.lir().instructionsList();
567
568 int numInst = instructions.size();
569 for (int j = 0; j < numInst; j++) {
570 LIRInstruction op = instructions.get(j);
571 op.id = opId;
572
573 opIdToInstructionMap[index] = op;
574 opIdToBlockMap[index] = block;
575 assert instructionForId(opId) == op : "must match";
576
577 index++;
578 opId += 2; // numbering of lirOps by two
579 }
580 block.setLastLirInstructionId((opId - 2));
581 }
582 assert index == numInstructions : "must match";
583 assert (index << 1) == opId : "must match: " + (index << 1);
584 }
585
586 /**
587 * Computes local live sets (i.e. {@link LIRBlock#liveGen} and {@link LIRBlock#liveKill}) separately for each block.
588 */
589 void computeLocalLiveSets() {
590 int numBlocks = blockCount();
591 int liveSize = liveSetSize();
592
593 BitMap2D localIntervalInLoop = new BitMap2D(operands.size(), numLoops());
594
595 // iterate all blocks
596 for (int i = 0; i < numBlocks; i++) {
597 LIRBlock block = blockAt(i);
598 final CiBitMap liveGen = new CiBitMap(liveSize);
599 final CiBitMap liveKill = new CiBitMap(liveSize);
600
601 List<LIRInstruction> instructions = block.lir().instructionsList();
602 int numInst = instructions.size();
603
604 // iterate all instructions of the block. skip the first because it is always a label
605 assert !instructions.get(0).hasOperands() : "first operation must always be a label";
606 for (int j = 1; j < numInst; j++) {
607 final LIRInstruction op = instructions.get(j);
608
609 // iterate input operands of instruction
610 int n = op.operandCount(LIRInstruction.OperandMode.Input);
611 for (int k = 0; k < n; k++) {
612 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k);
613
614 if (operand.isVariable()) {
615 int operandNum = operandNumber(operand);
616 if (!liveKill.get(operandNum)) {
617 liveGen.set(operandNum);
618 if (C1XOptions.TraceLinearScanLevel >= 4) {
619 TTY.println(" Setting liveGen for operand %d at instruction %d", operandNum, op.id);
620 }
621 }
622 if (block.loopIndex() >= 0) {
623 localIntervalInLoop.setBit(operandNum, block.loopIndex());
624 }
625 }
626
627 if (C1XOptions.DetailedAsserts) {
628 assert operand.isVariableOrRegister() : "visitor should only return register operands";
629 verifyInput(block, liveKill, operand);
630 }
631 }
632
633 // Add uses of live locals from interpreter's point of view for proper debug information generation
634 LIRDebugInfo info = op.info;
635 if (info != null) {
636 info.state.forEachLiveStateValue(new ValueProcedure() {
637 public void doValue(Value value) {
638 CiValue operand = value.operand();
639 if (operand.isVariable()) {
640 int operandNum = operandNumber(operand);
641 if (!liveKill.get(operandNum)) {
642 liveGen.set(operandNum);
643 if (C1XOptions.TraceLinearScanLevel >= 4) {
644 TTY.println(" Setting liveGen for value %s, LIR opId %d, operand %d because of state for " + op.toString(), Util.valueString(value), op.id, operandNum);
645 }
646 }
647 } else if (operand.isRegister()) {
648 assert !isProcessed(operand) && !operand.kind.isObject();
649 } else {
650 assert operand.isConstant() || operand.isIllegal() : "invalid operand for deoptimization value: " + value;
651 }
652 }
653 });
654 }
655
656 // iterate temp operands of instruction
657 n = op.operandCount(LIRInstruction.OperandMode.Temp);
658 for (int k = 0; k < n; k++) {
659 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k);
660
661 if (operand.isVariable()) {
662 int varNum = operandNumber(operand);
663 liveKill.set(varNum);
664 if (block.loopIndex() >= 0) {
665 localIntervalInLoop.setBit(varNum, block.loopIndex());
666 }
667 }
668
669 if (C1XOptions.DetailedAsserts) {
670 assert operand.isVariableOrRegister() : "visitor should only return register operands";
671 verifyTemp(liveKill, operand);
672 }
673 }
674
675 // iterate output operands of instruction
676 n = op.operandCount(LIRInstruction.OperandMode.Output);
677 for (int k = 0; k < n; k++) {
678 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k);
679
680 if (operand.isVariable()) {
681 int varNum = operandNumber(operand);
682 liveKill.set(varNum);
683 if (block.loopIndex() >= 0) {
684 localIntervalInLoop.setBit(varNum, block.loopIndex());
685 }
686 }
687
688 if (C1XOptions.DetailedAsserts) {
689 assert operand.isVariableOrRegister() : "visitor should only return register operands";
690 // fixed intervals are never live at block boundaries, so
691 // they need not be processed in live sets
692 // process them only in debug mode so that this can be checked
693 verifyTemp(liveKill, operand);
694 }
695 }
696 } // end of instruction iteration
697
698 block.liveGen = liveGen;
699 block.liveKill = liveKill;
700 block.liveIn = new CiBitMap(liveSize);
701 block.liveOut = new CiBitMap(liveSize);
702
703 if (C1XOptions.TraceLinearScanLevel >= 4) {
704 TTY.println("liveGen B%d %s", block.blockID(), block.liveGen);
705 TTY.println("liveKill B%d %s", block.blockID(), block.liveKill);
706 }
707 } // end of block iteration
708
709 intervalInLoop = localIntervalInLoop;
710 }
711
712 private void verifyTemp(CiBitMap liveKill, CiValue operand) {
713 // fixed intervals are never live at block boundaries, so
714 // they need not be processed in live sets
715 // process them only in debug mode so that this can be checked
716 if (!operand.isVariable()) {
717 if (isProcessed(operand)) {
718 liveKill.set(operandNumber(operand));
719 }
720 }
721 }
722
723 private void verifyInput(LIRBlock block, CiBitMap liveKill, CiValue operand) {
724 // fixed intervals are never live at block boundaries, so
725 // they need not be processed in live sets.
726 // this is checked by these assertions to be sure about it.
727 // the entry block may have incoming
728 // values in registers, which is ok.
729 if (!operand.isVariable() && block != ir.startBlock) {
730 if (isProcessed(operand)) {
731 assert liveKill.get(operandNumber(operand)) : "using fixed register that is not defined in this block";
732 }
733 }
734 }
735
736 /**
737 * Performs a backward dataflow analysis to compute global live sets (i.e. {@link LIRBlock#liveIn} and
738 * {@link LIRBlock#liveOut}) for each block.
739 */
740 void computeGlobalLiveSets() {
741 int numBlocks = blockCount();
742 boolean changeOccurred;
743 boolean changeOccurredInBlock;
744 int iterationCount = 0;
745 CiBitMap liveOut = new CiBitMap(liveSetSize()); // scratch set for calculations
746
747 // Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
748 // The loop is executed until a fixpoint is reached (no changes in an iteration)
749 do {
750 changeOccurred = false;
751
752 // iterate all blocks in reverse order
753 for (int i = numBlocks - 1; i >= 0; i--) {
754 LIRBlock block = blockAt(i);
755
756 changeOccurredInBlock = false;
757
758 // liveOut(block) is the union of liveIn(sux), for successors sux of block
759 int n = block.numberOfSux();
760 if (n > 0) {
761 // block has successors
762 if (n > 0) {
763 liveOut.setFrom(block.suxAt(0).liveIn);
764 for (int j = 1; j < n; j++) {
765 liveOut.setUnion(block.suxAt(j).liveIn);
766 }
767 } else {
768 liveOut.clearAll();
769 }
770
771 if (!block.liveOut.isSame(liveOut)) {
772 // A change occurred. Swap the old and new live out sets to avoid copying.
773 CiBitMap temp = block.liveOut;
774 block.liveOut = liveOut;
775 liveOut = temp;
776
777 changeOccurred = true;
778 changeOccurredInBlock = true;
779 }
780 }
781
782 if (iterationCount == 0 || changeOccurredInBlock) {
783 // liveIn(block) is the union of liveGen(block) with (liveOut(block) & !liveKill(block))
784 // note: liveIn has to be computed only in first iteration or if liveOut has changed!
785 CiBitMap liveIn = block.liveIn;
786 liveIn.setFrom(block.liveOut);
787 liveIn.setDifference(block.liveKill);
788 liveIn.setUnion(block.liveGen);
789 }
790
791 if (C1XOptions.TraceLinearScanLevel >= 4) {
792 traceLiveness(changeOccurredInBlock, iterationCount, block);
793 }
794 }
795 iterationCount++;
796
797 if (changeOccurred && iterationCount > 50) {
798 throw new CiBailout("too many iterations in computeGlobalLiveSets");
799 }
800 } while (changeOccurred);
801
802 if (C1XOptions.DetailedAsserts) {
803 verifyLiveness(numBlocks);
804 }
805
806 // check that the liveIn set of the first block is empty
807 LIRBlock startBlock = ir.startBlock;
808 CiBitMap liveInArgs = new CiBitMap(startBlock.liveIn.size());
809 if (!startBlock.liveIn.isSame(liveInArgs)) {
810 if (C1XOptions.DetailedAsserts) {
811 reportFailure(numBlocks);
812 }
813
814 TTY.println("preds=" + startBlock.blockPredecessors().size() + ", succs=" + startBlock.blockSuccessors().size());
815 TTY.println("startBlock-ID: " + startBlock.blockID());
816
817 // bailout of if this occurs in product mode.
818 throw new CiBailout("liveIn set of first block must be empty");
819 }
820 }
821
822 private void reportFailure(int numBlocks) {
823 TTY.println(compilation.method.toString());
824 TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)");
825 TTY.print("affected registers:");
826 TTY.println(ir.startBlock.liveIn.toString());
827
828 // print some additional information to simplify debugging
829 for (int operandNum = 0; operandNum < ir.startBlock.liveIn.size(); operandNum++) {
830 if (ir.startBlock.liveIn.get(operandNum)) {
831 CiValue operand = operands.operandFor(operandNum);
832 Value instr = operand.isVariable() ? gen.operands.instructionForResult(((CiVariable) operand)) : null;
833 TTY.println(" var %d (HIR instruction %s)", operandNum, instr == null ? " " : instr.toString());
834
835 if (instr instanceof Phi) {
836 Phi phi = (Phi) instr;
837 TTY.println("phi block begin: " + phi.block());
838 TTY.println("pred count on blockbegin: " + phi.block().predecessors().size());
839 TTY.println("phi values: " + phi.valueCount());
840 TTY.println("phi block preds:");
841 for (Node n : phi.block().predecessors()) {
842 TTY.println(n.toString());
843 }
844 }
845
846 for (int j = 0; j < numBlocks; j++) {
847 LIRBlock block = blockAt(j);
848 if (block.liveGen.get(operandNum)) {
849 TTY.println(" used in block B%d", block.blockID());
850 for (LIRInstruction ins : block.lir().instructionsList()) {
851 TTY.println(ins.id + ": " + ins.result() + " " + ins.toString());
852 }
853 }
854 if (block.liveKill.get(operandNum)) {
855 TTY.println(" defined in block B%d", block.blockID());
856 for (LIRInstruction ins : block.lir().instructionsList()) {
857 TTY.println(ins.id + ": " + ins.result() + " " + ins.toString());
858 }
859 }
860 }
861 }
862 }
863 }
864
865 private void verifyLiveness(int numBlocks) {
866 // check that fixed intervals are not live at block boundaries
867 // (live set must be empty at fixed intervals)
868 for (int i = 0; i < numBlocks; i++) {
869 LIRBlock block = blockAt(i);
870 for (int j = 0; j <= operands.maxRegisterNumber(); j++) {
871 assert !block.liveIn.get(j) : "liveIn set of fixed register must be empty";
872 assert !block.liveOut.get(j) : "liveOut set of fixed register must be empty";
873 assert !block.liveGen.get(j) : "liveGen set of fixed register must be empty";
874 }
875 }
876 }
877
878 private void traceLiveness(boolean changeOccurredInBlock, int iterationCount, LIRBlock block) {
879 char c = iterationCount == 0 || changeOccurredInBlock ? '*' : ' ';
880 TTY.print("(%d) liveIn%c B%d ", iterationCount, c, block.blockID());
881 TTY.println(block.liveIn.toString());
882 TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.blockID());
883 TTY.println(block.liveOut.toString());
884 }
885
886 Interval addUse(CiValue operand, int from, int to, RegisterPriority registerPriority, CiKind kind) {
887 if (!isProcessed(operand)) {
888 return null;
889 }
890 if (C1XOptions.TraceLinearScanLevel >= 2 && kind == null) {
891 TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name());
892 }
893
894 if (kind == null) {
895 kind = operand.kind.stackKind();
896 }
897 Interval interval = intervalFor(operand);
898 if (interval == null) {
899 interval = createInterval(operand);
900 }
901
902 if (kind != CiKind.Illegal) {
903 interval.setKind(kind);
904 }
905
906 if (operand.isVariable() && gen.operands.mustStayInMemory((CiVariable) operand)) {
907 interval.addRange(from, maxOpId());
908 } else {
909 interval.addRange(from, to);
910 }
911
912 interval.addUsePos(to, registerPriority);
913 return interval;
914 }
915
916 void addTemp(CiValue operand, int tempPos, RegisterPriority registerPriority, CiKind kind) {
917 if (!isProcessed(operand)) {
918 return;
919 }
920 Interval interval = intervalFor(operand);
921 if (interval == null) {
922 interval = createInterval(operand);
923 }
924
925 if (kind != CiKind.Illegal) {
926 interval.setKind(kind);
927 }
928
929 interval.addRange(tempPos, tempPos + 1);
930 interval.addUsePos(tempPos, registerPriority);
931 }
932
933 boolean isProcessed(CiValue operand) {
934 return !operand.isRegister() || attributes(operand.asRegister()).isAllocatable;
935 }
936
937 void addDef(CiValue operand, int defPos, RegisterPriority registerPriority, CiKind kind) {
938 if (!isProcessed(operand)) {
939 return;
940 }
941 if (C1XOptions.TraceLinearScanLevel >= 2) {
942 TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name());
943 }
944 Interval interval = intervalFor(operand);
945 if (interval != null) {
946
947 if (kind != CiKind.Illegal) {
948 interval.setKind(kind);
949 }
950
951 Range r = interval.first();
952 if (r.from <= defPos) {
953 // Update the starting point (when a range is first created for a use, its
954 // start is the beginning of the current block until a def is encountered.)
955 r.from = defPos;
956 interval.addUsePos(defPos, registerPriority);
957
958 } else {
959 // Dead value - make vacuous interval
960 // also add register priority for dead intervals
961 interval.addRange(defPos, defPos + 1);
962 interval.addUsePos(defPos, registerPriority);
963 if (C1XOptions.TraceLinearScanLevel >= 2) {
964 TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos);
965 }
966 }
967
968 } else {
969 // Dead value - make vacuous interval
970 // also add register priority for dead intervals
971 interval = createInterval(operand);
972 if (kind != CiKind.Illegal) {
973 interval.setKind(kind);
974 }
975
976 interval.addRange(defPos, defPos + 1);
977 interval.addUsePos(defPos, registerPriority);
978 if (C1XOptions.TraceLinearScanLevel >= 2) {
979 TTY.println("Warning: dead value %s at %d in live intervals", operand, defPos);
980 }
981 }
982
983 changeSpillDefinitionPos(interval, defPos);
984 if (registerPriority == RegisterPriority.None && interval.spillState().ordinal() <= SpillState.StartInMemory.ordinal()) {
985 // detection of method-parameters and roundfp-results
986 // TODO: move this directly to position where use-kind is computed
987 interval.setSpillState(SpillState.StartInMemory);
988 }
989 }
990
991 /**
992 * Determines the register priority for an instruction's output/result operand.
993 */
994 RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op, CiValue operand) {
995 if (op.code == LIROpcode.Move) {
996 LIROp1 move = (LIROp1) op;
997 CiValue res = move.result();
998 boolean resultInMemory = res.isVariable() && operands.mustStartInMemory((CiVariable) res);
999
1000 if (resultInMemory) {
1001 // Begin of an interval with mustStartInMemory set.
1002 // This interval will always get a stack slot first, so return noUse.
1003 return RegisterPriority.None;
1004
1005 } else if (move.operand().isStackSlot()) {
1006 // method argument (condition must be equal to handleMethodArguments)
1007 return RegisterPriority.None;
1008
1009 }
1010 }
1011
1012 if (operand.isVariable() && operands.mustStartInMemory((CiVariable) operand)) {
1013 // result is a stack-slot, so prevent immediate reloading
1014 return RegisterPriority.None;
1015 }
1016
1017 // all other operands require a register
1018 return RegisterPriority.MustHaveRegister;
1019 }
1020
1021 /**
1022 * Determines the priority which with an instruction's input operand will be allocated a register.
1023 */
1024 RegisterPriority registerPriorityOfInputOperand(LIRInstruction op, CiValue operand) {
1025 if (op.code == LIROpcode.Move) {
1026 LIROp1 move = (LIROp1) op;
1027 CiValue res = move.result();
1028 boolean resultInMemory = res.isVariable() && operands.mustStartInMemory((CiVariable) res);
1029
1030 if (resultInMemory) {
1031 // Move to an interval with mustStartInMemory set.
1032 // To avoid moves from stack to stack (not allowed) force the input operand to a register
1033 return RegisterPriority.MustHaveRegister;
1034
1035 } else if (move.operand().isVariableOrRegister() && move.result().isVariableOrRegister()) {
1036 // The input operand is not forced to a register (moves from stack to register are allowed),
1037 // but it is faster if the input operand is in a register
1038 return RegisterPriority.ShouldHaveRegister;
1039 }
1040 }
1041
1042 if (compilation.target.arch.isX86()) {
1043 if (op.code == LIROpcode.Cmove) {
1044 // conditional moves can handle stack operands
1045 assert op.result().isVariableOrRegister();
1046 return RegisterPriority.ShouldHaveRegister;
1047 }
1048
1049 // optimizations for second input operand of arithmetic operations on Intel
1050 // this operand is allowed to be on the stack in some cases
1051 CiKind kind = operand.kind.stackKind();
1052 if (kind == CiKind.Float || kind == CiKind.Double) {
1053 // SSE float instruction (CiKind.Double only supported with SSE2)
1054 switch (op.code) {
1055 case Cmp:
1056 case Add:
1057 case Sub:
1058 case Mul:
1059 case Div: {
1060 LIROp2 op2 = (LIROp2) op;
1061 if (op2.operand1() != op2.operand2() && op2.operand2() == operand) {
1062 assert (op2.result().isVariableOrRegister() || op.code == LIROpcode.Cmp) && op2.operand1().isVariableOrRegister() : "cannot mark second operand as stack if others are not in register";
1063 return RegisterPriority.ShouldHaveRegister;
1064 }
1065 }
1066 }
1067 } else if (kind != CiKind.Long) {
1068 // integer instruction (note: long operands must always be in register)
1069 switch (op.code) {
1070 case Cmp:
1071 case Add:
1072 case Sub:
1073 case LogicAnd:
1074 case LogicOr:
1075 case LogicXor: {
1076 LIROp2 op2 = (LIROp2) op;
1077 if (op2.operand1() != op2.operand2() && op2.operand2() == operand) {
1078 assert (op2.result().isVariableOrRegister() || op.code == LIROpcode.Cmp) && op2.operand1().isVariableOrRegister() : "cannot mark second operand as stack if others are not in register";
1079 return RegisterPriority.ShouldHaveRegister;
1080 }
1081 }
1082 }
1083 }
1084 } // X86
1085
1086 // all other operands require a register
1087 return RegisterPriority.MustHaveRegister;
1088 }
1089
1090 /**
1091 * Optimizes moves related to incoming stack based arguments.
1092 * The interval for the destination of such moves is assigned
1093 * the stack slot (which is in the caller's frame) as its
1094 * spill slot.
1095 */
1096 void handleMethodArguments(LIRInstruction op) {
1097 if (op.code == LIROpcode.Move) {
1098 LIROp1 move = (LIROp1) op;
1099
1100 if (move.operand().isStackSlot()) {
1101 CiStackSlot slot = (CiStackSlot) move.operand();
1102 if (C1XOptions.DetailedAsserts) {
1103 int argSlots = compilation.method.signature().argumentSlots(!isStatic(compilation.method.accessFlags()));
1104 assert slot.index() >= 0 && slot.index() < argSlots;
1105 assert move.id > 0 : "invalid id";
1106 assert blockForId(move.id).numberOfPreds() == 0 : "move from stack must be in first block";
1107 assert move.result().isVariable() : "result of move must be a variable";
1108
1109 if (C1XOptions.TraceLinearScanLevel >= 4) {
1110 TTY.println("found move from stack slot %s to %s", slot, move.result());
1111 }
1112 }
1113
1114 Interval interval = intervalFor(move.result());
1115 CiStackSlot copySlot = slot;
1116 if (C1XOptions.CopyPointerStackArguments && slot.kind == CiKind.Object) {
1117 copySlot = allocateSpillSlot(slot.kind);
1118 }
1119 interval.setSpillSlot(copySlot);
1120 interval.assignLocation(copySlot);
1121 }
1122 }
1123 }
1124
1125 void addRegisterHints(LIRInstruction op) {
1126 switch (op.code) {
1127 case Move: // fall through
1128 case Convert: {
1129 LIROp1 move = (LIROp1) op;
1130
1131 CiValue moveFrom = move.operand();
1132 CiValue moveTo = move.result();
1133
1134 if (moveTo.isVariableOrRegister() && moveFrom.isVariableOrRegister()) {
1135 Interval from = intervalFor(moveFrom);
1136 Interval to = intervalFor(moveTo);
1137 if (from != null && to != null) {
1138 to.setLocationHint(from);
1139 if (C1XOptions.TraceLinearScanLevel >= 4) {
1140 TTY.println("operation at opId %d: added hint from interval %d to %d", move.id, from.operandNumber, to.operandNumber);
1141 }
1142 }
1143 }
1144 break;
1145 }
1146 case Cmove: {
1147 LIROp2 cmove = (LIROp2) op;
1148
1149 CiValue moveFrom = cmove.operand1();
1150 CiValue moveTo = cmove.result();
1151
1152 if (moveTo.isVariableOrRegister() && moveFrom.isVariableOrRegister()) {
1153 Interval from = intervalFor(moveFrom);
1154 Interval to = intervalFor(moveTo);
1155 if (from != null && to != null) {
1156 to.setLocationHint(from);
1157 if (C1XOptions.TraceLinearScanLevel >= 4) {
1158 TTY.println("operation at opId %d: added hint from interval %d to %d", cmove.id, from.operandNumber, to.operandNumber);
1159 }
1160 }
1161 }
1162 break;
1163 }
1164 }
1165 }
1166
1167 void buildIntervals() {
1168 intervalsSize = operands.size();
1169 intervals = new Interval[intervalsSize + INITIAL_SPLIT_INTERVALS_CAPACITY];
1170
1171 // create a list with all caller-save registers (cpu, fpu, xmm)
1172 RiRegisterConfig registerConfig = compilation.registerConfig;
1173 CiRegister[] callerSaveRegs = registerConfig.getCallerSaveRegisters();
1174
1175 // iterate all blocks in reverse order
1176 for (int i = blockCount() - 1; i >= 0; i--) {
1177 LIRBlock block = blockAt(i);
1178 List<LIRInstruction> instructions = block.lir().instructionsList();
1179 final int blockFrom = block.firstLirInstructionId();
1180 int blockTo = block.lastLirInstructionId();
1181
1182 assert blockFrom == instructions.get(0).id;
1183 assert blockTo == instructions.get(instructions.size() - 1).id;
1184
1185 // Update intervals for operands live at the end of this block;
1186 CiBitMap live = block.liveOut;
1187 for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
1188 assert live.get(operandNum) : "should not stop here otherwise";
1189 CiValue operand = operands.operandFor(operandNum);
1190 if (C1XOptions.TraceLinearScanLevel >= 2) {
1191 TTY.println("live in %s to %d", operand, blockTo + 2);
1192 }
1193
1194 addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, CiKind.Illegal);
1195
1196 // add special use positions for loop-end blocks when the
1197 // interval is used anywhere inside this loop. It's possible
1198 // that the block was part of a non-natural loop, so it might
1199 // have an invalid loop index.
1200 if (block.isLinearScanLoopEnd() && block.loopIndex() != -1 && isIntervalInLoop(operandNum, block.loopIndex())) {
1201 intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd);
1202 }
1203 }
1204
1205 // iterate all instructions of the block in reverse order.
1206 // skip the first instruction because it is always a label
1207 // definitions of intervals are processed before uses
1208 assert !instructions.get(0).hasOperands() : "first operation must always be a label";
1209 for (int j = instructions.size() - 1; j >= 1; j--) {
1210 LIRInstruction op = instructions.get(j);
1211 final int opId = op.id;
1212
1213 // add a temp range for each register if operation destroys caller-save registers
1214 if (op.hasCall) {
1215 for (CiRegister r : callerSaveRegs) {
1216 if (attributes(r).isAllocatable) {
1217 addTemp(r.asValue(), opId, RegisterPriority.None, CiKind.Illegal);
1218 }
1219 }
1220 if (C1XOptions.TraceLinearScanLevel >= 4) {
1221 TTY.println("operation destroys all caller-save registers");
1222 }
1223 }
1224
1225 // Add any platform dependent temps
1226 pdAddTemps(op);
1227
1228 // visit definitions (output and temp operands)
1229 int k;
1230 int n;
1231 n = op.operandCount(LIRInstruction.OperandMode.Output);
1232 for (k = 0; k < n; k++) {
1233 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k);
1234 assert operand.isVariableOrRegister();
1235 addDef(operand, opId, registerPriorityOfOutputOperand(op, operand), operand.kind.stackKind());
1236 }
1237
1238 n = op.operandCount(LIRInstruction.OperandMode.Temp);
1239 for (k = 0; k < n; k++) {
1240 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k);
1241 assert operand.isVariableOrRegister();
1242 if (C1XOptions.TraceLinearScanLevel >= 2) {
1243 TTY.println(" temp %s tempPos %d (%s)", operand, opId, RegisterPriority.MustHaveRegister.name());
1244 }
1245 addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.kind.stackKind());
1246 }
1247
1248 // visit uses (input operands)
1249 n = op.operandCount(LIRInstruction.OperandMode.Input);
1250 for (k = 0; k < n; k++) {
1251 CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k);
1252 assert operand.isVariableOrRegister();
1253 RegisterPriority p = registerPriorityOfInputOperand(op, operand);
1254 Interval interval = addUse(operand, blockFrom, opId, p, null);
1255 if (interval != null && op instanceof LIRXirInstruction) {
1256 Range range = interval.first();
1257 // (tw) Increase range by 1 in order to overlap the input with the temp and the output operand.
1258 if (range.to == opId) {
1259 range.to++;
1260 }
1261 }
1262 }
1263
1264 // Add uses of live locals from interpreter's point of view for proper
1265 // debug information generation
1266 // Treat these operands as temp values (if the live range is extended
1267 // to a call site, the value would be in a register at the call otherwise)
1268 LIRDebugInfo info = op.info;
1269 if (info != null) {
1270 info.state.forEachLiveStateValue(new ValueProcedure() {
1271 public void doValue(Value value) {
1272 CiValue operand = value.operand();
1273 if (operand.isVariableOrRegister()) {
1274 addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, null);
1275 }
1276 }
1277 });
1278 }
1279
1280 // special steps for some instructions (especially moves)
1281 handleMethodArguments(op);
1282 addRegisterHints(op);
1283
1284 } // end of instruction iteration
1285 } // end of block iteration
1286
1287 // add the range [0, 1] to all fixed intervals.
1288 // the register allocator need not handle unhandled fixed intervals
1289 for (Interval interval : intervals) {
1290 if (interval != null && interval.operand.isRegister()) {
1291 interval.addRange(0, 1);
1292 }
1293 }
1294 }
1295
1296 // * Phase 5: actual register allocation
1297
1298 private void pdAddTemps(LIRInstruction op) {
1299 // TODO Platform dependent!
1300 assert compilation.target.arch.isX86();
1301
1302 switch (op.code) {
1303 case Tan:
1304 case Sin:
1305 case Cos: {
1306 // The slow path for these functions may need to save and
1307 // restore all live registers but we don't want to save and
1308 // restore everything all the time, so mark the xmms as being
1309 // killed. If the slow path were explicit or we could propagate
1310 // live register masks down to the assembly we could do better
1311 // but we don't have any easy way to do that right now. We
1312 // could also consider not killing all xmm registers if we
1313 // assume that slow paths are uncommon but it's not clear that
1314 // would be a good idea.
1315 if (C1XOptions.TraceLinearScanLevel >= 2) {
1316 TTY.println("killing XMMs for trig");
1317 }
1318 int opId = op.id;
1319
1320 for (CiRegister r : compilation.registerConfig.getCallerSaveRegisters()) {
1321 if (r.isFpu()) {
1322 addTemp(r.asValue(), opId, RegisterPriority.None, CiKind.Illegal);
1323 }
1324 }
1325 break;
1326 }
1327 }
1328
1329 }
1330
1331 boolean isSorted(Interval[] intervals) {
1332 int from = -1;
1333 for (Interval interval : intervals) {
1334 assert interval != null;
1335 assert from <= interval.from();
1336 from = interval.from();
1337
1338 // XXX: very slow!
1339 assert Arrays.asList(this.intervals).contains(interval);
1340 }
1341 return true;
1342 }
1343
1344 Interval addToList(Interval first, Interval prev, Interval interval) {
1345 Interval newFirst = first;
1346 if (prev != null) {
1347 prev.next = interval;
1348 } else {
1349 newFirst = interval;
1350 }
1351 return newFirst;
1352 }
1353
1354 Interval.Pair createUnhandledLists(IntervalPredicate isList1, IntervalPredicate isList2) {
1355 assert isSorted(sortedIntervals) : "interval list is not sorted";
1356
1357 Interval list1 = Interval.EndMarker;
1358 Interval list2 = Interval.EndMarker;
1359
1360 Interval list1Prev = null;
1361 Interval list2Prev = null;
1362 Interval v;
1363
1364 int n = sortedIntervals.length;
1365 for (int i = 0; i < n; i++) {
1366 v = sortedIntervals[i];
1367 if (v == null) {
1368 continue;
1369 }
1370
1371 if (isList1.apply(v)) {
1372 list1 = addToList(list1, list1Prev, v);
1373 list1Prev = v;
1374 } else if (isList2 == null || isList2.apply(v)) {
1375 list2 = addToList(list2, list2Prev, v);
1376 list2Prev = v;
1377 }
1378 }
1379
1380 if (list1Prev != null) {
1381 list1Prev.next = Interval.EndMarker;
1382 }
1383 if (list2Prev != null) {
1384 list2Prev.next = Interval.EndMarker;
1385 }
1386
1387 assert list1Prev == null || list1Prev.next == Interval.EndMarker : "linear list ends not with sentinel";
1388 assert list2Prev == null || list2Prev.next == Interval.EndMarker : "linear list ends not with sentinel";
1389
1390 return new Interval.Pair(list1, list2);
1391 }
1392
1393 void sortIntervalsBeforeAllocation() {
1394 int sortedLen = 0;
1395 for (Interval interval : intervals) {
1396 if (interval != null) {
1397 sortedLen++;
1398 }
1399 }
1400
1401 Interval[] sortedList = new Interval[sortedLen];
1402 int sortedIdx = 0;
1403 int sortedFromMax = -1;
1404
1405 // special sorting algorithm: the original interval-list is almost sorted,
1406 // only some intervals are swapped. So this is much faster than a complete QuickSort
1407 for (Interval interval : intervals) {
1408 if (interval != null) {
1409 int from = interval.from();
1410
1411 if (sortedFromMax <= from) {
1412 sortedList[sortedIdx++] = interval;
1413 sortedFromMax = interval.from();
1414 } else {
1415 // the assumption that the intervals are already sorted failed,
1416 // so this interval must be sorted in manually
1417 int j;
1418 for (j = sortedIdx - 1; j >= 0 && from < sortedList[j].from(); j--) {
1419 sortedList[j + 1] = sortedList[j];
1420 }
1421 sortedList[j + 1] = interval;
1422 sortedIdx++;
1423 }
1424 }
1425 }
1426 sortedIntervals = sortedList;
1427 }
1428
1429 void sortIntervalsAfterAllocation() {
1430 if (firstDerivedIntervalIndex == -1) {
1431 // no intervals have been added during allocation, so sorted list is already up to date
1432 return;
1433 }
1434
1435 Interval[] oldList = sortedIntervals;
1436 Interval[] newList = Arrays.copyOfRange(intervals, firstDerivedIntervalIndex, intervalsSize);
1437 int oldLen = oldList.length;
1438 int newLen = newList.length;
1439
1440 // conventional sort-algorithm for new intervals
1441 Arrays.sort(newList, INTERVAL_COMPARATOR);
1442
1443 // merge old and new list (both already sorted) into one combined list
1444 Interval[] combinedList = new Interval[oldLen + newLen];
1445 int oldIdx = 0;
1446 int newIdx = 0;
1447
1448 while (oldIdx + newIdx < combinedList.length) {
1449 if (newIdx >= newLen || (oldIdx < oldLen && oldList[oldIdx].from() <= newList[newIdx].from())) {
1450 combinedList[oldIdx + newIdx] = oldList[oldIdx];
1451 oldIdx++;
1452 } else {
1453 combinedList[oldIdx + newIdx] = newList[newIdx];
1454 newIdx++;
1455 }
1456 }
1457
1458 sortedIntervals = combinedList;
1459 }
1460
1461 private static final Comparator<Interval> INTERVAL_COMPARATOR = new Comparator<Interval>() {
1462
1463 public int compare(Interval a, Interval b) {
1464 if (a != null) {
1465 if (b != null) {
1466 return a.from() - b.from();
1467 } else {
1468 return -1;
1469 }
1470 } else {
1471 if (b != null) {
1472 return 1;
1473 } else {
1474 return 0;
1475 }
1476 }
1477 }
1478 };
1479
1480 public void allocateRegisters() {
1481 Interval precoloredIntervals;
1482 Interval notPrecoloredIntervals;
1483
1484 Interval.Pair result = createUnhandledLists(IS_PRECOLORED_INTERVAL, IS_VARIABLE_INTERVAL);
1485 precoloredIntervals = result.first;
1486 notPrecoloredIntervals = result.second;
1487
1488 // allocate cpu registers
1489 LinearScanWalker lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals);
1490 lsw.walk();
1491 lsw.finishAllocation();
1492 }
1493
1494 // * Phase 6: resolve data flow
1495 // (insert moves at edges between blocks if intervals have been split)
1496
1497 // wrapper for Interval.splitChildAtOpId that performs a bailout in product mode
1498 // instead of returning null
1499 Interval splitChildAtOpId(Interval interval, int opId, LIRInstruction.OperandMode mode) {
1500 Interval result = interval.getSplitChildAtOpId(opId, mode, this);
1501
1502 if (result != null) {
1503 if (C1XOptions.TraceLinearScanLevel >= 4) {
1504 TTY.println("Split child at pos " + opId + " of interval " + interval.toString() + " is " + result.toString());
1505 }
1506 return result;
1507 }
1508
1509 throw new CiBailout("LinearScan: interval is null");
1510 }
1511
1512 Interval intervalAtBlockBegin(LIRBlock block, CiValue operand) {
1513 assert operand.isVariable() : "register number out of bounds";
1514 assert intervalFor(operand) != null : "no interval found";
1515
1516 return splitChildAtOpId(intervalFor(operand), block.firstLirInstructionId(), LIRInstruction.OperandMode.Output);
1517 }
1518
1519 Interval intervalAtBlockEnd(LIRBlock block, CiValue operand) {
1520 assert operand.isVariable() : "register number out of bounds";
1521 assert intervalFor(operand) != null : "no interval found";
1522
1523 return splitChildAtOpId(intervalFor(operand), block.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
1524 }
1525
1526 Interval intervalAtOpId(CiValue operand, int opId) {
1527 assert operand.isVariable() : "register number out of bounds";
1528 assert intervalFor(operand) != null : "no interval found";
1529
1530 return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input);
1531 }
1532
1533 void resolveCollectMappings(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
1534 assert moveResolver.checkEmpty();
1535
1536 int numOperands = operands.size();
1537 CiBitMap liveAtEdge = toBlock.liveIn;
1538
1539 // visit all variables for which the liveAtEdge bit is set
1540 for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
1541 assert operandNum < numOperands : "live information set for not exisiting interval";
1542 assert fromBlock.liveOut.get(operandNum) && toBlock.liveIn.get(operandNum) : "interval not live at this edge";
1543
1544 CiValue liveOperand = operands.operandFor(operandNum);
1545 Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand);
1546 Interval toInterval = intervalAtBlockBegin(toBlock, liveOperand);
1547
1548 if (fromInterval != toInterval && (fromInterval.location() != toInterval.location())) {
1549 // need to insert move instruction
1550 moveResolver.addMapping(fromInterval, toInterval);
1551 }
1552 }
1553 }
1554
1555 void resolveFindInsertPos(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) {
1556 if (fromBlock.numberOfSux() <= 1) {
1557 if (C1XOptions.TraceLinearScanLevel >= 4) {
1558 TTY.println("inserting moves at end of fromBlock B%d", fromBlock.blockID());
1559 }
1560
1561 List<LIRInstruction> instructions = fromBlock.lir().instructionsList();
1562 LIRInstruction instr = instructions.get(instructions.size() - 1);
1563 if (instr instanceof LIRBranch) {
1564 LIRBranch branch = (LIRBranch) instr;
1565 // insert moves before branch
1566 assert branch.cond() == Condition.TRUE : "block does not end with an unconditional jump";
1567 moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 2);
1568 } else {
1569 moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 1);
1570 }
1571
1572 } else {
1573 if (C1XOptions.TraceLinearScanLevel >= 4) {
1574 TTY.println("inserting moves at beginning of toBlock B%d", toBlock.blockID());
1575 }
1576
1577 if (C1XOptions.DetailedAsserts) {
1578 assert fromBlock.lir().instructionsList().get(0) instanceof LIRLabel : "block does not start with a label";
1579
1580 // because the number of predecessor edges matches the number of
1581 // successor edges, blocks which are reached by switch statements
1582 // may have be more than one predecessor but it will be guaranteed
1583 // that all predecessors will be the same.
1584 for (int i = 0; i < toBlock.numberOfPreds(); i++) {
1585 assert fromBlock == toBlock.predAt(i) : "all critical edges must be broken";
1586 }
1587 }
1588
1589 moveResolver.setInsertPosition(toBlock.lir(), 0);
1590 }
1591 }
1592
1593 /**
1594 * Inserts necessary moves (spilling or reloading) at edges between blocks for intervals that
1595 * have been split.
1596 */
1597 void resolveDataFlow() {
1598 int numBlocks = blockCount();
1599 MoveResolver moveResolver = new MoveResolver(this);
1600 CiBitMap blockCompleted = new CiBitMap(numBlocks);
1601 CiBitMap alreadyResolved = new CiBitMap(numBlocks);
1602
1603 int i;
1604 for (i = 0; i < numBlocks; i++) {
1605 LIRBlock block = blockAt(i);
1606
1607 // check if block has only one predecessor and only one successor
1608 if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) {
1609 List<LIRInstruction> instructions = block.lir().instructionsList();
1610 assert instructions.get(0).code == LIROpcode.Label : "block must start with label";
1611 assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successors must end with branch (" + block + "), " + instructions.get(instructions.size() - 1);
1612 assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "block with successor must end with unconditional branch";
1613
1614 // check if block is empty (only label and branch)
1615 if (instructions.size() == 2) {
1616 LIRBlock pred = block.predAt(0);
1617 LIRBlock sux = block.suxAt(0);
1618
1619 // prevent optimization of two consecutive blocks
1620 if (!blockCompleted.get(pred.linearScanNumber()) && !blockCompleted.get(sux.linearScanNumber())) {
1621 if (C1XOptions.TraceLinearScanLevel >= 3) {
1622 TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.blockID(), pred.blockID(), sux.blockID());
1623 }
1624 blockCompleted.set(block.linearScanNumber());
1625
1626 // directly resolve between pred and sux (without looking at the empty block between)
1627 resolveCollectMappings(pred, sux, moveResolver);
1628 if (moveResolver.hasMappings()) {
1629 moveResolver.setInsertPosition(block.lir(), 0);
1630 moveResolver.resolveAndAppendMoves();
1631 }
1632 }
1633 }
1634 }
1635 }
1636
1637 for (i = 0; i < numBlocks; i++) {
1638 if (!blockCompleted.get(i)) {
1639 LIRBlock fromBlock = blockAt(i);
1640 alreadyResolved.setFrom(blockCompleted);
1641
1642 int numSux = fromBlock.numberOfSux();
1643 for (int s = 0; s < numSux; s++) {
1644 LIRBlock toBlock = fromBlock.suxAt(s);
1645
1646 // check for duplicate edges between the same blocks (can happen with switch blocks)
1647 if (!alreadyResolved.get(toBlock.linearScanNumber())) {
1648 if (C1XOptions.TraceLinearScanLevel >= 3) {
1649 TTY.println(" processing edge between B%d and B%d", fromBlock.blockID(), toBlock.blockID());
1650 }
1651 alreadyResolved.set(toBlock.linearScanNumber());
1652
1653 // collect all intervals that have been split between fromBlock and toBlock
1654 resolveCollectMappings(fromBlock, toBlock, moveResolver);
1655 if (moveResolver.hasMappings()) {
1656 resolveFindInsertPos(fromBlock, toBlock, moveResolver);
1657 moveResolver.resolveAndAppendMoves();
1658 }
1659 }
1660 }
1661 }
1662 }
1663 }
1664
1665 // * Phase 7: assign register numbers back to LIR
1666 // (includes computation of debug information and oop maps)
1667
1668 boolean verifyAssignedLocation(Interval interval, CiValue location) {
1669 CiKind kind = interval.kind();
1670
1671 assert location.isRegister() || location.isStackSlot();
1672
1673 if (location.isRegister()) {
1674 CiRegister reg = location.asRegister();
1675
1676 // register
1677 switch (kind) {
1678 case Byte:
1679 case Char:
1680 case Short:
1681 case Jsr:
1682 case Word:
1683 case Object:
1684 case Int: {
1685 assert reg.isCpu() : "not cpu register";
1686 break;
1687 }
1688
1689 case Long: {
1690 assert reg.isCpu() : "not cpu register";
1691 break;
1692 }
1693
1694 case Float: {
1695 assert !compilation.target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg;
1696 break;
1697 }
1698
1699 case Double: {
1700 assert !compilation.target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg;
1701 break;
1702 }
1703
1704 default: {
1705 throw Util.shouldNotReachHere();
1706 }
1707 }
1708 }
1709 return true;
1710 }
1711
1712 CiStackSlot canonicalSpillOpr(Interval interval) {
1713 assert interval.spillSlot() != null : "canonical spill slot not set";
1714 return interval.spillSlot();
1715 }
1716
1717 /**
1718 * Assigns the allocated location for an LIR instruction operand back into the instruction.
1719 *
1720 * @param operand an LIR instruction operand
1721 * @param opId the id of the LIR instruction using {@code operand}
1722 * @param mode the usage mode for {@code operand} by the instruction
1723 * @return the location assigned for the operand
1724 */
1725 private CiValue colorLirOperand(CiVariable operand, int opId, OperandMode mode) {
1726 Interval interval = intervalFor(operand);
1727 assert interval != null : "interval must exist";
1728
1729 if (opId != -1) {
1730 if (C1XOptions.DetailedAsserts) {
1731 LIRBlock block = blockForId(opId);
1732 if (block.numberOfSux() <= 1 && opId == block.lastLirInstructionId()) {
1733 // check if spill moves could have been appended at the end of this block, but
1734 // before the branch instruction. So the split child information for this branch would
1735 // be incorrect.
1736 LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
1737 if (instr instanceof LIRBranch) {
1738 LIRBranch branch = (LIRBranch) instr;
1739 if (block.liveOut.get(operandNumber(operand))) {
1740 assert branch.cond() == Condition.TRUE : "block does not end with an unconditional jump";
1741 throw new CiBailout("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)");
1742 }
1743 }
1744 }
1745 }
1746
1747 // operands are not changed when an interval is split during allocation,
1748 // so search the right interval here
1749 interval = splitChildAtOpId(interval, opId, mode);
1750 }
1751
1752 return interval.location();
1753 }
1754
1755 IntervalWalker initComputeOopMaps() {
1756 // setup lists of potential oops for walking
1757 Interval oopIntervals;
1758 Interval nonOopIntervals;
1759
1760 oopIntervals = createUnhandledLists(IS_OOP_INTERVAL, null).first;
1761
1762 // intervals that have no oops inside need not to be processed.
1763 // to ensure a walking until the last instruction id, add a dummy interval
1764 // with a high operation id
1765 nonOopIntervals = new Interval(CiValue.IllegalValue, -1);
1766 nonOopIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
1767
1768 return new IntervalWalker(this, oopIntervals, nonOopIntervals);
1769 }
1770
1771 void computeOopMap(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info, boolean isCallSite, CiBitMap frameRefMap, CiBitMap regRefMap) {
1772 if (C1XOptions.TraceLinearScanLevel >= 3) {
1773 TTY.println("creating oop map at opId %d", op.id);
1774 }
1775
1776 // walk before the current operation . intervals that start at
1777 // the operation (i.e. output operands of the operation) are not
1778 // included in the oop map
1779 iw.walkBefore(op.id);
1780
1781 // Iterate through active intervals
1782 for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
1783 CiValue operand = interval.operand;
1784
1785 assert interval.currentFrom() <= op.id && op.id <= interval.currentTo() : "interval should not be active otherwise";
1786 assert interval.operand.isVariable() : "fixed interval found";
1787
1788 // Check if this range covers the instruction. Intervals that
1789 // start or end at the current operation are not included in the
1790 // oop map, except in the case of patching moves. For patching
1791 // moves, any intervals which end at this instruction are included
1792 // in the oop map since we may safepoint while doing the patch
1793 // before we've consumed the inputs.
1794 if (op.id < interval.currentTo()) {
1795 // caller-save registers must not be included into oop-maps at calls
1796 assert !isCallSite || !operand.isRegister() || !isCallerSave(operand) : "interval is in a caller-save register at a call . register will be overwritten";
1797
1798 CiValue location = interval.location();
1799 if (location.isStackSlot()) {
1800 location = frameMap.toStackAddress((CiStackSlot) location);
1801 }
1802 info.setOop(location, compilation, frameRefMap, regRefMap);
1803
1804 // Spill optimization: when the stack value is guaranteed to be always correct,
1805 // then it must be added to the oop map even if the interval is currently in a register
1806 if (interval.alwaysInMemory() && op.id > interval.spillDefinitionPos() && !interval.location().equals(interval.spillSlot())) {
1807 assert interval.spillDefinitionPos() > 0 : "position not set correctly";
1808 assert interval.spillSlot() != null : "no spill slot assigned";
1809 assert !interval.operand.isRegister() : "interval is on stack : so stack slot is registered twice";
1810 info.setOop(frameMap.toStackAddress(interval.spillSlot()), compilation, frameRefMap, regRefMap);
1811 }
1812 }
1813 }
1814 }
1815
1816 private boolean isCallerSave(CiValue operand) {
1817 return attributes(operand.asRegister()).isCallerSave;
1818 }
1819
1820 void computeOopMap(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info, CiBitMap frameRefMap, CiBitMap regRefMap) {
1821 computeOopMap(iw, op, info, op.hasCall, frameRefMap, regRefMap);
1822 if (op instanceof LIRCall) {
1823 List<CiValue> pointerSlots = ((LIRCall) op).pointerSlots;
1824 if (pointerSlots != null) {
1825 for (CiValue v : pointerSlots) {
1826 info.setOop(v, compilation, frameRefMap, regRefMap);
1827 }
1828 }
1829 } else if (op instanceof LIRXirInstruction) {
1830 List<CiValue> pointerSlots = ((LIRXirInstruction) op).pointerSlots;
1831 if (pointerSlots != null) {
1832 for (CiValue v : pointerSlots) {
1833 info.setOop(v, compilation, frameRefMap, regRefMap);
1834 }
1835 }
1836 }
1837 }
1838
1839 CiValue toCiValue(int opId, Value value) {
1840 if (value != null && value.operand() != CiValue.IllegalValue) {
1841 CiValue operand = value.operand();
1842 Constant con = null;
1843 if (value instanceof Constant) {
1844 con = (Constant) value;
1845 }
1846
1847 assert con == null || operand.isVariable() || operand.isConstant() || operand.isIllegal() : "Constant instructions have only constant operands (or illegal if constant is optimized away)";
1848
1849 if (operand.isVariable()) {
1850 OperandMode mode = OperandMode.Input;
1851 LIRBlock block = blockForId(opId);
1852 if (block.numberOfSux() == 1 && opId == block.lastLirInstructionId()) {
1853 // generating debug information for the last instruction of a block.
1854 // if this instruction is a branch, spill moves are inserted before this branch
1855 // and so the wrong operand would be returned (spill moves at block boundaries are not
1856 // considered in the live ranges of intervals)
1857 // Solution: use the first opId of the branch target block instead.
1858 final LIRInstruction instr = block.lir().instructionsList().get(block.lir().instructionsList().size() - 1);
1859 if (instr instanceof LIRBranch) {
1860 if (block.liveOut.get(operandNumber(operand))) {
1861 opId = block.suxAt(0).firstLirInstructionId();
1862 mode = OperandMode.Output;
1863 }
1864 }
1865 }
1866
1867 // Get current location of operand
1868 // The operand must be live because debug information is considered when building the intervals
1869 // if the interval is not live, colorLirOperand will cause an assert on failure
1870 operand = colorLirOperand((CiVariable) operand, opId, mode);
1871 assert !hasCall(opId) || operand.isStackSlot() || !isCallerSave(operand) : "cannot have caller-save register operands at calls";
1872 return operand;
1873 } else if (operand.isRegister()) {
1874 assert false : "must not reach here";
1875 return operand;
1876 } else {
1877 assert value instanceof Constant;
1878 assert operand.isConstant() : "operand must be constant";
1879 return operand;
1880 }
1881 } else {
1882 // return a dummy value because real value not needed
1883 return CiValue.IllegalValue;
1884 }
1885 }
1886
1887 CiFrame computeFrameForState(FrameState state, int opId, CiBitMap frameRefMap) {
1888 CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()];
1889 int valueIndex = 0;
1890
1891 for (int i = 0; i < state.valuesSize(); i++) {
1892 values[valueIndex++] = toCiValue(opId, state.valueAt(i));
1893 }
1894
1895 for (int i = 0; i < state.locksSize(); i++) {
1896 if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
1897 CiStackSlot monitorAddress = frameMap.toMonitorBaseStackAddress(i);
1898 values[valueIndex++] = monitorAddress;
1899 assert frameRefMap != null;
1900 CiStackSlot objectAddress = frameMap.toMonitorObjectStackAddress(i);
1901 // LIRDebugInfo.setBit(frameRefMap, objectAddress.index());
1902 frameRefMap.set(objectAddress.index());
1903 } else {
1904 Value lock = state.lockAt(i);
1905 if (lock.isConstant() && compilation.runtime.asJavaClass(lock.asConstant()) != null) {
1906 // lock on class for synchronized static method
1907 values[valueIndex++] = lock.asConstant();
1908 } else {
1909 values[valueIndex++] = toCiValue(opId, lock);
1910 }
1911 }
1912 }
1913 CiFrame caller = null;
1914 if (state.outerFrameState() != null) {
1915 caller = computeFrameForState(state.outerFrameState(), opId, frameRefMap);
1916 }
1917 return new CiFrame(caller, state.method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize());
1918 }
1919
1920 private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
1921 assert iw != null : "interval walker needed for debug information";
1922 computeDebugInfo(iw, op, op.info);
1923
1924 if (op instanceof LIRXirInstruction) {
1925 LIRXirInstruction xir = (LIRXirInstruction) op;
1926 if (xir.infoAfter != null) {
1927 computeDebugInfo(iw, op, xir.infoAfter);
1928 }
1929 }
1930 }
1931
1932
1933 private void computeDebugInfo(IntervalWalker iw, LIRInstruction op, LIRDebugInfo info) {
1934 if (info != null) {
1935 if (info.debugInfo == null) {
1936 int frameSize = compilation.frameMap().frameSize();
1937 int frameWords = frameSize / compilation.target.spillSlotSize;
1938 CiBitMap frameRefMap = new CiBitMap(frameWords);
1939 CiBitMap regRefMap = !op.hasCall ? new CiBitMap(compilation.target.arch.registerReferenceMapBitCount) : null;
1940 CiFrame frame = compilation.placeholderState != null ? null : computeFrame(info.state, op.id, frameRefMap);
1941 computeOopMap(iw, op, info, frameRefMap, regRefMap);
1942 info.debugInfo = new CiDebugInfo(frame, regRefMap, frameRefMap);
1943 } else if (C1XOptions.DetailedAsserts) {
1944 assert info.debugInfo.frame().equals(computeFrame(info.state, op.id, new CiBitMap(info.debugInfo.frameRefMap.size())));
1945 }
1946 }
1947 }
1948
1949 CiFrame computeFrame(FrameState state, int opId, CiBitMap frameRefMap) {
1950 if (C1XOptions.TraceLinearScanLevel >= 3) {
1951 TTY.println("creating debug information at opId %d", opId);
1952 }
1953 return computeFrameForState(state, opId, frameRefMap);
1954 }
1955
1956 private void assignLocations(List<LIRInstruction> instructions, IntervalWalker iw) {
1957 int numInst = instructions.size();
1958 boolean hasDead = false;
1959
1960 for (int j = 0; j < numInst; j++) {
1961 LIRInstruction op = instructions.get(j);
1962 if (op == null) { // this can happen when spill-moves are removed in eliminateSpillMoves
1963 hasDead = true;
1964 continue;
1965 }
1966
1967 // iterate all modes of the visitor and process all virtual operands
1968 for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) {
1969 int n = op.operandCount(mode);
1970 for (int k = 0; k < n; k++) {
1971 CiValue operand = op.operandAt(mode, k);
1972 if (operand.isVariable()) {
1973 op.setOperandAt(mode, k, colorLirOperand((CiVariable) operand, op.id, mode));
1974 }
1975 }
1976 }
1977
1978 if (op.info != null) {
1979 // compute reference map and debug information
1980 computeDebugInfo(iw, op);
1981 }
1982
1983 // make sure we haven't made the op invalid.
1984 assert op.verify();
1985
1986 // remove useless moves
1987 if (op.code == LIROpcode.Move) {
1988 CiValue src = op.operand(0);
1989 CiValue dst = op.result();
1990 if (dst == src || src.equals(dst)) {
1991 // TODO: what about o.f = o.f and exceptions?
1992 instructions.set(j, null);
1993 hasDead = true;
1994 }
1995 }
1996 }
1997
1998 if (hasDead) {
1999 // iterate all instructions of the block and remove all null-values.
2000 int insertPoint = 0;
2001 for (int j = 0; j < numInst; j++) {
2002 LIRInstruction op = instructions.get(j);
2003 if (op != null) {
2004 if (insertPoint != j) {
2005 instructions.set(insertPoint, op);
2006 }
2007 insertPoint++;
2008 }
2009 }
2010 Util.truncate(instructions, insertPoint);
2011 }
2012 }
2013
2014 private void assignLocations() {
2015 IntervalWalker iw = initComputeOopMaps();
2016 for (LIRBlock block : sortedBlocks) {
2017 assignLocations(block.lir().instructionsList(), iw);
2018 }
2019 }
2020
2021 public void allocate() {
2022 if (C1XOptions.PrintTimers) {
2023 C1XTimers.LIFETIME_ANALYSIS.start();
2024 }
2025
2026 numberInstructions();
2027
2028 printLir("Before register allocation", true);
2029
2030 computeLocalLiveSets();
2031 computeGlobalLiveSets();
2032
2033 buildIntervals();
2034 sortIntervalsBeforeAllocation();
2035
2036 if (C1XOptions.PrintTimers) {
2037 C1XTimers.LIFETIME_ANALYSIS.stop();
2038 C1XTimers.LINEAR_SCAN.start();
2039 }
2040
2041 printIntervals("Before register allocation");
2042
2043 allocateRegisters();
2044
2045 if (C1XOptions.PrintTimers) {
2046 C1XTimers.LINEAR_SCAN.stop();
2047 C1XTimers.RESOLUTION.start();
2048 }
2049
2050 resolveDataFlow();
2051
2052 if (C1XOptions.PrintTimers) {
2053 C1XTimers.RESOLUTION.stop();
2054 C1XTimers.DEBUG_INFO.start();
2055 }
2056
2057 C1XMetrics.LSRASpills += (maxSpills - frameMap.initialSpillSlot());
2058
2059 // fill in number of spill slots into frameMap
2060 frameMap.finalizeFrame(maxSpills);
2061
2062 printIntervals("After register allocation");
2063 printLir("After register allocation", true);
2064
2065 sortIntervalsAfterAllocation();
2066
2067 if (C1XOptions.DetailedAsserts) {
2068 verify();
2069 }
2070
2071 eliminateSpillMoves();
2072 assignLocations();
2073
2074 if (C1XOptions.DetailedAsserts) {
2075 verifyIntervals();
2076 }
2077
2078 if (C1XOptions.PrintTimers) {
2079 C1XTimers.DEBUG_INFO.stop();
2080 C1XTimers.CODE_CREATE.start();
2081 }
2082
2083 printLir("After register number assignment", true);
2084 EdgeMoveOptimizer.optimize(ir.linearScanOrder());
2085 ControlFlowOptimizer.optimize(ir);
2086 printLir("After control flow optimization", false);
2087 }
2088
2089 void printIntervals(String label) {
2090 if (C1XOptions.TraceLinearScanLevel >= 1) {
2091 int i;
2092 TTY.println();
2093 TTY.println(label);
2094
2095 for (Interval interval : intervals) {
2096 if (interval != null) {
2097 TTY.out().println(interval.logString(this));
2098 }
2099 }
2100
2101 TTY.println();
2102 TTY.println("--- Basic Blocks ---");
2103 for (i = 0; i < blockCount(); i++) {
2104 LIRBlock block = blockAt(i);
2105 TTY.print("B%d [%d, %d, %d, %d] ", block.blockID(), block.firstLirInstructionId(), block.lastLirInstructionId(), block.loopIndex(), block.loopDepth());
2106 }
2107 TTY.println();
2108 TTY.println();
2109 }
2110
2111 if (compilation.compiler.isObserved()) {
2112 compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, this, intervals, intervalsSize));
2113 }
2114 }
2115
2116 void printLir(String label, boolean hirValid) {
2117 if (C1XOptions.TraceLinearScanLevel >= 1 && !TTY.isSuppressed()) {
2118 TTY.println();
2119 TTY.println(label);
2120 LIRList.printLIR(ir.linearScanOrder());
2121 TTY.println();
2122 }
2123
2124 if (compilation.compiler.isObserved()) {
2125 compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, label, compilation.graph, hirValid, true));
2126 }
2127 }
2128
2129 boolean verify() {
2130 // (check that all intervals have a correct register and that no registers are overwritten)
2131 if (C1XOptions.TraceLinearScanLevel >= 2) {
2132 TTY.println(" verifying intervals *");
2133 }
2134 verifyIntervals();
2135
2136 if (C1XOptions.TraceLinearScanLevel >= 2) {
2137 TTY.println(" verifying that no oops are in fixed intervals *");
2138 }
2139 //verifyNoOopsInFixedIntervals();
2140
2141 if (C1XOptions.TraceLinearScanLevel >= 2) {
2142 TTY.println(" verifying that unpinned constants are not alive across block boundaries");
2143 }
2144 verifyConstants();
2145
2146 if (C1XOptions.TraceLinearScanLevel >= 2) {
2147 TTY.println(" verifying register allocation *");
2148 }
2149 verifyRegisters();
2150
2151 if (C1XOptions.TraceLinearScanLevel >= 2) {
2152 TTY.println(" no errors found *");
2153 }
2154
2155 return true;
2156 }
2157
2158 private void verifyRegisters() {
2159 RegisterVerifier verifier = new RegisterVerifier(this);
2160 verifier.verify(blockAt(0));
2161 }
2162
2163 void verifyIntervals() {
2164 int len = intervalsSize;
2165
2166 for (int i = 0; i < len; i++) {
2167 Interval i1 = intervals[i];
2168 if (i1 == null) {
2169 continue;
2170 }
2171
2172 i1.checkSplitChildren();
2173
2174 if (i1.operandNumber != i) {
2175 TTY.println("Interval %d is on position %d in list", i1.operandNumber, i);
2176 TTY.println(i1.logString(this));
2177 throw new CiBailout("");
2178 }
2179
2180 if (i1.operand.isVariable() && i1.kind() == CiKind.Illegal) {
2181 TTY.println("Interval %d has no type assigned", i1.operandNumber);
2182 TTY.println(i1.logString(this));
2183 throw new CiBailout("");
2184 }
2185
2186 if (i1.location() == null) {
2187 TTY.println("Interval %d has no register assigned", i1.operandNumber);
2188 TTY.println(i1.logString(this));
2189 throw new CiBailout("");
2190 }
2191
2192 if (!isProcessed(i1.location())) {
2193 TTY.println("Can not have an Interval for an ignored register " + i1.location());
2194 TTY.println(i1.logString(this));
2195 throw new CiBailout("");
2196 }
2197
2198 if (i1.first() == Range.EndMarker) {
2199 TTY.println("Interval %d has no Range", i1.operandNumber);
2200 TTY.println(i1.logString(this));
2201 throw new CiBailout("");
2202 }
2203
2204 for (Range r = i1.first(); r != Range.EndMarker; r = r.next) {
2205 if (r.from >= r.to) {
2206 TTY.println("Interval %d has zero length range", i1.operandNumber);
2207 TTY.println(i1.logString(this));
2208 throw new CiBailout("");
2209 }
2210 }
2211
2212 for (int j = i + 1; j < len; j++) {
2213 Interval i2 = intervals[j];
2214 if (i2 == null) {
2215 continue;
2216 }
2217
2218 // special intervals that are created in MoveResolver
2219 // . ignore them because the range information has no meaning there
2220 if (i1.from() == 1 && i1.to() == 2) {
2221 continue;
2222 }
2223 if (i2.from() == 1 && i2.to() == 2) {
2224 continue;
2225 }
2226 CiValue l1 = i1.location();
2227 CiValue l2 = i2.location();
2228 if (i1.intersects(i2) && (l1.equals(l2))) {
2229 if (C1XOptions.DetailedAsserts) {
2230 TTY.println("Intervals %d and %d overlap and have the same register assigned", i1.operandNumber, i2.operandNumber);
2231 TTY.println(i1.logString(this));
2232 TTY.println(i2.logString(this));
2233 }
2234 throw new CiBailout("");
2235 }
2236 }
2237 }
2238 }
2239
2240 void verifyNoOopsInFixedIntervals() {
2241 Interval fixedIntervals;
2242 Interval otherIntervals;
2243 fixedIntervals = createUnhandledLists(IS_PRECOLORED_INTERVAL, null).first;
2244 // to ensure a walking until the last instruction id, add a dummy interval
2245 // with a high operation id
2246 otherIntervals = new Interval(CiValue.IllegalValue, -1);
2247 otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1);
2248 IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals);
2249
2250 for (int i = 0; i < blockCount(); i++) {
2251 LIRBlock block = blockAt(i);
2252
2253 List<LIRInstruction> instructions = block.lir().instructionsList();
2254
2255 for (int j = 0; j < instructions.size(); j++) {
2256 LIRInstruction op = instructions.get(j);
2257
2258 if (op.info != null) {
2259 iw.walkBefore(op.id);
2260 boolean checkLive = true;
2261
2262 // Make sure none of the fixed registers is live across an
2263 // oopmap since we can't handle that correctly.
2264 if (checkLive) {
2265 for (Interval interval = iw.activeLists.get(RegisterBinding.Fixed); interval != Interval.EndMarker; interval = interval.next) {
2266 if (interval.currentTo() > op.id + 1) {
2267 // This interval is live out of this op so make sure
2268 // that this interval represents some value that's
2269 // referenced by this op either as an input or output.
2270 boolean ok = false;
2271 for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) {
2272 int n = op.operandCount(mode);
2273 for (int k = 0; k < n; k++) {
2274 CiValue operand = op.operandAt(mode, k);
2275 if (operand.isRegister()) {
2276 if (intervalFor(operand) == interval) {
2277 ok = true;
2278 break;
2279 }
2280 }
2281 }
2282 }
2283 assert ok : "fixed intervals should never be live across an oopmap point";
2284 }
2285 }
2286 }
2287 }
2288 }
2289 }
2290 }
2291
2292 void verifyConstants() {
2293 int numBlocks = blockCount();
2294
2295 for (int i = 0; i < numBlocks; i++) {
2296 LIRBlock block = blockAt(i);
2297 CiBitMap liveAtEdge = block.liveIn;
2298
2299 // visit all operands where the liveAtEdge bit is set
2300 for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
2301 if (C1XOptions.TraceLinearScanLevel >= 4) {
2302 TTY.println("checking interval %d of block B%d", operandNum, block.blockID());
2303 }
2304 CiValue operand = operands.operandFor(operandNum);
2305 assert operand.isVariable() : "value must have variable operand";
2306 Value value = gen.operands.instructionForResult(((CiVariable) operand));
2307 assert value != null : "all intervals live across block boundaries must have Value";
2308 // TKR assert value.asConstant() == null || value.isPinned() :
2309 // "only pinned constants can be alive accross block boundaries";
2310 }
2311 }
2312 }
2313
2314 public int numberOfSpillSlots(CiKind kind) {
2315 return compilation.target.spillSlots(kind);
2316 }
2317 }