diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 617c6016bc5a5..9061c2879bb09 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -2949,7 +2949,8 @@ regNumber LinearScan::allocateReg(Interval* currentInterval, } else if (wasAssigned) { - updatePreviousInterval(availablePhysRegRecord, assignedInterval, assignedInterval->registerType); + updatePreviousInterval(availablePhysRegRecord, + assignedInterval ARM_ARG(assignedInterval->registerType)); } else { @@ -3288,7 +3289,7 @@ void LinearScan::checkAndAssignInterval(RegRecord* regRec, Interval* interval) } #endif - updateAssignedInterval(regRec, interval, interval->registerType); + updateAssignedInterval(regRec, interval ARM_ARG(interval->registerType)); } // Assign the given physical register interval to the given interval @@ -3525,7 +3526,7 @@ void LinearScan::checkAndClearInterval(RegRecord* regRec, RefPosition* spillRefP assert(spillRefPosition->getInterval() == assignedInterval); } - updateAssignedInterval(regRec, nullptr, assignedInterval->registerType); + clearAssignedInterval(regRec ARM_ARG(assignedInterval->registerType)); } //------------------------------------------------------------------------ @@ -3784,8 +3785,8 @@ void LinearScan::unassignPhysReg(RegRecord* regRec, RefPosition* spillRefPositio } else { - updateAssignedInterval(regRec, nullptr, assignedInterval->registerType); - updatePreviousInterval(regRec, nullptr, assignedInterval->registerType); + clearAssignedInterval(regRec ARM_ARG(assignedInterval->registerType)); + updatePreviousInterval(regRec, nullptr ARM_ARG(assignedInterval->registerType)); } } @@ -4114,7 +4115,7 @@ void LinearScan::unassignIntervalBlockStart(RegRecord* regRecord, VarToRegMap in else { // This interval is no longer assigned to this register. - updateAssignedInterval(regRecord, nullptr, assignedInterval->registerType); + clearAssignedInterval(regRecord ARM_ARG(assignedInterval->registerType)); } } } @@ -4422,7 +4423,7 @@ void LinearScan::processBlockStartLocations(BasicBlock* currentBlock) { // This interval may still be active, but was in another register in an // intervening block. - updateAssignedInterval(physRegRecord, nullptr, assignedInterval->registerType); + clearAssignedInterval(physRegRecord ARM_ARG(assignedInterval->registerType)); } #ifdef TARGET_ARM @@ -5973,6 +5974,51 @@ void LinearScan::allocateRegisters() #endif // DEBUG } +//----------------------------------------------------------------------------- +// clearAssignedInterval: Clear assigned interval of register. +// +// Arguments: +// reg - register to be updated +// regType - register type +// +// Return Value: +// None +// +// Note: +// For ARM32, two float registers consisting a double register are cleared +// together when "regType" is TYP_DOUBLE. +// +void LinearScan::clearAssignedInterval(RegRecord* reg ARM_ARG(RegisterType regType)) +{ +#ifdef TARGET_ARM + regNumber doubleReg = REG_NA; + Interval* oldAssignedInterval = reg->assignedInterval; + if (regType == TYP_DOUBLE) + { + RegRecord* anotherHalfReg = findAnotherHalfRegRec(reg); + doubleReg = genIsValidDoubleReg(reg->regNum) ? reg->regNum : anotherHalfReg->regNum; + anotherHalfReg->assignedInterval = nullptr; + } + else if ((oldAssignedInterval != nullptr) && (oldAssignedInterval->registerType == TYP_DOUBLE)) + { + RegRecord* anotherHalfReg = findAnotherHalfRegRec(reg); + doubleReg = genIsValidDoubleReg(reg->regNum) ? reg->regNum : anotherHalfReg->regNum; + anotherHalfReg->assignedInterval = nullptr; + } + + if (doubleReg != REG_NA) + { + clearNextIntervalRef(doubleReg, TYP_DOUBLE); + clearSpillCost(doubleReg, TYP_DOUBLE); + clearConstantReg(doubleReg, TYP_DOUBLE); + } +#endif // TARGET_ARM + + reg->assignedInterval = nullptr; + clearNextIntervalRef(reg->regNum, reg->registerType); + clearSpillCost(reg->regNum, reg->registerType); +} + //----------------------------------------------------------------------------- // updateAssignedInterval: Update assigned interval of register. // @@ -5988,8 +6034,10 @@ void LinearScan::allocateRegisters() // For ARM32, two float registers consisting a double register are updated // together when "regType" is TYP_DOUBLE. // -void LinearScan::updateAssignedInterval(RegRecord* reg, Interval* interval, RegisterType regType) +void LinearScan::updateAssignedInterval(RegRecord* reg, Interval* interval ARM_ARG(RegisterType regType)) { + assert(interval != nullptr); + #ifdef TARGET_ARM // Update overlapping floating point register for TYP_DOUBLE. Interval* oldAssignedInterval = reg->assignedInterval; @@ -6014,25 +6062,17 @@ void LinearScan::updateAssignedInterval(RegRecord* reg, Interval* interval, Regi } #endif reg->assignedInterval = interval; - if (interval != nullptr) + setRegInUse(reg->regNum, interval->registerType); + if (interval->isConstant) { - setRegInUse(reg->regNum, interval->registerType); - if (interval->isConstant) - { - setConstantReg(reg->regNum, interval->registerType); - } - else - { - clearConstantReg(reg->regNum, interval->registerType); - } - updateNextIntervalRef(reg->regNum, interval); - updateSpillCost(reg->regNum, interval); + setConstantReg(reg->regNum, interval->registerType); } else { - clearNextIntervalRef(reg->regNum, reg->registerType); - clearSpillCost(reg->regNum, reg->registerType); + clearConstantReg(reg->regNum, interval->registerType); } + updateNextIntervalRef(reg->regNum, interval); + updateSpillCost(reg->regNum, interval); } //----------------------------------------------------------------------------- @@ -6054,7 +6094,7 @@ void LinearScan::updateAssignedInterval(RegRecord* reg, Interval* interval, Regi // For ARM32, two float registers consisting a double register are updated // together when "regType" is TYP_DOUBLE. // -void LinearScan::updatePreviousInterval(RegRecord* reg, Interval* interval, RegisterType regType) +void LinearScan::updatePreviousInterval(RegRecord* reg, Interval* interval ARM_ARG(RegisterType regType)) { reg->previousInterval = interval; @@ -6186,7 +6226,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, Ref varDsc->SetRegNum(REG_STK); if (interval->assignedReg != nullptr && interval->assignedReg->assignedInterval == interval) { - updateAssignedInterval(interval->assignedReg, nullptr, interval->registerType); + clearAssignedInterval(interval->assignedReg ARM_ARG(interval->registerType)); } interval->assignedReg = nullptr; interval->physReg = REG_NA; @@ -6219,7 +6259,7 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, Ref RegRecord* oldRegRecord = getRegisterRecord(oldAssignedReg); if (oldRegRecord->assignedInterval == interval) { - updateAssignedInterval(oldRegRecord, nullptr, interval->registerType); + clearAssignedInterval(oldRegRecord ARM_ARG(interval->registerType)); } } } @@ -6431,14 +6471,14 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, Ref interval->assignedReg = nullptr; interval->physReg = REG_NA; - updateAssignedInterval(physRegRecord, nullptr, interval->registerType); + clearAssignedInterval(physRegRecord ARM_ARG(interval->registerType)); } else { interval->isActive = true; interval->assignedReg = physRegRecord; - updateAssignedInterval(physRegRecord, interval, interval->registerType); + updateAssignedInterval(physRegRecord, interval ARM_ARG(interval->registerType)); } } diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index a5e79ebfab51c..3decb1d6fbfb3 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -1017,8 +1017,9 @@ class LinearScan : public LinearScanInterface bool canSpillDoubleReg(RegRecord* physRegRecord, LsraLocation refLocation); void unassignDoublePhysReg(RegRecord* doubleRegRecord); #endif - void updateAssignedInterval(RegRecord* reg, Interval* interval, RegisterType regType); - void updatePreviousInterval(RegRecord* reg, Interval* interval, RegisterType regType); + void clearAssignedInterval(RegRecord* reg ARM_ARG(RegisterType regType)); + void updateAssignedInterval(RegRecord* reg, Interval* interval ARM_ARG(RegisterType regType)); + void updatePreviousInterval(RegRecord* reg, Interval* interval ARM_ARG(RegisterType regType)); bool canRestorePreviousInterval(RegRecord* regRec, Interval* assignedInterval); bool isAssignedToInterval(Interval* interval, RegRecord* regRec); bool isRefPositionActive(RefPosition* refPosition, LsraLocation refLocation); @@ -1552,8 +1553,7 @@ class LinearScan : public LinearScanInterface #endif // !TRACK_LSRA_STATS private: - Compiler* compiler; - + Compiler* compiler; CompAllocator getAllocator(Compiler* comp) { return comp->getAllocator(CMK_LSRA);