Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NOP
Browse files Browse the repository at this point in the history
VSadov committed Mar 29, 2024
1 parent c77dbfb commit 3bda307
Showing 7 changed files with 50 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
@@ -502,9 +502,9 @@ void CodeGenInterface::genUpdateLife(GenTree* tree)
treeLifeUpdater->UpdateLife(tree);
}

void CodeGenInterface::genUpdateLife(VARSET_VALARG_TP newLife)
bool CodeGenInterface::genUpdateLife(VARSET_VALARG_TP newLife)
{
compiler->compUpdateLife</*ForCodeGen*/ true>(newLife);
return compiler->compUpdateLife</*ForCodeGen*/ true>(newLife);
}

// Return the register mask for the given register variable
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegeninterface.h
Original file line number Diff line number Diff line change
@@ -165,7 +165,7 @@ class CodeGenInterface
regMaskTP genGetRegMask(GenTree* tree);

void genUpdateLife(GenTree* tree);
void genUpdateLife(VARSET_VALARG_TP newLife);
bool genUpdateLife(VARSET_VALARG_TP newLife);

TreeLifeUpdater<true>* treeLifeUpdater;

13 changes: 12 additions & 1 deletion src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
@@ -194,7 +194,18 @@ void CodeGen::genCodeForBBlist()

// Updating variable liveness after last instruction of previous block was emitted
// and before first of the current block is emitted
genUpdateLife(block->bbLiveIn);
bool livenessChanged = genUpdateLife(block->bbLiveIn);

// if liveness has changed and the last block ended on emitting a call that can do GC,
// emit a nop to ensure that GC info is not changing between
// "call has been made" and "call has returned" states.
if (livenessChanged)
{
if (GetEmitter()->emitLastInsIsCallWithGC())
{
instGen(INS_nop);
}
}

// Even if liveness didn't change, we need to update the registers containing GC references.
// genUpdateLife will update the registers live due to liveness changes. But what about registers that didn't
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
@@ -8516,7 +8516,7 @@ class Compiler
// Update the GC's masks, register's masks and reports change on variable's homes given a set of
// current live variables if changes have happened since "compCurLife".
template <bool ForCodeGen>
inline void compUpdateLife(VARSET_VALARG_TP newLife);
inline bool compUpdateLife(VARSET_VALARG_TP newLife);

// Gets a register mask that represent the kill set for a helper call since
// not all JIT Helper calls follow the standard ABI on the target architecture.
5 changes: 4 additions & 1 deletion src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
@@ -3543,11 +3543,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// The set of live variables reflects the result of only emitted code, it should not be considering the becoming
// live/dead of instructions that has not been emitted yet. This is requires by "compChangeLife".
template <bool ForCodeGen>
inline void Compiler::compUpdateLife(VARSET_VALARG_TP newLife)
inline bool Compiler::compUpdateLife(VARSET_VALARG_TP newLife)
{
if (!VarSetOps::Equal(this, compCurLife, newLife))
{
compChangeLife<ForCodeGen>(newLife);
return true;
}
#ifdef DEBUG
else
@@ -3560,6 +3561,8 @@ inline void Compiler::compUpdateLife(VARSET_VALARG_TP newLife)
}
}
#endif // DEBUG

return false;
}

/*****************************************************************************
21 changes: 18 additions & 3 deletions src/coreclr/jit/emit.cpp
Original file line number Diff line number Diff line change
@@ -3640,8 +3640,9 @@ emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
instrDescCGCA* id;

id = emitAllocInstrCGCA(retSize);

id->idSetIsLargeCall();
id->idSetIsLargeCns();
id->idSetIsCall();
assert(id->idIsLargeCall());

VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
id->idcGcrefRegs = gcrefRegs;
@@ -3663,6 +3664,7 @@ emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,

/* Make sure we didn't waste space unexpectedly */
assert(!id->idIsLargeCns());
id->idSetIsCall();

#ifdef TARGET_XARCH
/* Store the displacement and make sure the value fit */
@@ -3720,7 +3722,9 @@ emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,

// printf("Direct call with GC vars / big arg cnt / explicit scope\n");

id->idSetIsLargeCall();
id->idSetIsLargeCns();
id->idSetIsCall();
assert(id->idIsLargeCall());

VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
id->idcGcrefRegs = gcrefRegs;
@@ -3742,6 +3746,7 @@ emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,

/* Make sure we didn't waste space unexpectedly */
assert(!id->idIsLargeCns());
id->idSetIsCall();

/* Save the live GC registers in the unused register fields */
assert((gcrefRegs & RBM_CALLEE_TRASH) == 0);
@@ -8763,6 +8768,16 @@ void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
emitThisGCrefVset = true;
}

/*****************************************************************************
*
* Last emitted instruction is a call that is not a NoGC call.
*/

bool emitter::emitLastInsIsCallWithGC()
{
return emitLastIns != nullptr && emitLastIns->idIsCall() && !emitLastIns->idIsNoGC();
}

/*****************************************************************************
*
* Record a call location for GC purposes (we know that this is a method that
17 changes: 12 additions & 5 deletions src/coreclr/jit/emit.h
Original file line number Diff line number Diff line change
@@ -766,7 +766,7 @@ class emitter
unsigned _idSmallDsc : 1; // is this a "small" descriptor?
unsigned _idLargeCns : 1; // does a large constant follow?
unsigned _idLargeDsp : 1; // does a large displacement follow?
unsigned _idLargeCall : 1; // large call descriptor used
unsigned _idCall : 1; // this is a call

// We have several pieces of information we need to encode but which are only applicable
// to a subset of instrDescs. To accommodate that, we define a several _idCustom# bitfields
@@ -1592,13 +1592,18 @@ class emitter
_idLargeDsp = 0;
}

bool idIsLargeCall() const
bool idIsCall() const
{
return _idCall != 0;
}
void idSetIsCall()
{
return _idLargeCall != 0;
_idCall = 1;
}
void idSetIsLargeCall()

bool idIsLargeCall() const
{
_idLargeCall = 1;
return idIsCall() && idIsLargeCns();
}

bool idIsBound() const
@@ -3196,6 +3201,8 @@ class emitter

void emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize);

bool emitLastInsIsCallWithGC();

// Helpers for the above

void emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count = 1);

0 comments on commit 3bda307

Please sign in to comment.