Skip to content
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
36 changes: 34 additions & 2 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,35 @@ RegRecord* LinearScan::getRegisterRecord(regNumber regNum)
return &physRegs[regNum];
}

//------------------------------------------------------------------------
// getAvailableGPRsForType: Returns available general-purpose registers for the given type,
// with platform-specific restrictions applied.
//
// Arguments:
// candidates - The candidate register mask to be filtered
// regType - The register type for which we need available registers
//
// Return Value:
// A filtered register mask with platform-specific restrictions applied.
// For AMD64: GC types and long types are restricted to low GPRs only.
// For other platforms: Returns the original candidates unchanged.
//
// Notes:
// On AMD64, we don't use extended GPRs (R16-R31) for GC types to ensure
// proper GC tracking and code generation compatibility.
//
SingleTypeRegSet LinearScan::getAvailableGPRsForType(SingleTypeRegSet candidates, var_types regType)
{
#ifdef TARGET_AMD64
if (varTypeIsGC(regType) || varTypeIsLong(regType))
{
// For AMD64, we don't use eGPR for GC types.
candidates &= (SingleTypeRegSet)RBM_LOWINT.getLow();
}
#endif // TARGET_AMD64
return candidates;
}

#ifdef DEBUG

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -8694,6 +8723,9 @@ regNumber LinearScan::getTempRegForResolution(BasicBlock* fromBlock,
}
#else // !TARGET_ARM
SingleTypeRegSet freeRegs = allRegs(type);
// We call getTempRegForResolution() with only either TYP_INT or TYP_FLOAT.
// We are being conservative with eGPR usage when type is TYP_INT since it could be a reference type.
freeRegs = getAvailableGPRsForType(freeRegs, (type == TYP_INT) ? TYP_REF : type);
#endif // !TARGET_ARM

#ifdef DEBUG
Expand Down Expand Up @@ -13466,7 +13498,7 @@ SingleTypeRegSet LinearScan::RegisterSelection::select(Interval*
{
preferences = candidates;
}

candidates = linearScan->getAvailableGPRsForType(candidates, regType);
#ifdef DEBUG
candidates = linearScan->stressLimitRegs(refPosition, regType, candidates);
#endif
Expand Down Expand Up @@ -13934,7 +13966,7 @@ SingleTypeRegSet LinearScan::RegisterSelection::selectMinimal(
}
}
}

candidates = linearScan->getAvailableGPRsForType(candidates, regType);
#ifdef DEBUG
candidates = linearScan->stressLimitRegs(refPosition, regType, candidates);
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/lsra.h
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,8 @@ class LinearScan : public LinearScanInterface
return getIntervalForLocalVar(varDsc->lvVarIndex);
}

RegRecord* getRegisterRecord(regNumber regNum);
RegRecord* getRegisterRecord(regNumber regNum);
SingleTypeRegSet getAvailableGPRsForType(SingleTypeRegSet candidates, var_types regType);

RefPosition* newRefPositionRaw(LsraLocation nodeLocation, GenTree* treeNode, RefType refType);

Expand Down
Loading