Enable more hw intrinsics for AOT (mono/mono#17160)
authorEgor Bogatov <egorbo@gmail.com>
Fri, 11 Oct 2019 19:09:08 +0000 (22:09 +0300)
committerZoltan Varga <vargaz@gmail.com>
Fri, 11 Oct 2019 19:09:08 +0000 (15:09 -0400)
* Enable more hw intrinsics for AOT

* Address feedback

* does it fix the failure?

* fix loadedllvm

* Address feedback

* fix copy-paste

* forgot MONO_LLVM_INTERNAL

Commit migrated from https://github.com/mono/mono/commit/9cc5ea3862894a10d87a51e302893b0165e4850c

src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/intrinsics.c
src/mono/mono/mini/mini-amd64.c
src/mono/mono/mini/mini-llvm-loaded.c
src/mono/mono/mini/mini-llvm.h
src/mono/mono/mini/mini.c
src/mono/mono/mini/mini.h
src/mono/mono/mini/simd-intrinsics-netcore.c

index 54ccdce..3a8ce48 100644 (file)
@@ -8018,7 +8018,7 @@ parse_cpu_features (const gchar *attr)
        // TODO: neon, sha1, sha2, asimd, etc...
 #endif
 
-       if (!enabled)
+       if (enabled)
                mono_cpu_features_enabled = (MonoCPUFeatures) (mono_cpu_features_enabled | feature);
        else 
                mono_cpu_features_disabled = (MonoCPUFeatures) (mono_cpu_features_disabled | feature);
index a10fa51..f9b5eb3 100644 (file)
@@ -135,7 +135,7 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                opcode = OP_TRUNCF;
                        }
 #if defined(TARGET_X86) || defined(TARGET_AMD64)
