Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
some fixes
  • Loading branch information
kunalspathak committed Jul 9, 2021
commit 62b1d57d7080dec6bbdd02abf475446dee407995
14 changes: 7 additions & 7 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ void CodeGenInterface::genUpdateRegLife(const LclVarDsc* varDsc, bool isBorn, bo
// If this is going live, the register must not have a variable in it, except
// in the case of an exception variable, which may be already treated as live
// in the register.
assert(varDsc->lvLiveInOutOfHndlr || ((regSet.GetMaskVars() & regMask) == 0));
assert(varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef || ((regSet.GetMaskVars() & regMask) == 0));
regSet.AddMaskVars(regMask);
}
}
Expand Down Expand Up @@ -736,7 +736,7 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
bool isGCRef = (varDsc->TypeGet() == TYP_REF);
bool isByRef = (varDsc->TypeGet() == TYP_BYREF);
bool isInReg = varDsc->lvIsInReg();
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr;
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef;

if (isInReg)
{
Expand Down Expand Up @@ -778,7 +778,7 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
{
// If this variable is going live in a register, it is no longer live on the stack,
// unless it is an EH var, which always remains live on the stack.
if (!varDsc->lvLiveInOutOfHndlr)
if (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSpillAtSingleDef)
{
#ifdef DEBUG
if (VarSetOps::IsMember(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex))
Expand Down Expand Up @@ -3704,7 +3704,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
}

regArgTab[regArgNum + i].processed = false;
regArgTab[regArgNum + i].writeThru = (varDsc->lvIsInReg() && varDsc->lvLiveInOutOfHndlr);
regArgTab[regArgNum + i].writeThru = (varDsc->lvIsInReg() && (varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef));

/* mark stack arguments since we will take care of those first */
regArgTab[regArgNum + i].stackArg = (varDsc->lvIsInReg()) ? false : true;
Expand Down Expand Up @@ -4762,7 +4762,7 @@ void CodeGen::genCheckUseBlockInit()
{
if (!varDsc->lvRegister)
{
if (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr)
if (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef)
{
// Var is on the stack at entry.
initStkLclCnt +=
Expand Down Expand Up @@ -7125,7 +7125,7 @@ void CodeGen::genFnProlog()
}

bool isInReg = varDsc->lvIsInReg();
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr;
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef;

// Note that 'lvIsInReg()' will only be accurate for variables that are actually live-in to
// the first block. This will include all possibly-uninitialized locals, whose liveness
Expand Down Expand Up @@ -11422,7 +11422,7 @@ void CodeGen::genMultiRegStoreToLocal(GenTreeLclVar* lclNode)
{
varReg = REG_STK;
}
if ((varReg == REG_STK) || fieldVarDsc->lvLiveInOutOfHndlr)
if ((varReg == REG_STK) || fieldVarDsc->lvLiveInOutOfHndlr || fieldVarDsc->lvSpillAtSingleDef)
{
if (!lclNode->AsLclVar()->IsLastUse(i))
{
Expand Down
22 changes: 16 additions & 6 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,16 @@ void CodeGen::genCodeForBBlist()

BasicBlock* block;

////////////
//compiler->opts.dspCode = true;
//compiler->opts.dspEHTable = true;
//compiler->opts.dspGCtbls = true;
//compiler->opts.disAsm2 = true;
//compiler->opts.dspUnwind = true;
//compiler->verbose = true;
//compiler->codeGen->setVerbose(true);
///////////

for (block = compiler->fgFirstBB; block != nullptr; block = block->bbNext)
{
#ifdef DEBUG
Expand Down Expand Up @@ -229,7 +239,7 @@ void CodeGen::genCodeForBBlist()
{
newRegByrefSet |= varDsc->lvRegMask();
}
if (!varDsc->lvLiveInOutOfHndlr)
if (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSpillAtSingleDef)
{
#ifdef DEBUG
if (verbose && VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex))
Expand All @@ -240,7 +250,7 @@ void CodeGen::genCodeForBBlist()
VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varIndex);
}
}
if ((!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr) && compiler->lvaIsGCTracked(varDsc))
if ((!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef) && compiler->lvaIsGCTracked(varDsc))
{
#ifdef DEBUG
if (verbose && !VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varIndex))
Expand Down Expand Up @@ -875,7 +885,7 @@ void CodeGen::genSpillVar(GenTree* tree)

// If this is a write-thru or a single-def variable, we don't actually spill at a use,
// but we will kill the var in the reg (below).
if (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSingleDefRegCandidate)
if (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSpillAtSingleDef)
{
instruction storeIns = ins_Store(lclType, compiler->isSIMDTypeLocalAligned(varNum));
assert(varDsc->GetRegNum() == tree->GetRegNum());
Expand Down Expand Up @@ -919,7 +929,7 @@ void CodeGen::genSpillVar(GenTree* tree)
else
{
// We only have 'GTF_SPILL' and 'GTF_SPILLED' on a def of a write-thru lclVar.
assert((varDsc->lvLiveInOutOfHndlr | varDsc->lvSingleDefRegCandidate) && ((tree->gtFlags & GTF_VAR_DEF) != 0));
assert((varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef) && ((tree->gtFlags & GTF_VAR_DEF) != 0));
}

#ifdef USING_VARIABLE_LIVE_RANGE
Expand Down Expand Up @@ -1055,7 +1065,7 @@ void CodeGen::genUnspillLocal(
}
#endif // USING_VARIABLE_LIVE_RANGE

if (!varDsc->lvLiveInOutOfHndlr)
if (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSpillAtSingleDef)
{
#ifdef DEBUG
if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
Expand Down Expand Up @@ -2049,7 +2059,7 @@ void CodeGen::genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclN
// spilled, i.e. write-thru).
// An EH var use is always valid on the stack (so we don't need to actually spill it),
// but the GTF_SPILL flag records the fact that the register value is going dead.
if (((lclNode->gtFlags & GTF_VAR_DEF) != 0) || !varDsc->lvLiveInOutOfHndlr)
if (((lclNode->gtFlags & GTF_VAR_DEF) != 0) || (!varDsc->lvLiveInOutOfHndlr && !varDsc->lvSpillAtSingleDef))
{
// Store local variable to its home location.
// Ensure that lclVar stores are typed correctly.
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ class LclVarDsc
// Currently, it is the criteria to decide if an EH variable can be
// a register candiate or not.

unsigned char lvSpillAtSingleDef : 1;

unsigned char lvDisqualifySingleDefRegCandidate : 1; // tracks variable that are disqualified from register
// candidancy

Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4117,6 +4117,7 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt,
bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0;
bool bbIsReturn = block->bbJumpKind == BBJ_RETURN;
bool needsExplicitZeroInit = fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn);
varDsc->lvSpillAtSingleDef = false;

if (varDsc->lvSingleDefRegCandidate || needsExplicitZeroInit)
{
Expand Down Expand Up @@ -4557,6 +4558,8 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers)
// count those in our heuristic for register allocation, since they always
// must be stored, so there's no value in enregistering them at defs; only
// if there are enough uses to justify it.
//
//TODO: May be applicable for single-def as well.
if (varDsc->lvLiveInOutOfHndlr && !varDsc->lvDoNotEnregister &&
((node->gtFlags & GTF_VAR_DEF) != 0))
{
Expand Down Expand Up @@ -7495,10 +7498,15 @@ void Compiler::lvaDumpEntry(unsigned lclNum, FrameLayoutState curState, size_t r
{
printf(" EH-live");
}
if (varDsc->lvSingleDef)
if (varDsc->lvSpillAtSingleDef)
{
printf(" spill-single-def");
}
else if (varDsc->lvSingleDefRegCandidate)
{
printf(" single-def");
}

#ifndef TARGET_64BIT
if (varDsc->lvStructDoubleAlign)
printf(" double-align");
Expand Down
15 changes: 10 additions & 5 deletions src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ BasicBlock::weight_t LinearScan::getWeight(RefPosition* refPos)
if (refPos->getInterval()->isSpilled)
{
// Decrease the weight if the interval has already been spilled.
if (varDsc->lvLiveInOutOfHndlr)
if (varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef)
{
// An EH var is always spilled at defs, and we'll decrease the weight by half,
// An EH-var/single-def is always spilled at defs, and we'll decrease the weight by half,
// since only the reload is needed.
weight = weight / 2;
}
Expand Down Expand Up @@ -1800,7 +1800,7 @@ void LinearScan::identifyCandidates()
if (varDsc->lvLiveInOutOfHndlr)
{
newInt->isWriteThru = varDsc->lvSingleDefRegCandidate;
setIntervalAsSpilled(newInt);
setIntervalAsSpilled(newInt); // TODO: Explore what happens if we mark interval as spilled right here.
}

INTRACK_STATS(regCandidateVarCount++);
Expand Down Expand Up @@ -6044,11 +6044,16 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreeLclVar* treeNode, Ref
{
treeNode->gtFlags |= GTF_SPILL;
treeNode->gtFlags |= GTF_SPILLED;


if (treeNode->IsMultiReg())
{
treeNode->SetRegSpillFlagByIdx(GTF_SPILLED, currentRefPosition->getMultiRegIdx());
}
}

// TODO: See if this can be outside the if-check.
varDsc->lvSpillAtSingleDef = true;
}
}

Expand Down Expand Up @@ -9714,12 +9719,12 @@ void LinearScan::dumpLsraAllocationEvent(

case LSRA_EVENT_DONE_KILL_GC_REFS:
dumpRefPositionShort(activeRefPosition, currentBlock);
printf("Done ");
printf("Done ");
break;

case LSRA_EVENT_NO_GC_KILLS:
dumpRefPositionShort(activeRefPosition, currentBlock);
printf("None ");
printf("None ");
break;

// Block boundaries
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17448,6 +17448,8 @@ void Compiler::fgRetypeImplicitByRefArgs()
newVarDsc->lvLclFieldExpr = varDsc->lvLclFieldExpr;
newVarDsc->lvVMNeedsStackAddr = varDsc->lvVMNeedsStackAddr;
newVarDsc->lvLiveInOutOfHndlr = varDsc->lvLiveInOutOfHndlr;
newVarDsc->lvSingleDefRegCandidate = varDsc->lvSingleDefRegCandidate;
newVarDsc->lvSpillAtSingleDef = varDsc->lvSpillAtSingleDef;
newVarDsc->lvLiveAcrossUCall = varDsc->lvLiveAcrossUCall;
#endif // DEBUG

Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/treelifeupdater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ bool TreeLifeUpdater<ForCodeGen>::UpdateLifeFieldVar(GenTreeLclVar* lclNode, uns
{
regNumber reg = lclNode->GetRegNumByIdx(multiRegIndex);
bool isInReg = fldVarDsc->lvIsInReg() && reg != REG_NA;
isInMemory = !isInReg || fldVarDsc->lvLiveInOutOfHndlr;
isInMemory = !isInReg || fldVarDsc->lvLiveInOutOfHndlr || fldVarDsc->lvSpillAtSingleDef;
if (isInReg)
{
if (isBorn)
Expand Down Expand Up @@ -259,7 +259,7 @@ void TreeLifeUpdater<ForCodeGen>::UpdateLifeVar(GenTree* tree)
compiler->codeGen->genUpdateVarReg(varDsc, tree);
}
bool isInReg = varDsc->lvIsInReg() && tree->GetRegNum() != REG_NA;
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr;
bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr || varDsc->lvSpillAtSingleDef;
if (isInReg)
{
compiler->codeGen->genUpdateRegLife(varDsc, isBorn, isDying DEBUGARG(tree));
Expand All @@ -283,7 +283,7 @@ void TreeLifeUpdater<ForCodeGen>::UpdateLifeVar(GenTree* tree)
unsigned fldVarIndex = fldVarDsc->lvVarIndex;
regNumber reg = lclVarTree->AsLclVar()->GetRegNumByIdx(i);
bool isInReg = fldVarDsc->lvIsInReg() && reg != REG_NA;
bool isInMemory = !isInReg || fldVarDsc->lvLiveInOutOfHndlr;
bool isInMemory = !isInReg || fldVarDsc->lvLiveInOutOfHndlr || fldVarDsc->lvSpillAtSingleDef;
bool isFieldDying = lclVarTree->AsLclVar()->IsLastUse(i);
if ((isBorn && !isFieldDying) || (!isBorn && isFieldDying))
{
Expand Down