Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NativeAOT-LLVM: RyuJIT IR -> LLVM for improved performance #647

Merged
merged 50 commits into from
Mar 21, 2021

Conversation

yowl
Copy link
Contributor

@yowl yowl commented Feb 6, 2021

Some mucking around to try to get something that can be played with. Copied a lot of clrjit macros and code from xarch/amd64 and deleted/changed to get compilation to succeed and run at least as far as compiling the first method. This is my attempt to tackle #313 and may be total garbage. The clrjit does nothing at the moment exception assert(false) at the appropriate phase. In theory it should be possible to catch this and revert to CIL -> LLVM allowing tests to run at an early stage of playing while adding IR support.

yowl added 4 commits February 4, 2021 20:41
…orRunner}

>	clrjit_unix_x64_x64.dll!Compiler::getPrimitiveTypeForStruct(unsigned int structSize, CORINFO_CLASS_STRUCT_ * clsHnd, bool isVarArg) Line 723	C++

with

Run-Time Check Failure dotnet#2 - Stack around the variable 'gcPtr' was corrupted.
Wasm64 has some macros defined, but otherwise not compiled
Copied mostly from the xarch and AMD64 macros to get something to compile and run.
@yowl yowl changed the title Ryujit IR -> LLVM for improved performance RyuJIT IR -> LLVM for improved performance Feb 6, 2021
@jkotas
Copy link
Member

jkotas commented Feb 7, 2021

cc @EgorBo

//InstructionSet_SSE3 = 4,
//InstructionSet_SSSE3 = 5,
//InstructionSet_SSE41 = 6,
InstructionSet_SSE42 = 7,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not sound right that you have to define SSE2 and AVX2 for wasm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were getting used for the SIMD check

SIMDLevel getSIMDSupportLevel()
. Wasm can support SIMD, for c++ emscripten handles things. for LLVM I've not looked what might be necessary, but it would be good if the clrjit optimisation for SIMD that occurs before lowering, if any, was still in I suppose. For now this method is an assert for Wasm and these instructions in corinfoinstructionset.h are removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect Wasm to have its own wasm-specific names for SIMD levels, and not to reuse the x86/x64 ones. ARM does not reuse the x86/x64 ones either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. https://github.com/WebAssembly/simd isn't finalized yet, but when it is I'd expect we would look at introducing a new System.Runtime.Intrinsics.Wasm namespace and corresponding ISAs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -576,6 +576,10 @@ class emitter
#elif defined(TARGET_ARM64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeGen and emitter are late phases. They should be all replaced by the LLVM part. Is it possible to ifdef them out?

Copy link
Contributor Author

@yowl yowl Feb 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think I should be able #if out the Lowering class? https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/src/coreclr/jit/lower.h
Edit... I will go for removing it as well as the lsra code as that seems to make sense as at least the SIMPLE_LOWERING is a late phase and assume Lowering is part of that, or something later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have removed those + lsra + lower. There's a few places that require #ifdefs to allow compilation to succeed. In some places where I'm not sure what's best I've left the wasm build throwing an assert.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think inst* can be remove too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed.

yowl added 5 commits February 7, 2021 13:05
wasm compilation will now complete, although has an issue with the dbg instruction in Array Resize
Some code alerts false where not sure what to do.

Passes non-wasm tests locally.
Some code alerts false where not sure what to do.

Passes non-wasm tests locally.
@@ -735,7 +735,7 @@ class LinearScan : public LinearScanInterface
// Hence the "SmallFPSet" has 5 elements.
CLANG_FORMAT_COMMENT_ANCHOR;

#if defined(TARGET_AMD64)
#if defined(TARGET_AMD64) || defined(TARGET_WASM)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There changes should not be needed now that the whole file is ifdefed out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

// The constructor reads this value to skip iterations that could set it if it is already set.
compiler->codeGen->resetWritePhaseForFramePointerRequired();
#else
assert(false); // Wasm - TODO can this be ignored?
Copy link
Member

@jkotas jkotas Feb 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible to exclude the whole StackLevelSetter (it runs after lowering).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, yes, removed also.

@yowl
Copy link
Contributor Author

yowl commented Feb 10, 2021

@jkotas For the wasm build, I need to build the clrjit for the host platform, initially win64. The gen-buildsys script at the moment uses emcmake to configure the CMake system for emscripten, but I don't want that for clrjit. One thought I have is to just run the build twice, run build-runtime.cmd twice I suppose, once for wasm and once for the host, possibly disabling as much as possible on the host build so that just the jitinterface and clrjit is build. The other option which might be possible, it to use __BuildCrossArchNative but I'm not sure if this is really the intended use for that?

@jkotas
Copy link
Member

jkotas commented Feb 10, 2021

I am not sure which one of these options will turn out better. I think either one can work fine.

yowl added 3 commits February 13, 2021 10:55
…oment

attempt to add a second platform to the wasm yaml build
fix problem where Array<T>.Resize has its code compiled twice.
@yowl
Copy link
Contributor Author

yowl commented Feb 21, 2021

At

#define T_CONTEXT CONTEXT

It defines T_CONTEXT. For windows this comes from winnt.h in the SDK, but for Wasm what should I do here? It looks like its mostly registers, so would an empty

typedef struct DECLSPEC_ALIGN(16) DECLSPEC_NOINITALL _CONTEXT {
} CONTEXT, *PCONTEXT;

Be somewhere to start?

@jkotas
Copy link
Member

