dotnet10.0/SOURCES/runtime-118376-z13-simd.patch
2025-11-19 07:28:16 +00:00

658 lines
27 KiB
Diff

From 97f2fb6ab2988c03917a937cc1552356ff5f7069 Mon Sep 17 00:00:00 2001
From: saitama951 <sanjamkumar360@gmail.com>
Date: Tue, 5 Aug 2025 07:12:13 +0000
Subject: [PATCH 1/4] [S390X] Add simd fallback support for unsupported s390x
architectures
Vector facility was introduced in the z13, which majorly
introduces vector int/short/long/double variants of the
vector instructions. with the release of z14 we introduced
vector float variant as part of vector enhancement facility 1.
This patch majorly supports z13 and previous generations.
---
src/mono/mono/mini/simd-intrinsics.c | 113 +++++++++++++++++++++++--
src/mono/mono/utils/mono-hwcap-s390x.c | 1 +
src/mono/mono/utils/mono-hwcap-vars.h | 1 +
3 files changed, 109 insertions(+), 6 deletions(-)
diff --git a/src/runtime/src/mono/mono/mini/simd-intrinsics.c b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
index 88143637310ef9..b8f78487cd85e6 100644
--- a/src/runtime/src/mono/mono/mini/simd-intrinsics.c
+++ b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
@@ -2112,6 +2112,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
}
#elif defined(TARGET_S390X)
if (type_enum_is_float(arg0_type)) {
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_S390_VFLPDB : OP_S390_VFLPSB, -1, arg0_type, fsig, args);
} else {
return emit_simd_ins_for_sig (cfg, klass, OP_VECTOR_IABS, -1, arg0_type, fsig, args);
@@ -2135,11 +2137,17 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
if (!is_element_type_primitive (fsig->params [0]) || !is_element_type_primitive (fsig->params [1]))
return NULL;
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative) || (id !=SN_Xor) || (id != SN_BitwiseAnd) || (id != SN_BitwiseOr)) && arg0_type == MONO_TYPE_R4)
+ return NULL;
+#endif
+
#if !defined(TARGET_ARM64) && !defined(TARGET_S390X)
if (((id == SN_Max) || (id == SN_Min)) && type_enum_is_float(arg0_type))
return NULL;
#endif
+
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Divide: {
@@ -2149,7 +2157,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
if (!is_element_type_primitive (fsig->params [0]) ||
!(MONO_TYPE_IS_VECTOR_PRIMITIVE (fsig->params [1]) || is_element_type_primitive (fsig->params [1])))
return NULL;
-
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Multiply: {
@@ -2170,7 +2181,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
} else if (!(is_element_type_primitive (fsig->params [0]) && is_element_type_primitive (fsig->params [1])))
return NULL;
-
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (vector_inner_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, vector_inner_type, id);
}
case SN_AndNot: {
@@ -2198,13 +2212,17 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
int add_op;
if (type_enum_is_float (arg0_type)) {
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
mul_op = OP_FMUL;
add_op = OP_FADD;
} else {
mul_op = OP_IMUL;
add_op = OP_IADD;
-#ifdef TARGET_ARM64
+#if defined(TARGET_ARM64) || defined(TARGET_S390X)
if (!COMPILE_LLVM (cfg) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8 || arg0_type == MONO_TYPE_I || arg0_type == MONO_TYPE_U))
return NULL;
#endif
@@ -2274,6 +2292,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
int ceil_or_floor = id == SN_Ceiling ? 10 : 9;
return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_ROUNDP, ceil_or_floor, arg0_type, fsig, args);
#elif defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
int ceil_or_floor = id == SN_Ceiling ? 6 : 7;
switch (arg0_type){
case MONO_TYPE_R4:
@@ -2464,6 +2484,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return emit_vector_create_scalar (cfg, vklass, etype, args [0], is_unsafe);
}
case SN_Dot: {
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_dot (cfg, klass, fsig->params [0], arg0_type, args [0]->dreg, args [1]->dreg);
}
case SN_Equals:
@@ -2472,6 +2496,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
if (id == SN_Equals)
return emit_xcompare (cfg, klass, arg0_type, args [0], args [1]);
@@ -2733,7 +2761,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
case SN_LessThanOrEqual: {
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
-
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_xcompare_for_intrinsic (cfg, klass, id, arg0_type, args [0], args [1]);
}
case SN_GreaterThanAll:
@@ -2750,7 +2781,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
g_assert (fsig->param_count == 2 &&
fsig->ret->type == MONO_TYPE_BOOLEAN &&
mono_metadata_type_equal (fsig->params [0], fsig->params [1]));
-
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
gboolean is_all = FALSE;
switch (id) {
case SN_GreaterThanAll:
@@ -2857,6 +2891,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
if (!type_enum_is_float(arg0_type))
return emit_xzero (cfg, klass);
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
int op = -1;
#if defined(TARGET_ARM64) || defined(TARGET_AMD64) || defined(TARGET_WASM) || defined(TARGET_S390X)
op = OP_ONES_COMPLEMENT;
@@ -2879,7 +2917,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return emit_xones (cfg, klass);
}
}
-
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
MonoInst *arg0 = args [0];
MonoClass *op_klass = klass;
@@ -2907,6 +2948,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
case SN_IsPositiveInfinity: {
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
if (arg0_type == MONO_TYPE_R4) {
guint32 value[4];
@@ -2984,6 +3029,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
case SN_IsZero: {
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_xcompare (cfg, klass, arg0_type, args [0], emit_xzero (cfg, klass));
}
case SN_Narrow: {
@@ -3129,7 +3178,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
case SN_OnesComplement: {
if (!is_element_type_primitive (fsig->params [0]))
return NULL;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (id == SN_Negate) && (arg0_type == MONO_TYPE_R4))
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
+#endif
}
case SN_Shuffle: {
MonoType *etype = get_vector_t_elem_type (fsig->ret);
@@ -3295,6 +3347,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X, instc0, arg0_type, fsig, args);
#elif defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+
int instc0 = arg0_type == MONO_TYPE_R4 ? OP_S390_VFSQSB : OP_S390_VFSQDB;
return emit_simd_ins_for_sig (cfg, klass, instc0, 0, arg0_type, fsig, args);
#else
@@ -3792,6 +3847,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
if (fsig->param_count != 2 )
return NULL;
arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && ((id !=SN_op_ExclusiveOr) || (id != SN_op_BitwiseAnd) || (id != SN_op_BitwiseOr)) && arg0_type == MONO_TYPE_R4)
+ return NULL;
+#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
}
@@ -3800,6 +3859,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
if (fsig->param_count != 2 )
return NULL;
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
switch (id) {
case SN_op_Equality: return emit_xequal (cfg, arg_class, arg0_type, args [0], args [1]);
case SN_op_Inequality: return emit_not_xequal (cfg, arg_class, arg0_type, args [0], args [1]);
@@ -3810,6 +3873,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
case SN_op_UnaryNegation:
if (fsig->param_count != 1 )
return NULL;
+#if defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1 && (id == SN_op_UnaryNegation) && (arg0_type == MONO_TYPE_R4))
+ return NULL;
+#endif
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
case SN_op_UnaryPlus:
if (fsig->param_count != 1)
@@ -4150,10 +4217,18 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
#ifndef TARGET_ARM64
if ((id == SN_Max) || (id == SN_Min))
return NULL;
+#endif
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative)))
+ return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, MONO_TYPE_R4, id);
}
case SN_Dot: {
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
return emit_dot (cfg, klass, fsig->params [0], MONO_TYPE_R4, args [0]->dreg, args [1]->dreg);
}
case SN_Negate:
@@ -4172,6 +4247,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return emit_simd_ins_for_sig (cfg, cmethod->klass, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FABS, MONO_TYPE_R4, fsig, args);
#endif
}
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
// MAX(x,0-x)
MonoInst *zero = emit_xzero (cfg, klass);
MonoInst *neg = emit_simd_ins (cfg, klass, OP_XBINOP, zero->dreg, args [0]->dreg);
@@ -4185,12 +4264,20 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
case SN_op_Equality: {
if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)))
return NULL;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
}
case SN_op_Inequality: {
if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)))
return NULL;
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_not_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
}
@@ -4201,6 +4288,11 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
ins = emit_simd_ins (cfg, klass, OP_XOP_X_X, args [0]->dreg, -1);
ins->inst_c0 = (IntrinsicId)INTRINS_SIMD_SQRT_R4;
return ins;
+#elif defined(TARGET_S390X)
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+ ins = emit_simd_ins (cfg, klass, OP_S390_VFSQSB, args [0]->dreg, -1);
+ return ins;
#else
return NULL;
#endif
@@ -4215,6 +4307,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
if (id == SN_Clamp)
return NULL;
#endif
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg);
max->inst_c0 = OP_FMAX;
@@ -6865,6 +6961,11 @@ static MonoInst*
emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
MonoInst *ins;
+#ifdef TARGET_S390X
+ /* vector facility was introduced in z13 */
+ if (!mono_hwcap_s390x_has_vec)
+ return NULL;
+#endif
if (cfg->opt & MONO_OPT_SIMD) {
ins = arch_emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);
diff --git a/src/runtime/src/mono/mono/utils/mono-hwcap-s390x.c b/src/runtime/src/mono/mono/utils/mono-hwcap-s390x.c
index ddc828bbc046a0..7f735066e238b8 100644
--- a/src/runtime/src/mono/mono/utils/mono-hwcap-s390x.c
+++ b/src/runtime/src/mono/mono/utils/mono-hwcap-s390x.c
@@ -157,6 +157,7 @@ mono_hwcap_arch_init (void)
mono_hwcap_s390x_has_fpe = facs.fpe;
mono_hwcap_s390x_has_vec = facs.vec;
+ mono_hwcap_s390x_has_ve1 = facs.ve1;
mono_hwcap_s390x_has_mlt = facs.multi;
mono_hwcap_s390x_has_ia = facs.ia;
mono_hwcap_s390x_has_gie = facs.gie;
diff --git a/src/runtime/src/mono/mono/utils/mono-hwcap-vars.h b/src/runtime/src/mono/mono/utils/mono-hwcap-vars.h
index 98f4eb29115e83..391910a919c76e 100644
--- a/src/runtime/src/mono/mono/utils/mono-hwcap-vars.h
+++ b/src/runtime/src/mono/mono/utils/mono-hwcap-vars.h
@@ -54,6 +54,7 @@ MONO_HWCAP_VAR(riscv_has_stdext_v)
#elif defined (TARGET_S390X)
MONO_HWCAP_VAR(s390x_has_fpe)
+MONO_HWCAP_VAR(s390x_has_ve1)
MONO_HWCAP_VAR(s390x_has_vec)
MONO_HWCAP_VAR(s390x_has_mlt)
MONO_HWCAP_VAR(s390x_has_ia)
From f5e4c47373482aedd36b7f9c579739f3e8160432 Mon Sep 17 00:00:00 2001
From: Sanjam Panda <36253777+saitama951@users.noreply.github.com>
Date: Tue, 5 Aug 2025 14:45:51 +0530
Subject: [PATCH 2/4] Apply suggestions from code review
fix code style
Co-authored-by: kasperk81 <83082615+kasperk81@users.noreply.github.com>
---
src/mono/mono/mini/simd-intrinsics.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/runtime/src/mono/mono/mini/simd-intrinsics.c b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
index b8f78487cd85e6..0b33399d8634b5 100644
--- a/src/runtime/src/mono/mono/mini/simd-intrinsics.c
+++ b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
@@ -2183,7 +2183,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
#if defined(TARGET_S390X)
if (!mono_hwcap_s390x_has_ve1 && (vector_inner_type == MONO_TYPE_R4))
- return NULL;
+ return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, vector_inner_type, id);
}
@@ -2783,7 +2783,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
mono_metadata_type_equal (fsig->params [0], fsig->params [1]));
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
- return NULL;
+ return NULL;
#endif
gboolean is_all = FALSE;
switch (id) {
@@ -4227,7 +4227,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
case SN_Dot: {
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1)
- return NULL;
+ return NULL;
#endif
return emit_dot (cfg, klass, fsig->params [0], MONO_TYPE_R4, args [0]->dreg, args [1]->dreg);
}
@@ -4249,7 +4249,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
}
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1)
- return NULL;
+ return NULL;
#endif
// MAX(x,0-x)
MonoInst *zero = emit_xzero (cfg, klass);
@@ -4266,7 +4266,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return NULL;
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1)
- return NULL;
+ return NULL;
#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
@@ -4276,7 +4276,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return NULL;
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1)
- return NULL;
+ return NULL;
#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_not_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
@@ -4309,7 +4309,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
#endif
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1)
- return NULL;
+ return NULL;
#endif
MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg);
From 579eda9bc245938bbb2a932064ba552528b7457d Mon Sep 17 00:00:00 2001
From: saitama951 <sanjamkumar360@gmail.com>
Date: Wed, 6 Aug 2025 04:35:56 +0000
Subject: [PATCH 3/4] fix errors * fix test case failures on arm64 * fix more
code style reviews
---
src/mono/mono/mini/simd-intrinsics.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/runtime/src/mono/mono/mini/simd-intrinsics.c b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
index 0b33399d8634b5..fab77158e8bdf5 100644
--- a/src/runtime/src/mono/mono/mini/simd-intrinsics.c
+++ b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
@@ -2782,7 +2782,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
fsig->ret->type == MONO_TYPE_BOOLEAN &&
mono_metadata_type_equal (fsig->params [0], fsig->params [1]));
#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
+ if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
return NULL;
#endif
gboolean is_all = FALSE;
@@ -3180,8 +3180,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1 && (id == SN_Negate) && (arg0_type == MONO_TYPE_R4))
- return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
+ return NULL;
#endif
+ return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Shuffle: {
MonoType *etype = get_vector_t_elem_type (fsig->ret);
@@ -3849,7 +3850,7 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1 && ((id !=SN_op_ExclusiveOr) || (id != SN_op_BitwiseAnd) || (id != SN_op_BitwiseOr)) && arg0_type == MONO_TYPE_R4)
- return NULL;
+ return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
@@ -4220,7 +4221,7 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
#endif
#ifdef TARGET_S390X
if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative)))
- return NULL;
+ return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, MONO_TYPE_R4, id);
}
From 9f2dad96c5bf08f462577f11100249fdb3f060a6 Mon Sep 17 00:00:00 2001
From: saitama951 <sanjamkumar360@gmail.com>
Date: Thu, 14 Aug 2025 12:51:00 +0000
Subject: [PATCH 4/4] address review comments
---
src/mono/mono/mini/mini-s390x.h | 2 +-
src/mono/mono/mini/mini.h | 11 ++++++++
src/mono/mono/mini/simd-intrinsics.c | 38 +++++++---------------------
3 files changed, 21 insertions(+), 30 deletions(-)
diff --git a/src/runtime/src/mono/mono/mini/mini-s390x.h b/src/runtime/src/mono/mono/mini/mini-s390x.h
index 6e680ba9c6374b..82b2f411f4d439 100644
--- a/src/runtime/src/mono/mono/mini/mini-s390x.h
+++ b/src/runtime/src/mono/mono/mini/mini-s390x.h
@@ -83,7 +83,7 @@ struct SeqPointInfo {
#define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
#define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
#define MONO_ARCH_FLOAT32_SUPPORTED 1
-#define MONO_ARCH_SIMD_INTRINSICS mono_hwcap_s390x_has_vec
+#define MONO_ARCH_SIMD_INTRINSICS 1
#define MONO_ARCH_NEED_SIMD_BANK 1
#define MONO_ARCH_USE_SHARED_FP_SIMD_BANK 1
#define S390_STACK_ALIGNMENT 8
diff --git a/src/runtime/src/mono/mono/mini/mini.h b/src/runtime/src/mono/mono/mini/mini.h
index 30e5f5c4728811..65b38b751e8c45 100644
--- a/src/runtime/src/mono/mono/mini/mini.h
+++ b/src/runtime/src/mono/mono/mini/mini.h
@@ -64,6 +64,12 @@ typedef struct SeqPointInfo SeqPointInfo;
#include "mono/metadata/callspec.h"
#include "mono/metadata/icall-signatures.h"
+/* we use runtime checks to fallback to scalar ops for/
+ * older z/Architectures
+ */
+#ifdef TARGET_S390X
+#include <mono/utils/mono-hwcap.h>
+#endif
/*
* The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
* can be linked into both mono and mono-sgen.
@@ -3015,6 +3021,11 @@ mini_safepoints_enabled (void)
static inline gboolean
mini_class_is_simd (MonoCompile *cfg, MonoClass *klass)
{
+#ifdef TARGET_S390X
+ /* vector facility was introduced in z13 */
+ if (!mono_hwcap_s390x_has_vec)
+ return FALSE;
+#endif
#ifdef MONO_ARCH_SIMD_INTRINSICS
if (!(((cfg)->opt & MONO_OPT_SIMD) && m_class_is_simd_type (klass)))
return FALSE;
diff --git a/src/runtime/src/mono/mono/mini/simd-intrinsics.c b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
index fab77158e8bdf5..ebe0637605fe5a 100644
--- a/src/runtime/src/mono/mono/mini/simd-intrinsics.c
+++ b/src/runtime/src/mono/mono/mini/simd-intrinsics.c
@@ -2138,7 +2138,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
#if defined(TARGET_S390X)
- if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative) || (id !=SN_Xor) || (id != SN_BitwiseAnd) || (id != SN_BitwiseOr)) && arg0_type == MONO_TYPE_R4)
+ if (!mono_hwcap_s390x_has_ve1 && arg0_type == MONO_TYPE_R4)
+ return NULL;
+ if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative)) && (arg0_type == MONO_TYPE_R8))
return NULL;
#endif
@@ -2147,7 +2149,6 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
return NULL;
#endif
-
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Divide: {
@@ -3849,7 +3850,7 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return NULL;
arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;
#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1 && ((id !=SN_op_ExclusiveOr) || (id != SN_op_BitwiseAnd) || (id != SN_op_BitwiseOr)) && arg0_type == MONO_TYPE_R4)
+ if (!mono_hwcap_s390x_has_ve1 && arg0_type == MONO_TYPE_R4)
return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
@@ -3968,6 +3969,11 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return NULL;
#endif
+#ifdef TARGET_S390X
+ if (!mono_hwcap_s390x_has_ve1)
+ return NULL;
+#endif
+
if (!(cfg->opt & MONO_OPT_SIMD))
return NULL;
@@ -4218,18 +4224,10 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
#ifndef TARGET_ARM64
if ((id == SN_Max) || (id == SN_Min))
return NULL;
-#endif
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative)))
- return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, MONO_TYPE_R4, id);
}
case SN_Dot: {
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
-#endif
return emit_dot (cfg, klass, fsig->params [0], MONO_TYPE_R4, args [0]->dreg, args [1]->dreg);
}
case SN_Negate:
@@ -4248,10 +4246,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
return emit_simd_ins_for_sig (cfg, cmethod->klass, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FABS, MONO_TYPE_R4, fsig, args);
#endif
}
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
-#endif
// MAX(x,0-x)
MonoInst *zero = emit_xzero (cfg, klass);
MonoInst *neg = emit_simd_ins (cfg, klass, OP_XBINOP, zero->dreg, args [0]->dreg);
@@ -4265,20 +4259,12 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
case SN_op_Equality: {
if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)))
return NULL;
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
-#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
}
case SN_op_Inequality: {
if (!(fsig->param_count == 2 && mono_metadata_type_equal (fsig->params [0], type) && mono_metadata_type_equal (fsig->params [1], type)))
return NULL;
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
-#endif
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
return emit_not_xequal (cfg, arg_class, MONO_TYPE_R4, args [0], args [1]);
}
@@ -4290,8 +4276,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
ins->inst_c0 = (IntrinsicId)INTRINS_SIMD_SQRT_R4;
return ins;
#elif defined(TARGET_S390X)
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
ins = emit_simd_ins (cfg, klass, OP_S390_VFSQSB, args [0]->dreg, -1);
return ins;
#else
@@ -4308,10 +4292,6 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
if (id == SN_Clamp)
return NULL;
#endif
-#ifdef TARGET_S390X
- if (!mono_hwcap_s390x_has_ve1)
- return NULL;
-#endif
MonoInst *max = emit_simd_ins (cfg, klass, OP_XBINOP, args[0]->dreg, args[1]->dreg);
max->inst_c0 = OP_FMAX;