Skip to content

Commit 164d93a

Browse files
committed
JIT: Avoid reordering operands in fgMorphModToSubMulDiv
fgMorphModToSubMulDiv tries to check if it is ok to "clone" locals instead of spilling them by checking for address exposure. This was necessary because GTF_GLOB_REF is not up-to-date in preorder during morph, which is when this runs. However, address exposure is not valid for implicit byrefs at this point, so the check is not enough. The logic is trying to figure out which of the operands need to be spilled and which of them can be cloned. However, the logic was also wrong in the face of potential embedded assignments. Thus, rework it to be a bit more conservative but correct. As part of this, remove fgIsSafeToClone and make fgMakeMultiUse less conservative by avoiding checking for address exposure. This was probably an attempt at some limited interference checks, but from what I could see other uses do not need this. Fix dotnet#65118
1 parent 32d0360 commit 164d93a

File tree

2 files changed

+40
-43
lines changed

2 files changed

+40
-43
lines changed

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5506,7 +5506,6 @@ class Compiler
55065506
// Create a new temporary variable to hold the result of *ppTree,
55075507
// and transform the graph accordingly.
55085508
GenTree* fgInsertCommaFormTemp(GenTree** ppTree, CORINFO_CLASS_HANDLE structType = nullptr);
5509-
bool fgIsSafeToClone(GenTree* tree);
55105509
TempInfo fgMakeTemp(GenTree* rhs, CORINFO_CLASS_HANDLE structType = nullptr);
55115510
GenTree* fgMakeMultiUse(GenTree** ppTree, CORINFO_CLASS_HANDLE structType = nullptr);
55125511

src/coreclr/jit/morph.cpp

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,39 +1785,6 @@ void CallArgs::SetNeedsTemp(CallArg* arg)
17851785
m_needsTemps = true;
17861786
}
17871787

1788-
//------------------------------------------------------------------------------
1789-
// fgIsSafeToClone: If the node is an unaliased local or constant,
1790-
// then it is safe to clone.
1791-
//
1792-
// Arguments:
1793-
// tree - The node to check if it is safe to clone.
1794-
//
1795-
// Return Value:
1796-
// True if the tree is cloneable. False if the tree is not cloneable.
1797-
//
1798-
// Notes:
1799-
// This is conservative as this will return False if the local's address
1800-
// is exposed.
1801-
//
1802-
bool Compiler::fgIsSafeToClone(GenTree* tree)
1803-
{
1804-
if (tree->IsInvariant())
1805-
{
1806-
return true;
1807-
}
1808-
else if (tree->IsLocal())
1809-
{
1810-
// Can't rely on GTF_GLOB_REF here.
1811-
//
1812-
if (!lvaGetDesc(tree->AsLclVarCommon())->IsAddressExposed())
1813-
{
1814-
return true;
1815-
}
1816-
}
1817-
1818-
return false;
1819-
}
1820-
18211788
//------------------------------------------------------------------------------
18221789
// fgMakeTemp: Make a temp variable with a right-hand side expression as the assignment.
18231790
//
@@ -1865,16 +1832,16 @@ TempInfo Compiler::fgMakeTemp(GenTree* rhs, CORINFO_CLASS_HANDLE structType /*=
18651832
// A fresh GT_LCL_VAR node referencing the temp which has not been used
18661833
//
18671834
// Notes:
1868-
// Caller must ensure that if the node is an unaliased local, the second use this
1869-
// creates will be evaluated before the local can be reassigned.
1870-
//
1871-
// Can be safely called in morph preorder, before GTF_GLOB_REF is reliable.
1835+
// This function will clone invariant nodes and locals, so this function
1836+
// should only be used in situations where no interference between the
1837+
// original use and new use is possible. Otherwise, fgInsertCommaFormTemp
1838+
// should be used directly.
18721839
//
18731840
GenTree* Compiler::fgMakeMultiUse(GenTree** pOp, CORINFO_CLASS_HANDLE structType /*= nullptr*/)
18741841
{
18751842
GenTree* const tree = *pOp;
18761843

1877-
if (fgIsSafeToClone(tree))
1844+
if (tree->IsInvariant() || tree->OperIsLocal())
18781845
{
18791846
return gtClone(tree);
18801847
}
@@ -12922,7 +12889,15 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul)
1292212889
// math INTRINSICSs into calls...).
1292312890
if ((multiplierValue == 2.0) && (op1->IsLocal() || (fgOrder == FGOrderLinear)))
1292412891
{
12925-
op2 = fgMakeMultiUse(&op1);
12892+
if (op1->IsInvariant() || op1->IsLocal())
12893+
{
12894+
op2 = gtCloneExpr(op1);
12895+
}
12896+
else
12897+
{
12898+
op2 = fgInsertCommaFormTemp(&op1);
12899+
}
12900+
1292612901
GenTree* add = gtNewOperNode(GT_ADD, mul->TypeGet(), op1, op2);
1292712902
INDEBUG(add->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
1292812903

@@ -13816,20 +13791,43 @@ GenTree* Compiler::fgMorphModToSubMulDiv(GenTreeOp* tree)
1381613791

1381713792
GenTreeOp* const div = tree;
1381813793

13794+
assert(!div->IsReverseOp());
13795+
1381913796
GenTree* dividend = div->gtGetOp1();
1382013797
GenTree* divisor = div->gtGetOp2();
1382113798

13822-
TempInfo tempInfos[2]{};
13799+
TempInfo tempInfos[2];
1382313800
int tempInfoCount = 0;
1382413801

13825-
if (!fgIsSafeToClone(dividend))
13802+
// This transform runs in pre-morph so we cannot rely on GTF_GLOB_REF.
13803+
// Furthermore, this logic is somewhat complicated since the divisor and
13804+
// dividend are arbitrary nodes. For instance, if we spill the divisor and
13805+
// the dividend is a local, we need to spill the dividend too unless the
13806+
// divisor could not cause it to be reassigned.
13807+
// This could be slightly better via GTF_CALL and GTF_ASG checks on the
13808+
// divisor but the diffs of this were minor and the extra complexity seemed
13809+
// not worth it.
13810+
bool spillDividend;
13811+
bool spillDivisor;
13812+
if (divisor->IsInvariant() || divisor->OperIsLocal())
13813+
{
13814+
spillDivisor = false;
13815+
spillDividend = !dividend->IsInvariant() && !dividend->OperIsLocal();
13816+
}
13817+
else
13818+
{
13819+
spillDivisor = true;
13820+
spillDividend = !dividend->IsInvariant();
13821+
}
13822+
13823+
if (spillDividend)
1382613824
{
1382713825
tempInfos[tempInfoCount] = fgMakeTemp(dividend);
1382813826
dividend = tempInfos[tempInfoCount].load;
1382913827
tempInfoCount++;
1383013828
}
1383113829

13832-
if (!fgIsSafeToClone(divisor))
13830+
if (spillDivisor)
1383313831
{
1383413832
tempInfos[tempInfoCount] = fgMakeTemp(divisor);
1383513833
divisor = tempInfos[tempInfoCount].load;

0 commit comments

Comments
 (0)