Add x86 SIMD implementation of float comparison

This commit is contained in:
Andrew Brown
2019-10-28 13:26:21 -07:00
parent e5a36e2c61
commit d32301854d
5 changed files with 122 additions and 0 deletions

View File

@@ -610,6 +610,7 @@ pub(crate) fn define(
let rec_null_fpr = r.recipe("null_fpr");
let rec_pcrel_fnaddr8 = r.template("pcrel_fnaddr8");
let rec_pcrel_gvaddr8 = r.template("pcrel_gvaddr8");
let rec_pfcmp = r.template("pfcmp");
let rec_popq = r.template("popq");
let rec_pu_id = r.template("pu_id");
let rec_pu_id_bool = r.template("pu_id_bool");
@@ -2070,6 +2071,16 @@ pub(crate) fn define(
e.enc_32_64_maybe_isap(inst_, rec_fa.opcodes(opcodes), *isa_predicate);
}
// SIMD float comparisons
e.enc_both(
fcmp.bind(vector(F32, sse_vector_size)),
rec_pfcmp.opcodes(&CMPPS),
);
e.enc_both(
fcmp.bind(vector(F64, sse_vector_size)),
rec_pfcmp.opcodes(&CMPPD),
);
// Reference type instructions
// Null references implemented as iconst 0.

View File

@@ -61,6 +61,14 @@ pub static CMP_IMM8: [u8; 1] = [0x83];
/// Compare r{16,32,64} with r/m of the same size.
pub static CMP_REG: [u8; 1] = [0x39];
/// Compare packed double-precision floating-point value in xmm2/m32 and xmm1 using bits 2:0 of
/// imm8 as comparison predicate (SSE2).
pub static CMPPD: [u8; 3] = [0x66, 0x0f, 0xc2];
/// Compare packed single-precision floating-point value in xmm2/m32 and xmm1 using bits 2:0 of
/// imm8 as comparison predicate (SSE).
pub static CMPPS: [u8; 2] = [0x0f, 0xc2];
/// Convert scalar double-precision floating-point value to scalar single-precision
/// floating-point value.
pub static CVTSD2SS: [u8; 3] = [0xf2, 0x0f, 0x5a];

View File

@@ -3015,6 +3015,43 @@ pub(crate) fn define<'shared>(
),
);
{
let supported_floatccs: Vec<Literal> = ["eq", "lt", "le", "uno", "ne", "gt", "ge", "ord"]
.iter()
.map(|name| Literal::enumerator_for(floatcc, name))
.collect();
recipes.add_template_recipe(
EncodingRecipeBuilder::new("pfcmp", &formats.float_compare, 2)
.operands_in(vec![fpr, fpr])
.operands_out(vec![0])
.inst_predicate(supported_floatccs_predicate(
&supported_floatccs[..],
&*formats.float_compare,
))
.emit(
r#"
// Comparison instruction.
{{PUT_OP}}(bits, rex2(in_reg1, in_reg0), sink);
modrm_rr(in_reg1, in_reg0, sink);
// Add immediate byte indicating what type of comparison.
use crate::ir::condcodes::FloatCC::*;
let imm = match cond {
Equal => 0x00,
LessThan => 0x01,
LessThanOrEqual => 0x02,
Unordered => 0x03,
NotEqual => 0x04,
GreaterThanOrEqual => 0x05,
GreaterThan => 0x06,
Ordered => 0x07,
_ => panic!("{} not supported by pfcmp", cond),
};
sink.put1(imm);
"#,
),
);
}
recipes.add_template_recipe(
EncodingRecipeBuilder::new("is_zero", &formats.unary, 2 + 2)
.operands_in(vec![gpr])