From d4ec04ee91047d4eb82634bfad47ef54277d2409 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 10 Nov 2022 13:09:08 -0500 Subject: [PATCH] [mono][aot] Prefer concrete instances instead of gshared ones for methods containing type equality checks. For example, calls to Vector.IsSupported cannot be optimized away in a method where T is T_BYTE because its written as: ``` get => (typeof(T) == typeof(byte)) || (typeof(T) == typeof(double)) || ``` and T_BYTE could be instantiated with an enum whose basetype is byte. Fixes some of the issues in https://github.com/dotnet/runtime/issues/78163. --- src/mono/mono/mini/intrinsics.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index a2348e0f379fe..eaa0b333baa14 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -762,7 +762,7 @@ get_class_from_ldtoken_ins (MonoInst *ins) * their relation (EQ/NE/NONE). */ static CompRelation -get_rttype_ins_relation (MonoInst *ins1, MonoInst *ins2) +get_rttype_ins_relation (MonoInst *ins1, MonoInst *ins2, gboolean *vtype_constrained_gparam) { MonoClass *k1 = get_class_from_ldtoken_ins (ins1); MonoClass *k2 = get_class_from_ldtoken_ins (ins2); @@ -783,6 +783,7 @@ get_rttype_ins_relation (MonoInst *ins1, MonoInst *ins2) if (MONO_TYPE_IS_PRIMITIVE (t2) || MONO_TYPE_ISSTRUCT (t2)) rel = CMP_NE; } else if (MONO_TYPE_IS_PRIMITIVE (constraint1)) { + *vtype_constrained_gparam = TRUE; if (MONO_TYPE_IS_PRIMITIVE (t2) && constraint1->type != t2->type) rel = CMP_NE; else if (MONO_TYPE_IS_REFERENCE (t2)) @@ -1879,7 +1880,8 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } } else if (cmethod->klass == mono_defaults.systemtype_class && !strcmp (cmethod->name, "op_Equality") && args [0]->klass == mono_defaults.runtimetype_class && args [1]->klass == mono_defaults.runtimetype_class) { - CompRelation rel = get_rttype_ins_relation (args [0], args [1]); + gboolean vtype_constrained_gparam = FALSE; + CompRelation rel = get_rttype_ins_relation (args [0], args [1], &vtype_constrained_gparam); if (rel == CMP_EQ) { if (cfg->verbose_level > 2) printf ("-> true\n"); @@ -1894,11 +1896,16 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->dreg = alloc_preg (cfg); ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); + + /* Type checks in gshared methods like Vector.IsSupported can not be optimized away if the type is T_BYTE etc. */ + if (cfg->gshared && !cfg->gsharedvt && vtype_constrained_gparam) + cfg->prefer_instances = TRUE; } return ins; } else if (cmethod->klass == mono_defaults.systemtype_class && !strcmp (cmethod->name, "op_Inequality") && args [0]->klass == mono_defaults.runtimetype_class && args [1]->klass == mono_defaults.runtimetype_class) { - CompRelation rel = get_rttype_ins_relation (args [0], args [1]); + gboolean vtype_constrained_gparam = FALSE; + CompRelation rel = get_rttype_ins_relation (args [0], args [1], &vtype_constrained_gparam); if (rel == CMP_NE) { if (cfg->verbose_level > 2) printf ("-> true\n"); @@ -1913,6 +1920,9 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->dreg = alloc_preg (cfg); ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); + + if (cfg->gshared && !cfg->gsharedvt && vtype_constrained_gparam) + cfg->prefer_instances = TRUE; } return ins; } else if (cmethod->klass == mono_defaults.systemtype_class && !strcmp (cmethod->name, "get_IsValueType") &&