Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/mono/mono/mini/mini-s390x.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/mono/mono/mini/mini.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
94 changes: 88 additions & 6 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -2135,6 +2137,13 @@ 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 && 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

#if !defined(TARGET_ARM64) && !defined(TARGET_S390X)
if (((id == SN_Max) || (id == SN_Min)) && type_enum_is_float(arg0_type))
return NULL;
Expand All @@ -2149,7 +2158,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: {
Expand All @@ -2170,7 +2182,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: {
Expand Down Expand Up @@ -2198,13 +2213,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
Expand Down Expand Up @@ -2274,6 +2293,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:
Expand Down Expand Up @@ -2464,6 +2485,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:
Expand All @@ -2472,6 +2497,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]);

Expand Down Expand Up @@ -2733,7 +2762,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:
Expand All @@ -2750,7 +2782,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:
Expand Down Expand Up @@ -2857,6 +2892,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;
Expand All @@ -2879,7 +2918,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;

Expand Down Expand Up @@ -2907,6 +2949,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];

Expand Down Expand Up @@ -2984,6 +3030,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: {
Expand Down Expand Up @@ -3129,6 +3179,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 NULL;
#endif
return emit_simd_ins_for_unary_op (cfg, klass, fsig, args, arg0_type, id);
}
case SN_Shuffle: {
Expand Down Expand Up @@ -3295,6 +3349,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
Expand Down Expand Up @@ -3792,6 +3849,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 && arg0_type == MONO_TYPE_R4)
return NULL;
#endif
return emit_simd_ins_for_binary_op (cfg, klass, fsig, args, arg0_type, id);

}
Expand All @@ -3800,6 +3861,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]);
Expand All @@ -3810,6 +3875,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)
Expand Down Expand Up @@ -3900,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;

Expand Down Expand Up @@ -4201,6 +4275,9 @@ 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)
ins = emit_simd_ins (cfg, klass, OP_S390_VFSQSB, args [0]->dreg, -1);
return ins;
#else
return NULL;
#endif
Expand Down Expand Up @@ -6865,6 +6942,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);
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/utils/mono-hwcap-s390x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/utils/mono-hwcap-vars.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading