Skip to content

Commit 657a419

Browse files
Expt 3
1 parent 50cf7cc commit 657a419

File tree

2 files changed

+157
-39
lines changed

2 files changed

+157
-39
lines changed

src/coreclr/jit/lsra.cpp

Lines changed: 136 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,33 @@ void LinearScan::updateRegsFreeBusyState(RefPosition& refPosition,
465465
}
466466
}
467467

468+
void LinearScan::updateRegsFreeBusyState(RefPosition& refPosition,
469+
var_types registerType,
470+
SingleTypeRegSet regsBusy,
471+
regsFreeStruct* currentRegsFree DEBUG_ARG(Interval* interval)
472+
DEBUG_ARG(regNumber assignedReg))
473+
{
474+
regsInUseThisLocation.AddRegsetForType(regsBusy, registerType);
475+
if (refPosition.lastUse)
476+
{
477+
if (refPosition.delayRegFree)
478+
{
479+
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED, interval, assignedReg));
480+
currentRegsFree->delayRegsToFree |= (regsBusy);
481+
regsInUseNextLocation.AddRegsetForType(regsBusy, registerType);
482+
}
483+
else
484+
{
485+
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE, interval, assignedReg));
486+
currentRegsFree->regsToFree |= (regsBusy);
487+
}
488+
}
489+
else if (refPosition.delayRegFree)
490+
{
491+
regsInUseNextLocation.AddRegsetForType(regsBusy, registerType);
492+
}
493+
}
494+
468495
//------------------------------------------------------------------------
469496
// internalFloatRegCandidates: Return the set of registers that are appropriate
470497
// for use as internal float registers.
@@ -4874,6 +4901,40 @@ void LinearScan::freeRegisters(regMaskTP regsToFree)
48744901
#endif
48754902
}
48764903

4904+
//------------------------------------------------------------------------
4905+
// LinearScan::freeRegisters: Free the registers in 'regsToFree'
4906+
//
4907+
// Arguments:
4908+
// regsToFree - the mask of registers to free
4909+
//
4910+
void LinearScan::freeRegisters(SingleTypeRegSet regsToFree, var_types varType, int regBase)
4911+
{
4912+
if (regsToFree != RBM_NONE)
4913+
{
4914+
return;
4915+
}
4916+
4917+
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_FREE_REGS));
4918+
makeRegsAvailable(regsToFree, varType);
4919+
4920+
#ifdef TARGET_ARM
4921+
while (regsToFree != RBM_NONE)
4922+
{
4923+
regNumber nextReg = genFirstRegNumFromMaskAndToggle(regsToFree);
4924+
4925+
RegRecord* regRecord = getRegisterRecord(nextReg);
4926+
if (regRecord->assignedInterval != nullptr && (regRecord->assignedInterval->registerType == TYP_DOUBLE))
4927+
{
4928+
assert(genIsValidDoubleReg(nextReg));
4929+
regsToFree &= ~genSingleTypeRegMask(regNumber(nextReg + 1));
4930+
}
4931+
freeRegister(regRecord);
4932+
}
4933+
#else
4934+
freeRegistersSingleType(regsToFree, regBase);
4935+
#endif
4936+
}
4937+
48774938
//------------------------------------------------------------------------
48784939
// LinearScan::allocateRegistersMinimal: Perform the actual register allocation when localVars
48794940
// are not enregistered.
@@ -4930,8 +4991,17 @@ void LinearScan::allocateRegistersMinimal()
49304991
regMaskTP regsToMakeInactive = RBM_NONE;
49314992
regMaskTP delayRegsToMakeInactive = RBM_NONE;
49324993
regMaskTP copyRegsToFree = RBM_NONE;
4933-
regsInUseThisLocation = RBM_NONE;
4934-
regsInUseNextLocation = RBM_NONE;
4994+
4995+
// regsFreeStruct *currentRegsFree = nullptr;
4996+
regsFreeStruct regsFreeLow;
4997+
#ifdef HAS_MORE_THAN_64_REGISTERS
4998+
regsFreeStruct regsFreeHigh;
4999+
#endif // HAS_MORE_THAN_64_REGISTERS
5000+
regsFreeStruct* currentRegsFree = &regsFreeLow;
5001+
int regOffset = REG_LOW_BASE;
5002+
var_types currType = TYP_UNDEF;
5003+
regsInUseThisLocation = RBM_NONE;
5004+
regsInUseNextLocation = RBM_NONE;
49355005

