-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mono][jit] Add vector horizontal sums and ToScalar on arm64. #83675
Changes from 1 commit
db38ad2
edc4582
f0c04e3
3359543
6561cb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
#include <mono/utils/mono-memory-model.h> | ||
#include <mono/metadata/abi-details.h> | ||
#include <mono/metadata/tokentype.h> | ||
#include "llvm-intrinsics-types.h" | ||
|
||
#include "interp/interp.h" | ||
|
||
|
@@ -35,6 +36,7 @@ | |
#define PARENTHESIZE(...) (__VA_ARGS__) | ||
#define EXPAND_FUN(m, ...) EXPAND(m PARENTHESIZE(__VA_ARGS__)) | ||
#define OPFMT_WDSS _w, dreg, sreg1, sreg2 | ||
#define OPFMT_WTDS _w, _t, dreg, sreg1 | ||
#define OPFMT_WTDSS _w, _t, dreg, sreg1, sreg2 | ||
#define OPFMT_WTDSS_REV _w, _t, dreg, sreg2, sreg1 | ||
#define _UNDEF(...) g_assert_not_reached () | ||
|
@@ -3445,6 +3447,12 @@ is_type_float_macro (MonoTypeEnum type) | |
return (type == MONO_TYPE_R4 || type == MONO_TYPE_R8); | ||
} | ||
|
||
static gboolean | ||
is_type_unsigned_macro (MonoTypeEnum type) | ||
{ | ||
return (type == MONO_TYPE_U1 || type == MONO_TYPE_U2 || type == MONO_TYPE_U4 || type == MONO_TYPE_U8); | ||
} | ||
|
||
static int | ||
get_vector_size_macro (MonoInst *ins) | ||
{ | ||
|
@@ -3715,6 +3723,57 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) | |
case OP_XCAST: | ||
break; | ||
|
||
|
||
|
||
case OP_EXTRACT_I1: | ||
case OP_EXTRACT_I2: | ||
case OP_EXTRACT_I4: | ||
case OP_EXTRACT_I8: { | ||
const int t = get_type_size_macro (ins->inst_c1); | ||
if (is_type_unsigned_macro (ins->inst_c1)) { | ||
arm_neon_umov (code, t, ins->dreg, ins->sreg1, ins->inst_c0); | ||
} else { | ||
arm_neon_smov (code, t, ins->dreg, ins->sreg1, ins->inst_c0); | ||
} | ||
break; | ||
} | ||
case OP_EXTRACT_R4: | ||
case OP_EXTRACT_R8: | ||
if (ins->dreg != ins->sreg1 || ins->inst_c0 != 0) { | ||
const int t = get_type_size_macro (ins->inst_c1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation. |
||
// Technically, this broadcasts element #inst_c0 to all dest XREG elements; whereas it should | ||
// set the FREG to the said element. Since FREG and XREG pool is the same on arm64 and the rest | ||
// of the F/XREG is ignored in FREG mode, this operation remains valid. | ||
arm_neon_fdup_e (code, VREG_FULL, t, ins->dreg, ins->sreg1, ins->inst_c0); | ||
} | ||
break; | ||
case OP_ARM64_XADDV: { | ||
switch (ins->inst_c0) { | ||
case INTRINS_AARCH64_ADV_SIMD_FADDV: | ||
if (ins->inst_c1 == MONO_TYPE_R8) { | ||
arm_neon_faddp (code, VREG_FULL, TYPE_F64, ins->dreg, ins->sreg1, ins->sreg1); | ||
} else if (ins->inst_c1 == MONO_TYPE_R4) { | ||
arm_neon_faddp (code, VREG_FULL, TYPE_F32, ins->dreg, ins->sreg1, ins->sreg1); | ||
arm_neon_faddp (code, VREG_FULL, TYPE_F32, ins->dreg, ins->dreg, ins->dreg); | ||
} else { | ||
g_assert_not_reached (); | ||
} | ||
break; | ||
|
||
case INTRINS_AARCH64_ADV_SIMD_UADDV: | ||
case INTRINS_AARCH64_ADV_SIMD_SADDV: | ||
if (ins->inst_c1 == MONO_TYPE_I8 || ins->inst_c1 == MONO_TYPE_U8) | ||
arm_neon_addp (code, VREG_FULL, TYPE_I64, ins->dreg, ins->sreg1, ins->sreg1); | ||
else | ||
g_assert_not_reached (); // remaining int types are handled through the codegen table | ||
break; | ||
|
||
default: | ||
g_assert_not_reached (); | ||
} | ||
break; | ||
} | ||
|
||
/* BRANCH */ | ||
case OP_BR: | ||
mono_add_patch_info_rel (cfg, offset, MONO_PATCH_INFO_BB, ins->inst_target_bb, MONO_R_ARM64_B); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -613,15 +613,23 @@ emit_sum_vector (MonoCompile *cfg, MonoType *vector_type, MonoTypeEnum element_t | |
return ins; | ||
} | ||
|
||
MonoInst *ins = emit_simd_ins (cfg, vector_class, OP_ARM64_XADDV, arg->dreg, -1); | ||
|
||
MonoInst *sum = emit_simd_ins (cfg, vector_class, OP_ARM64_XADDV, arg->dreg, -1); | ||
if (type_enum_is_float (element_type)) { | ||
ins->inst_c0 = INTRINS_AARCH64_ADV_SIMD_FADDV; | ||
sum->inst_c0 = INTRINS_AARCH64_ADV_SIMD_FADDV; | ||
sum->inst_c1 = element_type; | ||
} else { | ||
ins->inst_c0 = type_enum_is_unsigned (element_type) ? INTRINS_AARCH64_ADV_SIMD_UADDV : INTRINS_AARCH64_ADV_SIMD_SADDV; | ||
sum->inst_c0 = type_enum_is_unsigned (element_type) ? INTRINS_AARCH64_ADV_SIMD_UADDV : INTRINS_AARCH64_ADV_SIMD_SADDV; | ||
sum->inst_c1 = element_type; | ||
} | ||
|
||
return ins; | ||
if (COMPILE_LLVM (cfg)) { | ||
return sum; | ||
} else { | ||
MonoInst *ins = emit_simd_ins (cfg, vector_class, type_to_extract_op (element_type), sum->dreg, -1); | ||
ins->inst_c0 = 0; | ||
ins->inst_c1 = element_type; | ||
return ins; | ||
} | ||
} | ||
#endif | ||
#ifdef TARGET_WASM | ||
|
@@ -1191,8 +1199,8 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi | |
#endif | ||
// FIXME: This limitation could be removed once everything here are supported by mini JIT on arm64 | ||
#ifdef TARGET_ARM64 | ||
if (!(cfg->compile_aot && cfg->full_aot && !cfg->interp)) | ||
return NULL; | ||
//if (!(cfg->compile_aot && cfg->full_aot && !cfg->interp)) | ||
// return NULL; | ||
#endif | ||
|
||
int id = lookup_intrins (sri_vector_methods, sizeof (sri_vector_methods), cmethod); | ||
|
@@ -1233,6 +1241,7 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi | |
case SN_AsUInt64: | ||
case SN_Max: | ||
case SN_Min: | ||
case SN_Sum: | ||
break; | ||
default: | ||
return NULL; | ||
|
@@ -1908,6 +1917,7 @@ emit_vector64_vector128_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign | |
case SN_op_BitwiseAnd: | ||
case SN_op_BitwiseOr: | ||
case SN_op_ExclusiveOr: | ||
case SN_Sum: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not needed, as |
||
break; | ||
default: | ||
return NULL; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra newline.