@@ -504,7 +504,10 @@ void CodeGenInterface::genUpdateRegLife(const LclVarDsc* varDsc, bool isBorn, bo
504
504
}
505
505
else
506
506
{
507
- assert((regSet.GetMaskVars() & regMask) == 0);
507
+ // If this is going live, the register must not have a variable in it, except
508
+ // in the case of an exception variable, which may be already treated as live
509
+ // in the register.
510
+ assert(varDsc->lvLiveInOutOfHndlr || ((regSet.GetMaskVars() & regMask) == 0));
508
511
regSet.AddMaskVars(regMask);
509
512
}
510
513
}
@@ -681,12 +684,14 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
681
684
unsigned deadVarIndex = 0;
682
685
while (deadIter.NextElem(&deadVarIndex))
683
686
{
684
- unsigned varNum = lvaTrackedIndexToLclNum(deadVarIndex);
685
- LclVarDsc* varDsc = lvaGetDesc(varNum);
686
- bool isGCRef = (varDsc->TypeGet() == TYP_REF);
687
- bool isByRef = (varDsc->TypeGet() == TYP_BYREF);
687
+ unsigned varNum = lvaTrackedIndexToLclNum(deadVarIndex);
688
+ LclVarDsc* varDsc = lvaGetDesc(varNum);
689
+ bool isGCRef = (varDsc->TypeGet() == TYP_REF);
690
+ bool isByRef = (varDsc->TypeGet() == TYP_BYREF);
691
+ bool isInReg = varDsc->lvIsInReg();
692
+ bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr;
688
693
689
- if (varDsc->lvIsInReg() )
694
+ if (isInReg )
690
695
{
691
696
// TODO-Cleanup: Move the code from compUpdateLifeVar to genUpdateRegLife that updates the
692
697
// gc sets
@@ -701,8 +706,8 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
701
706
}
702
707
codeGen->genUpdateRegLife(varDsc, false /*isBorn*/, true /*isDying*/ DEBUGARG(nullptr));
703
708
}
704
- // This isn't in a register, so update the gcVarPtrSetCur .
705
- else if (isGCRef || isByRef)
709
+ // Update the gcVarPtrSetCur if it is in memory .
710
+ if (isInMemory && ( isGCRef || isByRef) )
706
711
{
707
712
VarSetOps::RemoveElemD(this, codeGen->gcInfo.gcVarPtrSetCur, deadVarIndex);
708
713
JITDUMP("\t\t\t\t\t\t\tV%02u becoming dead\n", varNum);
@@ -724,13 +729,18 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
724
729
725
730
if (varDsc->lvIsInReg())
726
731
{
727
- #ifdef DEBUG
728
- if (VarSetOps::IsMember(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex))
732
+ // If this variable is going live in a register, it is no longer live on the stack,
733
+ // unless it is an EH var, which always remains live on the stack.
734
+ if (!varDsc->lvLiveInOutOfHndlr)
729
735
{
730
- JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", varNum);
731
- }
736
+ #ifdef DEBUG
737
+ if (VarSetOps::IsMember(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex))
738
+ {
739
+ JITDUMP("\t\t\t\t\t\t\tRemoving V%02u from gcVarPtrSetCur\n", varNum);
740
+ }
732
741
#endif // DEBUG
733
- VarSetOps::RemoveElemD(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex);
742
+ VarSetOps::RemoveElemD(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex);
743
+ }
734
744
codeGen->genUpdateRegLife(varDsc, true /*isBorn*/, false /*isDying*/ DEBUGARG(nullptr));
735
745
regMaskTP regMask = varDsc->lvRegMask();
736
746
if (isGCRef)
@@ -742,9 +752,9 @@ void Compiler::compChangeLife(VARSET_VALARG_TP newLife)
742
752
codeGen->gcInfo.gcRegByrefSetCur |= regMask;
743
753
}
744
754
}
745
- // This isn't in a register, so update the gcVarPtrSetCur
746
755
else if (lvaIsGCTracked(varDsc))
747
756
{
757
+ // This isn't in a register, so update the gcVarPtrSetCur to show that it's live on the stack.
748
758
VarSetOps::AddElemD(this, codeGen->gcInfo.gcVarPtrSetCur, bornVarIndex);
749
759
JITDUMP("\t\t\t\t\t\t\tV%02u becoming live\n", varNum);
750
760
}
@@ -3269,6 +3279,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3269
3279
// 1 means the first part of a register argument
3270
3280
// 2, 3 or 4 means the second,third or fourth part of a multireg argument
3271
3281
bool stackArg; // true if the argument gets homed to the stack
3282
+ bool writeThru; // true if the argument gets homed to both stack and register
3272
3283
bool processed; // true after we've processed the argument (and it is in its final location)
3273
3284
bool circular; // true if this register participates in a circular dependency loop.
3274
3285
@@ -3605,6 +3616,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3605
3616
}
3606
3617
3607
3618
regArgTab[regArgNum + i].processed = false;
3619
+ regArgTab[regArgNum + i].writeThru = (varDsc->lvIsInReg() && varDsc->lvLiveInOutOfHndlr);
3608
3620
3609
3621
/* mark stack arguments since we will take care of those first */
3610
3622
regArgTab[regArgNum + i].stackArg = (varDsc->lvIsInReg()) ? false : true;
@@ -3765,9 +3777,9 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3765
3777
noway_assert(((regArgMaskLive & RBM_FLTARG_REGS) == 0) &&
3766
3778
"Homing of float argument registers with circular dependencies not implemented.");
3767
3779
3768
- /* Now move the arguments to their locations.
3769
- * First consider ones that go on the stack since they may
3770
- * free some registers. */
3780
+ // Now move the arguments to their locations.
3781
+ // First consider ones that go on the stack since they may free some registers.
3782
+ // Also home writeThru args, since they're also homed to the stack.
3771
3783
3772
3784
regArgMaskLive = regState->rsCalleeRegArgMaskLiveIn; // reset the live in to what it was at the start
3773
3785
for (argNum = 0; argNum < argMax; argNum++)
@@ -3805,7 +3817,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3805
3817
// If this arg is never on the stack, go to the next one.
3806
3818
if (varDsc->lvType == TYP_LONG)
3807
3819
{
3808
- if (regArgTab[argNum].slot == 1 && !regArgTab[argNum].stackArg)
3820
+ if (regArgTab[argNum].slot == 1 && !regArgTab[argNum].stackArg && !regArgTab[argNum].writeThru )
3809
3821
{
3810
3822
continue;
3811
3823
}
@@ -3839,7 +3851,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3839
3851
3840
3852
noway_assert(varDsc->lvIsParam);
3841
3853
noway_assert(varDsc->lvIsRegArg);
3842
- noway_assert(varDsc->lvIsInReg() == false ||
3854
+ noway_assert(varDsc->lvIsInReg() == false || varDsc->lvLiveInOutOfHndlr ||
3843
3855
(varDsc->lvType == TYP_LONG && varDsc->GetOtherReg() == REG_STK && regArgTab[argNum].slot == 2));
3844
3856
3845
3857
var_types storeType = TYP_UNDEF;
@@ -3906,13 +3918,17 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
3906
3918
#endif // USING_SCOPE_INFO
3907
3919
}
3908
3920
3909
- /* mark the argument as processed */
3910
-
3911
- regArgTab[argNum].processed = true;
3912
- regArgMaskLive &= ~genRegMask(srcRegNum);
3921
+ // Mark the argument as processed, and set it as no longer live in srcRegNum,
3922
+ // unless it is a writeThru var, in which case we home it to the stack, but
3923
+ // don't mark it as processed until below.
3924
+ if (!regArgTab[argNum].writeThru)
3925
+ {
3926
+ regArgTab[argNum].processed = true;
3927
+ regArgMaskLive &= ~genRegMask(srcRegNum);
3928
+ }
3913
3929
3914
3930
#if defined(TARGET_ARM)
3915
- if (storeType == TYP_DOUBLE)
3931
+ if (( storeType == TYP_DOUBLE) && !regArgTab[argNum].writeThru )
3916
3932
{
3917
3933
regArgTab[argNum + 1].processed = true;
3918
3934
regArgMaskLive &= ~genRegMask(REG_NEXT(srcRegNum));
@@ -4618,7 +4634,7 @@ void CodeGen::genCheckUseBlockInit()
4618
4634
{
4619
4635
if (!varDsc->lvRegister)
4620
4636
{
4621
- if (!varDsc->lvIsInReg())
4637
+ if (!varDsc->lvIsInReg() || varDsc->lvLiveInOutOfHndlr )
4622
4638
{
4623
4639
// Var is on the stack at entry.
4624
4640
initStkLclCnt +=
@@ -7233,7 +7249,9 @@ void CodeGen::genFnProlog()
7233
7249
continue;
7234
7250
}
7235
7251
7236
- if (varDsc->lvIsInReg())
7252
+ bool isInReg = varDsc->lvIsInReg();
7253
+ bool isInMemory = !isInReg || varDsc->lvLiveInOutOfHndlr;
7254
+ if (isInReg)
7237
7255
{
7238
7256
regMaskTP regMask = genRegMask(varDsc->GetRegNum());
7239
7257
if (!varDsc->IsFloatRegType())
@@ -7264,7 +7282,7 @@ void CodeGen::genFnProlog()
7264
7282
initFltRegs |= regMask;
7265
7283
}
7266
7284
}
7267
- else
7285
+ if (isInMemory)
7268
7286
{
7269
7287
INIT_STK:
7270
7288
0 commit comments