@@ -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