@@ -9613,6 +9613,29 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
9613
9613
}
9614
9614
}
9615
9615
9616
+ #ifdef TARGET_ARM
9617
+ auto addOtherHalfRegToReady = [&](regNumber otherHalfReg) {
9618
+ // For a double interval, if the first half if freed up, check if the other
9619
+ // half can also be freed (if it is a target for resolution).
9620
+
9621
+ regNumber otherHalfSrcReg = (regNumber)source[otherHalfReg];
9622
+ regNumber otherHalfSrcLoc = (regNumber)location[otherHalfReg];
9623
+
9624
+ // Necessary conditions:
9625
+ // - There is a source register for this reg (otherHalfSrcReg != REG_NA)
9626
+ // - It is currently free (otherHalfSrcLoc == REG_NA)
9627
+ // - The source interval isn't yet completed (sourceIntervals[otherHalfSrcReg] != nullptr)
9628
+ // - It's in the TODO set (targetRegsToDo.IsRegNumInMask(otherHalfReg))
9629
+ // - It's not resolved from stack (!targetRegsFromStack.IsRegNumInMask(otherHalfReg))
9630
+ if ((otherHalfSrcReg != REG_NA) && (otherHalfSrcLoc == REG_NA) &&
9631
+ (sourceIntervals[otherHalfSrcReg] != nullptr) && targetRegsToDo.IsRegNumInMask(otherHalfReg) &&
9632
+ !targetRegsFromStack.IsRegNumInMask(otherHalfReg))
9633
+ {
9634
+ targetRegsReady.AddRegNumInMask(otherHalfReg);
9635
+ }
9636
+ };
9637
+ #endif // TARGET_ARM
9638
+
9616
9639
// Perform reg to reg moves
9617
9640
while (targetRegsToDo.IsNonEmpty())
9618
9641
{
@@ -9654,48 +9677,18 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
9654
9677
}
9655
9678
9656
9679
// Since we want to check if we can free upperHalfReg, only do it
9657
- // if lowerHalfReg is ready.
9680
+ // if lowerHalfReg is ready and it is one of the target candidate .
9658
9681
if (targetRegsReady.IsRegNumInMask(fromReg))
9659
9682
{
9660
- regNumber upperHalfSrcReg = (regNumber)source[upperHalfReg];
9661
- regNumber upperHalfSrcLoc = (regNumber)location[upperHalfReg];
9662
- // Necessary conditions:
9663
- // - There is a source register for this reg (upperHalfSrcReg != REG_NA)
9664
- // - It is currently free (upperHalfSrcLoc == REG_NA)
9665
- // - The source interval isn't yet completed (sourceIntervals[upperHalfSrcReg] != nullptr)
9666
- // - It's not resolved from stack (!targetRegsFromStack.IsRegNumInMask(upperHalfReg))
9667
- if ((upperHalfSrcReg != REG_NA) && (upperHalfSrcLoc == REG_NA) &&
9668
- (sourceIntervals[upperHalfSrcReg] != nullptr) &&
9669
- !targetRegsFromStack.IsRegNumInMask(upperHalfReg))
9670
- {
9671
- targetRegsReady.AddRegNumInMask(upperHalfReg);
9672
- }
9683
+ addOtherHalfRegToReady(upperHalfReg);
9673
9684
}
9674
9685
}
9675
9686
}
9676
9687
else if (genIsValidFloatReg(fromReg) && !genIsValidDoubleReg(fromReg))
9677
9688
{
9678
9689
// We may have freed up the other half of a double where the lower half
9679
9690
// was already free.
9680
- regNumber lowerHalfReg = REG_PREV(fromReg);
9681
- regNumber lowerHalfSrcReg = (regNumber)source[lowerHalfReg];
9682
- regNumber lowerHalfSrcLoc = (regNumber)location[lowerHalfReg];
9683
- // Necessary conditions:
9684
- // - There is a source register for this reg (lowerHalfSrcReg != REG_NA)
9685
- // - It is currently free (lowerHalfSrcLoc == REG_NA)
9686
- // - The source interval isn't yet completed (sourceIntervals[lowerHalfSrcReg] != nullptr)
9687
- // - It's not in the ready set (!targetRegsReady.IsRegNumInMask(lowerHalfReg))
9688
- // - It's not resolved from stack (!targetRegsFromStack.IsRegNumInMask(lowerHalfReg))
9689
- if ((lowerHalfSrcReg != REG_NA) && (lowerHalfSrcLoc == REG_NA) &&
9690
- (sourceIntervals[lowerHalfSrcReg] != nullptr) &&
9691
- !targetRegsReady.IsRegNumInMask(lowerHalfReg) &&
9692
- !targetRegsFromStack.IsRegNumInMask(lowerHalfReg))
9693
- {
9694
- // This must be a double interval, otherwise it would be in targetRegsReady, or already
9695
- // completed.
9696
- assert(sourceIntervals[lowerHalfSrcReg]->registerType == TYP_DOUBLE);
9697
- targetRegsReady.AddRegNumInMask(lowerHalfReg);
9698
- }
9691
+ addOtherHalfRegToReady(REG_PREV(fromReg));
9699
9692
#endif // TARGET_ARM
9700
9693
}
9701
9694
}
@@ -9870,6 +9863,14 @@ void LinearScan::resolveEdge(BasicBlock* fromBlock,
9870
9863
targetReg DEBUG_ARG(fromBlock) DEBUG_ARG(toBlock)
9871
9864
DEBUG_ARG(resolveTypeName[resolveType]));
9872
9865
location[targetReg] = (regNumberSmall)tempReg;
9866
+
9867
+ if (sourceIntervals[targetReg]->registerType == TYP_DOUBLE)
9868
+ {
9869
+ // Free up upperHalf reg of this targetReg, if it is one of the target candidate.
9870
+
9871
+ assert(genIsValidDoubleReg(targetReg));
9872
+ addOtherHalfRegToReady(REG_NEXT(targetReg));
9873
+ }
9873
9874
}
9874
9875
#else
9875
9876
assert(sourceIntervals[targetReg] != nullptr);
0 commit comments