Skip to content

Commit

Permalink
Fix OP_FMAX an OP_FMIN on amd64 and lift the arch limitation (#65445)
Browse files Browse the repository at this point in the history
  • Loading branch information
fanyang-mono authored Feb 17, 2022
1 parent f8fb217 commit 158f089
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 33 deletions.
44 changes: 26 additions & 18 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -7718,24 +7718,33 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
LLVMValueRef args [] = { l, r };
#if defined(TARGET_X86) || defined(TARGET_AMD64)
LLVMTypeRef t = LLVMTypeOf (l);
LLVMTypeRef elem_t = LLVMGetElementType (t);
unsigned int elems = LLVMGetVectorSize (t);
gboolean is_r4 = ins->inst_c1 == MONO_TYPE_R4;
int iid = -1;
if (ins->inst_c0 == OP_FMAX) {
if (elems == 1)
iid = is_r4 ? INTRINS_SSE_MAXSS : INTRINS_SSE_MAXSD;
else
iid = is_r4 ? INTRINS_SSE_MAXPS : INTRINS_SSE_MAXPD;
unsigned int elem_bits = mono_llvm_get_prim_size_bits (elem_t);
unsigned int v_size = elems * elem_bits;
if (v_size == 128) {
gboolean is_r4 = ins->inst_c1 == MONO_TYPE_R4;
int iid = -1;
if (ins->inst_c0 == OP_FMAX) {
if (elems == 1)
iid = is_r4 ? INTRINS_SSE_MAXSS : INTRINS_SSE_MAXSD;
else
iid = is_r4 ? INTRINS_SSE_MAXPS : INTRINS_SSE_MAXPD;
} else {
if (elems == 1)
iid = is_r4 ? INTRINS_SSE_MINSS : INTRINS_SSE_MINSD;
else
iid = is_r4 ? INTRINS_SSE_MINPS : INTRINS_SSE_MINPD;
}
result = call_intrins (ctx, iid, args, dname);
} else {
if (elems == 1)
iid = is_r4 ? INTRINS_SSE_MINSS : INTRINS_SSE_MINSD;
else
iid = is_r4 ? INTRINS_SSE_MINPS : INTRINS_SSE_MINPD;
LLVMRealPredicate op = ins->inst_c0 == OP_FMAX ? LLVMRealUGE : LLVMRealULE;
LLVMValueRef cmp = LLVMBuildFCmp (builder, op, l, r, "");
result = LLVMBuildSelect (builder, cmp, l, r, "");
}
result = call_intrins (ctx, iid, args, dname);

#elif defined(TARGET_ARM64)
int instc0_arm64 = ins->inst_c0 == OP_FMAX ? INTRINS_AARCH64_ADV_SIMD_FMAX : INTRINS_AARCH64_ADV_SIMD_FMIN;
IntrinsicId iid = (IntrinsicId) instc0_arm64;
IntrinsicId iid = ins->inst_c0 == OP_FMAX ? INTRINS_AARCH64_ADV_SIMD_FMAX : INTRINS_AARCH64_ADV_SIMD_FMIN;
llvm_ovr_tag_t ovr_tag = ovr_tag_from_mono_vector_class (ins->klass);
result = call_overloaded_intrins (ctx, iid, ovr_tag, args, "");
#else
Expand All @@ -7762,18 +7771,17 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
LLVMValueRef cmp = LLVMBuildICmp (builder, op, l, r, "");
result = LLVMBuildSelect (builder, cmp, l, r, "");
} else {
int instc0_arm64;
IntrinsicId iid;
switch (ins->inst_c0) {
case OP_IMAX:
instc0_arm64 = is_unsigned ? INTRINS_AARCH64_ADV_SIMD_UMAX : INTRINS_AARCH64_ADV_SIMD_SMAX;
iid = is_unsigned ? INTRINS_AARCH64_ADV_SIMD_UMAX : INTRINS_AARCH64_ADV_SIMD_SMAX;
break;
case OP_IMIN:
instc0_arm64 = is_unsigned ? INTRINS_AARCH64_ADV_SIMD_UMIN : INTRINS_AARCH64_ADV_SIMD_SMIN;
iid = is_unsigned ? INTRINS_AARCH64_ADV_SIMD_UMIN : INTRINS_AARCH64_ADV_SIMD_SMIN;
break;
default:
g_assert_not_reached ();
}
IntrinsicId iid = (IntrinsicId) instc0_arm64;
LLVMValueRef args [] = { l, r };
llvm_ovr_tag_t ovr_tag = ovr_tag_from_mono_vector_class (ins->klass);
result = call_overloaded_intrins (ctx, iid, ovr_tag, args, "");
Expand Down
17 changes: 2 additions & 15 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -3186,7 +3186,7 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
if (m_class_get_nested_in (cmethod->klass))
class_ns = m_class_get_name_space (m_class_get_nested_in (cmethod->klass));

#if defined(TARGET_ARM64)
#if defined(TARGET_ARM64) || defined(TARGET_AMD64)
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
if (!strcmp (class_name, "Vector128") || !strcmp (class_name, "Vector64"))
return emit_sri_vector (cfg, cmethod, fsig, args);
Expand All @@ -3196,20 +3196,7 @@ mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
if (!strcmp (class_name, "Vector128`1") || !strcmp (class_name, "Vector64`1"))
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
}
#endif // defined(TARGET_ARM64)

// There isn't any SIMD intrinsitcs to replace with for Vector64 methods on non-arm architectures
#if defined(TARGET_AMD64)
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
if (!strcmp (class_name, "Vector128"))
return emit_sri_vector (cfg, cmethod, fsig, args);
}

if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
if (!strcmp (class_name, "Vector128`1"))
return emit_vector64_vector128_t (cfg, cmethod, fsig, args);
}
#endif // defined(TARGET_AMD64)
#endif // defined(TARGET_ARM64) || defined(TARGET_AMD64)

return emit_simd_intrinsics (class_ns, class_name, cfg, cmethod, fsig, args);
}
Expand Down

0 comments on commit 158f089

Please sign in to comment.