Mercurial > hg > truffle
comparison graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java @ 20994:68ff637e95b1
Merge
author | Stefan Anzinger <stefan.anzinger@oracle.com> |
---|---|
date | Thu, 16 Apr 2015 17:09:06 +0200 |
parents | ec36daea3cf0 abc059cb0acf |
children | 9f45587ad8f5 |
comparison
equal
deleted
inserted
replaced
20993:ec36daea3cf0 | 20994:68ff637e95b1 |
---|---|
295 | 295 |
296 int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { | 296 int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { |
297 int optimalSplitPos = -1; | 297 int optimalSplitPos = -1; |
298 if (minSplitPos == maxSplitPos) { | 298 if (minSplitPos == maxSplitPos) { |
299 // trivial case, no optimization of split position possible | 299 // trivial case, no optimization of split position possible |
300 Debug.log("min-pos and max-pos are equal, no optimization possible"); | 300 if (Debug.isLogEnabled()) { |
301 Debug.log("min-pos and max-pos are equal, no optimization possible"); | |
302 } | |
301 optimalSplitPos = minSplitPos; | 303 optimalSplitPos = minSplitPos; |
302 | 304 |
303 } else { | 305 } else { |
304 assert minSplitPos < maxSplitPos : "must be true then"; | 306 assert minSplitPos < maxSplitPos : "must be true then"; |
305 assert minSplitPos > 0 : "cannot access minSplitPos - 1 otherwise"; | 307 assert minSplitPos > 0 : "cannot access minSplitPos - 1 otherwise"; |
317 AbstractBlockBase<?> maxBlock = allocator.blockForId(maxSplitPos - 1); | 319 AbstractBlockBase<?> maxBlock = allocator.blockForId(maxSplitPos - 1); |
318 | 320 |
319 assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; | 321 assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; |
320 if (minBlock == maxBlock) { | 322 if (minBlock == maxBlock) { |
321 // split position cannot be moved to block boundary : so split as late as possible | 323 // split position cannot be moved to block boundary : so split as late as possible |
322 Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); | 324 if (Debug.isLogEnabled()) { |
325 Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); | |
326 } | |
323 optimalSplitPos = maxSplitPos; | 327 optimalSplitPos = maxSplitPos; |
324 | 328 |
325 } else { | 329 } else { |
326 if (interval.hasHoleBetween(maxSplitPos - 1, maxSplitPos) && !allocator.isBlockBegin(maxSplitPos)) { | 330 if (interval.hasHoleBetween(maxSplitPos - 1, maxSplitPos) && !allocator.isBlockBegin(maxSplitPos)) { |
327 // Do not move split position if the interval has a hole before maxSplitPos. | 331 // Do not move split position if the interval has a hole before maxSplitPos. |
328 // Intervals resulting from Phi-Functions have more than one definition (marked | 332 // Intervals resulting from Phi-Functions have more than one definition (marked |
329 // as mustHaveRegister) with a hole before each definition. When the register is | 333 // as mustHaveRegister) with a hole before each definition. When the register is |
330 // needed | 334 // needed |
331 // for the second definition : an earlier reloading is unnecessary. | 335 // for the second definition : an earlier reloading is unnecessary. |
332 Debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); | 336 if (Debug.isLogEnabled()) { |
337 Debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); | |
338 } | |
333 optimalSplitPos = maxSplitPos; | 339 optimalSplitPos = maxSplitPos; |
334 | 340 |
335 } else { | 341 } else { |
336 // seach optimal block boundary between minSplitPos and maxSplitPos | 342 // seach optimal block boundary between minSplitPos and maxSplitPos |
337 Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); | 343 if (Debug.isLogEnabled()) { |
344 Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); | |
345 } | |
338 | 346 |
339 if (doLoopOptimization) { | 347 if (doLoopOptimization) { |
340 // Loop optimization: if a loop-end marker is found between min- and | 348 // Loop optimization: if a loop-end marker is found between min- and |
341 // max-position : | 349 // max-position : |
342 // then split before this loop | 350 // then split before this loop |
343 int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2); | 351 int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2); |
344 Debug.log("loop optimization: loop end found at pos %d", loopEndPos); | 352 if (Debug.isLogEnabled()) { |
353 Debug.log("loop optimization: loop end found at pos %d", loopEndPos); | |
354 } | |
345 | 355 |
346 assert loopEndPos > minSplitPos : "invalid order"; | 356 assert loopEndPos > minSplitPos : "invalid order"; |
347 if (loopEndPos < maxSplitPos) { | 357 if (loopEndPos < maxSplitPos) { |
348 // loop-end marker found between min- and max-position | 358 // loop-end marker found between min- and max-position |
349 // if it is not the end marker for the same loop as the min-position : | 359 // if it is not the end marker for the same loop as the min-position : |
352 // Desired result: uses tagged as shouldHaveRegister inside a loop cause | 362 // Desired result: uses tagged as shouldHaveRegister inside a loop cause |
353 // a reloading | 363 // a reloading |
354 // of the interval (normally, only mustHaveRegister causes a reloading) | 364 // of the interval (normally, only mustHaveRegister causes a reloading) |
355 AbstractBlockBase<?> loopBlock = allocator.blockForId(loopEndPos); | 365 AbstractBlockBase<?> loopBlock = allocator.blockForId(loopEndPos); |
356 | 366 |
357 Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); | 367 if (Debug.isLogEnabled()) { |
368 Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); | |
369 } | |
358 assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; | 370 assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; |
359 | 371 |
360 optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, allocator.getLastLirInstructionId(loopBlock) + 2); | 372 int maxSpillPos = allocator.getLastLirInstructionId(loopBlock) + 2; |
361 if (optimalSplitPos == allocator.getLastLirInstructionId(loopBlock) + 2) { | 373 optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, maxSpillPos); |
374 if (optimalSplitPos == maxSpillPos) { | |
362 optimalSplitPos = -1; | 375 optimalSplitPos = -1; |
363 Debug.log("loop optimization not necessary"); | 376 if (Debug.isLogEnabled()) { |
377 Debug.log("loop optimization not necessary"); | |
378 } | |
364 } else { | 379 } else { |
365 Debug.log("loop optimization successful"); | 380 if (Debug.isLogEnabled()) { |
381 Debug.log("loop optimization successful"); | |
382 } | |
366 } | 383 } |
367 } | 384 } |
368 } | 385 } |
369 | 386 |
370 if (optimalSplitPos == -1) { | 387 if (optimalSplitPos == -1) { |
372 optimalSplitPos = findOptimalSplitPos(minBlock, maxBlock, maxSplitPos); | 389 optimalSplitPos = findOptimalSplitPos(minBlock, maxBlock, maxSplitPos); |
373 } | 390 } |
374 } | 391 } |
375 } | 392 } |
376 } | 393 } |
377 Debug.log("optimal split position: %d", optimalSplitPos); | 394 if (Debug.isLogEnabled()) { |
395 Debug.log("optimal split position: %d", optimalSplitPos); | |
396 } | |
378 | 397 |
379 return optimalSplitPos; | 398 return optimalSplitPos; |
380 } | 399 } |
381 | 400 |
382 // split an interval at the optimal position between minSplitPos and | 401 // split an interval at the optimal position between minSplitPos and |
399 assert optimalSplitPos > interval.from() : "cannot split at start of interval"; | 418 assert optimalSplitPos > interval.from() : "cannot split at start of interval"; |
400 | 419 |
401 if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { | 420 if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { |
402 // the split position would be just before the end of the interval | 421 // the split position would be just before the end of the interval |
403 // . no split at all necessary | 422 // . no split at all necessary |
404 Debug.log("no split necessary because optimal split position is at end of interval"); | 423 if (Debug.isLogEnabled()) { |
424 Debug.log("no split necessary because optimal split position is at end of interval"); | |
425 } | |
405 return; | 426 return; |
406 } | 427 } |
407 | 428 |
408 // must calculate this before the actual split is performed and before split position is | 429 // must calculate this before the actual split is performed and before split position is |
409 // moved to odd opId | 430 // moved to odd opId |
412 if (!allocator.isBlockBegin(optimalSplitPos)) { | 433 if (!allocator.isBlockBegin(optimalSplitPos)) { |
413 // move position before actual instruction (odd opId) | 434 // move position before actual instruction (odd opId) |
414 optimalSplitPos = (optimalSplitPos - 1) | 1; | 435 optimalSplitPos = (optimalSplitPos - 1) | 1; |
415 } | 436 } |
416 | 437 |
417 Debug.log("splitting at position %d", optimalSplitPos); | 438 if (Debug.isLogEnabled()) { |
439 Debug.log("splitting at position %d", optimalSplitPos); | |
440 } | |
418 | 441 |
419 assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; | 442 assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; |
420 assert !allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 0) : "split pos must be even on block boundary"; | 443 assert !allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 0) : "split pos must be even on block boundary"; |
421 | 444 |
422 Interval splitPart = interval.split(optimalSplitPos, allocator); | 445 Interval splitPart = interval.split(optimalSplitPos, allocator); |
470 parent = parent.getSplitChildBeforeOpId(parent.from()); | 493 parent = parent.getSplitChildBeforeOpId(parent.from()); |
471 | 494 |
472 if (isRegister(parent.location())) { | 495 if (isRegister(parent.location())) { |
473 if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) { | 496 if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) { |
474 // parent is never used, so kick it out of its assigned register | 497 // parent is never used, so kick it out of its assigned register |
475 Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); | 498 if (Debug.isLogEnabled()) { |
499 Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); | |
500 } | |
476 allocator.assignSpillSlot(parent); | 501 allocator.assignSpillSlot(parent); |
477 handleSpillSlot(parent); | 502 handleSpillSlot(parent); |
478 } else { | 503 } else { |
479 // do not go further back because the register is actually used by | 504 // do not go further back because the register is actually used by |
480 // the interval | 505 // the interval |
505 allocator.assignSpillSlot(spilledPart); | 530 allocator.assignSpillSlot(spilledPart); |
506 handleSpillSlot(spilledPart); | 531 handleSpillSlot(spilledPart); |
507 allocator.changeSpillState(spilledPart, optimalSplitPos); | 532 allocator.changeSpillState(spilledPart, optimalSplitPos); |
508 | 533 |
509 if (!allocator.isBlockBegin(optimalSplitPos)) { | 534 if (!allocator.isBlockBegin(optimalSplitPos)) { |
510 Debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); | 535 if (Debug.isLogEnabled()) { |
536 Debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); | |
537 } | |
511 insertMove(optimalSplitPos, interval, spilledPart); | 538 insertMove(optimalSplitPos, interval, spilledPart); |
512 } | 539 } |
513 | 540 |
514 // the currentSplitChild is needed later when moves are inserted for reloading | 541 // the currentSplitChild is needed later when moves are inserted for reloading |
515 assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild"; | 542 assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild"; |
597 | 624 |
598 Register hint = null; | 625 Register hint = null; |
599 Interval locationHint = interval.locationHint(true); | 626 Interval locationHint = interval.locationHint(true); |
600 if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) { | 627 if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) { |
601 hint = asRegister(locationHint.location()); | 628 hint = asRegister(locationHint.location()); |
602 Debug.log("hint register %d from interval %s", hint.number, locationHint); | 629 if (Debug.isLogEnabled()) { |
630 Debug.log("hint register %d from interval %s", hint.number, locationHint); | |
631 } | |
603 } | 632 } |
604 assert interval.location() == null : "register already assigned to interval"; | 633 assert interval.location() == null : "register already assigned to interval"; |
605 | 634 |
606 // the register must be free at least until this position | 635 // the register must be free at least until this position |
607 int regNeededUntil = interval.from() + 1; | 636 int regNeededUntil = interval.from() + 1; |
639 return false; | 668 return false; |
640 } | 669 } |
641 | 670 |
642 splitPos = usePos[reg.number]; | 671 splitPos = usePos[reg.number]; |
643 interval.assignLocation(reg.asValue(interval.kind())); | 672 interval.assignLocation(reg.asValue(interval.kind())); |
644 Debug.log("selected register %d", reg.number); | 673 if (Debug.isLogEnabled()) { |
674 Debug.log("selected register %d", reg.number); | |
675 } | |
645 | 676 |
646 assert splitPos > 0 : "invalid splitPos"; | 677 assert splitPos > 0 : "invalid splitPos"; |
647 if (needSplit) { | 678 if (needSplit) { |
648 // register not available for full interval, so split it | 679 // register not available for full interval, so split it |
649 splitWhenPartialRegisterAvailable(interval, splitPos); | 680 splitWhenPartialRegisterAvailable(interval, splitPos); |
708 } | 739 } |
709 } | 740 } |
710 | 741 |
711 int regUsePos = (reg == null ? 0 : usePos[reg.number]); | 742 int regUsePos = (reg == null ? 0 : usePos[reg.number]); |
712 if (regUsePos <= firstUsage) { | 743 if (regUsePos <= firstUsage) { |
713 Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); | 744 if (Debug.isLogEnabled()) { |
745 Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); | |
746 } | |
714 | 747 |
715 if (firstUsage <= interval.from() + 1) { | 748 if (firstUsage <= interval.from() + 1) { |
716 String description = "cannot spill interval that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + ", interval.from()=" + | 749 String description = "cannot spill interval that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + ", interval.from()=" + |
717 interval.from() + "; already used candidates: " + Arrays.toString(availableRegs); | 750 interval.from() + "; already used candidates: " + Arrays.toString(availableRegs); |
718 // assign a reasonable register and do a bailout in product mode to avoid errors | 751 // assign a reasonable register and do a bailout in product mode to avoid errors |
727 | 760 |
728 boolean needSplit = blockPos[reg.number] <= intervalTo; | 761 boolean needSplit = blockPos[reg.number] <= intervalTo; |
729 | 762 |
730 int splitPos = blockPos[reg.number]; | 763 int splitPos = blockPos[reg.number]; |
731 | 764 |
732 Debug.log("decided to use register %d", reg.number); | 765 if (Debug.isLogEnabled()) { |
766 Debug.log("decided to use register %d", reg.number); | |
767 } | |
733 assert splitPos > 0 : "invalid splitPos"; | 768 assert splitPos > 0 : "invalid splitPos"; |
734 assert needSplit || splitPos > interval.from() : "splitting interval at from"; | 769 assert needSplit || splitPos > interval.from() : "splitting interval at from"; |
735 | 770 |
736 interval.assignLocation(reg.asValue(interval.kind())); | 771 interval.assignLocation(reg.asValue(interval.kind())); |
737 if (needSplit) { | 772 if (needSplit) { |
754 // (an interval got a register until this position) | 789 // (an interval got a register until this position) |
755 int pos = interval.from(); | 790 int pos = interval.from(); |
756 if (isOdd(pos)) { | 791 if (isOdd(pos)) { |
757 // the current instruction is a call that blocks all registers | 792 // the current instruction is a call that blocks all registers |
758 if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) { | 793 if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) { |
759 Debug.log("free register cannot be available because all registers blocked by following call"); | 794 if (Debug.isLogEnabled()) { |
795 Debug.log("free register cannot be available because all registers blocked by following call"); | |
796 } | |
760 | 797 |
761 // safety check that there is really no register available | 798 // safety check that there is really no register available |
762 assert !allocFreeRegister(interval) : "found a register for this interval"; | 799 assert !allocFreeRegister(interval) : "found a register for this interval"; |
763 return true; | 800 return true; |
764 } | 801 } |
850 final Value operand = interval.operand; | 887 final Value operand = interval.operand; |
851 if (interval.location() != null && isStackSlotValue(interval.location())) { | 888 if (interval.location() != null && isStackSlotValue(interval.location())) { |
852 // activating an interval that has a stack slot assigned . split it at first use | 889 // activating an interval that has a stack slot assigned . split it at first use |
853 // position | 890 // position |
854 // used for method parameters | 891 // used for method parameters |
855 Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); | 892 if (Debug.isLogEnabled()) { |
893 Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); | |
894 } | |
856 splitStackInterval(interval); | 895 splitStackInterval(interval); |
857 result = false; | 896 result = false; |
858 | 897 |
859 } else { | 898 } else { |
860 if (interval.location() == null) { | 899 if (interval.location() == null) { |
861 // interval has not assigned register . normal allocation | 900 // interval has not assigned register . normal allocation |
862 // (this is the normal case for most intervals) | 901 // (this is the normal case for most intervals) |
863 Debug.log("normal allocation of register"); | 902 if (Debug.isLogEnabled()) { |
903 Debug.log("normal allocation of register"); | |
904 } | |
864 | 905 |
865 // assign same spill slot to non-intersecting intervals | 906 // assign same spill slot to non-intersecting intervals |
866 combineSpilledIntervals(interval); | 907 combineSpilledIntervals(interval); |
867 | 908 |
868 initVarsForAlloc(interval); | 909 initVarsForAlloc(interval); |
882 // load spilled values that become active from stack slot to register | 923 // load spilled values that become active from stack slot to register |
883 if (interval.insertMoveWhenActivated()) { | 924 if (interval.insertMoveWhenActivated()) { |
884 assert interval.isSplitChild(); | 925 assert interval.isSplitChild(); |
885 assert interval.currentSplitChild() != null; | 926 assert interval.currentSplitChild() != null; |
886 assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval"; | 927 assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval"; |
887 Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); | 928 if (Debug.isLogEnabled()) { |
929 Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); | |
930 } | |
888 | 931 |
889 insertMove(interval.from(), interval.currentSplitChild(), interval); | 932 insertMove(interval.from(), interval.currentSplitChild(), interval); |
890 } | 933 } |
891 interval.makeCurrentSplitChild(); | 934 interval.makeCurrentSplitChild(); |
892 | 935 |