Skip to content

Commit

Permalink
Workaround for missing icmp{,_imm}.i128 legalizations
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Aug 15, 2019
1 parent 9505d60 commit 7c7a8e8
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 160 deletions.
112 changes: 0 additions & 112 deletions patches/0002-Disable-u128-and-i128-in-libcore.patch

This file was deleted.

34 changes: 1 addition & 33 deletions src/codegen_i128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,39 +73,7 @@ pub fn maybe_codegen<'a, 'tcx>(
}
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {
assert!(!checked);
let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs_val);
let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs_val);

let res = match bin_op {
BinOp::Eq => {
let lsb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_lsb, rhs_lsb);
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
fx.bcx.ins().band(lsb_eq, msb_eq)
}
BinOp::Ne => {
let lsb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_lsb, rhs_lsb);
let msb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_msb, rhs_msb);
fx.bcx.ins().bor(lsb_ne, msb_ne)
}
_ => {
// if msb_eq {
// lsb_cc
// } else {
// msb_cc
// }
let cc = crate::num::bin_op_to_intcc(bin_op, is_signed).unwrap();

let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
let lsb_cc = fx.bcx.ins().icmp(cc, lhs_lsb, rhs_lsb);
let msb_cc = fx.bcx.ins().icmp(cc, lhs_msb, rhs_msb);

fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
}
};

let res = fx.bcx.ins().bint(types::I8, res);
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.bool));
return Some(res);
return None;
}
BinOp::Shl | BinOp::Shr => {
let is_overflow = if checked {
Expand Down
89 changes: 89 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,95 @@ pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: V
}
}

pub fn codegen_icmp<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
intcc: IntCC,
lhs: Value,
rhs: Value,
) -> Value {
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
let rhs_ty = fx.bcx.func.dfg.value_type(rhs);
assert_eq!(lhs_ty, rhs_ty);
if lhs_ty == types::I128 {
// FIXME legalize `icmp.i128` in Cranelift

let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs);
let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs);

match intcc {
IntCC::Equal => {
let lsb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_lsb, rhs_lsb);
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
fx.bcx.ins().band(lsb_eq, msb_eq)
}
IntCC::NotEqual => {
let lsb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_lsb, rhs_lsb);
let msb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_msb, rhs_msb);
fx.bcx.ins().bor(lsb_ne, msb_ne)
}
_ => {
// if msb_eq {
// lsb_cc
// } else {
// msb_cc
// }

let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
let lsb_cc = fx.bcx.ins().icmp(intcc, lhs_lsb, rhs_lsb);
let msb_cc = fx.bcx.ins().icmp(intcc, lhs_msb, rhs_msb);

fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
}
}
} else {
fx.bcx.ins().icmp(intcc, lhs, rhs)
}
}

pub fn codegen_icmp_imm<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
intcc: IntCC,
lhs: Value,
rhs: i128,
) -> Value {
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
if lhs_ty == types::I128 {
// FIXME legalize `icmp_imm.i128` in Cranelift

let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs);
let (rhs_lsb, rhs_msb) = (rhs as u128 as u64 as i64, (rhs as u128 >> 64) as u64 as i64);

match intcc {
IntCC::Equal => {
let lsb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_lsb, rhs_lsb);
let msb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_msb, rhs_msb);
fx.bcx.ins().band(lsb_eq, msb_eq)
}
IntCC::NotEqual => {
let lsb_ne = fx.bcx.ins().icmp_imm(IntCC::NotEqual, lhs_lsb, rhs_lsb);
let msb_ne = fx.bcx.ins().icmp_imm(IntCC::NotEqual, lhs_msb, rhs_msb);
fx.bcx.ins().bor(lsb_ne, msb_ne)
}
_ => {
// if msb_eq {
// lsb_cc
// } else {
// msb_cc
// }

let msb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_msb, rhs_msb);
let lsb_cc = fx.bcx.ins().icmp_imm(intcc, lhs_lsb, rhs_lsb);
let msb_cc = fx.bcx.ins().icmp_imm(intcc, lhs_msb, rhs_msb);

fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
}
}
} else {
let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
}
}

