Skip to content

Commit

Permalink
[Mono]: Reduce Mono AOT cross compiler x64 memory footprint. (#97096)
Browse files Browse the repository at this point in the history
Building .net8 S.P.C using Mono AOT cross compiler in full AOT consumes
a large amount of memory (up to 6 GB). This is mainly due to generated
LLVM module not being optimized at all while kept in memory during
full module generation. Mono x64 also lacks support for several
intrinsics as well as Vector 256/512 that in turn leads to massive
inlining of intrinsics functions generating a very large LLVM module,
where majority of this code ends up as dead code due to
IsSupported/IsHardwareAccelerated returning false.

The follow commit adjusts several things that will bring down the
memory usage, compiling .net8/.net9 Mono S.P.C on x64 Windows
from 6 GB down to ~750 MB.

* Use PSNE implementations on intrinsics not supported on Mono.
* Add ILLinker substitutions for intrinsics not supported on Mono. Enables
ILLinker to do dead code elimination, reduce code to AOT compile.
* Prevent aggressive inlining for a couple of unsupported intrinsics types
making sure we don't end up with excessive inlining, exploding code size.
* Run a couple of LLVM optimization passes on each generated method doing
early code simplification and dead code elimination during LLVM module
generation.
* Explicit SN_get_IsHardwareAccelerated/SN_get_IsSupported intrinsics
implementation for all unsupported Mono x64 SIMD intrinsics.
* Fixed numerous memory leaks in Mono AOT cross compiler code.
* Fix a couple of sequence points free after use errors.
* Fix an anonymous struct build warning triggering build error for
LLVM enabled cross compiler on Windows.

---------

Co-authored-by: Zoltan Varga <vargaz@gmail.com>
  • Loading branch information
lateralusX and vargaz authored Feb 9, 2024
1 parent 3e9cce6 commit a79c62d
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2576,17 +2576,26 @@
</ItemGroup>
<ItemGroup Condition="'$(SupportsX86Intrinsics)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Aes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx2.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512BW.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512CD.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512DQ.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512F.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512Vbmi.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\AvxVnni.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx2.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx2.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512BW.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512BW.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512CD.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512CD.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512DQ.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512DQ.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512F.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512F.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512Vbmi.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx512Vbmi.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\AvxVnni.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\AvxVnni.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi2.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Fma.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Fma.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Fma.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Lzcnt.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Pclmulqdq.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Popcnt.cs" />
Expand All @@ -2597,7 +2606,8 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse42.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Ssse3.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\X86Base.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\X86Serialize.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\X86Serialize.cs" Condition="'$(FeatureMono)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\X86Serialize.PlatformNotSupported.cs" Condition="'$(FeatureMono)' == 'true'" />
</ItemGroup>
<ItemGroup Condition="'$(SupportsX86Intrinsics)' != 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Aes.PlatformNotSupported.cs" />
Expand Down
2 changes: 2 additions & 0 deletions src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@

<ILLinkSubstitutionsXmls Include="$(ILLinkDirectory)ILLink.Substitutions.$(Platform).xml" Condition="Exists('$(ILLinkDirectory)ILLink.Substitutions.$(Platform).xml')" />
<ILLinkSubstitutionsXmls Include="$(ILLinkDirectory)ILLink.Substitutions.iOS.xml" Condition="'$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true'" />
<ILLinkSubstitutionsXmls Include="$(ILLinkDirectory)ILLink.Substitutions.Intrinsics.x86.xml" />
<ILLinkSubstitutionsXmls Include="$(ILLinkDirectory)ILLink.Substitutions.Intrinsics.Vectors.xml" />

<ILLinkLinkAttributesXmls Include="$(ILLinkDirectory)ILLink.LinkAttributes.xml" />
<ILLinkLinkAttributesXmls Include="$(ILLinkDirectory)ILLink.LinkAttributes.$(Platform).xml" Condition="Exists('$(ILLinkDirectory)ILLink.LinkAttributes.$(Platform).xml')" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Runtime.Intrinsics.Vector256">
<method signature="System.Boolean get_IsHardwareAccelerated()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.Vector512">
<method signature="System.Boolean get_IsHardwareAccelerated()" body="stub" value="false" />
</type>
</assembly>
</linker>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Runtime.Intrinsics.X86.Avx">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx2">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx2/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512BW">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512BW/VL">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512BW/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512CD">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512CD/VL">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512CD/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512DQ">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512DQ/VL">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512DQ/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512F">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512F/VL">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512F/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512Vbmi">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512Vbmi/VL">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Avx512Vbmi/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.AvxVnni">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.AvxVnni/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Fma">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.Fma/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.X86Serialize">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
<type fullname="System.Runtime.Intrinsics.X86.X86Serialize/X64">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
</assembly>
</linker>
2 changes: 1 addition & 1 deletion src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -14229,7 +14229,7 @@ static void
acfg_free (MonoAotCompile *acfg)
{
#ifdef ENABLE_LLVM
if (acfg->aot_opts.llvm)
if (mono_use_llvm || acfg->aot_opts.llvm)
mono_llvm_free_aot_module ();
#endif

Expand Down
11 changes: 10 additions & 1 deletion src/mono/mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -4746,6 +4746,15 @@ mini_inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *
return inline_method (cfg, cmethod, fsig, sp, ip, real_offset, inline_always, NULL);
}

static gboolean
aggressive_inline_method (MonoMethod *cmethod)
{
gboolean aggressive_inline = m_method_is_aggressive_inlining (cmethod);
if (aggressive_inline)
aggressive_inline = !mono_simd_unsupported_aggressive_inline_intrinsic_type (cmethod);
return aggressive_inline;
}

/*
* inline_method:
*
Expand Down Expand Up @@ -4871,7 +4880,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
cfg->disable_inline = prev_disable_inline;
cfg->inline_depth --;

if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))) {
if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && aggressive_inline_method (cmethod))) {
if (cfg->verbose_level > 2)
printf ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));

Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -2962,6 +2962,7 @@ MonoInst* mono_emit_common_intrinsics (MonoCompile *cfg, MonoMethod *cmethod,
MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args);
MonoInst* mono_emit_simd_field_load (MonoCompile *cfg, MonoClassField *field, MonoInst *addr);
void mono_simd_intrinsics_init (void);
gboolean mono_simd_unsupported_aggressive_inline_intrinsic_type (MonoMethod *cmethod);

MonoMethod*
mini_method_to_shared (MonoMethod *method); // null if not shared
Expand Down
61 changes: 59 additions & 2 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,20 @@ create_class_instance (const char* name_space, const char *name, MonoType *param
return ivector_inst;
}

static gboolean
is_supported_vector_primitive_type (MonoType *type)
{
gboolean constrained_generic_param = (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);

if (constrained_generic_param && type->data.generic_param->gshared_constraint && MONO_TYPE_IS_VECTOR_PRIMITIVE (type->data.generic_param->gshared_constraint))
return TRUE;

if (MONO_TYPE_IS_VECTOR_PRIMITIVE (type))
return TRUE;

return FALSE;
}

static guint16 sri_vector_methods [] = {
SN_Abs,
SN_Add,
Expand Down Expand Up @@ -1423,8 +1437,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;

if (vector_size == 256 || vector_size == 512)
return NULL;
return NULL;

// FIXME: This limitation could be removed once everything here are supported by mini JIT on arm64
#ifdef TARGET_ARM64
if (!COMPILE_LLVM (cfg)) {
Expand Down Expand Up @@ -2477,6 +2491,12 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
g_free (name);
}

if (id == SN_get_IsSupported) {
MonoInst *ins;
EMIT_NEW_ICONST (cfg, ins, is_supported_vector_primitive_type (etype) ? 1 : 0);
return ins;
}

// Apart from filtering out non-primitive types this also filters out shared generic instance types like: T_BYTE which cannot be intrinsified
if (!MONO_TYPE_IS_VECTOR_PRIMITIVE (etype)) {
// Happens often in gshared code
Expand Down Expand Up @@ -3199,6 +3219,11 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
type = m_class_get_byval_arg (klass);
etype = mono_class_get_context (klass)->class_inst->type_argv [0];

if (id == SN_get_IsSupported) {
EMIT_NEW_ICONST (cfg, ins, is_supported_vector_primitive_type (etype) ? 1 : 0);
return ins;
}

if (!MONO_TYPE_IS_VECTOR_PRIMITIVE (etype))
return NULL;

Expand Down Expand Up @@ -6118,11 +6143,37 @@ mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *i
decompose_vtype_opt_store_arg (cfg, bb, ins, &(ins->dreg));
}
}

gboolean
mono_simd_unsupported_aggressive_inline_intrinsic_type (MonoMethod *cmethod)
{
/*
* If a method has been marked with aggressive inlining, check if we support
* aggressive inlining of the intrinsics type, if not, ignore aggressive inlining
* since it could end up inlining a large amount of code that most likely will end
* up as dead code.
*/
if (!strcmp (m_class_get_name_space (cmethod->klass), "System.Runtime.Intrinsics")) {
if (!strncmp(m_class_get_name (cmethod->klass), "Vector", 6)) {
const char *vector_type = m_class_get_name (cmethod->klass) + 6;
if (!strcmp(vector_type, "256`1") || !strcmp(vector_type, "512`1"))
return TRUE;
}
}
return FALSE;
}
#else
void
mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins)
{
}

gboolean
mono_simd_unsupported_aggressive_inline_intrinsic_type (MonoMethod* cmethod)
{
return FALSE;
}

#endif /*defined(TARGET_WIN32) && defined(TARGET_AMD64)*/

#endif /* DISABLE_JIT */
Expand Down Expand Up @@ -6157,6 +6208,12 @@ mono_simd_decompose_intrinsic (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *i
{
}

gboolean
mono_simd_unsupported_aggressive_inline_intrinsic_type (MonoMethod* cmethod)
{
return FALSE;
}

#endif /* MONO_ARCH_SIMD_INTRINSICS */

#if defined(TARGET_AMD64)
Expand Down

0 comments on commit a79c62d

Please sign in to comment.