diff --git a/cranelift/codegen/meta/src/isa/x86/legalize.rs b/cranelift/codegen/meta/src/isa/x86/legalize.rs index 0d0ab76a57..aa91741dba 100644 --- a/cranelift/codegen/meta/src/isa/x86/legalize.rs +++ b/cranelift/codegen/meta/src/isa/x86/legalize.rs @@ -43,6 +43,8 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct let iadd = insts.by_name("iadd"); let icmp = insts.by_name("icmp"); let iconst = insts.by_name("iconst"); + let imax = insts.by_name("imax"); + let imin = insts.by_name("imin"); let imul = insts.by_name("imul"); let ineg = insts.by_name("ineg"); let insertlane = insts.by_name("insertlane"); @@ -61,6 +63,8 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct let sshr = insts.by_name("sshr"); let trueif = insts.by_name("trueif"); let udiv = insts.by_name("udiv"); + let umax = insts.by_name("umax"); + let umin = insts.by_name("umin"); let umulhi = insts.by_name("umulhi"); let ushr_imm = insts.by_name("ushr_imm"); let urem = insts.by_name("urem"); @@ -71,6 +75,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct let x86_bsf = x86_instructions.by_name("x86_bsf"); let x86_bsr = x86_instructions.by_name("x86_bsr"); + let x86_pmaxs = x86_instructions.by_name("x86_pmaxs"); let x86_pmaxu = x86_instructions.by_name("x86_pmaxu"); let x86_pmins = x86_instructions.by_name("x86_pmins"); let x86_pminu = x86_instructions.by_name("x86_pminu"); @@ -554,6 +559,18 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct narrow.legalize(def!(c = icmp_(ule, a, b)), vec![def!(c = icmp(uge, b, a))]); } + // SIMD integer min/max + for ty in &[I8, I16, I32] { + let imin = imin.bind(vector(*ty, sse_vector_size)); + narrow.legalize(def!(c = imin(a, b)), vec![def!(c = x86_pmins(a, b))]); + let umin = umin.bind(vector(*ty, sse_vector_size)); + narrow.legalize(def!(c = umin(a, b)), vec![def!(c = x86_pminu(a, b))]); + let imax = imax.bind(vector(*ty, sse_vector_size)); + narrow.legalize(def!(c = imax(a, b)), vec![def!(c = x86_pmaxs(a, b))]); + let umax = umax.bind(vector(*ty, sse_vector_size)); + narrow.legalize(def!(c = umax(a, b)), vec![def!(c = x86_pmaxu(a, b))]); + } + // SIMD fcmp greater-/less-than let gt = Literal::enumerator_for(&imm.floatcc, "gt"); let lt = Literal::enumerator_for(&imm.floatcc, "lt"); diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 08b4f66a7a..d9ff3f04e3 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -481,6 +481,75 @@ fn define_control_flow( ); } +#[inline(never)] +fn define_simd_arithmetic( + ig: &mut InstructionGroupBuilder, + formats: &Formats, + _: &Immediates, + _: &EntityRefs, +) { + let Int = &TypeVar::new( + "Int", + "A scalar or vector integer type", + TypeSetBuilder::new() + .ints(Interval::All) + .simd_lanes(Interval::All) + .build(), + ); + + let a = &Operand::new("a", Int); + let x = &Operand::new("x", Int); + let y = &Operand::new("y", Int); + + ig.push( + Inst::new( + "imin", + r#" + Signed integer minimum. + "#, + &formats.binary, + ) + .operands_in(vec![x, y]) + .operands_out(vec![a]), + ); + + ig.push( + Inst::new( + "umin", + r#" + Unsigned integer minimum. + "#, + &formats.binary, + ) + .operands_in(vec![x, y]) + .operands_out(vec![a]), + ); + + ig.push( + Inst::new( + "imax", + r#" + Signed integer maximum. + "#, + &formats.binary, + ) + .operands_in(vec![x, y]) + .operands_out(vec![a]), + ); + + ig.push( + Inst::new( + "umax", + r#" + Unsigned integer maximum. + "#, + &formats.binary, + ) + .operands_in(vec![x, y]) + .operands_out(vec![a]), + ); +} + #[allow(clippy::many_single_char_names)] pub(crate) fn define( all_instructions: &mut AllInstructions, @@ -491,6 +560,7 @@ pub(crate) fn define( let mut ig = InstructionGroupBuilder::new(all_instructions); define_control_flow(&mut ig, formats, imm, entities); + define_simd_arithmetic(&mut ig, formats, imm, entities); // Operand kind shorthands. let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();