summaryrefslogtreecommitdiff
path: root/src/jit/liveness.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/liveness.cpp')
-rw-r--r--src/jit/liveness.cpp111
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).