Skip to content

Commit

Permalink
[mono][interp] Fix short branches (dotnet#58806)
Browse files Browse the repository at this point in the history
* [interp] Fix short branches

In interp, long branches have 4 byte signed offset while short branches have a 2 byte signed offset. Ideally we would want to always emit short branches if possible due to improved performance. The problem is that we emit a short or long branch early in the codegen process, there is no way to know whether a branch is long or short at that time and no further computations were done later to determine whether the branch is really long or short.  Before this commit we arbitrarily decided that all branches in methods with IL size of less than 25000 are short and, in some cases, completely ignored that long branches actually happen in practice.

This commit makes it such that we always emit long opcodes at the beginning of the codegen process, also serving as a simplification since optimizations operating on IR code don't need to care about both short and long versions of branches. Later on, we will end up converting all these long branches to short branches when emitting the final method code. We achieve this by doing a quick preliminary code iteration and computing conservative native offsets (assuming all branches are long). Since the final code will be equal in size or smaller, we have the guarantee that if a branch is short between the conservative offsets, it will surely be short also in the final code. With this approach we guarantee correctness and we can fail to shorten only a negligible amount of branches.

Since the super instruction pass generates some branching instructions that are supported only for the short version, we need to run a computation of conservative offsets beforehand.

* Re-enable test suite
  • Loading branch information
BrzVlad authored Oct 12, 2021
1 parent df42364 commit 383a479
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace System.CodeDom.Compiler.Tests
{
[ActiveIssue("https://github.com/dotnet/runtime/issues/57363", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter))]
public class CSharpCodeGeneratorTests
{
private static IEnumerable<string> Identifier_TestData()
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/mini/interp/mintops.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ typedef enum {

#define MINT_SWITCH_LEN(n) (4 + (n) * 2)

#define MINT_IS_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DUMMY_USE || (op) == MINT_IL_SEQ_POINT)
#define MINT_IS_MOV(op) ((op) >= MINT_MOV_I1 && (op) <= MINT_MOV_VT)
#define MINT_IS_UNCONDITIONAL_BRANCH(op) ((op) >= MINT_BR && (op) <= MINT_CALL_HANDLER_S)
#define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8_S)
#define MINT_IS_UNOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BRTRUE_R8_S)
#define MINT_IS_BINOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BEQ_I4 && (op) <= MINT_BLT_UN_R8_S)
#define MINT_IS_SUPER_BRANCH(op) ((op) >= MINT_BRFALSE_I4_SP && (op) <= MINT_BLT_UN_I8_IMM_SP)
#define MINT_IS_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_JIT_CALL)
#define MINT_IS_PATCHABLE_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_VCALL)
#define MINT_IS_LDC_I4(op) ((op) >= MINT_LDC_I4_M1 && (op) <= MINT_LDC_I4)
Expand Down
Loading

0 comments on commit 383a479

Please sign in to comment.