Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@imhameed
Copy link
Contributor

@imhameed imhameed commented Feb 13, 2020

We currently reuse LLVM's command line parsing system to configure and
enable passes. When using the default code generator pass configuration,
the ImplicitNullChecks and X86CallFrameOptimization passes can only
be enabled or disabled via the command line argument parser: the
cl::opts controlling these (and many other) passes are private to
their translation units, and TargetPassConfig/X86PassConfig read
from these cl::opts with no other means to override these values.

Unfortunately, some LLVM command line options have restrictions on the
number of times they may be set, and running the LLVM command line
argument parser more than once can fail, because the 'number of
occurrences' counter is stored in each global cl::opt. This causes
several tests to fail--one such test is unhandled-exception-7.cs.

This change:

  • removes the lazy LLVM JIT initialization logic and instead
    runs this initialization once during mini_init,

  • moves some stray JIT-only code from mini-llvm.c to llvm-jit.cpp,

  • wraps the declarations in domain-internals.h with a
    G_BEGIN_DECLS/G_END_DECLS pair, so that they avoid name
    mangling when included in C++ source, and

  • removes exception_cb and emitted_cb: neither were actually used
    by live code.

We currently reuse LLVM's command line parsing system to configure and
enable passes. When using the default code generator pass configuration,
the `ImplicitNullChecks` and `X86CallFrameOptimization` passes can only
be enabled or disabled via the command line argument parser: the
`cl::opt`s controlling these (and many other) passes are private to
their translation units, and `TargetPassConfig`/`X86PassConfig` read
from these `cl::opt`s with no other means to override these values.

Unfortunately, some LLVM command line options have restrictions on the
number of times they may be set, and running the LLVM command line
argument parser more than once can fail, because the 'number of
occurrences' counter is stored in each global `cl::opt`. This causes
several tests to fail--one such test is unhandled-exception-7.cs.

This change:
- removes the lazy LLVM JIT initialization logic and instead
  runs this initialization once during `mini_init`,

- moves some stray JIT-only code from mini-llvm.c to llvm-jit.cpp,

- wraps the declarations in domain-internals.h with a
  `MONO_BEGIN_DECLS`/`MONO_END_DECLS` pair, so that they avoid name
  mangling when included in C++ source, and

- removes `exception_cb` and `emitted_cb`: neither were actually used
  by live code.
@vargaz
Copy link
Contributor

vargaz commented Feb 13, 2020

This will break the loaded llvm support, which is needed because a runtime with a statically linked llvm will take 100ms longer to start up even if llvm is not used.

@jaykrell
Copy link
Contributor

This will break the loaded llvm support, which is needed because a runtime with a statically linked llvm will take 100ms longer to start up even if llvm is not used.

Agreed, but someone should fix that 100ms.

@imhameed
Copy link
Contributor Author

This will break the loaded llvm support, which is needed because a runtime with a statically linked llvm will take 100ms longer to start up even if llvm is not used.

Loaded LLVM should still work: I updated mini-llvm-loaded.c and ran mono with loaded LLVM locally against some of the tests in mono/tests. The extra startup cost of LLVM, in a loaded LLVM mono, will continue to be paid exactly when mono_use_llvm is true and mono_llvm_load succeeds.

mono_llvm_create_ee/mono_llvm_jit_init takes a little under 1ms to run on my machine; this particular cost will have to be paid either at startup (when mono_use_llvm is true) or when first compiling a function with LLVM.

An argument in favor of preserving lazy initialization (with the necessary flag/test/lock/fence to ensure that it really does only execute once) is that, if we ever support a tiered JIT, this would allow us to avoid paying the LLVM JIT initialization cost on program runs that never have any functions advance to the LLVM tier. If that's preferable, I could do that instead.

@vargaz
Copy link
Contributor

vargaz commented Feb 13, 2020

@monojenkins build failed

llvm-jit.h is included in both C++ and C code.
@imhameed
Copy link
Contributor Author

imhameed commented Feb 13, 2020

RE loaded LLVM; just to verify, in a quick and dirty way, that I didn't make things worse, I just ran mono (with no command line arguments at all) on my computer with the CPU frequency locked to 1.2ghz. A copy of mono built without LLVM at all took 6ms to do nothing and print usage text. A copy of mono built with loaded LLVM also took 6ms to do this. A copy of mono built with statically linked LLVM took 19ms to do the same.

@vargaz
Copy link
Contributor

vargaz commented Feb 13, 2020

I can't reproduce the slowdown either any more, 10ms is ok. If this is the case, we could remove the whole loaded llvm mess as well.

@imhameed
Copy link
Contributor Author

@monojenkins build failed

@imhameed
Copy link
Contributor Author

@monojenkins build Linux i386

@imhameed imhameed merged commit 013e3c0 into mono:master Feb 15, 2020
imhameed added a commit to imhameed/mono that referenced this pull request Mar 5, 2020
Should fix mono#19115. This bug was
introduced in mono#18824, which
conditionally initalized an LLVM JIT-related TLS slot while preserving
unconditonal stores to that same slot.

The value stored in this TLS slot should only be used during JIT
compilation, so set/reset it in `mono_llvm_compile_method` instead of
during IR construction in `mono_llvm_emit_method`. No non-JIT code
should depend on the existence or presence of this TLS variable, so
remove `mono_llvm_jit_set_tls_cfg`.
monojenkins pushed a commit to monojenkins/runtime that referenced this pull request Mar 5, 2020
Should fix mono/mono#19115. This bug was
introduced in mono/mono#18824, which
conditionally initalized an LLVM JIT-related TLS slot while preserving
unconditonal stores to that same slot.

The value stored in this TLS slot should only be used during JIT
compilation, so set/reset it in `mono_llvm_compile_method` instead of
during IR construction in `mono_llvm_emit_method`. No non-JIT code
should depend on the existence or presence of this TLS variable, so
remove `mono_llvm_jit_set_tls_cfg`.
SamMonoRT added a commit that referenced this pull request Mar 5, 2020
Should fix #19115. This bug was
introduced in #18824, which
conditionally initalized an LLVM JIT-related TLS slot while preserving
unconditonal stores to that same slot.

The value stored in this TLS slot should only be used during JIT
compilation, so set/reset it in `mono_llvm_compile_method` instead of
during IR construction in `mono_llvm_emit_method`. No non-JIT code
should depend on the existence or presence of this TLS variable, so
remove `mono_llvm_jit_set_tls_cfg`.
SamMonoRT added a commit to dotnet/runtime that referenced this pull request Mar 5, 2020
Should fix mono/mono#19115. This bug was
introduced in mono/mono#18824, which
conditionally initalized an LLVM JIT-related TLS slot while preserving
unconditonal stores to that same slot.

The value stored in this TLS slot should only be used during JIT
compilation, so set/reset it in `mono_llvm_compile_method` instead of
during IR construction in `mono_llvm_emit_method`. No non-JIT code
should depend on the existence or presence of this TLS variable, so
remove `mono_llvm_jit_set_tls_cfg`.

Co-authored-by: imhameed <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants