未验证 提交 337999d5 编写于 作者: J Jakob Botsch Nielsen 提交者: GitHub

JIT: Handle some "field offset computation" patterns (#81998)

Both during local morph and during VN.

Fix #40021

Saves 3 KB on BasicMinimalApi after #84095 (there's 1111 __GetFieldHelper functions). About 0.04%. There's still a null check kept for each offset computation, which we cannot really get rid of, but NAOT could maybe emit the IL such that there is a dominating null check so that only one is emitted.

Example:
Base:
```
.managed:0000000140347CC0 loc_140347CC0:                          ; CODE XREF: S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey__System___Canon_____GetFieldHelper+23↑j
.managed:0000000140347CC0                                         ; DATA XREF: .rdata:__readonlydata_S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey__System___Canon_____GetFieldHelper↓o
.managed:0000000140347CC0                 lea     rax, ??_7Boxed_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey@@6B@ ; jumptable 0000000140347CB3 case 0
.managed:0000000140347CC7                 mov     [r9], rax
.managed:0000000140347CCA                 cmp     [rcx], cl
.managed:0000000140347CCC                 lea     rax, [rcx+8]
.managed:0000000140347CD0                 sub     rax, rcx
.managed:0000000140347CD3                 add     rsp, 8
.managed:0000000140347CD7                 retn
```
Diff:

```
.managed:0000000140347AA0 loc_140347AA0:                          ; CODE XREF: S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey__System___Canon_____GetFieldHelper+23↑j
.managed:0000000140347AA0                                         ; DATA XREF: .rdata:__readonlydata_S_P_CoreLib_System_Collections_Generic_KeyValuePair_2_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey__System___Canon_____GetFieldHelper↓o
.managed:0000000140347AA0                 lea     rax, ??_7Boxed_System_Net_Security_System_Net_Security_SslSessionsCache_SslCredKey@@6B@ ; jumptable 0000000140347A93 case 0
.managed:0000000140347AA7                 mov     [r9], rax
.managed:0000000140347AAA                 cmp     [rcx], cl
.managed:0000000140347AAC                 mov     eax, 8
.managed:0000000140347AB1                 add     rsp, 8
.managed:0000000140347AB5                 retn
```

Local morph changes handle the pattern for local structs -- VN changes handle the pattern for classes (and more complicated struct cases, like storing them in locals, which there are a few examples of in #40021).
上级 e0c94f84
......@@ -650,6 +650,34 @@ public:
PopValue();
break;
case GT_SUB:
{
Value& rhs = TopValue(0);
Value& lhs = TopValue(1);
if (m_compiler->opts.OptimizationEnabled() && lhs.IsAddress() && rhs.IsAddress() &&
(lhs.LclNum() == rhs.LclNum()) && (rhs.Offset() <= lhs.Offset()) &&
FitsIn<int>(lhs.Offset() - rhs.Offset()))
{
// TODO-Bug: Due to inlining we may end up with incorrectly typed SUB trees here.
assert(node->TypeIs(TYP_I_IMPL, TYP_BYREF));
ssize_t result = (ssize_t)(lhs.Offset() - rhs.Offset());
node->BashToConst(result, TYP_I_IMPL);
INDEBUG(lhs.Consume());
INDEBUG(rhs.Consume());
PopValue();
PopValue();
m_stmtModified = true;
break;
}
EscapeValue(TopValue(0), node);
PopValue();
EscapeValue(TopValue(0), node);
PopValue();
break;
}
case GT_FIELD_ADDR:
if (node->AsField()->IsInstance())
{
......
......@@ -4450,7 +4450,7 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN
// (x - 0) == x
// (x - x) == 0
// This identity does not apply for floating point (when x == -0.0).
auto identityForSubtraction = [=]() -> ValueNum {
auto identityForSubtraction = [=](bool ovf) -> ValueNum {
if (!varTypeIsFloating(typ))
{
ValueNum ZeroVN = VNZeroForType(typ);
......@@ -4462,6 +4462,39 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN
{
return ZeroVN;
}
if (!ovf)
{
// (x + a) - x == a
// (a + x) - x == a
VNFuncApp add;
if (GetVNFunc(arg0VN, &add) && (add.m_func == (VNFunc)GT_ADD))
{
if (add.m_args[0] == arg1VN)
return add.m_args[1];
if (add.m_args[1] == arg1VN)
return add.m_args[0];
// (x + a) - (x + b) == a - b
// (a + x) - (x + b) == a - b
// (x + a) - (b + x) == a - b
// (a + x) - (b + x) == a - b
VNFuncApp add2;
if (GetVNFunc(arg1VN, &add2) && (add2.m_func == (VNFunc)GT_ADD))
{
for (int a = 0; a < 2; a++)
{
for (int b = 0; b < 2; b++)
{
if (add.m_args[a] == add2.m_args[b])
{
return VNForFunc(typ, (VNFunc)GT_SUB, add.m_args[1 - a], add2.m_args[1 - b]);
}
}
}
}
}
}
}
return NoVN;
......@@ -4515,7 +4548,7 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN
break;
case GT_SUB:
resultVN = identityForSubtraction();
resultVN = identityForSubtraction(/* ovf */ false);
break;
case GT_MUL:
......@@ -4830,7 +4863,7 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN
case VNF_SUB_OVF:
case VNF_SUB_UN_OVF:
resultVN = identityForSubtraction();
resultVN = identityForSubtraction(/* ovf */ true);
break;
case VNF_MUL_OVF:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册