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:
@@ -327,7 +327,7 @@ impl FpuOPRR {
|
||||
}
|
||||
|
||||
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 {
|
||||
F32 => {
|
||||
if is_type_signed {
|
||||
|
||||
@@ -1781,6 +1781,58 @@ impl MachInstEmit for Inst {
|
||||
rs,
|
||||
}
|
||||
.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.
|
||||
Inst::Jal {
|
||||
dest: BranchTarget::Label(label_jump_over),
|
||||
|
||||
@@ -2190,17 +2190,52 @@ fn riscv64_worst_case_instruction_size() {
|
||||
rs: fa0(),
|
||||
is_signed: true,
|
||||
in_type: F64,
|
||||
out_type: I64,
|
||||
is_sat: true,
|
||||
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: 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,
|
||||
tmp: writable_a1(),
|
||||
});
|
||||
|
||||
@@ -752,7 +752,7 @@ impl MachInst for Inst {
|
||||
|
||||
fn worst_case_size() -> CodeOffset {
|
||||
// calculate by test function riscv64_worst_case_instruction_size()
|
||||
100
|
||||
116
|
||||
}
|
||||
|
||||
fn ref_type_regclass(_settings: &settings::Flags) -> RegClass {
|
||||
|
||||
20
cranelift/filetests/filetests/runtests/issue5528.clif
Normal file
20
cranelift/filetests/filetests/runtests/issue5528.clif
Normal 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
|
||||
Reference in New Issue
Block a user