Skip to content

Commit 7c7a8e8

Browse files
committed
Workaround for missing icmp{,_imm}.i128 legalizations
Fixes #667
1 parent 9505d60 commit 7c7a8e8

File tree

6 files changed

+103
-160
lines changed

6 files changed

+103
-160
lines changed

patches/0002-Disable-u128-and-i128-in-libcore.patch

-112
This file was deleted.

src/codegen_i128.rs

+1-33
Original file line numberDiff line numberDiff line change
@@ -73,39 +73,7 @@ pub fn maybe_codegen<'a, 'tcx>(
7373
}
7474
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {
7575
assert!(!checked);
76-
let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs_val);
77-
let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs_val);
78-
79-
let res = match bin_op {
80-
BinOp::Eq => {
81-
let lsb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_lsb, rhs_lsb);
82-
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
83-
fx.bcx.ins().band(lsb_eq, msb_eq)
84-
}
85-
BinOp::Ne => {
86-
let lsb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_lsb, rhs_lsb);
87-
let msb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_msb, rhs_msb);
88-
fx.bcx.ins().bor(lsb_ne, msb_ne)
89-
}
90-
_ => {
91-
// if msb_eq {
92-
// lsb_cc
93-
// } else {
94-
// msb_cc
95-
// }
96-
let cc = crate::num::bin_op_to_intcc(bin_op, is_signed).unwrap();
97-
98-
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
99-
let lsb_cc = fx.bcx.ins().icmp(cc, lhs_lsb, rhs_lsb);
100-
let msb_cc = fx.bcx.ins().icmp(cc, lhs_msb, rhs_msb);
101-
102-
fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
103-
}
104-
};
105-
106-
let res = fx.bcx.ins().bint(types::I8, res);
107-
let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.bool));
108-
return Some(res);
76+
return None;
10977
}
11078
BinOp::Shl | BinOp::Shr => {
11179
let is_overflow = if checked {

src/common.rs

+89
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,95 @@ pub fn codegen_select(bcx: &mut FunctionBuilder, cond: Value, lhs: Value, rhs: V
7373
}
7474
}
7575

76+
pub fn codegen_icmp<'tcx>(
77+
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
78+
intcc: IntCC,
79+
lhs: Value,
80+
rhs: Value,
81+
) -> Value {
82+
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
83+
let rhs_ty = fx.bcx.func.dfg.value_type(rhs);
84+
assert_eq!(lhs_ty, rhs_ty);
85+
if lhs_ty == types::I128 {
86+
// FIXME legalize `icmp.i128` in Cranelift
87+
88+
let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs);
89+
let (rhs_lsb, rhs_msb) = fx.bcx.ins().isplit(rhs);
90+
91+
match intcc {
92+
IntCC::Equal => {
93+
let lsb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_lsb, rhs_lsb);
94+
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
95+
fx.bcx.ins().band(lsb_eq, msb_eq)
96+
}
97+
IntCC::NotEqual => {
98+
let lsb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_lsb, rhs_lsb);
99+
let msb_ne = fx.bcx.ins().icmp(IntCC::NotEqual, lhs_msb, rhs_msb);
100+
fx.bcx.ins().bor(lsb_ne, msb_ne)
101+
}
102+
_ => {
103+
// if msb_eq {
104+
// lsb_cc
105+
// } else {
106+
// msb_cc
107+
// }
108+
109+
let msb_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_msb, rhs_msb);
110+
let lsb_cc = fx.bcx.ins().icmp(intcc, lhs_lsb, rhs_lsb);
111+
let msb_cc = fx.bcx.ins().icmp(intcc, lhs_msb, rhs_msb);
112+
113+
fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
114+
}
115+
}
116+
} else {
117+
fx.bcx.ins().icmp(intcc, lhs, rhs)
118+
}
119+
}
120+
121+
pub fn codegen_icmp_imm<'tcx>(
122+
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
123+
intcc: IntCC,
124+
lhs: Value,
125+
rhs: i128,
126+
) -> Value {
127+
let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
128+
if lhs_ty == types::I128 {
129+
// FIXME legalize `icmp_imm.i128` in Cranelift
130+
131+
let (lhs_lsb, lhs_msb) = fx.bcx.ins().isplit(lhs);
132+
let (rhs_lsb, rhs_msb) = (rhs as u128 as u64 as i64, (rhs as u128 >> 64) as u64 as i64);
133+
134+
match intcc {
135+
IntCC::Equal => {
136+
let lsb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_lsb, rhs_lsb);
137+
let msb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_msb, rhs_msb);
138+
fx.bcx.ins().band(lsb_eq, msb_eq)
139+
}
140+
IntCC::NotEqual => {
141+
let lsb_ne = fx.bcx.ins().icmp_imm(IntCC::NotEqual, lhs_lsb, rhs_lsb);
142+
let msb_ne = fx.bcx.ins().icmp_imm(IntCC::NotEqual, lhs_msb, rhs_msb);
143+
fx.bcx.ins().bor(lsb_ne, msb_ne)
144+
}
145+
_ => {
146+
// if msb_eq {
147+
// lsb_cc
148+
// } else {
149+
// msb_cc
150+
// }
151+
152+
let msb_eq = fx.bcx.ins().icmp_imm(IntCC::Equal, lhs_msb, rhs_msb);
153+
let lsb_cc = fx.bcx.ins().icmp_imm(intcc, lhs_lsb, rhs_lsb);
154+
let msb_cc = fx.bcx.ins().icmp_imm(intcc, lhs_msb, rhs_msb);
155+
156+
fx.bcx.ins().select(msb_eq, lsb_cc, msb_cc)
157+
}
158+
}
159+
} else {
160+
let rhs = i64::try_from(rhs).expect("codegen_icmp_imm rhs out of range for <128bit int");
161+
fx.bcx.ins().icmp_imm(intcc, lhs, rhs)
162+
}
163+
}
164+
76165
fn resolve_normal_value_imm(func: &Function, val: Value) -> Option<i64> {
77166
if let ValueDef::Result(inst, 0 /*param*/) = func.dfg.value_def(val) {
78167
if let InstructionData::UnaryImm {

src/discriminant.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,7 @@ pub fn codegen_get_discriminant<'tcx>(
102102
let niche_llty = fx.clif_type(discr_ty).unwrap();
103103
let dest_clif_ty = fx.clif_type(dest_layout.ty).unwrap();
104104
if niche_variants.start() == niche_variants.end() {
105-
let b = fx
106-
.bcx
107-
.ins()
108-
.icmp_imm(IntCC::Equal, lldiscr, *niche_start as u64 as i64);
105+
let b = codegen_icmp_imm(fx, IntCC::Equal, lldiscr, *niche_start as i128);
109106
let if_true = fx
110107
.bcx
111108
.ins()
@@ -121,10 +118,11 @@ pub fn codegen_get_discriminant<'tcx>(
121118
let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128);
122119
let delta = fx.bcx.ins().iconst(niche_llty, delta as u64 as i64);
123120
let lldiscr = fx.bcx.ins().isub(lldiscr, delta);
124-
let b = fx.bcx.ins().icmp_imm(
121+
let b = codegen_icmp_imm(
122+
fx,
125123
IntCC::UnsignedLessThanOrEqual,
126124
lldiscr,
127-
niche_variants.end().as_u32() as i64,
125+
i128::from(niche_variants.end().as_u32()),
128126
);
129127
let if_true =
130128
clif_intcast(fx, lldiscr, fx.clif_type(dest_layout.ty).unwrap(), false);

src/intrinsics.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ macro_rules! atomic_minmax {
119119
let old = $fx.bcx.ins().load(clif_ty, MemFlags::new(), $ptr, 0);
120120

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

125125
// Write new
126126
$fx.bcx.ins().store(MemFlags::new(), new, $ptr, 0);
@@ -198,7 +198,7 @@ macro_rules! simd_cmp {
198198
($fx:expr, $intrinsic:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
199199
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
200200
let res_lane = match lane_layout.ty.sty {
201-
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane),
201+
ty::Uint(_) | ty::Int(_) => codegen_icmp(fx, IntCC::$cc, x_lane, y_lane),
202202
_ => unreachable!("{:?}", lane_layout.ty),
203203
};
204204
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
@@ -207,8 +207,8 @@ macro_rules! simd_cmp {
207207
($fx:expr, $intrinsic:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
208208
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
209209
let res_lane = match lane_layout.ty.sty {
210-
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
211-
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
210+
ty::Uint(_) => codegen_icmp(fx, IntCC::$cc_u, x_lane, y_lane),
211+
ty::Int(_) => codegen_icmp(fx, IntCC::$cc_s, x_lane, y_lane),
212212
_ => unreachable!("{:?}", lane_layout.ty),
213213
};
214214
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
@@ -791,7 +791,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
791791
let old = fx.bcx.ins().load(clif_ty, MemFlags::new(), ptr, 0);
792792

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

797797
// Write new

src/num.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ fn codegen_compare_bin_op<'tcx>(
2121
lhs: Value,
2222
rhs: Value,
2323
) -> CValue<'tcx> {
24-
let val = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, signed).unwrap(), lhs, rhs);
24+
let intcc = crate::num::bin_op_to_intcc(bin_op, signed).unwrap();
25+
let val = codegen_icmp(fx, intcc, lhs, rhs);
2526
let val = fx.bcx.ins().bint(types::I8, val);
2627
CValue::by_val(val, fx.layout_of(fx.tcx.types.bool))
2728
}
@@ -35,7 +36,6 @@ pub fn codegen_binop<'tcx>(
3536
match bin_op {
3637
BinOp::Eq | BinOp::Lt | BinOp::Le | BinOp::Ne | BinOp::Ge | BinOp::Gt => {
3738
match in_lhs.layout().ty.sty {
38-
ref sty if *sty == fx.tcx.types.u128.sty || *sty == fx.tcx.types.i128.sty => {}
3939
ty::Bool | ty::Uint(_) | ty::Int(_) | ty::Char => {
4040
let signed = type_sign(in_lhs.layout().ty);
4141
let lhs = in_lhs.load_scalar(fx);
@@ -310,7 +310,7 @@ pub fn trans_ptr_binop<'a, 'tcx: 'a>(
310310
let lhs = in_lhs.load_scalar(fx);
311311
let rhs = in_rhs.load_scalar(fx);
312312

313-
return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs);
313+
return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs);;
314314
}
315315
BinOp::Offset => {
316316
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));

0 commit comments

Comments
 (0)