Merge pull request #1520 from bjorn3/aarch64-lower-small-fcvt_from_int
Lower fcvt_from_{u,s}int for 8 and 16 bit ints
This commit is contained in:
@@ -2157,12 +2157,12 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let out_bits = ty_bits(ctx.output_ty(insn, 0));
|
let out_bits = ty_bits(ctx.output_ty(insn, 0));
|
||||||
let signed = op == Opcode::FcvtToSint;
|
let signed = op == Opcode::FcvtToSint;
|
||||||
let op = match (signed, in_bits, out_bits) {
|
let op = match (signed, in_bits, out_bits) {
|
||||||
(false, 32, 32) => FpuToIntOp::F32ToU32,
|
(false, 32, 8) | (false, 32, 16) | (false, 32, 32) => FpuToIntOp::F32ToU32,
|
||||||
(true, 32, 32) => FpuToIntOp::F32ToI32,
|
(true, 32, 8) | (true, 32, 16) | (true, 32, 32) => FpuToIntOp::F32ToI32,
|
||||||
(false, 32, 64) => FpuToIntOp::F32ToU64,
|
(false, 32, 64) => FpuToIntOp::F32ToU64,
|
||||||
(true, 32, 64) => FpuToIntOp::F32ToI64,
|
(true, 32, 64) => FpuToIntOp::F32ToI64,
|
||||||
(false, 64, 32) => FpuToIntOp::F64ToU32,
|
(false, 64, 8) | (false, 64, 16) | (false, 64, 32) => FpuToIntOp::F64ToU32,
|
||||||
(true, 64, 32) => FpuToIntOp::F64ToI32,
|
(true, 64, 8) | (true, 64, 16) | (true, 64, 32) => FpuToIntOp::F64ToI32,
|
||||||
(false, 64, 64) => FpuToIntOp::F64ToU64,
|
(false, 64, 64) => FpuToIntOp::F64ToU64,
|
||||||
(true, 64, 64) => FpuToIntOp::F64ToI64,
|
(true, 64, 64) => FpuToIntOp::F64ToI64,
|
||||||
_ => panic!("Unknown input/output-bits combination"),
|
_ => panic!("Unknown input/output-bits combination"),
|
||||||
@@ -2199,6 +2199,16 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
if in_bits == 32 {
|
if in_bits == 32 {
|
||||||
// From float32.
|
// From float32.
|
||||||
let (low_bound, low_cond, high_bound) = match (signed, out_bits) {
|
let (low_bound, low_cond, high_bound) = match (signed, out_bits) {
|
||||||
|
(true, 8) => (
|
||||||
|
i8::min_value() as f32 - 1.,
|
||||||
|
FloatCC::GreaterThan,
|
||||||
|
i8::max_value() as f32 + 1.,
|
||||||
|
),
|
||||||
|
(true, 16) => (
|
||||||
|
i16::min_value() as f32 - 1.,
|
||||||
|
FloatCC::GreaterThan,
|
||||||
|
i16::max_value() as f32 + 1.,
|
||||||
|
),
|
||||||
(true, 32) => (
|
(true, 32) => (
|
||||||
i32::min_value() as f32, // I32_MIN - 1 isn't precisely representable as a f32.
|
i32::min_value() as f32, // I32_MIN - 1 isn't precisely representable as a f32.
|
||||||
FloatCC::GreaterThanOrEqual,
|
FloatCC::GreaterThanOrEqual,
|
||||||
@@ -2209,6 +2219,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
FloatCC::GreaterThanOrEqual,
|
FloatCC::GreaterThanOrEqual,
|
||||||
i64::max_value() as f32 + 1.,
|
i64::max_value() as f32 + 1.,
|
||||||
),
|
),
|
||||||
|
(false, 8) => (-1., FloatCC::GreaterThan, u8::max_value() as f32 + 1.),
|
||||||
|
(false, 16) => (-1., FloatCC::GreaterThan, u16::max_value() as f32 + 1.),
|
||||||
(false, 32) => (-1., FloatCC::GreaterThan, u32::max_value() as f32 + 1.),
|
(false, 32) => (-1., FloatCC::GreaterThan, u32::max_value() as f32 + 1.),
|
||||||
(false, 64) => (-1., FloatCC::GreaterThan, u64::max_value() as f32 + 1.),
|
(false, 64) => (-1., FloatCC::GreaterThan, u64::max_value() as f32 + 1.),
|
||||||
_ => panic!("Unknown input/output-bits combination"),
|
_ => panic!("Unknown input/output-bits combination"),
|
||||||
@@ -2240,6 +2252,16 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
} else {
|
} else {
|
||||||
// From float64.
|
// From float64.
|
||||||
let (low_bound, low_cond, high_bound) = match (signed, out_bits) {
|
let (low_bound, low_cond, high_bound) = match (signed, out_bits) {
|
||||||
|
(true, 8) => (
|
||||||
|
i8::min_value() as f64 - 1.,
|
||||||
|
FloatCC::GreaterThan,
|
||||||
|
i8::max_value() as f64 + 1.,
|
||||||
|
),
|
||||||
|
(true, 16) => (
|
||||||
|
i16::min_value() as f64 - 1.,
|
||||||
|
FloatCC::GreaterThan,
|
||||||
|
i16::max_value() as f64 + 1.,
|
||||||
|
),
|
||||||
(true, 32) => (
|
(true, 32) => (
|
||||||
i32::min_value() as f64 - 1.,
|
i32::min_value() as f64 - 1.,
|
||||||
FloatCC::GreaterThan,
|
FloatCC::GreaterThan,
|
||||||
@@ -2250,6 +2272,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
FloatCC::GreaterThanOrEqual,
|
FloatCC::GreaterThanOrEqual,
|
||||||
i64::max_value() as f64 + 1.,
|
i64::max_value() as f64 + 1.,
|
||||||
),
|
),
|
||||||
|
(false, 8) => (-1., FloatCC::GreaterThan, u8::max_value() as f64 + 1.),
|
||||||
|
(false, 16) => (-1., FloatCC::GreaterThan, u16::max_value() as f64 + 1.),
|
||||||
(false, 32) => (-1., FloatCC::GreaterThan, u32::max_value() as f64 + 1.),
|
(false, 32) => (-1., FloatCC::GreaterThan, u32::max_value() as f64 + 1.),
|
||||||
(false, 64) => (-1., FloatCC::GreaterThan, u64::max_value() as f64 + 1.),
|
(false, 64) => (-1., FloatCC::GreaterThan, u64::max_value() as f64 + 1.),
|
||||||
_ => panic!("Unknown input/output-bits combination"),
|
_ => panic!("Unknown input/output-bits combination"),
|
||||||
@@ -2289,10 +2313,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let out_bits = ty_bits(ctx.output_ty(insn, 0));
|
let out_bits = ty_bits(ctx.output_ty(insn, 0));
|
||||||
let signed = op == Opcode::FcvtFromSint;
|
let signed = op == Opcode::FcvtFromSint;
|
||||||
let op = match (signed, in_bits, out_bits) {
|
let op = match (signed, in_bits, out_bits) {
|
||||||
(false, 32, 32) => IntToFpuOp::U32ToF32,
|
(false, 8, 32) | (false, 16, 32) | (false, 32, 32) => IntToFpuOp::U32ToF32,
|
||||||
(true, 32, 32) => IntToFpuOp::I32ToF32,
|
(true, 8, 32) | (true, 16, 32) | (true, 32, 32) => IntToFpuOp::I32ToF32,
|
||||||
(false, 32, 64) => IntToFpuOp::U32ToF64,
|
(false, 8, 64) | (false, 16, 64) | (false, 32, 64) => IntToFpuOp::U32ToF64,
|
||||||
(true, 32, 64) => IntToFpuOp::I32ToF64,
|
(true, 8, 64) | (true, 16, 64) | (true, 32, 64) => IntToFpuOp::I32ToF64,
|
||||||
(false, 64, 32) => IntToFpuOp::U64ToF32,
|
(false, 64, 32) => IntToFpuOp::U64ToF32,
|
||||||
(true, 64, 32) => IntToFpuOp::I64ToF32,
|
(true, 64, 32) => IntToFpuOp::I64ToF32,
|
||||||
(false, 64, 64) => IntToFpuOp::U64ToF64,
|
(false, 64, 64) => IntToFpuOp::U64ToF64,
|
||||||
@@ -2300,8 +2324,8 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
_ => panic!("Unknown input/output-bits combination"),
|
_ => panic!("Unknown input/output-bits combination"),
|
||||||
};
|
};
|
||||||
let narrow_mode = match (signed, in_bits) {
|
let narrow_mode = match (signed, in_bits) {
|
||||||
(false, 32) => NarrowValueMode::ZeroExtend32,
|
(false, 8) | (false, 16) | (false, 32) => NarrowValueMode::ZeroExtend32,
|
||||||
(true, 32) => NarrowValueMode::SignExtend32,
|
(true, 8) | (true, 16) | (true, 32) => NarrowValueMode::SignExtend32,
|
||||||
(false, 64) => NarrowValueMode::ZeroExtend64,
|
(false, 64) => NarrowValueMode::ZeroExtend64,
|
||||||
(true, 64) => NarrowValueMode::SignExtend64,
|
(true, 64) => NarrowValueMode::SignExtend64,
|
||||||
_ => panic!("Unknown input size"),
|
_ => panic!("Unknown input size"),
|
||||||
|
|||||||
134
cranelift/filetests/filetests/vcode/aarch64/fcvt-small.clif
Normal file
134
cranelift/filetests/filetests/vcode/aarch64/fcvt-small.clif
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
test compile
|
||||||
|
target aarch64
|
||||||
|
|
||||||
|
function u0:0(i8) -> f32 {
|
||||||
|
block0(v0: i8):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_from_uint.f32 v0
|
||||||
|
; check: uxtb w0, w0
|
||||||
|
; check: ucvtf s0, w0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(i8) -> f64 {
|
||||||
|
block0(v0: i8):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_from_uint.f64 v0
|
||||||
|
; check: uxtb w0, w0
|
||||||
|
; check: ucvtf d0, w0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(i16) -> f32 {
|
||||||
|
block0(v0: i16):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_from_uint.f32 v0
|
||||||
|
; check: uxth w0, w0
|
||||||
|
; check: ucvtf s0, w0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(i16) -> f64 {
|
||||||
|
block0(v0: i16):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_from_uint.f64 v0
|
||||||
|
; check: uxth w0, w0
|
||||||
|
; check: ucvtf d0, w0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(f32) -> i8 {
|
||||||
|
block0(v0: f32):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_to_uint.i8 v0
|
||||||
|
; check: fcmp s0, s0
|
||||||
|
; check: b.vc 8 ; udf
|
||||||
|
; check: ldr s1, pc+8 ; b 8 ; data.f32 -1
|
||||||
|
; check: fcmp s0, s1
|
||||||
|
; check: b.gt 8 ; udf
|
||||||
|
; check: ldr s1, pc+8 ; b 8 ; data.f32 256
|
||||||
|
; check: fcmp s0, s1
|
||||||
|
; check: b.mi 8 ; udf
|
||||||
|
; check: fcvtzu w0, s0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(f64) -> i8 {
|
||||||
|
block0(v0: f64):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_to_uint.i8 v0
|
||||||
|
; check: fcmp d0, d0
|
||||||
|
; check: b.vc 8 ; udf
|
||||||
|
; check: ldr d1, pc+8 ; b 12 ; data.f64 -1
|
||||||
|
; check: fcmp d0, d1
|
||||||
|
; check: b.gt 8 ; udf
|
||||||
|
; check: ldr d1, pc+8 ; b 12 ; data.f64 256
|
||||||
|
; check: fcmp d0, d1
|
||||||
|
; check: b.mi 8 ; udf
|
||||||
|
; check: fcvtzu w0, d0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(f32) -> i16 {
|
||||||
|
block0(v0: f32):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_to_uint.i16 v0
|
||||||
|
; check: fcmp s0, s0
|
||||||
|
; check: b.vc 8 ; udf
|
||||||
|
; check: ldr s1, pc+8 ; b 8 ; data.f32 -1
|
||||||
|
; check: fcmp s0, s1
|
||||||
|
; check: b.gt 8 ; udf
|
||||||
|
; check: ldr s1, pc+8 ; b 8 ; data.f32 65536
|
||||||
|
; check: fcmp s0, s1
|
||||||
|
; check: b.mi 8 ; udf
|
||||||
|
; check: fcvtzu w0, s0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function u0:0(f64) -> i16 {
|
||||||
|
block0(v0: f64):
|
||||||
|
; check: stp fp, lr, [sp, #-16]!
|
||||||
|
; check: mov fp, sp
|
||||||
|
v1 = fcvt_to_uint.i16 v0
|
||||||
|
; check: fcmp d0, d0
|
||||||
|
; check: b.vc 8 ; udf
|
||||||
|
; check: ldr d1, pc+8 ; b 12 ; data.f64 -1
|
||||||
|
; check: fcmp d0, d1
|
||||||
|
; check: b.gt 8 ; udf
|
||||||
|
; check: ldr d1, pc+8 ; b 12 ; data.f64 65536
|
||||||
|
; check: fcmp d0, d1
|
||||||
|
; check: b.mi 8 ; udf
|
||||||
|
; check: fcvtzu w0, d0
|
||||||
|
return v1
|
||||||
|
; check: mov sp, fp
|
||||||
|
; check: ldp fp, lr, [sp], #16
|
||||||
|
; check: ret
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user