Add new Cranelift instructions for integer min/max
This includes legalizations to the previously-existing x86 SIMD integer min/max.
This commit is contained in:
@@ -43,6 +43,8 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
|
|||||||
let iadd = insts.by_name("iadd");
|
let iadd = insts.by_name("iadd");
|
||||||
let icmp = insts.by_name("icmp");
|
let icmp = insts.by_name("icmp");
|
||||||
let iconst = insts.by_name("iconst");
|
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 imul = insts.by_name("imul");
|
||||||
let ineg = insts.by_name("ineg");
|
let ineg = insts.by_name("ineg");
|
||||||
let insertlane = insts.by_name("insertlane");
|
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 sshr = insts.by_name("sshr");
|
||||||
let trueif = insts.by_name("trueif");
|
let trueif = insts.by_name("trueif");
|
||||||
let udiv = insts.by_name("udiv");
|
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 umulhi = insts.by_name("umulhi");
|
||||||
let ushr_imm = insts.by_name("ushr_imm");
|
let ushr_imm = insts.by_name("ushr_imm");
|
||||||
let urem = insts.by_name("urem");
|
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_bsf = x86_instructions.by_name("x86_bsf");
|
||||||
let x86_bsr = x86_instructions.by_name("x86_bsr");
|
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_pmaxu = x86_instructions.by_name("x86_pmaxu");
|
||||||
let x86_pmins = x86_instructions.by_name("x86_pmins");
|
let x86_pmins = x86_instructions.by_name("x86_pmins");
|
||||||
let x86_pminu = x86_instructions.by_name("x86_pminu");
|
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))]);
|
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
|
// SIMD fcmp greater-/less-than
|
||||||
let gt = Literal::enumerator_for(&imm.floatcc, "gt");
|
let gt = Literal::enumerator_for(&imm.floatcc, "gt");
|
||||||
let lt = Literal::enumerator_for(&imm.floatcc, "lt");
|
let lt = Literal::enumerator_for(&imm.floatcc, "lt");
|
||||||
|
|||||||
@@ -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)]
|
#[allow(clippy::many_single_char_names)]
|
||||||
pub(crate) fn define(
|
pub(crate) fn define(
|
||||||
all_instructions: &mut AllInstructions,
|
all_instructions: &mut AllInstructions,
|
||||||
@@ -491,6 +560,7 @@ pub(crate) fn define(
|
|||||||
let mut ig = InstructionGroupBuilder::new(all_instructions);
|
let mut ig = InstructionGroupBuilder::new(all_instructions);
|
||||||
|
|
||||||
define_control_flow(&mut ig, formats, imm, entities);
|
define_control_flow(&mut ig, formats, imm, entities);
|
||||||
|
define_simd_arithmetic(&mut ig, formats, imm, entities);
|
||||||
|
|
||||||
// Operand kind shorthands.
|
// Operand kind shorthands.
|
||||||
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
|
let iflags: &TypeVar = &ValueType::Special(types::Flag::IFlags.into()).into();
|
||||||
|
|||||||
Reference in New Issue
Block a user