[RyuJIT/ARM32] Update LinearScan::resolveLocalRef() for ARM32 (dotnet/coreclr#12194)
authorHyung-Kyu Choi <hk0110.choi@samsung.com>
Mon, 19 Jun 2017 17:47:37 +0000 (02:47 +0900)
committerBruce Forstall <brucefo@microsoft.com>
Mon, 19 Jun 2017 17:47:37 +0000 (10:47 -0700)
Update LinearScan::resolveLocalRef()
- Always update two float register consisting a double register
- Use helper function for ARM32 double register
- Use stronger assertion condition

Introduce updateAssignedInterval() to update assigned interval
of ARM32 register considering register type.

Commit migrated from https://github.com/dotnet/coreclr/commit/f6ce70eb9b6cb08b4ca0fb91692d284a1d37e37b

src/coreclr/src/jit/lsra.cpp
src/coreclr/src/jit/lsra.h

index e1adcd7..f496315 100644 (file)
@@ -6719,7 +6719,7 @@ regNumber LinearScan::rotateBlockStartLocation(Interval* interval, regNumber tar
 
 #ifdef _TARGET_ARM_
 //--------------------------------------------------------------------------------------
-// isSecondHalfReg: Test if recRec is second half of double reigster
+// isSecondHalfReg: Test if recRec is second half of double register
 //                  which is assigned to an interval.
 //
 // Arguments:
@@ -8012,6 +8012,40 @@ void LinearScan::allocateRegisters()
 #endif // DEBUG
 }
 
+#ifdef _TARGET_ARM_
+//-----------------------------------------------------------------------------
+// updateAssignedInterval: Update assigned interval of register for ARM32
+// considering register type. When register type is TYP_DOUBLE, update
+// two float registers consisting a double register.
+//
+// Arguments:
+//    reg      -    register to be updated
+//    interval -    interval to be assigned
+//    regType  -    regsiter type
+//
+// Return Value:
+//    None
+//
+// Assumptions:
+//    When "regType" is TYP_DOUBLE, "reg" should be a even-numbered float register,
+//    i.e. lower half of double register.
+//
+void LinearScan::updateAssignedInterval(RegRecord* reg, Interval* interval, RegisterType regType)
+{
+    reg->assignedInterval = interval;
+
+    // Update overlapping floating point register for TYP_DOUBLE
+    if (regType == TYP_DOUBLE)
+    {
+        assert(genIsValidDoubleReg(reg->regNum));
+
+        RegRecord* anotherHalfReg = findAnotherHalfRegRec(reg);
+
+        anotherHalfReg->assignedInterval = interval;
+    }
+}
+#endif
+
 // LinearScan::resolveLocalRef
 // Description:
 //      Update the graph for a local reference.
@@ -8087,7 +8121,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi
         varDsc->lvRegNum = REG_STK;
         if (interval->assignedReg != nullptr && interval->assignedReg->assignedInterval == interval)
         {
+#ifdef _TARGET_ARM_
+            updateAssignedInterval(interval->assignedReg, nullptr, interval->registerType);
+#else
             interval->assignedReg->assignedInterval = nullptr;
+#endif
         }
         interval->assignedReg = nullptr;
         interval->physReg     = REG_NA;
@@ -8115,7 +8153,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi
             RegRecord* oldRegRecord = getRegisterRecord(oldAssignedReg);
             if (oldRegRecord->assignedInterval == interval)
             {
-                oldRegRecord->assignedInterval = nullptr;
+#ifdef _TARGET_ARM_
+                updateAssignedInterval(oldRegRecord, nullptr, interval->registerType);
+#else
+                oldRegRecord->assignedInterval      = nullptr;
+#endif
             }
         }
     }
@@ -8266,27 +8308,25 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi
     RegRecord* physRegRecord = getRegisterRecord(homeReg);
     if (spillAfter || currentRefPosition->lastUse)
     {
-        physRegRecord->assignedInterval = nullptr;
-        interval->assignedReg           = nullptr;
-        interval->physReg               = REG_NA;
-        interval->isActive              = false;
+        interval->isActive    = false;
+        interval->assignedReg = nullptr;
+        interval->physReg     = REG_NA;
+
+#ifdef _TARGET_ARM_
+        updateAssignedInterval(physRegRecord, nullptr, interval->registerType);
+#else
+        physRegRecord->assignedInterval             = nullptr;
+#endif
     }
     else
     {
-        interval->isActive              = true;
-        physRegRecord->assignedInterval = interval;
-        interval->assignedReg           = physRegRecord;
-#ifdef _TARGET_ARM_
-        // Update overlapping floating point register for TYP_DOUBLE
-        if (interval->registerType == TYP_DOUBLE)
-        {
-            assert(isFloatRegType(physRegRecord->registerType));
+        interval->isActive    = true;
+        interval->assignedReg = physRegRecord;
 
-            regNumber  nextRegNum        = REG_NEXT(physRegRecord->regNum);
-            RegRecord* nextPhysRegRecord = getRegisterRecord(nextRegNum);
-
-            nextPhysRegRecord->assignedInterval = interval;
-        }
+#ifdef _TARGET_ARM_
+        updateAssignedInterval(physRegRecord, interval, interval->registerType);
+#else
+        physRegRecord->assignedInterval             = interval;
 #endif
     }
 }
@@ -10052,7 +10092,7 @@ void LinearScan::resolveEdge(BasicBlock*      fromBlock,
             tempRegFlt = getTempRegForResolution(fromBlock, toBlock, TYP_FLOAT);
         }
 #else
-        tempRegFlt = getTempRegForResolution(fromBlock, toBlock, TYP_FLOAT);
+        tempRegFlt                                  = getTempRegForResolution(fromBlock, toBlock, TYP_FLOAT);
 #endif
     }
 
index 3ef17f0..14a986f 100644 (file)
@@ -697,6 +697,7 @@ private:
 #ifdef _TARGET_ARM_
     bool isSecondHalfReg(RegRecord* regRec, Interval* interval);
     RegRecord* findAnotherHalfRegRec(RegRecord* regRec);
+    void updateAssignedInterval(RegRecord* reg, Interval* interval, RegisterType regType);
 #endif
     bool canRestorePreviousInterval(RegRecord* regRec, Interval* assignedInterval);