summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarol Eidt <carol.eidt@microsoft.com>2017-11-04 17:40:42 -0700
committerGitHub <noreply@github.com>2017-11-04 17:40:42 -0700
commitae8891aac45bf296bc22a8c9ea051c77d3cada80 (patch)
treedb1333bf1c2f546c74cd71ee627943154678125a
parent5a01d8a39576f0d07441e4d123a90138f4ae0735 (diff)
parent7ca15826297bd798ad68c29ae332600336959f47 (diff)
downloadcoreclr-ae8891aac45bf296bc22a8c9ea051c77d3cada80.tar.gz
coreclr-ae8891aac45bf296bc22a8c9ea051c77d3cada80.tar.bz2
coreclr-ae8891aac45bf296bc22a8c9ea051c77d3cada80.zip
Merge pull request #14851 from CarolEidt/Fix14372
Unassign both floats if assigning double
-rw-r--r--src/jit/lsra.cpp56
-rw-r--r--src/jit/lsra.h1
2 files changed, 51 insertions, 6 deletions
diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp
index 658026417d..6b9cde5acc 100644
--- a/src/jit/lsra.cpp
+++ b/src/jit/lsra.cpp
@@ -6590,7 +6590,8 @@ bool LinearScan::isAssigned(RegRecord* regRec, LsraLocation lastLocation ARM_ARG
//
void LinearScan::checkAndAssignInterval(RegRecord* regRec, Interval* interval)
{
- if (regRec->assignedInterval != nullptr && regRec->assignedInterval != interval)
+ Interval* assignedInterval = regRec->assignedInterval;
+ if (assignedInterval != nullptr && assignedInterval != interval)
{
// This is allocated to another interval. Either it is inactive, or it was allocated as a
// copyReg and is therefore not the "assignedReg" of the other interval. In the latter case,
@@ -6600,13 +6601,32 @@ void LinearScan::checkAndAssignInterval(RegRecord* regRec, Interval* interval)
// in method SerialStream.GetDcbFlag.
// Note that we can't check for the copyReg case, because we may have seen a more recent
// RefPosition for the Interval that was NOT a copyReg.
- if (regRec->assignedInterval->assignedReg == regRec)
+ if (assignedInterval->assignedReg == regRec)
{
- assert(regRec->assignedInterval->isActive == false);
- regRec->assignedInterval->physReg = REG_NA;
+ assert(assignedInterval->isActive == false);
+ assignedInterval->physReg = REG_NA;
}
unassignPhysReg(regRec->regNum);
}
+#ifdef _TARGET_ARM_
+ // If 'interval' and 'assignedInterval' were both TYP_DOUBLE, then we have unassigned 'assignedInterval'
+ // from both halves. Otherwise, if 'interval' is TYP_DOUBLE, we now need to unassign the other half.
+ if ((interval->registerType == TYP_DOUBLE) &&
+ ((assignedInterval == nullptr) || (assignedInterval->registerType == TYP_FLOAT)))
+ {
+ RegRecord* otherRegRecord = getSecondHalfRegRec(regRec);
+ assignedInterval = otherRegRecord->assignedInterval;
+ if (assignedInterval != nullptr && assignedInterval != interval)
+ {
+ if (assignedInterval->assignedReg == otherRegRecord)
+ {
+ assert(assignedInterval->isActive == false);
+ assignedInterval->physReg = REG_NA;
+ }
+ unassignPhysReg(otherRegRecord->regNum);
+ }
+ }
+#endif
updateAssignedInterval(regRec, interval, interval->registerType);
}
@@ -7210,6 +7230,30 @@ bool LinearScan::isSecondHalfReg(RegRecord* regRec, Interval* interval)
}
//------------------------------------------------------------------------------------------
+// getSecondHalfRegRec: Get the second (odd) half of an ARM32 double register
+//
+// Arguments:
+// regRec - A float RegRecord
+//
+// Assumptions:
+// regRec must be a valid double register (i.e. even)
+//
+// Return Value:
+// The RegRecord for the second half of the double register
+//
+RegRecord* LinearScan::getSecondHalfRegRec(RegRecord* regRec)
+{
+ regNumber secondHalfRegNum;
+ RegRecord* secondHalfRegRec;
+
+ assert(genIsValidDoubleReg(regRec->regNum));
+
+ secondHalfRegNum = REG_NEXT(regRec->regNum);
+ secondHalfRegRec = getRegisterRecord(secondHalfRegNum);
+
+ return secondHalfRegRec;
+}
+//------------------------------------------------------------------------------------------
// findAnotherHalfRegRec: Find another half RegRecord which forms same ARM32 double register
//
// Arguments:
@@ -7650,7 +7694,7 @@ bool LinearScan::registerIsFree(regNumber regNum, RegisterType regType)
#ifdef _TARGET_ARM_
if (isFree && regType == TYP_DOUBLE)
{
- isFree = getRegisterRecord(REG_NEXT(regNum))->isFree();
+ isFree = getSecondHalfRegRec(physRegRecord)->isFree();
}
#endif // _TARGET_ARM_
@@ -7942,7 +7986,7 @@ void LinearScan::allocateRegisters()
// Update overlapping floating point register for TYP_DOUBLE
if (assignedInterval->registerType == TYP_DOUBLE)
{
- regRecord = getRegisterRecord(REG_NEXT(regRecord->regNum));
+ regRecord = getSecondHalfRegRec(regRecord);
assignedInterval = regRecord->assignedInterval;
assert(assignedInterval != nullptr && !assignedInterval->isActive && assignedInterval->isConstant);
diff --git a/src/jit/lsra.h b/src/jit/lsra.h
index 72c54593a5..65a23b3ca6 100644
--- a/src/jit/lsra.h
+++ b/src/jit/lsra.h
@@ -717,6 +717,7 @@ private:
#ifdef _TARGET_ARM_
bool isSecondHalfReg(RegRecord* regRec, Interval* interval);
+ RegRecord* getSecondHalfRegRec(RegRecord* regRec);
RegRecord* findAnotherHalfRegRec(RegRecord* regRec);
bool canSpillDoubleReg(RegRecord* physRegRecord, LsraLocation refLocation, unsigned* recentAssignedRefWeight);
void unassignDoublePhysReg(RegRecord* doubleRegRecord);