Skip to content
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][amd64] Pass and return SIMD values in SIMD registers. #93182

Closed
wants to merge 6 commits into from
Closed
Changes from 1 commit
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
Next Next commit
[mono][amd64] Pass SIMD arguments in SIMD registers.
vargaz committed Nov 6, 2023

Verified

This commit was signed with the committer’s verified signature.
Eikix Elias Tazartes
commit ae616fafd54c872f6e16f32296eca419a9064fe2
45 changes: 39 additions & 6 deletions src/mono/mono/mini/mini-amd64.c
Original file line number Diff line number Diff line change
@@ -674,6 +674,18 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
return;
}

/* Can't use mini_class_is_simd () here as we don't have access to a MonoCompile */
if (m_class_is_simd_type (klass) && struct_size == 16 && !sig->pinvoke && !is_return) {
if (*fr >= FLOAT_PARAM_REGS) {
pass_on_stack = TRUE;
} else {
ainfo->storage = ArgSIMDInSSEReg;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional this doesn't match the native ABI for the platform?

There are particular rules for when and how certain SIMD types are passed depending on the ABI of the underlying platform (Windows x64, Unix SysV, etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just an experiment right now, it has many problems, including this one.

ainfo->reg = (guint8)*fr;
(*fr) ++;
return;
}
}

if (pass_on_stack) {
/* Always pass in memory */
ainfo->offset = GINT32_TO_INT16 (*stack_size);
@@ -1877,7 +1889,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
* are volatile across calls.
* FIXME: Optimize this.
*/
if ((ainfo->storage == ArgInIReg) || (ainfo->storage == ArgInFloatSSEReg) || (ainfo->storage == ArgInDoubleSSEReg) || (ainfo->storage == ArgValuetypeInReg) || (ainfo->storage == ArgGSharedVtInReg))
if ((ainfo->storage == ArgInIReg) || (ainfo->storage == ArgInFloatSSEReg) || (ainfo->storage == ArgInDoubleSSEReg) || (ainfo->storage == ArgSIMDInSSEReg) || (ainfo->storage == ArgValuetypeInReg) || (ainfo->storage == ArgGSharedVtInReg))
inreg = FALSE;

ins->opcode = OP_REGOFFSET;
@@ -1886,6 +1898,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
case ArgInIReg:
case ArgInFloatSSEReg:
case ArgInDoubleSSEReg:
case ArgSIMDInSSEReg:
case ArgGSharedVtInReg:
if (inreg) {
ins->opcode = OP_REGVAR;
@@ -1933,14 +1946,23 @@ mono_arch_allocate_vars (MonoCompile *cfg)
ins->opcode = OP_REGOFFSET;
ins->inst_basereg = cfg->frame_reg;
/* These arguments are saved to the stack in the prolog */
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
int argsize, align;
if (ainfo->storage == ArgSIMDInSSEReg) {
argsize = 16;
align = 16;
offset = ALIGN_TO (offset, 16);
} else {
argsize = (ainfo->storage == ArgValuetypeInReg) ? ainfo->nregs * sizeof (target_mgreg_t) : sizeof (target_mgreg_t);
align = sizeof (target_mgreg_t);
}
offset = ALIGN_TO (offset, align);
if (cfg->arch.omit_fp) {
ins->inst_offset = offset;
offset += (ainfo->storage == ArgValuetypeInReg) ? ainfo->nregs * sizeof (target_mgreg_t) : sizeof (target_mgreg_t);
offset += argsize;
// Arguments are yet supported by the stack map creation code
//cfg->locals_max_stack_offset = MAX (cfg->locals_max_stack_offset, offset);
} else {
offset += (ainfo->storage == ArgValuetypeInReg) ? ainfo->nregs * sizeof (target_mgreg_t) : sizeof (target_mgreg_t);
offset += argsize;
ins->inst_offset = - offset;
//cfg->locals_min_stack_offset = MIN (cfg->locals_min_stack_offset, offset);
}
@@ -2027,7 +2049,15 @@ add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int re
MONO_ADD_INS (cfg->cbb, ins);

mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
break;
case ArgSIMDInSSEReg:
MONO_INST_NEW (cfg, ins, OP_XMOVE);
ins->dreg = alloc_xreg (cfg);
ins->sreg1 = tree->dreg;
ins->klass = tree->klass;
MONO_ADD_INS (cfg->cbb, ins);

mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, MONO_REG_SIMD);
break;
default:
g_assert_not_reached ();
@@ -2171,10 +2201,9 @@ mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)

switch (ainfo->storage) {
case ArgInIReg:
linfo->args [i].storage = LLVMArgNormal;
break;
case ArgInDoubleSSEReg:
case ArgInFloatSSEReg:
case ArgSIMDInSSEReg:
linfo->args [i].storage = LLVMArgNormal;
break;
case ArgOnStack:
@@ -2318,6 +2347,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
break;
case ArgInFloatSSEReg:
case ArgInDoubleSSEReg:
case ArgSIMDInSSEReg:
add_outarg_reg (cfg, call, ainfo->storage, ainfo->reg, in);
break;
case ArgOnStack:
@@ -8094,6 +8124,9 @@ MONO_RESTORE_WARNING
case ArgInDoubleSSEReg:
amd64_movsd_membase_reg (code, ins->inst_basereg, ins->inst_offset, ainfo->reg);
break;
case ArgSIMDInSSEReg:
amd64_sse_movups_membase_reg (code, ins->inst_basereg, ins->inst_offset, ainfo->reg);
break;
case ArgValuetypeInReg:
for (quad = 0; quad < 2; quad ++) {
switch (ainfo->pair_storage [quad]) {
2 changes: 2 additions & 0 deletions src/mono/mono/mini/mini-amd64.h
Original file line number Diff line number Diff line change
@@ -292,6 +292,8 @@ typedef enum {
ArgValuetypeInReg,
ArgValuetypeAddrInIReg,
ArgValuetypeAddrOnStack,
/* SIMD value in SSE register */
ArgSIMDInSSEReg,
/* gsharedvt argument passed by addr */
ArgGSharedVtInReg,
ArgGSharedVtOnStack,