[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:
committed by
Benjamin Bouvier
parent
19444649e7
commit
c062f12d7c
@@ -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] {
|
||||
|
||||
Reference in New Issue
Block a user