Skip to content

Commit b7ffc01

Browse files
github-actions[bot]saitama951kasperk81
authored
[release/10.0] [S390X] Add simd fallback support for unsupported s390x architectures (#119284)
* [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. * Apply suggestions from code review fix code style Co-authored-by: kasperk81 <[email protected]> * fix errors * fix test case failures on arm64 * fix more code style reviews * address review comments --------- Co-authored-by: saitama951 <[email protected]> Co-authored-by: Sanjam Panda <[email protected]> Co-authored-by: kasperk81 <[email protected]>
1 parent ba62724 commit b7ffc01

File tree

5 files changed

+102
-7
lines changed

5 files changed

+102
-7
lines changed

src/mono/mono/mini/mini-s390x.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ struct SeqPointInfo {
8383
#define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
8484
#define MONO_ARCH_HAVE_UNWIND_BACKTRACE 1
8585
#define MONO_ARCH_FLOAT32_SUPPORTED 1
86-
#define MONO_ARCH_SIMD_INTRINSICS mono_hwcap_s390x_has_vec
86+
#define MONO_ARCH_SIMD_INTRINSICS 1
8787
#define MONO_ARCH_NEED_SIMD_BANK 1
8888
#define MONO_ARCH_USE_SHARED_FP_SIMD_BANK 1
8989
#define S390_STACK_ALIGNMENT 8

src/mono/mono/mini/mini.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ typedef struct SeqPointInfo SeqPointInfo;
6464
#include "mono/metadata/callspec.h"
6565
#include "mono/metadata/icall-signatures.h"
6666

67+
/* we use runtime checks to fallback to scalar ops for/
68+
* older z/Architectures
69+
*/
70+
#ifdef TARGET_S390X
71+
#include <mono/utils/mono-hwcap.h>
72+
#endif
6773
/*
6874
* The mini code should not have any compile time dependencies on the GC being used, so the same object file from mini/
6975
* can be linked into both mono and mono-sgen.
@@ -3015,6 +3021,11 @@ mini_safepoints_enabled (void)
30153021
static inline gboolean
30163022
mini_class_is_simd (MonoCompile *cfg, MonoClass *klass)
30173023
{
3024+
#ifdef TARGET_S390X
3025+
/* vector facility was introduced in z13 */
3026+
if (!mono_hwcap_s390x_has_vec)
3027+
return FALSE;
3028+
#endif
30183029
#ifdef MONO_ARCH_SIMD_INTRINSICS
30193030
if (!(((cfg)->opt & MONO_OPT_SIMD) && m_class_is_simd_type (klass)))
30203031
return FALSE;

src/mono/mono/mini/simd-intrinsics.c

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21122112
}
21132113
#elif defined(TARGET_S390X)
21142114
if (type_enum_is_float(arg0_type)) {
2115+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2116+
return NULL;
21152117
return emit_simd_ins_for_sig (cfg, klass, arg0_type == MONO_TYPE_R8 ? OP_S390_VFLPDB : OP_S390_VFLPSB, -1, arg0_type, fsig, args);
21162118
} else {
21172119
return emit_simd_ins_for_sig (cfg, klass, OP_VECTOR_IABS, -1, arg0_type, fsig, args);
@@ -2135,6 +2137,13 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21352137
if (!is_element_type_primitive (fsig->params [0]) || !is_element_type_primitive (fsig->params [1]))
21362138
return NULL;
21372139

2140+
#if defined(TARGET_S390X)
2141+
if (!mono_hwcap_s390x_has_ve1 && arg0_type == MONO_TYPE_R4)
2142+
return NULL;
2143+
if (!mono_hwcap_s390x_has_ve1 && ((id == SN_Max) || (id == SN_Min) || (id == SN_MaxNative) || (id == SN_MinNative)) && (arg0_type == MONO_TYPE_R8))
2144+
return NULL;
2145+
#endif
2146+
21382147
#if !defined(TARGET_ARM64) && !defined(TARGET_S390X)
21392148
if (((id == SN_Max) || (id == SN_Min)) && type_enum_is_float(arg0_type))
21402149
return NULL;
@@ -2149,7 +2158,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21492158
if (!is_element_type_primitive (fsig->params [0]) ||
21502159
!(MONO_TYPE_IS_VECTOR_PRIMITIVE (fsig->params [1]) || is_element_type_primitive (fsig->params [1])))
21512160
return NULL;
2152-
2161+
#if defined(TARGET_S390X)
2162+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2163+
return NULL;
2164+
#endif
21532165
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
21542166
}
21552167
case SN_Multiply: {
@@ -2170,7 +2182,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21702182
return NULL;
21712183
} else if (!(is_element_type_primitive (fsig->params [0]) && is_element_type_primitive (fsig->params [1])))
21722184
return NULL;
2173-
2185+
#if defined(TARGET_S390X)
2186+
if (!mono_hwcap_s390x_has_ve1 && (vector_inner_type == MONO_TYPE_R4))
2187+
return NULL;
2188+
#endif
21742189
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, vector_inner_type, id);
21752190
}
21762191
case SN_AndNot: {
@@ -2198,13 +2213,17 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
21982213
int add_op;
21992214

22002215
if (type_enum_is_float (arg0_type)) {
2216+
#if defined(TARGET_S390X)
2217+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2218+
return NULL;
2219+
#endif
22012220
mul_op = OP_FMUL;
22022221
add_op = OP_FADD;
22032222
} else {
22042223
mul_op = OP_IMUL;
22052224
add_op = OP_IADD;
22062225

2207-
#ifdef TARGET_ARM64
2226+
#if defined(TARGET_ARM64) || defined(TARGET_S390X)
22082227
if (!COMPILE_LLVM (cfg) && (arg0_type == MONO_TYPE_I8 || arg0_type == MONO_TYPE_U8 || arg0_type == MONO_TYPE_I || arg0_type == MONO_TYPE_U))
22092228
return NULL;
22102229
#endif
@@ -2274,6 +2293,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
22742293
int ceil_or_floor = id == SN_Ceiling ? 10 : 9;
22752294
return emit_simd_ins_for_sig (cfg, klass, OP_SSE41_ROUNDP, ceil_or_floor, arg0_type, fsig, args);
22762295
#elif defined(TARGET_S390X)
2296+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2297+
return NULL;
22772298
int ceil_or_floor = id == SN_Ceiling ? 6 : 7;
22782299
switch (arg0_type){
22792300
case MONO_TYPE_R4:
@@ -2464,6 +2485,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
24642485
return emit_vector_create_scalar (cfg, vklass, etype, args [0], is_unsafe);
24652486
}
24662487
case SN_Dot: {
2488+
#if defined(TARGET_S390X)
2489+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2490+
return NULL;
2491+
#endif
24672492
return emit_dot (cfg, klass, fsig->params [0], arg0_type, args [0]->dreg, args [1]->dreg);
24682493
}
24692494
case SN_Equals:
@@ -2472,6 +2497,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
24722497
if (!is_element_type_primitive (fsig->params [0]))
24732498
return NULL;
24742499
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
2500+
#ifdef TARGET_S390X
2501+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2502+
return NULL;
2503+
#endif
24752504
if (id == SN_Equals)
24762505
return emit_xcompare (cfg, klass, arg0_type, args [0], args [1]);
24772506

@@ -2733,7 +2762,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
27332762
case SN_LessThanOrEqual: {
27342763
if (!is_element_type_primitive (fsig->params [0]))
27352764
return NULL;
2736-
2765+
#ifdef TARGET_S390X
2766+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2767+
return NULL;
2768+
#endif
27372769
return emit_xcompare_for_intrinsic (cfg, klass, id, arg0_type, args [0], args [1]);
27382770
}
27392771
case SN_GreaterThanAll:
@@ -2750,7 +2782,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
27502782
g_assert (fsig->param_count == 2 &&
27512783
fsig->ret->type == MONO_TYPE_BOOLEAN &&
27522784
mono_metadata_type_equal (fsig->params [0], fsig->params [1]));
2753-
2785+
#ifdef TARGET_S390X
2786+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2787+
return NULL;
2788+
#endif
27542789
gboolean is_all = FALSE;
27552790
switch (id) {
27562791
case SN_GreaterThanAll:
@@ -2857,6 +2892,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
28572892
return NULL;
28582893
if (!type_enum_is_float(arg0_type))
28592894
return emit_xzero (cfg, klass);
2895+
#ifdef TARGET_S390X
2896+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2897+
return NULL;
2898+
#endif
28602899
int op = -1;
28612900
#if defined(TARGET_ARM64) || defined(TARGET_AMD64) || defined(TARGET_WASM) || defined(TARGET_S390X)
28622901
op = OP_ONES_COMPLEMENT;
@@ -2879,7 +2918,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
28792918
return emit_xones (cfg, klass);
28802919
}
28812920
}
2882-
2921+
#ifdef TARGET_S390X
2922+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2923+
return NULL;
2924+
#endif
28832925
MonoInst *arg0 = args [0];
28842926
MonoClass *op_klass = klass;
28852927

@@ -2907,6 +2949,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
29072949
case SN_IsPositiveInfinity: {
29082950
if (!is_element_type_primitive (fsig->params [0]))
29092951
return NULL;
2952+
#ifdef TARGET_S390X
2953+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
2954+
return NULL;
2955+
#endif
29102956
if (arg0_type == MONO_TYPE_R4) {
29112957
guint32 value[4];
29122958

@@ -2984,6 +3030,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
29843030
case SN_IsZero: {
29853031
if (!is_element_type_primitive (fsig->params [0]))
29863032
return NULL;
3033+
#ifdef TARGET_S390X
3034+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
3035+
return NULL;
3036+
#endif
29873037
return emit_xcompare (cfg, klass, arg0_type, args [0], emit_xzero (cfg, klass));
29883038
}
29893039
case SN_Narrow: {
@@ -3129,6 +3179,10 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
31293179
case SN_OnesComplement: {
31303180
if (!is_element_type_primitive (fsig->params [0]))
31313181
return NULL;
3182+
#ifdef TARGET_S390X
3183+
if (!mono_hwcap_s390x_has_ve1 && (id == SN_Negate) && (arg0_type == MONO_TYPE_R4))
3184+
return NULL;
3185+
#endif
31323186
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
31333187
}
31343188
case SN_Shuffle: {
@@ -3295,6 +3349,9 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
32953349

32963350
return emit_simd_ins_for_sig (cfg, klass, OP_XOP_X_X, instc0, arg0_type, fsig, args);
32973351
#elif defined(TARGET_S390X)
3352+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
3353+
return NULL;
3354+
32983355
int instc0 = arg0_type == MONO_TYPE_R4 ? OP_S390_VFSQSB : OP_S390_VFSQDB;
32993356
return emit_simd_ins_for_sig (cfg, klass, instc0, 0, arg0_type, fsig, args);
33003357
#else
@@ -3792,6 +3849,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
37923849
if (fsig->param_count != 2 )
37933850
return NULL;
37943851
arg0_type = fsig->param_count > 0 ? get_underlying_type (fsig->params [0]) : MONO_TYPE_VOID;
3852+
#ifdef TARGET_S390X
3853+
if (!mono_hwcap_s390x_has_ve1 && arg0_type == MONO_TYPE_R4)
3854+
return NULL;
3855+
#endif
37953856
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);
37963857

37973858
}
@@ -3800,6 +3861,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
38003861
if (fsig->param_count != 2 )
38013862
return NULL;
38023863
MonoClass *arg_class = mono_class_from_mono_type_internal (fsig->params [0]);
3864+
#ifdef TARGET_S390X
3865+
if (!mono_hwcap_s390x_has_ve1 && (arg0_type == MONO_TYPE_R4))
3866+
return NULL;
3867+
#endif
38033868
switch (id) {
38043869
case SN_op_Equality: return emit_xequal (cfg, arg_class, arg0_type, args [0], args [1]);
38053870
case SN_op_Inequality: return emit_not_xequal (cfg, arg_class, arg0_type, args [0], args [1]);
@@ -3810,6 +3875,10 @@ emit_sri_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
38103875
case SN_op_UnaryNegation:
38113876
if (fsig->param_count != 1 )
38123877
return NULL;
3878+
#if defined(TARGET_S390X)
3879+
if (!mono_hwcap_s390x_has_ve1 && (id == SN_op_UnaryNegation) && (arg0_type == MONO_TYPE_R4))
3880+
return NULL;
3881+
#endif
38133882
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
38143883
case SN_op_UnaryPlus:
38153884
if (fsig->param_count != 1)
@@ -3900,6 +3969,11 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
39003969
return NULL;
39013970
#endif
39023971

3972+
#ifdef TARGET_S390X
3973+
if (!mono_hwcap_s390x_has_ve1)
3974+
return NULL;
3975+
#endif
3976+
39033977
if (!(cfg->opt & MONO_OPT_SIMD))
39043978
return NULL;
39053979

@@ -4201,6 +4275,9 @@ emit_vector_2_3_4 (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *f
42014275
ins = emit_simd_ins (cfg, klass, OP_XOP_X_X, args [0]->dreg, -1);
42024276
ins->inst_c0 = (IntrinsicId)INTRINS_SIMD_SQRT_R4;
42034277
return ins;
4278+
#elif defined(TARGET_S390X)
4279+
ins = emit_simd_ins (cfg, klass, OP_S390_VFSQSB, args [0]->dreg, -1);
4280+
return ins;
42044281
#else
42054282
return NULL;
42064283
#endif
@@ -6865,6 +6942,11 @@ static MonoInst*
68656942
emit_simd_intrinsics (const char *class_ns, const char *class_name, MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
68666943
{
68676944
MonoInst *ins;
6945+
#ifdef TARGET_S390X
6946+
/* vector facility was introduced in z13 */
6947+
if (!mono_hwcap_s390x_has_vec)
6948+
return NULL;
6949+
#endif
68686950

68696951
if (cfg->opt & MONO_OPT_SIMD) {
68706952
ins = arch_emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);

src/mono/mono/utils/mono-hwcap-s390x.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ mono_hwcap_arch_init (void)
157157

158158
mono_hwcap_s390x_has_fpe = facs.fpe;
159159
mono_hwcap_s390x_has_vec = facs.vec;
160+
mono_hwcap_s390x_has_ve1 = facs.ve1;
160161
mono_hwcap_s390x_has_mlt = facs.multi;
161162
mono_hwcap_s390x_has_ia = facs.ia;
162163
mono_hwcap_s390x_has_gie = facs.gie;

src/mono/mono/utils/mono-hwcap-vars.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ MONO_HWCAP_VAR(riscv_has_stdext_v)
5454
#elif defined (TARGET_S390X)
5555

5656
MONO_HWCAP_VAR(s390x_has_fpe)
57+
MONO_HWCAP_VAR(s390x_has_ve1)
5758
MONO_HWCAP_VAR(s390x_has_vec)
5859
MONO_HWCAP_VAR(s390x_has_mlt)
5960
MONO_HWCAP_VAR(s390x_has_ia)

0 commit comments

Comments
 (0)