fn resolve_normal_value_imm(func: &Function, val: Value) -> Option<i64> {
if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) {
if let InstructionData::UnaryImm {
Expand Down
10 changes: 4 additions & 6 deletions src/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ pub fn codegen_get_discriminant<'tcx>(
let niche_llty = fx.clif_type(discr_ty).unwrap();
let dest_clif_ty = fx.clif_type(dest_layout.ty).unwrap();
if niche_variants.start() == niche_variants.end() {
let b = fx
.bcx
.ins()
.icmp_imm(IntCC::Equal, lldiscr, *niche_start as u64 as i64);
let b = codegen_icmp_imm(fx, IntCC::Equal, lldiscr, *niche_start as i128);
let if_true = fx
.bcx
.ins()
Expand All @@ -121,10 +118,11 @@ pub fn codegen_get_discriminant<'tcx>(
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
let b = fx.bcx.ins().icmp_imm(
let b = codegen_icmp_imm(
fx,
IntCC::UnsignedLessThanOrEqual,
lldiscr,
niche_variants.end().as_u32() as i64,
i128::from(niche_variants.end().as_u32()),
);
let if_true =
clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), false);
Expand Down
12 changes: 6 additions & 6 deletions src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ macro_rules! atomic_minmax {
let old = $fx.bcx.ins().load(clif_ty, MemFlags::new(), $ptr, 0);

// Compare
let is_eq = $fx.bcx.ins().icmp(IntCC::SignedGreaterThan, old, $src);
let new = crate::common::codegen_select(&mut $fx.bcx, is_eq, old, $src);
let is_eq = codegen_icmp($fx, IntCC::SignedGreaterThan, old, $src);
let new = codegen_select(&mut $fx.bcx, is_eq, old, $src);

// Write new
$fx.bcx.ins().store(MemFlags::new(), new, $ptr, 0);
Expand Down Expand Up @@ -198,7 +198,7 @@ macro_rules! simd_cmp {
($fx:expr, $intrinsic:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
let res_lane = match lane_layout.ty.sty {
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane),
ty::Uint(_) | ty::Int(_) => codegen_icmp(fx, IntCC::$cc, x_lane, y_lane),
_ => unreachable!("{:?}", lane_layout.ty),
};
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
Expand All @@ -207,8 +207,8 @@ macro_rules! simd_cmp {
($fx:expr, $intrinsic:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
let res_lane = match lane_layout.ty.sty {
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
ty::Uint(_) => codegen_icmp(fx, IntCC::$cc_u, x_lane, y_lane),
ty::Int(_) => codegen_icmp(fx, IntCC::$cc_s, x_lane, y_lane),
_ => unreachable!("{:?}", lane_layout.ty),
};
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
Expand Down Expand Up @@ -791,7 +791,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
let old = fx.bcx.ins().load(clif_ty, MemFlags::new(), ptr, 0);

// Compare
let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old);
let is_eq = codegen_icmp(fx, IntCC::Equal, old, test_old);
let new = crate::common::codegen_select(&mut fx.bcx, is_eq, new, old); // Keep old if not equal to test_old

// Write new
Expand Down
6 changes: 3 additions & 3 deletions src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ fn codegen_compare_bin_op<'tcx>(
lhs: Value,
rhs: Value,
) -> CValue<'tcx> {
let val = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, signed).unwrap(), lhs, rhs);
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
let val = codegen_icmp(fx, intcc, lhs, rhs);
let val = fx.bcx.ins().bint(types::I8, val);
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
}
Expand All @@ -35,7 +36,6 @@ pub fn codegen_binop<'tcx>(
match bin_op {
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
match in_lhs.layout().ty.sty {
ref sty if *sty == fx.tcx.types.u128.sty || *sty == fx.tcx.types.i128.sty => {}
ty::Bool | ty::Uint(_) | ty::Int(_) | ty::Char => {
let signed = type_sign(in_lhs.layout().ty);
let lhs = in_lhs.load_scalar(fx);
Expand Down Expand Up @@ -310,7 +310,7 @@ pub fn trans_ptr_binop<'a, 'tcx: 'a>(
let lhs = in_lhs.load_scalar(fx);
let rhs = in_rhs.load_scalar(fx);

return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs);
return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs);;
}
BinOp::Offset => {
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
Expand Down

0 comments on commit 7c7a8e8

Please sign in to comment.