jkotas commented Feb 21, 2021

Yes, a dummy definitions like this sound like a good way to start. You can omit DECLSPEC_ALIGN(16).

This whole header should not be really included by the JIT (there are only a very few things - if any - needed by the JIT from this header), but refactoring to fix that may be too involved.

yowl added 4 commits February 27, 2021 15:38
May also need before including any LLVM header files:

#undef NumItems
…jit-llvm-imethodcodenode

# Conflicts:
#	src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
#	src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
#	src/coreclr/inc/icorjitinfoimpl_generated.h
#	src/coreclr/inc/jiteeversionguid.h
#	src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
#	src/coreclr/jit/instr.cpp
#	src/coreclr/jit/target.h
#	src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
#	src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
#	src/coreclr/tools/aot/ILCompiler.LLVM/Compiler/LLVMCodegenCompilation.cs
#	src/coreclr/tools/aot/ILCompiler.LLVM/Compiler/LLVMCodegenCompilationBuilder.cs
#	src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
#	src/coreclr/tools/aot/jitinterface/jitinterface.h

Workaround for min, max, and NumItems #defines.
@yowl yowl force-pushed the ryujit-llvm-imethodcodenode branch from 627c5b5 to 33a1b1a Compare March 15, 2021 22:20
yowl added 2 commits March 16, 2021 09:57
enable linking from publish
some refactor to allow the signature to be retrieved to create the externals for clrjit methods.
…jit-llvm-imethodcodenode

# Conflicts:
#	src/coreclr/tools/aot/ILCompiler.LLVM/CodeGen/ILToLLVMImporter.cs
@yowl
Copy link
Contributor Author

yowl commented Mar 16, 2021

@jkotas This has gotten pretty long in number of commits, especially the attempts to get the CI working, which I tried to squash, but must have failed. Do you want me to squash the whole lot?

Its ready for review now that the nuget package is working and the hard coded method is removed (it does 9 methods currently, which is all the nop;ret void that it encounters). I put in a bit of a temporary fudge in src\coreclr\nativeaot\BuildIntegration\Microsoft.NETCore.Native.targets to handle the fact that while coverage is brought to 100% there will be 2 native object files.

From here I was going to suggest that coverage of LIR is done in smaller PRs, each one adding to the % of method coverage.

@yowl yowl marked this pull request as ready for review March 16, 2021 17:27
Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pushing this forward!

docs/workflow/building/coreclr/nativeaot.md Outdated Show resolved Hide resolved
@@ -30,6 +30,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include "patchpointinfo.h"

/*****************************************************************************/
#endif //!TARGET_WASM

const BYTE genTypeSizes[] = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be nice to move this to compiler.cpp since they are declared in compiler.h/hpp

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This change can be pushed to dotnet/runtime as general goodness.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks,
If I've got this right at https://github.com/dotnet/runtimelab/pull/647/commits
/76fb9b5a3ffc78b4164526e4a4f706b4fac3cbe9 then I'll do the runtime PR

@@ -65,6 +65,8 @@
#define USE_UPPER_ADDRESS 0
#endif // !HOST_UNIX

#elif defined(TARGET_WASM)
#define USE_UPPER_ADDRESS 0 // TODO : what's this?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This controls how VM allocates memory for executable code. JIT should not really depend on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, have left it in, but updated the comment

#if defined(TARGET_WASM)
#include "llvm.h"
#else
// TODO: how to get different exports.def for the different clrjits?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround. It should be a method on the JIT/EE interface eventually that will make this problem go away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I handled the exports.def in the CMakeLists.txt so deleted this comment.

Llvm* llvm = new Llvm();
llvm->Compile(pCompiler);
delete llvm;
//assert(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//assert(false);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -3,7 +3,11 @@

#define GCS EA_GCREF
#define BRS EA_BYREF
#if defined(TARGET_WASM)
#define PS TARGET_POINTER_SIZE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be TARGET_POINTER_SIZE unconditionally

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, push to runtime?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that may be nice.

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be only called from codegen. None of it should be needed (or be reachable).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

@@ -173,6 +175,74 @@ public ILImporter(LLVMCodegenCompilation compilation, MethodDesc method, MethodI
_builder = Context.CreateBuilder();
}

// [DllImport(JitSupportLibrary)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, done, thanks

@@ -0,0 +1,200 @@
// // Licensed to the .NET Foundation under one or more agreements.
// // The .NET Foundation licenses this file to you under the MIT license.
//
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete? The whole file is commented out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

[UnmanagedCallersOnly]
public static byte* getMangledMethodName(IntPtr thisHandle, CORINFO_METHOD_STRUCT_* ftn)
{
//var _this = GetThis(thisHandle); // TODO: this doesn't work, but how does it cope anyway with this being moved by the GC?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but how does it cope anyway with this being moved by the GC?

The IntPtr points to stack location where CorInfoImpl reference is stored.

JIT/EE interface assumes that the JIT does not store the this pointer in a static. registerLlvmCallbacks stores the this pointer in a static. I suspect that it is why it does not work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation, have done something similar so this now works without the static.

yowl and others added 4 commits March 17, 2021 07:19
Co-authored-by: Jan Kotas <[email protected]>
- Remove unnecessary ifdefs
- Replace ifdefs with cmake exclusions
- Fix passing of corinfo
- remove some comments
@yowl
Copy link
Contributor Author

yowl commented Mar 21, 2021

Thanks @jkotas @SingleAccretion for the help.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

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.

6 participants