diff options
Diffstat (limited to 'src/jit/liveness.cpp')
-rw-r--r-- | src/jit/liveness.cpp | 111 |
1 files changed, 90 insertions, 21 deletions
diff --git a/src/jit/liveness.cpp b/src/jit/liveness.cpp index a541417d2b..432ac80065 100644 --- a/src/jit/liveness.cpp +++ b/src/jit/liveness.cpp @@ -1341,21 +1341,29 @@ void Compiler::fgLiveVarAnalysis(bool updateInternalOnly) #endif // DEBUG } -/***************************************************************************** - * - * Mark any variables in varSet1 as interfering with any variables - * specified in varSet2. - * We ensure that the interference graph is reflective: - * (if T11 interferes with T16, then T16 interferes with T11) - * returns true if an interference was added - * This function returns true if any new interferences were added - * and returns false if no new interference were added - */ +//------------------------------------------------------------------------ +// Compiler::fgMarkIntf: +// Mark any variables in varSet1 as interfering with any variables +// specified in varSet2. +// +// We ensure that the interference graph is reflective: if T_x +// interferes with T_y, then T_y interferes with T_x. +// +// Note that this function is a no-op when targeting the RyuJIT +// backend, as it does not require the interference graph. +// +// Arguments: +// varSet1 - The first set of variables. +// varSet2 - The second set of variables. +// +// Returns: +// True if any new interferences were recorded; false otherwise. +// bool Compiler::fgMarkIntf(VARSET_VALARG_TP varSet1, VARSET_VALARG_TP varSet2) { #ifdef LEGACY_BACKEND /* If either set has no bits set (or we are not optimizing), take an early out */ - if (VarSetOps::IsEmpty(this, varSet2) || VarSetOps::IsEmpty(this, varSet1) || opts.MinOpts()) + if (opts.MinOpts() || VarSetOps::IsEmpty(this, varSet2) || VarSetOps::IsEmpty(this, varSet1)) { return false; } @@ -1400,6 +1408,72 @@ bool Compiler::fgMarkIntf(VARSET_VALARG_TP varSet1, VARSET_VALARG_TP varSet2) #endif } +//------------------------------------------------------------------------ +// Compiler::fgMarkIntf: +// Mark any variables in varSet1 as interfering with the variable +// specified by varIndex. +// +// We ensure that the interference graph is reflective: if T_x +// interferes with T_y, then T_y interferes with T_x. +// +// Note that this function is a no-op when targeting the RyuJIT +// backend, as it does not require the interference graph. +// +// Arguments: +// varSet1 - The first set of variables. +// varIndex - The second variable. +// +// Returns: +// True if any new interferences were recorded; false otherwise. +// +bool Compiler::fgMarkIntf(VARSET_VALARG_TP varSet, unsigned varIndex) +{ +#ifdef LEGACY_BACKEND + // If the input set has no bits set (or we are not optimizing), take an early out + if (opts.MinOpts() || VarSetOps::IsEmpty(this, varSet)) + { + return false; + } + + bool addedIntf = false; // This is set to true if we add any new interferences + + VarSetOps::Assign(this, fgMarkIntfUnionVS, varSet); + VarSetOps::AddElemD(this, fgMarkIntfUnionVS, varIndex); + + VarSetOps::Iter iter(this, fgMarkIntfUnionVS); + unsigned refIndex = 0; + while (iter.NextElem(&refIndex)) + { + // if varSet has this bit set then it interferes with varIndex + if (VarSetOps::IsMember(this, varSet, refIndex)) + { + // Calculate the set of new interference to add + if (!VarSetOps::IsMember(this, lvaVarIntf[refIndex], varIndex)) + { + addedIntf = true; + VarSetOps::AddElemD(this, lvaVarIntf[refIndex], varIndex); + } + } + + // if this bit is the same as varIndex then it interferes with varSet1 + if (refIndex == varIndex) + { + // Calculate the set of new interference to add + VARSET_TP newIntf(VarSetOps::Diff(this, varSet, lvaVarIntf[refIndex])); + if (!VarSetOps::IsEmpty(this, newIntf)) + { + addedIntf = true; + VarSetOps::UnionD(this, lvaVarIntf[refIndex], newIntf); + } + } + } + + return addedIntf; +#else + return false; +#endif +} + /***************************************************************************** * * Mark any variables in varSet as interfering with each other, @@ -1521,13 +1595,10 @@ void Compiler::fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call) if (frameVarDsc->lvTracked) { - VARSET_TP varBit(VarSetOps::MakeSingleton(this, frameVarDsc->lvVarIndex)); - VarSetOps::AddElemD(this, life, frameVarDsc->lvVarIndex); - /* Record interference with other live variables */ - - fgMarkIntf(life, varBit); + // Record interference with other live variables + fgMarkIntf(life, frameVarDsc->lvVarIndex); } } } @@ -1572,9 +1643,7 @@ void Compiler::fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call) } // Record an interference with the other live variables - // - VARSET_TP varBit(VarSetOps::MakeSingleton(this, varIndex)); - fgMarkIntf(life, varBit); + fgMarkIntf(life, varIndex); } } @@ -1737,7 +1806,7 @@ bool Compiler::fgComputeLifeLocal(VARSET_TP& life, VARSET_VALARG_TP keepAliveVar printf("Ref V%02u,T%02u] at ", lclNum, varIndex); printTreeID(node); printf(" life %s -> %s\n", VarSetOps::ToString(this, life), - VarSetOps::ToString(this, VarSetOps::Union(this, life, varBit))); + VarSetOps::ToString(this, VarSetOps::AddElem(this, life, varIndex))); } #endif // DEBUG @@ -1747,7 +1816,7 @@ bool Compiler::fgComputeLifeLocal(VARSET_TP& life, VARSET_VALARG_TP keepAliveVar VarSetOps::AddElemD(this, life, varIndex); // Record interference with other live variables - fgMarkIntf(life, VarSetOps::MakeSingleton(this, varIndex)); + fgMarkIntf(life, varIndex); } } // Note that promoted implies not tracked (i.e. only the fields are tracked). |