Skip to content

Commit

Permalink
Misc LSRA throughput improvements (#85842)
Browse files Browse the repository at this point in the history
* Use BitOperations in few hot methods

* Do not pass RegisterType for non-arm sarchitectures

* Add clearAssignedInterval()

* Consume clearAssignedInterval()

* Do not pass RegisterType for updateInterval()

* Revert the change in genFindLowestBit()

* Revert "Use BitOperations in few hot methods"

This reverts commit a75a7da.

* Add the missing case for clearAssignedInterval()

* Remove logging

* jit formatting

* Use popcount intrinsics

* Revert "Use popcount intrinsics"

This reverts commit 0b3da21.

* revert unintentional change from superpmi.py

* Revert "Do not pass RegisterType for non-arm sarchitectures"

This reverts commit 46d4d3d.

* fix the merge conflicts
  • Loading branch information
kunalspathak authored May 10, 2023
1 parent fe01aba commit af1de13
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 31 deletions.
94 changes: 67 additions & 27 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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));
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
//
Expand All @@ -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;
Expand All @@ -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);
}

//-----------------------------------------------------------------------------
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}
}
Expand Down Expand Up @@ -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));
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/jit/lsra.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit af1de13

Please sign in to comment.