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 {
|
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 {
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
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