[codegen] legalize icmp for 64 and 128 bit operands

Add legalizations for icmp and icmp_imm for i64 and i128 operands for
the narrow legalization set, allowing 32-bit ISAs (like x86-32) to
compare 64-bit integers and all ISAs to compare 128-bit integers.

Fixes: https://github.com/bnjbvr/cranelift-x86/issues/2
This commit is contained in:
Ujjwal Sharma
2019-09-26 21:59:56 +05:30
committed by Benjamin Bouvier
parent 19444649e7
commit c062f12d7c
5 changed files with 504 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ use crate::cdsl::xform::{TransformGroupBuilder, TransformGroups};
use crate::shared::immediates::Immediates;
use crate::shared::types::Float::{F32, F64};
use crate::shared::types::Int::{I128, I16, I32, I64, I8};
use cranelift_codegen_shared::condcodes::{CondCode, IntCC};
pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGroups {
let mut narrow = TransformGroupBuilder::new(
@@ -272,6 +273,69 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
],
);
// TODO(ryzokuken): benchmark this and decide if branching is a faster
// approach than evaluating boolean expressions.
narrow.custom_legalize(icmp_imm, "narrow_icmp_imm");
let intcc_eq = Literal::enumerator_for(&imm.intcc, "eq");
let intcc_ne = Literal::enumerator_for(&imm.intcc, "ne");
for &(int_ty, int_ty_half) in &[(I64, I32), (I128, I64)] {
narrow.legalize(
def!(b = icmp.int_ty(intcc_eq, x, y)),
vec![
def!((xl, xh) = isplit(x)),
def!((yl, yh) = isplit(y)),
def!(b1 = icmp.int_ty_half(intcc_eq, xl, yl)),
def!(b2 = icmp.int_ty_half(intcc_eq, xh, yh)),
def!(b = band(b1, b2)),
],
);
narrow.legalize(
def!(b = icmp.int_ty(intcc_ne, x, y)),
vec![
def!((xl, xh) = isplit(x)),
def!((yl, yh) = isplit(y)),
def!(b1 = icmp.int_ty_half(intcc_ne, xl, yl)),
def!(b2 = icmp.int_ty_half(intcc_ne, xh, yh)),
def!(b = bor(b1, b2)),
],
);
use IntCC::*;
for cc in &[
SignedGreaterThan,
SignedGreaterThanOrEqual,
SignedLessThan,
SignedLessThanOrEqual,
UnsignedGreaterThan,
UnsignedGreaterThanOrEqual,
UnsignedLessThan,
UnsignedLessThanOrEqual,
] {
let intcc_cc = Literal::enumerator_for(&imm.intcc, cc.to_static_str());
let cc1 = Literal::enumerator_for(&imm.intcc, cc.without_equal().to_static_str());
let cc2 =
Literal::enumerator_for(&imm.intcc, cc.inverse().without_equal().to_static_str());
let cc3 = Literal::enumerator_for(&imm.intcc, cc.unsigned().to_static_str());
narrow.legalize(
def!(b = icmp.int_ty(intcc_cc, x, y)),
vec![
def!((xl, xh) = isplit(x)),
def!((yl, yh) = isplit(y)),
// X = cc1 || (!cc2 && cc3)
def!(b1 = icmp.int_ty_half(cc1, xh, yh)),
def!(b2 = icmp.int_ty_half(cc2, xh, yh)),
def!(b3 = icmp.int_ty_half(cc3, xl, yl)),
def!(c1 = bnot(b2)),
def!(c2 = band(c1, b3)),
def!(b = bor(b1, c2)),
],
);
}
}
// Widen instructions with one input operand.
for &op in &[bnot, popcnt] {
for &int_ty in &[I8, I16] {