Skip to content

Commit 4ba3e09

Browse files
authored
JIT: hash lookup vn func before trying to optimize (#72576)
Always consult the func hash table before trying to optimize, and record the optimized result in the hash table. Also found a few more cases where we can defer work on a VN pair when the liberal and conservative VNs match.
1 parent f5469fe commit 4ba3e09

File tree

1 file changed

+72
-31
lines changed

1 file changed

+72
-31
lines changed

src/coreclr/jit/valuenum.cpp

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,28 +2071,38 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN)
20712071
assert(func != VNF_MemOpaque);
20722072
assert(arg0VN == VNNormalValue(arg0VN)); // Arguments don't carry exceptions.
20732073

2074-
// Try to perform constant-folding.
2075-
if (VNEvalCanFoldUnaryFunc(typ, func, arg0VN))
2076-
{
2077-
return EvalFuncForConstantArgs(typ, func, arg0VN);
2078-
}
2079-
2080-
ValueNum resultVN;
2074+
ValueNum resultVN = NoVN;
20812075

20822076
// Have we already assigned a ValueNum for 'func'('arg0VN') ?
2077+
//
20832078
VNDefFuncApp<1> fstruct(func, arg0VN);
2084-
if (!GetVNFunc1Map()->Lookup(fstruct, &resultVN))
2079+
if (GetVNFunc1Map()->Lookup(fstruct, &resultVN))
20852080
{
2081+
assert(resultVN != NoVN);
2082+
}
2083+
else
2084+
{
2085+
// Try to perform constant-folding.
2086+
//
2087+
if (VNEvalCanFoldUnaryFunc(typ, func, arg0VN))
2088+
{
2089+
resultVN = EvalFuncForConstantArgs(typ, func, arg0VN);
2090+
}
2091+
20862092
// Otherwise, Allocate a new ValueNum for 'func'('arg0VN')
20872093
//
2088-
Chunk* const c = GetAllocChunk(typ, CEA_Func1);
2089-
unsigned const offsetWithinChunk = c->AllocVN();
2090-
VNDefFuncAppFlexible* fapp = c->PointerToFuncApp(offsetWithinChunk, 1);
2091-
fapp->m_func = func;
2092-
fapp->m_args[0] = arg0VN;
2093-
resultVN = c->m_baseVN + offsetWithinChunk;
2094+
if (resultVN == NoVN)
2095+
{
2096+
Chunk* const c = GetAllocChunk(typ, CEA_Func1);
2097+
unsigned const offsetWithinChunk = c->AllocVN();
2098+
VNDefFuncAppFlexible* fapp = c->PointerToFuncApp(offsetWithinChunk, 1);
2099+
fapp->m_func = func;
2100+
fapp->m_args[0] = arg0VN;
2101+
resultVN = c->m_baseVN + offsetWithinChunk;
2102+
}
20942103

20952104
// Record 'resultVN' in the Func1Map
2105+
//
20962106
GetVNFunc1Map()->Set(fstruct, resultVN);
20972107
}
20982108
return resultVN;
@@ -2123,16 +2133,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
21232133
assert((VNFuncArity(func) == 0) || (VNFuncArity(func) == 2));
21242134
assert(func != VNF_MapSelect); // Precondition: use the special function VNForMapSelect defined for that.
21252135

2126-
ValueNum resultVN;
2127-
2128-
// When both operands are constants we can usually perform constant-folding,
2129-
// except if the expression will always throw an exception (constant VN-based
2130-
// propagation depends on that).
2131-
//
2132-
if (VNEvalCanFoldBinaryFunc(typ, func, arg0VN, arg1VN) && VNEvalShouldFold(typ, func, arg0VN, arg1VN))
2133-
{
2134-
return EvalFuncForConstantArgs(typ, func, arg0VN, arg1VN);
2135-
}
2136+
ValueNum resultVN = NoVN;
21362137

