Fix issue 5528 (#5605)

* fix parameter error.

* fix float convert to i8 and i16   should extract sign bit.

* add missing regression test file.

* using tmp register.

* float convert i8 will consume more instructions.

* fix worse inst emit size.

* fix worst_case_size.
This commit is contained in:
yuyang
2023-02-01 07:37:36 +08:00
committed by GitHub
parent 8c9eb9939b
commit 0c66a1bba7
5 changed files with 113 additions and 6 deletions

View File

@@ -327,7 +327,7 @@ impl FpuOPRR {
} }
pub(crate) fn float_convert_2_int_op(from: Type, is_type_signed: bool, to: Type) -> Self { pub(crate) fn float_convert_2_int_op(from: Type, is_type_signed: bool, to: Type) -> Self {
let type_32 = to.bits() == 32; let type_32 = to.bits() <= 32;
match from { match from {
F32 => { F32 => {
if is_type_signed { if is_type_signed {

View File

@@ -1781,6 +1781,58 @@ impl MachInstEmit for Inst {
rs, rs,
} }
.emit(&[], sink, emit_info, state); .emit(&[], sink, emit_info, state);
if out_type.bits() < 32 && is_signed {
// load value part mask.
Inst::load_constant_u32(
tmp,
if 16 == out_type.bits() {
(u16::MAX >> 1) as u64
} else {
// I8
(u8::MAX >> 1) as u64
},
&mut |_| writable_spilltmp_reg(),
)
.into_iter()
.for_each(|x| x.emit(&[], sink, emit_info, state));
// keep value part.
Inst::AluRRR {
alu_op: AluOPRRR::And,
rd: tmp,
rs1: rd.to_reg(),
rs2: tmp.to_reg(),
}
.emit(&[], sink, emit_info, state);
// extact sign bit.
Inst::AluRRImm12 {
alu_op: AluOPRRI::Srli,
rd: rd,
rs: rd.to_reg(),
imm12: Imm12::from_bits(31),
}
.emit(&[], sink, emit_info, state);
Inst::AluRRImm12 {
alu_op: AluOPRRI::Slli,
rd: rd,
rs: rd.to_reg(),
imm12: Imm12::from_bits(if 16 == out_type.bits() {
15
} else {
// I8
7
}),
}
.emit(&[], sink, emit_info, state);
// make result,sign bit and value part.
Inst::AluRRR {
alu_op: AluOPRRR::Or,
rd: rd,
rs1: rd.to_reg(),
rs2: tmp.to_reg(),
}
.emit(&[], sink, emit_info, state);
}
// I already have the result,jump over. // I already have the result,jump over.
Inst::Jal { Inst::Jal {
dest: BranchTarget::Label(label_jump_over), dest: BranchTarget::Label(label_jump_over),

View File

@@ -2190,17 +2190,52 @@ fn riscv64_worst_case_instruction_size() {
rs: fa0(), rs: fa0(),
is_signed: true, is_signed: true,
in_type: F64, in_type: F64,
out_type: I64, out_type: I8,
is_sat: true, is_sat: false,
tmp: writable_a1(), tmp: writable_a1(),
}); });
candidates.push(Inst::FcvtToInt { candidates.push(Inst::FcvtToInt {
rd: writable_a0(), rd: writable_a0(),
rs: fa0(), rs: fa0(),
is_signed: true, is_signed: true,
in_type: F64, in_type: F64,
out_type: I64, out_type: I16,
is_sat: false,
tmp: writable_a1(),
});
candidates.push(Inst::FcvtToInt {
rd: writable_a0(),
rs: fa0(),
is_signed: true,
in_type: F32,
out_type: I8,
is_sat: false,
tmp: writable_a1(),
});
candidates.push(Inst::FcvtToInt {
rd: writable_a0(),
rs: fa0(),
is_signed: true,
in_type: F32,
out_type: I16,
is_sat: false,
tmp: writable_a1(),
});
candidates.push(Inst::FcvtToInt {
rd: writable_a0(),
rs: fa0(),
is_signed: true,
in_type: F64,
out_type: I8,
is_sat: false,
tmp: writable_a1(),
});
candidates.push(Inst::FcvtToInt {
rd: writable_a0(),
rs: fa0(),
is_signed: true,
in_type: F64,
out_type: I16,
is_sat: false, is_sat: false,
tmp: writable_a1(), tmp: writable_a1(),
}); });

View File

@@ -752,7 +752,7 @@ impl MachInst for Inst {
fn worst_case_size() -> CodeOffset { fn worst_case_size() -> CodeOffset {
// calculate by test function riscv64_worst_case_instruction_size() // calculate by test function riscv64_worst_case_instruction_size()
100 116
} }
fn ref_type_regclass(_settings: &settings::Flags) -> RegClass { fn ref_type_regclass(_settings: &settings::Flags) -> RegClass {

View File

@@ -0,0 +1,20 @@
test interpret
test run
target riscv64
function %a(f32) -> i8 system_v {
block0(v0: f32):
v1 = fcvt_to_sint_sat.i8 v0
return v1
}
; run: %a(-0x1.000006p125) == -128
function %b(f32) -> i16 system_v {
block0(v0: f32):
v1 = fcvt_to_sint_sat.i16 v0
return v1
}
; run: %b(-0x1.000006p125) == -32768