Skip to content

Commit f1fb602

Browse files
committed
Use the *_overflow instructions where possible
1 parent 7e4cafb commit f1fb602

File tree

1 file changed

+17
-74
lines changed

1 file changed

+17
-74
lines changed

src/num.rs

Lines changed: 17 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -208,86 +208,29 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
208208

209209
let (res, has_overflow) = match bin_op {
210210
BinOp::Add => {
211-
/*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
212-
(val, c_out)*/
213-
// FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
214-
let val = fx.bcx.ins().iadd(lhs, rhs);
215-
let has_overflow = if !signed {
216-
fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
211+
if !signed {
212+
fx.bcx.ins().uadd_overflow(lhs, rhs)
217213
} else {
218-
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
219-
let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
220-
fx.bcx.ins().bxor(rhs_is_negative, slt)
221-
};
222-
(val, has_overflow)
214+
fx.bcx.ins().sadd_overflow(lhs, rhs)
215+
}
223216
}
224217
BinOp::Sub => {
225-
/*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
226-
(val, b_out)*/
227-
// FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
228-
let val = fx.bcx.ins().isub(lhs, rhs);
229-
let has_overflow = if !signed {
230-
fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
218+
if !signed {
219+
fx.bcx.ins().usub_overflow(lhs, rhs)
231220
} else {
232-
let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
233-
let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
234-
fx.bcx.ins().bxor(rhs_is_negative, sgt)
235-
};
236-
(val, has_overflow)
221+
fx.bcx.ins().ssub_overflow(lhs, rhs)
222+
}
237223
}
238224
BinOp::Mul => {
239-
let ty = fx.bcx.func.dfg.value_type(lhs);
240-
match ty {
241-
types::I8 | types::I16 | types::I32 if !signed => {
242-
let lhs = fx.bcx.ins().uextend(ty.double_width().unwrap(), lhs);
243-
let rhs = fx.bcx.ins().uextend(ty.double_width().unwrap(), rhs);
244-
let val = fx.bcx.ins().imul(lhs, rhs);
245-
let has_overflow = fx.bcx.ins().icmp_imm(
246-
IntCC::UnsignedGreaterThan,
247-
val,
248-
(1 << ty.bits()) - 1,
249-
);
250-
let val = fx.bcx.ins().ireduce(ty, val);
251-
(val, has_overflow)
252-
}
253-
types::I8 | types::I16 | types::I32 if signed => {
254-
let lhs = fx.bcx.ins().sextend(ty.double_width().unwrap(), lhs);
255-
let rhs = fx.bcx.ins().sextend(ty.double_width().unwrap(), rhs);
256-
let val = fx.bcx.ins().imul(lhs, rhs);
257-
let has_underflow =
258-
fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, val, -(1 << (ty.bits() - 1)));
259-
let has_overflow = fx.bcx.ins().icmp_imm(
260-
IntCC::SignedGreaterThan,
261-
val,
262-
(1 << (ty.bits() - 1)) - 1,
263-
);
264-
let val = fx.bcx.ins().ireduce(ty, val);
265-
(val, fx.bcx.ins().bor(has_underflow, has_overflow))
266-
}
267-
types::I64 => {
268-
let val = fx.bcx.ins().imul(lhs, rhs);
269-
let has_overflow = if !signed {
270-
let val_hi = fx.bcx.ins().umulhi(lhs, rhs);
271-
fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0)
272-
} else {
273-
// Based on LLVM's instruction sequence for compiling
274-
// a.checked_mul(b).is_some() to riscv64gc:
275-
// mulh a2, a0, a1
276-
// mul a0, a0, a1
277-
// srai a0, a0, 63
278-
// xor a0, a0, a2
279-
// snez a0, a0
280-
let val_hi = fx.bcx.ins().smulhi(lhs, rhs);
281-
let val_sign = fx.bcx.ins().sshr_imm(val, i64::from(ty.bits() - 1));
282-
let xor = fx.bcx.ins().bxor(val_hi, val_sign);
283-
fx.bcx.ins().icmp_imm(IntCC::NotEqual, xor, 0)
284-
};
285-
(val, has_overflow)
286-
}
287-
types::I128 => {
288-
unreachable!("i128 should have been handled by codegen_i128::maybe_codegen")
289-
}
290-
_ => unreachable!("invalid non-integer type {}", ty),
225+
assert_ne!(
226+
fx.bcx.func.dfg.value_type(lhs),
227+
types::I128,
228+
"i128 should have been handled by codegen_i128::maybe_codegen"
229+
);
230+
if !signed {
231+
fx.bcx.ins().umul_overflow(lhs, rhs)
232+
} else {
233+
fx.bcx.ins().smul_overflow(lhs, rhs)
291234
}
292235
}
293236
_ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),

0 commit comments

Comments
 (0)