49365006
// This is the most recent RefPosition for which a register was allocated
49375007
// - currently only used for DEBUG but maintained in non-debug, for clarity of code
@@ -4945,22 +5015,23 @@ void LinearScan::allocateRegistersMinimal()
49455015
// TODO: Can we combine this with the freeing of registers below? It might
49465016
// mess with the dump, since this was previously being done before the call below
49475017
// to dumpRegRecords.
4948-
regMaskTP tempRegsToMakeInactive = (regsToMakeInactive | delayRegsToMakeInactive);
4949-
while (tempRegsToMakeInactive.IsNonEmpty())
5018+
SingleTypeRegSet tempRegsToMakeInactive =
5019+
(currentRegsFree->regsToMakeInactive | currentRegsFree->delayRegsToMakeInactive);
5020+
while (tempRegsToMakeInactive != RBM_NONE)
49505021
{
4951-
regNumber nextReg = genFirstRegNumFromMaskAndToggle(tempRegsToMakeInactive);
5022+
regNumber nextReg = (regNumber)(genFirstRegNumFromMaskAndToggle(tempRegsToMakeInactive) + regOffset);
49525023
RegRecord* regRecord = getRegisterRecord(nextReg);
49535024
clearSpillCost(regRecord->regNum, regRecord->registerType);
49545025
makeRegisterInactive(regRecord);
49555026
}
49565027
if (currentRefPosition.nodeLocation > prevLocation)
49575028
{
4958-
makeRegsAvailable(regsToMakeInactive);
5029+
makeRegsAvailable(currentRegsFree->regsToMakeInactive, currType);
49595030
// TODO: Clean this up. We need to make the delayRegs inactive as well, but don't want
49605031
// to mark them as free yet.
4961-
regsToMakeInactive |= delayRegsToMakeInactive;
4962-
regsToMakeInactive = delayRegsToMakeInactive;
4963-
delayRegsToMakeInactive = RBM_NONE;
5032+
// regsToMakeInactive |= delayRegsToMakeInactive;
5033+
currentRegsFree->regsToMakeInactive = currentRegsFree->delayRegsToMakeInactive;
5034+
currentRegsFree->delayRegsToMakeInactive = RBM_NONE;
49645035
}
49655036

