@@ -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 = ®sFreeLow;
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 = ®sFreeHigh;
5246+ }
5247+ else
5248+ {
5249+ regOffset = REG_LOW_BASE;
5250+ currentRegsFree = ®sFreeLow;
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, ®sToFree,
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
0 commit comments