-                       else if (!strcmp (cmethod->name, "Round") && !cfg->compile_aot && (mono_arch_cpu_enumerate_simd_versions () & SIMD_VERSION_SSE41)) {
+                       else if (!strcmp (cmethod->name, "Round") && (mini_get_cpu_features (cfg) & MONO_CPU_X86_SSE41) != 0) {
                                // special case: emit vroundps for MathF.Round directly instead of what llvm.round.f32 emits
                                // to align with CoreCLR behavior
                                int xreg = alloc_xreg (cfg);
index 28cac2a..cd3621c 100644 (file)
@@ -8737,7 +8737,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
                }
 #endif
 
-               if (!cfg->compile_aot && (mono_arch_cpu_enumerate_simd_versions () & SIMD_VERSION_SSE41) && fsig->param_count == 1 && fsig->params [0]->type == MONO_TYPE_R8) {
+               if ((mini_get_cpu_features (cfg) & MONO_CPU_X86_SSE41) != 0 && fsig->param_count == 1 && fsig->params [0]->type == MONO_TYPE_R8) {
                        int mode = -1;
                        if (!strcmp (cmethod->name, "Round"))
                                mode = 0;
index df15283..6b0e0df 100644 (file)
@@ -22,6 +22,7 @@ typedef struct {
        void (*emit_aot_data)(const char *symbol, guint8 *data, int data_len);
        void (*free_domain_info)(MonoDomain *domain);
        void (*create_vars)(MonoCompile *cfg);
+       MonoCPUFeatures (*get_cpu_features)(void);
 } LoadedBackend;
 
 static LoadedBackend backend;
@@ -136,6 +137,8 @@ mono_llvm_load (const char* bpath)
        if (err) goto symbol_error;
        err = mono_dl_symbol (llvm_lib, "mono_llvm_create_vars", (void**)&backend.create_vars);
        if (err) goto symbol_error;
+       err = mono_dl_symbol (llvm_lib, "mono_llvm_get_cpu_features", (void**)&backend.get_cpu_features);
+       if (err) goto symbol_error;
        return TRUE;
 symbol_error:
        g_warning ("llvm symbol load failed: %s\n", err);
@@ -143,6 +146,11 @@ symbol_error:
        return FALSE;
 }
 
+MonoCPUFeatures mono_llvm_get_cpu_features (void)
+{
+       return backend.get_cpu_features ();
+}
+
 #else
 
 int
index 6198167..e7df081 100644 (file)
@@ -35,6 +35,6 @@ void     mono_llvm_create_vars (MonoCompile *cfg) MONO_LLVM_INTERNAL;
 void     mono_llvm_fixup_aot_module         (void) MONO_LLVM_INTERNAL;
 
 gboolean mini_llvm_init                     (void);
-MonoCPUFeatures mono_llvm_get_cpu_features  (void);
+MonoCPUFeatures mono_llvm_get_cpu_features  (void) MONO_LLVM_INTERNAL;
 
 #endif
index 4d6cef6..5a8d9eb 100644 (file)
@@ -4301,3 +4301,25 @@ mono_target_pagesize (void)
         */
        return 4 * 1024;
 }
+
+MonoCPUFeatures
+mini_get_cpu_features (MonoCompile* cfg)
+{
+       MonoCPUFeatures features = (MonoCPUFeatures)0;
+#if !defined(MONO_CROSS_COMPILE)
+       if (!cfg->compile_aot || cfg->use_current_cpu) {
+               // detect current CPU features if we are in JIT mode or AOT with use_current_cpu flag.
+#if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
+               features = mono_llvm_get_cpu_features (); // llvm has a nice built-in API to detect features
+#elif defined(TARGET_AMD64)
+               features = mono_arch_get_cpu_features ();
+#endif
+       }
+#endif
+       MonoCPUFeatures features_ = features;
+
+       // apply parameters passed via -mattr
+       features = (MonoCPUFeatures) (features | mono_cpu_features_enabled);
+       features = (MonoCPUFeatures) (features & ~mono_cpu_features_disabled);
+       return features;
+}
index 8a77924..7305a8b 100644 (file)
@@ -2846,6 +2846,8 @@ typedef enum {
 #endif
 } MonoCPUFeatures;
 
+MonoCPUFeatures mini_get_cpu_features (MonoCompile* cfg);
+
 enum {
        SIMD_COMP_EQ,
        SIMD_COMP_LT,
index b474e77..072d3c5 100644 (file)
@@ -55,33 +55,12 @@ enum {
 
 static int register_size;
 
-static MonoCPUFeatures
-get_cpu_features (MonoCompile* cfg)
-{
-       MonoCPUFeatures features = (MonoCPUFeatures)0;
-#if !defined(MONO_CROSS_COMPILE)
-       if (!cfg->compile_aot || cfg->use_current_cpu) {
-               // detect current CPU features if we are in JIT mode or AOT with use_current_cpu flag.
-#if defined(ENABLE_LLVM)
-               features = mono_llvm_get_cpu_features (); // llvm has a nice built-in API to detect features
-#elif defined(TARGET_AMD64)
-               features = mono_arch_get_cpu_features ();
-#endif
-       }
-#endif
-
-       // apply parameters passed via -mattr
-       features = (MonoCPUFeatures) (features | mono_cpu_features_enabled);
-       features = (MonoCPUFeatures) (features & ~mono_cpu_features_disabled);
-       return features;
-}
-
 void
 mono_simd_intrinsics_init (void)
 {
        register_size = 16;
 #if FALSE
-       if ((get_cpu_features () & MONO_CPU_X86_AVX) != 0)
+       if ((mini_get_cpu_features () & MONO_CPU_X86_AVX) != 0)
                register_size = 32;
 #endif
        /* Tell the class init code the size of the System.Numerics.Register type */
@@ -596,7 +575,7 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature
                if (id == -1)
                        return NULL;
 
-               supported = (get_cpu_features (cfg) & MONO_CPU_X86_POPCNT) != 0;
+               supported = (mini_get_cpu_features (cfg) & MONO_CPU_X86_POPCNT) != 0;
                is_64bit = !strcmp (class_name, "X64");
 
                switch (id) {
@@ -622,7 +601,7 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature
                if (id == -1)
                        return NULL;
 
-               supported = (get_cpu_features (cfg) & MONO_CPU_X86_LZCNT) != 0;
+               supported = (mini_get_cpu_features (cfg) & MONO_CPU_X86_LZCNT) != 0;
                is_64bit = !strcmp (class_name, "X64");
 
                switch (id) {
@@ -649,7 +628,7 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature
                id = lookup_intrins (bmi1_methods, sizeof (bmi1_methods), cmethod);
 
                g_assert (id != -1);
-               supported = (get_cpu_features (cfg) & MONO_CPU_X86_BMI1) != 0;
+               supported = (mini_get_cpu_features (cfg) & MONO_CPU_X86_BMI1) != 0;
                is_64bit = !strcmp (class_name, "X64");
 
                switch (id) {
@@ -722,7 +701,7 @@ emit_x86_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature
                        return NULL;
                id = lookup_intrins (bmi2_methods, sizeof (bmi2_methods), cmethod);
                g_assert (id != -1);
-               supported = (get_cpu_features (cfg) & MONO_CPU_X86_BMI2) != 0;
+               supported = (mini_get_cpu_features (cfg) & MONO_CPU_X86_BMI2) != 0;
                is_64bit = !strcmp (class_name, "X64");
 
                switch (id) {
@@ -886,36 +865,26 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
        class_ns = m_class_get_name_space (cmethod->klass);
        class_name = m_class_get_name (cmethod->klass);
 
-#ifdef TARGET_AMD64 // TODO: test and enable for x86 too
        if (cmethod->klass->nested_in)
                class_ns = m_class_get_name_space (cmethod->klass->nested_in), class_name, cmethod->klass->nested_in;
+
+#ifdef TARGET_AMD64 // TODO: test and enable for x86 too
        if (!strcmp (class_ns, "System.Runtime.Intrinsics.X86"))
                return emit_x86_intrinsics (cfg ,cmethod, fsig, args);
 #endif
 
        if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
                if (!strcmp (class_name, "Vector128`1"))
-                       return emit_vector128_t (cfg ,cmethod, fsig, args);
+                       return emit_vector128_t (cfgcmethod, fsig, args);
                if (!strcmp (class_name, "Vector256`1"))
-               return emit_vector256_t (cfg ,cmethod, fsig, args);
+                       return emit_vector256_t (cfg, cmethod, fsig, args);
        }
 
-       // FIXME: Make sure get_cpu_features is used where needed
-       if (cfg->compile_aot)
-               return NULL;
-       if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector")) {
-               MonoInst *ins = emit_sys_numerics_vector (cfg, cmethod, fsig, args);
-               if (!ins) {
-                       //printf ("M: %s %s\n", mono_method_get_full_name (cfg->method), mono_method_get_full_name (cmethod));
-               }
-               return ins;
-       }
-       if (!strcmp (class_ns, "System.Numerics") && !strcmp (class_name, "Vector`1")) {
-               MonoInst *ins = emit_sys_numerics_vector_t (cfg, cmethod, fsig, args);
-               if (!ins) {
-                       //printf ("M: %s %s\n", mono_method_get_full_name (cfg->method), mono_method_get_full_name (cmethod));
-               }
-               return ins;
+       if (!strcmp (class_ns, "System.Numerics")) {
+               if (!strcmp (class_name, "Vector"))
+                       return emit_sys_numerics_vector (cfg, cmethod, fsig, args);
+               if (!strcmp (class_name, "Vector`1"))
+                       return emit_sys_numerics_vector_t (cfg, cmethod, fsig, args);
        }
 
        return NULL;