49665037
#ifdef DEBUG
@@ -5016,28 +5087,30 @@ void LinearScan::allocateRegistersMinimal()
50165087
if (currentLocation > prevLocation)
50175088
{
50185089
// CopyRegs are simply made available - we don't want to make the associated interval inactive.
5019-
makeRegsAvailable(copyRegsToFree);
5020-
copyRegsToFree = RBM_NONE;
5021-
regsInUseThisLocation = regsInUseNextLocation;
5022-
regsInUseNextLocation = RBM_NONE;
5023-
if ((regsToFree | delayRegsToFree).IsNonEmpty())
5090+
makeRegsAvailable(currentRegsFree->copyRegsToFree, currType);
5091+
currentRegsFree->copyRegsToFree = RBM_NONE;
5092+
regsInUseThisLocation = regsInUseNextLocation;
5093+
regsInUseNextLocation = RBM_NONE;
5094+
if ((currentRegsFree->regsToFree | currentRegsFree->delayRegsToFree) != RBM_NONE)
50245095
{
5025-
freeRegisters(regsToFree);
5026-
if ((currentLocation > (prevLocation + 1)) && (delayRegsToFree.IsNonEmpty()))
5096+
freeRegisters(currentRegsFree->regsToFree, currType, regOffset);
5097+
if ((currentLocation > (prevLocation + 1)) && (currentRegsFree->delayRegsToFree != RBM_NONE))
50275098
{
50285099
// We should never see a delayReg that is delayed until a Location that has no RefPosition
50295100
// (that would be the RefPosition that it was supposed to interfere with).
50305101
assert(!"Found a delayRegFree associated with Location with no reference");
50315102
// However, to be cautious for the Release build case, we will free them.
5032-
freeRegisters(delayRegsToFree);
5033-
delayRegsToFree = RBM_NONE;
5034-
regsInUseThisLocation = RBM_NONE;
5103+
freeRegisters(currentRegsFree->delayRegsToFree, currType, regOffset);
5104+
currentRegsFree->delayRegsToFree = RBM_NONE;
5105+
regsInUseThisLocation = RBM_NONE;
50355106
}
5036-
regsToFree = delayRegsToFree;
5037-
delayRegsToFree = RBM_NONE;
5107+
currentRegsFree->regsToFree = currentRegsFree->delayRegsToFree;
5108+
currentRegsFree->delayRegsToFree = RBM_NONE;
50385109

50395110
#ifdef DEBUG
5040-
verifyFreeRegisters(regsToFree);
5111+
regMaskTP regsToFreeVerify = RBM_NONE;
5112+
regsToFreeVerify.AddRegsetForType(currentRegsFree->regsToFree, currType);
5113+
verifyFreeRegisters(regsToFreeVerify);
50415114
#endif // DEBUG
50425115
}
50435116
}
@@ -5075,12 +5148,13 @@ void LinearScan::allocateRegistersMinimal()
50755148
if (!handledBlockEnd && refType == RefTypeBB)
50765149
{
50775150
// Free any delayed regs (now in regsToFree) before processing the block boundary
5078-
freeRegisters(regsToFree);
5079-
regsToFree = RBM_NONE;
5080-
regsInUseThisLocation = RBM_NONE;
5081-
regsInUseNextLocation = RBM_NONE;
5082-
handledBlockEnd = true;
5083-
curBBStartLocation = currentRefPosition.nodeLocation;
5151+
// freeRegisters(regsToFree);
5152+
freeRegisters(currentRegsFree->regsToFree, currType, regOffset);
5153+
currentRegsFree->regsToFree = RBM_NONE;
5154+
regsInUseThisLocation = RBM_NONE;
5155+
regsInUseNextLocation = RBM_NONE;
5156+
handledBlockEnd = true;
5157+
curBBStartLocation = currentRefPosition.nodeLocation;
50845158
if (currentBlock == nullptr)
50855159
{
50865160
currentBlock = startBlockSequence();
@@ -5163,6 +5237,19 @@ void LinearScan::allocateRegistersMinimal()
51635237
// Identify the special cases where we decide up-front not to allocate
51645238
bool allocate = true;
51655239
bool didDump = false;
5240+
#ifdef HAS_MORE_THAN_64_REGISTERS
5241+
currType = currentInterval->registerType;
5242+
if (varTypeIsMask(currType))
5243+
{
5244+
regOffset = REG_HIGH_BASE;
5245+
currentRegsFree = &regsFreeHigh;
5246+
}
5247+
else
5248+
{
5249+
regOffset = REG_LOW_BASE;
5250+
currentRegsFree = &regsFreeLow;
5251+
}
5252+
#endif // HAS_MORE_THAN_64_REGISTERS
51665253

51675254
#ifdef FEATURE_SIMD
51685255
#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE
@@ -5271,11 +5358,11 @@ void LinearScan::allocateRegistersMinimal()
52715358
// happened to be restored in assignedReg, we would need assignedReg to stay alive because
52725359
// we will copy the entire vector value from it to the `copyReg`.
52735360
updateRegsFreeBusyState(currentRefPosition, currentInterval->registerType,
5274-
assignedRegMask | copyRegMask, &regsToFree,
5275-
&delayRegsToFree DEBUG_ARG(currentInterval) DEBUG_ARG(assignedRegister));
5361+
assignedRegMask | copyRegMask,
5362+
currentRegsFree DEBUG_ARG(currentInterval) DEBUG_ARG(assignedRegister));
52765363
if (!currentRefPosition.lastUse)
52775364
{
5278-
copyRegsToFree.AddRegsetForType(copyRegMask, currentInterval->registerType);
5365+
currentRegsFree->copyRegsToFree |= copyRegMask;
52795366
}
52805367

52815368
// For tree temp (non-localVar) interval, we will need an explicit move.
@@ -5290,7 +5377,8 @@ void LinearScan::allocateRegistersMinimal()
52905377
else
52915378
{
52925379
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NEEDS_NEW_REG, nullptr, assignedRegister));
5293-
regsToFree.AddRegNum(assignedRegister, currentInterval->registerType);
5380+
currentRegsFree->regsToFree |=
5381+
getSingleTypeRegMask(assignedRegister, currentInterval->registerType);
52945382
// We want a new register, but we don't want this to be considered a spill.
52955383
assignedRegister = REG_NA;
52965384
if (physRegRecord->assignedInterval == currentInterval)
@@ -5398,8 +5486,10 @@ void LinearScan::allocateRegistersMinimal()
53985486
currentRefPosition.registerAssignment = assignedRegBit;
53995487

