diff --git a/build.rs b/build.rs index 278646aa9236..47852cf61815 100644 --- a/build.rs +++ b/build.rs @@ -224,8 +224,7 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool { ("simd", _) if platform_is_s390x() => return true, // These are new instructions that are not really implemented in any backend. - ("simd", "simd_conversions") - | ("simd", "simd_i16x8_extadd_pairwise_i8x16") + ("simd", "simd_i16x8_extadd_pairwise_i8x16") | ("simd", "simd_i32x4_extadd_pairwise_i16x8") => return true, _ => {} diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 87ba64ee13a7..e6a5582e7901 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -2128,6 +2128,8 @@ impl MachInstEmit for Inst { VecRRNarrowOp::Uqxtn16 => (0b1, 0b00, 0b10100), VecRRNarrowOp::Uqxtn32 => (0b1, 0b01, 0b10100), VecRRNarrowOp::Uqxtn64 => (0b1, 0b10, 0b10100), + VecRRNarrowOp::Fcvtn32 => (0b0, 0b00, 0b10110), + VecRRNarrowOp::Fcvtn64 => (0b0, 0b01, 0b10110), }; sink.put4(enc_vec_rr_misc( diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index 2ed45ed78b28..53f68a994a0b 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -2611,6 +2611,28 @@ fn test_aarch64_binemit() { "uqxtn2 v11.4s, v12.2d", )); + insns.push(( + Inst::VecRRNarrow { + op: VecRRNarrowOp::Fcvtn32, + rd: writable_vreg(0), + rn: vreg(0), + high_half: false, + }, + "0068210E", + "fcvtn v0.4h, v0.4s", + )); + + insns.push(( + Inst::VecRRNarrow { + op: VecRRNarrowOp::Fcvtn64, + rd: writable_vreg(31), + rn: vreg(30), + high_half: true, + }, + "DF6B614E", + "fcvtn2 v31.4s, v30.2d", + )); + insns.push(( Inst::VecRRPair { op: VecPairOp::Addp, diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 5f8f8f0eec1e..0312a7626ece 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -396,6 +396,10 @@ pub enum VecRRNarrowOp { Uqxtn32, /// Unsigned saturating extract narrow, 64-bit elements Uqxtn64, + /// Floating-point convert to lower precision narrow, 32-bit elements + Fcvtn32, + /// Floating-point convert to lower precision narrow, 64-bit elements + Fcvtn64, } /// A vector operation on a pair of elements with one register. @@ -4073,6 +4077,18 @@ impl Inst { (VecRRNarrowOp::Uqxtn64, true) => { ("uqxtn2", VectorSize::Size32x4, VectorSize::Size64x2) } + (VecRRNarrowOp::Fcvtn32, false) => { + ("fcvtn", VectorSize::Size16x4, VectorSize::Size32x4) + } + (VecRRNarrowOp::Fcvtn32, true) => { + ("fcvtn2", VectorSize::Size16x8, VectorSize::Size32x4) + } + (VecRRNarrowOp::Fcvtn64, false) => { + ("fcvtn", VectorSize::Size32x2, VectorSize::Size64x2) + } + (VecRRNarrowOp::Fcvtn64, true) => { + ("fcvtn2", VectorSize::Size32x4, VectorSize::Size64x2) + } }; let rd = show_vreg_vector(rd.to_reg(), mb_rru, rd_size); let rn = show_vreg_vector(rn, mb_rru, size); diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index 8c46602cbdd0..a833a3090b34 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -3555,12 +3555,62 @@ pub(crate) fn lower_insn_to_regs>( }); } - Opcode::ConstAddr - | Opcode::FcvtLowFromSint - | Opcode::Fvdemote - | Opcode::FvpromoteLow - | Opcode::Vconcat - | Opcode::Vsplit => unimplemented!("lowering {}", op), + Opcode::FcvtLowFromSint => { + let ty = ty.unwrap(); + + if ty != F64X2 { + return Err(CodegenError::Unsupported(format!( + "FcvtLowFromSint: Unsupported type: {:?}", + ty + ))); + } + + let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); + let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None); + + ctx.emit(Inst::VecExtend { + t: VecExtendOp::Sxtl32, + rd, + rn, + high_half: false, + }); + ctx.emit(Inst::VecMisc { + op: VecMisc2::Scvtf, + rd, + rn: rd.to_reg(), + size: VectorSize::Size64x2, + }); + } + + Opcode::FvpromoteLow => { + debug_assert_eq!(ty.unwrap(), F64X2); + + let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); + let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None); + + ctx.emit(Inst::VecRRLong { + op: VecRRLongOp::Fcvtl32, + rd, + rn, + high_half: false, + }); + } + + Opcode::Fvdemote => { + debug_assert_eq!(ty.unwrap(), F32X4); + + let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); + let rn = put_input_in_reg(ctx, inputs[0], NarrowValueMode::None); + + ctx.emit(Inst::VecRRNarrow { + op: VecRRNarrowOp::Fcvtn64, + rd, + rn, + high_half: false, + }); + } + + Opcode::ConstAddr | Opcode::Vconcat | Opcode::Vsplit => unimplemented!("lowering {}", op), } Ok(())