You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JIT: Improve interference checks for thrown exceptions and enable CSE/hoisting of GVM resolution helpers (#122017)
- Introduce `ExceptionSetFlags::UnknownException`. This special value
marks that an operation may throw an exception that we cannot say
anything about. Consumers of flags must be specially aware about this
exception type.
- Make `GenTree::OperExceptions` callable on all trees by changing
arbitrary user calls to return the new `UnknownException` type.
- Switch `OperMayThrow` to be literally `OperExceptions() != None`
- Enhance precision about exceptions thrown by helper calls. Instead of
just modelling "may throw" and "may not throw", we model the exact
exceptions a helper may throw via `ExceptionSetFlags`.
- Add helper call properties for `CORINFO_HELP_VIRTUAL_FUNC_PTR`,
`CORINFO_HELP_GVMLOOKUP_FOR_SLOT`,
`CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR`. These do not mutate the heap
and we use the new mechanism above to indicate that the only exception
they can throw is NRE. They are also pure, so add a VN function so VN
can model them. This allows us to CSE and hoist these helpers.
- Update `SideEffectSet` to track and precisely handle interference for
exceptions. We can now reorder two operations if we know they can only
throw the exact same exception.
- Generalize `OptimizeCallIndirectTargetEvaluation`; manual interference
handling is no longer necessary, and we can use it for all calls.
Example:
```csharp
public static void Test(Base b)
{
b.Foo<string>();
b.Foo<int>();
b.Foo<string>();
b.Foo<int>();
for (int i = 0; i < 10; i++)
b.Foo<double>();
}
public abstract class Base
{
public abstract void Foo<T>();
}
public class Derived : Base
{
public override void Foo<T>()
{
}
}
```
Before:
```asm
G_M7145_IG02:
mov rcx, rbx
mov rsi, 0xD1FFAB1E ; Program+Base
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
call rax
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
call rax
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
call rax
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
call rax
mov edi, 10
;; size=119 bbWeight=1 PerfScore 20.50
G_M7145_IG03:
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
call rax
dec edi
jne SHORT G_M7145_IG03
;; size=30 bbWeight=8 PerfScore 50.00
```
After:
```asm
G_M7145_IG02:
mov rcx, rbx
mov rsi, 0xD1FFAB1E ; Program+Base
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
mov rdi, rax
call rdi
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rcx, rbx
mov rbp, rax
call rbp
mov rcx, rbx
call rdi
mov rcx, rbx
call rbp
mov rcx, rbx
mov rdx, rsi
mov r8, 0xD1FFAB1E ; token handle
call CORINFO_HELP_VIRTUAL_FUNC_PTR
mov rsi, rax
mov edi, 10
;; size=107 bbWeight=1 PerfScore 19.50
G_M7145_IG03:
mov rcx, rbx
call rsi
dec edi
jne SHORT G_M7145_IG03
;; size=9 bbWeight=8 PerfScore 36.00
```
0 commit comments