21372138
// We canonicalize commutative operations.
21382139
// (Perhaps should eventually handle associative/commutative [AC] ops -- but that gets complicated...)
@@ -2148,7 +2149,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
21482149
// Have we already assigned a ValueNum for 'func'('arg0VN','arg1VN') ?
21492150
//
21502151
VNDefFuncApp<2> fstruct(func, arg0VN, arg1VN);
2151-
if (!GetVNFunc2Map()->Lookup(fstruct, &resultVN))
2152+
if (GetVNFunc2Map()->Lookup(fstruct, &resultVN))
2153+
{
2154+
assert(resultVN != NoVN);
2155+
}
2156+
else
21522157
{
21532158
if (func == VNF_CastClass)
21542159
{
@@ -2159,10 +2164,27 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
21592164
}
21602165
else
21612166
{
2162-
resultVN = EvalUsingMathIdentity(typ, func, arg0VN, arg1VN);
2167+
// When both operands are constants we can usually perform constant-folding,
2168+
// except if the expression will always throw an exception (constant VN-based
2169+
// propagation depends on that).
2170+
//
2171+
bool folded = false;
2172+
if (VNEvalCanFoldBinaryFunc(typ, func, arg0VN, arg1VN) && VNEvalShouldFold(typ, func, arg0VN, arg1VN))
2173+
{
2174+
resultVN = EvalFuncForConstantArgs(typ, func, arg0VN, arg1VN);
2175+
}
2176+
2177+
if (resultVN != NoVN)
2178+
{
2179+
folded = true;
2180+
}
2181+
else
2182+
{
2183+
resultVN = EvalUsingMathIdentity(typ, func, arg0VN, arg1VN);
2184+
}
21632185

21642186
// Do we have a valid resultVN?
2165-
if ((resultVN == NoVN) || (genActualType(TypeOfVN(resultVN)) != genActualType(typ)))
2187+
if ((resultVN == NoVN) || (!folded && (genActualType(TypeOfVN(resultVN)) != genActualType(typ))))
21662188
{
21672189
// Otherwise, Allocate a new ValueNum for 'func'('arg0VN','arg1VN')
21682190
//
@@ -2173,10 +2195,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
21732195
fapp->m_args[0] = arg0VN;
21742196
fapp->m_args[1] = arg1VN;
21752197
resultVN = c->m_baseVN + offsetWithinChunk;
2176-
// Record 'resultVN' in the Func2Map
2177-
GetVNFunc2Map()->Set(fstruct, resultVN);
21782198
}
21792199
}
2200+
2201+
// Record 'resultVN' in the Func2Map
2202+
GetVNFunc2Map()->Set(fstruct, resultVN);
21802203
}
21812204
return resultVN;
21822205
}
@@ -9389,7 +9412,16 @@ ValueNumPair ValueNumStore::VNPairForCast(ValueNumPair srcVNPair,
93899412
ValueNum srcLibVN = srcVNPair.GetLiberal();
93909413
ValueNum srcConVN = srcVNPair.GetConservative();
93919414
ValueNum castLibVN = VNForCast(srcLibVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck);
9392-
ValueNum castConVN = VNForCast(srcConVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck);
9415+
ValueNum castConVN;
9416+
9417+
if (srcVNPair.BothEqual())
9418+
{
9419+
castConVN = castLibVN;
9420+
}
9421+
else
9422+
{
9423+
castConVN = VNForCast(srcConVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck);
9424+
}
93939425

93949426
return {castLibVN, castConVN};
93959427
}
@@ -9476,7 +9508,16 @@ ValueNumPair ValueNumStore::VNPairForBitCast(ValueNumPair srcVNPair, var_types c
94769508
ValueNum srcConVN = srcVNPair.GetConservative();
94779509

94789510
ValueNum bitCastLibVN = VNForBitCast(srcLibVN, castToType);
9479-
ValueNum bitCastConVN = VNForBitCast(srcConVN, castToType);
9511+
ValueNum bitCastConVN;
9512+
9513+
if (srcVNPair.BothEqual())
9514+
{
9515+
bitCastConVN = bitCastLibVN;
9516+
}
9517+
else
9518+
{
9519+
bitCastConVN = VNForBitCast(srcConVN, castToType);
9520+
}
94809521

94819522
return ValueNumPair(bitCastLibVN, bitCastConVN);
94829523
}

0 commit comments

Comments
 (0)