54005488
currentInterval->physReg = assignedRegister;
5401-
regsToFree.RemoveRegsetForType(regMask, currentInterval->registerType); // we'll set it again later if it's
5402-
// dead
5489+
currentRegsFree->regsToFree &= ~regMask;
5490+
// regsToFree.RemoveRegsetForType(regMask, currentInterval->registerType); // we'll set it again later if
5491+
// it's
5492+
// dead
54035493

54045494
// If this interval is dead, free the register.
54055495
// The interval could be dead if this is a user variable, or if the
@@ -5420,11 +5510,13 @@ void LinearScan::allocateRegistersMinimal()
54205510
{
54215511
if (currentRefPosition.delayRegFree)
54225512
{
5423-
delayRegsToMakeInactive.AddRegsetForType(regMask, currentInterval->registerType);
5513+
currentRegsFree->delayRegsToMakeInactive |= regMask;
5514+
// delayRegsToMakeInactive.AddRegsetForType(regMask, currentInterval->registerType);
54245515
}
54255516
else
54265517
{
5427-
regsToMakeInactive.AddRegsetForType(regMask, currentInterval->registerType);
5518+
currentRegsFree->regsToMakeInactive |= regMask;
5519+
// regsToMakeInactive.AddRegsetForType(regMask, currentInterval->registerType);
54285520
}
54295521
// TODO-Cleanup: this makes things consistent with previous, and will enable preferences
54305522
// to be propagated, but it seems less than ideal.
@@ -5443,13 +5535,15 @@ void LinearScan::allocateRegistersMinimal()
54435535
{
54445536
if (currentRefPosition.delayRegFree)
54455537
{
5446-
delayRegsToFree.AddRegsetForType(regMask, currentInterval->registerType);
5538+
currentRegsFree->delayRegsToFree |= regMask;
5539+
// delayRegsToFree.AddRegsetForType(regMask, currentInterval->registerType);
54475540

54485541
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE_DELAYED));
54495542
}
54505543
else
54515544
{
5452-
regsToFree.AddRegsetForType(regMask, currentInterval->registerType);
5545+
currentRegsFree->regsToFree |= regMask;
5546+
// regsToFree.AddRegsetForType(regMask, currentInterval->registerType);
54535547

54545548
INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_LAST_USE));
54555549
}
@@ -5483,7 +5577,10 @@ void LinearScan::allocateRegistersMinimal()
54835577
else
54845578
#endif // DEBUG
54855579
{
5486-
freeRegisters(regsToFree | delayRegsToFree);
5580+
freeRegisters(regsFreeLow.regsToFree | regsFreeLow.delayRegsToFree, TYP_UNDEF, REG_LOW_BASE);
5581+
#ifdef HAS_MORE_THAN_64_REGISTERS
5582+
freeRegisters(regsFreeHigh.regsToFree | regsFreeHigh.delayRegsToFree, TYP_MASK, REG_HIGH_BASE);
5583+
#endif // HAS_MORE_THAN_64_REGISTERS
54875584
}
54885585

