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