JIT: add pass to merge common throw helper calls (dotnet/coreclr#27113)
authorAndy Ayers <andya@microsoft.com>
Wed, 30 Oct 2019 16:58:06 +0000 (09:58 -0700)
committerGitHub <noreply@github.com>
Wed, 30 Oct 2019 16:58:06 +0000 (09:58 -0700)
commita6088891da73ef2bf813b6ef7c4587e1a30036b5
tree64547e9bbe5409993fc8d2d24917b55877d02e2a
parent6255177467ea39f9632a1360ed62251e38220e8b
JIT: add pass to merge common throw helper calls (dotnet/coreclr#27113)

Look for blocks with single statement noreturn calls, and try to reroute
flow so there's just one block call that all predecessors target.

Resolves dotnet/coreclr#14770.

Note this impairs debuggability of optimized code a bit, as it can change which
line of code apparently invokes a throw helper in a backtrace. But since we're
already commoning jit-inserted throw helpers (like array index OOB) this is not
breaking any new ground.

We could also handle commoning BBJ_THROW blocks, with some extra effort,
but prototyping indicates duplicate throws are pretty rare.

This phase runs just before `optOptimizeFlow`, so that we can leverage
the ref counts and predecessor lists to ensure we make correct flow updates.

It doesn't bother trying to clean out IR, that happens naturally as blocks
become unreferenced.

In some cases nothrow helpers end up being tail call candidates. We now suppress
tail calling noreturn methods if there is more than one such call site in the method,
hoping that instead we can merge the calls.

Commit migrated from https://github.com/dotnet/coreclr/commit/b962c97257400bee07805ccee66cd85d97195b40
src/coreclr/src/jit/compiler.cpp
src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/compmemkind.h
src/coreclr/src/jit/compphases.h
src/coreclr/src/jit/flowgraph.cpp
src/coreclr/src/jit/morph.cpp
src/coreclr/tests/src/JIT/opt/ThrowHelper/ThrowHelper.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/opt/ThrowHelper/ThrowHelper.csproj [new file with mode: 0644]