summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyung-Kyu Choi <hk0110.choi@samsung.com>2017-08-02 18:35:53 +0900
committerHyung-Kyu Choi <hk0110.choi@samsung.com>2017-08-02 18:38:47 +0900
commit7b8dc3fd1ba66de23f25b173a35959b28648fc56 (patch)
treef0e07720c3af5e5af9086d2cb613b0533d5fff68
parent70e070d44b3b6fb328d5e2b18ec85211bc19cdb3 (diff)
downloadcoreclr-7b8dc3fd1ba66de23f25b173a35959b28648fc56.tar.gz
coreclr-7b8dc3fd1ba66de23f25b173a35959b28648fc56.tar.bz2
coreclr-7b8dc3fd1ba66de23f25b173a35959b28648fc56.zip
[RyuJIT/ARM32] Unassign a double register properly in allocateBusyReg()
- Introduce a helper, `unassignDoublePhysReg()` for ARM32 - Update `allocateBusyReg()` for ARM32 using `unassignDoublePhysReg()` Signed-off-by: Hyung-Kyu Choi <hk0110.choi@samsung.com>
-rw-r--r--src/jit/lsra.cpp97
-rw-r--r--src/jit/lsra.h1
2 files changed, 51 insertions, 47 deletions
diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp
index 6181c9b742..63194b6504 100644
--- a/src/jit/lsra.cpp
+++ b/src/jit/lsra.cpp
@@ -5867,6 +5867,47 @@ bool LinearScan::checkActiveIntervals(RegRecord* physRegRecord, LsraLocation ref
#endif
}
+#ifdef _TARGET_ARM_
+void LinearScan::unassignDoublePhysReg(RegRecord* doubleRegRecord)
+{
+ RegRecord* doubleRegRecordLo = doubleRegRecord;
+ RegRecord* doubleRegRecordHi = findAnotherHalfRegRec(doubleRegRecordLo);
+ // For a double register, we has following four cases.
+ // Case 1: doubleRegRecLo is assigned to TYP_DOUBLE interval
+ // Case 2: doubleRegRecLo and doubleRegRecHi are assigned to different TYP_FLOAT intervals
+ // Case 3: doubelRegRecLo is assgined to TYP_FLOAT interval and doubleRegRecHi is nullptr
+ // Case 4: doubleRegRecordLo is nullptr, and doubleRegRecordHi is assigned to a TYP_FLOAT interval
+ if (doubleRegRecordLo->assignedInterval != nullptr)
+ {
+ if (doubleRegRecordLo->assignedInterval->registerType == TYP_DOUBLE)
+ {
+ // Case 1: doubleRegRecLo is assigned to TYP_DOUBLE interval
+ unassignPhysReg(doubleRegRecordLo, doubleRegRecordLo->assignedInterval->recentRefPosition);
+ }
+ else
+ {
+ // Case 2: doubleRegRecLo and doubleRegRecHi are assigned to different TYP_FLOAT intervals
+ // Case 3: doubelRegRecLo is assgined to TYP_FLOAT interval and doubleRegRecHi is nullptr
+ assert(doubleRegRecordLo->assignedInterval->registerType == TYP_FLOAT);
+ unassignPhysReg(doubleRegRecordLo, doubleRegRecordLo->assignedInterval->recentRefPosition);
+
+ if (doubleRegRecordHi != nullptr)
+ {
+ assert(doubleRegRecordHi->assignedInterval->registerType == TYP_FLOAT);
+ unassignPhysReg(doubleRegRecordHi, doubleRegRecordHi->assignedInterval->recentRefPosition);
+ }
+ }
+ }
+ else
+ {
+ // Case 4: doubleRegRecordLo is nullptr, and doubleRegRecordHi is assigned to a TYP_FLOAT interval
+ assert(doubleRegRecordHi->assignedInterval != nullptr);
+ assert(doubleRegRecordHi->assignedInterval->registerType == TYP_FLOAT);
+ unassignPhysReg(doubleRegRecordHi, doubleRegRecordHi->assignedInterval->recentRefPosition);
+ }
+}
+#endif // _TARGET_ARM_
+
//------------------------------------------------------------------------
// allocateBusyReg: Find a busy register that satisfies the requirements for refPosition,
// and that can be spilled.
@@ -6219,71 +6260,33 @@ regNumber LinearScan::allocateBusyReg(Interval* current, RefPosition* refPositio
{
assert(nextRefPosition2 != nullptr && !nextRefPosition2->RequiresRegister());
}
-#else
+#else // !_TARGET_ARM_
Interval* assignedInterval = farthestRefPhysRegRecord->assignedInterval;
RefPosition* nextRefPosition = assignedInterval->getNextRefPosition();
assert(!nextRefPosition->RequiresRegister());
-#endif
+#endif // !_TARGET_ARM_
}
else
{
assert(farthestLocation > refLocation || refPosition->isFixedRegRef);
}
}
-#endif
+#endif // DEBUG
if (farthestRefPhysRegRecord != nullptr)
{
foundReg = farthestRefPhysRegRecord->regNum;
+
#ifdef _TARGET_ARM_
- if (genIsValidDoubleReg(foundReg))
+ if (current->registerType == TYP_DOUBLE)
{
- // For a double register, we has following three cases.
- // Case 1: farthestRefPhysRegRecord is assigned to TYP_DOUBLE interval
- // Case 2: farthestRefPhysRegRecord and farthestRefPhysRegRecord2 are assigned to
- // different TYP_FLOAT intervals
- // Case 3: farthestRefPhysRegRecord is assgined to TYP_FLOAT interval
- // and farthestRefPhysRegRecord2 is nullptr
- // Case 4: farthestRefPhysRegRecord is nullptr, and farthestRefPhysRegRecord2 is
- // assigned to a TYP_FLOAT interval
- if (farthestRefPhysRegRecord->assignedInterval != nullptr)
- {
- if (farthestRefPhysRegRecord->assignedInterval->registerType == TYP_DOUBLE)
- {
- // Case 1: farthestRefPhysRegRecord is assigned to TYP_DOUBLE interval
- unassignPhysReg(farthestRefPhysRegRecord,
- farthestRefPhysRegRecord->assignedInterval->recentRefPosition);
- }
- else
- {
- // Case 2: farthestRefPhysRegRecord and farthestRefPhysRegRecord2 are assigned to
- // different TYP_FLOAT intervals
- // Case 3: farthestRefPhysRegRecord is assgined to TYP_FLOAT interval
- // and farthestRefPhysRegRecord2 is nullptr
- unassignPhysReg(farthestRefPhysRegRecord,
- farthestRefPhysRegRecord->assignedInterval->recentRefPosition);
- if (farthestRefPhysRegRecord2 != nullptr)
- unassignPhysReg(farthestRefPhysRegRecord2,
- farthestRefPhysRegRecord2->assignedInterval->recentRefPosition);
- }
- }
- else
- {
- // Case 4: farthestRefPhysRegRecord is nullptr, and farthestRefPhysRegRecord2 is
- // assigned to a TYP_FLOAT interval
- assert(farthestRefPhysRegRecord2->assignedInterval != nullptr);
- assert(farthestRefPhysRegRecord2->assignedInterval->registerType == TYP_FLOAT);
- unassignPhysReg(farthestRefPhysRegRecord2,
- farthestRefPhysRegRecord2->assignedInterval->recentRefPosition);
- }
+ assert(genIsValidDoubleReg(foundReg));
+ unassignDoublePhysReg(farthestRefPhysRegRecord);
}
else
- {
- unassignPhysReg(farthestRefPhysRegRecord, farthestRefPhysRegRecord->assignedInterval->recentRefPosition);
- }
-#else
- unassignPhysReg(farthestRefPhysRegRecord, farthestRefPhysRegRecord->assignedInterval->recentRefPosition);
#endif
+ unassignPhysReg(farthestRefPhysRegRecord, farthestRefPhysRegRecord->assignedInterval->recentRefPosition);
+
assignPhysReg(farthestRefPhysRegRecord, current);
refPosition->registerAssignment = genRegMask(foundReg);
}
diff --git a/src/jit/lsra.h b/src/jit/lsra.h
index f4855a93ca..2ef9feecd6 100644
--- a/src/jit/lsra.h
+++ b/src/jit/lsra.h
@@ -701,6 +701,7 @@ private:
LsraLocation refLocation,
unsigned* recentAssignedRefWeight,
unsigned farthestRefPosWeight);
+ void unassignDoublePhysReg(RegRecord* doubleRegRecord);
#endif
void updateAssignedInterval(RegRecord* reg, Interval* interval, RegisterType regType);
void updatePreviousInterval(RegRecord* reg, Interval* interval, RegisterType regType);