diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 6b4d0bcdb8dd1c..57530cccf56bcf 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -2174,6 +2174,14 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) return linfo; } + if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) { + MonoClass *klass = mono_class_from_mono_type_internal (t); + if (m_class_is_simd_type (klass)) { + linfo->args [i].storage = LLVMArgVtypeInSIMDReg; + break; + } + } + linfo->args [i].storage = LLVMArgVtypeInReg; for (j = 0; j < 2; ++j) linfo->args [i].pair_storage [j] = arg_storage_to_llvm_arg_storage (cfg, ainfo->pair_storage [j]); diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 4d2125c82247ef..625108729015b9 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -2491,6 +2491,13 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) lainfo->storage = LLVMArgNone; + MonoType *t; + if (i >= sig->hasthis) + t = sig->params [i - sig->hasthis]; + else + t = mono_get_int_type (); + t = mini_type_get_underlying_type (t); + switch (ainfo->storage) { case ArgInIReg: case ArgInFReg: @@ -2515,6 +2522,14 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) break; } case ArgVtypeInIRegs: + if ((t->type == MONO_TYPE_GENERICINST) && !cfg->full_aot && !sig->pinvoke) { + MonoClass *klass = mono_class_from_mono_type_internal (t); + if (m_class_is_simd_type (klass)) { + lainfo->storage = LLVMArgVtypeInSIMDReg; + break; + } + } + lainfo->storage = LLVMArgAsIArgs; lainfo->nslots = ainfo->nregs; break; diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index cb95ea2a6655f3..5b092a92f01aa7 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -1738,6 +1738,11 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo * } } break; + case LLVMArgVtypeInSIMDReg: { + MonoClass *klass = mono_class_from_mono_type_internal (sig->params [i]); + param_types [pindex ++] = simd_class_to_llvm_type (ctx, klass); + break; + } case LLVMArgVtypeByVal: param_types [pindex] = type_to_llvm_arg_type (ctx, ainfo->type); if (!ctx_ok (ctx)) @@ -3922,6 +3927,13 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) emit_args_to_vtype (ctx, builder, ainfo->type, ctx->addresses [reg]->value, ainfo, args); break; } + case LLVMArgVtypeInSIMDReg: { + LLVMValueRef arg = LLVMGetParam (ctx->lmethod, pindex); + + ctx->addresses [reg] = build_alloca_address (ctx, ainfo->type); + LLVMBuildStore (builder, arg, build_ptr_cast (builder, ctx->addresses [reg]->value, pointer_type(LLVMTypeOf (arg)))); + break; + } case LLVMArgVtypeByVal: { g_assert (ctx->param_etypes [pindex]); ctx->addresses [reg] = create_address (ctx->module, LLVMGetParam (ctx->lmethod, pindex), ctx->param_etypes [pindex]); @@ -4017,6 +4029,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) switch (ainfo->storage) { case LLVMArgVtypeInReg: + case LLVMArgVtypeInSIMDReg: case LLVMArgVtypeByVal: case LLVMArgAsIArgs: // FIXME: Enabling this fails on windows @@ -4571,6 +4584,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, // FIXME: Get rid of the VMOVE break; } + case LLVMArgVtypeInSIMDReg: { + args [pindex] = LLVMBuildLoad2 (ctx->builder, addresses [reg]->type, addresses [reg]->value, "load_param"); + break; + } case LLVMArgVtypeByVal: g_assert (addresses [reg]); args [pindex] = addresses [reg]->value; @@ -12427,6 +12444,7 @@ mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call) case LLVMArgVtypeByVal: case LLVMArgVtypeByRef: case LLVMArgVtypeInReg: + case LLVMArgVtypeInSIMDReg: case LLVMArgVtypeAddr: case LLVMArgVtypeAsScalar: case LLVMArgAsIArgs: diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 853b25eef306ba..f9a9a51aa96216 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -632,6 +632,8 @@ typedef enum { LLVMArgInFPReg, /* Valuetype passed in 1-2 consecutive register */ LLVMArgVtypeInReg, + /* Pass vector types in SIMD registers */ + LLVMArgVtypeInSIMDReg, LLVMArgVtypeByVal, LLVMArgVtypeRetAddr, /* On on cinfo->ret */ LLVMArgGSharedVt,