@@ -1748,28 +1748,34 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
17481748 } ;
17491749
17501750 // adopted partially from https://github.com/ziglang/zig/blob/master/src/codegen/spirv.zig
1751+ // FIXME(eddyb) ^^ find a working a permalink, and also inform them
1752+ // of the difference between these two approaches:
1753+ // - broken: https://alive2.llvm.org/ce/z/Q3Pchi
1754+ // - correct: https://alive2.llvm.org/ce/z/aWvThi
17511755
17521756 // when adding, overflow could happen if
17531757 // - rhs is positive and result < lhs; or
1754- // - rhs is negative and result > lhs
1755- // this is equivalent to (rhs < 0) == (result > lhs)
1758+ // - rhs is negative and result >= lhs
1759+ // (`result == lhs` impossible, `>=` used as it's `!(result < lhs)`)
1760+ // this is equivalent to (rhs < 0) == (result >= lhs)
17561761 //
17571762 // when subtracting, overflow happens if
17581763 // - rhs is positive and result > lhs; or
1759- // - rhs is negative and result < lhs
1760- // this is equivalent to (rhs < 0) == (result < lhs)
1764+ // - rhs is negative and result <= lhs
1765+ // (`result == lhs` impossible, `<=` used as it's `!(result > lhs)`)
1766+ // this is equivalent to (rhs < 0) == (result <= lhs)
17611767 let rhs_lt_zero = self . icmp ( IntPredicate :: IntSLT , rhs, self . constant_int ( rhs. ty , 0 ) ) ;
1762- let result_gt_lhs = self . icmp (
1768+ let result_ge_lhs = self . icmp (
17631769 match oop {
1764- OverflowOp :: Add => IntPredicate :: IntSGT ,
1765- OverflowOp :: Sub => IntPredicate :: IntSLT ,
1770+ OverflowOp :: Add => IntPredicate :: IntSGE ,
1771+ OverflowOp :: Sub => IntPredicate :: IntSLE ,
17661772 OverflowOp :: Mul => unreachable ! ( ) ,
17671773 } ,
17681774 result,
17691775 lhs,
17701776 ) ;
17711777
1772- let overflowed = self . icmp ( IntPredicate :: IntEQ , rhs_lt_zero, result_gt_lhs ) ;
1778+ let overflowed = self . icmp ( IntPredicate :: IntEQ , rhs_lt_zero, result_ge_lhs ) ;
17731779
17741780 return ( result, overflowed) ;
17751781 }
0 commit comments