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] [RISC-V] re-implement floating point arithmetic without r4fp #84470

Merged
merged 3 commits into from
Apr 8, 2023
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
4 changes: 4 additions & 0 deletions src/mono/mono/mini/cpu-riscv64.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ long_add: dest:i src1:i src2:i len:4
int_sub: dest:i src1:i src2:i len:4
long_sub: dest:i src1:i src2:i len:4
int_mul: dest:i src1:i src2:i len:4
r4_mul: dest:f src1:f src2:f len:4
float_mul: dest:f src1:f src2:f len:4
long_div: dest:i src1:i src2:i len:32
long_div_un: dest:i src1:i src2:i len:32
r4_div: dest:f src1:f src2:f len:36
int_rem: dest:i src1:i src2:i len:32
long_rem: dest:i src1:i src2:i len:32
int_rem_un: dest:i src1:i src2:i len:32
Expand All @@ -122,11 +124,13 @@ r8const: dest:f len:16
int_conv_to_r4: dest:f src1:i len:4
int_conv_to_r8: dest:f src1:i len:4
r4_conv_to_r8: dest:f src1:f len:4
r4_conv_to_i4: dest:i src1:f len:4
float_conv_to_i4: dest:i src1:f len:4
float_conv_to_r4: dest:f src1:f len:4
float_ceq: dest:i src1:f src2:f len:4
float_clt: dest:i src1:f src2:f len:4
float_clt_un: dest:i src1:f src2:f len:4
r4_clt: dest:i src1:f src2:f len:4

add_imm: dest:i src1:i len:4
int_add_imm: dest:i src1:i len:4
Expand Down
109 changes: 81 additions & 28 deletions src/mono/mono/mini/mini-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1330,10 +1330,7 @@ add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int re
mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
break;
case ArgInFRegR4:
if (cfg->r4fp)
MONO_INST_NEW (cfg, ins, OP_RMOVE);
else
MONO_INST_NEW (cfg, ins, OP_RISCV_SETFREG_R4);
MONO_INST_NEW (cfg, ins, OP_RMOVE);
ins->dreg = mono_alloc_freg (cfg);
ins->sreg1 = arg->dreg;
MONO_ADD_INS (cfg->cbb, ins);
Expand Down Expand Up @@ -1660,8 +1657,10 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
case OP_ICONV_TO_U1:
case OP_ICONV_TO_I2:
case OP_ICONV_TO_U2:
case OP_RCONV_TO_I4:
case OP_FCONV_TO_I4:
case OP_ICONV_TO_R4:
case OP_RCONV_TO_R8:
#ifdef TARGET_RISCV64
case OP_LNEG:

Expand Down Expand Up @@ -1703,12 +1702,14 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)

case OP_IMUL:
case OP_LMUL:
case OP_RMUL:
Copy link
Member

@am11 am11 Apr 25, 2023

Choose a reason for hiding this comment

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

@Xinlong-Wu, can we also handle long_mul_ovf_un here? In qemu, I'm getting:

# built with runtimeFlavor: mono
$ /runtime/artifacts/bin/testhost/net8.0-linux-Debug-riscv64/dotnet \
     bin/Release/net8.0/helloworld.dll

Can't decompose the OP long_mul_ovf_un
* Assertion: should not be reached at /runtime/src/mono/mono/mini/mini-riscv.c:1731


=================================================================
	Native Crash Reporting
=================================================================
Got a SIGABRT while executing native code. This usually indicates
...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure,I will submit a pr of the progress so far.
I think it may fix this problem.
And I plan to use monthly and half monthly pr to synchronize changes in the future

Copy link
Contributor Author

Choose a reason for hiding this comment

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

have submit a pr #85445
Now we are searching for when to push/pop lmf so that tey-catch can be executed correctly and mono can print the call stack correctly.