54895586
#ifdef DEBUG

src/coreclr/jit/lsra.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ class LinearScan : public LinearScanInterface
10841084
void makeRegisterInactive(RegRecord* physRegRecord);
10851085
void freeRegister(RegRecord* physRegRecord);
10861086
void freeRegisters(regMaskTP regsToFree);
1087+
void freeRegisters(SingleTypeRegSet regsToFree, var_types varType, int regBase);
10871088
FORCEINLINE void freeRegistersSingleType(SingleTypeRegSet regsToFree, int regBase);
10881089

10891090
// Get the type that this tree defines.
@@ -1788,6 +1789,11 @@ class LinearScan : public LinearScanInterface
17881789
{
17891790
m_AvailableRegs |= regMask;
17901791
}
1792+
void makeRegsAvailable(SingleTypeRegSet regMask, var_types regType)
1793+
{
1794+
m_AvailableRegs.AddRegsetForType(regMask, regType);
1795+
}
1796+
17911797
void makeRegAvailable(regNumber reg, var_types regType)
17921798
{
17931799
m_AvailableRegs.AddRegNum(reg, regType);
@@ -1801,12 +1807,26 @@ class LinearScan : public LinearScanInterface
18011807
void clearSpillCost(regNumber reg, var_types regType);
18021808
void updateSpillCost(regNumber reg, Interval* interval);
18031809

1810+
struct regsFreeStruct
1811+
{
1812+
SingleTypeRegSet regsToFree{RBM_NONE};
1813+
SingleTypeRegSet delayRegsToFree{RBM_NONE};
1814+
SingleTypeRegSet regsToMakeInactive{RBM_NONE};
1815+
SingleTypeRegSet delayRegsToMakeInactive{RBM_NONE};
1816+
SingleTypeRegSet copyRegsToFree{RBM_NONE};
1817+
};
1818+
18041819
FORCEINLINE void updateRegsFreeBusyState(RefPosition& refPosition,
18051820
var_types registerType,
18061821
SingleTypeRegSet regsBusy,
18071822
regMaskTP* regsToFree,
18081823
regMaskTP* delayRegsToFree DEBUG_ARG(Interval* interval)
18091824
DEBUG_ARG(regNumber assignedReg));
1825+
FORCEINLINE void updateRegsFreeBusyState(RefPosition& refPosition,
1826+
var_types registerType,
1827+
SingleTypeRegSet regsBusy,
1828+
regsFreeStruct* currentRegsFree DEBUG_ARG(Interval* interval)
1829+
DEBUG_ARG(regNumber assignedReg));
18101830

18111831
regMaskTP m_RegistersWithConstants;
18121832
void clearConstantReg(regNumber reg, var_types regType)
@@ -1874,6 +1894,7 @@ class LinearScan : public LinearScanInterface
18741894
regMaskTP regsBusyUntilKill;
18751895
regMaskTP regsInUseThisLocation;
18761896
regMaskTP regsInUseNextLocation;
1897+
18771898
#ifdef TARGET_ARM64
18781899
SingleTypeRegSet consecutiveRegsInUseThisLocation;
18791900
#endif

0 commit comments

Comments
 (0)