Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc LSRA throughput improvements #85842

Merged
merged 15 commits into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 67 additions & 27 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2945,7 +2945,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 @@ -3284,7 +3285,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 @@ -3521,7 +3522,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 @@ -3780,8 +3781,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 @@ -4110,7 +4111,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 @@ -4418,7 +4419,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 @@ -5969,6 +5970,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 @@ -5984,8 +6030,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 @@ -6010,25 +6058,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 @@ -6050,7 +6090,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 @@ -6182,7 +6222,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 @@ -6215,7 +6255,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 @@ -6427,14 +6467,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 @@ -1016,8 +1016,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 @@ -1551,8 +1552,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