case OP_FMUL:
case OP_LMUL_IMM:
case OP_IDIV:
case OP_LDIV:
case OP_LDIV_UN:
case OP_IDIV_UN:
case OP_RDIV:
case OP_IREM:
case OP_LREM:
case OP_IREM_UN:
Expand Down Expand Up @@ -1982,9 +1983,11 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LSUB:
case OP_IADD:
case OP_LADD:
case OP_RMUL:
case OP_FMUL:
case OP_LDIV:
case OP_LDIV_UN:
case OP_RDIV:
case OP_IREM:
case OP_LREM:
case OP_IREM_UN:
Expand Down Expand Up @@ -2055,6 +2058,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_R8CONST:
case OP_ICONV_TO_R8:
case OP_RCONV_TO_R8:
case OP_RCONV_TO_I4:
case OP_FCONV_TO_I4:
case OP_FCEQ:
case OP_FCLT:
Expand All @@ -2063,14 +2067,16 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
break;
case OP_R4CONST:
case OP_ICONV_TO_R4:
if (!cfg->r4fp) {
NEW_INS_AFTER (cfg, ins, temp, OP_RCONV_TO_R8);
temp->dreg = ins->dreg;
temp->sreg1 = mono_alloc_freg (cfg);

ins->dreg = temp->sreg1;
}
break;
case OP_RCGT:
case OP_RCGT_UN: {
// rcgt rd, rs1, rs2 -> rlt rd, rs2, rs1
ins->opcode = OP_RCLT;
int tmp_reg = ins->sreg1;
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;
break;
}
case OP_FCGT:
case OP_FCGT_UN: {
// fcgt rd, rs1, rs2 -> flt rd, rs2, rs1
Expand All @@ -2080,6 +2086,36 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg2 = tmp_reg;
break;
}
case OP_RCOMPARE: {
if (ins->next) {
if (ins->next->opcode == OP_FBLT || ins->next->opcode == OP_FBLT_UN) {
ins->opcode = OP_RCLT;
ins->dreg = mono_alloc_ireg (cfg);

ins->next->opcode = OP_RISCV_BNE;
ins->next->sreg1 = ins->dreg;
ins->next->sreg2 = RISCV_ZERO;
} else if (ins->next->opcode == OP_FBGT || ins->next->opcode == OP_FBGT_UN) {
// rcmp rd, rs1, rs2; fbgt rd -> rcgt rd, rs1, rs2; bne rd, X0
// rcgt rd, rs1, rs2 -> flt.s rd, rs2, rs1
ins->opcode = OP_RCLT;
ins->dreg = mono_alloc_ireg (cfg);
int tmp_reg = ins->sreg1;
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;

ins->next->opcode = OP_RISCV_BNE;
ins->next->sreg1 = ins->dreg;
ins->next->sreg2 = RISCV_ZERO;
} else {
g_print ("Unhandaled op %s following after OP_RCOMPARE\n", mono_inst_name (ins->next->opcode));
NOT_IMPLEMENTED;
}
} else {
g_assert_not_reached ();
}
break;
}
case OP_FCOMPARE: {
if (ins->next) {
if (ins->next->opcode == OP_FBLT || ins->next->opcode == OP_FBLT_UN) {
Expand All @@ -2091,7 +2127,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->next->sreg2 = RISCV_ZERO;
} else if (ins->next->opcode == OP_FBGT || ins->next->opcode == OP_FBGT_UN) {
// fcmp rd, rs1, rs2; fbgt rd -> fcgt rd, rs1, rs2; bne rd, X0
// fcgt rd, rs1, rs2 -> flt rd, rs2, rs1
// fcgt rd, rs1, rs2 -> flt.d rd, rs2, rs1
ins->opcode = OP_FCLT;
ins->dreg = mono_alloc_ireg (cfg);
int tmp_reg = ins->sreg1;
Expand Down Expand Up @@ -2205,13 +2241,6 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
#endif
case OP_STORER8_MEMBASE_REG:
case OP_STORE_MEMBASE_REG:
if (ins->opcode == OP_STORER4_MEMBASE_REG && !cfg->r4fp) {
NEW_INS_BEFORE (cfg, ins, temp, OP_FCONV_TO_R4);
temp->dreg = mono_alloc_freg (cfg);
temp->sreg1 = ins->sreg1;

ins->sreg1 = temp->dreg;
}
// check if offset is valid I-type Imm
if (!RISCV_VALID_I_IMM ((gint32)(gssize)(ins->inst_offset)))
NOT_IMPLEMENTED;
Expand All @@ -2230,13 +2259,6 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LOADR4_MEMBASE:
case OP_LOADR8_MEMBASE:
case OP_LOAD_MEMBASE:
if (ins->opcode == OP_LOADR4_MEMBASE && !cfg->r4fp) {
NEW_INS_AFTER (cfg, ins, temp, OP_RCONV_TO_R8);
temp->dreg = ins->dreg;
temp->sreg1 = mono_alloc_freg (cfg);

ins->dreg = temp->sreg1;
}
if (!RISCV_VALID_I_IMM ((gint32)(gssize)(ins->inst_imm))) {
NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
temp->inst_c0 = ins->inst_imm;
Expand Down Expand Up @@ -3629,12 +3651,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
g_assert (riscv_stdext_m);
riscv_mul (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
case OP_RMUL:
g_assert (riscv_stdext_f);
riscv_fmul_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
break;
case OP_FMUL:
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
riscv_fmul_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
else
riscv_fmul_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
NOT_IMPLEMENTED;
break;
case OP_LDIV:
g_assert (riscv_stdext_m);
Expand Down Expand Up @@ -3874,6 +3900,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_fcvt_d_s (code, ins->dreg, ins->sreg1);
break;
}
case OP_RCONV_TO_I4: {
g_assert (riscv_stdext_f);
riscv_fcvt_w_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
break;
}
case OP_FCONV_TO_I4: {
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
Expand All @@ -3888,6 +3919,22 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_fcvt_s_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
break;
}
case OP_RDIV: {
g_assert (riscv_stdext_f);
/**
* insert inst for the case Divide By 0
* fmv.w.x ft0, zero
* feq.s t0, sreg2, ft0
* beqz t0, zero
*/
riscv_fmv_w_x (code, RISCV_FT0, RISCV_ZERO);
riscv_feq_s (code, RISCV_T0, ins->sreg2, RISCV_FT0);

code = mono_riscv_emit_branch_exc (cfg, code, OP_RISCV_EXC_BNE, RISCV_T0, RISCV_ZERO,
"DivideByZeroException");
riscv_fdiv_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
break;
}
case OP_FCEQ: {
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
Expand All @@ -3896,13 +3943,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_feq_s (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
}
case OP_RCLT:
case OP_RCLT_UN: {
g_assert (riscv_stdext_f);
riscv_flt_s (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
}
case OP_FCLT:
case OP_FCLT_UN: {
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
riscv_flt_d (code, ins->dreg, ins->sreg1, ins->sreg2);
else
riscv_flt_s (code, ins->dreg, ins->sreg1, ins->sreg2);
NOT_IMPLEMENTED;
break;
}
case OP_STORER4_MEMBASE_REG: {
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ extern gboolean riscv_stdext_a, riscv_stdext_b, riscv_stdext_c, riscv_stdext_d,
//#define MONO_ARCH_AOT_SUPPORTED (1)
//#define MONO_ARCH_LLVM_SUPPORTED (1)
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED (1)
#define MONO_ARCH_FLOAT32_SUPPORTED (1)


// #define MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE (1)
Expand Down