-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone
Description
(Note this is milestoned as Future on purpose - none of this is blocking.)
A couple relatively low hanging optimization opportunities in the JIT space.
- Enable loop alignment
Loop alignment seems to have some pretty nice benefits. NativeAOT/crossgen2 will already respect requests to align at 32-byte boundaries (Add support in crossgen2 for 32-byte alignment #32602), but RyuJIT never requests that for prejit. RyuJIT seems to also have assumptions that the code buffer to write instructions into is 32-byte aligned. It's a managedbyte[]in our AOT compilers and it's hard to align that. RyuJIT should ideally count bytes from the beginning of the buffer. - Optimize static field access
Static fields always go through a helper call. It can be done better. Improve static field access for NativeAOT #63620 is a WIP pull request. I don't know when I'll get back to it.- non-GC fields - NativeAOT: avoid helper calls for static fields #79709
- GC fields - NativeAOT: Optimize static fields of gc types #80969
- Optimize class constructor checks - NativeAOT: Inline static initialization checks in codegen #80954
If there's a static constructor, the EE side will ask RyuJIT to run the class constructor check (CORINFO_INITCLASS_USE_HELPER). This is a helper call that checks whether the class constructor already ran and if not, runs it. The helper looks like this:. We could inline the fast path into RyuJIT codegen (compare a dereferenced IConHandle with 1 and if they're equal, the cctor already executed and we can move on). This would probably require a new JitInteface method that provides info about lookup for the IConHandle and lookup for the helper to call if the IConHandle is not 1. There already is a pull request that does pretty much that: RyuJIT: Inlined "is class statically inited" check #47901. We need to revive it for NativeAOT.Lines 58 to 66 in 74d8d0d
// We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region. encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeNonGCStaticsSymbol(target), -NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)); AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg0, null, factory.Target.PointerSize, 0, AddrModeSize.Int32); encoder.EmitCMP(ref initialized, 1); encoder.EmitRETIfEqual(); encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result); encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase)); - Optimize thread static field access [NativeAOT] Inline access to thread statics #79521
Emit the platform-specific native sequence to access thread statics inline instead of calling a helper. - Reading preinitialized data JIT: import static readonly fields holding frozen objects as const handles #76112
NativeAOT can run static constructors at compile time and provide values ofreadonly staticfields. RyuJIT can already consume that (see code aroundCORINFO_FLG_FIELD_FINAL), but in doing so it assumes the address returned fromgetFieldAddressis an actual address that can be dereferenced. It's a handle when precompiling. We would want to introduce a proper JitInterface API for this. The static data preinitializer can return more than just primitive types - we could also make this work for reference types (we can return a handle that points to an object in the frozen data segment). Might be better to look into this after "Optimize static field access" above is done. - Devirtualization
The compiler driver has a pretty good idea of what types will be allocated over the lifetime of the app. It can provide answers to questions such as "what are all the types that could implement this interface". This can be used to drive devirtualization. Some of it doesn't really even have to be guarded (there might only be a single possibility, for example).- Interface calls with single implementations NativeAOT: Guarded devirtualization #64497
- isinst/castclass against interface/classes with single implementation - NativeAOT: devirtualize isinst/castclass for monomorphic cases #80831
- Abstract classes with single implementations
- Guarded devirtualization with multiple guesses without fallback (e.g. an interface has two implementations) - Guarded devirtualization: multiple type checks #86551
- General optimizations
Cc @EgorBo - might be in your area of interest
category:cq
theme:ready-to-run
skill-level:expert
cost:medium
impact:medium
omariom, rgwood, EgorBo, MichalPetryka, hez2010 and 3 more
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Type
Projects
Status
Done